/*
9 * Copyright (C) 2018 Authors
10 * Released under GNU GPL v2+, read the file
'COPYING' for more information.
185 g_warning (
"Shape error in ConvertToShape: directedEulerian(a) == false\n");
192 if (
sTree ==
nullptr) {
195 if (
sEvts ==
nullptr) {
216 double lastChange = a->
pData[0].rx[1] - 1.0;
219 Shape *shapeHead =
nullptr;
233 Shape *ptSh =
nullptr;
234 bool isIntersection =
false;
244 if (
sEvts->
peek(intersL, intersR, ptX, ptL, ptR))
248 if (a->
pData[curAPt].pending > 0
249 || (a->
pData[curAPt].rx[1] > ptX[1]
250 || (a->
pData[curAPt].rx[1] == ptX[1]
251 && a->
pData[curAPt].rx[0] > ptX[0])))
256 isIntersection =
true;
262 ptX = ptSh->
pData[nPt].rx;
263 isIntersection =
false;
270 ptX = ptSh->
pData[nPt].rx;
271 isIntersection =
false;
274 if (isIntersection ==
false)
282 rPtX[0]=
Round (ptX[0]);
283 rPtX[1]=
Round (ptX[1]);
285 pData[lastPointNo].rx = rPtX;
294 if (rPtX[1] > lastChange)
312 Shape *curSh = shapeHead;
313 int curBo = edgeHead;
316 curSh->
swsData[curBo].leftRnd =
318 curSh->
swsData[curBo].rightRnd =
322 curBo = curSh->
swsData[curBo].nextBo;
326 for (
auto & chgt :
chgts)
328 chgt.ptNo =
pData[chgt.ptNo].newInd;
331 if (chgt.src->getEdge(chgt.bord).st <
332 chgt.src->getEdge(chgt.bord).en)
334 chgt.src->
swsData[chgt.bord].stPt =
339 chgt.src->swsData[chgt.bord].enPt =
343 else if (chgt.type == 1)
345 if (chgt.src->getEdge(chgt.bord).st >
346 chgt.src->getEdge(chgt.bord).en)
348 chgt.src->swsData[chgt.bord].stPt =
353 chgt.src->swsData[chgt.bord].enPt =
369 for (
int i = lastChgtPt; i < lastI; i++) {
370 if (
pData[i].askForWindingS) {
372 int windB =
pData[i].askForWindingB;
373 pData[i].nextLinkedPoint = windS->
swsData[windB].firstLinkedPoint;
374 windS->
swsData[windB].firstLinkedPoint = i;
382 if (lastI < lastPointNo) {
388 _pts.resize(lastI + 1);
391 lastChgtPt = lastPointNo;
392 lastChange = rPtX[1];
430 int nbUp = 0, nbDn = 0;
431 int upNo = -1, dnNo = -1;
451 cb = ptSh->
NextAt (nPt, cb);
458 if (upNo >= 0 && ptSh->
swsData[upNo].misc ==
nullptr)
463 bool doWinding =
true;
488 AddChgt (lastPointNo, lastChgtPt, shapeHead,
491 ptSh->
swsData[cb].misc =
nullptr;
493 int onLeftB = -1, onRightB = -1;
494 Shape *onLeftS =
nullptr;
495 Shape *onRightS =
nullptr;
518 if (onLeftS && onRightS)
532 || onRightS->
getEdge(onRightB).
545 cb = ptSh->
NextAt (nPt, cb);
558 node->src,
node->bord,
nullptr, -1);
560 ptSh->
swsData[upNo].misc =
nullptr;
563 node->ConvertTo (ptSh, dnNo, 1, lastPointNo);
567 insertionNode =
node;
569 ptSh->
swsData[dnNo].curPoint = lastPointNo;
571 node->src,
node->bord,
nullptr, -1);
584 pData[lastPointNo].askForWindingS = myLeft->
src;
585 pData[lastPointNo].askForWindingB = myLeft->
bord;
589 pData[lastPointNo].askForWindingB = -1;
595 insertionNode =
node;
597 ptSh->
swsData[dnNo].curPoint = lastPointNo;
599 node->src,
node->bord,
nullptr, -1);
625 pData[lastPointNo].askForWindingS =
627 pData[lastPointNo].askForWindingB =
632 pData[lastPointNo].askForWindingB = -1;
639 ptSh->
swsData[cb].curPoint = lastPointNo;
640 AddChgt (lastPointNo, lastChgtPt, shapeHead,
645 cb = ptSh->
NextAt (nPt, cb);
656 Shape *curSh = shapeHead;
657 int curBo = edgeHead;
660 curSh->
swsData[curBo].leftRnd =
662 curSh->
swsData[curBo].rightRnd =
666 curBo = curSh->
swsData[curBo].nextBo;
670 for (
auto & chgt :
chgts)
672 chgt.ptNo =
pData[chgt.ptNo].newInd;
675 if (chgt.src->getEdge(chgt.bord).st <
676 chgt.src->getEdge(chgt.bord).en)
678 chgt.src->
swsData[chgt.bord].stPt = chgt.ptNo;
682 chgt.src->swsData[chgt.bord].enPt = chgt.ptNo;
685 else if (chgt.type == 1)
687 if (chgt.src->getEdge(chgt.bord).st >
688 chgt.src->getEdge(chgt.bord).en)
690 chgt.src->swsData[chgt.bord].stPt = chgt.ptNo;
694 chgt.src->swsData[chgt.bord].enPt = chgt.ptNo;
703 for (
int i = lastChgtPt; i < lastI; i++)
705 if (
pData[i].askForWindingS)
708 int windB =
pData[i].askForWindingB;
709 pData[i].nextLinkedPoint = windS->
swsData[windB].firstLinkedPoint;
710 windS->
swsData[windB].firstLinkedPoint = i;
928 if (a == b || a ==
nullptr || b ==
nullptr)
947 if (
sTree ==
nullptr) {
950 if (
sEvts ==
nullptr) {
980 b->
pData[0].rx[1]) ? a->
pData[0].rx[1] - 1.0 : b->
pData[0].rx[1] - 1.0;
983 Shape *shapeHead =
nullptr;
1010 Shape *ptSh =
nullptr;
1011 bool isIntersection =
false;
1013 if (
sEvts->
peek(intersL, intersR, ptX, ptL, ptR))
1019 if (a->
pData[curAPt].rx[1] < b->
pData[curBPt].rx[1]
1020 || (a->
pData[curAPt].rx[1] == b->
pData[curBPt].rx[1]
1021 && a->
pData[curAPt].rx[0] < b->
pData[curBPt].rx[0]))
1023 if (a->
pData[curAPt].pending > 0
1024 || (a->
pData[curAPt].rx[1] > ptX[1]
1025 || (a->
pData[curAPt].rx[1] == ptX[1]
1026 && a->
pData[curAPt].rx[0] > ptX[0])))
1030 isIntersection =
true;
1036 ptX = ptSh->
pData[nPt].rx;
1037 isIntersection =
false;
1042 if (b->
pData[curBPt].pending > 0
1043 || (b->
pData[curBPt].rx[1] > ptX[1]
1044 || (b->
pData[curBPt].rx[1] == ptX[1]
1045 && b->
pData[curBPt].rx[0] > ptX[0])))
1049 isIntersection =
true;
1055 ptX = ptSh->
pData[nPt].rx;
1056 isIntersection =
false;
1062 if (a->
pData[curAPt].pending > 0
1063 || (a->
pData[curAPt].rx[1] > ptX[1]
1064 || (a->
pData[curAPt].rx[1] == ptX[1]
1065 && a->
pData[curAPt].rx[0] > ptX[0])))
1069 isIntersection =
true;
1075 ptX = ptSh->
pData[nPt].rx;
1076 isIntersection =
false;
1082 if (b->
pData[curBPt].pending > 0
1083 || (b->
pData[curBPt].rx[1] > ptX[1]
1084 || (b->
pData[curBPt].rx[1] == ptX[1]
1085 && b->
pData[curBPt].rx[0] > ptX[0])))
1089 isIntersection =
true;
1095 ptX = ptSh->
pData[nPt].rx;
1096 isIntersection =
false;
1106 if (a->
pData[curAPt].rx[1] < b->
pData[curBPt].rx[1]
1107 || (a->
pData[curAPt].rx[1] == b->
pData[curBPt].rx[1]
1108 && a->
pData[curAPt].rx[0] < b->
pData[curBPt].rx[0]))
1130 ptX = ptSh->
pData[nPt].rx;
1131 isIntersection =
false;
1134 if (isIntersection ==
false)
1141 rPtX[0]=
Round (ptX[0]);
1142 rPtX[1]=
Round (ptX[1]);
1144 pData[lastPointNo].rx = rPtX;
1146 if (rPtX[1] > lastChange)
1151 Shape *curSh = shapeHead;
1152 int curBo = edgeHead;
1155 curSh->
swsData[curBo].leftRnd =
1157 curSh->
swsData[curBo].rightRnd =
1161 curBo = curSh->
swsData[curBo].nextBo;
1165 for (
auto & chgt :
chgts)
1167 chgt.ptNo =
pData[chgt.ptNo].newInd;
1170 if (chgt.src->getEdge(chgt.bord).st <
1171 chgt.src->getEdge(chgt.bord).en)
1173 chgt.src->
swsData[chgt.bord].stPt =
1178 chgt.src->swsData[chgt.bord].enPt =
1182 else if (chgt.type == 1)
1184 if (chgt.src->getEdge(chgt.bord).st >
1185 chgt.src->getEdge(chgt.bord).en)
1187 chgt.src->swsData[chgt.bord].stPt =
1192 chgt.src->swsData[chgt.bord].enPt =
1202 for (
int i = lastChgtPt; i < lastI; i++)
1204 if (
pData[i].askForWindingS)
1207 int windB =
pData[i].askForWindingB;
1208 pData[i].nextLinkedPoint =
1209 windS->
swsData[windB].firstLinkedPoint;
1210 windS->
swsData[windB].firstLinkedPoint = i;
1214 if (lastI < lastPointNo)
1219 lastPointNo = lastI;
1220 _pts.resize(lastI + 1);
1222 lastChgtPt = lastPointNo;
1223 lastChange = rPtX[1];
1226 shapeHead =
nullptr;
1249 int nbUp = 0, nbDn = 0;
1250 int upNo = -1, dnNo = -1;
1270 cb = ptSh->
NextAt (nPt, cb);
1277 if (upNo >= 0 && !ptSh->
swsData[upNo].misc)
1284 bool doWinding =
true;
1299 if (
node ==
nullptr)
1304 AddChgt (lastPointNo, lastChgtPt, shapeHead,
1307 ptSh->
swsData[cb].misc =
nullptr;
1309 int onLeftB = -1, onRightB = -1;
1310 Shape *onLeftS =
nullptr;
1311 Shape *onRightS =
nullptr;
1332 if (onLeftS && onRightS)
1344 if (onRightS == ptSh
1347 || onRightS->
getEdge(onRightB).
1360 cb = ptSh->
NextAt (nPt, cb);
1373 node->src,
node->bord,
nullptr, -1);
1375 ptSh->
swsData[upNo].misc =
nullptr;
1378 node->ConvertTo (ptSh, dnNo, 1, lastPointNo);
1382 insertionNode =
node;
1384 ptSh->
swsData[dnNo].curPoint = lastPointNo;
1387 node->src,
node->bord,
nullptr, -1);
1401 pData[lastPointNo].askForWindingS = myLeft->
src;
1402 pData[lastPointNo].askForWindingB = myLeft->
bord;
1406 pData[lastPointNo].askForWindingB = -1;
1413 insertionNode =
node;
1415 ptSh->
swsData[dnNo].curPoint = lastPointNo;
1418 node->src,
node->bord,
nullptr, -1);
1446 pData[lastPointNo].askForWindingS =
1448 pData[lastPointNo].askForWindingB =
1453 pData[lastPointNo].askForWindingB = -1;
1461 ptSh->
swsData[cb].curPoint = lastPointNo;
1463 AddChgt (lastPointNo, lastChgtPt, shapeHead,
1468 cb = ptSh->
NextAt (nPt, cb);
1477 Shape *curSh = shapeHead;
1478 int curBo = edgeHead;
1481 curSh->
swsData[curBo].leftRnd =
1483 curSh->
swsData[curBo].rightRnd =
1487 curBo = curSh->
swsData[curBo].nextBo;
1492 for (
auto & chgt :
chgts)
1494 chgt.ptNo =
pData[chgt.ptNo].newInd;
1497 if (chgt.src->getEdge(chgt.bord).st <
1498 chgt.src->getEdge(chgt.bord).en)
1500 chgt.src->
swsData[chgt.bord].stPt = chgt.ptNo;
1504 chgt.src->swsData[chgt.bord].enPt = chgt.ptNo;
1507 else if (chgt.type == 1)
1509 if (chgt.src->getEdge(chgt.bord).st >
1510 chgt.src->getEdge(chgt.bord).en)
1512 chgt.src->swsData[chgt.bord].stPt = chgt.ptNo;
1516 chgt.src->swsData[chgt.bord].enPt = chgt.ptNo;
1525 for (
int i = lastChgtPt; i < lastI; i++)
1527 if (
pData[i].askForWindingS)
1530 int windB =
pData[i].askForWindingB;
1531 pData[i].nextLinkedPoint = windS->
swsData[windB].firstLinkedPoint;
1532 windS->
swsData[windB].firstLinkedPoint = i;
1539 shapeHead =
nullptr;
1552 if (
ebData[i].pathID == cutPathID ) {
1555 ebData[nEd].pathID=cutPathID;
1562 int cp =
swsData[i].firstLinkedPoint;
1564 pData[cp].askForWindingB = nEd;
1565 cp =
pData[cp].nextLinkedPoint;
1568 swsData[i].firstLinkedPoint=-1;
1600 eData[i].weight = 1;
1605 eData[i].weight = 1;
1609 eData[i].weight = 0;
1621 eData[i].weight = 1;
1626 eData[i].weight = 1;
1630 eData[i].weight = 0;
1642 eData[i].weight = 1;
1647 eData[i].weight = 1;
1651 eData[i].weight = 0;
1664 pData[cp].askForWindingB = i;
1665 cp =
pData[cp].nextLinkedPoint;
1672 }
else if (
ebData[i].pathID == cutPathID ) {
1695 eData[i].weight = 1;
1700 eData[i].weight = 1;
1704 eData[i].weight = 0;
1743 if (tt ==
nullptr) {
1783 std::swap(lSt, lEn);
1791 std::swap(rSt, rEn);
1835 double ang = cross (ldir, rdir);
1838 if (
ang <= 0)
return false;
1843 if (iL->
src == iR->
src && lSt == rSt)
1846 if (iL->
src == iR->
src && lEn == rEn)
1856 if (iL->
src == iR->
src && lEn == rEn)
1865 if (onlyDiff && iL->
src == iR->
src)
1881 double slDot, elDot;
1882 double srDot, erDot;
1887 srDot = cross(rdir, sDiff);
1888 erDot = cross(rdir, eDiff);
1893 slDot = cross(ldir, sDiff);
1894 elDot = cross(ldir, eDiff);
1908 if ((srDot >= 0 && erDot >= 0) || (srDot <= 0 && erDot <= 0))
1932 atR = slDot / (slDot - elDot);
1940 else if (erDot == 0)
1946 atR = slDot / (slDot - elDot);
1956 if (srDot > 0 && erDot > 0)
1966 atR = slDot / (slDot - elDot);
1976 atR = slDot / (slDot - elDot);
1982 if (srDot < 0 && erDot < 0)
1992 atR = slDot / (slDot - elDot);
2002 atR = slDot / (slDot - elDot);
2011 if ((slDot >= 0 && elDot >= 0) || (slDot <= 0 && elDot <= 0))
2019 atL = srDot / (srDot - erDot);
2027 else if (elDot == 0)
2033 atL = srDot / (srDot - erDot);
2041 if (slDot > 0 && elDot > 0)
2051 atL = srDot / (srDot - erDot);
2061 atL = srDot / (srDot - erDot);
2067 if (slDot < 0 && elDot < 0)
2077 atL = srDot / (srDot - erDot);
2087 atL = srDot / (srDot - erDot);
2108 elDot * iR->
src->
pData[rSt].rx) / (slDot - elDot);
2114 erDot * iL->
src->
pData[lSt].rx) / (srDot - erDot);
2116 atL = srDot / (srDot - erDot);
2117 atR = slDot / (slDot - elDot);
2127 if (theta < 0 || theta > 1)
2140 a->
swsData[cb].firstLinkedPoint = n;
2148 adir = a->
eData[no].rdx;
2150 double t =
dot (diff, adir);
2151 t *= a->
eData[no].ilength;
2161 int askTo =
pData[nPt].askForWindingB;
2182 int lr = 0, ll = 0, rr = 0;
2188 adir =
eData[i].rdx;
2193 int nWeight =
eData[i].weight;
2202 if (ast[0] < aen[0])
2219 if (ast[0] == px[0])
2221 if (ast[1] >= px[1])
2223 if (aen[0] == px[0])
2231 if (aen[0] == px[0])
2233 if (aen[1] >= px[1])
2235 if (ast[0] == px[0])
2246 if (ast[1] < aen[1])
2248 if (ast[1] >= px[1])
2253 if (aen[1] >= px[1])
2259 double cote = cross(adir, diff);
2273 return lr + (ll + rr) / 2;
2281 for (
int i = st; i < en; i++)
pData[i].oldInd = i;
2287 for (
int i = st; i < en; i++)
pData[
pData[i].oldInd].newInd = i;
2290 for (
int i = st; i < en; i++) {
2291 pData[i].pending = lastI++;
2294 if (
pData[
pData[i].pending].askForWindingS ==
nullptr) {
2299 &&
pData[
pData[i].pending].askForWindingB ==
pData[i].askForWindingB) {
2311 if (i >
pData[i].pending) {
2319 for (
int i = st; i < en; i++)
pData[i].newInd =
pData[
pData[i].newInd].pending;
2337 for (
int i = 0; i <
nbInc; i++)
2369 }
else if (
ebData[cb].pieceID ==
ebData[cc].pieceID ) {
2377 if ( doublon )
eData[cc].weight = 0;
2386 eData[cc].weight = 0;
2389 if (
swsData[cc].firstLinkedPoint >= 0) {
2390 int cp =
swsData[cc].firstLinkedPoint;
2392 pData[cp].askForWindingB = cb;
2393 cp =
pData[cp].nextLinkedPoint;
2395 if (
swsData[cb].firstLinkedPoint < 0) {
2398 int ncp =
swsData[cb].firstLinkedPoint;
2399 while (
pData[ncp].nextLinkedPoint >= 0) {
2400 ncp =
pData[ncp].nextLinkedPoint;
2402 pData[ncp].nextLinkedPoint =
swsData[cc].firstLinkedPoint;
2413 pData[cp].askForWindingB = cc;
2414 cp =
pData[cp].nextLinkedPoint;
2429 int other =
Other (i, cb);
2433 int ncc =
NextAt (i, cc);
2435 if (cc != cb &&
Other (i, cc) == other ) doublon=
true;
2443 }
else if (
ebData[cb].pieceID ==
ebData[cc].pieceID ) {
2450 if ( doublon )
eData[cc].weight = 0;
2461 eData[cc].weight = 0;
2463 if (
swsData[cc].firstLinkedPoint >= 0) {
2464 int cp =
swsData[cc].firstLinkedPoint;
2466 pData[cp].askForWindingB = cb;
2467 cp =
pData[cp].nextLinkedPoint;
2469 if (
swsData[cb].firstLinkedPoint < 0) {
2472 int ncp =
swsData[cb].firstLinkedPoint;
2473 while (
pData[ncp].nextLinkedPoint >= 0) {
2474 ncp =
pData[ncp].nextLinkedPoint;
2476 pData[ncp].nextLinkedPoint =
swsData[cc].firstLinkedPoint;
2485 pData[cp].askForWindingB = cc;
2486 cp =
pData[cp].nextLinkedPoint;
2563 lastPtUsed = fi + 1;
2595 if (
getPoint(fi).totalDegree() == 1 ) {
2596 if ( fi ==
getEdge(startBord).en ) {
2606 if (
getEdge(startBord).en == fi)
2607 outsideW +=
eData[startBord].weight;
2622 swdData[startBord].leW = outsideW;
2623 swdData[startBord].riW = outsideW -
eData[startBord].weight;
2626 int curBord = startBord;
2630 swdData[curBord].precParc = -1;
2631 swdData[curBord].suivParc = -1;
2671 while (nb >= 0 && nb != curBord &&
swdData[nb].misc != 0);
2674 if (nb < 0 || nb == curBord)
2685 curBord =
swdData[curBord].precParc;
2689 if (oPt ==
getEdge(curBord).en)
2700 swdData[nb].ind = searchInd++;
2712 swdData[nb].precParc = curBord;
2713 swdData[curBord].suivParc = nb;
2739 if (lSt == rSt || lSt == rEn)
2743 if (lEn == rSt || lEn == rEn)
2749 ldir = ils->
eData[ilb].rdx;
2750 rdir = irs->
eData[irb].rdx;
2752 double il = ils->
pData[lSt].rx[0], it = ils->
pData[lSt].rx[1], ir =
2753 ils->
pData[lEn].rx[0], ib = ils->
pData[lEn].rx[1];
2762 double jl = irs->
pData[rSt].rx[0], jt = irs->
pData[rSt].rx[1], jr =
2763 irs->
pData[rEn].rx[0], jb = irs->
pData[rEn].rx[1];
2773 if (il > jr || it > jb || ir < jl || ib < jt)
2779 double slDot, elDot;
2780 double srDot, erDot;
2781 sDiff = ils->
pData[lSt].rx - irs->
pData[rSt].rx;
2782 eDiff = ils->
pData[lEn].rx - irs->
pData[rSt].rx;
2783 srDot = cross(rdir, sDiff);
2784 erDot = cross(rdir, eDiff);
2785 if ((srDot >= 0 && erDot >= 0) || (srDot <= 0 && erDot <= 0))
2788 sDiff = irs->
pData[rSt].rx - ils->
pData[lSt].rx;
2789 eDiff = irs->
pData[rEn].rx - ils->
pData[lSt].rx;
2790 slDot = cross(ldir, sDiff);
2791 elDot = cross(ldir, eDiff);
2792 if ((slDot >= 0 && elDot >= 0) || (slDot <= 0 && elDot <= 0))
2795 double slb = slDot - elDot, srb = srDot - erDot;
2803 (slDot * irs->
pData[rEn].rx - elDot * irs->
pData[rSt].rx) / (slDot -
2809 (srDot * ils->
pData[lEn].rx - erDot * ils->
pData[lSt].rx) / (srDot -
2812 atL = srDot / (srDot - erDot);
2813 atR = slDot / (slDot - elDot);
2819 usvs = irs->
pData[rSt].rx - ils->
pData[lSt].rx;
2827 double tdet =
det * ils->
eData[ilb].isqlength * irs->
eData[irb].isqlength;
2829 if (tdet > -0.0001 && tdet < 0.0001)
2833 sDiff = ils->
pData[lSt].rx - irs->
pData[rSt].rx;
2834 eDiff = ils->
pData[lEn].rx - irs->
pData[rSt].rx;
2835 sDot = cross(rdir, sDiff);
2836 eDot = cross(rdir, eDiff);
2839 (sDot * irs->
pData[lEn].rx - eDot * irs->
pData[lSt].rx) / (sDot -
2841 atL = sDot / (sDot - eDot);
2843 sDiff = irs->
pData[rSt].rx - ils->
pData[lSt].rx;
2844 eDiff = irs->
pData[rEn].rx - ils->
pData[lSt].rx;
2845 sDot = cross(ldir, sDiff);
2846 eDot = cross(ldir, eDiff);
2848 atR = sDot / (sDot - eDot);
2862 atL = (m[0]* usvs[0] + m[1] * usvs[1]) /
det;
2863 atR = -(m[2] * usvs[0] + m[3] * usvs[1]) /
det;
2864 atx = ils->
pData[lSt].rx + atL * ldir;
2877 Geom::Point adir, diff, ast, aen, diff1, diff2, diff3, diff4;
2882 adir = a->
eData[no].rdx;
2884 double sle = a->
eData[no].length;
2885 double ile = a->
eData[no].ilength;
2890 if (-3 < e && e < 3)
2894 diff1[0] = diff[0] - rad;
2895 diff1[1] = diff[1] - rad;
2896 diff2[0] = diff[0] + rad;
2897 diff2[1] = diff[1] - rad;
2898 diff3[0] = diff[0] + rad;
2899 diff3[1] = diff[1] + rad;
2900 diff4[0] = diff[0] - rad;
2901 diff4[1] = diff[1] + rad;
2903 bool adjacent =
false;
2904 di1 = cross(adir, diff1);
2905 di2 = cross(adir, diff3);
2906 if ((di1 < 0 && di2 > 0) || (di1 > 0 && di2 < 0))
2912 di1 = cross(adir, diff2);
2913 di2 = cross(adir, diff4);
2914 if ((di1 < 0 && di2 > 0) || (di1 > 0 && di2 < 0))
2921 double t =
dot (diff, adir);
2922 if (t > 0 && t < sle)
2941 for (
auto & chgt :
chgts)
2944 int chLeN = chgt.ptNo;
2945 int chRiN = chgt.ptNo;
2948 Shape *lS = chgt.src;
2951 int lftN = lS->
swsData[lB].leftRnd;
2952 int rgtN = lS->
swsData[lB].rightRnd;
2964 for (
int n = lftN - 1; n >= lastChgtPt; n--)
2975 for (
int n = rgtN + 1; n < lastPointNo; n++)
2986 Shape *rS = chgt.osrc;
2987 int rB = chgt.obord;
2988 int lftN = rS->
swsData[rB].leftRnd;
2989 int rgtN = rS->
swsData[rB].rightRnd;
2995 for (
int n = lftN - 1; n >= lastChgtPt; n--)
3002 for (
int n = rgtN + 1; n < lastPointNo; n++)
3017 if (chgt.lSrc->swsData[chgt.lBrd].leftRnd < lastChgtPt)
3020 Shape *nSrc = chgt.lSrc;
3021 int nBrd = chgt.lBrd ;
3030 for (
int n = chRiN; n >= chLeN; n--)
3034 (nSrc, nBrd,
getPoint(n).x, n,
false))
3037 if (nSrc->
swsData[nBrd].leftRnd < lastChgtPt)
3039 nSrc->
swsData[nBrd].leftRnd = n;
3040 nSrc->
swsData[nBrd].rightRnd = n;
3044 if (n < nSrc->
swsData[nBrd].leftRnd)
3045 nSrc->
swsData[nBrd].leftRnd = n;
3046 if (n > nSrc->
swsData[nBrd].rightRnd)
3047 nSrc->
swsData[nBrd].rightRnd = n;
3053 for (
int n = chLeN - 1; n >= lastChgtPt; n--)
3056 (nSrc, nBrd,
getPoint(n).x, n,
false) ==
false)
3058 if (nSrc->
swsData[nBrd].leftRnd < lastChgtPt)
3060 nSrc->
swsData[nBrd].leftRnd = n;
3061 nSrc->
swsData[nBrd].rightRnd = n;
3065 if (n < nSrc->
swsData[nBrd].leftRnd)
3066 nSrc->
swsData[nBrd].leftRnd = n;
3067 if (n > nSrc->
swsData[nBrd].rightRnd)
3068 nSrc->
swsData[nBrd].rightRnd = n;
3079 if (
node ==
nullptr)
3082 if (
node ==
nullptr)
3087 if (nSrc->
swsData[nBrd].leftRnd >= lastChgtPt)
3098 if (chgt.rSrc->swsData[chgt.rBrd].leftRnd < lastChgtPt)
3100 Shape *nSrc = chgt.rSrc;
3101 int nBrd = chgt.rBrd ;
3108 for (
int n = chLeN; n <= chRiN; n++)
3113 if (nSrc->
swsData[nBrd].leftRnd < lastChgtPt)
3115 nSrc->
swsData[nBrd].leftRnd = n;
3116 nSrc->
swsData[nBrd].rightRnd = n;
3120 if (n < nSrc->
swsData[nBrd].leftRnd)
3121 nSrc->
swsData[nBrd].leftRnd = n;
3122 if (n > nSrc->
swsData[nBrd].rightRnd)
3123 nSrc->
swsData[nBrd].rightRnd = n;
3129 for (
int n = chRiN + 1; n < lastPointNo; n++)
3132 (nSrc, nBrd,
getPoint(n).
x, n,
false) ==
false)
3134 if (nSrc->
swsData[nBrd].leftRnd < lastChgtPt)
3136 nSrc->
swsData[nBrd].leftRnd = n;
3137 nSrc->
swsData[nBrd].rightRnd = n;
3141 if (n < nSrc->
swsData[nBrd].leftRnd)
3142 nSrc->
swsData[nBrd].leftRnd = n;
3143 if (n > nSrc->
swsData[nBrd].rightRnd)
3144 nSrc->
swsData[nBrd].rightRnd = n;
3151 if (
node ==
nullptr)
3154 if (
node ==
nullptr)
3158 if (nSrc->
swsData[nBrd].leftRnd >= lastChgtPt)
3175 c.
ptNo = lastPointNo;
3183 const int nCh =
chgts.size() - 1;
3195 chgts[nCh].lSrc =
nullptr;
3196 chgts[nCh].lBrd = -1;
3203 if (lS->
swsData[lB].leftRnd < lastChgtPt) {
3204 lS->
swsData[lB].leftRnd = lastPointNo;
3205 lS->
swsData[lB].nextSh = shapeHead;
3206 lS->
swsData[lB].nextBo = edgeHead;
3212 int old = lS->
swsData[lB].leftRnd;
3218 lS->
swsData[lB].leftRnd = lastPointNo;
3222 if (lS->
swsData[lB].rightRnd < lastChgtPt) {
3223 lS->
swsData[lB].rightRnd = lastPointNo;
3225 int old = lS->
swsData[lB].rightRnd;
3227 lS->
swsData[lB].rightRnd = lastPointNo;
3241 chgts[nCh].rSrc =
nullptr;
3242 chgts[nCh].rBrd = -1;
3246 if (rS->
swsData[rB].leftRnd < lastChgtPt) {
3247 rS->
swsData[rB].leftRnd = lastPointNo;
3248 rS->
swsData[rB].nextSh = shapeHead;
3249 rS->
swsData[rB].nextBo = edgeHead;
3253 int old = rS->
swsData[rB].leftRnd;
3255 rS->
swsData[rB].leftRnd = lastPointNo;
3258 if (rS->
swsData[rB].rightRnd < lastChgtPt) {
3259 rS->
swsData[rB].rightRnd = lastPointNo;
3261 int old = rS->
swsData[rB].rightRnd;
3263 rS->
swsData[rB].rightRnd = lastPointNo;
3273 chgts[nCh].rSrc =
nullptr;
3274 chgts[nCh].rBrd = -1;
3311 for (
auto & chgt :
chgts)
3318 Shape *lS = chgt.src;
3320 lS->
swsData[lB].curPoint = chgt.ptNo;
3324 for (
auto & chgt :
chgts)
3331 Shape *lS = chgt.src;
3333 Avance (lastPointNo, lastChgtPt, lS, lB, a, b, mod);
3338 Shape *rS = chgt.osrc;
3339 int rB = chgt.obord;
3340 Avance (lastPointNo, lastChgtPt, rS, rB, a, b, mod);
3354 Shape *nSrc = chgt.lSrc;
3355 int nBrd = chgt.lBrd;
3356 while (nSrc->
swsData[nBrd].leftRnd >=
3359 Avance (lastPointNo, lastChgtPt, nSrc, nBrd, a, b, mod);
3362 if (
node ==
nullptr)
3365 if (
node ==
nullptr)
3373 Shape *nSrc = chgt.rSrc;
3374 int nBrd = chgt.rBrd;
3375 while (nSrc->
swsData[nBrd].rightRnd >=
3378 Avance (lastPointNo, lastChgtPt, nSrc, nBrd, a, b, mod);
3381 if (
node ==
nullptr)
3384 if (
node ==
nullptr)
3398 bool avoidDiag =
false;
3410 int lftN = lS->
swsData[lB].leftRnd;
3411 int rgtN = lS->
swsData[lB].rightRnd;
3414 if (lS->
swsData[lB].doneTo < lastChgtPt)
3417 int lp = lS->
swsData[lB].curPoint;
3429 if (lS->
eData[lB].rdx[1] == 0)
3432 if (lS->
eData[lB].rdx[0] >= 0)
3434 for (
int p = lftN; p <= rgtN; p++)
3436 DoEdgeTo (lS, lB, p, direct,
true);
3442 for (
int p = lftN; p <= rgtN; p++)
3444 DoEdgeTo (lS, lB, p, direct,
false);
3449 else if (lS->
eData[lB].rdx[1] > 0)
3451 if (lS->
eData[lB].rdx[0] >= 0)
3454 for (
int p = lftN; p <= rgtN; p++)
3459 if (avoidDiag && p == lftN &&
getPoint(lftN).x[0] ==
getPoint(lp).x[0] + dd)
3464 if (lftN > 0 && lftN - 1 >= lastChgtPt
3467 DoEdgeTo (lS, lB, lftN - 1, direct,
true);
3468 DoEdgeTo (lS, lB, lftN, direct,
true);
3472 DoEdgeTo (lS, lB, lftN, direct,
true);
3477 DoEdgeTo (lS, lB, p, direct,
true);
3485 for (
int p = rgtN; p >= lftN; p--)
3488 if (avoidDiag && p == rgtN &&
getPoint(rgtN).x[0] ==
getPoint(lp).x[0] - dd)
3493 DoEdgeTo (lS, lB, rgtN + 1, direct,
true);
3494 DoEdgeTo (lS, lB, rgtN, direct,
true);
3498 DoEdgeTo (lS, lB, rgtN, direct,
true);
3503 DoEdgeTo (lS, lB, p, direct,
true);
3511 if (lS->
eData[lB].rdx[0] >= 0)
3514 for (
int p = rgtN; p >= lftN; p--)
3516 if (avoidDiag && p == rgtN &&
getPoint(rgtN).x[0] ==
getPoint(lp).x[0] - dd)
3521 DoEdgeTo (lS, lB, rgtN + 1, direct,
false);
3522 DoEdgeTo (lS, lB, rgtN, direct,
false);
3526 DoEdgeTo (lS, lB, rgtN, direct,
false);
3531 DoEdgeTo (lS, lB, p, direct,
false);
3539 for (
int p = lftN; p <= rgtN; p++)
3542 if (avoidDiag && p == lftN &&
getPoint(lftN).x[0] ==
getPoint(lp).x[0] + dd)
3544 if (lftN > 0 && lftN - 1 >= lastChgtPt
3547 DoEdgeTo (lS, lB, lftN - 1, direct,
false);
3548 DoEdgeTo (lS, lB, lftN, direct,
false);
3552 DoEdgeTo (lS, lB, lftN, direct,
false);
3557 DoEdgeTo (lS, lB, p, direct,
false);
3563 lS->
swsData[lB].curPoint = lp;
3568 lS->
swsData[lB].doneTo = lastPointNo - 1;
3574 int lp = iS->
swsData[iB].curPoint;
3594 if (iS->
eData[iB].length < 0.00001)
3600 double bdl = iS->
eData[iB].ilength;
3607 double pst =
dot(psbx,bdx) * bdl;
3608 double pet =
dot(pebx,bdx) * bdl;
3609 pst = iS->
ebData[iB].tSt * (1 - pst) + iS->
ebData[iB].tEn * pst;
3610 pet = iS->
ebData[iB].tSt * (1 - pet) + iS->
ebData[iB].tEn * pet;
3615 iS->
swsData[iB].curPoint = iTo;
3618 int cp = iS->
swsData[iB].firstLinkedPoint;
3622 pData[cp].askForWindingB = ne;
3623 cp =
pData[cp].nextLinkedPoint;
3625 iS->
swsData[iB].firstLinkedPoint = -1;
TODO: insert short description here.
bool directedEulerian(Shape const *s)
Is the graph Eulerian?
3x3 affine transformation matrix.
3x3 matrix representing an affine transformation.
Coord det() const
Calculate the determinant.
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 DoEdgeTo(Shape *iS, int iB, int iTo, bool direct, bool sens)
Draw edge to a passed point.
int PushIncidence(Shape *a, int cb, int pt, double theta)
void MakeSweepDestData(bool nVal)
Initialize the sweep destination data cache.
void AddChgt(int lastPointNo, int lastChgtPt, Shape *&shapeHead, int &edgeHead, sTreeChangeType type, Shape *lS, int lB, Shape *rS, int rB)
Add the event in chgts.
std::vector< sweep_src_data > swsData
int Other(int p, int b) const
sTreeChangeType
Enum describing all the events that can happen to a sweepline.
void CheckAdjacencies(int lastPointNo, int lastChgtPt, Shape *shapeHead, int edgeHead)
If there are points that lie on edges, mark this by modifying leftRnd and rightRnd variables.
void ResetSweep()
Prepare point data cache, edge data cache and sweep source cache.
void AssembleAretes(FillRule directed=fill_nonZero)
int Booleen(Shape *a, Shape *b, BooleanOp mod, int cutPathID=-1)
void MakeBackData(bool nVal)
bool _point_data_initialised
the pData array is up to date
std::vector< sTreeChange > chgts
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 CyclePrevAt(int p, int b) const
bool _has_sweep_src_data
the swsData array is allocated
bool hasPoints() const
Do we have points?
std::vector< raster_data > swrData
bool TesteAdjacency(Shape *iL, int ilb, const Geom::Point atx, int nPt, bool push)
bool _bbox_up_to_date
the leftX/rightX/topY/bottomY are up to date
void CheckEdges(int lastPointNo, int lastChgtPt, Shape *a, Shape *b, BooleanOp mod)
Check if there are edges to draw and draw them.
std::vector< back_data > ebData
static double IHalfRound(double x)
void MakePointData(bool nVal)
Initialize the point data cache.
bool _need_edges_sorting
edges have been added: maybe they are not ordered clockwise
void Avance(int lastPointNo, int lastChgtPt, Shape *iS, int iB, Shape *a, Shape *b, BooleanOp mod)
Do the edge.
static double HalfRound(double x)
int numberOfEdges() const
Returns number of edges.
void CleanupSweep()
Clear point data cache, edge data cache and sweep source cache.
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
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 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
void GetWindings(bool brutal=false)
Calculates the winding numbers to the left and right of all edges of this shape.
int ConvertToShape(Shape *a, FillRule directed=fill_nonZero, bool invert=false)
Using a given fill rule, find all intersections in the shape given, create a new intersection free sh...
bool _has_raster_data
the swrData array is allocated
friend class SweepEventQueue
std::vector< dg_arete > _aretes
int AddPoint(const Geom::Point x)
void MakeEdgeData(bool nVal)
Initialize the edge data cache.
void TesteIntersection(SweepTree *t, Side s, bool onlyDiff)
Test if there is an intersection of an edge on a particular side.
void clearIncidenceData()
bool _has_sweep_dest_data
the swdData array is allocated
int Winding(const Geom::Point px) const
Compute the winding number of the point given.
dg_point const & getPoint(int n) const
Get a point.
std::vector< sweep_dest_data > swdData
void initialisePointData()
bool hasBackData() const
Do we have back data?
void AssemblePoints(Shape *a)
void DisconnectEnd(int b)
int CreateIncidence(Shape *a, int cb, int pt)
std::vector< point_data > pData
SweepEvent * add(SweepTree *iLeft, SweepTree *iRight, Geom::Point &iPt, double itl, double itr)
Add an intersection in the binary heap.
bool peek(SweepTree *&iLeft, SweepTree *&iRight, Geom::Point &oPt, double &itl, double &itr)
Look for the top most intersection in the heap.
bool extract(SweepTree *&iLeft, SweepTree *&iRight, Geom::Point &oPt, double &itl, double &itr)
Extract the top most intersection from the heap.
int size() const
Number of events currently stored.
The sweepline tree to store a linear sequence of edges that intersect with the sweepline in the exact...
SweepTree * add(Shape *iSrc, int iBord, int iWeight, int iStartPoint, Shape *iDst)
Create a new node and add it.
One node in the AVL tree of edges.
void SwapWithRight(SweepTreeList &list, SweepEventQueue &queue)
Swap nodes, or more exactly, swap the edges in them.
void RemoveEvent(SweepEventQueue &queue, Side s)
Remove event on the side s if it exists from event queue.
static T det(T a, T b, T c, T d)
Inkscape::XML::Node * node
double ang(Point n1, Point n2)
void invert(const double v[16], double alpha[16])
A structure that represents a change that took place in the sweepline.
A container of intersection events.
TODO: insert short description here.
TODO: insert short description here.
void dot(Cairo::RefPtr< Cairo::Context > &cr, double x, double y)