/*
9 * Copyright (C) 2018 Authors
10 * Released under GNU GPL v2+, read the file
'COPYING' for more information.
32 _need_points_sorting(false),
33 _need_edges_sorting(false),
34 _has_points_data(false),
35 _point_data_initialised(false),
36 _has_edges_data(false),
37 _has_sweep_src_data(false),
38 _has_sweep_dest_data(false),
39 _has_raster_data(false),
40 _has_back_data(false),
41 _bbox_up_to_date(false)
57 printf(
"sh=%p nbPt=%i nbAr=%i\n",
this,
static_cast<int>(
_pts.size()),
static_cast<int>(
_aretes.size()));
58 for (
unsigned int i=0; i<
_pts.size(); i++) {
59 printf(
"pt %u : x=(%f %f) dI=%i dO=%i\n",i,
_pts[i].x[0],
_pts[i].x[1],
_pts[i].dI,
_pts[i].dO);
61 for (
unsigned int i=0; i<
_aretes.size(); i++) {
241 if (pointCount >
maxPt)
247 if (edgeCount >
maxAr)
281 int const n =
_pts.size() - 1;
285 pData[n].pending = 0;
286 pData[n].nextLinkedPoint = -1;
287 pData[n].askForWindingS =
nullptr;
288 pData[n].askForWindingB = -1;
460 if (a == b || b ==
c || a ==
c)
494 int ppos = (s + e) / 2;
500 while (le < ppos || ri > plast)
511 else if (
getPoint(le).x[1] == pvaly)
517 else if (
getPoint(le).x[0] == pvalx)
539 else if (le == ppos - 1)
567 else if (
getPoint(ri).x[1] == pvaly)
573 else if (
getPoint(ri).x[0] == pvalx)
595 else if (ri == plast + 1)
630 else if (le == ppos - 1)
646 else if (ri == plast + 1)
676 int ppos = (s + e) / 2;
680 int pvali =
pData[ppos].oldInd;
683 while (le < ppos || ri > plast)
694 else if (
getPoint(le).x[1] == pvaly)
700 else if (
getPoint(le).x[0] == pvalx)
702 if (
pData[le].oldInd > pvali)
706 else if (
pData[le].oldInd == pvali)
733 else if (le == ppos - 1)
761 else if (
getPoint(ri).x[1] == pvaly)
767 else if (
getPoint(ri).x[0] == pvalx)
769 if (
pData[ri].oldInd > pvali)
773 else if (
pData[ri].oldInd == pvali)
800 else if (ri == plast + 1)
835 else if (le == ppos - 1)
851 else if (ri == plast + 1)
880 int ppos = (s + e) / 2;
882 double pvalx =
pData[ppos].rx[0];
883 double pvaly =
pData[ppos].rx[1];
886 while (le < ppos || ri > plast)
893 if (
pData[le].rx[1] > pvaly)
897 else if (
pData[le].rx[1] == pvaly)
899 if (
pData[le].rx[0] > pvalx)
903 else if (
pData[le].rx[0] == pvalx)
925 else if (le == ppos - 1)
949 if (
pData[ri].rx[1] > pvaly)
953 else if (
pData[ri].rx[1] == pvaly)
955 if (
pData[ri].rx[0] > pvalx)
959 else if (
pData[ri].rx[0] == pvalx)
981 else if (ri == plast + 1)
1016 else if (le == ppos - 1)
1032 else if (ri == plast + 1)
1056 if (st < 0 || en < 0)
1079 if (st >= 0 && en >= 0) {
1090 eData[n].weight = 1;
1096 swsData[n].firstLinkedPoint = -1;
1113 if (st < 0 || en < 0)
1147 if (st >= 0 && en >= 0) {
1158 eData[n].weight = 1;
1164 swsData[n].firstLinkedPoint = -1;
1301 for (
int i = 0; i < 2; i++) {
1304 if (
getPoint(p).incidentEdge[i] == b) {
1305 _pts[p].incidentEdge[i] = a;
1311 if (
getPoint(p).incidentEdge[i] == b) {
1312 _pts[p].incidentEdge[i] = a;
1319 _pts[p].incidentEdge[i] = b;
1326 _pts[p].incidentEdge[i] = b;
1386 if (a == b || b ==
c || a ==
c)
1434 _pts[p].incidentEdge[
LAST] = list[nb - 1].
no;
1435 for (
int i = 0; i < nb; i++)
1437 if (list[i].starting)
1510 int quadA = 0, quadB = 0;
1517 else if (tstAY == 0)
1526 else if (tstAX == 0)
1532 else if (tstAY == 0)
1547 else if (tstAY == 0)
1562 else if (tstBY == 0)
1571 else if (tstBX == 0)
1577 else if (tstBY == 0)
1592 else if (tstBY == 0)
1619 double si = cross(av, bv);
1623 if (si > 0.000001) tstSi = 1;
1624 if (si < -0.000001) tstSi = -1;
1629 if ( as && !
bs )
return -1;
1630 if ( !as &&
bs )
return 1;
1644 int cmpval=
CmpToVert (list[e].x, list[s].x,list[e].starting,list[s].starting);
1653 int ppos = (s + e) / 2;
1659 while (le < ppos || ri > plast)
1665 int test =
CmpToVert (pvalx, list[le].x,pvals,list[le].starting);
1672 list[le] = list[ppos - 1];
1673 list[ppos - 1] = list[ppos];
1678 else if (le == ppos - 1)
1701 int test =
CmpToVert (pvalx, list[ri].x,pvals,list[ri].starting);
1708 list[ri] = list[plast + 1];
1709 list[plast + 1] = list[plast];
1714 else if (ri == plast + 1)
1739 list[le] = list[ri];
1744 else if (le < ppos - 1)
1747 list[ppos - 1] = list[plast];
1748 list[plast] = list[le];
1753 else if (le == ppos - 1)
1756 list[plast] = list[le];
1771 list[plast + 1] = list[ppos];
1772 list[ppos] = list[ri];
1777 else if (ri == plast + 1)
1780 list[ppos] = list[ri];
1957 double swat =
ebData[b].tSt;
2003 int lr = 0, ll = 0, rr = 0;
2013 int const nWeight = 1;
2015 if (ast[0] < aen[0]) {
2016 if (ast[0] > px[0])
continue;
2017 if (aen[0] < px[0])
continue;
2019 if (ast[0] < px[0])
continue;
2020 if (aen[0] > px[0])
continue;
2022 if (ast[0] == px[0]) {
2023 if (ast[1] >= px[1])
continue;
2024 if (aen[0] == px[0])
continue;
2025 if (aen[0] < px[0]) ll += nWeight;
else rr -= nWeight;
2028 if (aen[0] == px[0]) {
2029 if (aen[1] >= px[1])
continue;
2030 if (ast[0] == px[0])
continue;
2031 if (ast[0] < px[0]) ll -= nWeight;
else rr += nWeight;
2035 if (ast[1] < aen[1]) {
2036 if (ast[1] >= px[1])
continue;
2038 if (aen[1] >= px[1])
continue;
2042 double const cote = cross(adir, diff);
2043 if (cote == 0)
continue;
2045 if (ast[0] > px[0]) lr += nWeight;
2047 if (ast[0] < px[0]) lr -= nWeight;
2050 return lr + (ll + rr) / 2;
2060 for (
int i = 0; i <
N; i++) {
2061 pData[i].pending = 0;
2062 pData[i].nextLinkedPoint = -1;
2074 for (
int i = 0; i <
N; i++) {
2083 if (
eData[i].siEd < 0) {
2089 swsData[i].firstLinkedPoint = -1;
2152 if ( ndot < bdot ) {
2170 if ( npr > 0 && npr < el ) {
2172 double ndot = nl * nl / el;
2173 if ( ndot < bdot ) {
2214 double const max_l1 = max_l2 * M_SQRT2;
2218 if ( (l1 <= max_l2) || ((l1 <= max_l1) && (
Geom::L2(
offset) <= max_l2)) ) {
2232 double const npr =
Geom::dot(d, e_unit);
2233 if ( npr > 0 && npr < el ) {
2235 if ( nl <= max_l2 ) {
bool distanceLessThanOrEqual(Shape const *s, Geom::Point const &p, double const max_l2)
Returns true iff the L2 distance from thePt to this shape is <= max_l2.
double distance(Shape const *s, Geom::Point const &p)
bool directedEulerian(Shape const *s)
A directed graph is Eulerian iff every vertex has equal indegree and outdegree.
TODO: insert short description here.
Two-dimensional point that doubles as a vector.
A class to store/manipulate directed graphs.
bool _has_edges_data
the eData array is allocated
void MakeSweepDestData(bool nVal)
Initialize the sweep destination data cache.
std::vector< sweep_src_data > swsData
void MakeBackData(bool nVal)
bool _point_data_initialised
the pData array is up to date
void MakeSweepSrcData(bool nVal)
Initialize the sweep source data cache.
void DisconnectStart(int b)
void SwapEdges(int a, int b)
int AddEdge(int st, int en)
int PtWinding(const Geom::Point px) const
bool _has_sweep_src_data
the swsData array is allocated
bool hasPoints() const
Do we have points?
std::vector< raster_data > swrData
void SortPoints()
Sort the points (all points) only if needed.
void SortEdgesList(edge_list *edges, int s, int e)
Sort edges given in a list.
bool _bbox_up_to_date
the leftX/rightX/topY/bottomY are up to date
bool _need_points_sorting
points have been added or removed: we need to sort the points again
std::vector< back_data > ebData
static int CmpToVert(const Geom::Point ax, const Geom::Point bx, bool as, bool bs)
Edge comparison function.
void MakePointData(bool nVal)
Initialize the point data cache.
bool _need_edges_sorting
edges have been added: maybe they are not ordered clockwise
void Copy(Shape *a)
Copy point and edge data from ‘who’ into this object, discarding any cached data that we have.
void CalcBBox(bool strict_degree=false)
int numberOfEdges() const
Returns number of edges.
void ConnectEnd(int p, int b)
static double Round(double x)
std::vector< edge_data > eData
int NextAt(int p, int b) const
int numberOfPoints() const
Returns number of points.
bool _has_points_data
the pData array is allocated
void SwapPoints(int a, int b)
dg_arete const & getEdge(int n) const
Get an edge.
void SortEdges()
Sort all edges (clockwise) around each point.
void SortPointsByOldInd(int s, int e)
Sort the points (take oldInd into account)
void MakeRasterData(bool nVal)
void Reset(int n=0, int m=0)
Clear all data.
void initialiseEdgeData()
void SortPointsRounded()
Sort all points by their rounded coordinates.
std::vector< dg_point > _pts
bool _has_raster_data
the swrData array is allocated
void ConnectStart(int p, int b)
std::vector< dg_arete > _aretes
int AddPoint(const Geom::Point x)
void MakeEdgeData(bool nVal)
Initialize the edge data cache.
void clearIncidenceData()
bool _has_sweep_dest_data
the swdData array is allocated
dg_point const & getPoint(int n) const
Get a point.
std::vector< sweep_dest_data > swdData
void initialisePointData()
void DisconnectEnd(int b)
std::vector< point_data > pData
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
SBasis L2(D2< SBasis > const &a, unsigned k)
T dot(D2< T > const &a, D2< T > const &b)
A structure to store back data for an edge.
An edge in the directed graph.
A point or vertex in the directed graph.
Extra data that some algorithms use.
A structure to help with sorting edges around a point.
Extra data for points used at various occasions.
A container of intersection events.
TODO: insert short description here.
void dot(Cairo::RefPtr< Cairo::Context > &cr, double x, double y)