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 *> ®ions, 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