Blender V5.0
Operators.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9
10#include <algorithm>
11#include <stdexcept>
12
13#include "Canvas.h"
14#include "CurveIterators.h"
15#include "Operators.h"
16#include "Stroke.h"
17#include "StrokeIterators.h"
18
19#include "BLI_sys_types.h"
20
21#include "BKE_global.hh"
22
23namespace Freestyle {
24
25Operators::I1DContainer Operators::_current_view_edges_set;
26Operators::I1DContainer Operators::_current_chains_set;
27Operators::I1DContainer *Operators::_current_set = nullptr;
28Operators::StrokesContainer Operators::_current_strokes_set;
29
31{
32 if (!_current_set) {
33 return 0;
34 }
35 if (_current_set->empty()) {
36 return 0;
37 }
38 I1DContainer new_set;
39 I1DContainer rejected;
42 I1DContainer::iterator it = _current_set->begin();
43 I1DContainer::iterator itbegin = it;
44 while (it != _current_set->end()) {
45 Interface1D *i1d = *it;
46 cts(*i1d); // mark everyone's chaining time stamp anyway
47 if (pred(*i1d) < 0) {
48 new_set.clear();
49 rejected.clear();
50 return -1;
51 }
52 if (pred.result) {
53 new_set.push_back(i1d);
54 ts(*i1d);
55 }
56 else {
57 rejected.push_back(i1d);
58 }
59 ++it;
60 }
61 if ((*itbegin)->getExactTypeName() != "ViewEdge") {
62 for (it = rejected.begin(); it != rejected.end(); ++it) {
63 delete *it;
64 }
65 }
66 rejected.clear();
67 _current_set->clear();
68 *_current_set = new_set;
69 return 0;
70}
71
73 UnaryPredicate1D &pred,
74 UnaryFunction1D_void &modifier)
75{
76 if (_current_view_edges_set.empty()) {
77 return 0;
78 }
79
80 uint id = 0;
81 ViewEdge *edge;
82 I1DContainer new_chains_set;
83
84 for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
85 it_edge != _current_view_edges_set.end();
86 ++it_edge)
87 {
88 if (pred(**it_edge) < 0) {
89 goto error;
90 }
91 if (pred.result) {
92 continue;
93 }
94
95 edge = dynamic_cast<ViewEdge *>(*it_edge);
96 it.setBegin(edge);
97 it.setCurrentEdge(edge);
98
99 Chain *new_chain = new Chain(id);
100 ++id;
101 while (true) {
102 new_chain->push_viewedge_back(*it, it.getOrientation());
103 if (modifier(**it) < 0) {
104 delete new_chain;
105 goto error;
106 }
107 ++it;
108 if (it.isEnd()) {
109 break;
110 }
111 if (pred(**it) < 0) {
112 delete new_chain;
113 goto error;
114 }
115 if (pred.result) {
116 break;
117 }
118 }
119 new_chains_set.push_back(new_chain);
120 }
121
122 if (!new_chains_set.empty()) {
123 for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
124 _current_chains_set.push_back(*it);
125 }
126 new_chains_set.clear();
127 _current_set = &_current_chains_set;
128 }
129 return 0;
130
131error:
132 for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
133 delete (*it);
134 }
135 new_chains_set.clear();
136 return -1;
137}
138
140{
141 if (_current_view_edges_set.empty()) {
142 return 0;
143 }
144
145 uint id = 0;
148 ViewEdge *edge;
149 I1DContainer new_chains_set;
150
151 for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
152 it_edge != _current_view_edges_set.end();
153 ++it_edge)
154 {
155 if (pred(**it_edge) < 0) {
156 goto error;
157 }
158 if (pred.result) {
159 continue;
160 }
161 if (pred_ts(**it_edge) < 0) {
162 goto error;
163 }
164 if (pred_ts.result) {
165 continue;
166 }
167
168 edge = dynamic_cast<ViewEdge *>(*it_edge);
169 it.setBegin(edge);
170 it.setCurrentEdge(edge);
171
172 Chain *new_chain = new Chain(id);
173 ++id;
174 while (true) {
175 new_chain->push_viewedge_back(*it, it.getOrientation());
176 ts(**it);
177 ++it;
178 if (it.isEnd()) {
179 break;
180 }
181 if (pred(**it) < 0) {
182 delete new_chain;
183 goto error;
184 }
185 if (pred.result) {
186 break;
187 }
188 if (pred_ts(**it) < 0) {
189 delete new_chain;
190 goto error;
191 }
192 if (pred_ts.result) {
193 break;
194 }
195 }
196 new_chains_set.push_back(new_chain);
197 }
198
199 if (!new_chains_set.empty()) {
200 for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
201 _current_chains_set.push_back(*it);
202 }
203 new_chains_set.clear();
204 _current_set = &_current_chains_set;
205 }
206 return 0;
207
208error:
209 for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
210 delete (*it);
211 }
212 new_chains_set.clear();
213 return -1;
214}
215
216#if 0
217void Operators::bidirectionalChain(ViewEdgeIterator &it,
218 UnaryPredicate1D &pred,
219 UnaryFunction1D_void &modifier)
220{
221 if (_current_view_edges_set.empty()) {
222 return;
223 }
224
225 uint id = 0;
226 ViewEdge *edge;
227 Chain *new_chain;
228
229 for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
230 it_edge != _current_view_edges_set.end();
231 ++it_edge)
232 {
233 if (pred(**it_edge)) {
234 continue;
235 }
236
237 edge = dynamic_cast<ViewEdge *>(*it_edge);
238 it.setBegin(edge);
239 it.setCurrentEdge(edge);
240
241 Chain *new_chain = new Chain(id);
242 ++id;
243# if 0 // FIXME
244 ViewEdgeIterator it_back(it);
245 --it_back;
246# endif
247 do {
248 new_chain->push_viewedge_back(*it, it.getOrientation());
249 modifier(**it);
250 ++it;
251 } while (!it.isEnd() && !pred(**it));
252 it.setBegin(edge);
253 it.setCurrentEdge(edge);
254 --it;
255 while (!it.isEnd() && !pred(**it)) {
256 new_chain->push_viewedge_front(*it, it.getOrientation());
257 modifier(**it);
258 --it;
259 }
260
261 _current_chains_set.push_back(new_chain);
262 }
263
264 if (!_current_chains_set.empty()) {
265 _current_set = &_current_chains_set;
266 }
267}
268
269void Operators::bidirectionalChain(ViewEdgeIterator &it, UnaryPredicate1D &pred)
270{
271 if (_current_view_edges_set.empty()) {
272 return;
273 }
274
275 uint id = 0;
276 Functions1D::IncrementChainingTimeStampF1D ts;
277 Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1);
278
279 ViewEdge *edge;
280 Chain *new_chain;
281
282 for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
283 it_edge != _current_view_edges_set.end();
284 ++it_edge)
285 {
286 if (pred(**it_edge) || pred_ts(**it_edge)) {
287 continue;
288 }
289
290 edge = dynamic_cast<ViewEdge *>(*it_edge);
291 it.setBegin(edge);
292 it.setCurrentEdge(edge);
293
294 Chain *new_chain = new Chain(id);
295 ++id;
296# if 0 // FIXME
297 ViewEdgeIterator it_back(it);
298 --it_back;
299# endif
300 do {
301 new_chain->push_viewedge_back(*it, it.getOrientation());
302 ts(**it);
303 ++it;
304 } while (!it.isEnd() && !pred(**it) && !pred_ts(**it));
305 it.setBegin(edge);
306 it.setCurrentEdge(edge);
307 --it;
308 while (!it.isEnd() && !pred(**it) && !pred_ts(**it)) {
309 new_chain->push_viewedge_front(*it, it.getOrientation());
310 ts(**it);
311 --it;
312 }
313
314 _current_chains_set.push_back(new_chain);
315 }
316
317 if (!_current_chains_set.empty()) {
318 _current_set = &_current_chains_set;
319 }
320}
321#endif
322
324{
325 if (_current_view_edges_set.empty()) {
326 return 0;
327 }
328
329 uint id = 0;
332 ViewEdge *edge;
333 I1DContainer new_chains_set;
334
335 for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
336 it_edge != _current_view_edges_set.end();
337 ++it_edge)
338 {
339 if (pred(**it_edge) < 0) {
340 goto error;
341 }
342 if (pred.result) {
343 continue;
344 }
345 if (pred_ts(**it_edge) < 0) {
346 goto error;
347 }
348 if (pred_ts.result) {
349 continue;
350 }
351
352 edge = dynamic_cast<ViewEdge *>(*it_edge);
353 // re-init iterator
354 it.setBegin(edge);
355 it.setCurrentEdge(edge);
356 it.setOrientation(true);
357 if (it.init() < 0) {
358 goto error;
359 }
360
361 Chain *new_chain = new Chain(id);
362 ++id;
363#if 0 // FIXME
364 ViewEdgeIterator it_back(it);
365 --it_back;
366#endif
367 while (true) {
368 new_chain->push_viewedge_back(*it, it.getOrientation());
369 ts(**it);
370 if (it.increment() < 0) {
371 delete new_chain;
372 goto error;
373 }
374 if (it.isEnd()) {
375 break;
376 }
377 if (pred(**it) < 0) {
378 delete new_chain;
379 goto error;
380 }
381 if (pred.result) {
382 break;
383 }
384 }
385 it.setBegin(edge);
386 it.setCurrentEdge(edge);
387 it.setOrientation(true);
388 if (it.decrement() < 0) {
389 delete new_chain;
390 goto error;
391 }
392 while (!it.isEnd()) {
393 if (pred(**it) < 0) {
394 delete new_chain;
395 goto error;
396 }
397 if (pred.result) {
398 break;
399 }
400 new_chain->push_viewedge_front(*it, it.getOrientation());
401 ts(**it);
402 if (it.decrement() < 0) {
403 delete new_chain;
404 goto error;
405 }
406 }
407 new_chains_set.push_back(new_chain);
408 }
409
410 if (!new_chains_set.empty()) {
411 for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
412 _current_chains_set.push_back(*it);
413 }
414 new_chains_set.clear();
415 _current_set = &_current_chains_set;
416 }
417 return 0;
418
419error:
420 for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
421 delete (*it);
422 }
423 new_chains_set.clear();
424 return -1;
425}
426
428{
429 if (_current_view_edges_set.empty()) {
430 return 0;
431 }
432
433 uint id = 0;
436 ViewEdge *edge;
437 I1DContainer new_chains_set;
438
439 for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
440 it_edge != _current_view_edges_set.end();
441 ++it_edge)
442 {
443 if (pred_ts(**it_edge) < 0) {
444 goto error;
445 }
446 if (pred_ts.result) {
447 continue;
448 }
449
450 edge = dynamic_cast<ViewEdge *>(*it_edge);
451 // re-init iterator
452 it.setBegin(edge);
453 it.setCurrentEdge(edge);
454 it.setOrientation(true);
455 if (it.init() < 0) {
456 goto error;
457 }
458
459 Chain *new_chain = new Chain(id);
460 ++id;
461#if 0 // FIXME
462 ViewEdgeIterator it_back(it);
463 --it_back;
464#endif
465 do {
466 new_chain->push_viewedge_back(*it, it.getOrientation());
467 ts(**it);
468 if (it.increment() < 0) { // FIXME
469 delete new_chain;
470 goto error;
471 }
472 } while (!it.isEnd());
473 it.setBegin(edge);
474 it.setCurrentEdge(edge);
475 it.setOrientation(true);
476 if (it.decrement() < 0) { // FIXME
477 delete new_chain;
478 goto error;
479 }
480 while (!it.isEnd()) {
481 new_chain->push_viewedge_front(*it, it.getOrientation());
482 ts(**it);
483 if (it.decrement() < 0) { // FIXME
484 delete new_chain;
485 goto error;
486 }
487 }
488 new_chains_set.push_back(new_chain);
489 }
490
491 if (!new_chains_set.empty()) {
492 for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
493 _current_chains_set.push_back(*it);
494 }
495 new_chains_set.clear();
496 _current_set = &_current_chains_set;
497 }
498 return 0;
499
500error:
501 for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
502 delete (*it);
503 }
504 new_chains_set.clear();
505 return -1;
506}
507
509{
510 if (_current_chains_set.empty()) {
511 cerr << "Warning: current set empty" << endl;
512 return 0;
513 }
514 CurvePoint *point;
515 Chain *new_curve;
516 I1DContainer splitted_chains;
521 I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
522 for (; cit != citend; ++cit) {
523 Id currentId = (*cit)->getId();
524 new_curve = new Chain(currentId);
525 first = (*cit)->pointsBegin(sampling);
526 end = (*cit)->pointsEnd(sampling);
527 last = end;
528 --last;
529 it = first;
530
531 point = dynamic_cast<CurvePoint *>(&(*it));
532 new_curve->push_vertex_back(point);
533 ++it;
534 for (; it != end; ++it) {
535 point = dynamic_cast<CurvePoint *>(&(*it));
536 new_curve->push_vertex_back(point);
537 if (pred(it) < 0) {
538 delete new_curve;
539 goto error;
540 }
541 if (pred.result && (it != last)) {
542 splitted_chains.push_back(new_curve);
543 currentId.setSecond(currentId.getSecond() + 1);
544 new_curve = new Chain(currentId);
545 new_curve->push_vertex_back(point);
546 }
547 }
548 if (new_curve->nSegments() == 0) {
549 delete new_curve;
550 return 0;
551 }
552
553 splitted_chains.push_back(new_curve);
554 }
555
556 // Update the current set of chains:
557 cit = _current_chains_set.begin();
558 for (; cit != citend; ++cit) {
559 delete (*cit);
560 }
561 _current_chains_set.clear();
562#if 0
563 _current_chains_set = splitted_chains;
564#else
565 for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) {
566 if ((*cit)->getLength2D() < M_EPSILON) {
567 delete (*cit);
568 continue;
569 }
570 _current_chains_set.push_back(*cit);
571 }
572#endif
573 splitted_chains.clear();
574
575 if (!_current_chains_set.empty()) {
576 _current_set = &_current_chains_set;
577 }
578 return 0;
579
580error:
581 cit = splitted_chains.begin();
582 citend = splitted_chains.end();
583 for (; cit != citend; ++cit) {
584 delete (*cit);
585 }
586 splitted_chains.clear();
587 return -1;
588}
589
591 UnaryPredicate0D &stoppingPred,
592 float sampling)
593{
594 if (_current_chains_set.empty()) {
595 cerr << "Warning: current set empty" << endl;
596 return 0;
597 }
598 CurvePoint *point;
599 Chain *new_curve;
600 I1DContainer splitted_chains;
604 Interface0DIterator itStart;
605 Interface0DIterator itStop;
606 I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
607 for (; cit != citend; ++cit) {
608 Id currentId = (*cit)->getId();
609 first = (*cit)->pointsBegin(sampling);
610 end = (*cit)->pointsEnd(sampling);
611 last = end;
612 --last;
613 itStart = first;
614 do {
615 itStop = itStart;
616 ++itStop;
617
618 new_curve = new Chain(currentId);
619 currentId.setSecond(currentId.getSecond() + 1);
620
621 point = dynamic_cast<CurvePoint *>(&(*itStart));
622 new_curve->push_vertex_back(point);
623 do {
624 point = dynamic_cast<CurvePoint *>(&(*itStop));
625 new_curve->push_vertex_back(point);
626 ++itStop;
627 if (itStop == end) {
628 break;
629 }
630 if (stoppingPred(itStop) < 0) {
631 delete new_curve;
632 goto error;
633 }
634 } while (!stoppingPred.result);
635 if (itStop != end) {
636 point = dynamic_cast<CurvePoint *>(&(*itStop));
637 new_curve->push_vertex_back(point);
638 }
639 if (new_curve->nSegments() == 0) {
640 delete new_curve;
641 }
642 else {
643 splitted_chains.push_back(new_curve);
644 }
645 // find next start
646 do {
647 ++itStart;
648 if (itStart == end) {
649 break;
650 }
651 if (startingPred(itStart) < 0) {
652 goto error;
653 }
654 } while (!startingPred.result);
655 } while (!ELEM(itStart, end, last));
656 }
657
658 // Update the current set of chains:
659 cit = _current_chains_set.begin();
660 for (; cit != citend; ++cit) {
661 delete (*cit);
662 }
663 _current_chains_set.clear();
664#if 0
665 _current_chains_set = splitted_chains;
666#else
667 for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) {
668 if ((*cit)->getLength2D() < M_EPSILON) {
669 delete (*cit);
670 continue;
671 }
672 _current_chains_set.push_back(*cit);
673 }
674#endif
675 splitted_chains.clear();
676
677 if (!_current_chains_set.empty()) {
678 _current_set = &_current_chains_set;
679 }
680 return 0;
681
682error:
683 cit = splitted_chains.begin();
684 citend = splitted_chains.end();
685 for (; cit != citend; ++cit) {
686 delete (*cit);
687 }
688 splitted_chains.clear();
689 return -1;
690}
691
692// Internal function
693static int __recursiveSplit(Chain *_curve,
695 UnaryPredicate1D &pred,
696 float sampling,
697 Operators::I1DContainer &newChains,
698 Operators::I1DContainer &splitted_chains)
699{
700 if (((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)) {
701 newChains.push_back(_curve);
702 return 0;
703 }
704
705 CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling);
707 ++second;
712 real _min = FLT_MAX; // func(it0d);
713 ++it;
715 ++next;
716
717 bool bsplit = false;
718 for (; ((it != end) && (next != end)); ++it, ++next) {
719 it0d = it.castToInterface0DIterator();
720 if (func(it0d) < 0) {
721 return -1;
722 }
723 if (func.result < _min) {
724 _min = func.result;
725 split = it;
726 bsplit = true;
727 }
728 }
729
730 if (!bsplit) { // we didn't find any minimum
731 newChains.push_back(_curve);
732 return 0;
733 }
734
735 // retrieves the current splitting id
736 Id *newId = _curve->getSplittingId();
737 if (newId == nullptr) {
738 newId = new Id(_curve->getId());
739 _curve->setSplittingId(newId);
740 }
741
742 Chain *new_curve_a = new Chain(*newId);
743 newId->setSecond(newId->getSecond() + 1);
744 new_curve_a->setSplittingId(newId);
745 Chain *new_curve_b = new Chain(*newId);
746 newId->setSecond(newId->getSecond() + 1);
747 new_curve_b->setSplittingId(newId);
748
750 vitend = _curve->curveVerticesEnd();
752 ++vnext;
753
754 for (; (vit != vitend) && (vnext != vitend) &&
755 (vnext._CurvilinearLength < split._CurvilinearLength);
756 ++vit, ++vnext)
757 {
758 new_curve_a->push_vertex_back(&(*vit));
759 }
760 if ((vit == vitend) || (vnext == vitend)) {
761 if (G.debug & G_DEBUG_FREESTYLE) {
762 cout << "The split takes place in bad location" << endl;
763 }
764 newChains.push_back(_curve);
765 delete new_curve_a;
766 delete new_curve_b;
767 return 0;
768 }
769
770 // build the two resulting chains
771 new_curve_a->push_vertex_back(&(*vit));
772 new_curve_a->push_vertex_back(&(*split));
773 new_curve_b->push_vertex_back(&(*split));
774
775 for (vit = vnext; vit != vitend; ++vit) {
776 new_curve_b->push_vertex_back(&(*vit));
777 }
778
779 // let's check whether one or two of the two new curves satisfy the stopping condition or not.
780 // (if one of them satisfies it, we don't split)
781 if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) {
782 delete new_curve_a;
783 delete new_curve_b;
784 return -1;
785 }
786 if (pred.result) {
787 // we don't actually create these two chains
788 newChains.push_back(_curve);
789 delete new_curve_a;
790 delete new_curve_b;
791 return 0;
792 }
793 // here we know we'll split _curve:
794 splitted_chains.push_back(_curve);
795
796 __recursiveSplit(new_curve_a, func, pred, sampling, newChains, splitted_chains);
797 __recursiveSplit(new_curve_b, func, pred, sampling, newChains, splitted_chains);
798 return 0;
799}
800
802 UnaryPredicate1D &pred,
803 float sampling)
804{
805 if (_current_chains_set.empty()) {
806 cerr << "Warning: current set empty" << endl;
807 return 0;
808 }
809
810 Chain *currentChain = nullptr;
811 I1DContainer splitted_chains;
812 I1DContainer newChains;
813 I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
814 for (; cit != citend; ++cit) {
815 currentChain = dynamic_cast<Chain *>(*cit);
816 if (!currentChain) {
817 continue;
818 }
819 // let's check the first one:
820 if (pred(*currentChain) < 0) {
821 return -1;
822 }
823 if (!pred.result) {
824 __recursiveSplit(currentChain, func, pred, sampling, newChains, splitted_chains);
825 }
826 else {
827 newChains.push_back(currentChain);
828 }
829 }
830 // Update the current set of chains:
831 if (!splitted_chains.empty()) {
832 for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) {
833 delete (*cit);
834 }
835 splitted_chains.clear();
836 }
837
838 _current_chains_set.clear();
839#if 0
840 _current_chains_set = newChains;
841#else
842 for (cit = newChains.begin(), citend = newChains.end(); cit != citend; ++cit) {
843 if ((*cit)->getLength2D() < M_EPSILON) {
844 delete (*cit);
845 continue;
846 }
847 _current_chains_set.push_back(*cit);
848 }
849#endif
850 newChains.clear();
851
852 if (!_current_chains_set.empty()) {
853 _current_set = &_current_chains_set;
854 }
855 return 0;
856}
857
858// recursive split with pred 0D
859static int __recursiveSplit(Chain *_curve,
861 UnaryPredicate0D &pred0d,
862 UnaryPredicate1D &pred,
863 float sampling,
864 Operators::I1DContainer &newChains,
865 Operators::I1DContainer &splitted_chains)
866{
867 if (((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)) {
868 newChains.push_back(_curve);
869 return 0;
870 }
871
872 CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling);
874 ++second;
879#if 0
880 real _min = func(it0d);
881 ++it;
882#endif
883 real _min = FLT_MAX;
884 ++it;
885 // real mean = 0.0f;
886 // soc unused - real variance = 0.0f;
887 // uint count = 0;
889 ++next;
890
891 bool bsplit = false;
892 for (; ((it != end) && (next != end)); ++it, ++next) {
893 // ++count;
894 it0d = it.castToInterface0DIterator();
895 if (pred0d(it0d) < 0) {
896 return -1;
897 }
898 if (!pred0d.result) {
899 continue;
900 }
901 if (func(it0d) < 0) {
902 return -1;
903 }
904 // mean += func.result;
905 if (func.result < _min) {
906 _min = func.result;
907 split = it;
908 bsplit = true;
909 }
910 }
911 // mean /= float(count);
912
913 // if ((!bsplit) || (mean - _min > mean)) { // we didn't find any minimum
914 if (!bsplit) { // we didn't find any minimum
915 newChains.push_back(_curve);
916 return 0;
917 }
918
919 // retrieves the current splitting id
920 Id *newId = _curve->getSplittingId();
921 if (newId == nullptr) {
922 newId = new Id(_curve->getId());
923 _curve->setSplittingId(newId);
924 }
925
926 Chain *new_curve_a = new Chain(*newId);
927 newId->setSecond(newId->getSecond() + 1);
928 new_curve_a->setSplittingId(newId);
929 Chain *new_curve_b = new Chain(*newId);
930 newId->setSecond(newId->getSecond() + 1);
931 new_curve_b->setSplittingId(newId);
932
934 vitend = _curve->curveVerticesEnd();
936 ++vnext;
937
938 for (; (vit != vitend) && (vnext != vitend) &&
939 (vnext._CurvilinearLength < split._CurvilinearLength);
940 ++vit, ++vnext)
941 {
942 new_curve_a->push_vertex_back(&(*vit));
943 }
944 if ((vit == vitend) || (vnext == vitend)) {
945 if (G.debug & G_DEBUG_FREESTYLE) {
946 cout << "The split takes place in bad location" << endl;
947 }
948 newChains.push_back(_curve);
949 delete new_curve_a;
950 delete new_curve_b;
951 return 0;
952 }
953
954 // build the two resulting chains
955 new_curve_a->push_vertex_back(&(*vit));
956 new_curve_a->push_vertex_back(&(*split));
957 new_curve_b->push_vertex_back(&(*split));
958
959 for (vit = vnext; vit != vitend; ++vit) {
960 new_curve_b->push_vertex_back(&(*vit));
961 }
962
963 // let's check whether one or two of the two new curves satisfy the stopping condition or not.
964 // (if one of them satisfies it, we don't split)
965 if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) {
966 delete new_curve_a;
967 delete new_curve_b;
968 return -1;
969 }
970 if (pred.result) {
971 // we don't actually create these two chains
972 newChains.push_back(_curve);
973 delete new_curve_a;
974 delete new_curve_b;
975 return 0;
976 }
977 // here we know we'll split _curve:
978 splitted_chains.push_back(_curve);
979
980 __recursiveSplit(new_curve_a, func, pred0d, pred, sampling, newChains, splitted_chains);
981 __recursiveSplit(new_curve_b, func, pred0d, pred, sampling, newChains, splitted_chains);
982 return 0;
983}
984
986 UnaryPredicate0D &pred0d,
987 UnaryPredicate1D &pred,
988 float sampling)
989{
990 if (_current_chains_set.empty()) {
991 cerr << "Warning: current set empty" << endl;
992 return 0;
993 }
994
995 Chain *currentChain = nullptr;
996 I1DContainer splitted_chains;
997 I1DContainer newChains;
998 I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
999 for (; cit != citend; ++cit) {
1000 currentChain = dynamic_cast<Chain *>(*cit);
1001 if (!currentChain) {
1002 continue;
1003 }
1004 // let's check the first one:
1005 if (pred(*currentChain) < 0) {
1006 return -1;
1007 }
1008 if (!pred.result) {
1009 __recursiveSplit(currentChain, func, pred0d, pred, sampling, newChains, splitted_chains);
1010 }
1011 else {
1012 newChains.push_back(currentChain);
1013 }
1014 }
1015 // Update the current set of chains:
1016 if (!splitted_chains.empty()) {
1017 for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) {
1018 delete (*cit);
1019 }
1020 splitted_chains.clear();
1021 }
1022
1023 _current_chains_set.clear();
1024#if 0
1025 _current_chains_set = newChains;
1026#else
1027 for (cit = newChains.begin(), citend = newChains.end(); cit != citend; ++cit) {
1028 if ((*cit)->getLength2D() < M_EPSILON) {
1029 delete (*cit);
1030 continue;
1031 }
1032 _current_chains_set.push_back(*cit);
1033 }
1034#endif
1035 newChains.clear();
1036
1037 if (!_current_chains_set.empty()) {
1038 _current_set = &_current_chains_set;
1039 }
1040 return 0;
1041}
1042
1043// Internal class
1045 public:
1047 {
1048 _pred = &pred;
1049 }
1050
1051 inline bool operator()(Interface1D *i1, Interface1D *i2)
1052 {
1053 if (i1 == i2) {
1054 return false;
1055 }
1056 if ((*_pred)(*i1, *i2) < 0) {
1057 throw std::runtime_error("comparison failed");
1058 }
1059 return _pred->result;
1060 }
1061
1062 private:
1063 BinaryPredicate1D *_pred;
1064};
1065
1067{
1068 if (!_current_set) {
1069 return 0;
1070 }
1071 PredicateWrapper wrapper(pred);
1072 try {
1073 std::sort(_current_set->begin(), _current_set->end(), wrapper);
1074 }
1075 catch (std::runtime_error &e) {
1076 cerr << "Warning: Operator.sort(): " << e.what() << endl;
1077 return -1;
1078 }
1079 return 0;
1080}
1081
1083{
1084 Stroke *stroke = new Stroke;
1085 stroke->setId(inter.getId());
1086
1087 float currentCurvilignAbscissa = 0.0f;
1088
1089 Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
1090 Interface0DIterator itfirst = it;
1091
1092 Vec2r current(it->getPoint2D());
1093 Vec2r previous = current;
1094 SVertex *sv;
1095 CurvePoint *cp;
1096 StrokeVertex *stroke_vertex = nullptr;
1097 bool hasSingularity = false;
1098
1099 do {
1100 cp = dynamic_cast<CurvePoint *>(&(*it));
1101 if (!cp) {
1102 sv = dynamic_cast<SVertex *>(&(*it));
1103 if (!sv) {
1104 cerr << "Warning: unexpected Vertex type" << endl;
1105 continue;
1106 }
1107 stroke_vertex = new StrokeVertex(sv);
1108 }
1109 else {
1110 stroke_vertex = new StrokeVertex(cp);
1111 }
1112 current = stroke_vertex->getPoint2D();
1113 Vec2r vec_tmp(current - previous);
1114 real dist = vec_tmp.norm();
1115 if (dist < 1.0e-6) {
1116 hasSingularity = true;
1117 }
1118 currentCurvilignAbscissa += dist;
1119 stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa);
1120 stroke->push_back(stroke_vertex);
1121 previous = current;
1122 ++it;
1123 } while (!ELEM(it, itend, itfirst));
1124
1125 if (it == itfirst) {
1126 // Add last vertex:
1127 cp = dynamic_cast<CurvePoint *>(&(*it));
1128 if (!cp) {
1129 sv = dynamic_cast<SVertex *>(&(*it));
1130 if (!sv) {
1131 cerr << "Warning: unexpected Vertex type" << endl;
1132 }
1133 else {
1134 stroke_vertex = new StrokeVertex(sv);
1135 }
1136 }
1137 else {
1138 stroke_vertex = new StrokeVertex(cp);
1139 }
1140 current = stroke_vertex->getPoint2D();
1141 Vec2r vec_tmp(current - previous);
1142 real dist = vec_tmp.norm();
1143 if (dist < 1.0e-6) {
1144 hasSingularity = true;
1145 }
1146 currentCurvilignAbscissa += dist;
1147 stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa);
1148 stroke->push_back(stroke_vertex);
1149 }
1150 // Discard the stroke if the number of stroke vertices is less than two
1151 if (stroke->strokeVerticesSize() < 2) {
1152 delete stroke;
1153 return nullptr;
1154 }
1155 stroke->setLength(currentCurvilignAbscissa);
1156 if (hasSingularity) {
1157 // Try to address singular points such that the distance between two subsequent vertices
1158 // are smaller than epsilon.
1161 ++vnext;
1162 Vec2r next((*v).getPoint());
1163 while (!vnext.isEnd()) {
1164 current = next;
1165 next = (*vnext).getPoint();
1166 if ((next - current).norm() < 1.0e-6) {
1168 if (!vprevious.isBegin()) {
1169 --vprevious;
1170 }
1171
1172 // collect a set of overlapping vertices
1173 std::vector<StrokeVertex *> overlapping_vertices;
1174 overlapping_vertices.push_back(&(*v));
1175 do {
1176 overlapping_vertices.push_back(&(*vnext));
1177 current = next;
1178 ++v;
1179 ++vnext;
1180 if (vnext.isEnd()) {
1181 break;
1182 }
1183 next = (*vnext).getPoint();
1184 } while ((next - current).norm() < 1.0e-6);
1185
1186 Vec2r target;
1187 bool reverse;
1188 if (!vnext.isEnd()) {
1189 target = (*vnext).getPoint();
1190 reverse = false;
1191 }
1192 else if (!vprevious.isBegin()) {
1193 target = (*vprevious).getPoint();
1194 reverse = true;
1195 }
1196 else {
1197 // Discard the stroke because all stroke vertices are overlapping
1198 delete stroke;
1199 return nullptr;
1200 }
1201 current = overlapping_vertices.front()->getPoint();
1202 Vec2r dir(target - current);
1203 real dist = dir.norm();
1204 real len = 1.0e-3; // default offset length
1205 int nvert = overlapping_vertices.size();
1206 if (dist < len * nvert) {
1207 len = dist / nvert;
1208 }
1209 dir.normalize();
1210 Vec2r offset(dir * len);
1211 // add the offset to the overlapping vertices
1212 StrokeVertex *sv;
1213 std::vector<StrokeVertex *>::iterator it = overlapping_vertices.begin();
1214 if (!reverse) {
1215 for (int n = 0; n < nvert; n++) {
1216 sv = (*it);
1217 sv->setPoint(sv->getPoint() + offset * (n + 1));
1218 ++it;
1219 }
1220 }
1221 else {
1222 for (int n = 0; n < nvert; n++) {
1223 sv = (*it);
1224 sv->setPoint(sv->getPoint() + offset * (nvert - n));
1225 ++it;
1226 }
1227 }
1228
1229 if (vnext.isEnd()) {
1230 break;
1231 }
1232 }
1233 ++v;
1234 ++vnext;
1235 }
1236 }
1237 {
1238 // Check if the stroke no longer contains singular points
1240 Interface0DIterator vnext = v;
1241 ++vnext;
1242 Vec2r next((*v).getPoint2D());
1243 bool warning = false;
1244 while (!vnext.isEnd()) {
1245 current = next;
1246 next = (*vnext).getPoint2D();
1247 if ((next - current).norm() < 1.0e-6) {
1248 warning = true;
1249 break;
1250 }
1251 ++v;
1252 ++vnext;
1253 }
1254 if (warning && G.debug & G_DEBUG_FREESTYLE) {
1255 printf("Warning: stroke contains singular points.\n");
1256 }
1257 }
1258 return stroke;
1259}
1260
1261inline int applyShading(Stroke &stroke, vector<StrokeShader *> &shaders)
1262{
1263 for (vector<StrokeShader *>::iterator it = shaders.begin(); it != shaders.end(); ++it) {
1264 if ((*it)->shade(stroke) < 0) {
1265 return -1;
1266 }
1267 }
1268 return 0;
1269}
1270
1271int Operators::create(UnaryPredicate1D &pred, vector<StrokeShader *> shaders)
1272{
1273 // Canvas* canvas = Canvas::getInstance();
1274 if (!_current_set) {
1275 cerr << "Warning: current set empty" << endl;
1276 return 0;
1277 }
1278 StrokesContainer new_strokes_set;
1279 for (Operators::I1DContainer::iterator it = _current_set->begin(); it != _current_set->end();
1280 ++it)
1281 {
1282 if (pred(**it) < 0) {
1283 goto error;
1284 }
1285 if (!pred.result) {
1286 continue;
1287 }
1288
1289 Stroke *stroke = createStroke(**it);
1290 if (stroke) {
1291 if (applyShading(*stroke, shaders) < 0) {
1292 delete stroke;
1293 goto error;
1294 }
1295 // canvas->RenderStroke(stroke);
1296 new_strokes_set.push_back(stroke);
1297 }
1298 }
1299
1300 for (StrokesContainer::iterator it = new_strokes_set.begin(); it != new_strokes_set.end(); ++it)
1301 {
1302 _current_strokes_set.push_back(*it);
1303 }
1304 new_strokes_set.clear();
1305 return 0;
1306
1307error:
1308 for (StrokesContainer::iterator it = new_strokes_set.begin(); it != new_strokes_set.end(); ++it)
1309 {
1310 delete (*it);
1311 }
1312 new_strokes_set.clear();
1313 return -1;
1314}
1315
1316void Operators::reset(bool removeStrokes)
1317{
1319 if (!vm) {
1320 cerr << "Error: no ViewMap computed yet" << endl;
1321 return;
1322 }
1323 _current_view_edges_set.clear();
1324 for (I1DContainer::iterator it = _current_chains_set.begin(); it != _current_chains_set.end();
1325 ++it)
1326 {
1327 delete *it;
1328 }
1329 _current_chains_set.clear();
1330
1332 ViewMap::viewedges_container::iterator ve = vedges.begin(), veend = vedges.end();
1333 for (; ve != veend; ++ve) {
1334 if ((*ve)->getLength2D() < M_EPSILON) {
1335 continue;
1336 }
1337 _current_view_edges_set.push_back(*ve);
1338 }
1339 _current_set = &_current_view_edges_set;
1340 if (removeStrokes) {
1341 _current_strokes_set.clear();
1342 }
1343}
1344
1345} /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
unsigned int uint
#define ELEM(...)
Class to define a canvas designed to draw style modules.
Iterators used to iterate over the elements of the Curve.
static void split(const char *text, const char *seps, char ***str, int *count)
Class gathering stroke creation algorithms.
Iterators used to iterate over the elements of the Stroke.
Classes to define a stroke.
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition btVector3.h:263
void push_viewedge_front(ViewEdge *iViewEdge, bool orientation)
Definition Chain.cpp:80
void push_viewedge_back(ViewEdge *iViewEdge, bool orientation)
Definition Chain.cpp:17
Id * getSplittingId()
Definition Chain.h:88
void setSplittingId(Id *sid)
Definition Chain.h:83
Interface0DIterator castToInterface0DIterator() const
virtual Vec2r getPoint2D() const
Definition Curve.h:100
uint nSegments() const
Definition Curve.h:489
void push_vertex_back(Vertex *iVertex)
Definition Curve.h:423
real getLength2D() const
Definition Curve.h:477
virtual Id getId() const
Definition Curve.h:483
CurveInternal::CurvePointIterator curvePointsBegin(float t=0.0f)
Definition Curve.cpp:639
CurveInternal::CurvePointIterator curveVerticesBegin()
Definition Curve.cpp:671
CurveInternal::CurvePointIterator curveVerticesEnd()
Definition Curve.cpp:676
CurveInternal::CurvePointIterator curvePointsEnd(float t=0.0f)
Definition Curve.cpp:655
id_type getSecond() const
Definition Id.h:68
void setSecond(id_type second)
Definition Id.h:80
virtual bool isEnd() const
virtual Geometry::Vec2r getPoint2D() const
virtual Interface0DIterator verticesEnd()
virtual Interface0DIterator verticesBegin()
virtual Id getId() const
static int sort(BinaryPredicate1D &pred)
static int select(UnaryPredicate1D &pred)
Definition Operators.cpp:30
static int chain(ViewEdgeInternal::ViewEdgeIterator &it, UnaryPredicate1D &pred, UnaryFunction1D_void &modifier)
Definition Operators.cpp:72
static void reset(bool removeStrokes=true)
vector< Interface1D * > I1DContainer
Definition Operators.h:38
static int sequentialSplit(UnaryPredicate0D &startingPred, UnaryPredicate0D &stoppingPred, float sampling=0.0f)
static int recursiveSplit(UnaryFunction0D< double > &func, UnaryPredicate1D &pred, float sampling=0)
static int bidirectionalChain(ChainingIterator &it, UnaryPredicate1D &pred)
static int create(UnaryPredicate1D &pred, vector< StrokeShader * > shaders)
vector< Stroke * > StrokesContainer
Definition Operators.h:39
bool operator()(Interface1D *i1, Interface1D *i2)
PredicateWrapper(BinaryPredicate1D &pred)
Vec2r getPoint() const
Definition Stroke.h:360
void setCurvilinearAbscissa(float iAbscissa)
Definition Stroke.h:441
void setPoint(real x, real y)
Definition Stroke.h:415
void push_back(StrokeVertex *iVertex)
Definition Stroke.h:778
void setId(const Id &id)
Definition Stroke.h:728
virtual Interface0DIterator verticesBegin()
Definition Stroke.cpp:771
uint strokeVerticesSize() const
Definition Stroke.h:833
void setLength(float iLength)
Definition Stroke.cpp:483
StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t=0.0f)
Definition Stroke.cpp:756
static TimeStamp * instance()
Definition TimeStamp.h:20
Vec< T, N > & normalize()
Definition VecMat.h:102
value_type norm() const
Definition VecMat.h:92
vector< ViewEdge * > viewedges_container
Definition ViewMap.h:47
static ViewMap * getInstance()
Definition ViewMap.h:90
viewedges_container & ViewEdges()
Definition ViewMap.h:102
#define printf(...)
static ulong * next
#define G(x, y, z)
static void error(const char *str)
VecMat::Vec2< real > Vec2r
Definition Geom.h:24
inherits from class Rep
Definition AppCanvas.cpp:20
static const real M_EPSILON
Definition Precision.h:17
static int __recursiveSplit(Chain *_curve, UnaryFunction0D< double > &func, UnaryPredicate1D &pred, float sampling, Operators::I1DContainer &newChains, Operators::I1DContainer &splitted_chains)
static Stroke * createStroke(Interface1D &inter)
int applyShading(Stroke &stroke, vector< StrokeShader * > &shaders)
double real
Definition Precision.h:14
#define FLT_MAX
Definition stdcycles.h:14
uint len