1 
2 
3 //#include "tsystem.h"
4 #include "tmachine.h"
5 #include "tcurves.h"
6 #include "tcommon.h"
7 #include "tregion.h"
8 //#include "tregionutil.h"
9 #include "tstopwatch.h"
10 
11 #include "tstroke.h"
12 #include "tstrokeutil.h"
13 #include "tvectorimageP.h"
14 #include "tdebugmessage.h"
15 #include <vector>
16 
17 #include "tcurveutil.h"
18 
19 #include <algorithm>
20 
21 #if !defined(TNZ_LITTLE_ENDIAN)
22 TNZ_LITTLE_ENDIAN undefined !!
23 #endif
24 
25 //-----------------------------------------------------------------------------
26 
27 #ifdef IS_DOTNET
28 #define NULL_ITER list<IntersectedStroke>::iterator()
29 #else
30 #define NULL_ITER 0
31 #endif
32 
33     using namespace std;
34 
35 typedef TVectorImage::IntersectionBranch IntersectionBranch;
36 //-----------------------------------------------------------------------------
37 
myRound(double x)38 inline double myRound(double x) {
39   return (1.0 / REGION_COMPUTING_PRECISION) *
40          ((long)(x * REGION_COMPUTING_PRECISION));
41 }
42 
myRound(const TThickPoint & p)43 inline TThickPoint myRound(const TThickPoint &p) {
44   return TThickPoint(myRound(p.x), myRound(p.y), p.thick);
45 }
46 
print(list<Intersection> & intersectionList,char * str)47 void print(list<Intersection> &intersectionList, char *str) {
48   ofstream of(str);
49 
50   of << "***************************" << endl;
51 
52   list<Intersection>::const_iterator it;
53   list<IntersectedStroke>::const_iterator it1;
54   int i, j;
55   for (i = 0, it = intersectionList.begin(); it != intersectionList.end();
56        it++, i++) {
57     of << "***************************" << endl;
58     of << "Intersection#" << i << ": " << it->m_intersection
59        << "numBranches: " << it->m_numInter << endl;
60     of << endl;
61 
62     for (j = 0, it1 = it->m_strokeList.begin(); it1 != it->m_strokeList.end();
63          it1++, j++) {
64       of << "----Branch #" << j;
65       if (it1->m_edge.m_index < 0) of << "(AUTOCLOSE)";
66       of << "Intersection at " << it1->m_edge.m_w0 << ": "
67          << ": " << endl;
68       of << "ColorId: " << it1->m_edge.m_styleId << endl;
69       /*
70 TColorStyle* fs = it1->m_edge.m_fillStyle;
71 if (fs==0)
72 of<<"NO color: "<< endl;
73 else
74 {
75 TFillStyleP fp = fs->getFillStyle();
76 if (fp)
77 {
78 fp->
79 assert(false) ;
80 else
81 of<<"Color: ("<< colorStyle->getColor().r<<", "<< colorStyle->getColor().g<<",
82 "<< colorStyle->getColor().b<<")"<<endl;
83 */
84 
85       of << "----Stroke " << (it1->m_gettingOut ? "OUT" : "IN") << " #"
86          << it1->m_edge.m_index << ": " << endl;
87       // if (it1->m_dead)
88       // of<<"---- DEAD Intersection.";
89       // else
90       {
91         of << "---- NEXT Intersection:";
92         if (it1->m_nextIntersection != intersectionList.end()) {
93           int dist =
94               std::distance(intersectionList.begin(), it1->m_nextIntersection);
95           of << dist;
96           list<Intersection>::iterator iit = intersectionList.begin();
97           std::advance(iit, dist);
98           of << " "
99              << std::distance(iit->m_strokeList.begin(), it1->m_nextStroke);
100         }
101 
102         else
103           of << "NULL!!";
104         of << "---- NEXT Stroke:";
105         if (it1->m_nextIntersection != intersectionList.end())
106           of << it1->m_nextStroke->m_edge.m_index;
107         else
108           of << "NULL!!";
109       }
110       of << endl << endl;
111     }
112   }
113 }
114 
115 void findNearestIntersection(list<Intersection> &interList,
116                              const list<Intersection>::iterator &i1,
117                              const list<IntersectedStroke>::iterator &i2);
118 
119 //-----------------------------------------------------------------------------
120 
121 #ifdef _TOLGO
checkInterList(list<Intersection> & intersectionList)122 void checkInterList(list<Intersection> &intersectionList) {
123   list<Intersection>::iterator it;
124   list<IntersectedStroke>::iterator it1;
125 
126   for (it = intersectionList.begin(); it != intersectionList.end(); it++) {
127     int count = 0;
128     for (it1 = it->m_strokeList.begin(); it1 != it->m_strokeList.end(); it1++) {
129       int val;
130       if (it1->m_nextIntersection != intersectionList.end()) {
131         count++;
132         // assert (it1->m_nextIntersection!=intersectionList.end());
133         assert(it1->m_nextStroke->m_nextIntersection == it);
134         assert(it1->m_nextStroke->m_nextStroke == it1);
135 
136         // int k = it1->m_edge.m_index;
137         val = std::distance(intersectionList.begin(), it1->m_nextIntersection);
138       }
139       // else
140       // assert(it1->m_nextIntersection==intersectionList.end());
141     }
142     assert(count == it->m_numInter);
143   }
144 }
145 #else
146 #define checkInterList
147 #endif
148 
149 //-----------------------------------------------------------------------------
150 
151 // void addFakeIntersection(list<Intersection>& intersectionList,TStroke* s,
152 // UINT ii, double w);
153 
154 void addIntersections(IntersectionData &intersectionData,
155                       const vector<VIStroke *> &s, int ii, int jj,
156                       const vector<DoublePair> &intersections, int numStrokes);
157 
158 void addIntersection(IntersectionData &intData, const vector<VIStroke *> &s,
159                      int ii, int jj, DoublePair intersections, int strokeSize);
160 
161 //-----------------------------------------------------------------------------
162 
sortBBox(const TStroke * s1,const TStroke * s2)163 bool sortBBox(const TStroke *s1, const TStroke *s2) {
164   return s1->getBBox().x0 < s2->getBBox().x0;
165 }
166 
167 //-----------------------------------------------------------------------------
168 
cleanIntersectionMarks(list<Intersection> & interList)169 void cleanIntersectionMarks(list<Intersection> &interList) {
170   for (list<Intersection>::iterator it1 = interList.begin();
171        it1 != interList.end(); it1++)
172     for (list<IntersectedStroke>::iterator it2 = (*it1).m_strokeList.begin();
173          it2 != (*it1).m_strokeList.end(); it2++) {
174       it2->m_visited =
175           false;  // Ogni ramo della lista viene messo nella condizione
176                   // di poter essere visitato
177 
178       if (it2->m_nextIntersection != interList.end()) {
179         it2->m_nextIntersection =
180             interList.end();  // pezza tremenda, da togliere!!!
181         it1->m_numInter--;
182       }
183     }
184 }
185 
186 //-----------------------------------------------------------------------------
187 
cleanNextIntersection(list<Intersection> & interList,TStroke * s)188 void cleanNextIntersection(list<Intersection> &interList, TStroke *s) {
189   for (list<Intersection>::iterator it1 = interList.begin();
190        it1 != interList.end(); it1++)
191     for (list<IntersectedStroke>::iterator it2 = (*it1).m_strokeList.begin();
192          it2 != (*it1).m_strokeList.end(); it2++)
193       if (it2->m_edge.m_s == s) {
194         // if (it2->m_nextIntersection==NULL)
195         //  return; //gia' ripulita prima
196         if (it2->m_nextIntersection != interList.end()) {
197           it2->m_nextIntersection = interList.end();
198           it1->m_numInter--;
199         }
200         it2->m_nextStroke = (*it1).m_strokeList.end();
201       }
202 }
203 
204 //-----------------------------------------------------------------------------
205 
eraseEdgeFromStroke(list<IntersectedStroke>::iterator it2)206 void TVectorImage::Imp::eraseEdgeFromStroke(
207     list<IntersectedStroke>::iterator it2) {
208   if (it2->m_edge.m_index >=
209       0)  // elimino il puntatore all'edge nella lista della VIStroke
210   {
211     VIStroke *s;
212     s = m_strokes[it2->m_edge.m_index];
213     assert(s->m_s == it2->m_edge.m_s);
214     list<TEdge *>::iterator iit  = s->m_edgeList.begin(),
215                             it_e = s->m_edgeList.end();
216 
217     for (; iit != it_e; ++iit)
218       if ((*iit)->m_w0 == it2->m_edge.m_w0 &&
219           (*iit)->m_w1 == it2->m_edge.m_w1) {
220         assert((*iit)->m_toBeDeleted == false);
221         s->m_edgeList.erase(iit);
222         return;
223       }
224   }
225 }
226 
227 //-----------------------------------------------------------------------------
228 
eraseBranch(list<Intersection>::iterator it1,list<IntersectedStroke>::iterator it2)229 list<IntersectedStroke>::iterator TVectorImage::Imp::eraseBranch(
230     list<Intersection>::iterator it1, list<IntersectedStroke>::iterator it2) {
231   // list<Intersection>::iterator iit1;
232   // list<IntersectedStroke>::iterator iit2;
233   list<Intersection> &intList = m_intersectionData.m_intList;
234 
235   if (it2->m_nextIntersection != intList.end()) {
236     list<Intersection>::iterator nextInt         = it2->m_nextIntersection;
237     list<IntersectedStroke>::iterator nextStroke = it2->m_nextStroke;
238     assert(nextStroke->m_nextIntersection == it1);
239     assert(nextStroke->m_nextStroke == it2);
240     assert(nextStroke != it2);
241 
242     // nextStroke->m_nextIntersection = intList.end();
243     // nextStroke->m_nextStroke = nextInt->m_strokeList.end();
244 
245     if (nextStroke->m_nextIntersection != intList.end()) {
246       nextStroke->m_nextIntersection = intList.end();
247       nextInt->m_numInter--;
248     }
249     // nextInt->m_strokeList.erase(nextStroke);//non posso cancellarla, puo'
250     // servire in futuro!
251   }
252   if (it2->m_nextIntersection != intList.end()) it1->m_numInter--;
253 
254   eraseEdgeFromStroke(it2);
255 
256   it2->m_edge.m_w0 = it2->m_edge.m_w1 = -3;
257   it2->m_edge.m_index                 = -3;
258   it2->m_edge.m_s                     = 0;
259   it2->m_edge.m_styleId               = -3;
260 
261   list<IntersectedStroke>::iterator ret = (*it1).m_strokeList.erase(it2);
262 
263   return ret;
264 }
265 
266 //-----------------------------------------------------------------------------
267 
eraseDeadIntersections()268 void TVectorImage::Imp::eraseDeadIntersections() {
269   list<Intersection>::iterator it;
270 
271   for (it = m_intersectionData.m_intList.begin();
272        it != m_intersectionData.m_intList.end();)  // la faccio qui, e non nella
273                                                    // eraseIntersection. vedi
274                                                    // commento li'.
275   {
276     list<Intersection> &intList = m_intersectionData.m_intList;
277 
278     if (it->m_strokeList.size() == 1) {
279       eraseBranch(it, (*it).m_strokeList.begin());
280       assert(it->m_strokeList.empty());
281       it = intList.erase(it);
282     } else if (it->m_strokeList.size() == 2 &&
283                ((*it).m_strokeList.front().m_edge.m_s ==
284                     (*it).m_strokeList.back().m_edge.m_s &&
285                 (*it).m_strokeList.front().m_edge.m_w0 ==
286                     (*it).m_strokeList.back().m_edge.m_w0))  // intersezione
287                                                              // finta
288     {
289       list<IntersectedStroke>::iterator it1 = it->m_strokeList.begin(), iit1,
290                                         iit2;
291       list<IntersectedStroke>::iterator it2 = it1;
292       it2++;
293 
294       eraseEdgeFromStroke(it1);
295       eraseEdgeFromStroke(it2);
296 
297       iit1 = (it1->m_nextIntersection == intList.end()) ? NULL_ITER
298                                                         : it1->m_nextStroke;
299       iit2 = (it2->m_nextIntersection == intList.end()) ? NULL_ITER
300                                                         : it2->m_nextStroke;
301 
302       if (iit1 != NULL_ITER && iit2 != NULL_ITER) {
303         iit1->m_edge.m_w1 = iit2->m_edge.m_w0;
304         iit2->m_edge.m_w1 = iit1->m_edge.m_w0;
305       }
306       if (iit1 != NULL_ITER) {
307         iit1->m_nextStroke       = iit2;
308         iit1->m_nextIntersection = it2->m_nextIntersection;
309         if (iit1->m_nextIntersection == intList.end())
310           it1->m_nextIntersection->m_numInter--;
311       }
312 
313       if (iit2 != NULL_ITER) {
314         iit2->m_nextStroke       = iit1;
315         iit2->m_nextIntersection = it1->m_nextIntersection;
316         if (iit2->m_nextIntersection == intList.end())
317           it2->m_nextIntersection->m_numInter--;
318       }
319 
320       it->m_strokeList.clear();
321       it->m_numInter = 0;
322       it             = intList.erase(it);
323     } else
324       ++it;
325   }
326 }
327 
328 //-----------------------------------------------------------------------------
329 
doEraseIntersection(int index,vector<int> * toBeDeleted)330 void TVectorImage::Imp::doEraseIntersection(int index,
331                                             vector<int> *toBeDeleted) {
332   list<Intersection> &interList = m_intersectionData.m_intList;
333 
334   list<Intersection>::iterator it1 = interList.begin();
335   TStroke *deleteIt                = 0;
336 
337   while (it1 != interList.end()) {
338     bool removeAutocloses = false;
339 
340     list<IntersectedStroke>::iterator it2 = (*it1).m_strokeList.begin();
341 
342     while (it2 != (*it1).m_strokeList.end()) {
343       IntersectedStroke &is = *it2;
344 
345       if (is.m_edge.m_index == index) {
346         if (is.m_edge.m_index >= 0)
347           // if (!is.m_autoclose && (is.m_edge.m_w0==1 || is.m_edge.m_w0==0))
348           removeAutocloses = true;
349         else
350           deleteIt = is.m_edge.m_s;
351         it2        = eraseBranch(it1, it2);
352       } else
353         ++it2;
354       // checkInterList(interList);
355     }
356     if (removeAutocloses)  // se ho tolto una stroke dall'inter corrente, tolgo
357                            // tutti le stroke di autclose che partono da qui
358     {
359       assert(toBeDeleted);
360       for (it2 = (*it1).m_strokeList.begin(); it2 != (*it1).m_strokeList.end();
361            it2++)
362         if (it2->m_edge.m_index < 0 &&
363             (it2->m_edge.m_w0 == 1 || it2->m_edge.m_w0 == 0))
364           toBeDeleted->push_back(it2->m_edge.m_index);
365     }
366 
367     if ((*it1).m_strokeList.empty())
368       it1 = interList.erase(it1);
369     else
370       it1++;
371   }
372 
373   if (deleteIt) delete deleteIt;
374 }
375 
376 //-----------------------------------------------------------------------------
377 
getFillData(IntersectionBranch * & v)378 UINT TVectorImage::Imp::getFillData(IntersectionBranch *&v) {
379   // print(m_intersectionData.m_intList, "C:\\temp\\intersectionPrimaSave.txt");
380 
381   list<Intersection> &intList = m_intersectionData.m_intList;
382   if (intList.empty()) return 0;
383 
384   list<Intersection>::iterator it1;
385   list<IntersectedStroke>::iterator it2;
386   UINT currInt = 0;
387   vector<UINT> branchesBefore(intList.size() + 1);
388 
389   branchesBefore[0] = 0;
390   UINT count = 0, size = 0;
391 
392   for (it1 = intList.begin(); it1 != intList.end(); ++it1, currInt++) {
393     UINT strokeListSize = it1->m_strokeList.size();
394     size += strokeListSize;
395     branchesBefore[currInt + 1] = branchesBefore[currInt] + strokeListSize;
396   }
397 
398   v       = new IntersectionBranch[size];
399   currInt = 0;
400 
401   for (it1 = intList.begin(); it1 != intList.end(); ++it1, currInt++) {
402     UINT currBranch = 0;
403     for (it2 = it1->m_strokeList.begin(); it2 != it1->m_strokeList.end();
404          ++it2, currBranch++) {
405       IntersectionBranch &b = v[count];
406       b.m_currInter         = currInt;
407       b.m_strokeIndex       = it2->m_edge.m_index;
408       b.m_w                 = it2->m_edge.m_w0;
409       b.m_style             = it2->m_edge.m_styleId;
410       // assert(b.m_style<100);
411       b.m_gettingOut = it2->m_gettingOut;
412       if (it2->m_nextIntersection == intList.end())
413         b.m_nextBranch = count;
414       else {
415         UINT distInt = std::distance(intList.begin(), it2->m_nextIntersection);
416         UINT distBranch = std::distance(
417             it2->m_nextIntersection->m_strokeList.begin(), it2->m_nextStroke);
418 
419         if ((distInt < currInt) ||
420             (distInt == currInt && distBranch < currBranch)) {
421           UINT posNext = branchesBefore[distInt] + distBranch;
422           assert(posNext < count);
423           b.m_nextBranch = posNext;
424           assert(v[posNext].m_nextBranch == (std::numeric_limits<UINT>::max)());
425           v[posNext].m_nextBranch = count;
426         } else
427           b.m_nextBranch = (std::numeric_limits<UINT>::max)();
428       }
429       count++;
430     }
431   }
432 
433 // for (UINT i=0; i<count; i++)
434 //  assert(v[i].m_nextBranch != std::numeric_limits<UINT>::max());
435 
436 #ifdef _DEBUG
437 /*ofstream of("C:\\temp\\fillDataOut.txt");
438 
439 for (UINT ii=0; ii<size; ii++)
440   {
441   of<<ii<<"----------------------"<<endl;
442   of<<"index:"<<v[ii].m_strokeIndex<<endl;
443   of<<"w:"<<v[ii].m_w<<endl;
444   of<<"curr inter:"<<v[ii].m_currInter<<endl;
445   of<<"next inter:"<<v[ii].m_nextBranch<<endl;
446   of<<"gettingOut:"<<((v[ii].m_gettingOut)?"TRUE":"FALSE")<<endl;
447   of<<"colorId:"<<v[ii].m_style<<endl;
448   }*/
449 #endif
450 
451   return size;
452 }
453 
454 //-----------------------------------------------------------------------------
455 
456 //-----------------------------------------------------------------------------
457 namespace {
reconstructAutocloseStroke(list<Intersection> & intList,list<Intersection>::iterator it1,list<IntersectedStroke>::iterator it2)458 TStroke *reconstructAutocloseStroke(list<Intersection> &intList,
459                                     list<Intersection>::iterator it1,
460                                     list<IntersectedStroke>::iterator it2)
461 
462 {
463   bool found                        = false;
464   list<Intersection>::iterator iit1 = it1;
465   list<IntersectedStroke>::iterator iit2;
466   iit1++;
467   // vector<TEdge*> vapp;
468   for (; !found && iit1 != intList.end(); iit1++) {
469     for (iit2 = iit1->m_strokeList.begin();
470          !found && iit2 != iit1->m_strokeList.end(); iit2++) {
471       if (it2->m_edge.m_index == iit2->m_edge.m_index) {
472         if ((iit2->m_edge.m_w0 == 1 && it2->m_edge.m_w0 == 0) ||
473             (iit2->m_edge.m_w0 == 0 && it2->m_edge.m_w0 == 1)) {
474           found = true;
475           vector<TPointD> v;
476           if (it2->m_edge.m_w0 == 0) {
477             v.push_back(it1->m_intersection);
478             v.push_back(iit1->m_intersection);
479           } else {
480             v.push_back(iit1->m_intersection);
481             v.push_back(it1->m_intersection);
482           }
483           it2->m_edge.m_s = iit2->m_edge.m_s = new TStroke(v);
484           // for (UINT ii=0; ii<vapp.size(); ii++)
485           // vapp[ii]->m_s = it2->m_edge.m_s;
486         }
487         // else if (iit2->m_edge.m_w0!=0 && iit2->m_edge.m_w0!=1)
488         //  vapp.push_back(&(iit2->m_edge));
489       }
490     }
491   }
492   assert(found);
493   if (!found) it2->m_edge.m_s = 0;
494 
495   return it2->m_edge.m_s;
496 }
497 
498 }  // namespace
499 //-----------------------------------------------------------------------------
500 
setFillData(IntersectionBranch * v,UINT branchCount)501 void TVectorImage::Imp::setFillData(IntersectionBranch *v, UINT branchCount) {
502 #ifdef _DEBUG
503 /*ofstream of("C:\\temp\\fillDataIn.txt");
504 
505 for (UINT ii=0; ii<branchCount; ii++)
506   {
507   of<<ii<<"----------------------"<<endl;
508   of<<"index:"<<v[ii].m_strokeIndex<<endl;
509   of<<"w:"<<v[ii].m_w<<endl;
510   of<<"curr inter:"<<v[ii].m_currInter<<endl;
511   of<<"next inter:"<<v[ii].m_nextBranch<<endl;
512   of<<"gettingOut:"<<((v[ii].m_gettingOut)?"TRUE":"FALSE")<<endl;
513   of<<"colorId:"<<v[ii].m_style<<endl;
514   }*/
515 #endif
516 
517   if (branchCount == 0) return;
518 
519   list<Intersection> &intList = m_intersectionData.m_intList;
520   clearPointerContainer(m_regions);
521   m_regions.clear();
522   intList.clear();
523   list<Intersection>::iterator currInt;
524   list<IntersectedStroke>::iterator currBranch;
525 
526   vector<UINT> branchesBefore(v[branchCount - 1].m_currInter + 1);
527 
528   UINT i = 0;
529   for (; i < branchCount; i++) {
530     const IntersectionBranch &b = v[i];
531     if (i == 0 || v[i].m_currInter != v[i - 1].m_currInter) {
532       assert(i == 0 || v[i].m_currInter == v[i - 1].m_currInter + 1);
533 
534       branchesBefore[v[i].m_currInter] = i;
535       intList.push_back(Intersection());
536       currInt = intList.begin();
537       advance(currInt, intList.size() - 1);
538     }
539 
540     IntersectedStroke is;
541     currInt->m_strokeList.push_back(is);
542     currBranch = currInt->m_strokeList.begin();
543     advance(currBranch, currInt->m_strokeList.size() - 1);
544 
545     currBranch->m_edge.m_styleId = b.m_style;
546     // assert(b.m_style<100);
547     currBranch->m_edge.m_index = b.m_strokeIndex;
548     if (b.m_strokeIndex >= 0)
549       currBranch->m_edge.m_s = m_strokes[b.m_strokeIndex]->m_s;
550     else
551       currBranch->m_edge.m_s = 0;
552     currBranch->m_gettingOut = b.m_gettingOut;
553     currBranch->m_edge.m_w0  = b.m_w;
554     currBranch->m_edge.m_w1  = v[b.m_nextBranch].m_w;
555     assert(currBranch->m_edge.m_w0 >= -1e-8 &&
556            currBranch->m_edge.m_w0 <= 1 + 1e-8);
557     assert(currBranch->m_edge.m_w1 >= -1e-8 &&
558            currBranch->m_edge.m_w1 <= 1 + 1e-8);
559 
560     if (b.m_nextBranch < i) {
561       list<Intersection>::iterator it1;
562       list<IntersectedStroke>::iterator it2;
563       it1 = intList.begin();
564       std::advance(it1, v[b.m_nextBranch].m_currInter);
565       it2 = it1->m_strokeList.begin();
566       assert(b.m_nextBranch - branchesBefore[v[b.m_nextBranch].m_currInter] >=
567              0);
568 
569       std::advance(
570           it2, b.m_nextBranch - branchesBefore[v[b.m_nextBranch].m_currInter]);
571 
572       currBranch->m_nextIntersection = it1;
573       currBranch->m_nextStroke       = it2;
574       it2->m_nextIntersection        = currInt;
575       it2->m_nextStroke              = currBranch;
576 
577       // if (currBranch == currInt->m_strokeList.begin())
578       //  currInt->m_intersection =
579       //  currBranch->m_edge.m_s->getPoint(currBranch->m_edge.m_w0);
580 
581       currInt->m_numInter++;
582       it1->m_numInter++;
583     } else if (b.m_nextBranch == i)
584       currBranch->m_nextIntersection = intList.end();
585     else if (b.m_nextBranch == (std::numeric_limits<UINT>::max)()) {
586       currBranch->m_nextIntersection = intList.end();
587       currBranch->m_nextStroke       = currInt->m_strokeList.end();
588     }
589 
590     /* {
591 assert(b.m_nextBranch<branchCount);
592 assert(v[b.m_nextBranch].m_nextBranch==i);
593 }*/
594 
595     if (i == branchCount - 1 || v[i].m_currInter != v[i + 1].m_currInter) {
596       int j = i;
597       while (v[j].m_strokeIndex < 0 &&
598              ((j > 0 && v[j].m_currInter == v[j - 1].m_currInter) || j == 0))
599         j--;
600       if (v[j].m_strokeIndex >= 0)
601         currInt->m_intersection =
602             m_strokes[v[j].m_strokeIndex]->m_s->getPoint(v[j].m_w);
603     }
604   }
605 
606   for (i = 0; i < m_strokes.size(); i++) m_strokes[i]->m_isNewForFill = false;
607 
608   // computeRegions();
609 
610   list<Intersection>::iterator it1;
611   list<IntersectedStroke>::iterator it2;
612 
613   vector<UINT> toBeDeleted;
614 
615   for (it1 = intList.begin(); it1 != intList.end(); it1++)
616     for (it2 = it1->m_strokeList.begin(); it2 != it1->m_strokeList.end();
617          ++it2) {
618       if (it2->m_edge.m_index < 0 && !it2->m_edge.m_s &&
619           (it2->m_edge.m_w0 == 0 || it2->m_edge.m_w0 == 1)) {
620         it2->m_edge.m_s = reconstructAutocloseStroke(intList, it1, it2);
621         if (it2->m_edge.m_s)
622           m_intersectionData.m_autocloseMap[it2->m_edge.m_index] =
623               it2->m_edge.m_s;
624         else
625           toBeDeleted.push_back(it2->m_edge.m_index);
626       }
627     }
628 
629   for (it1 = intList.begin(); it1 != intList.end(); it1++)
630     for (it2 = it1->m_strokeList.begin(); it2 != it1->m_strokeList.end();
631          ++it2) {
632       if (!it2->m_edge.m_s && it2->m_edge.m_index < 0) {
633         it2->m_edge.m_s =
634             m_intersectionData.m_autocloseMap[it2->m_edge.m_index];
635 
636         // TEdge& e = it2->m_edge;
637         if (!it2->m_edge.m_s) toBeDeleted.push_back(it2->m_edge.m_index);
638       }
639     }
640 
641   for (i = 0; i < toBeDeleted.size(); i++) eraseIntersection(toBeDeleted[i]);
642 
643   m_areValidRegions = false;
644 
645   computeRegions();
646   // print(m_intersectionData.m_intList, "C:\\temp\\intersectionDopoLoad.txt");
647 }
648 
649 //-----------------------------------------------------------------------------
650 
eraseIntersection(int index)651 void TVectorImage::Imp::eraseIntersection(int index) {
652   vector<int> autocloseStrokes;
653   doEraseIntersection(index, &autocloseStrokes);
654 
655   for (UINT i = 0; i < autocloseStrokes.size(); i++) {
656     doEraseIntersection(autocloseStrokes[i]);
657     assert(autocloseStrokes[i] < 0);
658     m_intersectionData.m_autocloseMap.erase(autocloseStrokes[i]);
659   }
660 }
661 //-----------------------------------------------------------------------------
662 
findNearestIntersection(list<Intersection> & interList)663 void findNearestIntersection(list<Intersection> &interList) {
664   list<Intersection>::iterator i1;
665   list<IntersectedStroke>::iterator i2;
666 
667   for (i1 = interList.begin(); i1 != interList.end(); i1++) {
668     for (i2 = (*i1).m_strokeList.begin(); i2 != (*i1).m_strokeList.end();
669          i2++) {
670       if ((*i2).m_nextIntersection != interList.end())  // already set
671         continue;
672 
673       int versus      = (i2->m_gettingOut) ? 1 : -1;
674       double minDelta = (std::numeric_limits<double>::max)();
675       list<Intersection>::iterator it1, it1Res;
676       list<IntersectedStroke>::iterator it2, it2Res;
677 
678       for (it1 = i1; it1 != interList.end(); ++it1) {
679         if (it1 == i1)
680           it2 = i2, it2++;
681         else
682           it2 = (*it1).m_strokeList.begin();
683 
684         for (; it2 != (*it1).m_strokeList.end(); ++it2) {
685           if ((*it2).m_edge.m_index == i2->m_edge.m_index &&
686               (*it2).m_gettingOut == !i2->m_gettingOut) {
687             double delta = versus * (it2->m_edge.m_w0 - i2->m_edge.m_w0);
688 
689             if (delta > 0 && delta < minDelta) {
690               it1Res   = it1;
691               it2Res   = it2;
692               minDelta = delta;
693             }
694           }
695         }
696       }
697 
698       if (minDelta != (std::numeric_limits<double>::max)()) {
699         (*it2Res).m_nextIntersection = i1;
700         (*it2Res).m_nextStroke       = i2;
701         (*it2Res).m_edge.m_w1        = i2->m_edge.m_w0;
702         (*i2).m_nextIntersection     = it1Res;
703         (*i2).m_nextStroke           = it2Res;
704         (*i2).m_edge.m_w1            = it2Res->m_edge.m_w0;
705         i1->m_numInter++;
706         it1Res->m_numInter++;
707       }
708     }
709   }
710 }
711 
712 //-----------------------------------------------------------------------------
713 void markDeadIntersections(list<Intersection> &intList,
714                            list<Intersection>::iterator it);
715 
716 // questa funzione "cuscinetto" serve perche crashava il compilatore in
717 // release!!!
markDeadIntersectionsRic(list<Intersection> & intList,list<Intersection>::iterator it)718 void inline markDeadIntersectionsRic(list<Intersection> &intList,
719                                      list<Intersection>::iterator it) {
720   markDeadIntersections(intList, it);
721 }
722 
723 //-----------------------------------------------------------------------------
724 
markDeadIntersections(list<Intersection> & intList,list<Intersection>::iterator it)725 void markDeadIntersections(list<Intersection> &intList,
726                            list<Intersection>::iterator it) {
727   list<IntersectedStroke>::iterator it1 = it->m_strokeList.begin();
728 
729   if (it->m_numInter == 1) {
730     while (it1->m_nextIntersection == intList.end()) it1++;
731     assert(it1 != it->m_strokeList.end());
732 
733     list<Intersection>::iterator nextInt         = it1->m_nextIntersection;
734     list<IntersectedStroke>::iterator nextStroke = it1->m_nextStroke;
735 
736     it->m_numInter          = 0;
737     it1->m_nextIntersection = intList.end();
738 
739     if (nextInt != intList.end() /*&& !nextStroke->m_dead*/) {
740       nextInt->m_numInter--;
741       nextStroke->m_nextIntersection = intList.end();
742       markDeadIntersectionsRic(intList, nextInt);
743     }
744   } else if (it->m_numInter == 2)  // intersezione finta (forse)
745   {
746     while (it1 != it->m_strokeList.end() &&
747            it1->m_nextIntersection == intList.end())
748       it1++;
749     assert(it1 != it->m_strokeList.end());
750     list<IntersectedStroke>::iterator it2 = it1;
751     it2++;
752     while (it2 != it->m_strokeList.end() &&
753            it2->m_nextIntersection == intList.end())
754       it2++;
755     assert(it2 != it->m_strokeList.end());
756 
757     if (it1->m_edge.m_s == it2->m_edge.m_s &&
758         it1->m_edge.m_w0 == it2->m_edge.m_w0)  // intersezione finta
759     {
760       list<IntersectedStroke>::iterator iit1, iit2;
761       assert(it1->m_nextIntersection != intList.end() &&
762              it2->m_nextIntersection != intList.end());
763 
764       iit1 = it1->m_nextStroke;
765       iit2 = it2->m_nextStroke;
766 
767       iit2->m_edge.m_w1 = iit1->m_edge.m_w0;
768       iit1->m_edge.m_w1 = iit2->m_edge.m_w0;
769 
770       // if (iit1!=0)
771       (*iit1).m_nextStroke = iit2;
772       // if (iit2!=0)
773       (*iit2).m_nextStroke = iit1;
774       // if (iit1!=0)
775       (*iit1).m_nextIntersection = it2->m_nextIntersection;
776       // if (iit2!=0)
777       (*iit2).m_nextIntersection = it1->m_nextIntersection;
778 
779       it->m_numInter          = 0;
780       it1->m_nextIntersection = intList.end();
781       it2->m_nextIntersection = intList.end();
782     }
783   }
784 }
785 
786 //-----------------------------------------------------------------------------
787 
788 // se cross val era 0, cerco di spostarmi un po' su w per vedere come sono
789 // orientate le tangenti agli stroke...
nearCrossVal(TStroke * s0,double w0,TStroke * s1,double w1)790 double nearCrossVal(TStroke *s0, double w0, TStroke *s1, double w1) {
791   double ltot0 = s0->getLength();
792   double ltot1 = s1->getLength();
793   double dl    = tmin(ltot1, ltot0) / 1000;
794 
795   double crossVal, dl0 = dl, dl1 = dl;
796 
797   TPointD p0, p1;
798   int count = 0;
799 
800   if (w0 == 1.0) dl0 = -dl0;
801   if (w1 == 1.0) dl1 = -dl1;
802 
803   double l0 = s0->getLength(w0) + dl0;
804   double l1 = s1->getLength(w1) + dl1;
805 
806   do {
807     p0       = s0->getSpeed(s0->getParameterAtLength(l0));
808     p1       = s1->getSpeed(s1->getParameterAtLength(l1));
809     crossVal = cross(p0, p1);
810     l0 += dl0, l1 += dl1;
811     count++;
812   } while (areAlmostEqual(crossVal, 0.0) &&
813            ((dl0 > 0 && l0 < ltot0) || (dl0 < 0 && l0 > 0)) &&
814            ((dl1 > 0 && l1 < ltot1) || (dl1 < 0 && l1 > 0)));
815   return crossVal;
816 }
817 
818 //-----------------------------------------------------------------------------
819 
insertBranch(Intersection & interList,IntersectedStroke & item,bool gettingOut)820 inline void insertBranch(Intersection &interList, IntersectedStroke &item,
821                          bool gettingOut) {
822   if (item.m_edge.m_w0 != (gettingOut ? 1.0 : 0.0)) {
823     item.m_gettingOut = gettingOut;
824     interList.m_strokeList.push_back(item);
825   }
826 }
827 
828 //-----------------------------------------------------------------------------
829 
getAngle(const TPointD & p0,const TPointD & p1)830 double getAngle(const TPointD &p0, const TPointD &p1) {
831   double angle1 = 180 * atan2(p0.x, p0.y) / TConsts::pi;
832   double angle2 = 180 * atan2(p1.x, p1.y) / TConsts::pi;
833 
834   if (angle1 < 0) angle1 = 360 + angle1;
835   if (angle2 < 0) angle2 = 360 + angle2;
836 
837   return (angle2 - angle1) < 0 ? 360 + angle2 - angle1 : angle2 - angle1;
838 }
839 
840 //-----------------------------------------------------------------------------
841 // nel caso l'angolo tra due stroke in un certo w sia nullo,
842 // si va un po' avanti per vedere come sono orientate....
getNearAngle(const TStroke * s1,double w1,bool out1,const TStroke * s2,double w2,bool out2)843 double getNearAngle(const TStroke *s1, double w1, bool out1, const TStroke *s2,
844                     double w2, bool out2) {
845   bool verse1  = (out1 && w1 < 1) || (!out1 && w1 == 0);
846   bool verse2  = (out2 && w2 < 1) || (!out2 && w2 == 0);
847   double ltot1 = s1->getLength();
848   double ltot2 = s2->getLength();
849   double l1    = s1->getLength(w1);
850   double l2    = s2->getLength(w2);
851   double dl    = min(ltot1, ltot2) / 1000;
852   double dl1   = verse1 ? dl : -dl;
853   double dl2   = verse2 ? dl : -dl;
854 
855   while (((verse1 && l1 < ltot1) || (!verse1 && l1 > 0)) &&
856          ((verse2 && l2 < ltot2) || (!verse2 && l2 > 0))) {
857     l1 += dl1;
858     l2 += dl2;
859     TPointD p1   = (out1 ? 1 : -1) * s1->getSpeed(s1->getParameterAtLength(l1));
860     TPointD p2   = (out2 ? 1 : -1) * s2->getSpeed(s2->getParameterAtLength(l2));
861     double angle = getAngle(p1, p2);
862     if (!areAlmostEqual(angle, 0, 1e-9)) return angle;
863   }
864   return 0;
865 }
866 
867 //-----------------------------------------------------------------------------
868 
makeEdgeIntersection(Intersection & interList,IntersectedStroke & item1,IntersectedStroke & item2,const TPointD & p1a,const TPointD & p1b,const TPointD & p2a,const TPointD & p2b)869 bool makeEdgeIntersection(Intersection &interList, IntersectedStroke &item1,
870                           IntersectedStroke &item2, const TPointD &p1a,
871                           const TPointD &p1b, const TPointD &p2a,
872                           const TPointD &p2b) {
873   double angle1 = getAngle(p1a, p1b);
874   double angle2 = getAngle(p1a, p2a);
875   double angle3 = getAngle(p1a, p2b);
876   double angle;
877 
878   bool eraseP1b = false, eraseP2a = false, eraseP2b = false;
879 
880   if (areAlmostEqual(angle1, 0, 1e-9)) {
881     angle1 = getNearAngle(item1.m_edge.m_s, item1.m_edge.m_w0, true,
882                           item1.m_edge.m_s, item1.m_edge.m_w0, false);
883     if (areAlmostEqual(angle1, 1e-9)) eraseP1b = true;
884   }
885   if (areAlmostEqual(angle2, 0, 1e-9)) {
886     angle2 = getNearAngle(item1.m_edge.m_s, item1.m_edge.m_w0, true,
887                           item2.m_edge.m_s, item2.m_edge.m_w0, true);
888     if (areAlmostEqual(angle2, 1e-9)) eraseP2a = true;
889   }
890   if (areAlmostEqual(angle3, 0, 1e-9)) {
891     angle3 = getNearAngle(item1.m_edge.m_s, item1.m_edge.m_w0, true,
892                           item2.m_edge.m_s, item2.m_edge.m_w0, false);
893     if (areAlmostEqual(angle3, 1e-9)) eraseP2b = true;
894   }
895 
896   if (areAlmostEqual(angle1, angle2, 1e-9)) {
897     angle = getNearAngle(item1.m_edge.m_s, item1.m_edge.m_w0, false,
898                          item2.m_edge.m_s, item2.m_edge.m_w0, true);
899     if (angle != 0) {
900       angle2 += angle;
901       if (angle2 > 360) angle2 -= 360;
902     } else
903       eraseP2a = true;
904   }
905   if (areAlmostEqual(angle1, angle3, 1e-9)) {
906     angle = getNearAngle(item1.m_edge.m_s, item1.m_edge.m_w0, false,
907                          item2.m_edge.m_s, item2.m_edge.m_w0, false);
908     if (angle != 0) {
909       angle3 += angle;
910       if (angle3 > 360) angle3 -= 360;
911     } else
912       eraseP2b = true;
913   }
914   if (areAlmostEqual(angle2, angle3, 1e-9)) {
915     angle = getNearAngle(item1.m_edge.m_s, item1.m_edge.m_w0, false,
916                          item2.m_edge.m_s, item2.m_edge.m_w0, true);
917     if (angle != 0) {
918       angle3 += angle;
919       if (angle3 > 360) angle3 -= 360;
920     } else
921       eraseP2b = true;
922   }
923 
924   int fac =
925       (angle1 < angle2) | ((angle1 < angle3) << 1) | ((angle2 < angle3) << 2);
926 
927   switch (fac) {
928     CASE 0 :  // p1a p2b p2a p1b
929               insertBranch(interList, item1, true);
930     if (!eraseP2b) insertBranch(interList, item2, false);
931     if (!eraseP2a) insertBranch(interList, item2, true);
932     if (!eraseP1b) insertBranch(interList, item1, false);
933     CASE 1 :  // p1a p2b p1b p2a
934               insertBranch(interList, item1, true);
935     if (!eraseP2b) insertBranch(interList, item2, false);
936     if (!eraseP1b) insertBranch(interList, item1, false);
937     if (!eraseP2a) insertBranch(interList, item2, true);
938     CASE 2 : assert(false);
939     CASE 3 :  // p1a p1b p2b p2a
940               insertBranch(interList, item1, true);
941     if (!eraseP1b) insertBranch(interList, item1, false);
942     if (!eraseP2b) insertBranch(interList, item2, false);
943     if (!eraseP2a) insertBranch(interList, item2, true);
944     CASE 4 :  // p1a p2a p2b p1b
945               insertBranch(interList, item1, true);
946     if (!eraseP2a) insertBranch(interList, item2, true);
947     if (!eraseP2b) insertBranch(interList, item2, false);
948     if (!eraseP1b) insertBranch(interList, item1, false);
949     CASE 5 : assert(false);
950     CASE 6 :  // p1a p2a p1b p2b
951               insertBranch(interList, item1, true);
952     if (!eraseP2a) insertBranch(interList, item2, true);
953     if (!eraseP1b) insertBranch(interList, item1, false);
954     if (!eraseP2b) insertBranch(interList, item2, false);
955     CASE 7 :  // p1a p1b p2a p2b
956               insertBranch(interList, item1, true);
957     if (!eraseP1b) insertBranch(interList, item1, false);
958     if (!eraseP2a) insertBranch(interList, item2, true);
959     if (!eraseP2b) insertBranch(interList, item2, false);
960   DEFAULT:
961     assert(false);
962   }
963 
964   return true;
965 }
966 
967 //-----------------------------------------------------------------------------
968 
makeIntersection(IntersectionData & intData,const vector<VIStroke * > & s,int ii,int jj,DoublePair inter,int strokeSize,Intersection & interList)969 bool makeIntersection(IntersectionData &intData, const vector<VIStroke *> &s,
970                       int ii, int jj, DoublePair inter, int strokeSize,
971                       Intersection &interList) {
972   IntersectedStroke item1(intData.m_intList.end(), NULL_ITER),
973       item2(intData.m_intList.end(), NULL_ITER);
974 
975   interList.m_intersection = s[ii]->m_s->getPoint(inter.first);
976 
977   item1.m_edge.m_w0 = inter.first;
978   item2.m_edge.m_w0 = inter.second;
979 
980   if (ii >= 0 && ii < strokeSize) {
981     item1.m_edge.m_s     = s[ii]->m_s;
982     item1.m_edge.m_index = ii;
983   } else {
984     if (ii < 0) {
985       item1.m_edge.m_s     = intData.m_autocloseMap[ii];
986       item1.m_edge.m_index = ii;
987     } else {
988       item1.m_edge.m_s     = s[ii]->m_s;
989       item1.m_edge.m_index = -(ii + intData.maxAutocloseId * 100000);
990       intData.m_autocloseMap[item1.m_edge.m_index] = item1.m_edge.m_s;
991     }
992   }
993 
994   if (jj >= 0 && jj < strokeSize) {
995     item2.m_edge.m_s     = s[jj]->m_s;
996     item2.m_edge.m_index = jj;
997   } else {
998     if (jj < 0) {
999       item2.m_edge.m_s     = intData.m_autocloseMap[jj];
1000       item2.m_edge.m_index = jj;
1001     } else {
1002       item2.m_edge.m_s     = s[jj]->m_s;
1003       item2.m_edge.m_index = -(jj + intData.maxAutocloseId * 100000);
1004       intData.m_autocloseMap[item2.m_edge.m_index] = item2.m_edge.m_s;
1005     }
1006   }
1007 
1008   bool reversed = false;
1009 
1010   TPointD p0, p0b, p1, p1b;
1011 
1012   bool ret1 = item1.m_edge.m_s->getSpeedTwoValues(item1.m_edge.m_w0, p0, p0b);
1013   bool ret2 = item2.m_edge.m_s->getSpeedTwoValues(item2.m_edge.m_w0, p1, p1b);
1014 
1015   if (ret1 || ret2)  // punto angoloso!!!!
1016     return makeEdgeIntersection(interList, item1, item2, p0, p0b, p1, p1b);
1017 
1018   double crossVal = cross(p0, p1);
1019 
1020   // crossVal = cross(p0, p1);
1021 
1022   if (areAlmostEqual(crossVal, 0.0)) {
1023     bool endpoint1 = (item1.m_edge.m_w0 == 0.0 || item1.m_edge.m_w0 == 1.0);
1024     bool endpoint2 = (item2.m_edge.m_w0 == 0.0 || item2.m_edge.m_w0 == 1.0);
1025     if (endpoint1 && endpoint2 && ((p0.x * p1.x >= 0 && p0.y * p1.y >= 0 &&
1026                                     item1.m_edge.m_w0 != item2.m_edge.m_w0) ||
1027                                    (p0.x * p1.x <= 0 && p0.y * p1.y <= 0 &&
1028                                     item1.m_edge.m_w0 == item2.m_edge.m_w0)))
1029     // due endpoint a 180 gradi;metto
1030     {
1031       item1.m_gettingOut = (item1.m_edge.m_w0 == 0.0);
1032       interList.m_strokeList.push_back(item1);
1033       item2.m_gettingOut = (item2.m_edge.m_w0 == 0.0);
1034       interList.m_strokeList.push_back(item2);
1035       return true;
1036     }
1037     // crossVal = nearCrossVal(item1.m_edge.m_s, item1.m_edge.m_w0,
1038     // item2.m_edge.m_s, item2.m_edge.m_w0);
1039     // if (areAlmostEqual(crossVal, 0.0))
1040     // return false;
1041     return makeEdgeIntersection(interList, item1, item2, p0, p0b, p1, p1b);
1042   }
1043 
1044   if (crossVal > 0)
1045     reversed = true;  // std::reverse(interList.m_strokeList.begin(),
1046                       // interList.m_strokeList.end());
1047 
1048   if (item1.m_edge.m_w0 != 1.0) {
1049     item1.m_gettingOut = true;
1050     interList.m_strokeList.push_back(item1);
1051   }
1052   if (item2.m_edge.m_w0 != (reversed ? 0.0 : 1.0)) {
1053     item2.m_gettingOut = !reversed;
1054     interList.m_strokeList.push_back(item2);
1055   }
1056   if (item1.m_edge.m_w0 != 0.0) {
1057     item1.m_gettingOut = false;
1058     interList.m_strokeList.push_back(item1);
1059   }
1060   if (item2.m_edge.m_w0 != (reversed ? 1.0 : 0.0)) {
1061     item2.m_gettingOut = reversed;
1062     interList.m_strokeList.push_back(item2);
1063   }
1064 
1065   return true;
1066 }
1067 
1068 //-----------------------------------------------------------------------------
1069 /*
1070 void checkAuto(const vector<VIStroke*>& s)
1071 {
1072 for (int i=0; i<(int)s.size(); i++)
1073 for (int j=i+1; j<(int)s.size(); j++)
1074   if (s[i]->m_s->getChunkCount()==1 && s[j]->m_s->getChunkCount()==1) //se ha
1075 una sola quadratica, probabilmente e' un autoclose.
1076           {
1077                 const TThickQuadratic*q = s[i]->m_s->getChunk(0);
1078                 const TThickQuadratic*p = s[j]->m_s->getChunk(0);
1079 
1080                 if (areAlmostEqual(q->getP0(), p->getP0(), 1e-2) &&
1081 areAlmostEqual(q->getP2(), p->getP2(), 1e-2))
1082                   assert(!"eccolo!");
1083                 if (areAlmostEqual(q->getP0(), p->getP2(), 1e-2) &&
1084 areAlmostEqual(q->getP2(), p->getP0(), 1e-2))
1085                   assert(!"eccolo!");
1086     }
1087 }
1088 */
1089 //-----------------------------------------------------------------------------
1090 
addAutocloseIntersection(IntersectionData & intData,vector<VIStroke * > & s,int ii,int jj,double w0,double w1,int strokeSize)1091 bool addAutocloseIntersection(IntersectionData &intData, vector<VIStroke *> &s,
1092                               int ii, int jj, double w0, double w1,
1093                               int strokeSize) {
1094   list<Intersection>::reverse_iterator rit = intData.m_intList.rbegin();
1095 
1096   assert(w0 >= 0.0 && w0 <= 1.0);
1097   assert(w1 >= 0.0 && w1 <= 1.0);
1098 
1099   for (; rit != intData.m_intList.rend();
1100        rit++)  // evito di fare la connessione, se gia' ce
1101                // ne e' una simile tra le stesse due stroke
1102   {
1103     if (rit->m_strokeList.size() < 2) continue;
1104     list<IntersectedStroke>::iterator is = rit->m_strokeList.begin();
1105     int s0                               = is->m_edge.m_index;
1106     if (s0 < 0) continue;
1107     double ww0 = is->m_edge.m_w0;
1108     is++;
1109     if (is->m_edge.m_index == s0 && is->m_edge.m_w0 == ww0) {
1110       is++;
1111       if (is == rit->m_strokeList.end()) continue;
1112     }
1113     int s1 = is->m_edge.m_index;
1114     if (s1 < 0) continue;
1115     double ww1 = is->m_edge.m_w0;
1116 
1117     if (!((s0 == ii && s1 == jj) || (s0 == jj && s1 == ii))) continue;
1118 
1119     if (s0 == ii && areAlmostEqual(w0, ww0, 0.1) &&
1120         areAlmostEqual(w1, ww1, 0.1))
1121       return false;
1122     else if (s1 == ii && areAlmostEqual(w0, ww1, 0.1) &&
1123              areAlmostEqual(w1, ww0, 0.1))
1124       return false;
1125   }
1126 
1127   vector<TPointD> v;
1128   v.push_back(s[ii]->m_s->getPoint(w0));
1129   v.push_back(s[jj]->m_s->getPoint(w1));
1130   if (v[0] == v[1])  // le stroke si intersecano , ma la fottuta funzione
1131                      // intersect non ha trovato l'intersezione(tipicamente,
1132                      // questo accade agli estremi)!!!
1133   {
1134     addIntersection(intData, s, ii, jj, DoublePair(w0, w1), strokeSize);
1135     return true;
1136   }
1137 
1138   // se gia e' stato messo questo autoclose, evito
1139   for (int i = 0; i < (int)s.size(); i++)
1140     if (s[i]->m_s->getChunkCount() ==
1141         1)  // se ha una sola quadratica, probabilmente e' un autoclose.
1142     {
1143       const TThickQuadratic *q = s[i]->m_s->getChunk(0);
1144 
1145       if (areAlmostEqual(q->getP0(), v[0], 1e-2) &&
1146               areAlmostEqual(q->getP2(), v[1], 1e-2) ||
1147           areAlmostEqual(q->getP0(), v[1], 1e-2) &&
1148               areAlmostEqual(q->getP2(), v[0], 1e-2)) {
1149         return true;
1150         addIntersection(intData, s, i, ii, DoublePair(0.0, w0), strokeSize);
1151         addIntersection(intData, s, i, jj, DoublePair(1.0, w1), strokeSize);
1152         return true;
1153       }
1154     }
1155 
1156   s.push_back(new VIStroke(new TStroke(v)));
1157   addIntersection(intData, s, s.size() - 1, ii, DoublePair(0.0, w0),
1158                   strokeSize);
1159   addIntersection(intData, s, s.size() - 1, jj, DoublePair(1.0, w1),
1160                   strokeSize);
1161   return true;
1162 }
1163 
1164 //-----------------------------------------------------------------------------
1165 
1166 double g_autocloseTolerance = c_newAutocloseTolerance;
1167 
makeEndPointConnections(vector<VIStroke * > & s,int ii,bool isIStartPoint,int jj,bool isJStartPoint,IntersectionData & intData,int strokeSize)1168 bool makeEndPointConnections(vector<VIStroke *> &s, int ii, bool isIStartPoint,
1169                              int jj, bool isJStartPoint,
1170                              IntersectionData &intData, int strokeSize) {
1171   double x0 = (isIStartPoint ? 0.0 : 1.0);
1172   double x1 = (isJStartPoint ? 0.0 : 1.0);
1173 
1174   TThickPoint p0 = s[ii]->m_s->getThickPoint(x0);
1175   TThickPoint p1 = s[jj]->m_s->getThickPoint(x1);
1176   double dist2;
1177 
1178   dist2 = tdistance2(p0, p1);
1179   if (dist2 >= 0 &&
1180       dist2 <=
1181           tmax((g_autocloseTolerance == c_oldAutocloseTolerance) ? 9.09 : 2.0,
1182                g_autocloseTolerance * (p0.thick + p1.thick) *
1183                    (p0.thick +
1184                     p1.thick)))  // 0.01 tiene conto di quando thick==0
1185   {
1186     if (ii == jj) {
1187       TRectD r = s[ii]->m_s->getBBox();  // se e' un autoclose su una stroke
1188                                          // piccolissima, creerebbe uan area
1189                                          // trascurabile, ignoro
1190       if (fabs(r.x1 - r.x0) < 2 && fabs(r.y1 - r.y0) < 2) return false;
1191     }
1192     return addAutocloseIntersection(intData, s, ii, jj, x0, x1, strokeSize);
1193   }
1194 
1195   return false;
1196 }
1197 /*
1198 if (s[ii]==s[jj])
1199   return;
1200 
1201 dist2 = c_autocloseTolerance*tdistance2(p01, p10);
1202 if (dist2>0 && dist2<=(p01.thick+p10.thick)*(p01.thick+p10.thick))
1203   addAutocloseIntersection(intData, s, ii, jj, 1.0, 0.0, strokeSize);
1204 
1205 
1206 dist2 = c_autocloseTolerance*tdistance2(p00, p10);
1207 if ((dist2>0 && dist2<=(p00.thick+p10.thick)*(p00.thick+p10.thick)))
1208   addAutocloseIntersection(intData, s, ii, jj, 0.0, 0.0, strokeSize);
1209 
1210 dist2 = c_autocloseTolerance*tdistance2(p01, p11);
1211 if ((dist2>0 && dist2<=(p01.thick+p11.thick)*(p01.thick+p11.thick)))
1212   addAutocloseIntersection(intData, s, ii, jj, 1.0, 1.0, strokeSize);
1213 }
1214 */
1215 //-----------------------------------------------------------------------------
1216 
getCurlW(TStroke * s,bool isBegin)1217 double getCurlW(TStroke *s, bool isBegin)  // trova il punto di split su una
1218                                            // stroke, in prossimita di un
1219                                            // ricciolo;
1220 // un ricciolo c'e' se la curva ha un  min o max relativo su x seguito da uno su
1221 // y, o viceversa.
1222 {
1223   int numChunks = s->getChunkCount();
1224   double dx2, dx1 = 0, dy2, dy1 = 0;
1225 
1226   for (int i = 0; i < numChunks; i++) {
1227     const TQuadratic *q = s->getChunk(isBegin ? i : numChunks - 1 - i);
1228     dy2                 = q->getP1().y - q->getP0().y;
1229     if (dy1 * dy2 < 0) break;
1230     dy1 = dy2;
1231     dy2 = q->getP2().y - q->getP1().y;
1232     if (dy1 * dy2 < 0) break;
1233     dy1 = dy2;
1234   }
1235   if (i == numChunks) return -1;
1236 
1237   int maxMin0 = isBegin ? i : numChunks - 1 - i;
1238 
1239   for (int j = 0; j < numChunks; j++) {
1240     const TQuadratic *q = s->getChunk(isBegin ? j : numChunks - 1 - j);
1241     dx2                 = q->getP1().x - q->getP0().x;
1242     if (dx1 * dx2 < 0) break;
1243     dx1 = dx2;
1244     dx2 = q->getP2().x - q->getP1().x;
1245     if (dx1 * dx2 < 0) break;
1246     dx1 = dx2;
1247   }
1248   if (j == numChunks) return -1;
1249 
1250   int maxMin1 = isBegin ? j : numChunks - 1 - j;
1251 
1252   return getWfromChunkAndT(
1253       s, isBegin ? tmax(maxMin0, maxMin1) : tmin(maxMin0, maxMin1),
1254       isBegin ? 1.0 : 0.0);
1255 }
1256 
1257 #ifdef Levo
1258 bool lastIsX = false, lastIsY = false;
1259 for (int i = 0; i < numChunks; i++) {
1260   const TThickQuadratic *q = s->getChunk(isBegin ? i : numChunks - 1 - i);
1261   if ((q->getP0().y < q->getP1().y &&
1262        q->getP2().y <
1263            q->getP1().y) ||  // la quadratica ha un minimo o massimo relativo
1264       (q->getP0().y > q->getP1().y && q->getP2().y > q->getP1().y)) {
1265     double w = getWfromChunkAndT(s, isBegin ? i : numChunks - 1 - i,
1266                                  isBegin ? 1.0 : 0.0);
1267     if (lastIsX)  // e' il secondo min o max relativo
1268       return w;
1269     lastIsX = false;
1270     lastIsY = true;
1271 
1272   } else if ((q->getP0().x < q->getP1().x &&
1273               q->getP2().x <
1274                   q->getP1()
1275                       .x) ||  // la quadratica ha un minimo o massimo relativo
1276              (q->getP0().x > q->getP1().x && q->getP2().x > q->getP1().x)) {
1277     double w = getWfromChunkAndT(s, isBegin ? i : numChunks - 1 - i,
1278                                  isBegin ? 1.0 : 0.0);
1279     if (lastIsY)  // e' il secondo min o max relativo
1280       return w;
1281     lastIsX = true;
1282     lastIsY = false;
1283   }
1284 }
1285 
1286 return -1;
1287 }
1288 
1289 #endif
1290 //-----------------------------------------------------------------------------
1291 
1292 void makeConnection(vector<VIStroke *> &s, int ii, int jj, bool isBegin,
1293                     IntersectionData &intData, int strokeSize) {
1294   if (s[ii]->m_s->isSelfLoop()) return;
1295 
1296   double w0 = isBegin ? 0.0 : 1.0;
1297 
1298   TThickPoint p0 = s[ii]->m_s->getThickPoint(w0);
1299   double t, dist2;
1300   int index;
1301   TStroke sAux, *sComp;
1302 
1303   if (ii == jj)  // per trovare le intersezioni con una stroke e se stessa, si
1304                  // toglie il
1305   // pezzo di stroke di cui si cercano vicinanze fino alla prima curva
1306   {
1307     double w = getCurlW(s[ii]->m_s, isBegin);
1308     if (w == -1) return;
1309 
1310     split<TStroke>(*(s[ii]->m_s), tmin(isBegin ? 1.0 : 0.0, w),
1311                    tmax(isBegin ? 1.0 : 0.0, w), sAux);
1312     sComp = &sAux;
1313   } else
1314     sComp = s[jj]->m_s;
1315 
1316   if (sComp->getNearestChunk(p0, t, index, dist2) && dist2 > 0) {
1317     if (ii == jj) {
1318       double dummy;
1319       s[jj]->m_s->getNearestChunk(sComp->getChunk(index)->getPoint(t), t, index,
1320                                   dummy);
1321     }
1322 
1323     // if (areAlmostEqual(w, 0.0, 0.05) || areAlmostEqual(w, 1.0, 0.05))
1324     //  return; //se w e' vicino ad un estremo, rientra nell'autoclose point to
1325     //  point
1326 
1327     // if (s[jj]->m_s->getLength(w)<=s[jj]->m_s->getThickPoint(0).thick ||
1328     //    s[jj]->m_s->getLength(w, 1)<=s[jj]->m_s->getThickPoint(1).thick)
1329     //  return;
1330 
1331     TThickPoint p1 = s[jj]->m_s->getChunk(index)->getThickPoint(t);
1332     if (dist2 <=
1333         (tmax(
1334             (g_autocloseTolerance == c_oldAutocloseTolerance) ? 9.09 : 2.0,
1335             (g_autocloseTolerance + 0.7) * (p0.thick + p1.thick) *
1336                 (p0.thick + p1.thick))))  // 0.01 tiene conto di quando thick==0
1337     {
1338       // if (areAlmostEqual(dist2, 0.0))
1339       //  return;
1340       double w = getWfromChunkAndT(s[jj]->m_s, index, t);
1341       addAutocloseIntersection(intData, s, ii, jj, w0, w, strokeSize);
1342     }
1343   }
1344 }
1345 
1346 //-----------------------------------------------------------------------------
1347 
1348 void autoclose(vector<VIStroke *> &s, int ii, int jj, IntersectionData &IntData,
1349                int strokeSize) {
1350   bool ret1 = false, ret2 = false, ret3 = false, ret4 = false;
1351 
1352   if (!s[ii]->m_s->isSelfLoop() && !s[jj]->m_s->isSelfLoop()) {
1353     ret1 = makeEndPointConnections(s, ii, true, jj, false, IntData, strokeSize);
1354 
1355     if (ii != jj) {
1356       ret2 =
1357           makeEndPointConnections(s, ii, true, jj, true, IntData, strokeSize);
1358       ret3 =
1359           makeEndPointConnections(s, ii, false, jj, true, IntData, strokeSize);
1360       ret4 =
1361           makeEndPointConnections(s, ii, false, jj, false, IntData, strokeSize);
1362     }
1363   }
1364 
1365   if (!ret1 && !ret2) makeConnection(s, ii, jj, true, IntData, strokeSize);
1366   if (!ret1 && !ret4) makeConnection(s, jj, ii, false, IntData, strokeSize);
1367   if (ii != jj) {
1368     if (!ret2 && !ret3) makeConnection(s, jj, ii, true, IntData, strokeSize);
1369     if (!ret3 && !ret4) makeConnection(s, ii, jj, false, IntData, strokeSize);
1370   }
1371 }
1372 
1373 //-----------------------------------------------------------------------------
1374 
1375 TPointD inline getTangent(const IntersectedStroke &item) {
1376   return (item.m_gettingOut ? 1 : -1) *
1377          item.m_edge.m_s->getSpeed(item.m_edge.m_w0, item.m_gettingOut);
1378 }
1379 
1380 //-----------------------------------------------------------------------------
1381 
1382 void addBranch(IntersectionData &intData, list<IntersectedStroke> &strokeList,
1383                const vector<VIStroke *> &s, int ii, double w, int strokeSize,
1384                bool gettingOut) {
1385   list<IntersectedStroke>::iterator it1, it2;
1386   TPointD tanRef, lastTan;
1387 
1388   IntersectedStroke item(intData.m_intList.end(), strokeList.end());
1389 
1390   if (ii < 0) {
1391     item.m_edge.m_s     = intData.m_autocloseMap[ii];
1392     item.m_edge.m_index = ii;
1393   } else {
1394     item.m_edge.m_s = s[ii]->m_s;
1395     if (ii < strokeSize)
1396       item.m_edge.m_index = ii;
1397     else {
1398       item.m_edge.m_index = -(ii + intData.maxAutocloseId * 100000);
1399       intData.m_autocloseMap[item.m_edge.m_index] = item.m_edge.m_s;
1400     }
1401   }
1402 
1403   item.m_edge.m_w0  = w;
1404   item.m_gettingOut = gettingOut;
1405 
1406   /*
1407 if (strokeList.size()==2) //potrebbero essere orientati male; due branch possono
1408 stare come vogliono, ma col terzo no.
1409 {
1410 TPointD tan2 = getTangent(strokeList.back());
1411 TPointD aux= getTangent(*(strokeList.begin()));
1412 double crossVal = cross(aux, tan2);
1413 if (areAlmostEqual(aux, tan2, 1e-3))
1414     return;
1415 
1416   if (crossVal>0)
1417 {
1418           std::reverse(strokeList.begin(), strokeList.end());
1419 //tan2 = getTangent(strokeList.back());
1420           }
1421 }
1422 */
1423   /*
1424 if (areAlmostEqual(lastCross, 0.0) && tan1.x*tan2.x>=0 && tan1.y*tan2.y>=0)
1425 //significa angolo tra tangenti nullo
1426     {
1427           crossVal =  nearCrossVal(item.m_edge.m_s, item.m_edge.m_w0,
1428 strokeList.back().m_edge.m_s, strokeList.back().m_edge.m_w0);
1429 if (areAlmostEqual(crossVal, 0.0))
1430             return;
1431           if (!strokeList.back().m_gettingOut)
1432             crossVal = -crossVal;
1433 }
1434 */
1435 
1436   tanRef  = getTangent(item);
1437   lastTan = getTangent(strokeList.back());
1438   /*
1439 for (it=strokeList.begin(); it!=strokeList.end(); ++it)
1440 {
1441   TPointD curTan = getTangent(*it);
1442 double angle0 = getAngle(lastTan, curTan);
1443 double angle1 = getAngle(lastTan, tanRef);
1444 
1445 if (areAlmostEqual(angle0, angle1, 1e-8))
1446     {
1447           double angle = getNearAngle( it->m_edge.m_s,  it->m_edge.m_w0,
1448 it->m_gettingOut,
1449                                       item.m_edge.m_s, item.m_edge.m_w0,
1450 item.m_gettingOut);
1451 angle1 += angle; if (angle1>360) angle1-=360;
1452 }
1453 
1454 if (angle1<angle0)
1455 {
1456 strokeList.insert(it, item);
1457 return;
1458 }
1459   lastTan=curTan;
1460 }*/
1461 
1462   it2 = strokeList.end();
1463   it2--;
1464   for (it1 = strokeList.begin(); it1 != strokeList.end(); ++it1) {
1465     TPointD curTan = getTangent(*it1);
1466     double angle0  = getAngle(lastTan, curTan);
1467     double angle1  = getAngle(lastTan, tanRef);
1468 
1469     if (areAlmostEqual(angle1, 0, 1e-8)) {
1470       double angle =
1471           getNearAngle(it2->m_edge.m_s, it2->m_edge.m_w0, it2->m_gettingOut,
1472                        item.m_edge.m_s, item.m_edge.m_w0, item.m_gettingOut);
1473       angle1 += angle;
1474       if (angle1 > 360) angle1 -= 360;
1475     }
1476 
1477     if (areAlmostEqual(angle0, angle1, 1e-8)) {
1478       double angle =
1479           getNearAngle(it1->m_edge.m_s, it1->m_edge.m_w0, it1->m_gettingOut,
1480                        item.m_edge.m_s, item.m_edge.m_w0, item.m_gettingOut);
1481       angle1 += angle;
1482       if (angle1 > 360) angle1 -= 360;
1483     }
1484 
1485     if (angle1 < angle0) {
1486       strokeList.insert(it1, item);
1487       return;
1488     }
1489     lastTan = curTan;
1490     it2     = it1;
1491   }
1492 
1493   // assert(!"add branch: can't find where to insert!");
1494   strokeList.push_back(item);
1495 }
1496 
1497 //-----------------------------------------------------------------------------
1498 
1499 void addBranches(IntersectionData &intData, Intersection &intersection,
1500                  const vector<VIStroke *> &s, int ii, int jj,
1501                  DoublePair intersectionPair, int strokeSize) {
1502   bool foundS1 = false, foundS2 = false;
1503   list<IntersectedStroke>::iterator it;
1504 
1505   assert(!intersection.m_strokeList.empty());
1506 
1507   for (it = intersection.m_strokeList.begin();
1508        it != intersection.m_strokeList.end(); it++) {
1509     if ((ii >= 0 && (*it).m_edge.m_s == s[ii]->m_s &&
1510          it->m_edge.m_w0 == intersectionPair.first) ||
1511         (ii < 0 && (*it).m_edge.m_index == ii &&
1512          it->m_edge.m_w0 == intersectionPair.first))
1513       foundS1 = true;
1514     if ((jj >= 0 && (*it).m_edge.m_s == s[jj]->m_s &&
1515          it->m_edge.m_w0 == intersectionPair.second) ||
1516         (jj < 0 && (*it).m_edge.m_index == jj &&
1517          it->m_edge.m_w0 == intersectionPair.second))
1518       foundS2 = true;
1519   }
1520 
1521   if (foundS1 && foundS2) {
1522     /*
1523 //errore!(vedi commento sotto) possono essere un sacco di intersezioni
1524 coincidenti se passano per l'estremo di una quad
1525 //significa che ci sono due intersezioni coincidenti. cioe' due stroke tangenti.
1526 quindi devo invertire l'ordine di due branch enlla rosa dei branch.
1527 list<IntersectedStroke>::iterator it1, it2;
1528 it1=intersection.m_strokeList.begin();
1529 it2 = it1; it2++;
1530 for (; it2!=intersection.m_strokeList.end(); ++it1, ++it2)
1531 {
1532 if ((*it1).m_gettingOut!=(*it2).m_gettingOut &&((*it1).m_edge.m_index==jj &&
1533 (*it2).m_edge.m_index==ii) ||
1534         ((*it1).m_edge.m_index==ii && (*it2).m_edge.m_index==jj))
1535 {
1536             IntersectedStroke& el1 = (*it1);
1537             IntersectedStroke& el2 = (*it2);
1538 IntersectedStroke app;
1539             app = el1;
1540             el1=el2;
1541             el2=app;
1542             break;
1543 }
1544     }
1545 */
1546     return;
1547   }
1548 
1549   if (!foundS1) {
1550     if (intersectionPair.first != 1)
1551       addBranch(intData, intersection.m_strokeList, s, ii,
1552                 intersectionPair.first, strokeSize, true);
1553     if (intersectionPair.first != 0)
1554       addBranch(intData, intersection.m_strokeList, s, ii,
1555                 intersectionPair.first, strokeSize, false);
1556     // assert(intersection.m_strokeList.size()-size>0);
1557   }
1558   if (!foundS2) {
1559     if (intersectionPair.second != 1)
1560       addBranch(intData, intersection.m_strokeList, s, jj,
1561                 intersectionPair.second, strokeSize, true);
1562     if (intersectionPair.second != 0)
1563       addBranch(intData, intersection.m_strokeList, s, jj,
1564                 intersectionPair.second, strokeSize, false);
1565     // intersection.m_numInter+=intersection.m_strokeList.size()-size;
1566     // assert(intersection.m_strokeList.size()-size>0);
1567   }
1568 }
1569 
1570 //-----------------------------------------------------------------------------
1571 
1572 void addIntersections(IntersectionData &intData, const vector<VIStroke *> &s,
1573                       int ii, int jj, vector<DoublePair> &intersections,
1574                       int strokeSize) {
1575   for (int k = 0; k < (int)intersections.size(); k++) {
1576     if (ii >= strokeSize && (areAlmostEqual(intersections[k].first, 0.0) ||
1577                              areAlmostEqual(intersections[k].first, 1.0)))
1578       continue;
1579     if (jj >= strokeSize && (areAlmostEqual(intersections[k].second, 0.0) ||
1580                              areAlmostEqual(intersections[k].second, 1.0)))
1581       continue;
1582 
1583     addIntersection(intData, s, ii, jj, intersections[k], strokeSize);
1584   }
1585 }
1586 
1587 //-----------------------------------------------------------------------------
1588 
1589 inline double truncate(double x) {
1590   x += 1.0;
1591   unsigned long *l = (unsigned long *)&x;
1592 
1593 #if TNZ_LITTLE_ENDIAN
1594   l[0] &= 0xFFE00000;
1595 #else
1596   l[1] &= 0xFFE00000;
1597 #endif
1598 
1599   return x - 1.0;
1600 }
1601 
1602 //-----------------------------------------------------------------------------
1603 
1604 void addIntersection(IntersectionData &intData, const vector<VIStroke *> &s,
1605                      int ii, int jj, DoublePair intersection, int strokeSize) {
1606   list<Intersection>::iterator it;
1607   TPointD p;
1608 
1609   // UINT iw;
1610   // iw = ((UINT)(intersection.first*0x3fffffff));
1611   // intersection.first = truncate(intersection.first);
1612   // iw = (UINT)(intersection.second*0x3fffffff);
1613 
1614   // intersection.second = truncate(intersection.second);
1615 
1616   if (areAlmostEqual(intersection.first, 0.0, 1e-8))
1617     intersection.first = 0.0;
1618   else if (areAlmostEqual(intersection.first, 1.0, 1e-8))
1619     intersection.first = 1.0;
1620 
1621   if (areAlmostEqual(intersection.second, 0.0, 1e-8))
1622     intersection.second = 0.0;
1623   else if (areAlmostEqual(intersection.second, 1.0, 1e-8))
1624     intersection.second = 1.0;
1625 
1626   p = s[ii]->m_s->getPoint(intersection.first);
1627 
1628   for (it = intData.m_intList.begin(); it != intData.m_intList.end(); it++)
1629     if ((*it).m_intersection ==
1630         p)  // devono essere rigorosamente uguali, altrimenti
1631     // il calcolo dell'ordine dei rami con le tangenti sballa
1632     {
1633       addBranches(intData, *it, s, ii, jj, intersection, strokeSize);
1634       return;
1635     }
1636 
1637   intData.m_intList.push_back(Intersection());
1638 
1639   if (!makeIntersection(intData, s, ii, jj, intersection, strokeSize,
1640                         intData.m_intList.back())) {
1641     list<Intersection>::iterator it = intData.m_intList.begin();
1642     advance(it, intData.m_intList.size() - 1);
1643 
1644     intData.m_intList.erase(it);
1645   }
1646 }
1647 
1648 //-----------------------------------------------------------------------------
1649 
1650 void TVectorImage::Imp::findIntersections() {
1651   vector<VIStroke *> &strokeArray = m_strokes;
1652   IntersectionData &intData       = m_intersectionData;
1653   int strokeSize                  = (int)strokeArray.size();
1654   int i, j;
1655 
1656   assert(intData.m_intersectedStrokeArray.empty());
1657 
1658   intData.maxAutocloseId++;
1659 
1660   map<int, TStroke *>::iterator it, it_b = intData.m_autocloseMap.begin();
1661   map<int, TStroke *>::iterator it_e = intData.m_autocloseMap.end();
1662 
1663   // prima cerco le intersezioni tra nuove strokes e vecchi autoclose
1664   for (i = 0; i < strokeSize; i++) {
1665     TStroke *s1 = strokeArray[i]->m_s;
1666     if (!strokeArray[i]->m_isNewForFill || strokeArray[i]->m_isPoint) continue;
1667     TRectD bBox   = s1->getBBox();
1668     double thick2 = s1->getThickPoint(0).thick * 2;
1669     if (bBox.getLx() <= thick2 && bBox.getLy() <= thick2) {
1670       strokeArray[i]->m_isPoint = true;
1671       continue;
1672     }
1673     for (int j = 0; j < (int)s1->getControlPointCount(); j++) {
1674       TThickPoint p = s1->getControlPoint(j);
1675       s1->setControlPoint(j, myRound(p));
1676     }
1677 
1678     for (it = it_b; it != it_e; ++it) {
1679       TStroke *s2 = it->second;
1680       vector<DoublePair> parIntersections;
1681       if (intersect(s1, s2, parIntersections, true))
1682         addIntersections(intData, strokeArray, i, it->first, parIntersections,
1683                          strokeSize);
1684     }
1685   }
1686 
1687   // poi,  intersezioni tra stroke, in cui almeno uno dei due deve essere nuovo
1688 
1689   for (i = 0; i < strokeSize; i++) {
1690     TStroke *s1 = strokeArray[i]->m_s;
1691     if (strokeArray[i]->m_isPoint) continue;
1692     for (j = i; j < strokeSize /*&& (strokeArray[i]->getBBox().x1>=
1693                                   strokeArray[j]->getBBox().x0)*/
1694          ;
1695          j++) {
1696       TStroke *s2 = strokeArray[j]->m_s;
1697       if (strokeArray[j]->m_isPoint) continue;
1698       if (!(strokeArray[i]->m_isNewForFill || strokeArray[j]->m_isNewForFill))
1699         continue;
1700       vector<DoublePair> parIntersections;
1701       if (s1->getBBox().overlaps(s2->getBBox())) {
1702         UINT size = intData.m_intList.size();
1703 
1704         if (intersect(s1, s2, parIntersections, false)) {
1705           // if (i==0 && j==1) parIntersections.erase(parIntersections.begin());
1706 
1707           addIntersections(intData, strokeArray, i, j, parIntersections,
1708                            strokeSize);
1709         }
1710         // autoclose(strokeArray, i, j, intData, strokeSize);
1711         if (!strokeArray[i]->m_isNewForFill &&
1712             size != intData.m_intList.size() &&
1713             !strokeArray[i]->m_edgeList.empty())  // aggiunte nuove intersezioni
1714         {
1715           intData.m_intersectedStrokeArray.push_back(IntersectedStrokeEdges(i));
1716           list<TEdge *> &_list =
1717               intData.m_intersectedStrokeArray.back().m_edgeList;
1718           list<TEdge *>::const_iterator it;
1719           for (it = strokeArray[i]->m_edgeList.begin();
1720                it != strokeArray[i]->m_edgeList.end(); ++it)
1721             _list.push_back(new TEdge(**it, false));
1722         }
1723       }
1724     }
1725     // strokeArray[i]->m_isNewForFill = false;
1726   }
1727 
1728   for (i = 0; i < strokeSize; i++) {
1729     TStroke *s1 = strokeArray[i]->m_s;
1730     if (strokeArray[i]->m_isPoint) continue;
1731     for (j = i; j < strokeSize; j++) {
1732       TStroke *s2 = strokeArray[j]->m_s;
1733       if (strokeArray[j]->m_isPoint) continue;
1734       if (!(strokeArray[i]->m_isNewForFill || strokeArray[j]->m_isNewForFill))
1735         continue;
1736       if (s1->getBBox().overlaps(s2->getBBox()))
1737         autoclose(strokeArray, i, j, intData, strokeSize);
1738     }
1739     strokeArray[i]->m_isNewForFill = false;
1740   }
1741 
1742   for (i = 0; i < strokeSize; i++) {
1743     list<TEdge *>::iterator it, it_b = strokeArray[i]->m_edgeList.begin(),
1744                                 it_e = strokeArray[i]->m_edgeList.end();
1745     for (it = it_b; it != it_e; ++it)
1746       if ((*it)->m_toBeDeleted == 1) delete *it;
1747 
1748     strokeArray[i]->m_edgeList.clear();
1749   }
1750 
1751   // si devono cercare le intersezioni con i segmenti aggiunti per l'autoclose
1752 
1753   for (i = strokeSize; i < (int)strokeArray.size(); ++i) {
1754     TStroke *s1 = strokeArray[i]->m_s;
1755 
1756     for (j = i + 1; j < (int)strokeArray.size();
1757          ++j)  // intersezione segmento-segmento
1758     {
1759       TStroke *s2 = strokeArray[j]->m_s;
1760       vector<DoublePair> parIntersections;
1761       if (intersect(s1, s2, parIntersections, true))
1762         addIntersections(intData, strokeArray, i, j, parIntersections,
1763                          strokeSize);
1764     }
1765     for (j = 0; j < strokeSize; ++j)  // intersezione segmento-curva
1766     {
1767       if (strokeArray[j]->m_isPoint) continue;
1768       TStroke *s2 = strokeArray[j]->m_s;
1769       vector<DoublePair> parIntersections;
1770       if (intersect(s1, s2, parIntersections, true))
1771         addIntersections(intData, strokeArray, i, j, parIntersections,
1772                          strokeSize);
1773     }
1774   }
1775 }
1776 
1777 // la struttura delle intersezioni viene poi visitata per trovare
1778 // i link tra un'intersezione e la successiva
1779 
1780 //-----------------------------------------------------------------------------
1781 
1782 int TVectorImage::Imp::computeIntersections() {
1783   list<Intersection>::iterator it1;
1784   list<IntersectedStroke>::iterator it2;
1785   IntersectionData &intData = m_intersectionData;
1786   int strokeSize            = (int)m_strokes.size();
1787 
1788   findIntersections();
1789 
1790   findNearestIntersection(intData.m_intList);
1791 
1792   // for (it1=intData.m_intList.begin(); it1!=intData.m_intList.end();) //la
1793   // faccio qui, e non nella eraseIntersection. vedi commento li'.
1794   eraseDeadIntersections();
1795 
1796   for (it1 = intData.m_intList.begin(); it1 != intData.m_intList.end(); it1++)
1797     markDeadIntersections(intData.m_intList, it1);
1798 
1799   // checkInterList(intData.m_intList);
1800   return strokeSize;
1801 }
1802 
1803 //-----------------------------------------------------------------------------
1804 
1805 /*
1806 void endPointIntersect(const TStroke* s0, const TStroke* s1, vector<DoublePair>&
1807 parIntersections)
1808 {
1809 TPointD p00 = s0->getPoint(0);
1810 TPointD p11 = s1->getPoint(1);
1811 if (tdistance2(p00, p11)< 2*0.06*0.06)
1812   parIntersections.push_back(DoublePair(0, 1));
1813 
1814 if (s0==s1)
1815   return;
1816 
1817 TPointD p01 = s0->getPoint(1);
1818 TPointD p10 = s1->getPoint(0);
1819 
1820 if (tdistance2(p00, p10)< 2*0.06*0.06)
1821   parIntersections.push_back(DoublePair(0, 0));
1822 if (tdistance2(p01, p10)< 2*0.06*0.06)
1823   parIntersections.push_back(DoublePair(1, 0));
1824 if (tdistance2(p01, p11)< 2*0.06*0.06)
1825   parIntersections.push_back(DoublePair(1, 1));
1826 
1827 }
1828 */
1829 //-----------------------------------------------------------------------------
1830 
1831 //-----------------------------------------------------------------------------
1832 
1833 // Trova una possibile regione data una lista di punti di intersezione
1834 TRegion *findRegion(list<Intersection> &intList,
1835                     list<Intersection>::iterator it1,
1836                     list<IntersectedStroke>::iterator it2) {
1837   TRegion *r    = new TRegion();
1838   int currStyle = 0;
1839 
1840   list<IntersectedStroke>::iterator itStart = it2;
1841   list<Intersection>::iterator nextIt1;
1842   list<IntersectedStroke>::iterator nextIt2;
1843 
1844   // Cicla finche' t2 non punta ad uno stroke gia' visitato
1845   while (!it2->m_visited) {
1846     it2->m_visited = true;
1847 
1848     // Ciclo finche' lo stroke puntato da it2 non ha un successivo punto di
1849     // intersezione
1850     do {
1851       it2++;
1852       if (it2 ==
1853           it1->m_strokeList.end())  // uso la lista come se fosse circolare
1854         it2 = it1->m_strokeList.begin();
1855     } while (it2->m_nextIntersection == intList.end());
1856 
1857     nextIt1 = it2->m_nextIntersection;
1858     nextIt2 = it2->m_nextStroke;
1859 
1860     // Viene controllato e sistemato lo stile degli stroke
1861     if (it2->m_edge.m_styleId != 0) {
1862       if (currStyle == 0)
1863         currStyle = it2->m_edge.m_styleId;
1864       else if (it2->m_edge.m_styleId != currStyle) {
1865         currStyle = it2->m_edge.m_styleId;
1866         for (UINT i                = 0; i < r->getEdgeCount(); i++)
1867           r->getEdge(i)->m_styleId = currStyle;
1868       }
1869     } else
1870       it2->m_edge.m_styleId = currStyle;
1871 
1872     // Aggiunge lo stroke puntato da p2 alla regione
1873     r->addEdge(&it2->m_edge);
1874 
1875     if (nextIt2 == itStart) return r;
1876 
1877     it1 = nextIt1;
1878     it2 = nextIt2;
1879   }
1880 
1881   delete r;
1882   return 0;
1883 }
1884 
1885 //-----------------------------------------------------------------------------
1886 /*
1887 bool areEqualRegions(const TRegion& r1, const TRegion& r2)
1888 {
1889 if (r1.getBBox()!=r2.getBBox())
1890   return false;
1891 if (r1.getEdgeCount()!=r2.getEdgeCount())
1892   return false;
1893 
1894 for (UINT i=0; i<r1.getEdgeCount(); i++)
1895   {
1896   TEdge *e1 = r1.getEdge(i);
1897   for (j=0; j<r2.getEdgeCount(); j++)
1898     {
1899     TEdge *e2 = r2.getEdge(j);
1900     if (e1->m_s==e2->m_s &&
1901         tmin(e1->m_w0, e1->m_w1)==tmin(e2->m_w0, e2->m_w1) &&
1902         tmax(e1->m_w0, e1->m_w1)==tmax(e2->m_w0, e2->m_w1))
1903       {
1904       if (e1->m_styleId && !e2->m_styleId)
1905         e2->m_styleId=e1->m_styleId;
1906       else if (e2->m_styleId && !e1->m_styleId)
1907         e1->m_styleId=e2->m_styleId;
1908       break;
1909       }
1910     }
1911   if (j==r2.getEdgeCount())  //e1 non e' uguale a nessun edge di r2
1912     return false;
1913   }
1914 
1915 
1916 return true;
1917 }
1918 */
1919 //-----------------------------------------------------------------------------
1920 /*
1921 bool isMetaRegion(const TRegion& r1, const TRegion& r2)
1922 {
1923 if (areEqualRegions(r1, r2))
1924     return true;
1925 
1926 for (UINT i=0; i<r1.getRegionCount(); i++)
1927   {
1928   if (isMetaRegion(*r1.getRegion(i), r2))
1929     return true;
1930   }
1931 return false;
1932 }
1933 
1934 //-----------------------------------------------------------------------------
1935 
1936 bool isMetaRegion(const vector<TRegion*>& m_regions, const TRegion& r)
1937 {
1938 for (UINT i=0; i<m_regions.size(); i++)
1939   if (isMetaRegion(*(m_regions[i]), r))
1940     return true;
1941 
1942 return false;
1943 }
1944 
1945 //-----------------------------------------------------------------------------
1946 */
1947 
1948 bool isValidArea(const vector<TRegion *> &regions, const TRegion &r) {
1949   double area = 0.0;
1950   TPointD p, pOld /*, pAux*/;
1951   int pointAdded = 0;
1952 
1953   int size = r.getEdgeCount();
1954 
1955   if (size == 0) return false;
1956 
1957   // if (size<2)
1958   //  return !isMetaRegion(regions, r);
1959 
1960   int firstControlPoint;
1961   int lastControlPoint;
1962 
1963   TEdge *e = r.getEdge(size - 1);
1964   pOld     = e->m_s->getPoint(e->m_w1);
1965 
1966   for (int i = 0; i < size; i++) {
1967     TEdge *e          = r.getEdge(i);
1968     TStroke *s        = e->m_s;
1969     firstControlPoint = s->getControlPointIndexAfterParameter(e->m_w0);
1970     lastControlPoint  = s->getControlPointIndexAfterParameter(e->m_w1);
1971 
1972     p = s->getPoint(e->m_w0);
1973     area += (p.y + pOld.y) * (pOld.x - p.x);
1974     pOld = p;
1975     pointAdded++;
1976     if (firstControlPoint <= lastControlPoint) {
1977       if (firstControlPoint & 0x1) firstControlPoint++;
1978       if (lastControlPoint - firstControlPoint <=
1979           2)  /// per evitare di avere troppi pochi punti....
1980       {
1981         p = s->getPoint(0.333333 * e->m_w0 + 0.666666 * e->m_w1);
1982         area += (p.y + pOld.y) * (pOld.x - p.x);
1983         pOld = p;
1984         pointAdded++;
1985         p = s->getPoint(0.666666 * e->m_w0 + 0.333333 * e->m_w1);
1986         area += (p.y + pOld.y) * (pOld.x - p.x);
1987         pOld = p;
1988         pointAdded++;
1989       } else
1990         for (int j = firstControlPoint; j < lastControlPoint; j += 2) {
1991           p = s->getControlPoint(j);
1992           area += (p.y + pOld.y) * (pOld.x - p.x);
1993           pOld = p;
1994           pointAdded++;
1995         }
1996     } else {
1997       firstControlPoint--;  // this case, getControlPointIndexBEFOREParameter
1998       lastControlPoint--;
1999       if (firstControlPoint & 0x1) firstControlPoint--;
2000       if (firstControlPoint - lastControlPoint <=
2001           2)  /// per evitare di avere troppi pochi punti....
2002       {
2003         p = s->getPoint(0.333333 * e->m_w0 + 0.666666 * e->m_w1);
2004         area += (p.y + pOld.y) * (pOld.x - p.x);
2005         pOld = p;
2006         pointAdded++;
2007         p = s->getPoint(0.666666 * e->m_w0 + 0.333333 * e->m_w1);
2008         area += (p.y + pOld.y) * (pOld.x - p.x);
2009         pOld = p;
2010         pointAdded++;
2011       } else
2012         for (int j = firstControlPoint; j > lastControlPoint; j -= 2) {
2013           p = s->getControlPoint(j);
2014           area += (p.y + pOld.y) * (pOld.x - p.x);
2015           pOld = p;
2016           pointAdded++;
2017         }
2018     }
2019     p = s->getPoint(e->m_w1);
2020     area += (p.y + pOld.y) * (pOld.x - p.x);
2021     pOld = p;
2022     pointAdded++;
2023   }
2024   assert(pointAdded >= 4);
2025 
2026   return area > 0.5;
2027 }
2028 
2029 //-----------------------------------------------------------------------------
2030 
2031 void transferColors(const list<TEdge *> &oldList, const list<TEdge *> &newList,
2032                     bool isStrokeChanged, bool isFlipped, bool overwriteColor);
2033 
2034 //-----------------------------------------------------------------------------
2035 void printStrokes1(vector<VIStroke *> &v, int size) {
2036   UINT i = 0;
2037   ofstream of("C:\\temp\\strokes.txt");
2038 
2039   for (i = 0; i < (UINT)size; i++) {
2040     TStroke *s = v[i]->m_s;
2041     of << "***stroke " << i << endl;
2042     for (UINT j = 0; j < (UINT)s->getChunkCount(); j++) {
2043       const TThickQuadratic *q = s->getChunk(j);
2044 
2045       of << "   s0 " << q->getP0() << endl;
2046       of << "   s1 " << q->getP1() << endl;
2047       of << "   s2 " << q->getP2() << endl;
2048       of << "****** " << endl;
2049     }
2050     of << endl;
2051   }
2052   for (i = size; i < v.size(); i++) {
2053     TStroke *s = v[i]->m_s;
2054     of << "***Autostroke " << i << endl;
2055     of << "s0 " << s->getPoint(0.0) << endl;
2056     of << "s1 " << s->getPoint(1.0) << endl;
2057     of << endl;
2058   }
2059 }
2060 
2061 //-----------------------------------------------------------------------------
2062 #ifdef _DEBUG
2063 static void printTime(TStopWatch &sw, string name) {
2064   ostringstream ss;
2065   ss << name << " : ";
2066   sw.print(ss);
2067   ss << '\n' << '\0';
2068   string s(ss.str());
2069   // TSystem::outputDebug(s);
2070 }
2071 #endif
2072 //-----------------------------------------------------------------------------
2073 void printStrokes1(vector<VIStroke *> &v, int size);
2074 
2075 // Trova le regioni in una TVectorImage
2076 int TVectorImage::Imp::computeRegions() {
2077 #if defined(_DEBUG) && !defined(MACOSX)
2078   TStopWatch stopWatch;
2079   stopWatch.start(true);
2080 #endif
2081 
2082   if (!m_computeRegions) return 0;
2083 
2084   /*if (m_intersectionData.m_computedAlmostOnce)
2085 {
2086 UINT i,n=m_strokes.size();
2087   vector<int> vv(n);
2088 for( i=0; i<n;++i) vv[i] = i;
2089 m_intersectionData.m_computedAlmostOnce = true;
2090 notifyChangedStrokes(vv,vector<TStroke*>(), false);
2091 
2092 return true;
2093 }*/
2094 
2095   g_autocloseTolerance = m_autocloseTolerance;
2096 
2097   // Cancella le regioni gia' esistenti per ricalcolarle
2098   clearPointerContainer(m_regions);
2099   m_regions.clear();
2100 
2101   // Controlla che ci siano degli stroke
2102   if (m_strokes.empty()) {
2103 #if defined(_DEBUG) && !defined(MACOSX)
2104     stopWatch.stop();
2105 #endif
2106     return 0;
2107   }
2108 
2109   // Inizializza la lista di intersezioni intList
2110   m_intersectionData.m_computedAlmostOnce = true;
2111   list<Intersection> &intList             = m_intersectionData.m_intList;
2112   cleanIntersectionMarks(intList);
2113 
2114   // calcolo struttura delle intersezioni
2115   int added = 0, notAdded = 0;
2116   int strokeSize;
2117   strokeSize = computeIntersections();
2118 
2119   list<Intersection>::iterator it1;
2120   list<IntersectedStroke>::iterator it2;
2121 
2122   for (it1 = intList.begin(); it1 != intList.end(); it1++)
2123     for (it2 = (*it1).m_strokeList.begin(); it2 != (*it1).m_strokeList.end();
2124          it2++)
2125       it2->m_edge.m_r = 0;
2126 
2127   for (it1 = intList.begin(); it1 != intList.end(); it1++) {
2128     // Controlla che il punto in questione non sia isolato
2129     if (it1->m_numInter == 0) continue;
2130 
2131     for (it2 = it1->m_strokeList.begin(); it2 != it1->m_strokeList.end();
2132          it2++) {
2133       TRegion *region;
2134 
2135       // se lo stroke non unisce due punti di intersezione
2136       // non lo considero e vado avanti con un altro stroke
2137       if (it2->m_nextIntersection == intList.end()) continue;
2138 
2139       // Se lo stroke puntato da t2 non e' stato ancora visitato, trova una
2140       // regione
2141       if (!it2->m_visited && (region = findRegion(intList, it1, it2))) {
2142         // Se la regione e' valida la aggiunge al vettore delle regioni
2143         if (isValidArea(m_regions, *region)) {
2144           added++;
2145           addRegion(m_regions, region);
2146 
2147           // Lega ogni ramo della regione alla regione di appartenenza
2148           for (UINT i = 0; i < region->getEdgeCount(); i++) {
2149             TEdge *e = region->getEdge(i);
2150             e->m_r   = region;
2151             if (e->m_index >= 0) m_strokes[e->m_index]->addEdge(e);
2152           }
2153         } else  // Se la regione non e' valida viene scartata
2154         {
2155           notAdded++;
2156           delete region;
2157         }
2158       }
2159     }
2160   }
2161 
2162   if (!m_notIntersectingStrokes) {
2163     UINT i;
2164     for (i = 0; i < m_intersectionData.m_intersectedStrokeArray.size(); i++) {
2165       if (!m_strokes[m_intersectionData.m_intersectedStrokeArray[i].m_index]
2166                ->m_edgeList.empty())
2167         transferColors(
2168             m_intersectionData.m_intersectedStrokeArray[i].m_edgeList,
2169             m_strokes[m_intersectionData.m_intersectedStrokeArray[i].m_index]
2170                 ->m_edgeList,
2171             false, false, true);
2172       clearPointerContainer(
2173           m_intersectionData.m_intersectedStrokeArray[i].m_edgeList);
2174       m_intersectionData.m_intersectedStrokeArray[i].m_edgeList.clear();
2175     }
2176     m_intersectionData.m_intersectedStrokeArray.clear();
2177   }
2178 
2179   assert(m_intersectionData.m_intersectedStrokeArray.empty());
2180 
2181   // tolgo i segmenti aggiunti con l'autoclose
2182   vector<VIStroke *>::iterator it = m_strokes.begin();
2183   advance(it, strokeSize);
2184   m_strokes.erase(it, m_strokes.end());
2185 
2186   m_areValidRegions = true;
2187 
2188 #if defined(_DEBUG) && !defined(MACOSX)
2189 
2190 #endif
2191 
2192   return 0;
2193 }
2194 
2195 //-----------------------------------------------------------------------------
2196 //-----------------------------------------------------------------------------
2197 //-----------------------------------------------------------------------------
2198 //-----------------------------------------------------------------------------
2199 //-----------------------------------------------------------------------------
2200 //-----------------------------------------------------------------------------
2201 //-----------------------------------------------------------------------------
2202 //-----------------------------------------------------------------------------
2203 /*
2204 class Branch
2205   {
2206         TEdge m_edge;
2207   bool m_out, m_visited;
2208         Branch *m_next;
2209         Branch *m_nextBranch;
2210         Intersection* m_intersection;
2211 
2212         public:
2213           Branch* next()
2214                   {
2215                         assert(m_intersection);
2216                         return m_next?m_next:m_intersection->m_branchList;
2217                         }
2218         }
2219 
2220 
2221 class Intersection
2222   {
2223         private:
2224         TPointD m_intersectionPoint;
2225   int m_intersectionCount;
2226   Branch *m_branchList;
2227         Intersection* m_next;
2228   list<IntersectedStroke> m_strokeList;
2229         public:
2230   AddIntersection(int index0, int index1, DoublePair intersectionValues);
2231 
2232         }
2233 
2234 */
2235