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