Code

make rotations, scales and flips work with the object's rotation axis
[inkscape.git] / src / livarot / ShapeSweep.cpp
1 /*
2  *  ShapeSweep.cpp
3  *  nlivarot
4  *
5  *  Created by fred on Thu Jun 19 2003.
6  *
7  */
9 #include <glib/gmem.h>
10 #include "Shape.h"
11 #include "livarot/sweep-event-queue.h"
12 #include "livarot/sweep-tree-list.h"
13 #include "livarot/sweep-tree.h"
15 #include "libnr/nr-matrix.h"
17 //int   doDebug=0;
19 /*
20  * El Intersector.
21  * algorithm: 1) benley ottman to get intersections of all the polygon's edges
22  *            2) rounding of the points of the polygon, Hooby's algorithm
23  *            3) DFS with clockwise choice of the edge to compute the windings
24  *            4) choose edges according to winding numbers and fill rule
25  * some additional nastyness: step 2 needs a seed winding number for the upper-left point of each 
26  * connex subgraph of the graph. computing these brutally is O(n^3): baaaad. so during the sweeping in 1)
27  * we keep for each point the edge of the resulting graph (not the original) that lies just on its left; 
28  * when the time comes for the point to get its winding number computed, that edge must have been treated,
29  * because its upper end lies above the aforementioned point, meaning we know the winding number of the point.
30  * only, there is a catch: since we're sweeping the polygon, the edge we want to link the point to has not yet been
31  * added (that would be too easy...). so the points are put on a linked list on the original shape's edge, and the list
32  * is flushed when the edge is added.
33  * rounding: to do the rounding, we need to find which edges cross the surrounding of the rounded points (at 
34  * each sweepline position). grunt method tries all combination of "rounded points in the sweepline"x"edges crossing 
35  * the sweepline". That's bad (and that's what polyboolean does, if i am not mistaken). so for each point 
36  * rounded in a given sweepline, keep immediate left and right edges at the time the point is treated.
37  * when edges/points crossing are searched, walk the edge list (in the  sweepline at the end of the batch) starting 
38  * from the rounded points' left and right from that time. may sound strange, but it works because edges that
39  * end or start in the batch have at least one end in the batch.
40  * all these are the cause of the numerous linked lists of points and edges maintained in the sweeping
41  */
43 void
44 Shape::ResetSweep (void)
45 {
46   MakePointData (true);
47   MakeEdgeData (true);
48   MakeSweepSrcData (true);
49 }
51 void
52 Shape::CleanupSweep (void)
53 {
54   MakePointData (false);
55   MakeEdgeData (false);
56   MakeSweepSrcData (false);
57 }
59 void
60 Shape::ForceToPolygon (void)
61 {
62   type = shape_polygon;
63 }
65 int
66 Shape::Reoriente (Shape * a)
67 {
68   Reset (0, 0);
69   if (a->numberOfPoints() <= 1 || a->numberOfEdges() <= 1)
70     return 0;
71   if (directedEulerian(a) == false)
72     return shape_input_err;
74   _pts = a->_pts;
75   if (numberOfPoints() > maxPt)
76     {
77       maxPt = numberOfPoints();
78       if (_has_points_data) {
79         pData.resize(maxPt);
80         _point_data_initialised = false;
81         _bbox_up_to_date = false;
82         }
83     }
85   _aretes = a->_aretes;
86   if (numberOfEdges() > maxAr)
87     {
88       maxAr = numberOfEdges();
89       if (_has_edges_data)
90         eData.resize(maxAr);
91       if (_has_sweep_src_data)
92         swsData.resize(maxAr);
93       if (_has_sweep_dest_data)
94         swdData.resize(maxAr);
95       if (_has_raster_data)
96         swrData.resize(maxAr);
97     }
99   MakePointData (true);
100   MakeEdgeData (true);
101   MakeSweepDestData (true);
103   initialisePointData();
105   for (int i = 0; i < numberOfPoints(); i++) {
106       _pts[i].x = pData[i].rx;
107       _pts[i].oldDegree = getPoint(i).totalDegree();
108   }
109   
110   for (int i = 0; i < a->numberOfEdges(); i++)
111     {
112       eData[i].rdx = pData[getEdge(i).en].rx - pData[getEdge(i).st].rx;
113       eData[i].weight = 1;
114       _aretes[i].dx = eData[i].rdx;
115     }
117   SortPointsRounded ();
119   _need_edges_sorting = true;
120   GetWindings (this, NULL, bool_op_union, true);
122 //      Plot(341,56,8,400,400,true,true,false,true);
123   for (int i = 0; i < numberOfEdges(); i++)
124     {
125       swdData[i].leW %= 2;
126       swdData[i].riW %= 2;
127       if (swdData[i].leW < 0)
128         swdData[i].leW = -swdData[i].leW;
129       if (swdData[i].riW < 0)
130         swdData[i].riW = -swdData[i].riW;
131       if (swdData[i].leW > 0 && swdData[i].riW <= 0)
132         {
133           eData[i].weight = 1;
134         }
135       else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
136         {
137           Inverse (i);
138           eData[i].weight = 1;
139         }
140       else
141         {
142           eData[i].weight = 0;
143           SubEdge (i);
144           i--;
145         }
146     }
148   MakePointData (false);
149   MakeEdgeData (false);
150   MakeSweepDestData (false);
152   if (directedEulerian(this) == false)
153     {
154 //              printf( "pas euclidian2");
155       _pts.clear();
156       _aretes.clear();
157       return shape_euler_err;
158     }
160   type = shape_polygon;
161   return 0;
164 int
165 Shape::ConvertToShape (Shape * a, FillRule directed, bool invert)
167     Reset (0, 0);
169     if (a->numberOfPoints() <= 1 || a->numberOfEdges() <= 1) {
170         return 0;
171     }
172     
173     if ( directed != fill_justDont && directedEulerian(a) == false ) {
174         return shape_input_err;
175     }
176   
177     a->ResetSweep();
179     if (sTree == NULL) {
180         sTree = new SweepTreeList(a->numberOfEdges());
181     }
182     if (sEvts == NULL) {
183         sEvts = new SweepEventQueue(a->numberOfEdges());
184     }
185   
186     MakePointData(true);
187     MakeEdgeData(true);
188     MakeSweepSrcData(true);
189     MakeSweepDestData(true);
190     MakeBackData(a->_has_back_data);
192     a->initialisePointData();
193     a->initialiseEdgeData();
195     a->SortPointsRounded();
197     chgts.clear();
199     double lastChange = a->pData[0].rx[1] - 1.0;
200     int lastChgtPt = 0;
201     int edgeHead = -1;
202     Shape *shapeHead = NULL;
204     clearIncidenceData();
205     
206     int curAPt = 0;
208     while (curAPt < a->numberOfPoints() || sEvts->size() > 0) {
209         NR::Point ptX;
210       double ptL, ptR;
211       SweepTree *intersL = NULL;
212       SweepTree *intersR = NULL;
213       int nPt = -1;
214       Shape *ptSh = NULL;
215       bool isIntersection = false;
216       if (sEvts->peek(intersL, intersR, ptX, ptL, ptR))
217         {
218           if (a->pData[curAPt].pending > 0
219               || (a->pData[curAPt].rx[1] > ptX[1]
220                   || (a->pData[curAPt].rx[1] == ptX[1]
221                       && a->pData[curAPt].rx[0] > ptX[0])))
222             {
223               /* FIXME: could just be pop? */
224               sEvts->extract(intersL, intersR, ptX, ptL, ptR);
225               isIntersection = true;
226             }
227           else
228             {
229               nPt = curAPt++;
230               ptSh = a;
231               ptX = ptSh->pData[nPt].rx;
232               isIntersection = false;
233             }
234         }
235       else
236         {
237           nPt = curAPt++;
238           ptSh = a;
239           ptX = ptSh->pData[nPt].rx;
240           isIntersection = false;
241         }
243       if (isIntersection == false)
244         {
245           if (ptSh->getPoint(nPt).dI == 0 && ptSh->getPoint(nPt).dO == 0)
246             continue;
247         }
249       NR::Point rPtX;
250       rPtX[0]= Round (ptX[0]);
251       rPtX[1]= Round (ptX[1]);
252       int lastPointNo = -1;
253       lastPointNo = AddPoint (rPtX);
254       pData[lastPointNo].rx = rPtX;
256       if (rPtX[1] > lastChange)
257         {
258           int lastI = AssemblePoints (lastChgtPt, lastPointNo);
260           Shape *curSh = shapeHead;
261           int curBo = edgeHead;
262           while (curSh)
263             {
264               curSh->swsData[curBo].leftRnd =
265                 pData[curSh->swsData[curBo].leftRnd].newInd;
266               curSh->swsData[curBo].rightRnd =
267                 pData[curSh->swsData[curBo].rightRnd].newInd;
269               Shape *neSh = curSh->swsData[curBo].nextSh;
270               curBo = curSh->swsData[curBo].nextBo;
271               curSh = neSh;
272             }
274           for (unsigned int i = 0; i < chgts.size(); i++)
275             {
276               chgts[i].ptNo = pData[chgts[i].ptNo].newInd;
277               if (chgts[i].type == 0)
278                 {
279                   if (chgts[i].src->getEdge(chgts[i].bord).st <
280                       chgts[i].src->getEdge(chgts[i].bord).en)
281                     {
282                       chgts[i].src->swsData[chgts[i].bord].stPt =
283                         chgts[i].ptNo;
284                     }
285                   else
286                     {
287                       chgts[i].src->swsData[chgts[i].bord].enPt =
288                         chgts[i].ptNo;
289                     }
290                 }
291               else if (chgts[i].type == 1)
292                 {
293                   if (chgts[i].src->getEdge(chgts[i].bord).st >
294                       chgts[i].src->getEdge(chgts[i].bord).en)
295                     {
296                       chgts[i].src->swsData[chgts[i].bord].stPt =
297                         chgts[i].ptNo;
298                     }
299                   else
300                     {
301                       chgts[i].src->swsData[chgts[i].bord].enPt =
302                         chgts[i].ptNo;
303                     }
304                 }
305             }
307           CheckAdjacencies (lastI, lastChgtPt, shapeHead, edgeHead);
309           CheckEdges (lastI, lastChgtPt, a, NULL, bool_op_union);
311           for (int i = lastChgtPt; i < lastI; i++) {
312             if (pData[i].askForWindingS) {
313                     Shape *windS = pData[i].askForWindingS;
314                     int windB = pData[i].askForWindingB;
315                     pData[i].nextLinkedPoint = windS->swsData[windB].firstLinkedPoint;
316                     windS->swsData[windB].firstLinkedPoint = i;
317                   }
318            }
320     if (lastI < lastPointNo) {
321           _pts[lastI] = getPoint(lastPointNo);
322            pData[lastI] = pData[lastPointNo];
323           }
324           lastPointNo = lastI;
325           _pts.resize(lastI + 1);
327           lastChgtPt = lastPointNo;
328           lastChange = rPtX[1];
329           chgts.clear();
330           edgeHead = -1;
331           shapeHead = NULL;
332         }
335       if (isIntersection)
336         {
337 //                      printf("(%i %i [%i %i]) ",intersL->bord,intersR->bord,intersL->startPoint,intersR->startPoint);
338           intersL->RemoveEvent (*sEvts, LEFT);
339           intersR->RemoveEvent (*sEvts, RIGHT);
341           AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, INTERSECTION,
342                    intersL->src, intersL->bord, intersR->src, intersR->bord);
344           intersL->SwapWithRight (*sTree, *sEvts);
346           TesteIntersection (intersL, LEFT, false);
347           TesteIntersection (intersR, RIGHT, false);
348         }
349       else
350         {
351           int cb;
353           int nbUp = 0, nbDn = 0;
354           int upNo = -1, dnNo = -1;
355           cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
356           while (cb >= 0 && cb < ptSh->numberOfEdges())
357             {
358               if ((ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
359                    && nPt == ptSh->getEdge(cb).en)
360                   || (ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
361                       && nPt == ptSh->getEdge(cb).st))
362                 {
363                   upNo = cb;
364                   nbUp++;
365                 }
366               if ((ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
367                    && nPt == ptSh->getEdge(cb).en)
368                   || (ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
369                       && nPt == ptSh->getEdge(cb).st))
370                 {
371                   dnNo = cb;
372                   nbDn++;
373                 }
374               cb = ptSh->NextAt (nPt, cb);
375             }
377           if (nbDn <= 0)
378             {
379               upNo = -1;
380             }
381           if (upNo >= 0 && (SweepTree *) ptSh->swsData[upNo].misc == NULL)
382             {
383               upNo = -1;
384             }
386           bool doWinding = true;
388           if (nbUp > 0)
389             {
390               cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
391               while (cb >= 0 && cb < ptSh->numberOfEdges())
392                 {
393                   if ((ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
394                        && nPt == ptSh->getEdge(cb).en)
395                       || (ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
396                           && nPt == ptSh->getEdge(cb).st))
397                     {
398                       if (cb != upNo)
399                         {
400                           SweepTree *node =
401                             (SweepTree *) ptSh->swsData[cb].misc;
402                           if (node == NULL)
403                             {
404                             }
405                           else
406                             {
407                               AddChgt (lastPointNo, lastChgtPt, shapeHead,
408                                        edgeHead, EDGE_REMOVED, node->src, node->bord,
409                                        NULL, -1);
410                               ptSh->swsData[cb].misc = NULL;
412                               int onLeftB = -1, onRightB = -1;
413                               Shape *onLeftS = NULL;
414                               Shape *onRightS = NULL;
415                               if (node->elem[LEFT])
416                                 {
417                                   onLeftB =
418                                     (static_cast <
419                                      SweepTree * >(node->elem[LEFT]))->bord;
420                                   onLeftS =
421                                     (static_cast <
422                                      SweepTree * >(node->elem[LEFT]))->src;
423                                 }
424                               if (node->elem[RIGHT])
425                                 {
426                                   onRightB =
427                                     (static_cast <
428                                      SweepTree * >(node->elem[RIGHT]))->bord;
429                                   onRightS =
430                                     (static_cast <
431                                      SweepTree * >(node->elem[RIGHT]))->src;
432                                 }
434                               node->Remove (*sTree, *sEvts, true);
435                               if (onLeftS && onRightS)
436                                 {
437                                   SweepTree *onLeft =
438                                     (SweepTree *) onLeftS->swsData[onLeftB].
439                                     misc;
440                                   if (onLeftS == ptSh
441                                       && (onLeftS->getEdge(onLeftB).en == nPt
442                                           || onLeftS->getEdge(onLeftB).st ==
443                                           nPt))
444                                     {
445                                     }
446                                   else
447                                     {
448                                       if (onRightS == ptSh
449                                           && (onRightS->getEdge(onRightB).en ==
450                                               nPt
451                                               || onRightS->getEdge(onRightB).
452                                               st == nPt))
453                                         {
454                                         }
455                                       else
456                                         {
457                                           TesteIntersection (onLeft, RIGHT, false);
458                                         }
459                                     }
460                                 }
461                             }
462                         }
463                     }
464                   cb = ptSh->NextAt (nPt, cb);
465                 }
466             }
468           // traitement du "upNo devient dnNo"
469           SweepTree *insertionNode = NULL;
470           if (dnNo >= 0)
471             {
472               if (upNo >= 0)
473                 {
474                   SweepTree *node = (SweepTree *) ptSh->swsData[upNo].misc;
476                   AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_REMOVED,
477                            node->src, node->bord, NULL, -1);
479                   ptSh->swsData[upNo].misc = NULL;
481                   node->RemoveEvents (*sEvts);
482                   node->ConvertTo (ptSh, dnNo, 1, lastPointNo);
483                   ptSh->swsData[dnNo].misc = node;
484                   TesteIntersection (node, RIGHT, false);
485                   TesteIntersection (node, LEFT, false);
486                   insertionNode = node;
488                   ptSh->swsData[dnNo].curPoint = lastPointNo;
489                   AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_INSERTED,
490                            node->src, node->bord, NULL, -1);
491                 }
492               else
493                 {
494                   SweepTree *node = sTree->add(ptSh, dnNo, 1, lastPointNo, this);
495                   ptSh->swsData[dnNo].misc = node;
496                   node->Insert (*sTree, *sEvts, this, lastPointNo, true);
497                   if (doWinding)
498                     {
499                       SweepTree *myLeft =
500                         static_cast < SweepTree * >(node->elem[LEFT]);
501                       if (myLeft)
502                         {
503                           pData[lastPointNo].askForWindingS = myLeft->src;
504                           pData[lastPointNo].askForWindingB = myLeft->bord;
505                         }
506                       else
507                         {
508                           pData[lastPointNo].askForWindingB = -1;
509                         }
510                       doWinding = false;
511                     }
512                   TesteIntersection (node, RIGHT, false);
513                   TesteIntersection (node, LEFT, false);
514                   insertionNode = node;
516                   ptSh->swsData[dnNo].curPoint = lastPointNo;
517                   AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_INSERTED,
518                            node->src, node->bord, NULL, -1);
519                 }
520             }
522           if (nbDn > 1)
523             {                   // si nbDn == 1 , alors dnNo a deja ete traite
524               cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
525               while (cb >= 0 && cb < ptSh->numberOfEdges())
526                 {
527                   if ((ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
528                        && nPt == ptSh->getEdge(cb).en)
529                       || (ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
530                           && nPt == ptSh->getEdge(cb).st))
531                     {
532                       if (cb != dnNo)
533                         {
534                           SweepTree *node = sTree->add(ptSh, cb, 1, lastPointNo, this);
535                           ptSh->swsData[cb].misc = node;
536                           node->InsertAt (*sTree, *sEvts, this, insertionNode,
537                                           nPt, true);
538                           if (doWinding)
539                             {
540                               SweepTree *myLeft =
541                                 static_cast < SweepTree * >(node->elem[LEFT]);
542                               if (myLeft)
543                                 {
544                                   pData[lastPointNo].askForWindingS =
545                                     myLeft->src;
546                                   pData[lastPointNo].askForWindingB =
547                                     myLeft->bord;
548                                 }
549                               else
550                                 {
551                                   pData[lastPointNo].askForWindingB = -1;
552                                 }
553                               doWinding = false;
554                             }
555                           TesteIntersection (node, RIGHT, false);
556                           TesteIntersection (node, LEFT, false);
558                           ptSh->swsData[cb].curPoint = lastPointNo;
559                           AddChgt (lastPointNo, lastChgtPt, shapeHead,
560                                    edgeHead, EDGE_INSERTED, node->src, node->bord, NULL,
561                                    -1);
562                         }
563                     }
564                   cb = ptSh->NextAt (nPt, cb);
565                 }
566             }
567         }
568     }
569   {
570     int lastI = AssemblePoints (lastChgtPt, numberOfPoints());
573     Shape *curSh = shapeHead;
574     int curBo = edgeHead;
575     while (curSh)
576       {
577         curSh->swsData[curBo].leftRnd =
578           pData[curSh->swsData[curBo].leftRnd].newInd;
579         curSh->swsData[curBo].rightRnd =
580           pData[curSh->swsData[curBo].rightRnd].newInd;
582         Shape *neSh = curSh->swsData[curBo].nextSh;
583         curBo = curSh->swsData[curBo].nextBo;
584         curSh = neSh;
585       }
587     for (unsigned int i = 0; i < chgts.size(); i++)
588       {
589         chgts[i].ptNo = pData[chgts[i].ptNo].newInd;
590         if (chgts[i].type == 0)
591           {
592             if (chgts[i].src->getEdge(chgts[i].bord).st <
593                 chgts[i].src->getEdge(chgts[i].bord).en)
594               {
595                 chgts[i].src->swsData[chgts[i].bord].stPt = chgts[i].ptNo;
596               }
597             else
598               {
599                 chgts[i].src->swsData[chgts[i].bord].enPt = chgts[i].ptNo;
600               }
601           }
602         else if (chgts[i].type == 1)
603           {
604             if (chgts[i].src->getEdge(chgts[i].bord).st >
605                 chgts[i].src->getEdge(chgts[i].bord).en)
606               {
607                 chgts[i].src->swsData[chgts[i].bord].stPt = chgts[i].ptNo;
608               }
609             else
610               {
611                 chgts[i].src->swsData[chgts[i].bord].enPt = chgts[i].ptNo;
612               }
613           }
614       }
616     CheckAdjacencies (lastI, lastChgtPt, shapeHead, edgeHead);
618     CheckEdges (lastI, lastChgtPt, a, NULL, bool_op_union);
620     for (int i = lastChgtPt; i < lastI; i++)
621       {
622         if (pData[i].askForWindingS)
623           {
624             Shape *windS = pData[i].askForWindingS;
625             int windB = pData[i].askForWindingB;
626             pData[i].nextLinkedPoint = windS->swsData[windB].firstLinkedPoint;
627             windS->swsData[windB].firstLinkedPoint = i;
628           }
629       }
631     _pts.resize(lastI);
633     edgeHead = -1;
634     shapeHead = NULL;
635   }
637     chgts.clear();
639 //  Plot (98.0, 112.0, 8.0, 400.0, 400.0, true, true, true, true);
640 //      Plot(200.0,200.0,2.0,400.0,400.0,true,true,true,true);
642   //      AssemblePoints(a);
644 //      GetAdjacencies(a);
646 //      MakeAretes(a);
647     clearIncidenceData();
649   AssembleAretes (directed);
651 //  Plot (98.0, 112.0, 8.0, 400.0, 400.0, true, true, true, true);
653   for (int i = 0; i < numberOfPoints(); i++)
654     {
655       _pts[i].oldDegree = getPoint(i).totalDegree();
656     }
657 //      Validate();
659   _need_edges_sorting = true;
660   if ( directed == fill_justDont ) {
661     SortEdges();
662   } else {
663     GetWindings (a);
664   }
665 //  Plot (98.0, 112.0, 8.0, 400.0, 400.0, true, true, true, true);
666 //   if ( doDebug ) {
667 //   a->CalcBBox();
668 //     a->Plot(a->leftX,a->topY,32.0,0.0,0.0,true,true,true,true,"orig.svg");
669 //     Plot(a->leftX,a->topY,32.0,0.0,0.0,true,true,true,true,"winded.svg");
670 //   }
671   if (directed == fill_positive)
672   {
673     if (invert)
674     {
675       for (int i = 0; i < numberOfEdges(); i++)
676             {
677               if (swdData[i].leW < 0 && swdData[i].riW >= 0)
678         {
679           eData[i].weight = 1;
680         }
681               else if (swdData[i].leW >= 0 && swdData[i].riW < 0)
682         {
683           Inverse (i);
684           eData[i].weight = 1;
685         }
686               else
687         {
688           eData[i].weight = 0;
689           SubEdge (i);
690           i--;
691         }
692             }
693     }
694     else
695     {
696       for (int i = 0; i < numberOfEdges(); i++)
697             {
698               if (swdData[i].leW > 0 && swdData[i].riW <= 0)
699         {
700           eData[i].weight = 1;
701         }
702               else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
703         {
704           Inverse (i);
705           eData[i].weight = 1;
706         }
707               else
708         {
709            eData[i].weight = 0;
710           SubEdge (i);
711           i--;
712         }
713             }
714     }
715   }
716   else if (directed == fill_nonZero)
717   {
718     if (invert)
719     {
720       for (int i = 0; i < numberOfEdges(); i++)
721             {
722               if (swdData[i].leW < 0 && swdData[i].riW == 0)
723         {
724           eData[i].weight = 1;
725         }
726               else if (swdData[i].leW > 0 && swdData[i].riW == 0)
727         {
728           eData[i].weight = 1;
729         }
730               else if (swdData[i].leW == 0 && swdData[i].riW < 0)
731         {
732           Inverse (i);
733           eData[i].weight = 1;
734         }
735               else if (swdData[i].leW == 0 && swdData[i].riW > 0)
736         {
737           Inverse (i);
738           eData[i].weight = 1;
739         }
740               else
741         {
742           eData[i].weight = 0;
743           SubEdge (i);
744           i--;
745         }
746             }
747     }
748     else
749     {
750       for (int i = 0; i < numberOfEdges(); i++)
751             {
752               if (swdData[i].leW > 0 && swdData[i].riW == 0)
753         {
754           eData[i].weight = 1;
755         }
756               else if (swdData[i].leW < 0 && swdData[i].riW == 0)
757         {
758           eData[i].weight = 1;
759         }
760               else if (swdData[i].leW == 0 && swdData[i].riW > 0)
761         {
762           Inverse (i);
763           eData[i].weight = 1;
764         }
765               else if (swdData[i].leW == 0 && swdData[i].riW < 0)
766         {
767           Inverse (i);
768           eData[i].weight = 1;
769         }
770               else
771         {
772           eData[i].weight = 0;
773           SubEdge (i);
774           i--;
775         }
776             }
777     }
778   }
779   else if (directed == fill_oddEven)
780   {
781     for (int i = 0; i < numberOfEdges(); i++)
782     {
783       swdData[i].leW %= 2;
784       swdData[i].riW %= 2;
785       if (swdData[i].leW < 0)
786         swdData[i].leW = -swdData[i].leW;
787       if (swdData[i].riW < 0)
788         swdData[i].riW = -swdData[i].riW;
789       if (swdData[i].leW > 0 && swdData[i].riW <= 0)
790             {
791               eData[i].weight = 1;
792             }
793       else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
794             {
795               Inverse (i);
796               eData[i].weight = 1;
797             }
798       else
799             {
800               eData[i].weight = 0;
801               SubEdge (i);
802               i--;
803             }
804     }
805   } else if ( directed == fill_justDont ) {
806     for (int i=0;i<numberOfEdges();i++) {
807       if ( getEdge(i).st < 0 || getEdge(i).en < 0 ) {
808         SubEdge(i);
809         i--;
810       } else {
811               eData[i].weight = 0;
812       }
813     }
814   }
815   
816 //      Plot(200.0,200.0,2.0,400.0,400.0,true,true,true,true);
818   delete sTree;
819   sTree = NULL;
820   delete sEvts;
821   sEvts = NULL;
823   MakePointData (false);
824   MakeEdgeData (false);
825   MakeSweepSrcData (false);
826   MakeSweepDestData (false);
827   a->CleanupSweep ();
828   type = shape_polygon;
829   return 0;
832 // technically it's just a ConvertToShape() on 2 polygons at the same time, and different rules
833 // for choosing the edges according to their winding numbers.
834 // probably one of the biggest function i ever wrote.
835 int
836 Shape::Booleen (Shape * a, Shape * b, BooleanOp mod,int cutPathID)
838   if (a == b || a == NULL || b == NULL)
839     return shape_input_err;
840   Reset (0, 0);
841   if (a->numberOfPoints() <= 1 || a->numberOfEdges() <= 1)
842     return 0;
843   if (b->numberOfPoints() <= 1 || b->numberOfEdges() <= 1)
844     return 0;
845   if ( mod == bool_op_cut ) {
846   } else if ( mod == bool_op_slice ) {
847   } else {
848     if (a->type != shape_polygon)
849       return shape_input_err;
850     if (b->type != shape_polygon)
851       return shape_input_err;
852   }
854   a->ResetSweep ();
855   b->ResetSweep ();
857   if (sTree == NULL) {
858       sTree = new SweepTreeList(a->numberOfEdges() + b->numberOfEdges());
859   }
860   if (sEvts == NULL) {
861       sEvts = new SweepEventQueue(a->numberOfEdges() + b->numberOfEdges());
862   }
863   
864   MakePointData (true);
865   MakeEdgeData (true);
866   MakeSweepSrcData (true);
867   MakeSweepDestData (true);
868   if (a->hasBackData () && b->hasBackData ())
869     {
870       MakeBackData (true);
871     }
872   else
873     {
874       MakeBackData (false);
875     }
877   a->initialisePointData();
878   b->initialisePointData();
880   a->initialiseEdgeData();
881   b->initialiseEdgeData();
883   a->SortPointsRounded ();
884   b->SortPointsRounded ();
886   chgts.clear();
888   double lastChange =
889     (a->pData[0].rx[1] <
890      b->pData[0].rx[1]) ? a->pData[0].rx[1] - 1.0 : b->pData[0].rx[1] - 1.0;
891   int lastChgtPt = 0;
892   int edgeHead = -1;
893   Shape *shapeHead = NULL;
895   clearIncidenceData();
897   int curAPt = 0;
898   int curBPt = 0;
900   while (curAPt < a->numberOfPoints() || curBPt < b->numberOfPoints() || sEvts->size() > 0)
901     {
902 /*              for (int i=0;i<sEvts.nbEvt;i++) {
903                         printf("%f %f %i %i\n",sEvts.events[i].posx,sEvts.events[i].posy,sEvts.events[i].leftSweep->bord,sEvts.events[i].rightSweep->bord); // localizing ok
904                 }
905                 //              cout << endl;
906                 if ( sTree.racine ) {
907                         SweepTree*  ct=static_cast <SweepTree*> (sTree.racine->Leftmost());
908                         while ( ct ) {
909                                 printf("%i %i [%i\n",ct->bord,ct->startPoint,(ct->src==a)?1:0);
910                                 ct=static_cast <SweepTree*> (ct->elem[RIGHT]);
911                         }
912                 }
913                 printf("\n");*/
915     NR::Point ptX;
916       double ptL, ptR;
917       SweepTree *intersL = NULL;
918       SweepTree *intersR = NULL;
919       int nPt = -1;
920       Shape *ptSh = NULL;
921       bool isIntersection = false;
923       if (sEvts->peek(intersL, intersR, ptX, ptL, ptR))
924         {
925           if (curAPt < a->numberOfPoints())
926             {
927               if (curBPt < b->numberOfPoints())
928                 {
929                   if (a->pData[curAPt].rx[1] < b->pData[curBPt].rx[1]
930                       || (a->pData[curAPt].rx[1] == b->pData[curBPt].rx[1]
931                           && a->pData[curAPt].rx[0] < b->pData[curBPt].rx[0]))
932                     {
933                       if (a->pData[curAPt].pending > 0
934                           || (a->pData[curAPt].rx[1] > ptX[1]
935                               || (a->pData[curAPt].rx[1] == ptX[1]
936                                   && a->pData[curAPt].rx[0] > ptX[0])))
937                         {
938                           /* FIXME: could be pop? */
939                           sEvts->extract(intersL, intersR, ptX, ptL, ptR);
940                           isIntersection = true;
941                         }
942                       else
943                         {
944                           nPt = curAPt++;
945                           ptSh = a;
946                           ptX = ptSh->pData[nPt].rx;
947                           isIntersection = false;
948                         }
949                     }
950                   else
951                     {
952                       if (b->pData[curBPt].pending > 0
953                           || (b->pData[curBPt].rx[1] > ptX[1]
954                               || (b->pData[curBPt].rx[1] == ptX[1]
955                                   && b->pData[curBPt].rx[0] > ptX[0])))
956                         {
957                           /* FIXME: could be pop? */
958                           sEvts->extract(intersL, intersR, ptX, ptL, ptR);
959                           isIntersection = true;
960                         }
961                       else
962                         {
963                           nPt = curBPt++;
964                           ptSh = b;
965                           ptX = ptSh->pData[nPt].rx;
966                           isIntersection = false;
967                         }
968                     }
969                 }
970               else
971                 {
972                   if (a->pData[curAPt].pending > 0
973                       || (a->pData[curAPt].rx[1] > ptX[1]
974                           || (a->pData[curAPt].rx[1] == ptX[1]
975                               && a->pData[curAPt].rx[0] > ptX[0])))
976                     {
977                       /* FIXME: could be pop? */
978                       sEvts->extract(intersL, intersR, ptX, ptL, ptR);
979                       isIntersection = true;
980                     }
981                   else
982                     {
983                       nPt = curAPt++;
984                       ptSh = a;
985                       ptX = ptSh->pData[nPt].rx;
986                       isIntersection = false;
987                     }
988                 }
989             }
990           else
991             {
992               if (b->pData[curBPt].pending > 0
993                   || (b->pData[curBPt].rx[1] > ptX[1]
994                       || (b->pData[curBPt].rx[1] == ptX[1]
995                           && b->pData[curBPt].rx[0] > ptX[0])))
996                 {
997                   /* FIXME: could be pop? */
998                   sEvts->extract(intersL, intersR, ptX,  ptL, ptR);
999                   isIntersection = true;
1000                 }
1001               else
1002                 {
1003                   nPt = curBPt++;
1004                   ptSh = b;
1005                   ptX = ptSh->pData[nPt].rx;
1006                   isIntersection = false;
1007                 }
1008             }
1009         }
1010       else
1011         {
1012           if (curAPt < a->numberOfPoints())
1013             {
1014               if (curBPt < b->numberOfPoints())
1015                 {
1016                   if (a->pData[curAPt].rx[1] < b->pData[curBPt].rx[1]
1017                       || (a->pData[curAPt].rx[1] == b->pData[curBPt].rx[1]
1018                           && a->pData[curAPt].rx[0] < b->pData[curBPt].rx[0]))
1019                     {
1020                       nPt = curAPt++;
1021                       ptSh = a;
1022                     }
1023                   else
1024                     {
1025                       nPt = curBPt++;
1026                       ptSh = b;
1027                     }
1028                 }
1029               else
1030                 {
1031                   nPt = curAPt++;
1032                   ptSh = a;
1033                 }
1034             }
1035           else
1036             {
1037               nPt = curBPt++;
1038               ptSh = b;
1039             }
1040           ptX = ptSh->pData[nPt].rx;
1041           isIntersection = false;
1042         }
1044       if (isIntersection == false)
1045         {
1046           if (ptSh->getPoint(nPt).dI == 0 && ptSh->getPoint(nPt).dO == 0)
1047             continue;
1048         }
1050       NR::Point rPtX;
1051       rPtX[0]= Round (ptX[0]);
1052       rPtX[1]= Round (ptX[1]);
1053       int lastPointNo = -1;
1054       lastPointNo = AddPoint (rPtX);
1055       pData[lastPointNo].rx = rPtX;
1057       if (rPtX[1] > lastChange)
1058         {
1059           int lastI = AssemblePoints (lastChgtPt, lastPointNo);
1062           Shape *curSh = shapeHead;
1063           int curBo = edgeHead;
1064           while (curSh)
1065             {
1066               curSh->swsData[curBo].leftRnd =
1067                 pData[curSh->swsData[curBo].leftRnd].newInd;
1068               curSh->swsData[curBo].rightRnd =
1069                 pData[curSh->swsData[curBo].rightRnd].newInd;
1071               Shape *neSh = curSh->swsData[curBo].nextSh;
1072               curBo = curSh->swsData[curBo].nextBo;
1073               curSh = neSh;
1074             }
1076           for (unsigned int i = 0; i < chgts.size(); i++)
1077             {
1078               chgts[i].ptNo = pData[chgts[i].ptNo].newInd;
1079               if (chgts[i].type == 0)
1080                 {
1081                   if (chgts[i].src->getEdge(chgts[i].bord).st <
1082                       chgts[i].src->getEdge(chgts[i].bord).en)
1083                     {
1084                       chgts[i].src->swsData[chgts[i].bord].stPt =
1085                         chgts[i].ptNo;
1086                     }
1087                   else
1088                     {
1089                       chgts[i].src->swsData[chgts[i].bord].enPt =
1090                         chgts[i].ptNo;
1091                     }
1092                 }
1093               else if (chgts[i].type == 1)
1094                 {
1095                   if (chgts[i].src->getEdge(chgts[i].bord).st >
1096                       chgts[i].src->getEdge(chgts[i].bord).en)
1097                     {
1098                       chgts[i].src->swsData[chgts[i].bord].stPt =
1099                         chgts[i].ptNo;
1100                     }
1101                   else
1102                     {
1103                       chgts[i].src->swsData[chgts[i].bord].enPt =
1104                         chgts[i].ptNo;
1105                     }
1106                 }
1107             }
1109           CheckAdjacencies (lastI, lastChgtPt, shapeHead, edgeHead);
1111           CheckEdges (lastI, lastChgtPt, a, b, mod);
1113           for (int i = lastChgtPt; i < lastI; i++)
1114             {
1115               if (pData[i].askForWindingS)
1116                 {
1117                   Shape *windS = pData[i].askForWindingS;
1118                   int windB = pData[i].askForWindingB;
1119                   pData[i].nextLinkedPoint =
1120                     windS->swsData[windB].firstLinkedPoint;
1121                   windS->swsData[windB].firstLinkedPoint = i;
1122                 }
1123             }
1125     if (lastI < lastPointNo)
1126             {
1127               _pts[lastI] = getPoint(lastPointNo);
1128               pData[lastI] = pData[lastPointNo];
1129             }
1130           lastPointNo = lastI;
1131           _pts.resize(lastI + 1);
1133           lastChgtPt = lastPointNo;
1134           lastChange = rPtX[1];
1135           chgts.clear();
1136           edgeHead = -1;
1137           shapeHead = NULL;
1138         }
1141       if (isIntersection)
1142         {
1143           // les 2 events de part et d'autre de l'intersection
1144           // (celui de l'intersection a deja ete depile)
1145           intersL->RemoveEvent (*sEvts, LEFT);
1146           intersR->RemoveEvent (*sEvts, RIGHT);
1148           AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, INTERSECTION,
1149                    intersL->src, intersL->bord, intersR->src, intersR->bord);
1151           intersL->SwapWithRight (*sTree, *sEvts);
1153           TesteIntersection (intersL, LEFT, true);
1154           TesteIntersection (intersR, RIGHT, true);
1155         }
1156       else
1157         {
1158           int cb;
1160           int nbUp = 0, nbDn = 0;
1161           int upNo = -1, dnNo = -1;
1162           cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
1163           while (cb >= 0 && cb < ptSh->numberOfEdges())
1164             {
1165               if ((ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
1166                    && nPt == ptSh->getEdge(cb).en)
1167                   || (ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
1168                       && nPt == ptSh->getEdge(cb).st))
1169                 {
1170                   upNo = cb;
1171                   nbUp++;
1172                 }
1173               if ((ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
1174                    && nPt == ptSh->getEdge(cb).en)
1175                   || (ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
1176                       && nPt == ptSh->getEdge(cb).st))
1177                 {
1178                   dnNo = cb;
1179                   nbDn++;
1180                 }
1181               cb = ptSh->NextAt (nPt, cb);
1182             }
1184           if (nbDn <= 0)
1185             {
1186               upNo = -1;
1187             }
1188           if (upNo >= 0 && (SweepTree *) ptSh->swsData[upNo].misc == NULL)
1189             {
1190               upNo = -1;
1191             }
1193 //                      upNo=-1;
1195           bool doWinding = true;
1197           if (nbUp > 0)
1198             {
1199               cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
1200               while (cb >= 0 && cb < ptSh->numberOfEdges())
1201                 {
1202                   if ((ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
1203                        && nPt == ptSh->getEdge(cb).en)
1204                       || (ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
1205                           && nPt == ptSh->getEdge(cb).st))
1206                     {
1207                       if (cb != upNo)
1208                         {
1209                           SweepTree *node =
1210                             (SweepTree *) ptSh->swsData[cb].misc;
1211                           if (node == NULL)
1212                             {
1213                             }
1214                           else
1215                             {
1216                               AddChgt (lastPointNo, lastChgtPt, shapeHead,
1217                                        edgeHead, EDGE_REMOVED, node->src, node->bord,
1218                                        NULL, -1);
1219                               ptSh->swsData[cb].misc = NULL;
1221                               int onLeftB = -1, onRightB = -1;
1222                               Shape *onLeftS = NULL;
1223                               Shape *onRightS = NULL;
1224                               if (node->elem[LEFT])
1225                                 {
1226                                   onLeftB =
1227                                     (static_cast <
1228                                      SweepTree * >(node->elem[LEFT]))->bord;
1229                                   onLeftS =
1230                                     (static_cast <
1231                                      SweepTree * >(node->elem[LEFT]))->src;
1232                                 }
1233                               if (node->elem[RIGHT])
1234                                 {
1235                                   onRightB =
1236                                     (static_cast <
1237                                      SweepTree * >(node->elem[RIGHT]))->bord;
1238                                   onRightS =
1239                                     (static_cast <
1240                                      SweepTree * >(node->elem[RIGHT]))->src;
1241                                 }
1243                               node->Remove (*sTree, *sEvts, true);
1244                               if (onLeftS && onRightS)
1245                                 {
1246                                   SweepTree *onLeft =
1247                                     (SweepTree *) onLeftS->swsData[onLeftB].
1248                                     misc;
1249 //                                                                      SweepTree* onRight=(SweepTree*)onRightS->swsData[onRightB].misc;
1250                                   if (onLeftS == ptSh
1251                                       && (onLeftS->getEdge(onLeftB).en == nPt
1252                                           || onLeftS->getEdge(onLeftB).st ==
1253                                           nPt))
1254                                     {
1255                                     }
1256                                   else
1257                                     {
1258                                       if (onRightS == ptSh
1259                                           && (onRightS->getEdge(onRightB).en ==
1260                                               nPt
1261                                               || onRightS->getEdge(onRightB).
1262                                               st == nPt))
1263                                         {
1264                                         }
1265                                       else
1266                                         {
1267                                           TesteIntersection (onLeft, RIGHT, true);
1268                                         }
1269                                     }
1270                                 }
1271                             }
1272                         }
1273                     }
1274                   cb = ptSh->NextAt (nPt, cb);
1275                 }
1276             }
1278           // traitement du "upNo devient dnNo"
1279           SweepTree *insertionNode = NULL;
1280           if (dnNo >= 0)
1281             {
1282               if (upNo >= 0)
1283                 {
1284                   SweepTree *node = (SweepTree *) ptSh->swsData[upNo].misc;
1286                   AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_REMOVED,
1287                            node->src, node->bord, NULL, -1);
1289                   ptSh->swsData[upNo].misc = NULL;
1291                   node->RemoveEvents (*sEvts);
1292                   node->ConvertTo (ptSh, dnNo, 1, lastPointNo);
1293                   ptSh->swsData[dnNo].misc = node;
1294                   TesteIntersection (node, RIGHT, true);
1295                   TesteIntersection (node, LEFT, true);
1296                   insertionNode = node;
1298                   ptSh->swsData[dnNo].curPoint = lastPointNo;
1300                   AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_INSERTED,
1301                            node->src, node->bord, NULL, -1);
1302                 }
1303               else
1304                 {
1305                   SweepTree *node = sTree->add(ptSh, dnNo, 1, lastPointNo, this);
1306                   ptSh->swsData[dnNo].misc = node;
1307                   node->Insert (*sTree, *sEvts, this, lastPointNo, true);
1309                   if (doWinding)
1310                     {
1311                       SweepTree *myLeft =
1312                         static_cast < SweepTree * >(node->elem[LEFT]);
1313                       if (myLeft)
1314                         {
1315                           pData[lastPointNo].askForWindingS = myLeft->src;
1316                           pData[lastPointNo].askForWindingB = myLeft->bord;
1317                         }
1318                       else
1319                         {
1320                           pData[lastPointNo].askForWindingB = -1;
1321                         }
1322                       doWinding = false;
1323                     }
1325                   TesteIntersection (node, RIGHT, true);
1326                   TesteIntersection (node, LEFT, true);
1327                   insertionNode = node;
1329                   ptSh->swsData[dnNo].curPoint = lastPointNo;
1331                   AddChgt (lastPointNo, lastChgtPt, shapeHead, edgeHead, EDGE_INSERTED,
1332                            node->src, node->bord, NULL, -1);
1333                 }
1334             }
1336           if (nbDn > 1)
1337             {                   // si nbDn == 1 , alors dnNo a deja ete traite
1338               cb = ptSh->getPoint(nPt).incidentEdge[FIRST];
1339               while (cb >= 0 && cb < ptSh->numberOfEdges())
1340                 {
1341                   if ((ptSh->getEdge(cb).st > ptSh->getEdge(cb).en
1342                        && nPt == ptSh->getEdge(cb).en)
1343                       || (ptSh->getEdge(cb).st < ptSh->getEdge(cb).en
1344                           && nPt == ptSh->getEdge(cb).st))
1345                     {
1346                       if (cb != dnNo)
1347                         {
1348                           SweepTree *node = sTree->add(ptSh, cb, 1, lastPointNo, this);
1349                           ptSh->swsData[cb].misc = node;
1350 //                                                      node->Insert(sTree,*sEvts,this,lastPointNo,true);
1351                           node->InsertAt (*sTree, *sEvts, this, insertionNode,
1352                                           nPt, true);
1354                           if (doWinding)
1355                             {
1356                               SweepTree *myLeft =
1357                                 static_cast < SweepTree * >(node->elem[LEFT]);
1358                               if (myLeft)
1359                                 {
1360                                   pData[lastPointNo].askForWindingS =
1361                                     myLeft->src;
1362                                   pData[lastPointNo].askForWindingB =
1363                                     myLeft->bord;
1364                                 }
1365                               else
1366                                 {
1367                                   pData[lastPointNo].askForWindingB = -1;
1368                                 }
1369                               doWinding = false;
1370                             }
1372                           TesteIntersection (node, RIGHT, true);
1373                           TesteIntersection (node, LEFT, true);
1375                           ptSh->swsData[cb].curPoint = lastPointNo;
1377                           AddChgt (lastPointNo, lastChgtPt, shapeHead,
1378                                    edgeHead, EDGE_INSERTED, node->src, node->bord, NULL,
1379                                    -1);
1380                         }
1381                     }
1382                   cb = ptSh->NextAt (nPt, cb);
1383                 }
1384             }
1385         }
1386     }
1387   {
1388     int lastI = AssemblePoints (lastChgtPt, numberOfPoints());
1391     Shape *curSh = shapeHead;
1392     int curBo = edgeHead;
1393     while (curSh)
1394       {
1395         curSh->swsData[curBo].leftRnd =
1396           pData[curSh->swsData[curBo].leftRnd].newInd;
1397         curSh->swsData[curBo].rightRnd =
1398           pData[curSh->swsData[curBo].rightRnd].newInd;
1400         Shape *neSh = curSh->swsData[curBo].nextSh;
1401         curBo = curSh->swsData[curBo].nextBo;
1402         curSh = neSh;
1403       }
1405     /* FIXME: this kind of code seems to appear frequently */
1406     for (unsigned int i = 0; i < chgts.size(); i++)
1407       {
1408         chgts[i].ptNo = pData[chgts[i].ptNo].newInd;
1409         if (chgts[i].type == 0)
1410           {
1411             if (chgts[i].src->getEdge(chgts[i].bord).st <
1412                 chgts[i].src->getEdge(chgts[i].bord).en)
1413               {
1414                 chgts[i].src->swsData[chgts[i].bord].stPt = chgts[i].ptNo;
1415               }
1416             else
1417               {
1418                 chgts[i].src->swsData[chgts[i].bord].enPt = chgts[i].ptNo;
1419               }
1420           }
1421         else if (chgts[i].type == 1)
1422           {
1423             if (chgts[i].src->getEdge(chgts[i].bord).st >
1424                 chgts[i].src->getEdge(chgts[i].bord).en)
1425               {
1426                 chgts[i].src->swsData[chgts[i].bord].stPt = chgts[i].ptNo;
1427               }
1428             else
1429               {
1430                 chgts[i].src->swsData[chgts[i].bord].enPt = chgts[i].ptNo;
1431               }
1432           }
1433       }
1435     CheckAdjacencies (lastI, lastChgtPt, shapeHead, edgeHead);
1437     CheckEdges (lastI, lastChgtPt, a, b, mod);
1439     for (int i = lastChgtPt; i < lastI; i++)
1440       {
1441         if (pData[i].askForWindingS)
1442           {
1443             Shape *windS = pData[i].askForWindingS;
1444             int windB = pData[i].askForWindingB;
1445             pData[i].nextLinkedPoint = windS->swsData[windB].firstLinkedPoint;
1446             windS->swsData[windB].firstLinkedPoint = i;
1447           }
1448       }
1450     _pts.resize(lastI);
1452     edgeHead = -1;
1453     shapeHead = NULL;
1454   }
1456   chgts.clear();
1457   clearIncidenceData();
1459 //      Plot(190,70,6,400,400,true,false,true,true);
1461   if ( mod == bool_op_cut ) {
1462     AssembleAretes (fill_justDont);
1463     // dupliquer les aretes de la coupure
1464     int i=numberOfEdges()-1;
1465     for (;i>=0;i--) {
1466       if ( ebData[i].pathID == cutPathID ) {
1467         // on duplique
1468         int nEd=AddEdge(getEdge(i).en,getEdge(i).st);
1469         ebData[nEd].pathID=cutPathID;
1470         ebData[nEd].pieceID=ebData[i].pieceID;
1471         ebData[nEd].tSt=ebData[i].tEn;
1472         ebData[nEd].tEn=ebData[i].tSt;
1473         eData[nEd].weight=eData[i].weight;
1474         // lui donner les firstlinkedpoitn si besoin
1475         if ( getEdge(i).en >= getEdge(i).st ) {
1476           int cp = swsData[i].firstLinkedPoint;
1477           while (cp >= 0) {
1478             pData[cp].askForWindingB = nEd;
1479             cp = pData[cp].nextLinkedPoint;
1480           }
1481           swsData[nEd].firstLinkedPoint = swsData[i].firstLinkedPoint;
1482           swsData[i].firstLinkedPoint=-1;
1483         }
1484       }
1485     }
1486   } else if ( mod == bool_op_slice ) {
1487   } else {
1488     AssembleAretes ();
1489   }
1490   
1491   for (int i = 0; i < numberOfPoints(); i++)
1492     {
1493       _pts[i].oldDegree = getPoint(i).totalDegree();
1494     }
1496   _need_edges_sorting = true;
1497   if ( mod == bool_op_slice ) {
1498   } else {
1499     GetWindings (a, b, mod, false);
1500   }
1501 //      Plot(190,70,6,400,400,true,true,true,true);
1503   if (mod == bool_op_symdiff)
1504   {
1505     for (int i = 0; i < numberOfEdges(); i++)
1506     {
1507       swdData[i].leW = swdData[i].leW % 2;
1508       if (swdData[i].leW < 0)
1509         swdData[i].leW = -swdData[i].leW;
1510       swdData[i].riW = swdData[i].riW;
1511       if (swdData[i].riW < 0)
1512         swdData[i].riW = -swdData[i].riW;
1513       
1514       if (swdData[i].leW > 0 && swdData[i].riW <= 0)
1515             {
1516               eData[i].weight = 1;
1517             }
1518       else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
1519             {
1520               Inverse (i);
1521               eData[i].weight = 1;
1522             }
1523       else
1524             {
1525               eData[i].weight = 0;
1526               SubEdge (i);
1527               i--;
1528             }
1529     }
1530   }
1531   else if (mod == bool_op_union || mod == bool_op_diff)
1532   {
1533     for (int i = 0; i < numberOfEdges(); i++)
1534     {
1535       if (swdData[i].leW > 0 && swdData[i].riW <= 0)
1536             {
1537               eData[i].weight = 1;
1538             }
1539       else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
1540             {
1541               Inverse (i);
1542               eData[i].weight = 1;
1543             }
1544       else
1545             {
1546               eData[i].weight = 0;
1547               SubEdge (i);
1548               i--;
1549             }
1550     }
1551   }
1552   else if (mod == bool_op_inters)
1553   {
1554     for (int i = 0; i < numberOfEdges(); i++)
1555     {
1556       if (swdData[i].leW > 1 && swdData[i].riW <= 1)
1557             {
1558               eData[i].weight = 1;
1559             }
1560       else if (swdData[i].leW <= 1 && swdData[i].riW > 1)
1561             {
1562               Inverse (i);
1563               eData[i].weight = 1;
1564             }
1565       else
1566             {
1567               eData[i].weight = 0;
1568               SubEdge (i);
1569               i--;
1570             }
1571     }
1572   } else if ( mod == bool_op_cut ) {
1573     // inverser les aretes de la coupe au besoin
1574     for (int i=0;i<numberOfEdges();i++) {
1575       if ( getEdge(i).st < 0 || getEdge(i).en < 0 ) {
1576         if ( i < numberOfEdges()-1 ) {
1577           // decaler les askForWinding
1578           int cp = swsData[numberOfEdges()-1].firstLinkedPoint;
1579           while (cp >= 0) {
1580             pData[cp].askForWindingB = i;
1581             cp = pData[cp].nextLinkedPoint;
1582           }
1583         }
1584         SwapEdges(i,numberOfEdges()-1);
1585         SubEdge(numberOfEdges()-1);
1586 //        SubEdge(i);
1587         i--;
1588       } else if ( ebData[i].pathID == cutPathID ) {
1589         swdData[i].leW=swdData[i].leW%2;
1590         swdData[i].riW=swdData[i].riW%2;
1591         if ( swdData[i].leW < swdData[i].riW ) {
1592           Inverse(i);
1593         }
1594       }
1595     }
1596   } else if ( mod == bool_op_slice ) {
1597     // supprimer les aretes de la coupe
1598     int i=numberOfEdges()-1;
1599     for (;i>=0;i--) {
1600       if ( ebData[i].pathID == cutPathID || getEdge(i).st < 0 || getEdge(i).en < 0 ) {
1601         SubEdge(i);
1602       }
1603     }
1604   }
1605   else
1606   {
1607     for (int i = 0; i < numberOfEdges(); i++)
1608     {
1609       if (swdData[i].leW > 0 && swdData[i].riW <= 0)
1610             {
1611               eData[i].weight = 1;
1612             }
1613       else if (swdData[i].leW <= 0 && swdData[i].riW > 0)
1614             {
1615               Inverse (i);
1616               eData[i].weight = 1;
1617             }
1618       else
1619             {
1620               eData[i].weight = 0;
1621               SubEdge (i);
1622               i--;
1623             }
1624     }
1625   }
1626   
1627   delete sTree;
1628   sTree = NULL;
1629   delete sEvts;
1630   sEvts = NULL;
1631   
1632   if ( mod == bool_op_cut ) {
1633     // on garde le askForWinding
1634   } else {
1635     MakePointData (false);
1636   }
1637   MakeEdgeData (false);
1638   MakeSweepSrcData (false);
1639   MakeSweepDestData (false);
1640   a->CleanupSweep ();
1641   b->CleanupSweep ();
1643   if (directedEulerian(this) == false)
1644     {
1645 //              printf( "pas euclidian2");
1646       _pts.clear();
1647       _aretes.clear();
1648       return shape_euler_err;
1649     }
1650   type = shape_polygon;
1651   return 0;
1654 // frontend to the TesteIntersection() below
1655 void Shape::TesteIntersection(SweepTree *t, Side s, bool onlyDiff)
1657     SweepTree *tt = static_cast<SweepTree*>(t->elem[s]);
1658     if (tt == NULL) {
1659         return;
1660     }
1662     SweepTree *a = (s == LEFT) ? tt : t;
1663     SweepTree *b = (s == LEFT) ? t : tt;
1665     NR::Point atx;
1666     double atl;
1667     double atr;
1668     if (TesteIntersection(a, b, atx, atl, atr, onlyDiff)) {
1669         sEvts->add(a, b, atx, atl, atr);
1670     }
1673 // a crucial piece of code: computing intersections between segments
1674 bool
1675 Shape::TesteIntersection (SweepTree * iL, SweepTree * iR, NR::Point &atx, double &atL, double &atR, bool onlyDiff)
1677   int lSt = iL->src->getEdge(iL->bord).st, lEn = iL->src->getEdge(iL->bord).en;
1678   int rSt = iR->src->getEdge(iR->bord).st, rEn = iR->src->getEdge(iR->bord).en;
1679   NR::Point ldir, rdir;
1680   ldir = iL->src->eData[iL->bord].rdx;
1681   rdir = iR->src->eData[iR->bord].rdx;
1682   // first, a round of checks to quickly dismiss edge which obviously dont intersect,
1683   // such as having disjoint bounding boxes
1684   if (lSt < lEn)
1685     {
1686     }
1687   else
1688     {
1689       int swap = lSt;
1690       lSt = lEn;
1691       lEn = swap;
1692       ldir = -ldir;
1693     }
1694   if (rSt < rEn)
1695     {
1696     }
1697   else
1698     {
1699       int swap = rSt;
1700       rSt = rEn;
1701       rEn = swap;
1702       rdir = -rdir;
1703     }
1705   if (iL->src->pData[lSt].rx[0] < iL->src->pData[lEn].rx[0])
1706     {
1707       if (iR->src->pData[rSt].rx[0] < iR->src->pData[rEn].rx[0])
1708         {
1709           if (iL->src->pData[lSt].rx[0] > iR->src->pData[rEn].rx[0])
1710             return false;
1711           if (iL->src->pData[lEn].rx[0] < iR->src->pData[rSt].rx[0])
1712             return false;
1713         }
1714       else
1715         {
1716           if (iL->src->pData[lSt].rx[0] > iR->src->pData[rSt].rx[0])
1717             return false;
1718           if (iL->src->pData[lEn].rx[0] < iR->src->pData[rEn].rx[0])
1719             return false;
1720         }
1721     }
1722   else
1723     {
1724       if (iR->src->pData[rSt].rx[0] < iR->src->pData[rEn].rx[0])
1725         {
1726           if (iL->src->pData[lEn].rx[0] > iR->src->pData[rEn].rx[0])
1727             return false;
1728           if (iL->src->pData[lSt].rx[0] < iR->src->pData[rSt].rx[0])
1729             return false;
1730         }
1731       else
1732         {
1733           if (iL->src->pData[lEn].rx[0] > iR->src->pData[rSt].rx[0])
1734             return false;
1735           if (iL->src->pData[lSt].rx[0] < iR->src->pData[rEn].rx[0])
1736             return false;
1737         }
1738     }
1740   double ang = cross (rdir, ldir);
1741 //      ang*=iL->src->eData[iL->bord].isqlength;
1742 //      ang*=iR->src->eData[iR->bord].isqlength;
1743   if (ang <= 0) return false;           // edges in opposite directions:  <-left  ... right ->
1744                                 // they can't intersect
1746   // d'abord tester les bords qui partent d'un meme point
1747   if (iL->src == iR->src && lSt == rSt)
1748     {
1749       if (iL->src == iR->src && lEn == rEn)
1750         return false;           // c'est juste un doublon
1751       atx = iL->src->pData[lSt].rx;
1752       atR = atL = -1;
1753       return true;              // l'ordre est mauvais
1754     }
1755   if (iL->src == iR->src && lEn == rEn)
1756     return false;               // rien a faire=ils vont terminer au meme endroit
1758   // tester si on est dans une intersection multiple
1760   if (onlyDiff && iL->src == iR->src)
1761     return false;
1763   // on reprend les vrais points
1764   lSt = iL->src->getEdge(iL->bord).st;
1765   lEn = iL->src->getEdge(iL->bord).en;
1766   rSt = iR->src->getEdge(iR->bord).st;
1767   rEn = iR->src->getEdge(iR->bord).en;
1769   // compute intersection (if there is one)
1770   // Boissonat anr Preparata said in one paper that double precision floats were sufficient for get single precision
1771   // coordinates for the intersection, if the endpoints are single precision. i hope they're right...
1772   {
1773     NR::Point sDiff, eDiff;
1774     double slDot, elDot;
1775     double srDot, erDot;
1776     sDiff = iL->src->pData[lSt].rx - iR->src->pData[rSt].rx;
1777     eDiff = iL->src->pData[lEn].rx - iR->src->pData[rSt].rx;
1778     srDot = cross (sDiff,rdir);
1779     erDot = cross (eDiff,rdir);
1780     sDiff = iR->src->pData[rSt].rx - iL->src->pData[lSt].rx;
1781     eDiff = iR->src->pData[rEn].rx - iL->src->pData[lSt].rx;
1782     slDot = cross (sDiff,ldir);
1783     elDot = cross (eDiff,ldir);
1785     if ((srDot >= 0 && erDot >= 0) || (srDot <= 0 && erDot <= 0))
1786       {
1787         if (srDot == 0)
1788           {
1789             if (lSt < lEn)
1790               {
1791                 atx = iL->src->pData[lSt].rx;
1792                 atL = 0;
1793                 atR = slDot / (slDot - elDot);
1794                 return true;
1795               }
1796             else
1797               {
1798                 return false;
1799               }
1800           }
1801         else if (erDot == 0)
1802           {
1803             if (lSt > lEn)
1804               {
1805                 atx = iL->src->pData[lEn].rx;
1806                 atL = 1;
1807                 atR = slDot / (slDot - elDot);
1808                 return true;
1809               }
1810             else
1811               {
1812                 return false;
1813               }
1814           }
1815         if (srDot > 0 && erDot > 0)
1816           {
1817             if (rEn < rSt)
1818               {
1819                 if (srDot < erDot)
1820                   {
1821                     if (lSt < lEn)
1822                       {
1823                         atx = iL->src->pData[lSt].rx;
1824                         atL = 0;
1825                         atR = slDot / (slDot - elDot);
1826                         return true;
1827                       }
1828                   }
1829                 else
1830                   {
1831                     if (lEn < lSt)
1832                       {
1833                         atx = iL->src->pData[lEn].rx;
1834                         atL = 1;
1835                         atR = slDot / (slDot - elDot);
1836                         return true;
1837                       }
1838                   }
1839               }
1840           }
1841         if (srDot < 0 && erDot < 0)
1842           {
1843             if (rEn > rSt)
1844               {
1845                 if (srDot > erDot)
1846                   {
1847                     if (lSt < lEn)
1848                       {
1849                         atx = iL->src->pData[lSt].rx;
1850                         atL = 0;
1851                         atR = slDot / (slDot - elDot);
1852                         return true;
1853                       }
1854                   }
1855                 else
1856                   {
1857                     if (lEn < lSt)
1858                       {
1859                         atx = iL->src->pData[lEn].rx;
1860                         atL = 1;
1861                         atR = slDot / (slDot - elDot);
1862                         return true;
1863                       }
1864                   }
1865               }
1866           }
1867         return false;
1868       }
1869     if ((slDot >= 0 && elDot >= 0) || (slDot <= 0 && elDot <= 0))
1870       {
1871         if (slDot == 0)
1872           {
1873             if (rSt < rEn)
1874               {
1875                 atx = iR->src->pData[rSt].rx;
1876                 atR = 0;
1877                 atL = srDot / (srDot - erDot);
1878                 return true;
1879               }
1880             else
1881               {
1882                 return false;
1883               }
1884           }
1885         else if (elDot == 0)
1886           {
1887             if (rSt > rEn)
1888               {
1889                 atx = iR->src->pData[rEn].rx;
1890                 atR = 1;
1891                 atL = srDot / (srDot - erDot);
1892                 return true;
1893               }
1894             else
1895               {
1896                 return false;
1897               }
1898           }
1899         if (slDot > 0 && elDot > 0)
1900           {
1901             if (lEn > lSt)
1902               {
1903                 if (slDot < elDot)
1904                   {
1905                     if (rSt < rEn)
1906                       {
1907                         atx = iR->src->pData[rSt].rx;
1908                         atR = 0;
1909                         atL = srDot / (srDot - erDot);
1910                         return true;
1911                       }
1912                   }
1913                 else
1914                   {
1915                     if (rEn < rSt)
1916                       {
1917                         atx = iR->src->pData[rEn].rx;
1918                         atR = 1;
1919                         atL = srDot / (srDot - erDot);
1920                         return true;
1921                       }
1922                   }
1923               }
1924           }
1925         if (slDot < 0 && elDot < 0)
1926           {
1927             if (lEn < lSt)
1928               {
1929                 if (slDot > elDot)
1930                   {
1931                     if (rSt < rEn)
1932                       {
1933                         atx = iR->src->pData[rSt].rx;
1934                         atR = 0;
1935                         atL = srDot / (srDot - erDot);
1936                         return true;
1937                       }
1938                   }
1939                 else
1940                   {
1941                     if (rEn < rSt)
1942                       {
1943                         atx = iR->src->pData[rEn].rx;
1944                         atR = 1;
1945                         atL = srDot / (srDot - erDot);
1946                         return true;
1947                       }
1948                   }
1949               }
1950           }
1951         return false;
1952       }
1954 /*              double  slb=slDot-elDot,srb=srDot-erDot;
1955                 if ( slb < 0 ) slb=-slb;
1956                 if ( srb < 0 ) srb=-srb;*/
1957     if (iL->src->eData[iL->bord].siEd > iR->src->eData[iR->bord].siEd)
1958       {
1959         atx =
1960           (slDot * iR->src->pData[rEn].rx -
1961            elDot * iR->src->pData[rSt].rx) / (slDot - elDot);
1962       }
1963     else
1964       {
1965         atx =
1966           (srDot * iL->src->pData[lEn].rx -
1967            erDot * iL->src->pData[lSt].rx) / (srDot - erDot);
1968       }
1969     atL = srDot / (srDot - erDot);
1970     atR = slDot / (slDot - elDot);
1971     return true;
1972   }
1974   return true;
1977 int
1978 Shape::PushIncidence (Shape * a, int cb, int pt, double theta)
1980   if (theta < 0 || theta > 1)
1981     return -1;
1983   if (nbInc >= maxInc)
1984     {
1985       maxInc = 2 * nbInc + 1;
1986       iData =
1987         (incidenceData *) g_realloc(iData, maxInc * sizeof (incidenceData));
1988     }
1989   int n = nbInc++;
1990   iData[n].nextInc = a->swsData[cb].firstLinkedPoint;
1991   iData[n].pt = pt;
1992   iData[n].theta = theta;
1993   a->swsData[cb].firstLinkedPoint = n;
1994   return n;
1997 int
1998 Shape::CreateIncidence (Shape * a, int no, int nPt)
2000   NR::Point adir, diff;
2001   adir = a->eData[no].rdx;
2002   diff = getPoint(nPt).x - a->pData[a->getEdge(no).st].rx;
2003   double t = dot (diff, adir);
2004   t *= a->eData[no].ilength;
2005   return PushIncidence (a, no, nPt, t);
2008 int
2009 Shape::Winding (int nPt) const 
2011   int askTo = pData[nPt].askForWindingB;
2012   if (askTo < 0 || askTo >= numberOfEdges())
2013     return 0;
2014   if (getEdge(askTo).st < getEdge(askTo).en)
2015     {
2016       return swdData[askTo].leW;
2017     }
2018   else
2019     {
2020       return swdData[askTo].riW;
2021     }
2022   return 0;
2025 int
2026 Shape::Winding (const NR::Point px) const 
2028   int lr = 0, ll = 0, rr = 0;
2030   for (int i = 0; i < numberOfEdges(); i++)
2031     {
2032       NR::Point adir, diff, ast, aen;
2033       adir = eData[i].rdx;
2035       ast = pData[getEdge(i).st].rx;
2036       aen = pData[getEdge(i).en].rx;
2038       int nWeight = eData[i].weight;
2040       if (ast[0] < aen[0])
2041         {
2042           if (ast[0] > px[0])
2043             continue;
2044           if (aen[0] < px[0])
2045             continue;
2046         }
2047       else
2048         {
2049           if (ast[0] < px[0])
2050             continue;
2051           if (aen[0] > px[0])
2052             continue;
2053         }
2054       if (ast[0] == px[0])
2055         {
2056           if (ast[1] >= px[1])
2057             continue;
2058           if (aen[0] == px[0])
2059             continue;
2060           if (aen[0] < px[0])
2061             ll += nWeight;
2062           else
2063             rr -= nWeight;
2064           continue;
2065         }
2066       if (aen[0] == px[0])
2067         {
2068           if (aen[1] >= px[1])
2069             continue;
2070           if (ast[0] == px[0])
2071             continue;
2072           if (ast[0] < px[0])
2073             ll -= nWeight;
2074           else
2075             rr += nWeight;
2076           continue;
2077         }
2079       if (ast[1] < aen[1])
2080         {
2081           if (ast[1] >= px[1])
2082             continue;
2083         }
2084       else
2085         {
2086           if (aen[1] >= px[1])
2087             continue;
2088         }
2090       diff = px - ast;
2091       double cote = cross (diff,adir);
2092       if (cote == 0)
2093         continue;
2094       if (cote < 0)
2095         {
2096           if (ast[0] > px[0])
2097             lr += nWeight;
2098         }
2099       else
2100         {
2101           if (ast[0] < px[0])
2102             lr -= nWeight;
2103         }
2104     }
2105   return lr + (ll + rr) / 2;
2108 // merging duplicate points and edges
2109 int
2110 Shape::AssemblePoints (int st, int en)
2112   if (en > st) {
2113    for (int i = st; i < en; i++) pData[i].oldInd = i;
2114 //              SortPoints(st,en-1);
2115     SortPointsByOldInd (st, en - 1); // SortPointsByOldInd() is required here, because of the edges we have
2116                                        // associated with the point for later computation of winding numbers.
2117                                        // specifically, we need the first point we treated, it's the only one with a valid
2118                                        // associated edge (man, that was a nice bug).
2119      for (int i = st; i < en; i++) pData[pData[i].oldInd].newInd = i;
2121      int lastI = st;
2122      for (int i = st; i < en; i++) {
2123               pData[i].pending = lastI++;
2124               if (i > st && getPoint(i - 1).x[0] == getPoint(i).x[0] && getPoint(i - 1).x[1] == getPoint(i).x[1]) {
2125                 pData[i].pending = pData[i - 1].pending;
2126                 if (pData[pData[i].pending].askForWindingS == NULL) {
2127                         pData[pData[i].pending].askForWindingS = pData[i].askForWindingS;
2128                         pData[pData[i].pending].askForWindingB = pData[i].askForWindingB;
2129                       } else {
2130                         if (pData[pData[i].pending].askForWindingS == pData[i].askForWindingS
2131                       && pData[pData[i].pending].askForWindingB == pData[i].askForWindingB) {
2132                       // meme bord, c bon
2133                         } else {
2134                       // meme point, mais pas le meme bord: ouille!
2135                       // il faut prendre le bord le plus a gauche
2136                       // en pratique, n'arrive que si 2 maxima sont dans la meme case -> le mauvais choix prend une arete incidente 
2137                       // au bon choix
2138 //                                              printf("doh");
2139                         }
2140                       }
2141                 lastI--;
2142               } else {
2143                 if (i > pData[i].pending) {
2144                         _pts[pData[i].pending].x = getPoint(i).x;
2145                         pData[pData[i].pending].rx = getPoint(i).x;
2146                         pData[pData[i].pending].askForWindingS = pData[i].askForWindingS;
2147                         pData[pData[i].pending].askForWindingB = pData[i].askForWindingB;
2148                       }
2149               }
2150             }
2151       for (int i = st; i < en; i++) pData[i].newInd = pData[pData[i].newInd].pending;
2152       return lastI;
2153   }
2154   return en;
2157 void
2158 Shape::AssemblePoints (Shape * a)
2160   if (hasPoints())
2161     {
2162       int lastI = AssemblePoints (0, numberOfPoints());
2164       for (int i = 0; i < a->numberOfEdges(); i++)
2165         {
2166           a->swsData[i].stPt = pData[a->swsData[i].stPt].newInd;
2167           a->swsData[i].enPt = pData[a->swsData[i].enPt].newInd;
2168         }
2169       for (int i = 0; i < nbInc; i++)
2170         iData[i].pt = pData[iData[i].pt].newInd;
2172       _pts.resize(lastI);
2173     }
2175 void
2176 Shape::AssembleAretes (FillRule directed)
2178   if ( directed == fill_justDont && _has_back_data == false ) {
2179     directed=fill_nonZero;
2180   }
2181   
2182   for (int i = 0; i < numberOfPoints(); i++) {
2183     if (getPoint(i).totalDegree() == 2) {
2184       int cb, cc;
2185       cb = getPoint(i).incidentEdge[FIRST];
2186       cc = getPoint(i).incidentEdge[LAST];
2187       bool  doublon=false;
2188       if ((getEdge(cb).st == getEdge(cc).st && getEdge(cb).en == getEdge(cc).en)
2189           || (getEdge(cb).st == getEdge(cc).en && getEdge(cb).en == getEdge(cc).en)) doublon=true;
2190       if ( directed == fill_justDont ) {
2191         if ( doublon ) {
2192           if ( ebData[cb].pathID > ebData[cc].pathID ) {
2193             cc = getPoint(i).incidentEdge[FIRST]; // on swappe pour enlever cc
2194             cb = getPoint(i).incidentEdge[LAST];
2195           } else if ( ebData[cb].pathID == ebData[cc].pathID ) {
2196             if ( ebData[cb].pieceID > ebData[cc].pieceID ) {
2197               cc = getPoint(i).incidentEdge[FIRST]; // on swappe pour enlever cc
2198               cb = getPoint(i).incidentEdge[LAST];
2199             } else if ( ebData[cb].pieceID == ebData[cc].pieceID ) { 
2200               if ( ebData[cb].tSt > ebData[cc].tSt ) {
2201                 cc = getPoint(i).incidentEdge[FIRST]; // on swappe pour enlever cc
2202                 cb = getPoint(i).incidentEdge[LAST];
2203               }
2204             }
2205           }
2206         }
2207         if ( doublon ) eData[cc].weight = 0;
2208       } else {
2209       }
2210       if ( doublon ) {
2211         if (getEdge(cb).st == getEdge(cc).st) {
2212           eData[cb].weight += eData[cc].weight;
2213         } else {
2214           eData[cb].weight -= eData[cc].weight;
2215         }
2216               eData[cc].weight = 0;
2217         
2218               if (swsData[cc].firstLinkedPoint >= 0) {
2219           int cp = swsData[cc].firstLinkedPoint;
2220           while (cp >= 0) {
2221             pData[cp].askForWindingB = cb;
2222             cp = pData[cp].nextLinkedPoint;
2223           }
2224           if (swsData[cb].firstLinkedPoint < 0) {
2225             swsData[cb].firstLinkedPoint = swsData[cc].firstLinkedPoint;
2226           } else {
2227             int ncp = swsData[cb].firstLinkedPoint;
2228             while (pData[ncp].nextLinkedPoint >= 0) {
2229               ncp = pData[ncp].nextLinkedPoint;
2230             }
2231             pData[ncp].nextLinkedPoint = swsData[cc].firstLinkedPoint;
2232           }
2233         }
2234         
2235               DisconnectStart (cc);
2236               DisconnectEnd (cc);
2237               if (numberOfEdges() > 1) {
2238           int cp = swsData[numberOfEdges() - 1].firstLinkedPoint;
2239           while (cp >= 0) {
2240             pData[cp].askForWindingB = cc;
2241             cp = pData[cp].nextLinkedPoint;
2242           }
2243         }
2244               SwapEdges (cc, numberOfEdges() - 1);
2245               if (cb == numberOfEdges() - 1) {
2246           cb = cc;
2247         }
2248               _aretes.pop_back();
2249             }
2250     } else {
2251       int cb;
2252       cb = getPoint(i).incidentEdge[FIRST];
2253       while (cb >= 0 && cb < numberOfEdges()) {
2254               int other = Other (i, cb);
2255               int cc;
2256               cc = getPoint(i).incidentEdge[FIRST];
2257               while (cc >= 0 && cc < numberOfEdges()) {
2258           int ncc = NextAt (i, cc);
2259           bool  doublon=false;
2260           if (cc != cb && Other (i, cc) == other ) doublon=true;
2261           if ( directed == fill_justDont ) {
2262             if ( doublon ) {
2263               if ( ebData[cb].pathID > ebData[cc].pathID ) {
2264                 doublon=false;
2265               } else if ( ebData[cb].pathID == ebData[cc].pathID ) {
2266                 if ( ebData[cb].pieceID > ebData[cc].pieceID ) {
2267                   doublon=false;
2268                 } else if ( ebData[cb].pieceID == ebData[cc].pieceID ) { 
2269                   if ( ebData[cb].tSt > ebData[cc].tSt ) {
2270                     doublon=false;
2271                   }
2272                 }
2273               }
2274             }
2275             if ( doublon ) eData[cc].weight = 0;
2276           } else {
2277           }
2278           if ( doublon ) {
2279 //            if (cc != cb && Other (i, cc) == other) {
2280             // doublon
2281             if (getEdge(cb).st == getEdge(cc).st) {
2282               eData[cb].weight += eData[cc].weight;
2283             } else {
2284               eData[cb].weight -= eData[cc].weight;
2285             }
2286             eData[cc].weight = 0;
2287             
2288             if (swsData[cc].firstLinkedPoint >= 0) {
2289               int cp = swsData[cc].firstLinkedPoint;
2290               while (cp >= 0) {
2291                 pData[cp].askForWindingB = cb;
2292                 cp = pData[cp].nextLinkedPoint;
2293               }
2294               if (swsData[cb].firstLinkedPoint < 0) {
2295                 swsData[cb].firstLinkedPoint = swsData[cc].firstLinkedPoint;
2296               } else {
2297                 int ncp = swsData[cb].firstLinkedPoint;
2298                 while (pData[ncp].nextLinkedPoint >= 0) {
2299                   ncp = pData[ncp].nextLinkedPoint;
2300                 }
2301                 pData[ncp].nextLinkedPoint = swsData[cc].firstLinkedPoint;
2302               }
2303             }
2304             
2305             DisconnectStart (cc);
2306             DisconnectEnd (cc);
2307             if (numberOfEdges() > 1) {
2308               int cp = swsData[numberOfEdges() - 1].firstLinkedPoint;
2309               while (cp >= 0) {
2310                 pData[cp].askForWindingB = cc;
2311                 cp = pData[cp].nextLinkedPoint;
2312               }
2313             }
2314             SwapEdges (cc, numberOfEdges() - 1);
2315             if (cb == numberOfEdges() - 1) {
2316               cb = cc;
2317             }
2318             if (ncc == numberOfEdges() - 1) {
2319               ncc = cc;
2320             }
2321             _aretes.pop_back();
2322           }
2323           cc = ncc;
2324         }
2325               cb = NextAt (i, cb);
2326             }
2327     }
2328   }
2329   
2330   if ( directed == fill_justDont ) {
2331     for (int i = 0; i < numberOfEdges(); i++)  {
2332       if (eData[i].weight == 0) {
2333 //        SubEdge(i);
2334  //       i--;
2335       } else {
2336         if (eData[i].weight < 0) Inverse (i);
2337       }
2338     }
2339   } else {
2340     for (int i = 0; i < numberOfEdges(); i++)  {
2341       if (eData[i].weight == 0) {
2342         //                      SubEdge(i);
2343         //                      i--;
2344       } else {
2345         if (eData[i].weight < 0) Inverse (i);
2346       }
2347     }
2348   }
2350 void
2351 Shape::GetWindings (Shape * a, Shape * b, BooleanOp mod, bool brutal)
2353   // preparation du parcours
2354   for (int i = 0; i < numberOfEdges(); i++)
2355     {
2356       swdData[i].misc = 0;
2357       swdData[i].precParc = swdData[i].suivParc = -1;
2358     }
2360   // chainage
2361   SortEdges ();
2363   int searchInd = 0;
2365   int lastPtUsed = 0;
2366   do
2367     {
2368       int startBord = -1;
2369       int outsideW = 0;
2370       {
2371         int fi = 0;
2372         for (fi = lastPtUsed; fi < numberOfPoints(); fi++)
2373           {
2374             if (getPoint(fi).incidentEdge[FIRST] >= 0 && swdData[getPoint(fi).incidentEdge[FIRST]].misc == 0)
2375               break;
2376           }
2377         lastPtUsed = fi + 1;
2378         if (fi < numberOfPoints())
2379           {
2380             int bestB = getPoint(fi).incidentEdge[FIRST];
2381             if (bestB >= 0)
2382               {
2383                 startBord = bestB;
2384                 if (fi == 0)
2385                   {
2386                     outsideW = 0;
2387                   }
2388                 else
2389                   {
2390                     if (brutal)
2391                       {
2392                         outsideW = Winding (getPoint(fi).x);
2393                       }
2394                     else
2395                       {
2396                         outsideW = Winding (fi);
2397                       }
2398                   }
2399     if ( getPoint(fi).totalDegree() == 1 ) {
2400       if ( fi == getEdge(startBord).en ) {
2401         if ( eData[startBord].weight == 0 ) {
2402           // on se contente d'inverser
2403           Inverse(startBord);
2404         } else {
2405           // on passe le askForWinding (sinon ca va rester startBord)
2406           pData[getEdge(startBord).st].askForWindingB=pData[getEdge(startBord).en].askForWindingB;
2407         }
2408       }
2409     }
2410                 if (getEdge(startBord).en == fi)
2411                   outsideW += eData[startBord].weight;
2412               }
2413           }
2414       }
2415       if (startBord >= 0)
2416         {
2417           // parcours en profondeur pour mettre les leF et riF a leurs valeurs
2418           swdData[startBord].misc = (void *) 1;
2419           swdData[startBord].leW = outsideW;
2420           swdData[startBord].riW = outsideW - eData[startBord].weight;
2421 //    if ( doDebug ) printf("part de %d\n",startBord);
2422           int curBord = startBord;
2423           bool curDir = true;
2424           swdData[curBord].precParc = -1;
2425           swdData[curBord].suivParc = -1;
2426           do
2427             {
2428               int cPt;
2429               if (curDir)
2430                 cPt = getEdge(curBord).en;
2431               else
2432                 cPt = getEdge(curBord).st;
2433               int nb = curBord;
2434 //        if ( doDebug ) printf("de curBord= %d avec leF= %d et riF= %d  -> ",curBord,swdData[curBord].leW,swdData[curBord].riW);
2435               do
2436                 {
2437                   int nnb = -1;
2438                   if (getEdge(nb).en == cPt)
2439                     {
2440                       outsideW = swdData[nb].riW;
2441                       nnb = CyclePrevAt (cPt, nb);
2442                     }
2443                   else
2444                     {
2445                       outsideW = swdData[nb].leW;
2446                       nnb = CyclePrevAt (cPt, nb);
2447                     }
2448                   if (nnb == nb)
2449                     {
2450                       // cul-de-sac
2451                       nb = -1;
2452                       break;
2453                     }
2454                   nb = nnb;
2455                 }
2456               while (nb >= 0 && nb != curBord && swdData[nb].misc != 0);
2457               if (nb < 0 || nb == curBord)
2458                 {
2459                   // retour en arriere
2460                   int oPt;
2461                   if (curDir)
2462                     oPt = getEdge(curBord).st;
2463                   else
2464                     oPt = getEdge(curBord).en;
2465                   curBord = swdData[curBord].precParc;
2466 //    if ( doDebug ) printf("retour vers %d\n",curBord);
2467                   if (curBord < 0)
2468                     break;
2469                   if (oPt == getEdge(curBord).en)
2470                     curDir = true;
2471                   else
2472                     curDir = false;
2473                 }
2474               else
2475                 {
2476                   swdData[nb].misc = (void *) 1;
2477                   swdData[nb].ind = searchInd++;
2478                   if (cPt == getEdge(nb).st)
2479                     {
2480                       swdData[nb].riW = outsideW;
2481                       swdData[nb].leW = outsideW + eData[nb].weight;
2482                     }
2483                   else
2484                     {
2485                       swdData[nb].leW = outsideW;
2486                       swdData[nb].riW = outsideW - eData[nb].weight;
2487                     }
2488                   swdData[nb].precParc = curBord;
2489                   swdData[curBord].suivParc = nb;
2490                   curBord = nb;
2491 //                if ( doDebug ) printf("suite %d\n",curBord);
2492                   if (cPt == getEdge(nb).en)
2493                     curDir = false;
2494                   else
2495                     curDir = true;
2496                 }
2497             }
2498           while (1 /*swdData[curBord].precParc >= 0 */ );
2499           // fin du cas non-oriente
2500         }
2501     }
2502   while (lastPtUsed < numberOfPoints());
2503 //      fflush(stdout);
2506 bool
2507 Shape::TesteIntersection (Shape * ils, Shape * irs, int ilb, int irb,
2508                           NR::Point &atx, double &atL, double &atR,
2509                           bool onlyDiff)
2511   int lSt = ils->getEdge(ilb).st, lEn = ils->getEdge(ilb).en;
2512   int rSt = irs->getEdge(irb).st, rEn = irs->getEdge(irb).en;
2513   if (lSt == rSt || lSt == rEn)
2514     {
2515       return false;
2516     }
2517   if (lEn == rSt || lEn == rEn)
2518     {
2519       return false;
2520     }
2522   NR::Point ldir, rdir;
2523   ldir = ils->eData[ilb].rdx;
2524   rdir = irs->eData[irb].rdx;
2526   double il = ils->pData[lSt].rx[0], it = ils->pData[lSt].rx[1], ir =
2527     ils->pData[lEn].rx[0], ib = ils->pData[lEn].rx[1];
2528   if (il > ir)
2529     {
2530       double swf = il;
2531       il = ir;
2532       ir = swf;
2533     }
2534   if (it > ib)
2535     {
2536       double swf = it;
2537       it = ib;
2538       ib = swf;
2539     }
2540   double jl = irs->pData[rSt].rx[0], jt = irs->pData[rSt].rx[1], jr =
2541     irs->pData[rEn].rx[0], jb = irs->pData[rEn].rx[1];
2542   if (jl > jr)
2543     {
2544       double swf = jl;
2545       jl = jr;
2546       jr = swf;
2547     }
2548   if (jt > jb)
2549     {
2550       double swf = jt;
2551       jt = jb;
2552       jb = swf;
2553     }
2555   if (il > jr || it > jb || ir < jl || ib < jt)
2556     return false;
2558   // pre-test
2559   {
2560     NR::Point sDiff, eDiff;
2561     double slDot, elDot;
2562     double srDot, erDot;
2563     sDiff = ils->pData[lSt].rx - irs->pData[rSt].rx;
2564     eDiff = ils->pData[lEn].rx - irs->pData[rSt].rx;
2565     srDot = cross (sDiff,rdir );
2566     erDot = cross (eDiff,rdir );
2567     if ((srDot >= 0 && erDot >= 0) || (srDot <= 0 && erDot <= 0))
2568       return false;
2570     sDiff = irs->pData[rSt].rx - ils->pData[lSt].rx;
2571     eDiff = irs->pData[rEn].rx - ils->pData[lSt].rx;
2572     slDot = cross (sDiff,ldir );
2573     elDot = cross (eDiff,ldir);
2574     if ((slDot >= 0 && elDot >= 0) || (slDot <= 0 && elDot <= 0))
2575       return false;
2577     double slb = slDot - elDot, srb = srDot - erDot;
2578     if (slb < 0)
2579       slb = -slb;
2580     if (srb < 0)
2581       srb = -srb;
2582     if (slb > srb)
2583       {
2584         atx =
2585           (slDot * irs->pData[rEn].rx - elDot * irs->pData[rSt].rx) / (slDot -
2586                                                                        elDot);
2587       }
2588     else
2589       {
2590         atx =
2591           (srDot * ils->pData[lEn].rx - erDot * ils->pData[lSt].rx) / (srDot -
2592                                                                        erDot);
2593       }
2594     atL = srDot / (srDot - erDot);
2595     atR = slDot / (slDot - elDot);
2596     return true;
2597   }
2599   // a mettre en double precision pour des resultats exacts
2600   NR::Point usvs;
2601   usvs = irs->pData[rSt].rx - ils->pData[lSt].rx;
2603   // pas sur de l'ordre des coefs de m
2604   NR::Matrix m(ldir[0], ldir[1],
2605                rdir[0], rdir[1],
2606                0, 0);
2607   double det = m.det();
2609   double tdet = det * ils->eData[ilb].isqlength * irs->eData[irb].isqlength;
2611   if (tdet > -0.0001 && tdet < 0.0001)
2612     {                           // ces couillons de vecteurs sont colineaires
2613       NR::Point sDiff, eDiff;
2614       double sDot, eDot;
2615       sDiff = ils->pData[lSt].rx - irs->pData[rSt].rx;
2616       eDiff = ils->pData[lEn].rx - irs->pData[rSt].rx;
2617       sDot = cross (sDiff,rdir );
2618       eDot = cross (eDiff,rdir);
2620       atx =
2621         (sDot * irs->pData[lEn].rx - eDot * irs->pData[lSt].rx) / (sDot -
2622                                                                    eDot);
2623       atL = sDot / (sDot - eDot);
2625       sDiff = irs->pData[rSt].rx - ils->pData[lSt].rx;
2626        eDiff = irs->pData[rEn].rx - ils->pData[lSt].rx;
2627       sDot = cross (sDiff,ldir );
2628       eDot = cross (eDiff,ldir );
2630       atR = sDot / (sDot - eDot);
2632       return true;
2633     }
2635   // plus de colinearite ni d'extremites en commun
2636   m[1] = -m[1];
2637   m[2] = -m[2];
2638   {
2639     double swap = m[0];
2640     m[0] = m[3];
2641     m[3] = swap;
2642   }
2644   atL = (m[0]* usvs[0] + m[1] * usvs[1]) / det;
2645   atR = -(m[2] * usvs[0] + m[3] * usvs[1]) / det;
2646   atx = ils->pData[lSt].rx + atL * ldir;
2649   return true;
2652 bool
2653 Shape::TesteAdjacency (Shape * a, int no, const NR::Point atx, int nPt,
2654                        bool push)
2656   if (nPt == a->swsData[no].stPt || nPt == a->swsData[no].enPt)
2657     return false;
2659   NR::Point adir, diff, ast, aen, diff1, diff2, diff3, diff4;
2661   ast = a->pData[a->getEdge(no).st].rx;
2662   aen = a->pData[a->getEdge(no).en].rx;
2664   adir = a->eData[no].rdx;
2666   double sle = a->eData[no].length;
2667   double ile = a->eData[no].ilength;
2669   diff = atx - ast;
2670  
2671   double e = IHalfRound ((cross (diff,adir)) * a->eData[no].isqlength);
2672   if (-3 < e && e < 3)
2673     {
2674       double rad = HalfRound (0.501); // when using single precision, 0.505 is better (0.5 would be the correct value, 
2675                                       // but it produces lots of bugs)
2676       diff1[0] = diff[0] - rad;
2677       diff1[1] = diff[1] - rad;
2678       diff2[0] = diff[0] + rad;
2679       diff2[1] = diff[1] - rad;
2680       diff3[0] = diff[0] + rad;
2681       diff3[1] = diff[1] + rad;
2682       diff4[0] = diff[0] - rad;
2683       diff4[1] = diff[1] + rad;
2684       double di1, di2;
2685       bool adjacent = false;
2686       di1 = cross (diff1,adir);
2687       di2 = cross (diff3,adir);
2688       if ((di1 < 0 && di2 > 0) || (di1 > 0 && di2 < 0))
2689         {
2690           adjacent = true;
2691         }
2692       else
2693         {
2694           di1 = cross ( diff2,adir);
2695           di2 = cross (diff4,adir);
2696           if ((di1 < 0 && di2 > 0) || (di1 > 0 && di2 < 0))
2697             {
2698               adjacent = true;
2699             }
2700         }
2701       if (adjacent)
2702         {
2703           double t = dot (diff, adir);
2704           if (t > 0 && t < sle)
2705             {
2706               if (push)
2707                 {
2708                   t *= ile;
2709                   PushIncidence (a, no, nPt, t);
2710                 }
2711               return true;
2712             }
2713         }
2714     }
2715   return false;
2718 void
2719 Shape::CheckAdjacencies (int lastPointNo, int lastChgtPt, Shape * shapeHead,
2720                          int edgeHead)
2722   for (unsigned int cCh = 0; cCh < chgts.size(); cCh++)
2723     {
2724       int chLeN = chgts[cCh].ptNo;
2725       int chRiN = chgts[cCh].ptNo;
2726       if (chgts[cCh].src)
2727         {
2728           Shape *lS = chgts[cCh].src;
2729           int lB = chgts[cCh].bord;
2730           int lftN = lS->swsData[lB].leftRnd;
2731           int rgtN = lS->swsData[lB].rightRnd;
2732           if (lftN < chLeN)
2733             chLeN = lftN;
2734           if (rgtN > chRiN)
2735             chRiN = rgtN;
2736 //                      for (int n=lftN;n<=rgtN;n++) CreateIncidence(lS,lB,n);
2737           for (int n = lftN - 1; n >= lastChgtPt; n--)
2738             {
2739               if (TesteAdjacency (lS, lB, getPoint(n).x, n, false) ==
2740                   false)
2741                 break;
2742               lS->swsData[lB].leftRnd = n;
2743             }
2744           for (int n = rgtN + 1; n < lastPointNo; n++)
2745             {
2746               if (TesteAdjacency (lS, lB, getPoint(n).x, n, false) ==
2747                   false)
2748                 break;
2749               lS->swsData[lB].rightRnd = n;
2750             }
2751         }
2752       if (chgts[cCh].osrc)
2753         {
2754           Shape *rS = chgts[cCh].osrc;
2755           int rB = chgts[cCh].obord;
2756           int lftN = rS->swsData[rB].leftRnd;
2757           int rgtN = rS->swsData[rB].rightRnd;
2758           if (lftN < chLeN)
2759             chLeN = lftN;
2760           if (rgtN > chRiN)
2761             chRiN = rgtN;
2762 //                      for (int n=lftN;n<=rgtN;n++) CreateIncidence(rS,rB,n);
2763           for (int n = lftN - 1; n >= lastChgtPt; n--)
2764             {
2765               if (TesteAdjacency (rS, rB, getPoint(n).x, n, false) ==
2766                   false)
2767                 break;
2768               rS->swsData[rB].leftRnd = n;
2769             }
2770           for (int n = rgtN + 1; n < lastPointNo; n++)
2771             {
2772               if (TesteAdjacency (rS, rB, getPoint(n).x, n, false) ==
2773                   false)
2774                 break;
2775               rS->swsData[rB].rightRnd = n;
2776             }
2777         }
2778       if (chgts[cCh].lSrc)
2779         {
2780           if (chgts[cCh].lSrc->swsData[chgts[cCh].lBrd].leftRnd < lastChgtPt)
2781             {
2782               Shape *nSrc = chgts[cCh].lSrc;
2783               int nBrd = chgts[cCh].lBrd /*,nNo=chgts[cCh].ptNo */ ;
2784               bool hit;
2786               do
2787                 {
2788                   hit = false;
2789                   for (int n = chRiN; n >= chLeN; n--)
2790                     {
2791                       if (TesteAdjacency
2792                           (nSrc, nBrd, getPoint(n).x, n, false))
2793                         {
2794                           if (nSrc->swsData[nBrd].leftRnd < lastChgtPt)
2795                             {
2796                               nSrc->swsData[nBrd].leftRnd = n;
2797                               nSrc->swsData[nBrd].rightRnd = n;
2798                             }
2799                           else
2800                             {
2801                               if (n < nSrc->swsData[nBrd].leftRnd)
2802                                 nSrc->swsData[nBrd].leftRnd = n;
2803                               if (n > nSrc->swsData[nBrd].rightRnd)
2804                                 nSrc->swsData[nBrd].rightRnd = n;
2805                             }
2806                           hit = true;
2807                         }
2808                     }
2809                   for (int n = chLeN - 1; n >= lastChgtPt; n--)
2810                     {
2811                       if (TesteAdjacency
2812                           (nSrc, nBrd, getPoint(n).x, n, false) == false)
2813                         break;
2814                       if (nSrc->swsData[nBrd].leftRnd < lastChgtPt)
2815                         {
2816                           nSrc->swsData[nBrd].leftRnd = n;
2817                           nSrc->swsData[nBrd].rightRnd = n;
2818                         }
2819                       else
2820                         {
2821                           if (n < nSrc->swsData[nBrd].leftRnd)
2822                             nSrc->swsData[nBrd].leftRnd = n;
2823                           if (n > nSrc->swsData[nBrd].rightRnd)
2824                             nSrc->swsData[nBrd].rightRnd = n;
2825                         }
2826                       hit = true;
2827                     }
2828                   if (hit)
2829                     {
2830                       SweepTree *node =
2831                         static_cast < SweepTree * >(nSrc->swsData[nBrd].misc);
2832                       if (node == NULL)
2833                         break;
2834                       node = static_cast < SweepTree * >(node->elem[LEFT]);
2835                       if (node == NULL)
2836                         break;
2837                       nSrc = node->src;
2838                       nBrd = node->bord;
2839                       if (nSrc->swsData[nBrd].leftRnd >= lastChgtPt)
2840                         break;
2841                     }
2842                 }
2843               while (hit);
2845             }
2846         }
2847       if (chgts[cCh].rSrc)
2848         {
2849           if (chgts[cCh].rSrc->swsData[chgts[cCh].rBrd].leftRnd < lastChgtPt)
2850             {
2851               Shape *nSrc = chgts[cCh].rSrc;
2852               int nBrd = chgts[cCh].rBrd /*,nNo=chgts[cCh].ptNo */ ;
2853               bool hit;
2854               do
2855                 {
2856                   hit = false;
2857                   for (int n = chLeN; n <= chRiN; n++)
2858                     {
2859                       if (TesteAdjacency
2860                           (nSrc, nBrd, getPoint(n).x, n, false))
2861                         {
2862                           if (nSrc->swsData[nBrd].leftRnd < lastChgtPt)
2863                             {
2864                               nSrc->swsData[nBrd].leftRnd = n;
2865                               nSrc->swsData[nBrd].rightRnd = n;
2866                             }
2867                           else
2868                             {
2869                               if (n < nSrc->swsData[nBrd].leftRnd)
2870                                 nSrc->swsData[nBrd].leftRnd = n;
2871                               if (n > nSrc->swsData[nBrd].rightRnd)
2872                                 nSrc->swsData[nBrd].rightRnd = n;
2873                             }
2874                           hit = true;
2875                         }
2876                     }
2877                   for (int n = chRiN + 1; n < lastPointNo; n++)
2878                     {
2879                       if (TesteAdjacency
2880                           (nSrc, nBrd, getPoint(n).x, n, false) == false)
2881                         break;
2882                       if (nSrc->swsData[nBrd].leftRnd < lastChgtPt)
2883                         {
2884                           nSrc->swsData[nBrd].leftRnd = n;
2885                           nSrc->swsData[nBrd].rightRnd = n;
2886                         }
2887                       else
2888                         {
2889                           if (n < nSrc->swsData[nBrd].leftRnd)
2890                             nSrc->swsData[nBrd].leftRnd = n;
2891                           if (n > nSrc->swsData[nBrd].rightRnd)
2892                             nSrc->swsData[nBrd].rightRnd = n;
2893                         }
2894                       hit = true;
2895                     }
2896                   if (hit)
2897                     {
2898                       SweepTree *node =
2899                         static_cast < SweepTree * >(nSrc->swsData[nBrd].misc);
2900                       if (node == NULL)
2901                         break;
2902                       node = static_cast < SweepTree * >(node->elem[RIGHT]);
2903                       if (node == NULL)
2904                         break;
2905                       nSrc = node->src;
2906                       nBrd = node->bord;
2907                       if (nSrc->swsData[nBrd].leftRnd >= lastChgtPt)
2908                         break;
2909                     }
2910                 }
2911               while (hit);
2912             }
2913         }
2914     }
2918 void Shape::AddChgt(int lastPointNo, int lastChgtPt, Shape * &shapeHead,
2919                     int &edgeHead, sTreeChangeType type, Shape * lS, int lB, Shape * rS,
2920                     int rB)
2922     sTreeChange c;
2923     c.ptNo = lastPointNo;
2924     c.type = type;
2925     c.src = lS;
2926     c.bord = lB;
2927     c.osrc = rS;
2928     c.obord = rB;
2929     chgts.push_back(c);
2930     const int nCh = chgts.size() - 1;
2932     /* FIXME: this looks like a cut and paste job */
2934     if (lS) {
2935         SweepTree *lE = static_cast < SweepTree * >(lS->swsData[lB].misc);
2936         if (lE && lE->elem[LEFT]) {
2937             SweepTree *llE = static_cast < SweepTree * >(lE->elem[LEFT]);
2938             chgts[nCh].lSrc = llE->src;
2939             chgts[nCh].lBrd = llE->bord;
2940         } else {
2941             chgts[nCh].lSrc = NULL;
2942             chgts[nCh].lBrd = -1;
2943         }
2945         if (lS->swsData[lB].leftRnd < lastChgtPt) {
2946             lS->swsData[lB].leftRnd = lastPointNo;
2947             lS->swsData[lB].nextSh = shapeHead;
2948             lS->swsData[lB].nextBo = edgeHead;
2949             edgeHead = lB;
2950             shapeHead = lS;
2951         } else {
2952             int old = lS->swsData[lB].leftRnd;
2953             if (getPoint(old).x[0] > getPoint(lastPointNo).x[0]) {
2954                 lS->swsData[lB].leftRnd = lastPointNo;
2955             }
2956         }
2957         if (lS->swsData[lB].rightRnd < lastChgtPt) {
2958             lS->swsData[lB].rightRnd = lastPointNo;
2959         } else {
2960             int old = lS->swsData[lB].rightRnd;
2961             if (getPoint(old).x[0] < getPoint(lastPointNo).x[0])
2962                 lS->swsData[lB].rightRnd = lastPointNo;
2963         }
2964     }
2966     if (rS) {
2967         SweepTree *rE = static_cast < SweepTree * >(rS->swsData[rB].misc);
2968         if (rE->elem[RIGHT]) {
2969             SweepTree *rrE = static_cast < SweepTree * >(rE->elem[RIGHT]);
2970             chgts[nCh].rSrc = rrE->src;
2971             chgts[nCh].rBrd = rrE->bord;
2972         } else {
2973             chgts[nCh].rSrc = NULL;
2974             chgts[nCh].rBrd = -1;
2975         }
2976         
2977         if (rS->swsData[rB].leftRnd < lastChgtPt) {
2978             rS->swsData[rB].leftRnd = lastPointNo;
2979             rS->swsData[rB].nextSh = shapeHead;
2980             rS->swsData[rB].nextBo = edgeHead;
2981             edgeHead = rB;
2982             shapeHead = rS;
2983         } else {
2984             int old = rS->swsData[rB].leftRnd;
2985             if (getPoint(old).x[0] > getPoint(lastPointNo).x[0]) {
2986                 rS->swsData[rB].leftRnd = lastPointNo;
2987             }
2988         }
2989         if (rS->swsData[rB].rightRnd < lastChgtPt) {
2990             rS->swsData[rB].rightRnd = lastPointNo;
2991         } else {
2992             int old = rS->swsData[rB].rightRnd;
2993             if (getPoint(old).x[0] < getPoint(lastPointNo).x[0])
2994                 rS->swsData[rB].rightRnd = lastPointNo;
2995         }
2996     } else {
2997         SweepTree *lE = static_cast < SweepTree * >(lS->swsData[lB].misc);
2998         if (lE && lE->elem[RIGHT]) {
2999             SweepTree *rlE = static_cast < SweepTree * >(lE->elem[RIGHT]);
3000             chgts[nCh].rSrc = rlE->src;
3001             chgts[nCh].rBrd = rlE->bord;
3002         } else {
3003             chgts[nCh].rSrc = NULL;
3004             chgts[nCh].rBrd = -1;
3005         }
3006     }
3009 // is this a debug function?  It's calling localized "printf" ...
3010 void
3011 Shape::Validate (void)
3013   for (int i = 0; i < numberOfPoints(); i++)
3014     {
3015       pData[i].rx = getPoint(i).x;
3016     }
3017   for (int i = 0; i < numberOfEdges(); i++)
3018     {
3019       eData[i].rdx = getEdge(i).dx;
3020     }
3021   for (int i = 0; i < numberOfEdges(); i++)
3022     {
3023       for (int j = i + 1; j < numberOfEdges(); j++)
3024         {
3025         NR::Point atx;
3026         double   atL, atR;
3027           if (TesteIntersection (this, this, i, j, atx, atL, atR, false))
3028             {
3029               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]);
3030             }
3031         }
3032     }
3033   fflush (stdout);
3036 void
3037 Shape::CheckEdges (int lastPointNo, int lastChgtPt, Shape * a, Shape * b,
3038                    BooleanOp mod)
3041   for (unsigned int cCh = 0; cCh < chgts.size(); cCh++)
3042     {
3043       if (chgts[cCh].type == 0)
3044         {
3045           Shape *lS = chgts[cCh].src;
3046           int lB = chgts[cCh].bord;
3047           lS->swsData[lB].curPoint = chgts[cCh].ptNo;
3048         }
3049     }
3050   for (unsigned int cCh = 0; cCh < chgts.size(); cCh++)
3051     {
3052 //              int   chLeN=chgts[cCh].ptNo;
3053 //              int   chRiN=chgts[cCh].ptNo;
3054       if (chgts[cCh].src)
3055         {
3056           Shape *lS = chgts[cCh].src;
3057           int lB = chgts[cCh].bord;
3058           Avance (lastPointNo, lastChgtPt, lS, lB, a, b, mod);
3059         }
3060       if (chgts[cCh].osrc)
3061         {
3062           Shape *rS = chgts[cCh].osrc;
3063           int rB = chgts[cCh].obord;
3064           Avance (lastPointNo, lastChgtPt, rS, rB, a, b, mod);
3065         }
3066       if (chgts[cCh].lSrc)
3067         {
3068           Shape *nSrc = chgts[cCh].lSrc;
3069           int nBrd = chgts[cCh].lBrd;
3070           while (nSrc->swsData[nBrd].leftRnd >=
3071                  lastChgtPt /*&& nSrc->swsData[nBrd].doneTo < lastChgtPt */ )
3072             {
3073               Avance (lastPointNo, lastChgtPt, nSrc, nBrd, a, b, mod);
3075               SweepTree *node =
3076                 static_cast < SweepTree * >(nSrc->swsData[nBrd].misc);
3077               if (node == NULL)
3078                 break;
3079               node = static_cast < SweepTree * >(node->elem[LEFT]);
3080               if (node == NULL)
3081                 break;
3082               nSrc = node->src;
3083               nBrd = node->bord;
3084             }
3085         }
3086       if (chgts[cCh].rSrc)
3087         {
3088           Shape *nSrc = chgts[cCh].rSrc;
3089           int nBrd = chgts[cCh].rBrd;
3090           while (nSrc->swsData[nBrd].rightRnd >=
3091                  lastChgtPt /*&& nSrc->swsData[nBrd].doneTo < lastChgtPt */ )
3092             {
3093               Avance (lastPointNo, lastChgtPt, nSrc, nBrd, a, b, mod);
3095               SweepTree *node =
3096                 static_cast < SweepTree * >(nSrc->swsData[nBrd].misc);
3097               if (node == NULL)
3098                 break;
3099               node = static_cast < SweepTree * >(node->elem[RIGHT]);
3100               if (node == NULL)
3101                 break;
3102               nSrc = node->src;
3103               nBrd = node->bord;
3104             }
3105         }
3106     }
3109 void
3110 Shape::Avance (int lastPointNo, int lastChgtPt, Shape * lS, int lB, Shape * a,
3111                Shape * b, BooleanOp mod)
3113   double dd = HalfRound (1);
3114   bool avoidDiag = false;
3115 //      if ( lastChgtPt > 0 && pts[lastChgtPt-1].y+dd == pts[lastChgtPt].y ) avoidDiag=true;
3117   bool direct = true;
3118   if (lS == b && (mod == bool_op_diff || mod == bool_op_symdiff))
3119     direct = false;
3120   int lftN = lS->swsData[lB].leftRnd;
3121   int rgtN = lS->swsData[lB].rightRnd;
3122   if (lS->swsData[lB].doneTo < lastChgtPt)
3123     {
3124       int lp = lS->swsData[lB].curPoint;
3125       if (lp >= 0 && getPoint(lp).x[1] + dd == getPoint(lastChgtPt).x[1])
3126         avoidDiag = true;
3127       if (lS->eData[lB].rdx[1] == 0)
3128         {
3129           // tjs de gauche a droite et pas de diagonale
3130           if (lS->eData[lB].rdx[0] >= 0)
3131             {
3132               for (int p = lftN; p <= rgtN; p++)
3133                 {
3134                   DoEdgeTo (lS, lB, p, direct, true);
3135                   lp = p;
3136                 }
3137             }
3138           else
3139             {
3140               for (int p = lftN; p <= rgtN; p++)
3141                 {
3142                   DoEdgeTo (lS, lB, p, direct, false);
3143                   lp = p;
3144                 }
3145             }
3146         }
3147       else if (lS->eData[lB].rdx[1] > 0)
3148         {
3149           if (lS->eData[lB].rdx[0] >= 0)
3150             {
3152               for (int p = lftN; p <= rgtN; p++)
3153                 {
3154                   if (avoidDiag && p == lftN && getPoint(lftN).x[0] == getPoint(lp).x[0] + dd)
3155                     {
3156                       if (lftN > 0 && lftN - 1 >= lastChgtPt
3157                           && getPoint(lftN - 1).x[0] == getPoint(lp).x[0])
3158                         {
3159                           DoEdgeTo (lS, lB, lftN - 1, direct, true);
3160                           DoEdgeTo (lS, lB, lftN, direct, true);
3161                         }
3162                       else
3163                         {
3164                           DoEdgeTo (lS, lB, lftN, direct, true);
3165                         }
3166                     }
3167                   else
3168                     {
3169                       DoEdgeTo (lS, lB, p, direct, true);
3170                     }
3171                   lp = p;
3172                 }
3173             }
3174           else
3175             {
3177               for (int p = rgtN; p >= lftN; p--)
3178                 {
3179                   if (avoidDiag && p == rgtN && getPoint(rgtN).x[0] == getPoint(lp).x[0] - dd)
3180                     {
3181                       if (rgtN < numberOfPoints() && rgtN + 1 < lastPointNo
3182                           && getPoint(rgtN + 1).x[0] == getPoint(lp).x[0])
3183                         {
3184                           DoEdgeTo (lS, lB, rgtN + 1, direct, true);
3185                           DoEdgeTo (lS, lB, rgtN, direct, true);
3186                         }
3187                       else
3188                         {
3189                           DoEdgeTo (lS, lB, rgtN, direct, true);
3190                         }
3191                     }
3192                   else
3193                     {
3194                       DoEdgeTo (lS, lB, p, direct, true);
3195                     }
3196                   lp = p;
3197                 }
3198             }
3199         }
3200       else
3201         {
3202           if (lS->eData[lB].rdx[0] >= 0)
3203             {
3205               for (int p = rgtN; p >= lftN; p--)
3206                 {
3207                   if (avoidDiag && p == rgtN && getPoint(rgtN).x[0] == getPoint(lp).x[0] - dd)
3208                     {
3209                       if (rgtN < numberOfPoints() && rgtN + 1 < lastPointNo
3210                           && getPoint(rgtN + 1).x[0] == getPoint(lp).x[0])
3211                         {
3212                           DoEdgeTo (lS, lB, rgtN + 1, direct, false);
3213                           DoEdgeTo (lS, lB, rgtN, direct, false);
3214                         }
3215                       else
3216                         {
3217                           DoEdgeTo (lS, lB, rgtN, direct, false);
3218                         }
3219                     }
3220                   else
3221                     {
3222                       DoEdgeTo (lS, lB, p, direct, false);
3223                     }
3224                   lp = p;
3225                 }
3226             }
3227           else
3228             {
3230               for (int p = lftN; p <= rgtN; p++)
3231                 {
3232                   if (avoidDiag && p == lftN && getPoint(lftN).x[0] == getPoint(lp).x[0] + dd)
3233                     {
3234                       if (lftN > 0 && lftN - 1 >= lastChgtPt
3235                           && getPoint(lftN - 1).x[0] == getPoint(lp).x[0])
3236                         {
3237                           DoEdgeTo (lS, lB, lftN - 1, direct, false);
3238                           DoEdgeTo (lS, lB, lftN, direct, false);
3239                         }
3240                       else
3241                         {
3242                           DoEdgeTo (lS, lB, lftN, direct, false);
3243                         }
3244                     }
3245                   else
3246                     {
3247                       DoEdgeTo (lS, lB, p, direct, false);
3248                     }
3249                   lp = p;
3250                 }
3251             }
3252         }
3253       lS->swsData[lB].curPoint = lp;
3254     }
3255   lS->swsData[lB].doneTo = lastPointNo - 1;
3258 void
3259 Shape::DoEdgeTo (Shape * iS, int iB, int iTo, bool direct, bool sens)
3261   int lp = iS->swsData[iB].curPoint;
3262   int ne = -1;
3263   if (sens)
3264     {
3265       if (direct)
3266         ne = AddEdge (lp, iTo);
3267       else
3268         ne = AddEdge (iTo, lp);
3269     }
3270   else
3271     {
3272       if (direct)
3273         ne = AddEdge (iTo, lp);
3274       else
3275         ne = AddEdge (lp, iTo);
3276     }
3277   if (ne >= 0 && _has_back_data)
3278     {
3279       ebData[ne].pathID = iS->ebData[iB].pathID;
3280       ebData[ne].pieceID = iS->ebData[iB].pieceID;
3281       if (iS->eData[iB].length < 0.00001)
3282         {
3283           ebData[ne].tSt = ebData[ne].tEn = iS->ebData[iB].tSt;
3284         }
3285       else
3286         {
3287           double bdl = iS->eData[iB].ilength;
3288     NR::Point bpx = iS->pData[iS->getEdge(iB).st].rx;
3289           NR::Point bdx = iS->eData[iB].rdx;
3290           NR::Point psx = getPoint(getEdge(ne).st).x;
3291           NR::Point pex = getPoint(getEdge(ne).en).x;
3292         NR::Point psbx=psx-bpx;
3293         NR::Point pebx=pex-bpx;
3294           double pst = dot(psbx,bdx) * bdl;
3295           double pet = dot(pebx,bdx) * bdl;
3296           pst = iS->ebData[iB].tSt * (1 - pst) + iS->ebData[iB].tEn * pst;
3297           pet = iS->ebData[iB].tSt * (1 - pet) + iS->ebData[iB].tEn * pet;
3298           ebData[ne].tEn = pet;
3299           ebData[ne].tSt = pst;
3300         }
3301     }
3302   iS->swsData[iB].curPoint = iTo;
3303   if (ne >= 0)
3304     {
3305       int cp = iS->swsData[iB].firstLinkedPoint;
3306       swsData[ne].firstLinkedPoint = iS->swsData[iB].firstLinkedPoint;
3307       while (cp >= 0)
3308         {
3309           pData[cp].askForWindingB = ne;
3310           cp = pData[cp].nextLinkedPoint;
3311         }
3312       iS->swsData[iB].firstLinkedPoint = -1;
3313     }