Code

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