00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <cstdio>
00010 #include <cstdlib>
00011 #include <cstring>
00012 #include <glib/gmem.h>
00013 #include "Shape.h"
00014 #include "livarot/sweep-event-queue.h"
00015 #include "livarot/sweep-tree-list.h"
00016 #include "livarot/sweep-tree.h"
00017
00018 #include "libnr/nr-matrix.h"
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 void
00047 Shape::ResetSweep (void)
00048 {
00049 MakePointData (true);
00050 MakeEdgeData (true);
00051 MakeSweepSrcData (true);
00052 }
00053
00054 void
00055 Shape::CleanupSweep (void)
00056 {
00057 MakePointData (false);
00058 MakeEdgeData (false);
00059 MakeSweepSrcData (false);
00060 }
00061
00062 void
00063 Shape::ForceToPolygon (void)
00064 {
00065 type = shape_polygon;
00066 }
00067
00068 int
00069 Shape::Reoriente (Shape * a)
00070 {
00071 Reset (0, 0);
00072 if (a->numberOfPoints() <= 1 || a->numberOfEdges() <= 1)
00073 return 0;
00074 if (directedEulerian(a) == false)
00075 return shape_input_err;
00076
00077 _pts = a->_pts;
00078 if (numberOfPoints() > maxPt)
00079 {
00080 maxPt = numberOfPoints();
00081 if (_has_points_data) {
00082 pData.resize(maxPt);
00083 _point_data_initialised = false;
00084 _bbox_up_to_date = false;
00085 }
00086 }
00087
00088 _aretes = a->_aretes;
00089 if (numberOfEdges() > maxAr)
00090 {
00091 maxAr = numberOfEdges();
00092 if (_has_edges_data)
00093 eData.resize(maxAr);
00094 if (_has_sweep_src_data)
00095 swsData.resize(maxAr);
00096 if (_has_sweep_dest_data)
00097 swdData.resize(maxAr);
00098 if (_has_raster_data)
00099 swrData.resize(maxAr);
00100 }
00101
00102 MakePointData (true);
00103 MakeEdgeData (true);
00104 MakeSweepDestData (true);
00105
00106 initialisePointData();
00107
00108 for (int i = 0; i < numberOfPoints(); i++) {
00109 _pts[i].x = pData[i].rx;
00110 _pts[i].oldDegree = getPoint(i).totalDegree();
00111 }
00112
00113 for (int i = 0; i < a->numberOfEdges(); i++)
00114 {
00115 eData[i].rdx = pData[getEdge(i).en].rx - pData[getEdge(i).st].rx;
00116 eData[i].weight = 1;
00117 _aretes[i].dx = eData[i].rdx;
00118 }
00119
00120 SortPointsRounded ();
00121
00122 _need_edges_sorting = true;
00123 GetWindings (this, NULL, bool_op_union, true);
00124
00125
00126 for (int i = 0; i < numberOfEdges(); i++)
00127 {
00128 swdData[i].leW %= 2;
00129 swdData[i].riW %= 2;
00130 if (swdData[i].leW < 0)
00131 swdData[i].leW = -swdData[i].leW;
00132 if (swdData[i].riW < 0)
00133 swdData[i].riW = -swdData[i].riW;
00134 if (swdData[i].leW > 0 && swdData[i].riW <= 0)
00135 {
00136 eData[i].weight = 1;
00137 }
00138 else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
00139 {
00140 Inverse (i);
00141 eData[i].weight = 1;
00142 }
00143 else
00144 {
00145 eData[i].weight = 0;
00146 SubEdge (i);
00147 i--;
00148 }
00149 }
00150
00151 MakePointData (false);
00152 MakeEdgeData (false);
00153 MakeSweepDestData (false);
00154
00155 if (directedEulerian(this) == false)
00156 {
00157
00158 _pts.clear();
00159 _aretes.clear();
00160 return shape_euler_err;
00161 }
00162
00163 type = shape_polygon;
00164 return 0;
00165 }
00166
00167 int
00168 Shape::ConvertToShape (Shape * a, FillRule directed, bool invert)
00169 {
00170 Reset (0, 0);
00171
00172 if (a->numberOfPoints() <= 1 || a->numberOfEdges() <= 1) {
00173 return 0;
00174 }
00175
00176 if ( directed != fill_justDont && directedEulerian(a) == false ) {
00177 g_warning ("Shape error in ConvertToShape: directedEulerian(a) == false\n");
00178 return shape_input_err;
00179 }
00180
00181 a->ResetSweep();
00182
00183 if (sTree == NULL) {
00184 sTree = new SweepTreeList(a->numberOfEdges());
00185 }
00186 if (sEvts == NULL) {
00187 sEvts = new SweepEventQueue(a->numberOfEdges());
00188 }
00189
00190 MakePointData(true);
00191 MakeEdgeData(true);
00192 MakeSweepSrcData(true);
00193 MakeSweepDestData(true);
00194 MakeBackData(a->_has_back_data);
00195
00196 a->initialisePointData();
00197 a->initialiseEdgeData();
00198
00199 a->SortPointsRounded();
00200
00201 chgts.clear();
00202
00203 double lastChange = a->pData[0].rx[1] - 1.0;
00204 int lastChgtPt = 0;
00205 int edgeHead = -1;
00206 Shape *shapeHead = NULL;
00207
00208 clearIncidenceData();
00209
00210 int curAPt = 0;
00211
00212 while (curAPt < a->numberOfPoints() || sEvts->size() > 0) {
00213 Geom::Point ptX;
00214 double ptL, ptR;
00215 SweepTree *intersL = NULL;
00216 SweepTree *intersR = NULL;
00217 int nPt = -1;
00218 Shape *ptSh = NULL;
00219 bool isIntersection = false;
00220 if (sEvts->peek(intersL, intersR, ptX, ptL, ptR))
00221 {
00222 if (a->pData[curAPt].pending > 0
00223 || (a->pData[curAPt].rx[1] > ptX[1]
00224 || (a->pData[curAPt].rx[1] == ptX[1]
00225 && a->pData[curAPt].rx[0] > ptX[0])))
00226 {
00227
00228 sEvts->extract(intersL, intersR, ptX, ptL, ptR);
00229 isIntersection = true;
00230 }
00231 else
00232 {
00233 nPt = curAPt++;
00234 ptSh = a;
00235 ptX = ptSh->pData[nPt].rx;
00236 isIntersection = false;
00237 }
00238 }
00239 else
00240 {
00241 nPt = curAPt++;
00242 ptSh = a;
00243 ptX = ptSh->pData[nPt].rx;
00244 isIntersection = false;
00245 }
00246
00247 if (isIntersection == false)
00248 {
00249 if (ptSh->getPoint(nPt).dI == 0 && ptSh->getPoint(nPt).dO == 0)
00250 continue;
00251 }
00252
00253 Geom::Point rPtX;
00254 rPtX[0]= Round (ptX[0]);
00255 rPtX[1]= Round (ptX[1]);
00256 int lastPointNo = -1;
00257 lastPointNo = AddPoint (rPtX);
00258 pData[lastPointNo].rx = rPtX;
00259
00260 if (rPtX[1] > lastChange)
00261 {
00262 int lastI = AssemblePoints (lastChgtPt, lastPointNo);
00263
00264 Shape *curSh = shapeHead;
00265 int curBo = edgeHead;
00266 while (curSh)
00267 {
00268 curSh->swsData[curBo].leftRnd =
00269 pData[curSh->swsData[curBo].leftRnd].newInd;
00270 curSh->swsData[curBo].rightRnd =
00271 pData[curSh->swsData[curBo].rightRnd].newInd;
00272
00273 Shape *neSh = curSh->swsData[curBo].nextSh;
00274 curBo = curSh->swsData[curBo].nextBo;
00275 curSh = neSh;
00276 }
00277
00278 for (unsigned int i = 0; i < chgts.size(); i++)
00279 {
00280 chgts[i].ptNo = pData[chgts[i].ptNo].newInd;
00281 if (chgts[i].type == 0)
00282 {
00283 if (chgts[i].src->getEdge(chgts[i].bord).st <
00284 chgts[i].src->getEdge(chgts[i].bord).en)
00285 {
00286 chgts[i].src->swsData[chgts[i].bord].stPt =
00287 chgts[i].ptNo;
00288 }
00289 else
00290 {
00291 chgts[i].src->swsData[chgts[i].bord].enPt =
00292 chgts[i].ptNo;
00293 }
00294 }
00295 else if (chgts[i].type == 1)
00296 {
00297 if (chgts[i].src->getEdge(chgts[i].bord).st >
00298 chgts[i].src->getEdge(chgts[i].bord).en)
00299 {
00300 chgts[i].src->swsData[chgts[i].bord].stPt =
00301 chgts[i].ptNo;
00302 }
00303 else
00304 {
00305 chgts[i].src->swsData[chgts[i].bord].enPt =
00306 chgts[i].ptNo;
00307 }
00308 }
00309 }
00310
00311 CheckAdjacencies (lastI, lastChgtPt, shapeHead, edgeHead);
00312
00313 CheckEdges (lastI, lastChgtPt, a, NULL, bool_op_union);
00314
00315 for (int i = lastChgtPt; i < lastI; i++) {
00316 if (pData[i].askForWindingS) {
00317 Shape *windS = pData[i].askForWindingS;
00318 int windB = pData[i].askForWindingB;
00319 pData[i].nextLinkedPoint = windS->swsData[windB].firstLinkedPoint;
00320 windS->swsData[windB].firstLinkedPoint = i;
00321 }
00322 }
00323
00324 if (lastI < lastPointNo) {
00325 _pts[lastI] = getPoint(lastPointNo);
00326 pData[lastI] = pData[lastPointNo];
00327 }
00328 lastPointNo = lastI;
00329 _pts.resize(lastI + 1);
00330
00331 lastChgtPt = lastPointNo;
00332 lastChange = rPtX[1];
00333 chgts.clear();
00334 edgeHead = -1;
00335 shapeHead = NULL;
00336 }
00337
00338
00339 if (isIntersection)
00340 {
00341
00342 intersL->RemoveEvent (*sEvts, LEFT);
00343 intersR->RemoveEvent (*sEvts, RIGHT);
00344
00345 AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, INTERSECTION,
00346 intersL->src, intersL->bord, intersR->src, intersR->bord);
00347
00348 intersL->SwapWithRight (*sTree, *sEvts);
00349
00350 TesteIntersection (intersL, LEFT, false);
00351 TesteIntersection (intersR, RIGHT, false);
00352 }
00353 else
00354 {
00355 int cb;
00356
00357 int nbUp = 0, nbDn = 0;
00358 int upNo = -1, dnNo = -1;
00359 cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
00360 while (cb >= 0 && cb < ptSh->numberOfEdges())
00361 {
00362 if ((ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
00363 && nPt == ptSh->getEdge(cb).en)
00364 || (ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
00365 && nPt == ptSh->getEdge(cb).st))
00366 {
00367 upNo = cb;
00368 nbUp++;
00369 }
00370 if ((ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
00371 && nPt == ptSh->getEdge(cb).en)
00372 || (ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
00373 && nPt == ptSh->getEdge(cb).st))
00374 {
00375 dnNo = cb;
00376 nbDn++;
00377 }
00378 cb = ptSh->NextAt (nPt, cb);
00379 }
00380
00381 if (nbDn <= 0)
00382 {
00383 upNo = -1;
00384 }
00385 if (upNo >= 0 && (SweepTree *) ptSh->swsData[upNo].misc == NULL)
00386 {
00387 upNo = -1;
00388 }
00389
00390 bool doWinding = true;
00391
00392 if (nbUp > 0)
00393 {
00394 cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
00395 while (cb >= 0 && cb < ptSh->numberOfEdges())
00396 {
00397 if ((ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
00398 && nPt == ptSh->getEdge(cb).en)
00399 || (ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
00400 && nPt == ptSh->getEdge(cb).st))
00401 {
00402 if (cb != upNo)
00403 {
00404 SweepTree *node =
00405 (SweepTree *) ptSh->swsData[cb].misc;
00406 if (node == NULL)
00407 {
00408 }
00409 else
00410 {
00411 AddChgt (lastPointNo, lastChgtPt, shapeHead,
00412 edgeHead, EDGE_REMOVED, node->src, node->bord,
00413 NULL, -1);
00414 ptSh->swsData[cb].misc = NULL;
00415
00416 int onLeftB = -1, onRightB = -1;
00417 Shape *onLeftS = NULL;
00418 Shape *onRightS = NULL;
00419 if (node->elem[LEFT])
00420 {
00421 onLeftB =
00422 (static_cast <
00423 SweepTree * >(node->elem[LEFT]))->bord;
00424 onLeftS =
00425 (static_cast <
00426 SweepTree * >(node->elem[LEFT]))->src;
00427 }
00428 if (node->elem[RIGHT])
00429 {
00430 onRightB =
00431 (static_cast <
00432 SweepTree * >(node->elem[RIGHT]))->bord;
00433 onRightS =
00434 (static_cast <
00435 SweepTree * >(node->elem[RIGHT]))->src;
00436 }
00437
00438 node->Remove (*sTree, *sEvts, true);
00439 if (onLeftS && onRightS)
00440 {
00441 SweepTree *onLeft =
00442 (SweepTree *) onLeftS->swsData[onLeftB].
00443 misc;
00444 if (onLeftS == ptSh
00445 && (onLeftS->getEdge(onLeftB).en == nPt
00446 || onLeftS->getEdge(onLeftB).st ==
00447 nPt))
00448 {
00449 }
00450 else
00451 {
00452 if (onRightS == ptSh
00453 && (onRightS->getEdge(onRightB).en ==
00454 nPt
00455 || onRightS->getEdge(onRightB).
00456 st == nPt))
00457 {
00458 }
00459 else
00460 {
00461 TesteIntersection (onLeft, RIGHT, false);
00462 }
00463 }
00464 }
00465 }
00466 }
00467 }
00468 cb = ptSh->NextAt (nPt, cb);
00469 }
00470 }
00471
00472
00473 SweepTree *insertionNode = NULL;
00474 if (dnNo >= 0)
00475 {
00476 if (upNo >= 0)
00477 {
00478 SweepTree *node = (SweepTree *) ptSh->swsData[upNo].misc;
00479
00480 AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_REMOVED,
00481 node->src, node->bord, NULL, -1);
00482
00483 ptSh->swsData[upNo].misc = NULL;
00484
00485 node->RemoveEvents (*sEvts);
00486 node->ConvertTo (ptSh, dnNo, 1, lastPointNo);
00487 ptSh->swsData[dnNo].misc = node;
00488 TesteIntersection (node, RIGHT, false);
00489 TesteIntersection (node, LEFT, false);
00490 insertionNode = node;
00491
00492 ptSh->swsData[dnNo].curPoint = lastPointNo;
00493 AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_INSERTED,
00494 node->src, node->bord, NULL, -1);
00495 }
00496 else
00497 {
00498 SweepTree *node = sTree->add(ptSh, dnNo, 1, lastPointNo, this);
00499 ptSh->swsData[dnNo].misc = node;
00500 node->Insert (*sTree, *sEvts, this, lastPointNo, true);
00501 if (doWinding)
00502 {
00503 SweepTree *myLeft =
00504 static_cast < SweepTree * >(node->elem[LEFT]);
00505 if (myLeft)
00506 {
00507 pData[lastPointNo].askForWindingS = myLeft->src;
00508 pData[lastPointNo].askForWindingB = myLeft->bord;
00509 }
00510 else
00511 {
00512 pData[lastPointNo].askForWindingB = -1;
00513 }
00514 doWinding = false;
00515 }
00516 TesteIntersection (node, RIGHT, false);
00517 TesteIntersection (node, LEFT, false);
00518 insertionNode = node;
00519
00520 ptSh->swsData[dnNo].curPoint = lastPointNo;
00521 AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_INSERTED,
00522 node->src, node->bord, NULL, -1);
00523 }
00524 }
00525
00526 if (nbDn > 1)
00527 {
00528 cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
00529 while (cb >= 0 && cb < ptSh->numberOfEdges())
00530 {
00531 if ((ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
00532 && nPt == ptSh->getEdge(cb).en)
00533 || (ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
00534 && nPt == ptSh->getEdge(cb).st))
00535 {
00536 if (cb != dnNo)
00537 {
00538 SweepTree *node = sTree->add(ptSh, cb, 1, lastPointNo, this);
00539 ptSh->swsData[cb].misc = node;
00540 node->InsertAt (*sTree, *sEvts, this, insertionNode,
00541 nPt, true);
00542 if (doWinding)
00543 {
00544 SweepTree *myLeft =
00545 static_cast < SweepTree * >(node->elem[LEFT]);
00546 if (myLeft)
00547 {
00548 pData[lastPointNo].askForWindingS =
00549 myLeft->src;
00550 pData[lastPointNo].askForWindingB =
00551 myLeft->bord;
00552 }
00553 else
00554 {
00555 pData[lastPointNo].askForWindingB = -1;
00556 }
00557 doWinding = false;
00558 }
00559 TesteIntersection (node, RIGHT, false);
00560 TesteIntersection (node, LEFT, false);
00561
00562 ptSh->swsData[cb].curPoint = lastPointNo;
00563 AddChgt (lastPointNo, lastChgtPt, shapeHead,
00564 edgeHead, EDGE_INSERTED, node->src, node->bord, NULL,
00565 -1);
00566 }
00567 }
00568 cb = ptSh->NextAt (nPt, cb);
00569 }
00570 }
00571 }
00572 }
00573 {
00574 int lastI = AssemblePoints (lastChgtPt, numberOfPoints());
00575
00576
00577 Shape *curSh = shapeHead;
00578 int curBo = edgeHead;
00579 while (curSh)
00580 {
00581 curSh->swsData[curBo].leftRnd =
00582 pData[curSh->swsData[curBo].leftRnd].newInd;
00583 curSh->swsData[curBo].rightRnd =
00584 pData[curSh->swsData[curBo].rightRnd].newInd;
00585
00586 Shape *neSh = curSh->swsData[curBo].nextSh;
00587 curBo = curSh->swsData[curBo].nextBo;
00588 curSh = neSh;
00589 }
00590
00591 for (unsigned int i = 0; i < chgts.size(); i++)
00592 {
00593 chgts[i].ptNo = pData[chgts[i].ptNo].newInd;
00594 if (chgts[i].type == 0)
00595 {
00596 if (chgts[i].src->getEdge(chgts[i].bord).st <
00597 chgts[i].src->getEdge(chgts[i].bord).en)
00598 {
00599 chgts[i].src->swsData[chgts[i].bord].stPt = chgts[i].ptNo;
00600 }
00601 else
00602 {
00603 chgts[i].src->swsData[chgts[i].bord].enPt = chgts[i].ptNo;
00604 }
00605 }
00606 else if (chgts[i].type == 1)
00607 {
00608 if (chgts[i].src->getEdge(chgts[i].bord).st >
00609 chgts[i].src->getEdge(chgts[i].bord).en)
00610 {
00611 chgts[i].src->swsData[chgts[i].bord].stPt = chgts[i].ptNo;
00612 }
00613 else
00614 {
00615 chgts[i].src->swsData[chgts[i].bord].enPt = chgts[i].ptNo;
00616 }
00617 }
00618 }
00619
00620 CheckAdjacencies (lastI, lastChgtPt, shapeHead, edgeHead);
00621
00622 CheckEdges (lastI, lastChgtPt, a, NULL, bool_op_union);
00623
00624 for (int i = lastChgtPt; i < lastI; i++)
00625 {
00626 if (pData[i].askForWindingS)
00627 {
00628 Shape *windS = pData[i].askForWindingS;
00629 int windB = pData[i].askForWindingB;
00630 pData[i].nextLinkedPoint = windS->swsData[windB].firstLinkedPoint;
00631 windS->swsData[windB].firstLinkedPoint = i;
00632 }
00633 }
00634
00635 _pts.resize(lastI);
00636
00637 edgeHead = -1;
00638 shapeHead = NULL;
00639 }
00640
00641 chgts.clear();
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 clearIncidenceData();
00652
00653 AssembleAretes (directed);
00654
00655
00656
00657 for (int i = 0; i < numberOfPoints(); i++)
00658 {
00659 _pts[i].oldDegree = getPoint(i).totalDegree();
00660 }
00661
00662
00663 _need_edges_sorting = true;
00664 if ( directed == fill_justDont ) {
00665 SortEdges();
00666 } else {
00667 GetWindings (a);
00668 }
00669
00670
00671
00672
00673
00674
00675 if (directed == fill_positive)
00676 {
00677 if (invert)
00678 {
00679 for (int i = 0; i < numberOfEdges(); i++)
00680 {
00681 if (swdData[i].leW < 0 && swdData[i].riW >= 0)
00682 {
00683 eData[i].weight = 1;
00684 }
00685 else if (swdData[i].leW >= 0 && swdData[i].riW < 0)
00686 {
00687 Inverse (i);
00688 eData[i].weight = 1;
00689 }
00690 else
00691 {
00692 eData[i].weight = 0;
00693 SubEdge (i);
00694 i--;
00695 }
00696 }
00697 }
00698 else
00699 {
00700 for (int i = 0; i < numberOfEdges(); i++)
00701 {
00702 if (swdData[i].leW > 0 && swdData[i].riW <= 0)
00703 {
00704 eData[i].weight = 1;
00705 }
00706 else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
00707 {
00708 Inverse (i);
00709 eData[i].weight = 1;
00710 }
00711 else
00712 {
00713 eData[i].weight = 0;
00714 SubEdge (i);
00715 i--;
00716 }
00717 }
00718 }
00719 }
00720 else if (directed == fill_nonZero)
00721 {
00722 if (invert)
00723 {
00724 for (int i = 0; i < numberOfEdges(); i++)
00725 {
00726 if (swdData[i].leW < 0 && swdData[i].riW == 0)
00727 {
00728 eData[i].weight = 1;
00729 }
00730 else if (swdData[i].leW > 0 && swdData[i].riW == 0)
00731 {
00732 eData[i].weight = 1;
00733 }
00734 else if (swdData[i].leW == 0 && swdData[i].riW < 0)
00735 {
00736 Inverse (i);
00737 eData[i].weight = 1;
00738 }
00739 else if (swdData[i].leW == 0 && swdData[i].riW > 0)
00740 {
00741 Inverse (i);
00742 eData[i].weight = 1;
00743 }
00744 else
00745 {
00746 eData[i].weight = 0;
00747 SubEdge (i);
00748 i--;
00749 }
00750 }
00751 }
00752 else
00753 {
00754 for (int i = 0; i < numberOfEdges(); i++)
00755 {
00756 if (swdData[i].leW > 0 && swdData[i].riW == 0)
00757 {
00758 eData[i].weight = 1;
00759 }
00760 else if (swdData[i].leW < 0 && swdData[i].riW == 0)
00761 {
00762 eData[i].weight = 1;
00763 }
00764 else if (swdData[i].leW == 0 && swdData[i].riW > 0)
00765 {
00766 Inverse (i);
00767 eData[i].weight = 1;
00768 }
00769 else if (swdData[i].leW == 0 && swdData[i].riW < 0)
00770 {
00771 Inverse (i);
00772 eData[i].weight = 1;
00773 }
00774 else
00775 {
00776 eData[i].weight = 0;
00777 SubEdge (i);
00778 i--;
00779 }
00780 }
00781 }
00782 }
00783 else if (directed == fill_oddEven)
00784 {
00785 for (int i = 0; i < numberOfEdges(); i++)
00786 {
00787 swdData[i].leW %= 2;
00788 swdData[i].riW %= 2;
00789 if (swdData[i].leW < 0)
00790 swdData[i].leW = -swdData[i].leW;
00791 if (swdData[i].riW < 0)
00792 swdData[i].riW = -swdData[i].riW;
00793 if (swdData[i].leW > 0 && swdData[i].riW <= 0)
00794 {
00795 eData[i].weight = 1;
00796 }
00797 else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
00798 {
00799 Inverse (i);
00800 eData[i].weight = 1;
00801 }
00802 else
00803 {
00804 eData[i].weight = 0;
00805 SubEdge (i);
00806 i--;
00807 }
00808 }
00809 } else if ( directed == fill_justDont ) {
00810 for (int i=0;i<numberOfEdges();i++) {
00811 if ( getEdge(i).st < 0 || getEdge(i).en < 0 ) {
00812 SubEdge(i);
00813 i--;
00814 } else {
00815 eData[i].weight = 0;
00816 }
00817 }
00818 }
00819
00820
00821
00822 delete sTree;
00823 sTree = NULL;
00824 delete sEvts;
00825 sEvts = NULL;
00826
00827 MakePointData (false);
00828 MakeEdgeData (false);
00829 MakeSweepSrcData (false);
00830 MakeSweepDestData (false);
00831 a->CleanupSweep ();
00832 type = shape_polygon;
00833 return 0;
00834 }
00835
00836
00837
00838
00839 int
00840 Shape::Booleen (Shape * a, Shape * b, BooleanOp mod,int cutPathID)
00841 {
00842 if (a == b || a == NULL || b == NULL)
00843 return shape_input_err;
00844 Reset (0, 0);
00845 if (a->numberOfPoints() <= 1 || a->numberOfEdges() <= 1)
00846 return 0;
00847 if (b->numberOfPoints() <= 1 || b->numberOfEdges() <= 1)
00848 return 0;
00849 if ( mod == bool_op_cut ) {
00850 } else if ( mod == bool_op_slice ) {
00851 } else {
00852 if (a->type != shape_polygon)
00853 return shape_input_err;
00854 if (b->type != shape_polygon)
00855 return shape_input_err;
00856 }
00857
00858 a->ResetSweep ();
00859 b->ResetSweep ();
00860
00861 if (sTree == NULL) {
00862 sTree = new SweepTreeList(a->numberOfEdges() + b->numberOfEdges());
00863 }
00864 if (sEvts == NULL) {
00865 sEvts = new SweepEventQueue(a->numberOfEdges() + b->numberOfEdges());
00866 }
00867
00868 MakePointData (true);
00869 MakeEdgeData (true);
00870 MakeSweepSrcData (true);
00871 MakeSweepDestData (true);
00872 if (a->hasBackData () && b->hasBackData ())
00873 {
00874 MakeBackData (true);
00875 }
00876 else
00877 {
00878 MakeBackData (false);
00879 }
00880
00881 a->initialisePointData();
00882 b->initialisePointData();
00883
00884 a->initialiseEdgeData();
00885 b->initialiseEdgeData();
00886
00887 a->SortPointsRounded ();
00888 b->SortPointsRounded ();
00889
00890 chgts.clear();
00891
00892 double lastChange =
00893 (a->pData[0].rx[1] <
00894 b->pData[0].rx[1]) ? a->pData[0].rx[1] - 1.0 : b->pData[0].rx[1] - 1.0;
00895 int lastChgtPt = 0;
00896 int edgeHead = -1;
00897 Shape *shapeHead = NULL;
00898
00899 clearIncidenceData();
00900
00901 int curAPt = 0;
00902 int curBPt = 0;
00903
00904 while (curAPt < a->numberOfPoints() || curBPt < b->numberOfPoints() || sEvts->size() > 0)
00905 {
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919 Geom::Point ptX;
00920 double ptL, ptR;
00921 SweepTree *intersL = NULL;
00922 SweepTree *intersR = NULL;
00923 int nPt = -1;
00924 Shape *ptSh = NULL;
00925 bool isIntersection = false;
00926
00927 if (sEvts->peek(intersL, intersR, ptX, ptL, ptR))
00928 {
00929 if (curAPt < a->numberOfPoints())
00930 {
00931 if (curBPt < b->numberOfPoints())
00932 {
00933 if (a->pData[curAPt].rx[1] < b->pData[curBPt].rx[1]
00934 || (a->pData[curAPt].rx[1] == b->pData[curBPt].rx[1]
00935 && a->pData[curAPt].rx[0] < b->pData[curBPt].rx[0]))
00936 {
00937 if (a->pData[curAPt].pending > 0
00938 || (a->pData[curAPt].rx[1] > ptX[1]
00939 || (a->pData[curAPt].rx[1] == ptX[1]
00940 && a->pData[curAPt].rx[0] > ptX[0])))
00941 {
00942
00943 sEvts->extract(intersL, intersR, ptX, ptL, ptR);
00944 isIntersection = true;
00945 }
00946 else
00947 {
00948 nPt = curAPt++;
00949 ptSh = a;
00950 ptX = ptSh->pData[nPt].rx;
00951 isIntersection = false;
00952 }
00953 }
00954 else
00955 {
00956 if (b->pData[curBPt].pending > 0
00957 || (b->pData[curBPt].rx[1] > ptX[1]
00958 || (b->pData[curBPt].rx[1] == ptX[1]
00959 && b->pData[curBPt].rx[0] > ptX[0])))
00960 {
00961
00962 sEvts->extract(intersL, intersR, ptX, ptL, ptR);
00963 isIntersection = true;
00964 }
00965 else
00966 {
00967 nPt = curBPt++;
00968 ptSh = b;
00969 ptX = ptSh->pData[nPt].rx;
00970 isIntersection = false;
00971 }
00972 }
00973 }
00974 else
00975 {
00976 if (a->pData[curAPt].pending > 0
00977 || (a->pData[curAPt].rx[1] > ptX[1]
00978 || (a->pData[curAPt].rx[1] == ptX[1]
00979 && a->pData[curAPt].rx[0] > ptX[0])))
00980 {
00981
00982 sEvts->extract(intersL, intersR, ptX, ptL, ptR);
00983 isIntersection = true;
00984 }
00985 else
00986 {
00987 nPt = curAPt++;
00988 ptSh = a;
00989 ptX = ptSh->pData[nPt].rx;
00990 isIntersection = false;
00991 }
00992 }
00993 }
00994 else
00995 {
00996 if (b->pData[curBPt].pending > 0
00997 || (b->pData[curBPt].rx[1] > ptX[1]
00998 || (b->pData[curBPt].rx[1] == ptX[1]
00999 && b->pData[curBPt].rx[0] > ptX[0])))
01000 {
01001
01002 sEvts->extract(intersL, intersR, ptX, ptL, ptR);
01003 isIntersection = true;
01004 }
01005 else
01006 {
01007 nPt = curBPt++;
01008 ptSh = b;
01009 ptX = ptSh->pData[nPt].rx;
01010 isIntersection = false;
01011 }
01012 }
01013 }
01014 else
01015 {
01016 if (curAPt < a->numberOfPoints())
01017 {
01018 if (curBPt < b->numberOfPoints())
01019 {
01020 if (a->pData[curAPt].rx[1] < b->pData[curBPt].rx[1]
01021 || (a->pData[curAPt].rx[1] == b->pData[curBPt].rx[1]
01022 && a->pData[curAPt].rx[0] < b->pData[curBPt].rx[0]))
01023 {
01024 nPt = curAPt++;
01025 ptSh = a;
01026 }
01027 else
01028 {
01029 nPt = curBPt++;
01030 ptSh = b;
01031 }
01032 }
01033 else
01034 {
01035 nPt = curAPt++;
01036 ptSh = a;
01037 }
01038 }
01039 else
01040 {
01041 nPt = curBPt++;
01042 ptSh = b;
01043 }
01044 ptX = ptSh->pData[nPt].rx;
01045 isIntersection = false;
01046 }
01047
01048 if (isIntersection == false)
01049 {
01050 if (ptSh->getPoint(nPt).dI == 0 && ptSh->getPoint(nPt).dO == 0)
01051 continue;
01052 }
01053
01054 Geom::Point rPtX;
01055 rPtX[0]= Round (ptX[0]);
01056 rPtX[1]= Round (ptX[1]);
01057 int lastPointNo = -1;
01058 lastPointNo = AddPoint (rPtX);
01059 pData[lastPointNo].rx = rPtX;
01060
01061 if (rPtX[1] > lastChange)
01062 {
01063 int lastI = AssemblePoints (lastChgtPt, lastPointNo);
01064
01065
01066 Shape *curSh = shapeHead;
01067 int curBo = edgeHead;
01068 while (curSh)
01069 {
01070 curSh->swsData[curBo].leftRnd =
01071 pData[curSh->swsData[curBo].leftRnd].newInd;
01072 curSh->swsData[curBo].rightRnd =
01073 pData[curSh->swsData[curBo].rightRnd].newInd;
01074
01075 Shape *neSh = curSh->swsData[curBo].nextSh;
01076 curBo = curSh->swsData[curBo].nextBo;
01077 curSh = neSh;
01078 }
01079
01080 for (unsigned int i = 0; i < chgts.size(); i++)
01081 {
01082 chgts[i].ptNo = pData[chgts[i].ptNo].newInd;
01083 if (chgts[i].type == 0)
01084 {
01085 if (chgts[i].src->getEdge(chgts[i].bord).st <
01086 chgts[i].src->getEdge(chgts[i].bord).en)
01087 {
01088 chgts[i].src->swsData[chgts[i].bord].stPt =
01089 chgts[i].ptNo;
01090 }
01091 else
01092 {
01093 chgts[i].src->swsData[chgts[i].bord].enPt =
01094 chgts[i].ptNo;
01095 }
01096 }
01097 else if (chgts[i].type == 1)
01098 {
01099 if (chgts[i].src->getEdge(chgts[i].bord).st >
01100 chgts[i].src->getEdge(chgts[i].bord).en)
01101 {
01102 chgts[i].src->swsData[chgts[i].bord].stPt =
01103 chgts[i].ptNo;
01104 }
01105 else
01106 {
01107 chgts[i].src->swsData[chgts[i].bord].enPt =
01108 chgts[i].ptNo;
01109 }
01110 }
01111 }
01112
01113 CheckAdjacencies (lastI, lastChgtPt, shapeHead, edgeHead);
01114
01115 CheckEdges (lastI, lastChgtPt, a, b, mod);
01116
01117 for (int i = lastChgtPt; i < lastI; i++)
01118 {
01119 if (pData[i].askForWindingS)
01120 {
01121 Shape *windS = pData[i].askForWindingS;
01122 int windB = pData[i].askForWindingB;
01123 pData[i].nextLinkedPoint =
01124 windS->swsData[windB].firstLinkedPoint;
01125 windS->swsData[windB].firstLinkedPoint = i;
01126 }
01127 }
01128
01129 if (lastI < lastPointNo)
01130 {
01131 _pts[lastI] = getPoint(lastPointNo);
01132 pData[lastI] = pData[lastPointNo];
01133 }
01134 lastPointNo = lastI;
01135 _pts.resize(lastI + 1);
01136
01137 lastChgtPt = lastPointNo;
01138 lastChange = rPtX[1];
01139 chgts.clear();
01140 edgeHead = -1;
01141 shapeHead = NULL;
01142 }
01143
01144
01145 if (isIntersection)
01146 {
01147
01148
01149 intersL->RemoveEvent (*sEvts, LEFT);
01150 intersR->RemoveEvent (*sEvts, RIGHT);
01151
01152 AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, INTERSECTION,
01153 intersL->src, intersL->bord, intersR->src, intersR->bord);
01154
01155 intersL->SwapWithRight (*sTree, *sEvts);
01156
01157 TesteIntersection (intersL, LEFT, true);
01158 TesteIntersection (intersR, RIGHT, true);
01159 }
01160 else
01161 {
01162 int cb;
01163
01164 int nbUp = 0, nbDn = 0;
01165 int upNo = -1, dnNo = -1;
01166 cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
01167 while (cb >= 0 && cb < ptSh->numberOfEdges())
01168 {
01169 if ((ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
01170 && nPt == ptSh->getEdge(cb).en)
01171 || (ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
01172 && nPt == ptSh->getEdge(cb).st))
01173 {
01174 upNo = cb;
01175 nbUp++;
01176 }
01177 if ((ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
01178 && nPt == ptSh->getEdge(cb).en)
01179 || (ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
01180 && nPt == ptSh->getEdge(cb).st))
01181 {
01182 dnNo = cb;
01183 nbDn++;
01184 }
01185 cb = ptSh->NextAt (nPt, cb);
01186 }
01187
01188 if (nbDn <= 0)
01189 {
01190 upNo = -1;
01191 }
01192 if (upNo >= 0 && (SweepTree *) ptSh->swsData[upNo].misc == NULL)
01193 {
01194 upNo = -1;
01195 }
01196
01197
01198
01199 bool doWinding = true;
01200
01201 if (nbUp > 0)
01202 {
01203 cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
01204 while (cb >= 0 && cb < ptSh->numberOfEdges())
01205 {
01206 if ((ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
01207 && nPt == ptSh->getEdge(cb).en)
01208 || (ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
01209 && nPt == ptSh->getEdge(cb).st))
01210 {
01211 if (cb != upNo)
01212 {
01213 SweepTree *node =
01214 (SweepTree *) ptSh->swsData[cb].misc;
01215 if (node == NULL)
01216 {
01217 }
01218 else
01219 {
01220 AddChgt (lastPointNo, lastChgtPt, shapeHead,
01221 edgeHead, EDGE_REMOVED, node->src, node->bord,
01222 NULL, -1);
01223 ptSh->swsData[cb].misc = NULL;
01224
01225 int onLeftB = -1, onRightB = -1;
01226 Shape *onLeftS = NULL;
01227 Shape *onRightS = NULL;
01228 if (node->elem[LEFT])
01229 {
01230 onLeftB =
01231 (static_cast <
01232 SweepTree * >(node->elem[LEFT]))->bord;
01233 onLeftS =
01234 (static_cast <
01235 SweepTree * >(node->elem[LEFT]))->src;
01236 }
01237 if (node->elem[RIGHT])
01238 {
01239 onRightB =
01240 (static_cast <
01241 SweepTree * >(node->elem[RIGHT]))->bord;
01242 onRightS =
01243 (static_cast <
01244 SweepTree * >(node->elem[RIGHT]))->src;
01245 }
01246
01247 node->Remove (*sTree, *sEvts, true);
01248 if (onLeftS && onRightS)
01249 {
01250 SweepTree *onLeft =
01251 (SweepTree *) onLeftS->swsData[onLeftB].
01252 misc;
01253
01254 if (onLeftS == ptSh
01255 && (onLeftS->getEdge(onLeftB).en == nPt
01256 || onLeftS->getEdge(onLeftB).st ==
01257 nPt))
01258 {
01259 }
01260 else
01261 {
01262 if (onRightS == ptSh
01263 && (onRightS->getEdge(onRightB).en ==
01264 nPt
01265 || onRightS->getEdge(onRightB).
01266 st == nPt))
01267 {
01268 }
01269 else
01270 {
01271 TesteIntersection (onLeft, RIGHT, true);
01272 }
01273 }
01274 }
01275 }
01276 }
01277 }
01278 cb = ptSh->NextAt (nPt, cb);
01279 }
01280 }
01281
01282
01283 SweepTree *insertionNode = NULL;
01284 if (dnNo >= 0)
01285 {
01286 if (upNo >= 0)
01287 {
01288 SweepTree *node = (SweepTree *) ptSh->swsData[upNo].misc;
01289
01290 AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_REMOVED,
01291 node->src, node->bord, NULL, -1);
01292
01293 ptSh->swsData[upNo].misc = NULL;
01294
01295 node->RemoveEvents (*sEvts);
01296 node->ConvertTo (ptSh, dnNo, 1, lastPointNo);
01297 ptSh->swsData[dnNo].misc = node;
01298 TesteIntersection (node, RIGHT, true);
01299 TesteIntersection (node, LEFT, true);
01300 insertionNode = node;
01301
01302 ptSh->swsData[dnNo].curPoint = lastPointNo;
01303
01304 AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_INSERTED,
01305 node->src, node->bord, NULL, -1);
01306 }
01307 else
01308 {
01309 SweepTree *node = sTree->add(ptSh, dnNo, 1, lastPointNo, this);
01310 ptSh->swsData[dnNo].misc = node;
01311 node->Insert (*sTree, *sEvts, this, lastPointNo, true);
01312
01313 if (doWinding)
01314 {
01315 SweepTree *myLeft =
01316 static_cast < SweepTree * >(node->elem[LEFT]);
01317 if (myLeft)
01318 {
01319 pData[lastPointNo].askForWindingS = myLeft->src;
01320 pData[lastPointNo].askForWindingB = myLeft->bord;
01321 }
01322 else
01323 {
01324 pData[lastPointNo].askForWindingB = -1;
01325 }
01326 doWinding = false;
01327 }
01328
01329 TesteIntersection (node, RIGHT, true);
01330 TesteIntersection (node, LEFT, true);
01331 insertionNode = node;
01332
01333 ptSh->swsData[dnNo].curPoint = lastPointNo;
01334
01335 AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_INSERTED,
01336 node->src, node->bord, NULL, -1);
01337 }
01338 }
01339
01340 if (nbDn > 1)
01341 {
01342 cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
01343 while (cb >= 0 && cb < ptSh->numberOfEdges())
01344 {
01345 if ((ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
01346 && nPt == ptSh->getEdge(cb).en)
01347 || (ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
01348 && nPt == ptSh->getEdge(cb).st))
01349 {
01350 if (cb != dnNo)
01351 {
01352 SweepTree *node = sTree->add(ptSh, cb, 1, lastPointNo, this);
01353 ptSh->swsData[cb].misc = node;
01354
01355 node->InsertAt (*sTree, *sEvts, this, insertionNode,
01356 nPt, true);
01357
01358 if (doWinding)
01359 {
01360 SweepTree *myLeft =
01361 static_cast < SweepTree * >(node->elem[LEFT]);
01362 if (myLeft)
01363 {
01364 pData[lastPointNo].askForWindingS =
01365 myLeft->src;
01366 pData[lastPointNo].askForWindingB =
01367 myLeft->bord;
01368 }
01369 else
01370 {
01371 pData[lastPointNo].askForWindingB = -1;
01372 }
01373 doWinding = false;
01374 }
01375
01376 TesteIntersection (node, RIGHT, true);
01377 TesteIntersection (node, LEFT, true);
01378
01379 ptSh->swsData[cb].curPoint = lastPointNo;
01380
01381 AddChgt (lastPointNo, lastChgtPt, shapeHead,
01382 edgeHead, EDGE_INSERTED, node->src, node->bord, NULL,
01383 -1);
01384 }
01385 }
01386 cb = ptSh->NextAt (nPt, cb);
01387 }
01388 }
01389 }
01390 }
01391 {
01392 int lastI = AssemblePoints (lastChgtPt, numberOfPoints());
01393
01394
01395 Shape *curSh = shapeHead;
01396 int curBo = edgeHead;
01397 while (curSh)
01398 {
01399 curSh->swsData[curBo].leftRnd =
01400 pData[curSh->swsData[curBo].leftRnd].newInd;
01401 curSh->swsData[curBo].rightRnd =
01402 pData[curSh->swsData[curBo].rightRnd].newInd;
01403
01404 Shape *neSh = curSh->swsData[curBo].nextSh;
01405 curBo = curSh->swsData[curBo].nextBo;
01406 curSh = neSh;
01407 }
01408
01409
01410 for (unsigned int i = 0; i < chgts.size(); i++)
01411 {
01412 chgts[i].ptNo = pData[chgts[i].ptNo].newInd;
01413 if (chgts[i].type == 0)
01414 {
01415 if (chgts[i].src->getEdge(chgts[i].bord).st <
01416 chgts[i].src->getEdge(chgts[i].bord).en)
01417 {
01418 chgts[i].src->swsData[chgts[i].bord].stPt = chgts[i].ptNo;
01419 }
01420 else
01421 {
01422 chgts[i].src->swsData[chgts[i].bord].enPt = chgts[i].ptNo;
01423 }
01424 }
01425 else if (chgts[i].type == 1)
01426 {
01427 if (chgts[i].src->getEdge(chgts[i].bord).st >
01428 chgts[i].src->getEdge(chgts[i].bord).en)
01429 {
01430 chgts[i].src->swsData[chgts[i].bord].stPt = chgts[i].ptNo;
01431 }
01432 else
01433 {
01434 chgts[i].src->swsData[chgts[i].bord].enPt = chgts[i].ptNo;
01435 }
01436 }
01437 }
01438
01439 CheckAdjacencies (lastI, lastChgtPt, shapeHead, edgeHead);
01440
01441 CheckEdges (lastI, lastChgtPt, a, b, mod);
01442
01443 for (int i = lastChgtPt; i < lastI; i++)
01444 {
01445 if (pData[i].askForWindingS)
01446 {
01447 Shape *windS = pData[i].askForWindingS;
01448 int windB = pData[i].askForWindingB;
01449 pData[i].nextLinkedPoint = windS->swsData[windB].firstLinkedPoint;
01450 windS->swsData[windB].firstLinkedPoint = i;
01451 }
01452 }
01453
01454 _pts.resize(lastI);
01455
01456 edgeHead = -1;
01457 shapeHead = NULL;
01458 }
01459
01460 chgts.clear();
01461 clearIncidenceData();
01462
01463
01464
01465 if ( mod == bool_op_cut ) {
01466 AssembleAretes (fill_justDont);
01467
01468 int i=numberOfEdges()-1;
01469 for (;i>=0;i--) {
01470 if ( ebData[i].pathID == cutPathID ) {
01471
01472 int nEd=AddEdge(getEdge(i).en,getEdge(i).st);
01473 ebData[nEd].pathID=cutPathID;
01474 ebData[nEd].pieceID=ebData[i].pieceID;
01475 ebData[nEd].tSt=ebData[i].tEn;
01476 ebData[nEd].tEn=ebData[i].tSt;
01477 eData[nEd].weight=eData[i].weight;
01478
01479 if ( getEdge(i).en >= getEdge(i).st ) {
01480 int cp = swsData[i].firstLinkedPoint;
01481 while (cp >= 0) {
01482 pData[cp].askForWindingB = nEd;
01483 cp = pData[cp].nextLinkedPoint;
01484 }
01485 swsData[nEd].firstLinkedPoint = swsData[i].firstLinkedPoint;
01486 swsData[i].firstLinkedPoint=-1;
01487 }
01488 }
01489 }
01490 } else if ( mod == bool_op_slice ) {
01491 } else {
01492 AssembleAretes ();
01493 }
01494
01495 for (int i = 0; i < numberOfPoints(); i++)
01496 {
01497 _pts[i].oldDegree = getPoint(i).totalDegree();
01498 }
01499
01500 _need_edges_sorting = true;
01501 if ( mod == bool_op_slice ) {
01502 } else {
01503 GetWindings (a, b, mod, false);
01504 }
01505
01506
01507 if (mod == bool_op_symdiff)
01508 {
01509 for (int i = 0; i < numberOfEdges(); i++)
01510 {
01511 swdData[i].leW = swdData[i].leW % 2;
01512 if (swdData[i].leW < 0)
01513 swdData[i].leW = -swdData[i].leW;
01514 swdData[i].riW = swdData[i].riW;
01515 if (swdData[i].riW < 0)
01516 swdData[i].riW = -swdData[i].riW;
01517
01518 if (swdData[i].leW > 0 && swdData[i].riW <= 0)
01519 {
01520 eData[i].weight = 1;
01521 }
01522 else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
01523 {
01524 Inverse (i);
01525 eData[i].weight = 1;
01526 }
01527 else
01528 {
01529 eData[i].weight = 0;
01530 SubEdge (i);
01531 i--;
01532 }
01533 }
01534 }
01535 else if (mod == bool_op_union || mod == bool_op_diff)
01536 {
01537 for (int i = 0; i < numberOfEdges(); i++)
01538 {
01539 if (swdData[i].leW > 0 && swdData[i].riW <= 0)
01540 {
01541 eData[i].weight = 1;
01542 }
01543 else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
01544 {
01545 Inverse (i);
01546 eData[i].weight = 1;
01547 }
01548 else
01549 {
01550 eData[i].weight = 0;
01551 SubEdge (i);
01552 i--;
01553 }
01554 }
01555 }
01556 else if (mod == bool_op_inters)
01557 {
01558 for (int i = 0; i < numberOfEdges(); i++)
01559 {
01560 if (swdData[i].leW > 1 && swdData[i].riW <= 1)
01561 {
01562 eData[i].weight = 1;
01563 }
01564 else if (swdData[i].leW <= 1 && swdData[i].riW > 1)
01565 {
01566 Inverse (i);
01567 eData[i].weight = 1;
01568 }
01569 else
01570 {
01571 eData[i].weight = 0;
01572 SubEdge (i);
01573 i--;
01574 }
01575 }
01576 } else if ( mod == bool_op_cut ) {
01577
01578 for (int i=0;i<numberOfEdges();i++) {
01579 if ( getEdge(i).st < 0 || getEdge(i).en < 0 ) {
01580 if ( i < numberOfEdges()-1 ) {
01581
01582 int cp = swsData[numberOfEdges()-1].firstLinkedPoint;
01583 while (cp >= 0) {
01584 pData[cp].askForWindingB = i;
01585 cp = pData[cp].nextLinkedPoint;
01586 }
01587 }
01588 SwapEdges(i,numberOfEdges()-1);
01589 SubEdge(numberOfEdges()-1);
01590
01591 i--;
01592 } else if ( ebData[i].pathID == cutPathID ) {
01593 swdData[i].leW=swdData[i].leW%2;
01594 swdData[i].riW=swdData[i].riW%2;
01595 if ( swdData[i].leW < swdData[i].riW ) {
01596 Inverse(i);
01597 }
01598 }
01599 }
01600 } else if ( mod == bool_op_slice ) {
01601
01602 int i=numberOfEdges()-1;
01603 for (;i>=0;i--) {
01604 if ( ebData[i].pathID == cutPathID || getEdge(i).st < 0 || getEdge(i).en < 0 ) {
01605 SubEdge(i);
01606 }
01607 }
01608 }
01609 else
01610 {
01611 for (int i = 0; i < numberOfEdges(); i++)
01612 {
01613 if (swdData[i].leW > 0 && swdData[i].riW <= 0)
01614 {
01615 eData[i].weight = 1;
01616 }
01617 else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
01618 {
01619 Inverse (i);
01620 eData[i].weight = 1;
01621 }
01622 else
01623 {
01624 eData[i].weight = 0;
01625 SubEdge (i);
01626 i--;
01627 }
01628 }
01629 }
01630
01631 delete sTree;
01632 sTree = NULL;
01633 delete sEvts;
01634 sEvts = NULL;
01635
01636 if ( mod == bool_op_cut ) {
01637
01638 } else {
01639 MakePointData (false);
01640 }
01641 MakeEdgeData (false);
01642 MakeSweepSrcData (false);
01643 MakeSweepDestData (false);
01644 a->CleanupSweep ();
01645 b->CleanupSweep ();
01646
01647 if (directedEulerian(this) == false)
01648 {
01649
01650 _pts.clear();
01651 _aretes.clear();
01652 return shape_euler_err;
01653 }
01654 type = shape_polygon;
01655 return 0;
01656 }
01657
01658
01659 void Shape::TesteIntersection(SweepTree *t, Side s, bool onlyDiff)
01660 {
01661 SweepTree *tt = static_cast<SweepTree*>(t->elem[s]);
01662 if (tt == NULL) {
01663 return;
01664 }
01665
01666 SweepTree *a = (s == LEFT) ? tt : t;
01667 SweepTree *b = (s == LEFT) ? t : tt;
01668
01669 Geom::Point atx;
01670 double atl;
01671 double atr;
01672 if (TesteIntersection(a, b, atx, atl, atr, onlyDiff)) {
01673 sEvts->add(a, b, atx, atl, atr);
01674 }
01675 }
01676
01677
01678 bool
01679 Shape::TesteIntersection (SweepTree * iL, SweepTree * iR, Geom::Point &atx, double &atL, double &atR, bool onlyDiff)
01680 {
01681 int lSt = iL->src->getEdge(iL->bord).st, lEn = iL->src->getEdge(iL->bord).en;
01682 int rSt = iR->src->getEdge(iR->bord).st, rEn = iR->src->getEdge(iR->bord).en;
01683 Geom::Point ldir, rdir;
01684 ldir = iL->src->eData[iL->bord].rdx;
01685 rdir = iR->src->eData[iR->bord].rdx;
01686
01687
01688 if (lSt < lEn)
01689 {
01690 }
01691 else
01692 {
01693 int swap = lSt;
01694 lSt = lEn;
01695 lEn = swap;
01696 ldir = -ldir;
01697 }
01698 if (rSt < rEn)
01699 {
01700 }
01701 else
01702 {
01703 int swap = rSt;
01704 rSt = rEn;
01705 rEn = swap;
01706 rdir = -rdir;
01707 }
01708
01709 if (iL->src->pData[lSt].rx[0] < iL->src->pData[lEn].rx[0])
01710 {
01711 if (iR->src->pData[rSt].rx[0] < iR->src->pData[rEn].rx[0])
01712 {
01713 if (iL->src->pData[lSt].rx[0] > iR->src->pData[rEn].rx[0])
01714 return false;
01715 if (iL->src->pData[lEn].rx[0] < iR->src->pData[rSt].rx[0])
01716 return false;
01717 }
01718 else
01719 {
01720 if (iL->src->pData[lSt].rx[0] > iR->src->pData[rSt].rx[0])
01721 return false;
01722 if (iL->src->pData[lEn].rx[0] < iR->src->pData[rEn].rx[0])
01723 return false;
01724 }
01725 }
01726 else
01727 {
01728 if (iR->src->pData[rSt].rx[0] < iR->src->pData[rEn].rx[0])
01729 {
01730 if (iL->src->pData[lEn].rx[0] > iR->src->pData[rEn].rx[0])
01731 return false;
01732 if (iL->src->pData[lSt].rx[0] < iR->src->pData[rSt].rx[0])
01733 return false;
01734 }
01735 else
01736 {
01737 if (iL->src->pData[lEn].rx[0] > iR->src->pData[rSt].rx[0])
01738 return false;
01739 if (iL->src->pData[lSt].rx[0] < iR->src->pData[rEn].rx[0])
01740 return false;
01741 }
01742 }
01743
01744 double ang = cross (rdir, ldir);
01745
01746
01747 if (ang <= 0) return false;
01748
01749
01750
01751 if (iL->src == iR->src && lSt == rSt)
01752 {
01753 if (iL->src == iR->src && lEn == rEn)
01754 return false;
01755 atx = iL->src->pData[lSt].rx;
01756 atR = atL = -1;
01757 return true;
01758 }
01759 if (iL->src == iR->src && lEn == rEn)
01760 return false;
01761
01762
01763
01764 if (onlyDiff && iL->src == iR->src)
01765 return false;
01766
01767
01768 lSt = iL->src->getEdge(iL->bord).st;
01769 lEn = iL->src->getEdge(iL->bord).en;
01770 rSt = iR->src->getEdge(iR->bord).st;
01771 rEn = iR->src->getEdge(iR->bord).en;
01772
01773
01774
01775
01776 {
01777 Geom::Point sDiff, eDiff;
01778 double slDot, elDot;
01779 double srDot, erDot;
01780 sDiff = iL->src->pData[lSt].rx - iR->src->pData[rSt].rx;
01781 eDiff = iL->src->pData[lEn].rx - iR->src->pData[rSt].rx;
01782 srDot = cross (sDiff,rdir);
01783 erDot = cross (eDiff,rdir);
01784 sDiff = iR->src->pData[rSt].rx - iL->src->pData[lSt].rx;
01785 eDiff = iR->src->pData[rEn].rx - iL->src->pData[lSt].rx;
01786 slDot = cross (sDiff,ldir);
01787 elDot = cross (eDiff,ldir);
01788
01789 if ((srDot >= 0 && erDot >= 0) || (srDot <= 0 && erDot <= 0))
01790 {
01791 if (srDot == 0)
01792 {
01793 if (lSt < lEn)
01794 {
01795 atx = iL->src->pData[lSt].rx;
01796 atL = 0;
01797 atR = slDot / (slDot - elDot);
01798 return true;
01799 }
01800 else
01801 {
01802 return false;
01803 }
01804 }
01805 else if (erDot == 0)
01806 {
01807 if (lSt > lEn)
01808 {
01809 atx = iL->src->pData[lEn].rx;
01810 atL = 1;
01811 atR = slDot / (slDot - elDot);
01812 return true;
01813 }
01814 else
01815 {
01816 return false;
01817 }
01818 }
01819 if (srDot > 0 && erDot > 0)
01820 {
01821 if (rEn < rSt)
01822 {
01823 if (srDot < erDot)
01824 {
01825 if (lSt < lEn)
01826 {
01827 atx = iL->src->pData[lSt].rx;
01828 atL = 0;
01829 atR = slDot / (slDot - elDot);
01830 return true;
01831 }
01832 }
01833 else
01834 {
01835 if (lEn < lSt)
01836 {
01837 atx = iL->src->pData[lEn].rx;
01838 atL = 1;
01839 atR = slDot / (slDot - elDot);
01840 return true;
01841 }
01842 }
01843 }
01844 }
01845 if (srDot < 0 && erDot < 0)
01846 {
01847 if (rEn > rSt)
01848 {
01849 if (srDot > erDot)
01850 {
01851 if (lSt < lEn)
01852 {
01853 atx = iL->src->pData[lSt].rx;
01854 atL = 0;
01855 atR = slDot / (slDot - elDot);
01856 return true;
01857 }
01858 }
01859 else
01860 {
01861 if (lEn < lSt)
01862 {
01863 atx = iL->src->pData[lEn].rx;
01864 atL = 1;
01865 atR = slDot / (slDot - elDot);
01866 return true;
01867 }
01868 }
01869 }
01870 }
01871 return false;
01872 }
01873 if ((slDot >= 0 && elDot >= 0) || (slDot <= 0 && elDot <= 0))
01874 {
01875 if (slDot == 0)
01876 {
01877 if (rSt < rEn)
01878 {
01879 atx = iR->src->pData[rSt].rx;
01880 atR = 0;
01881 atL = srDot / (srDot - erDot);
01882 return true;
01883 }
01884 else
01885 {
01886 return false;
01887 }
01888 }
01889 else if (elDot == 0)
01890 {
01891 if (rSt > rEn)
01892 {
01893 atx = iR->src->pData[rEn].rx;
01894 atR = 1;
01895 atL = srDot / (srDot - erDot);
01896 return true;
01897 }
01898 else
01899 {
01900 return false;
01901 }
01902 }
01903 if (slDot > 0 && elDot > 0)
01904 {
01905 if (lEn > lSt)
01906 {
01907 if (slDot < elDot)
01908 {
01909 if (rSt < rEn)
01910 {
01911 atx = iR->src->pData[rSt].rx;
01912 atR = 0;
01913 atL = srDot / (srDot - erDot);
01914 return true;
01915 }
01916 }
01917 else
01918 {
01919 if (rEn < rSt)
01920 {
01921 atx = iR->src->pData[rEn].rx;
01922 atR = 1;
01923 atL = srDot / (srDot - erDot);
01924 return true;
01925 }
01926 }
01927 }
01928 }
01929 if (slDot < 0 && elDot < 0)
01930 {
01931 if (lEn < lSt)
01932 {
01933 if (slDot > elDot)
01934 {
01935 if (rSt < rEn)
01936 {
01937 atx = iR->src->pData[rSt].rx;
01938 atR = 0;
01939 atL = srDot / (srDot - erDot);
01940 return true;
01941 }
01942 }
01943 else
01944 {
01945 if (rEn < rSt)
01946 {
01947 atx = iR->src->pData[rEn].rx;
01948 atR = 1;
01949 atL = srDot / (srDot - erDot);
01950 return true;
01951 }
01952 }
01953 }
01954 }
01955 return false;
01956 }
01957
01958
01959
01960
01961 if (iL->src->eData[iL->bord].siEd > iR->src->eData[iR->bord].siEd)
01962 {
01963 atx =
01964 (slDot * iR->src->pData[rEn].rx -
01965 elDot * iR->src->pData[rSt].rx) / (slDot - elDot);
01966 }
01967 else
01968 {
01969 atx =
01970 (srDot * iL->src->pData[lEn].rx -
01971 erDot * iL->src->pData[lSt].rx) / (srDot - erDot);
01972 }
01973 atL = srDot / (srDot - erDot);
01974 atR = slDot / (slDot - elDot);
01975 return true;
01976 }
01977
01978 return true;
01979 }
01980
01981 int
01982 Shape::PushIncidence (Shape * a, int cb, int pt, double theta)
01983 {
01984 if (theta < 0 || theta > 1)
01985 return -1;
01986
01987 if (nbInc >= maxInc)
01988 {
01989 maxInc = 2 * nbInc + 1;
01990 iData =
01991 (incidenceData *) g_realloc(iData, maxInc * sizeof (incidenceData));
01992 }
01993 int n = nbInc++;
01994 iData[n].nextInc = a->swsData[cb].firstLinkedPoint;
01995 iData[n].pt = pt;
01996 iData[n].theta = theta;
01997 a->swsData[cb].firstLinkedPoint = n;
01998 return n;
01999 }
02000
02001 int
02002 Shape::CreateIncidence (Shape * a, int no, int nPt)
02003 {
02004 Geom::Point adir, diff;
02005 adir = a->eData[no].rdx;
02006 diff = getPoint(nPt).x - a->pData[a->getEdge(no).st].rx;
02007 double t = dot (diff, adir);
02008 t *= a->eData[no].ilength;
02009 return PushIncidence (a, no, nPt, t);
02010 }
02011
02012 int
02013 Shape::Winding (int nPt) const
02014 {
02015 int askTo = pData[nPt].askForWindingB;
02016 if (askTo < 0 || askTo >= numberOfEdges())
02017 return 0;
02018 if (getEdge(askTo).st < getEdge(askTo).en)
02019 {
02020 return swdData[askTo].leW;
02021 }
02022 else
02023 {
02024 return swdData[askTo].riW;
02025 }
02026 return 0;
02027 }
02028
02029 int
02030 Shape::Winding (const Geom::Point px) const
02031 {
02032 int lr = 0, ll = 0, rr = 0;
02033
02034 for (int i = 0; i < numberOfEdges(); i++)
02035 {
02036 Geom::Point adir, diff, ast, aen;
02037 adir = eData[i].rdx;
02038
02039 ast = pData[getEdge(i).st].rx;
02040 aen = pData[getEdge(i).en].rx;
02041
02042 int nWeight = eData[i].weight;
02043
02044 if (ast[0] < aen[0])
02045 {
02046 if (ast[0] > px[0])
02047 continue;
02048 if (aen[0] < px[0])
02049 continue;
02050 }
02051 else
02052 {
02053 if (ast[0] < px[0])
02054 continue;
02055 if (aen[0] > px[0])
02056 continue;
02057 }
02058 if (ast[0] == px[0])
02059 {
02060 if (ast[1] >= px[1])
02061 continue;
02062 if (aen[0] == px[0])
02063 continue;
02064 if (aen[0] < px[0])
02065 ll += nWeight;
02066 else
02067 rr -= nWeight;
02068 continue;
02069 }
02070 if (aen[0] == px[0])
02071 {
02072 if (aen[1] >= px[1])
02073 continue;
02074 if (ast[0] == px[0])
02075 continue;
02076 if (ast[0] < px[0])
02077 ll -= nWeight;
02078 else
02079 rr += nWeight;
02080 continue;
02081 }
02082
02083 if (ast[1] < aen[1])
02084 {
02085 if (ast[1] >= px[1])
02086 continue;
02087 }
02088 else
02089 {
02090 if (aen[1] >= px[1])
02091 continue;
02092 }
02093
02094 diff = px - ast;
02095 double cote = cross (diff,adir);
02096 if (cote == 0)
02097 continue;
02098 if (cote < 0)
02099 {
02100 if (ast[0] > px[0])
02101 lr += nWeight;
02102 }
02103 else
02104 {
02105 if (ast[0] < px[0])
02106 lr -= nWeight;
02107 }
02108 }
02109 return lr + (ll + rr) / 2;
02110 }
02111
02112
02113 int
02114 Shape::AssemblePoints (int st, int en)
02115 {
02116 if (en > st) {
02117 for (int i = st; i < en; i++) pData[i].oldInd = i;
02118
02119 SortPointsByOldInd (st, en - 1);
02120
02121
02122
02123 for (int i = st; i < en; i++) pData[pData[i].oldInd].newInd = i;
02124
02125 int lastI = st;
02126 for (int i = st; i < en; i++) {
02127 pData[i].pending = lastI++;
02128 if (i > st && getPoint(i - 1).x[0] == getPoint(i).x[0] && getPoint(i - 1).x[1] == getPoint(i).x[1]) {
02129 pData[i].pending = pData[i - 1].pending;
02130 if (pData[pData[i].pending].askForWindingS == NULL) {
02131 pData[pData[i].pending].askForWindingS = pData[i].askForWindingS;
02132 pData[pData[i].pending].askForWindingB = pData[i].askForWindingB;
02133 } else {
02134 if (pData[pData[i].pending].askForWindingS == pData[i].askForWindingS
02135 && pData[pData[i].pending].askForWindingB == pData[i].askForWindingB) {
02136
02137 } else {
02138
02139
02140
02141
02142
02143 }
02144 }
02145 lastI--;
02146 } else {
02147 if (i > pData[i].pending) {
02148 _pts[pData[i].pending].x = getPoint(i).x;
02149 pData[pData[i].pending].rx = getPoint(i).x;
02150 pData[pData[i].pending].askForWindingS = pData[i].askForWindingS;
02151 pData[pData[i].pending].askForWindingB = pData[i].askForWindingB;
02152 }
02153 }
02154 }
02155 for (int i = st; i < en; i++) pData[i].newInd = pData[pData[i].newInd].pending;
02156 return lastI;
02157 }
02158 return en;
02159 }
02160
02161 void
02162 Shape::AssemblePoints (Shape * a)
02163 {
02164 if (hasPoints())
02165 {
02166 int lastI = AssemblePoints (0, numberOfPoints());
02167
02168 for (int i = 0; i < a->numberOfEdges(); i++)
02169 {
02170 a->swsData[i].stPt = pData[a->swsData[i].stPt].newInd;
02171 a->swsData[i].enPt = pData[a->swsData[i].enPt].newInd;
02172 }
02173 for (int i = 0; i < nbInc; i++)
02174 iData[i].pt = pData[iData[i].pt].newInd;
02175
02176 _pts.resize(lastI);
02177 }
02178 }
02179 void
02180 Shape::AssembleAretes (FillRule directed)
02181 {
02182 if ( directed == fill_justDont && _has_back_data == false ) {
02183 directed=fill_nonZero;
02184 }
02185
02186 for (int i = 0; i < numberOfPoints(); i++) {
02187 if (getPoint(i).totalDegree() == 2) {
02188 int cb, cc;
02189 cb = getPoint(i).incidentEdge[FIRST];
02190 cc = getPoint(i).incidentEdge[LAST];
02191 bool doublon=false;
02192 if ((getEdge(cb).st == getEdge(cc).st && getEdge(cb).en == getEdge(cc).en)
02193 || (getEdge(cb).st == getEdge(cc).en && getEdge(cb).en == getEdge(cc).en)) doublon=true;
02194 if ( directed == fill_justDont ) {
02195 if ( doublon ) {
02196 if ( ebData[cb].pathID > ebData[cc].pathID ) {
02197 cc = getPoint(i).incidentEdge[FIRST];
02198 cb = getPoint(i).incidentEdge[LAST];
02199 } else if ( ebData[cb].pathID == ebData[cc].pathID ) {
02200 if ( ebData[cb].pieceID > ebData[cc].pieceID ) {
02201 cc = getPoint(i).incidentEdge[FIRST];
02202 cb = getPoint(i).incidentEdge[LAST];
02203 } else if ( ebData[cb].pieceID == ebData[cc].pieceID ) {
02204 if ( ebData[cb].tSt > ebData[cc].tSt ) {
02205 cc = getPoint(i).incidentEdge[FIRST];
02206 cb = getPoint(i).incidentEdge[LAST];
02207 }
02208 }
02209 }
02210 }
02211 if ( doublon ) eData[cc].weight = 0;
02212 } else {
02213 }
02214 if ( doublon ) {
02215 if (getEdge(cb).st == getEdge(cc).st) {
02216 eData[cb].weight += eData[cc].weight;
02217 } else {
02218 eData[cb].weight -= eData[cc].weight;
02219 }
02220 eData[cc].weight = 0;
02221
02222 if (swsData[cc].firstLinkedPoint >= 0) {
02223 int cp = swsData[cc].firstLinkedPoint;
02224 while (cp >= 0) {
02225 pData[cp].askForWindingB = cb;
02226 cp = pData[cp].nextLinkedPoint;
02227 }
02228 if (swsData[cb].firstLinkedPoint < 0) {
02229 swsData[cb].firstLinkedPoint = swsData[cc].firstLinkedPoint;
02230 } else {
02231 int ncp = swsData[cb].firstLinkedPoint;
02232 while (pData[ncp].nextLinkedPoint >= 0) {
02233 ncp = pData[ncp].nextLinkedPoint;
02234 }
02235 pData[ncp].nextLinkedPoint = swsData[cc].firstLinkedPoint;
02236 }
02237 }
02238
02239 DisconnectStart (cc);
02240 DisconnectEnd (cc);
02241 if (numberOfEdges() > 1) {
02242 int cp = swsData[numberOfEdges() - 1].firstLinkedPoint;
02243 while (cp >= 0) {
02244 pData[cp].askForWindingB = cc;
02245 cp = pData[cp].nextLinkedPoint;
02246 }
02247 }
02248 SwapEdges (cc, numberOfEdges() - 1);
02249 if (cb == numberOfEdges() - 1) {
02250 cb = cc;
02251 }
02252 _aretes.pop_back();
02253 }
02254 } else {
02255 int cb;
02256 cb = getPoint(i).incidentEdge[FIRST];
02257 while (cb >= 0 && cb < numberOfEdges()) {
02258 int other = Other (i, cb);
02259 int cc;
02260 cc = getPoint(i).incidentEdge[FIRST];
02261 while (cc >= 0 && cc < numberOfEdges()) {
02262 int ncc = NextAt (i, cc);
02263 bool doublon=false;
02264 if (cc != cb && Other (i, cc) == other ) doublon=true;
02265 if ( directed == fill_justDont ) {
02266 if ( doublon ) {
02267 if ( ebData[cb].pathID > ebData[cc].pathID ) {
02268 doublon=false;
02269 } else if ( ebData[cb].pathID == ebData[cc].pathID ) {
02270 if ( ebData[cb].pieceID > ebData[cc].pieceID ) {
02271 doublon=false;
02272 } else if ( ebData[cb].pieceID == ebData[cc].pieceID ) {
02273 if ( ebData[cb].tSt > ebData[cc].tSt ) {
02274 doublon=false;
02275 }
02276 }
02277 }
02278 }
02279 if ( doublon ) eData[cc].weight = 0;
02280 } else {
02281 }
02282 if ( doublon ) {
02283
02284
02285 if (getEdge(cb).st == getEdge(cc).st) {
02286 eData[cb].weight += eData[cc].weight;
02287 } else {
02288 eData[cb].weight -= eData[cc].weight;
02289 }
02290 eData[cc].weight = 0;
02291
02292 if (swsData[cc].firstLinkedPoint >= 0) {
02293 int cp = swsData[cc].firstLinkedPoint;
02294 while (cp >= 0) {
02295 pData[cp].askForWindingB = cb;
02296 cp = pData[cp].nextLinkedPoint;
02297 }
02298 if (swsData[cb].firstLinkedPoint < 0) {
02299 swsData[cb].firstLinkedPoint = swsData[cc].firstLinkedPoint;
02300 } else {
02301 int ncp = swsData[cb].firstLinkedPoint;
02302 while (pData[ncp].nextLinkedPoint >= 0) {
02303 ncp = pData[ncp].nextLinkedPoint;
02304 }
02305 pData[ncp].nextLinkedPoint = swsData[cc].firstLinkedPoint;
02306 }
02307 }
02308
02309 DisconnectStart (cc);
02310 DisconnectEnd (cc);
02311 if (numberOfEdges() > 1) {
02312 int cp = swsData[numberOfEdges() - 1].firstLinkedPoint;
02313 while (cp >= 0) {
02314 pData[cp].askForWindingB = cc;
02315 cp = pData[cp].nextLinkedPoint;
02316 }
02317 }
02318 SwapEdges (cc, numberOfEdges() - 1);
02319 if (cb == numberOfEdges() - 1) {
02320 cb = cc;
02321 }
02322 if (ncc == numberOfEdges() - 1) {
02323 ncc = cc;
02324 }
02325 _aretes.pop_back();
02326 }
02327 cc = ncc;
02328 }
02329 cb = NextAt (i, cb);
02330 }
02331 }
02332 }
02333
02334 if ( directed == fill_justDont ) {
02335 for (int i = 0; i < numberOfEdges(); i++) {
02336 if (eData[i].weight == 0) {
02337
02338
02339 } else {
02340 if (eData[i].weight < 0) Inverse (i);
02341 }
02342 }
02343 } else {
02344 for (int i = 0; i < numberOfEdges(); i++) {
02345 if (eData[i].weight == 0) {
02346
02347
02348 } else {
02349 if (eData[i].weight < 0) Inverse (i);
02350 }
02351 }
02352 }
02353 }
02354 void
02355 Shape::GetWindings (Shape * , Shape * , BooleanOp , bool brutal)
02356 {
02357
02358 for (int i = 0; i < numberOfEdges(); i++)
02359 {
02360 swdData[i].misc = 0;
02361 swdData[i].precParc = swdData[i].suivParc = -1;
02362 }
02363
02364
02365 SortEdges ();
02366
02367 int searchInd = 0;
02368
02369 int lastPtUsed = 0;
02370 do
02371 {
02372 int startBord = -1;
02373 int outsideW = 0;
02374 {
02375 int fi = 0;
02376 for (fi = lastPtUsed; fi < numberOfPoints(); fi++)
02377 {
02378 if (getPoint(fi).incidentEdge[FIRST] >= 0 && swdData[getPoint(fi).incidentEdge[FIRST]].misc == 0)
02379 break;
02380 }
02381 lastPtUsed = fi + 1;
02382 if (fi < numberOfPoints())
02383 {
02384 int bestB = getPoint(fi).incidentEdge[FIRST];
02385 if (bestB >= 0)
02386 {
02387 startBord = bestB;
02388 if (fi == 0)
02389 {
02390 outsideW = 0;
02391 }
02392 else
02393 {
02394 if (brutal)
02395 {
02396 outsideW = Winding (getPoint(fi).x);
02397 }
02398 else
02399 {
02400 outsideW = Winding (fi);
02401 }
02402 }
02403 if ( getPoint(fi).totalDegree() == 1 ) {
02404 if ( fi == getEdge(startBord).en ) {
02405 if ( eData[startBord].weight == 0 ) {
02406
02407 Inverse(startBord);
02408 } else {
02409
02410 pData[getEdge(startBord).st].askForWindingB=pData[getEdge(startBord).en].askForWindingB;
02411 }
02412 }
02413 }
02414 if (getEdge(startBord).en == fi)
02415 outsideW += eData[startBord].weight;
02416 }
02417 }
02418 }
02419 if (startBord >= 0)
02420 {
02421
02422 swdData[startBord].misc = (void *) 1;
02423 swdData[startBord].leW = outsideW;
02424 swdData[startBord].riW = outsideW - eData[startBord].weight;
02425
02426 int curBord = startBord;
02427 bool curDir = true;
02428 swdData[curBord].precParc = -1;
02429 swdData[curBord].suivParc = -1;
02430 do
02431 {
02432 int cPt;
02433 if (curDir)
02434 cPt = getEdge(curBord).en;
02435 else
02436 cPt = getEdge(curBord).st;
02437 int nb = curBord;
02438
02439 do
02440 {
02441 int nnb = -1;
02442 if (getEdge(nb).en == cPt)
02443 {
02444 outsideW = swdData[nb].riW;
02445 nnb = CyclePrevAt (cPt, nb);
02446 }
02447 else
02448 {
02449 outsideW = swdData[nb].leW;
02450 nnb = CyclePrevAt (cPt, nb);
02451 }
02452 if (nnb == nb)
02453 {
02454
02455 nb = -1;
02456 break;
02457 }
02458 nb = nnb;
02459 }
02460 while (nb >= 0 && nb != curBord && swdData[nb].misc != 0);
02461 if (nb < 0 || nb == curBord)
02462 {
02463
02464 int oPt;
02465 if (curDir)
02466 oPt = getEdge(curBord).st;
02467 else
02468 oPt = getEdge(curBord).en;
02469 curBord = swdData[curBord].precParc;
02470
02471 if (curBord < 0)
02472 break;
02473 if (oPt == getEdge(curBord).en)
02474 curDir = true;
02475 else
02476 curDir = false;
02477 }
02478 else
02479 {
02480 swdData[nb].misc = (void *) 1;
02481 swdData[nb].ind = searchInd++;
02482 if (cPt == getEdge(nb).st)
02483 {
02484 swdData[nb].riW = outsideW;
02485 swdData[nb].leW = outsideW + eData[nb].weight;
02486 }
02487 else
02488 {
02489 swdData[nb].leW = outsideW;
02490 swdData[nb].riW = outsideW - eData[nb].weight;
02491 }
02492 swdData[nb].precParc = curBord;
02493 swdData[curBord].suivParc = nb;
02494 curBord = nb;
02495
02496 if (cPt == getEdge(nb).en)
02497 curDir = false;
02498 else
02499 curDir = true;
02500 }
02501 }
02502 while (1 );
02503
02504 }
02505 }
02506 while (lastPtUsed < numberOfPoints());
02507
02508 }
02509
02510 bool
02511 Shape::TesteIntersection (Shape * ils, Shape * irs, int ilb, int irb,
02512 Geom::Point &atx, double &atL, double &atR,
02513 bool )
02514 {
02515 int lSt = ils->getEdge(ilb).st, lEn = ils->getEdge(ilb).en;
02516 int rSt = irs->getEdge(irb).st, rEn = irs->getEdge(irb).en;
02517 if (lSt == rSt || lSt == rEn)
02518 {
02519 return false;
02520 }
02521 if (lEn == rSt || lEn == rEn)
02522 {
02523 return false;
02524 }
02525
02526 Geom::Point ldir, rdir;
02527 ldir = ils->eData[ilb].rdx;
02528 rdir = irs->eData[irb].rdx;
02529
02530 double il = ils->pData[lSt].rx[0], it = ils->pData[lSt].rx[1], ir =
02531 ils->pData[lEn].rx[0], ib = ils->pData[lEn].rx[1];
02532 if (il > ir)
02533 {
02534 double swf = il;
02535 il = ir;
02536 ir = swf;
02537 }
02538 if (it > ib)
02539 {
02540 double swf = it;
02541 it = ib;
02542 ib = swf;
02543 }
02544 double jl = irs->pData[rSt].rx[0], jt = irs->pData[rSt].rx[1], jr =
02545 irs->pData[rEn].rx[0], jb = irs->pData[rEn].rx[1];
02546 if (jl > jr)
02547 {
02548 double swf = jl;
02549 jl = jr;
02550 jr = swf;
02551 }
02552 if (jt > jb)
02553 {
02554 double swf = jt;
02555 jt = jb;
02556 jb = swf;
02557 }
02558
02559 if (il > jr || it > jb || ir < jl || ib < jt)
02560 return false;
02561
02562
02563 {
02564 Geom::Point sDiff, eDiff;
02565 double slDot, elDot;
02566 double srDot, erDot;
02567 sDiff = ils->pData[lSt].rx - irs->pData[rSt].rx;
02568 eDiff = ils->pData[lEn].rx - irs->pData[rSt].rx;
02569 srDot = cross (sDiff,rdir );
02570 erDot = cross (eDiff,rdir );
02571 if ((srDot >= 0 && erDot >= 0) || (srDot <= 0 && erDot <= 0))
02572 return false;
02573
02574 sDiff = irs->pData[rSt].rx - ils->pData[lSt].rx;
02575 eDiff = irs->pData[rEn].rx - ils->pData[lSt].rx;
02576 slDot = cross (sDiff,ldir );
02577 elDot = cross (eDiff,ldir);
02578 if ((slDot >= 0 && elDot >= 0) || (slDot <= 0 && elDot <= 0))
02579 return false;
02580
02581 double slb = slDot - elDot, srb = srDot - erDot;
02582 if (slb < 0)
02583 slb = -slb;
02584 if (srb < 0)
02585 srb = -srb;
02586 if (slb > srb)
02587 {
02588 atx =
02589 (slDot * irs->pData[rEn].rx - elDot * irs->pData[rSt].rx) / (slDot -
02590 elDot);
02591 }
02592 else
02593 {
02594 atx =
02595 (srDot * ils->pData[lEn].rx - erDot * ils->pData[lSt].rx) / (srDot -
02596 erDot);
02597 }
02598 atL = srDot / (srDot - erDot);
02599 atR = slDot / (slDot - elDot);
02600 return true;
02601 }
02602
02603
02604 Geom::Point usvs;
02605 usvs = irs->pData[rSt].rx - ils->pData[lSt].rx;
02606
02607
02608 Geom::Matrix m(ldir[0], ldir[1],
02609 rdir[0], rdir[1],
02610 0, 0);
02611 double det = m.det();
02612
02613 double tdet = det * ils->eData[ilb].isqlength * irs->eData[irb].isqlength;
02614
02615 if (tdet > -0.0001 && tdet < 0.0001)
02616 {
02617 Geom::Point sDiff, eDiff;
02618 double sDot, eDot;
02619 sDiff = ils->pData[lSt].rx - irs->pData[rSt].rx;
02620 eDiff = ils->pData[lEn].rx - irs->pData[rSt].rx;
02621 sDot = cross (sDiff,rdir );
02622 eDot = cross (eDiff,rdir);
02623
02624 atx =
02625 (sDot * irs->pData[lEn].rx - eDot * irs->pData[lSt].rx) / (sDot -
02626 eDot);
02627 atL = sDot / (sDot - eDot);
02628
02629 sDiff = irs->pData[rSt].rx - ils->pData[lSt].rx;
02630 eDiff = irs->pData[rEn].rx - ils->pData[lSt].rx;
02631 sDot = cross (sDiff,ldir );
02632 eDot = cross (eDiff,ldir );
02633
02634 atR = sDot / (sDot - eDot);
02635
02636 return true;
02637 }
02638
02639
02640 m[1] = -m[1];
02641 m[2] = -m[2];
02642 {
02643 double swap = m[0];
02644 m[0] = m[3];
02645 m[3] = swap;
02646 }
02647
02648 atL = (m[0]* usvs[0] + m[1] * usvs[1]) / det;
02649 atR = -(m[2] * usvs[0] + m[3] * usvs[1]) / det;
02650 atx = ils->pData[lSt].rx + atL * ldir;
02651
02652
02653 return true;
02654 }
02655
02656 bool
02657 Shape::TesteAdjacency (Shape * a, int no, const Geom::Point atx, int nPt,
02658 bool push)
02659 {
02660 if (nPt == a->swsData[no].stPt || nPt == a->swsData[no].enPt)
02661 return false;
02662
02663 Geom::Point adir, diff, ast, aen, diff1, diff2, diff3, diff4;
02664
02665 ast = a->pData[a->getEdge(no).st].rx;
02666 aen = a->pData[a->getEdge(no).en].rx;
02667
02668 adir = a->eData[no].rdx;
02669
02670 double sle = a->eData[no].length;
02671 double ile = a->eData[no].ilength;
02672
02673 diff = atx - ast;
02674
02675 double e = IHalfRound ((cross (diff,adir)) * a->eData[no].isqlength);
02676 if (-3 < e && e < 3)
02677 {
02678 double rad = HalfRound (0.501);
02679
02680 diff1[0] = diff[0] - rad;
02681 diff1[1] = diff[1] - rad;
02682 diff2[0] = diff[0] + rad;
02683 diff2[1] = diff[1] - rad;
02684 diff3[0] = diff[0] + rad;
02685 diff3[1] = diff[1] + rad;
02686 diff4[0] = diff[0] - rad;
02687 diff4[1] = diff[1] + rad;
02688 double di1, di2;
02689 bool adjacent = false;
02690 di1 = cross (diff1,adir);
02691 di2 = cross (diff3,adir);
02692 if ((di1 < 0 && di2 > 0) || (di1 > 0 && di2 < 0))
02693 {
02694 adjacent = true;
02695 }
02696 else
02697 {
02698 di1 = cross ( diff2,adir);
02699 di2 = cross (diff4,adir);
02700 if ((di1 < 0 && di2 > 0) || (di1 > 0 && di2 < 0))
02701 {
02702 adjacent = true;
02703 }
02704 }
02705 if (adjacent)
02706 {
02707 double t = dot (diff, adir);
02708 if (t > 0 && t < sle)
02709 {
02710 if (push)
02711 {
02712 t *= ile;
02713 PushIncidence (a, no, nPt, t);
02714 }
02715 return true;
02716 }
02717 }
02718 }
02719 return false;
02720 }
02721
02722 void
02723 Shape::CheckAdjacencies (int lastPointNo, int lastChgtPt, Shape * ,
02724 int )
02725 {
02726 for (unsigned int cCh = 0; cCh < chgts.size(); cCh++)
02727 {
02728 int chLeN = chgts[cCh].ptNo;
02729 int chRiN = chgts[cCh].ptNo;
02730 if (chgts[cCh].src)
02731 {
02732 Shape *lS = chgts[cCh].src;
02733 int lB = chgts[cCh].bord;
02734 int lftN = lS->swsData[lB].leftRnd;
02735 int rgtN = lS->swsData[lB].rightRnd;
02736 if (lftN < chLeN)
02737 chLeN = lftN;
02738 if (rgtN > chRiN)
02739 chRiN = rgtN;
02740
02741 for (int n = lftN - 1; n >= lastChgtPt; n--)
02742 {
02743 if (TesteAdjacency (lS, lB, getPoint(n).x, n, false) ==
02744 false)
02745 break;
02746 lS->swsData[lB].leftRnd = n;
02747 }
02748 for (int n = rgtN + 1; n < lastPointNo; n++)
02749 {
02750 if (TesteAdjacency (lS, lB, getPoint(n).x, n, false) ==
02751 false)
02752 break;
02753 lS->swsData[lB].rightRnd = n;
02754 }
02755 }
02756 if (chgts[cCh].osrc)
02757 {
02758 Shape *rS = chgts[cCh].osrc;
02759 int rB = chgts[cCh].obord;
02760 int lftN = rS->swsData[rB].leftRnd;
02761 int rgtN = rS->swsData[rB].rightRnd;
02762 if (lftN < chLeN)
02763 chLeN = lftN;
02764 if (rgtN > chRiN)
02765 chRiN = rgtN;
02766
02767 for (int n = lftN - 1; n >= lastChgtPt; n--)
02768 {
02769 if (TesteAdjacency (rS, rB, getPoint(n).x, n, false) ==
02770 false)
02771 break;
02772 rS->swsData[rB].leftRnd = n;
02773 }
02774 for (int n = rgtN + 1; n < lastPointNo; n++)
02775 {
02776 if (TesteAdjacency (rS, rB, getPoint(n).x, n, false) ==
02777 false)
02778 break;
02779 rS->swsData[rB].rightRnd = n;
02780 }
02781 }
02782 if (chgts[cCh].lSrc)
02783 {
02784 if (chgts[cCh].lSrc->swsData[chgts[cCh].lBrd].leftRnd < lastChgtPt)
02785 {
02786 Shape *nSrc = chgts[cCh].lSrc;
02787 int nBrd = chgts[cCh].lBrd ;
02788 bool hit;
02789
02790 do
02791 {
02792 hit = false;
02793 for (int n = chRiN; n >= chLeN; n--)
02794 {
02795 if (TesteAdjacency
02796 (nSrc, nBrd, getPoint(n).x, n, false))
02797 {
02798 if (nSrc->swsData[nBrd].leftRnd < lastChgtPt)
02799 {
02800 nSrc->swsData[nBrd].leftRnd = n;
02801 nSrc->swsData[nBrd].rightRnd = n;
02802 }
02803 else
02804 {
02805 if (n < nSrc->swsData[nBrd].leftRnd)
02806 nSrc->swsData[nBrd].leftRnd = n;
02807 if (n > nSrc->swsData[nBrd].rightRnd)
02808 nSrc->swsData[nBrd].rightRnd = n;
02809 }
02810 hit = true;
02811 }
02812 }
02813 for (int n = chLeN - 1; n >= lastChgtPt; n--)
02814 {
02815 if (TesteAdjacency
02816 (nSrc, nBrd, getPoint(n).x, n, false) == false)
02817 break;
02818 if (nSrc->swsData[nBrd].leftRnd < lastChgtPt)
02819 {
02820 nSrc->swsData[nBrd].leftRnd = n;
02821 nSrc->swsData[nBrd].rightRnd = n;
02822 }
02823 else
02824 {
02825 if (n < nSrc->swsData[nBrd].leftRnd)
02826 nSrc->swsData[nBrd].leftRnd = n;
02827 if (n > nSrc->swsData[nBrd].rightRnd)
02828 nSrc->swsData[nBrd].rightRnd = n;
02829 }
02830 hit = true;
02831 }
02832 if (hit)
02833 {
02834 SweepTree *node =
02835 static_cast < SweepTree * >(nSrc->swsData[nBrd].misc);
02836 if (node == NULL)
02837 break;
02838 node = static_cast < SweepTree * >(node->elem[LEFT]);
02839 if (node == NULL)
02840 break;
02841 nSrc = node->src;
02842 nBrd = node->bord;
02843 if (nSrc->swsData[nBrd].leftRnd >= lastChgtPt)
02844 break;
02845 }
02846 }
02847 while (hit);
02848
02849 }
02850 }
02851 if (chgts[cCh].rSrc)
02852 {
02853 if (chgts[cCh].rSrc->swsData[chgts[cCh].rBrd].leftRnd < lastChgtPt)
02854 {
02855 Shape *nSrc = chgts[cCh].rSrc;
02856 int nBrd = chgts[cCh].rBrd ;
02857 bool hit;
02858 do
02859 {
02860 hit = false;
02861 for (int n = chLeN; n <= chRiN; n++)
02862 {
02863 if (TesteAdjacency
02864 (nSrc, nBrd, getPoint(n).x, n, false))
02865 {
02866 if (nSrc->swsData[nBrd].leftRnd < lastChgtPt)
02867 {
02868 nSrc->swsData[nBrd].leftRnd = n;
02869 nSrc->swsData[nBrd].rightRnd = n;
02870 }
02871 else
02872 {
02873 if (n < nSrc->swsData[nBrd].leftRnd)
02874 nSrc->swsData[nBrd].leftRnd = n;
02875 if (n > nSrc->swsData[nBrd].rightRnd)
02876 nSrc->swsData[nBrd].rightRnd = n;
02877 }
02878 hit = true;
02879 }
02880 }
02881 for (int n = chRiN + 1; n < lastPointNo; n++)
02882 {
02883 if (TesteAdjacency
02884 (nSrc, nBrd, getPoint(n).x, n, false) == false)
02885 break;
02886 if (nSrc->swsData[nBrd].leftRnd < lastChgtPt)
02887 {
02888 nSrc->swsData[nBrd].leftRnd = n;
02889 nSrc->swsData[nBrd].rightRnd = n;
02890 }
02891 else
02892 {
02893 if (n < nSrc->swsData[nBrd].leftRnd)
02894 nSrc->swsData[nBrd].leftRnd = n;
02895 if (n > nSrc->swsData[nBrd].rightRnd)
02896 nSrc->swsData[nBrd].rightRnd = n;
02897 }
02898 hit = true;
02899 }
02900 if (hit)
02901 {
02902 SweepTree *node =
02903 static_cast < SweepTree * >(nSrc->swsData[nBrd].misc);
02904 if (node == NULL)
02905 break;
02906 node = static_cast < SweepTree * >(node->elem[RIGHT]);
02907 if (node == NULL)
02908 break;
02909 nSrc = node->src;
02910 nBrd = node->bord;
02911 if (nSrc->swsData[nBrd].leftRnd >= lastChgtPt)
02912 break;
02913 }
02914 }
02915 while (hit);
02916 }
02917 }
02918 }
02919 }
02920
02921
02922 void Shape::AddChgt(int lastPointNo, int lastChgtPt, Shape * &shapeHead,
02923 int &edgeHead, sTreeChangeType type, Shape * lS, int lB, Shape * rS,
02924 int rB)
02925 {
02926 sTreeChange c;
02927 c.ptNo = lastPointNo;
02928 c.type = type;
02929 c.src = lS;
02930 c.bord = lB;
02931 c.osrc = rS;
02932 c.obord = rB;
02933 chgts.push_back(c);
02934 const int nCh = chgts.size() - 1;
02935
02936
02937
02938 if (lS) {
02939 SweepTree *lE = static_cast < SweepTree * >(lS->swsData[lB].misc);
02940 if (lE && lE->elem[LEFT]) {
02941 SweepTree *llE = static_cast < SweepTree * >(lE->elem[LEFT]);
02942 chgts[nCh].lSrc = llE->src;
02943 chgts[nCh].lBrd = llE->bord;
02944 } else {
02945 chgts[nCh].lSrc = NULL;
02946 chgts[nCh].lBrd = -1;
02947 }
02948
02949 if (lS->swsData[lB].leftRnd < lastChgtPt) {
02950 lS->swsData[lB].leftRnd = lastPointNo;
02951 lS->swsData[lB].nextSh = shapeHead;
02952 lS->swsData[lB].nextBo = edgeHead;
02953 edgeHead = lB;
02954 shapeHead = lS;
02955 } else {
02956 int old = lS->swsData[lB].leftRnd;
02957 if (getPoint(old).x[0] > getPoint(lastPointNo).x[0]) {
02958 lS->swsData[lB].leftRnd = lastPointNo;
02959 }
02960 }
02961 if (lS->swsData[lB].rightRnd < lastChgtPt) {
02962 lS->swsData[lB].rightRnd = lastPointNo;
02963 } else {
02964 int old = lS->swsData[lB].rightRnd;
02965 if (getPoint(old).x[0] < getPoint(lastPointNo).x[0])
02966 lS->swsData[lB].rightRnd = lastPointNo;
02967 }
02968 }
02969
02970 if (rS) {
02971 SweepTree *rE = static_cast < SweepTree * >(rS->swsData[rB].misc);
02972 if (rE->elem[RIGHT]) {
02973 SweepTree *rrE = static_cast < SweepTree * >(rE->elem[RIGHT]);
02974 chgts[nCh].rSrc = rrE->src;
02975 chgts[nCh].rBrd = rrE->bord;
02976 } else {
02977 chgts[nCh].rSrc = NULL;
02978 chgts[nCh].rBrd = -1;
02979 }
02980
02981 if (rS->swsData[rB].leftRnd < lastChgtPt) {
02982 rS->swsData[rB].leftRnd = lastPointNo;
02983 rS->swsData[rB].nextSh = shapeHead;
02984 rS->swsData[rB].nextBo = edgeHead;
02985 edgeHead = rB;
02986 shapeHead = rS;
02987 } else {
02988 int old = rS->swsData[rB].leftRnd;
02989 if (getPoint(old).x[0] > getPoint(lastPointNo).x[0]) {
02990 rS->swsData[rB].leftRnd = lastPointNo;
02991 }
02992 }
02993 if (rS->swsData[rB].rightRnd < lastChgtPt) {
02994 rS->swsData[rB].rightRnd = lastPointNo;
02995 } else {
02996 int old = rS->swsData[rB].rightRnd;
02997 if (getPoint(old).x[0] < getPoint(lastPointNo).x[0])
02998 rS->swsData[rB].rightRnd = lastPointNo;
02999 }
03000 } else {
03001 SweepTree *lE = static_cast < SweepTree * >(lS->swsData[lB].misc);
03002 if (lE && lE->elem[RIGHT]) {
03003 SweepTree *rlE = static_cast < SweepTree * >(lE->elem[RIGHT]);
03004 chgts[nCh].rSrc = rlE->src;
03005 chgts[nCh].rBrd = rlE->bord;
03006 } else {
03007 chgts[nCh].rSrc = NULL;
03008 chgts[nCh].rBrd = -1;
03009 }
03010 }
03011 }
03012
03013
03014 void
03015 Shape::Validate (void)
03016 {
03017 for (int i = 0; i < numberOfPoints(); i++)
03018 {
03019 pData[i].rx = getPoint(i).x;
03020 }
03021 for (int i = 0; i < numberOfEdges(); i++)
03022 {
03023 eData[i].rdx = getEdge(i).dx;
03024 }
03025 for (int i = 0; i < numberOfEdges(); i++)
03026 {
03027 for (int j = i + 1; j < numberOfEdges(); j++)
03028 {
03029 Geom::Point atx;
03030 double atL, atR;
03031 if (TesteIntersection (this, this, i, j, atx, atL, atR, false))
03032 {
03033 printf ("%i %i %f %f di=%f %f dj=%f %f\n", i, j, atx[0],atx[1],getEdge(i).dx[0],getEdge(i).dx[1],getEdge(j).dx[0],getEdge(j).dx[1]);
03034 }
03035 }
03036 }
03037 fflush (stdout);
03038 }
03039
03040 void
03041 Shape::CheckEdges (int lastPointNo, int lastChgtPt, Shape * a, Shape * b,
03042 BooleanOp mod)
03043 {
03044
03045 for (unsigned int cCh = 0; cCh < chgts.size(); cCh++)
03046 {
03047 if (chgts[cCh].type == 0)
03048 {
03049 Shape *lS = chgts[cCh].src;
03050 int lB = chgts[cCh].bord;
03051 lS->swsData[lB].curPoint = chgts[cCh].ptNo;
03052 }
03053 }
03054 for (unsigned int cCh = 0; cCh < chgts.size(); cCh++)
03055 {
03056
03057
03058 if (chgts[cCh].src)
03059 {
03060 Shape *lS = chgts[cCh].src;
03061 int lB = chgts[cCh].bord;
03062 Avance (lastPointNo, lastChgtPt, lS, lB, a, b, mod);
03063 }
03064 if (chgts[cCh].osrc)
03065 {
03066 Shape *rS = chgts[cCh].osrc;
03067 int rB = chgts[cCh].obord;
03068 Avance (lastPointNo, lastChgtPt, rS, rB, a, b, mod);
03069 }
03070 if (chgts[cCh].lSrc)
03071 {
03072 Shape *nSrc = chgts[cCh].lSrc;
03073 int nBrd = chgts[cCh].lBrd;
03074 while (nSrc->swsData[nBrd].leftRnd >=
03075 lastChgtPt )
03076 {
03077 Avance (lastPointNo, lastChgtPt, nSrc, nBrd, a, b, mod);
03078
03079 SweepTree *node =
03080 static_cast < SweepTree * >(nSrc->swsData[nBrd].misc);
03081 if (node == NULL)
03082 break;
03083 node = static_cast < SweepTree * >(node->elem[LEFT]);
03084 if (node == NULL)
03085 break;
03086 nSrc = node->src;
03087 nBrd = node->bord;
03088 }
03089 }
03090 if (chgts[cCh].rSrc)
03091 {
03092 Shape *nSrc = chgts[cCh].rSrc;
03093 int nBrd = chgts[cCh].rBrd;
03094 while (nSrc->swsData[nBrd].rightRnd >=
03095 lastChgtPt )
03096 {
03097 Avance (lastPointNo, lastChgtPt, nSrc, nBrd, a, b, mod);
03098
03099 SweepTree *node =
03100 static_cast < SweepTree * >(nSrc->swsData[nBrd].misc);
03101 if (node == NULL)
03102 break;
03103 node = static_cast < SweepTree * >(node->elem[RIGHT]);
03104 if (node == NULL)
03105 break;
03106 nSrc = node->src;
03107 nBrd = node->bord;
03108 }
03109 }
03110 }
03111 }
03112
03113 void
03114 Shape::Avance (int lastPointNo, int lastChgtPt, Shape * lS, int lB, Shape * ,
03115 Shape * b, BooleanOp mod)
03116 {
03117 double dd = HalfRound (1);
03118 bool avoidDiag = false;
03119
03120
03121 bool direct = true;
03122 if (lS == b && (mod == bool_op_diff || mod == bool_op_symdiff))
03123 direct = false;
03124 int lftN = lS->swsData[lB].leftRnd;
03125 int rgtN = lS->swsData[lB].rightRnd;
03126 if (lS->swsData[lB].doneTo < lastChgtPt)
03127 {
03128 int lp = lS->swsData[lB].curPoint;
03129 if (lp >= 0 && getPoint(lp).x[1] + dd == getPoint(lastChgtPt).x[1])
03130 avoidDiag = true;
03131 if (lS->eData[lB].rdx[1] == 0)
03132 {
03133
03134 if (lS->eData[lB].rdx[0] >= 0)
03135 {
03136 for (int p = lftN; p <= rgtN; p++)
03137 {
03138 DoEdgeTo (lS, lB, p, direct, true);
03139 lp = p;
03140 }
03141 }
03142 else
03143 {
03144 for (int p = lftN; p <= rgtN; p++)
03145 {
03146 DoEdgeTo (lS, lB, p, direct, false);
03147 lp = p;
03148 }
03149 }
03150 }
03151 else if (lS->eData[lB].rdx[1] > 0)
03152 {
03153 if (lS->eData[lB].rdx[0] >= 0)
03154 {
03155
03156 for (int p = lftN; p <= rgtN; p++)
03157 {
03158 if (avoidDiag && p == lftN && getPoint(lftN).x[0] == getPoint(lp).x[0] + dd)
03159 {
03160 if (lftN > 0 && lftN - 1 >= lastChgtPt
03161 && getPoint(lftN - 1).x[0] == getPoint(lp).x[0])
03162 {
03163 DoEdgeTo (lS, lB, lftN - 1, direct, true);
03164 DoEdgeTo (lS, lB, lftN, direct, true);
03165 }
03166 else
03167 {
03168 DoEdgeTo (lS, lB, lftN, direct, true);
03169 }
03170 }
03171 else
03172 {
03173 DoEdgeTo (lS, lB, p, direct, true);
03174 }
03175 lp = p;
03176 }
03177 }
03178 else
03179 {
03180
03181 for (int p = rgtN; p >= lftN; p--)
03182 {
03183 if (avoidDiag && p == rgtN && getPoint(rgtN).x[0] == getPoint(lp).x[0] - dd)
03184 {
03185 if (rgtN < numberOfPoints() && rgtN + 1 < lastPointNo
03186 && getPoint(rgtN + 1).x[0] == getPoint(lp).x[0])
03187 {
03188 DoEdgeTo (lS, lB, rgtN + 1, direct, true);
03189 DoEdgeTo (lS, lB, rgtN, direct, true);
03190 }
03191 else
03192 {
03193 DoEdgeTo (lS, lB, rgtN, direct, true);
03194 }
03195 }
03196 else
03197 {
03198 DoEdgeTo (lS, lB, p, direct, true);
03199 }
03200 lp = p;
03201 }
03202 }
03203 }
03204 else
03205 {
03206 if (lS->eData[lB].rdx[0] >= 0)
03207 {
03208
03209 for (int p = rgtN; p >= lftN; p--)
03210 {
03211 if (avoidDiag && p == rgtN && getPoint(rgtN).x[0] == getPoint(lp).x[0] - dd)
03212 {
03213 if (rgtN < numberOfPoints() && rgtN + 1 < lastPointNo
03214 && getPoint(rgtN + 1).x[0] == getPoint(lp).x[0])
03215 {
03216 DoEdgeTo (lS, lB, rgtN + 1, direct, false);
03217 DoEdgeTo (lS, lB, rgtN, direct, false);
03218 }
03219 else
03220 {
03221 DoEdgeTo (lS, lB, rgtN, direct, false);
03222 }
03223 }
03224 else
03225 {
03226 DoEdgeTo (lS, lB, p, direct, false);
03227 }
03228 lp = p;
03229 }
03230 }
03231 else
03232 {
03233
03234 for (int p = lftN; p <= rgtN; p++)
03235 {
03236 if (avoidDiag && p == lftN && getPoint(lftN).x[0] == getPoint(lp).x[0] + dd)
03237 {
03238 if (lftN > 0 && lftN - 1 >= lastChgtPt
03239 && getPoint(lftN - 1).x[0] == getPoint(lp).x[0])
03240 {
03241 DoEdgeTo (lS, lB, lftN - 1, direct, false);
03242 DoEdgeTo (lS, lB, lftN, direct, false);
03243 }
03244 else
03245 {
03246 DoEdgeTo (lS, lB, lftN, direct, false);
03247 }
03248 }
03249 else
03250 {
03251 DoEdgeTo (lS, lB, p, direct, false);
03252 }
03253 lp = p;
03254 }
03255 }
03256 }
03257 lS->swsData[lB].curPoint = lp;
03258 }
03259 lS->swsData[lB].doneTo = lastPointNo - 1;
03260 }
03261
03262 void
03263 Shape::DoEdgeTo (Shape * iS, int iB, int iTo, bool direct, bool sens)
03264 {
03265 int lp = iS->swsData[iB].curPoint;
03266 int ne = -1;
03267 if (sens)
03268 {
03269 if (direct)
03270 ne = AddEdge (lp, iTo);
03271 else
03272 ne = AddEdge (iTo, lp);
03273 }
03274 else
03275 {
03276 if (direct)
03277 ne = AddEdge (iTo, lp);
03278 else
03279 ne = AddEdge (lp, iTo);
03280 }
03281 if (ne >= 0 && _has_back_data)
03282 {
03283 ebData[ne].pathID = iS->ebData[iB].pathID;
03284 ebData[ne].pieceID = iS->ebData[iB].pieceID;
03285 if (iS->eData[iB].length < 0.00001)
03286 {
03287 ebData[ne].tSt = ebData[ne].tEn = iS->ebData[iB].tSt;
03288 }
03289 else
03290 {
03291 double bdl = iS->eData[iB].ilength;
03292 Geom::Point bpx = iS->pData[iS->getEdge(iB).st].rx;
03293 Geom::Point bdx = iS->eData[iB].rdx;
03294 Geom::Point psx = getPoint(getEdge(ne).st).x;
03295 Geom::Point pex = getPoint(getEdge(ne).en).x;
03296 Geom::Point psbx=psx-bpx;
03297 Geom::Point pebx=pex-bpx;
03298 double pst = dot(psbx,bdx) * bdl;
03299 double pet = dot(pebx,bdx) * bdl;
03300 pst = iS->ebData[iB].tSt * (1 - pst) + iS->ebData[iB].tEn * pst;
03301 pet = iS->ebData[iB].tSt * (1 - pet) + iS->ebData[iB].tEn * pet;
03302 ebData[ne].tEn = pet;
03303 ebData[ne].tSt = pst;
03304 }
03305 }
03306 iS->swsData[iB].curPoint = iTo;
03307 if (ne >= 0)
03308 {
03309 int cp = iS->swsData[iB].firstLinkedPoint;
03310 swsData[ne].firstLinkedPoint = iS->swsData[iB].firstLinkedPoint;
03311 while (cp >= 0)
03312 {
03313 pData[cp].askForWindingB = ne;
03314 cp = pData[cp].nextLinkedPoint;
03315 }
03316 iS->swsData[iB].firstLinkedPoint = -1;
03317 }
03318 }