Code

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