Blender V4.3
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
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 }
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 }
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;
711 Interface0DIterator it0d = it.castToInterface0DIterator();
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;
878 Interface0DIterator it0d = it.castToInterface0DIterator();
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.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
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
virtual Vec2r getPoint2D() const
Definition Curve.h:102
uint nSegments() const
Definition Curve.h:493
void push_vertex_back(Vertex *iVertex)
Definition Curve.h:427
real getLength2D() const
Definition Curve.h:481
virtual Id getId() const
Definition Curve.h:487
CurveInternal::CurvePointIterator curvePointsBegin(float t=0.0f)
Definition Curve.cpp:638
CurveInternal::CurvePointIterator curveVerticesBegin()
Definition Curve.cpp:670
CurveInternal::CurvePointIterator curveVerticesEnd()
Definition Curve.cpp:675
CurveInternal::CurvePointIterator curvePointsEnd(float t=0.0f)
Definition Curve.cpp:654
id_type getSecond() const
Definition Id.h:70
void setSecond(id_type second)
Definition Id.h:82
virtual bool isEnd() 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:40
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:41
bool operator()(Interface1D *i1, Interface1D *i2)
PredicateWrapper(BinaryPredicate1D &pred)
Vec2r getPoint() const
Definition Stroke.h:364
void setCurvilinearAbscissa(float iAbscissa)
Definition Stroke.h:445
void setPoint(real x, real y)
Definition Stroke.h:419
void push_back(StrokeVertex *iVertex)
Definition Stroke.h:784
void setId(const Id &id)
Definition Stroke.h:734
virtual Interface0DIterator verticesBegin()
Definition Stroke.cpp:771
uint strokeVerticesSize() const
Definition Stroke.h:839
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:22
Vec< T, N > & normalize()
Definition VecMat.h:104
value_type norm() const
Definition VecMat.h:94
vector< ViewEdge * > viewedges_container
Definition ViewMap.h:49
static ViewMap * getInstance()
Definition ViewMap.h:92
viewedges_container & ViewEdges()
Definition ViewMap.h:104
#define printf
int len
static ulong * next
#define G(x, y, z)
static void error(const char *str)
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