Blender  V3.3
Stroke.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
8 #include "Stroke.h"
10 #include "StrokeIterators.h"
11 #include "StrokeRenderer.h"
12 
13 #include "BKE_global.h"
14 #include "BKE_node.h"
15 
16 namespace Freestyle {
17 
18 /**********************************/
19 /* */
20 /* */
21 /* StrokeAttribute */
22 /* */
23 /* */
24 /**********************************/
25 
27 {
28  int i;
29  _alpha = 1.0f;
30  _thickness[0] = 1.0f;
31  _thickness[1] = 1.0f;
32  for (i = 0; i < 3; ++i) {
33  _color[i] = 0.2f;
34  }
35  _color[0] = 0.8f;
36  _userAttributesReal = nullptr;
37  _userAttributesVec2f = nullptr;
38  _userAttributesVec3f = nullptr;
39  _visible = true;
40 }
41 
43 {
44  _alpha = iBrother._alpha;
45  _thickness[0] = iBrother._thickness[0];
46  _thickness[1] = iBrother._thickness[1];
47  for (int i = 0; i < 3; ++i) {
48  _color[i] = iBrother._color[i];
49  }
50  _visible = iBrother._visible;
51  if (iBrother._userAttributesReal) {
52  _userAttributesReal = new realMap(*iBrother._userAttributesReal);
53  }
54  else {
55  _userAttributesReal = nullptr;
56  }
57  if (iBrother._userAttributesVec2f) {
58  _userAttributesVec2f = new Vec2fMap(*iBrother._userAttributesVec2f);
59  }
60  else {
61  _userAttributesVec2f = nullptr;
62  }
63  if (iBrother._userAttributesVec3f) {
64  _userAttributesVec3f = new Vec3fMap(*iBrother._userAttributesVec3f);
65  }
66  else {
67  _userAttributesVec3f = nullptr;
68  }
69 }
70 
72  float iGColor,
73  float iBColor,
74  float iAlpha,
75  float iRThickness,
76  float iLThickness)
77 {
78  _color[0] = iRColor;
79  _color[1] = iGColor;
80  _color[2] = iBColor;
81 
82  _alpha = iAlpha;
83 
84  _thickness[0] = iRThickness;
85  _thickness[1] = iLThickness;
86 
87  _visible = true;
88 
89  _userAttributesReal = nullptr;
90  _userAttributesVec2f = nullptr;
91  _userAttributesVec3f = nullptr;
92 }
93 
95 {
96  _alpha = (1 - t) * a1._alpha + t * a2._alpha;
97  _thickness[0] = (1 - t) * a1._thickness[0] + t * a2._thickness[0];
98  _thickness[1] = (1 - t) * a1._thickness[1] + t * a2._thickness[1];
99  for (int i = 0; i < 3; ++i) {
100  _color[i] = (1 - t) * a1._color[i] + t * a2._color[i];
101  }
102 
103  _visible = a1.isVisible();
104 
105  // FIXME: to be checked (and enhanced)
106  if ((a1._userAttributesReal) && (a2._userAttributesReal)) {
107  if (a1._userAttributesReal->size() == a2._userAttributesReal->size()) {
108  _userAttributesReal = new realMap;
109  realMap::iterator it1 = a1._userAttributesReal->begin(),
110  it1end = a1._userAttributesReal->end();
111  realMap::iterator it2 = a2._userAttributesReal->begin();
112  for (; it1 != it1end; ++it1, ++it2) {
113  (*_userAttributesReal)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second);
114  }
115  }
116  }
117  else {
118  _userAttributesReal = nullptr;
119  }
120  if ((a1._userAttributesVec2f) && (a2._userAttributesVec2f)) {
121  if (a1._userAttributesVec2f->size() == a2._userAttributesVec2f->size()) {
122  _userAttributesVec2f = new Vec2fMap;
123  Vec2fMap::iterator it1 = a1._userAttributesVec2f->begin(),
124  it1end = a1._userAttributesVec2f->end();
125  Vec2fMap::iterator it2 = a2._userAttributesVec2f->begin();
126  for (; it1 != it1end; ++it1, ++it2) {
127  (*_userAttributesVec2f)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second);
128  }
129  }
130  }
131  else {
132  _userAttributesVec2f = nullptr;
133  }
134  if ((a1._userAttributesVec3f) && (a2._userAttributesVec3f)) {
135  if (a1._userAttributesVec3f->size() == a2._userAttributesVec3f->size()) {
136  _userAttributesVec3f = new Vec3fMap;
137  Vec3fMap::iterator it1 = a1._userAttributesVec3f->begin(),
138  it1end = a1._userAttributesVec3f->end();
139  Vec3fMap::iterator it2 = a2._userAttributesVec3f->begin();
140  for (; it1 != it1end; ++it1, ++it2) {
141  (*_userAttributesVec3f)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second);
142  }
143  }
144  }
145  else {
146  _userAttributesVec3f = nullptr;
147  }
148 }
149 
151 {
152  if (_userAttributesReal) {
153  _userAttributesReal->clear();
154  delete _userAttributesReal;
155  }
156  if (_userAttributesVec2f) {
157  _userAttributesVec2f->clear();
158  delete _userAttributesVec2f;
159  }
160  if (_userAttributesVec3f) {
161  _userAttributesVec3f->clear();
162  delete _userAttributesVec3f;
163  }
164 }
165 
167 {
168  int i;
169  _alpha = iBrother._alpha;
170  _thickness[0] = iBrother._thickness[0];
171  _thickness[1] = iBrother._thickness[1];
172  for (i = 0; i < 3; ++i) {
173  _color[i] = iBrother._color[i];
174  }
175  _visible = iBrother._visible;
176  if (iBrother._userAttributesReal) {
177  if (!_userAttributesReal) {
178  _userAttributesReal = new realMap;
179  }
180  _userAttributesReal = new realMap(*(iBrother._userAttributesReal));
181  }
182  else {
183  _userAttributesReal = nullptr;
184  }
185  if (iBrother._userAttributesVec2f) {
186  if (!_userAttributesVec2f) {
187  _userAttributesVec2f = new Vec2fMap;
188  }
189  _userAttributesVec2f = new Vec2fMap(*(iBrother._userAttributesVec2f));
190  }
191  else {
192  _userAttributesVec2f = nullptr;
193  }
194  if (iBrother._userAttributesVec3f) {
195  if (!_userAttributesVec3f) {
196  _userAttributesVec3f = new Vec3fMap;
197  }
198  _userAttributesVec3f = new Vec3fMap(*(iBrother._userAttributesVec3f));
199  }
200  else {
201  _userAttributesVec3f = nullptr;
202  }
203  return *this;
204 }
205 
206 float StrokeAttribute::getAttributeReal(const char *iName) const
207 {
208  if (!_userAttributesReal) {
209  if (G.debug & G_DEBUG_FREESTYLE) {
210  cout << "StrokeAttribute warning: no real attribute was defined" << endl;
211  }
212  return 0.0f;
213  }
214  realMap::iterator a = _userAttributesReal->find(iName);
215  if (a == _userAttributesReal->end()) {
216  if (G.debug & G_DEBUG_FREESTYLE) {
217  cout << "StrokeAttribute warning: no real attribute was added with the name " << iName
218  << endl;
219  }
220  return 0.0f;
221  }
222  return (*a).second;
223 }
224 
226 {
227  if (!_userAttributesVec2f) {
228  if (G.debug & G_DEBUG_FREESTYLE) {
229  cout << "StrokeAttribute warning: no Vec2f attribute was defined" << endl;
230  }
231  return 0;
232  }
233  Vec2fMap::iterator a = _userAttributesVec2f->find(iName);
234  if (a == _userAttributesVec2f->end()) {
235  if (G.debug & G_DEBUG_FREESTYLE) {
236  cout << "StrokeAttribute warning: no Vec2f attribute was added with the name " << iName
237  << endl;
238  }
239  return 0;
240  }
241  return (*a).second;
242 }
243 
245 {
246  if (!_userAttributesVec3f) {
247  if (G.debug & G_DEBUG_FREESTYLE) {
248  cout << "StrokeAttribute warning: no Vec3f attribute was defined" << endl;
249  }
250  return 0;
251  }
252  Vec3fMap::iterator a = _userAttributesVec3f->find(iName);
253  if (a == _userAttributesVec3f->end()) {
254  if (G.debug & G_DEBUG_FREESTYLE) {
255  cout << "StrokeAttribute warning: no Vec3f attribute was added with the name " << iName
256  << endl;
257  }
258  return 0;
259  }
260  return (*a).second;
261 }
262 
263 bool StrokeAttribute::isAttributeAvailableReal(const char *iName) const
264 {
265  if (!_userAttributesReal) {
266  return false;
267  }
268  realMap::iterator a = _userAttributesReal->find(iName);
269  if (a == _userAttributesReal->end()) {
270  return false;
271  }
272  return true;
273 }
274 
275 bool StrokeAttribute::isAttributeAvailableVec2f(const char *iName) const
276 {
277  if (!_userAttributesVec2f) {
278  return false;
279  }
280  Vec2fMap::iterator a = _userAttributesVec2f->find(iName);
281  if (a == _userAttributesVec2f->end()) {
282  return false;
283  }
284  return true;
285 }
286 
287 bool StrokeAttribute::isAttributeAvailableVec3f(const char *iName) const
288 {
289  if (!_userAttributesVec3f) {
290  return false;
291  }
292  Vec3fMap::iterator a = _userAttributesVec3f->find(iName);
293  if (a == _userAttributesVec3f->end()) {
294  return false;
295  }
296  return true;
297 }
298 
299 void StrokeAttribute::setAttributeReal(const char *iName, float att)
300 {
301  if (!_userAttributesReal) {
302  _userAttributesReal = new realMap;
303  }
304  (*_userAttributesReal)[iName] = att;
305 }
306 
307 void StrokeAttribute::setAttributeVec2f(const char *iName, const Vec2f &att)
308 {
309  if (!_userAttributesVec2f) {
310  _userAttributesVec2f = new Vec2fMap;
311  }
312  (*_userAttributesVec2f)[iName] = att;
313 }
314 
315 void StrokeAttribute::setAttributeVec3f(const char *iName, const Vec3f &att)
316 {
317  if (!_userAttributesVec3f) {
318  _userAttributesVec3f = new Vec3fMap;
319  }
320  (*_userAttributesVec3f)[iName] = att;
321 }
322 
323 /**********************************/
324 /* */
325 /* */
326 /* StrokeVertex */
327 /* */
328 /* */
329 /**********************************/
330 
332 {
333  _CurvilignAbscissa = 0.0f;
334  _StrokeLength = 0.0f;
335 }
336 
338 {
339  _Attribute = iBrother._Attribute;
340  _CurvilignAbscissa = 0.0f;
341  _StrokeLength = 0.0f;
342 }
343 
344 StrokeVertex::StrokeVertex(SVertex *iSVertex) : CurvePoint(iSVertex, nullptr, 0.0f)
345 {
346  _CurvilignAbscissa = 0.0f;
347  _StrokeLength = 0.0f;
348 }
349 
351 {
352  _CurvilignAbscissa = 0.0f;
353  _StrokeLength = 0.0f;
354 }
355 
357 {
358  // interpolate attributes:
359  _Attribute = StrokeAttribute(iA->attribute(), iB->attribute(), t3);
360  _CurvilignAbscissa = (1 - t3) * iA->curvilinearAbscissa() + t3 * iB->curvilinearAbscissa();
361  _StrokeLength = iA->strokeLength();
362 }
363 
365  : CurvePoint(iSVertex, nullptr, 0.0f)
366 {
367  _Attribute = iAttribute;
368  _CurvilignAbscissa = 0.0f;
369  _StrokeLength = 0.0f;
370 }
371 
373 {
374  ((CurvePoint *)this)->operator=(iBrother);
375  _Attribute = iBrother._Attribute;
376 
377  _CurvilignAbscissa = 0.0f;
378 
379  _StrokeLength = 0.0f;
380  return *this;
381 }
382 
383 /**********************************/
384 /* */
385 /* */
386 /* Stroke */
387 /* */
388 /* */
389 /**********************************/
390 
392 {
393  _Length = 0;
394  _id = 0;
395  _sampling = FLT_MAX;
396  //_mediumType = DEFAULT_STROKE;
397  _mediumType = OPAQUE_MEDIUM;
398  _textureId = 0;
399  _textureStep = 1.0;
400  for (int a = 0; a < MAX_MTEX; a++) {
401  _mtex[a] = nullptr;
402  }
403  _nodeTree = nullptr;
404  _tips = false;
405  _rep = nullptr;
406 }
407 
408 Stroke::Stroke(const Stroke &iBrother) : Interface1D(iBrother)
409 {
410  for (vertex_container::const_iterator v = iBrother._Vertices.begin(),
411  vend = iBrother._Vertices.end();
412  v != vend;
413  v++) {
414  _Vertices.push_back(*v);
415  }
416  _Length = 0;
417  _id = iBrother._id;
418  _ViewEdges = iBrother._ViewEdges;
419  _sampling = iBrother._sampling;
420  _mediumType = iBrother._mediumType;
421  _textureId = iBrother._textureId;
422  _textureStep = iBrother._textureStep;
423  for (int a = 0; a < MAX_MTEX; a++) {
424  _mtex[a] = iBrother._mtex[a];
425  }
426  _nodeTree = iBrother._nodeTree;
427  _tips = iBrother._tips;
428  if (iBrother._rep) {
429  _rep = new StrokeRep(*(iBrother._rep));
430  }
431  else {
432  _rep = nullptr;
433  }
434 }
435 
437 {
438  if (!_Vertices.empty()) {
439  for (vertex_container::iterator v = _Vertices.begin(), vend = _Vertices.end(); v != vend;
440  v++) {
441  delete (*v);
442  }
443  _Vertices.clear();
444  }
445 
446  _ViewEdges.clear();
447  if (_rep) {
448  delete _rep;
449  _rep = nullptr;
450  }
451 }
452 
453 Stroke &Stroke::operator=(const Stroke &iBrother)
454 {
455  if (!_Vertices.empty()) {
456  _Vertices.clear();
457  }
458 
459  for (vertex_container::const_iterator v = iBrother._Vertices.begin(),
460  vend = iBrother._Vertices.end();
461  v != vend;
462  v++) {
463  _Vertices.push_back(*v);
464  }
465  _Length = iBrother._Length;
466  _id = iBrother._id;
467  _ViewEdges = iBrother._ViewEdges;
468  _sampling = iBrother._sampling;
469  delete _rep;
470  if (iBrother._rep) {
471  _rep = new StrokeRep(*(iBrother._rep));
472  }
473  else {
474  _rep = nullptr;
475  }
476  return *this;
477 }
478 
479 void Stroke::setLength(float iLength)
480 {
481  _Length = iLength;
482  for (vertex_container::iterator v = _Vertices.begin(), vend = _Vertices.end(); v != vend; ++v) {
483  (*v)->setStrokeLength(iLength);
484  }
485 }
486 
487 float Stroke::ComputeSampling(int iNVertices)
488 {
489  if (iNVertices <= (int)_Vertices.size()) { // soc
490  return _sampling;
491  }
492 
493  float sampling = _Length / (float)(iNVertices - _Vertices.size() + 1);
494  return sampling;
495 }
496 
498  public:
501  float _length;
502  int _n;
503  float _sampling;
505 
508  float ilength,
509  int in,
510  float isampling)
511  {
512  _begin = ibegin;
513  _end = iend;
514  _length = ilength;
515  _n = in;
516  _sampling = isampling;
517  _resampled = false;
518  }
519 };
520 
521 int Stroke::Resample(int iNPoints)
522 {
523  int NPointsToAdd = iNPoints - strokeVerticesSize();
524  if (NPointsToAdd <= 0) {
525  return 0;
526  }
527 
530  ++next;
532 
533  vertex_container newVertices;
534  real t = 0.0f;
535  StrokeVertex *newVertex = nullptr;
536  vector<StrokeSegment> strokeSegments;
537  int N = 0;
538  float meanlength = 0;
539  int nsegments = 0;
540  while ((it != itend) && (next != itend)) {
541  Vec2r a((it)->getPoint());
542  Vec2r b((next)->getPoint());
543  Vec2r vec_tmp(b - a);
544  real norm_var = vec_tmp.norm();
545  int numberOfPointsToAdd = (int)floor(NPointsToAdd * norm_var / _Length);
546  float csampling = norm_var / (float)(numberOfPointsToAdd + 1);
547  strokeSegments.emplace_back(it, next, norm_var, numberOfPointsToAdd, csampling);
548  N += numberOfPointsToAdd;
549  meanlength += norm_var;
550  ++nsegments;
551  ++it;
552  ++next;
553  }
554  meanlength /= (float)nsegments;
555 
556  // if we don't have enough points let's resample finer some segments
557  bool checkEveryone = false;
558  bool resampled;
559  while (N < NPointsToAdd) {
560  resampled = false;
561  for (vector<StrokeSegment>::iterator s = strokeSegments.begin(), send = strokeSegments.end();
562  s != send;
563  ++s) {
564  if (s->_sampling == 0.0f) {
565  continue;
566  }
567 
568  if (s->_resampled == false) {
569  if ((!checkEveryone) && (s->_length < meanlength)) {
570  continue;
571  }
572  // resample
573  s->_n = s->_n + 1;
574  s->_sampling = s->_length / (float)(s->_n + 1);
575  s->_resampled = resampled = true;
576  N++;
577  if (N == NPointsToAdd) {
578  break;
579  }
580  }
581  }
582  if (checkEveryone && !resampled) {
583  break;
584  }
585  checkEveryone = true;
586  }
587  if (N < NPointsToAdd) {
588  // fatal error, likely because _Length is inconsistent with the stroke length computed with the
589  // vertices
590  return -1;
591  }
592  // actually resample:
593  for (vector<StrokeSegment>::iterator s = strokeSegments.begin(), send = strokeSegments.end();
594  s != send;
595  ++s) {
596  newVertices.push_back(&(*(s->_begin)));
597  if (s->_sampling < _sampling) {
598  _sampling = s->_sampling;
599  }
600 
601  t = s->_sampling / s->_length;
602  for (int i = 0; i < s->_n; ++i) {
603  newVertex = new StrokeVertex(&(*(s->_begin)), &(*(s->_end)), t);
604  newVertices.push_back(newVertex);
605  t += s->_sampling / s->_length;
606  }
607  it = s->_begin;
608  next = s->_end;
609  }
610 
611  // add last:
612  ++it;
613  ++next;
614  if ((it != itend) && (next == itend) /* && (t == 0.0f) */) {
615  newVertices.push_back(&(*it));
616  }
617 
618  int newsize = newVertices.size();
619  if (newsize != iNPoints) {
620  cerr << "Warning: incorrect points number" << endl;
621  }
622 
623  _Vertices.clear();
624  _Vertices = newVertices;
625  newVertices.clear();
626 
627  return 0;
628 }
629 
630 int Stroke::Resample(float iSampling)
631 {
632  // cerr << "old size :" << strokeVerticesSize() << endl;
633  if (iSampling == 0) {
634  return 0;
635  }
636  if (iSampling >= _sampling) {
637  return 0;
638  }
639 
640  _sampling = iSampling;
641  // Resample...
642  // real curvilinearLength = 0.0f;
643  vertex_container newVertices;
644  real t = 0.0f;
645  const real limit = 0.99;
646  StrokeVertex *newVertex = nullptr;
649  ++next;
651  while ((it != itend) && (next != itend)) {
652  newVertices.push_back(&(*it));
653  Vec2r a((it)->getPoint());
654  Vec2r b((next)->getPoint());
655  Vec2r vec_tmp(b - a);
656  real norm_var = vec_tmp.norm();
657  if (norm_var <= _sampling) {
658  // curvilinearLength += norm_var;
659  ++it;
660  ++next;
661  continue;
662  }
663 
664  // curvilinearLength += _sampling;
665  t = _sampling / norm_var;
666  while (t < limit) {
667  newVertex = new StrokeVertex(&(*it), &(*next), t);
668  // newVertex->setCurvilinearAbscissa(curvilinearLength);
669  newVertices.push_back(newVertex);
670  t = t + _sampling / norm_var;
671  }
672  ++it;
673  ++next;
674  }
675  // add last:
676  if ((it != itend) && (next == itend) /* && (t == 0.0f) */) {
677  newVertices.push_back(&(*it));
678  }
679 
680  _Vertices.clear();
681  _Vertices = newVertices;
682  newVertices.clear();
683 
684  return 0;
685 }
686 
688 {
689  vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end();
690  for (; it != itend; ++it) {
691  delete (*it);
692  }
693  _Vertices.clear();
694  UpdateLength();
695 }
696 
698 {
699  vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end();
700  for (; it != itend; ++it) {
701  if ((*it) == iVertex) {
702  delete iVertex;
703  it = _Vertices.erase(it); // it is now the element just after the erased element
704  break;
705  }
706  }
707  UpdateLength();
708 }
709 
711 {
712  vertex_container::iterator itnext = next.getIt();
713  _Vertices.insert(itnext, iVertex);
714  UpdateLength();
715 }
716 
718 {
719  // recompute curvilinear abscissa and stroke length
720  float curvabsc = 0.0f;
721  vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end();
722  vertex_container::iterator previous = it;
723  for (; it != itend; ++it) {
724  curvabsc += ((*it)->getPoint() - (*previous)->getPoint()).norm();
725  (*it)->setCurvilinearAbscissa(curvabsc);
726  previous = it;
727  }
728  _Length = curvabsc;
729  for (it = _Vertices.begin(); it != itend; ++it) {
730  (*it)->setStrokeLength(_Length);
731  }
732 }
733 
736 {
737  return const_vertex_iterator(_Vertices.begin(), _Vertices.begin(), _Vertices.end());
738 }
739 
741 {
742  return const_vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end());
743 }
744 
746 {
747  return vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end());
748 }
749 
751 {
752  if ((t != 0) && (t < _sampling)) {
753  Resample(t);
754  }
756  this->_Vertices.begin(), this->_Vertices.begin(), this->_Vertices.end());
757 }
758 
760 {
762  this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end());
763 }
764 
766 {
768  this->_Vertices.begin(), this->_Vertices.begin(), this->_Vertices.end()));
769  return ret;
770 }
771 
773 {
775  this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end()));
776  return ret;
777 }
778 
780 {
781  return verticesBegin(); // FIXME
782 }
783 
785 {
786  return verticesEnd();
787 }
788 
789 void Stroke::ScaleThickness(float iFactor)
790 {
791  for (vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); it != itend;
792  ++it) {
793  StrokeAttribute &attr = (*it)->attribute();
794  attr.setThickness(iFactor * attr.getThicknessR(), iFactor * attr.getThicknessL());
795  }
796 }
797 
798 void Stroke::Render(const StrokeRenderer *iRenderer)
799 {
800  if (!_rep) {
801  _rep = new StrokeRep(this);
802  }
803  iRenderer->RenderStrokeRep(_rep);
804 }
805 
806 void Stroke::RenderBasic(const StrokeRenderer *iRenderer)
807 {
808  if (!_rep) {
809  _rep = new StrokeRep(this);
810  }
811  iRenderer->RenderStrokeRep(_rep);
812 }
813 
815 {
816  // Resample if necessary
817  if ((sampling != 0) && (sampling < _sampling)) {
818  Resample(sampling);
819  }
820  return vertex_iterator(_Vertices.begin(), _Vertices.begin(), _Vertices.end());
821  // return _Vertices.begin();
822 }
823 
824 #if 0
825 Stroke::vertex_iterator Stroke::vertices_last()
826 {
828  vertex_iterator next = res;
829  ++next;
830  while (!next.end()) {
831  ++next;
832  ++res;
833  }
834  return res;
835 }
836 
837 Stroke::const_vertex_iterator Stroke::vertices_last() const
838 {
841  ++next;
842  while (!next.end()) {
843  ++next;
844  ++res;
845  }
846  return res;
847 }
848 
849 Stroke::vertex_container::reverse_iterator Stroke::vertices_last(float sampling)
850 {
851  // Resample if necessary
852  if (sampling < _sampling) {
853  Resample(sampling);
854  }
855  return _Vertices.rbegin();
856 }
857 
858 inline Vec3r shaded_color(int iCombination = 0) const;
859 
860 inline Vec<3, real> Stroke::orientation2d(const_vertex_iterator it) const
861 {
862  return iterator_edge_orientation2d_function<Stroke, const_vertex_iterator>(this, it);
863 }
864 
865 Vec3r Stroke::orientation2d(int iCombination) const
866 {
867  return edge_orientation2d_function<Stroke>(*this, iCombination);
868 }
869 
870 inline Vec3r Stroke::orientation3d(const_vertex_iterator it) const
871 {
872  return iterator_edge_orientation3d_function<Stroke, const_vertex_iterator>(*this, it);
873 }
874 
875 Vec3r Stroke::orientation3d(int iCombination) const
876 {
877  return edge_orientation3d_function<Stroke>(*this, iCombination);
878 }
879 
881 {
883  Material mat = (*v)->material();
884  for (; v != vend; ++v) {
885  if (mat != (*v)->material()) {
887  }
888  }
889  return mat;
890 }
891 
892 int Stroke::qi() const
893 {
895  int qi_ = (*v)->qi();
896  for (; v != vend; ++v) {
897  if ((*v)->qi() != qi_) {
899  }
900  }
901  return qi_;
902 }
903 
904 inline occluder_container::const_iterator occluders_begin() const
905 {
906  return _FEdgeA->occluders().begin();
907 }
908 
909 inline occluder_container::const_iterator occluders_end() const
910 {
911  return _FEdgeA->occluders().end();
912 }
913 
914 int Stroke::occluders_size() const
915 {
916  return qi();
917 }
918 
919 bool Stroke::occluders_empty() const
920 {
922  bool empty = (*v)->occluders_empty();
923  for (; v != vend; ++v) {
924  if ((*v)->occluders_empty() != empty) {
926  }
927  }
928  return empty;
929 }
930 
931 # if 0
932 inline const polygon3d& occludee() const
933 {
934  return *(_FEdgeA->aFace());
935 }
936 # endif
937 
938 const SShape *Stroke::occluded_shape() const
939 {
941  const SShape *sshape = (*v)->occluded_shape();
942  for (; v != vend; ++v) {
943  if ((*v)->occluded_shape() != sshape) {
945  }
946  }
947  return sshape;
948 }
949 
950 const bool Stroke::occludee_empty() const
951 {
953  bool empty = (*v)->occludee_empty();
954  for (; v != vend; ++v) {
955  if ((*v)->occludee_empty() != empty) {
957  }
958  }
959  return empty;
960 }
961 
962 const SShape *Stroke::shape() const
963 {
965  const SShape *sshape = (*v)->shape();
966  for (; v != vend; ++v) {
967  if ((*v)->shape() != sshape) {
969  }
970  }
971  return sshape;
972 }
973 
974 real Stroke::z_discontinuity(int iCombination) const
975 {
976  return z_discontinuity_edge_function<Stroke>(*this, iCombination);
977 }
978 
979 Vec3r Stroke::curvature2d_as_vector(int iCombination) const
980 {
981  return curvature2d_as_vector_edge_function<Stroke>(*this, iCombination);
982 }
983 
984 real Stroke::curvature2d_as_angle(int iCombination) const
985 {
986  return curvature2d_as_angle_edge_function<Stroke>(*this, iCombination);
987 }
988 
989 float Stroke::shape_importance(int iCombination) const
990 {
991  return shape_importance_edge_function<Stroke>(*this, iCombination);
992 }
993 
994 float Stroke::local_average_depth(int iCombination) const
995 {
996  return local_average_depth_edge_function<Stroke>(*this, iCombination);
997 }
998 
999 float Stroke::local_depth_variance(int iCombination) const
1000 {
1001  return local_depth_variance_edge_function<Stroke>(*this, iCombination);
1002 }
1003 
1004 real Stroke::local_average_density(float sigma, int iCombination) const
1005 {
1006  return density_edge_function<Stroke>(*this, iCombination);
1007 }
1008 #endif
1009 
1010 } /* namespace Freestyle */
typedef float(TangentPoint)[2]
@ G_DEBUG_FREESTYLE
Definition: BKE_global.h:181
_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 GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Iterators used to iterate over the elements of the Stroke. Can't be used in python.
Iterators used to iterate over the elements of the Stroke.
Classes to render a stroke with OpenGL.
Classes to define a stroke.
#define MAX_MTEX
Definition: Stroke.h:31
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition: btVector3.h:263
static int raiseException(exception_type exception=UNDEFINED)
Definition: Exception.h:30
bool isAttributeAvailableVec3f(const char *iName) const
Definition: Stroke.cpp:287
void setThickness(float tr, float tl)
Definition: Stroke.h:233
Vec3f getAttributeVec3f(const char *iName) const
Definition: Stroke.cpp:244
void setAttributeReal(const char *iName, float att)
Definition: Stroke.cpp:299
const float getThicknessR() const
Definition: Stroke.h:140
void setAttributeVec3f(const char *iName, const Vec3f &att)
Definition: Stroke.cpp:315
bool isVisible() const
Definition: Stroke.h:159
const float getThicknessL() const
Definition: Stroke.h:146
bool isAttributeAvailableVec2f(const char *iName) const
Definition: Stroke.cpp:275
Vec2f getAttributeVec2f(const char *iName) const
Definition: Stroke.cpp:225
void setAttributeVec2f(const char *iName, const Vec2f &att)
Definition: Stroke.cpp:307
StrokeAttribute & operator=(const StrokeAttribute &iBrother)
Definition: Stroke.cpp:166
bool isAttributeAvailableReal(const char *iName) const
Definition: Stroke.cpp:263
float getAttributeReal(const char *iName) const
Definition: Stroke.cpp:206
virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const =0
StrokeInternal::StrokeVertexIterator _end
Definition: Stroke.cpp:500
StrokeSegment(StrokeInternal::StrokeVertexIterator ibegin, StrokeInternal::StrokeVertexIterator iend, float ilength, int in, float isampling)
Definition: Stroke.cpp:506
StrokeInternal::StrokeVertexIterator _begin
Definition: Stroke.cpp:499
float curvilinearAbscissa() const
Definition: Stroke.h:386
const StrokeAttribute & attribute() const
Definition: Stroke.h:374
float strokeLength() const
Definition: Stroke.h:392
StrokeVertex & operator=(const StrokeVertex &iBrother)
Definition: Stroke.cpp:372
virtual Interface0DIterator pointsEnd(float t=0.0f)
Definition: Stroke.cpp:784
const_vertex_iterator vertices_begin() const
embedding vertex iterator
Definition: Stroke.cpp:735
void ScaleThickness(float iFactor)
Definition: Stroke.cpp:789
virtual Interface0DIterator verticesBegin()
Definition: Stroke.cpp:765
StrokeInternal::vertex_iterator_base< StrokeInternal::vertex_nonconst_traits > vertex_iterator
Definition: Stroke.h:514
StrokeInternal::vertex_iterator_base< StrokeInternal::vertex_const_traits > const_vertex_iterator
Definition: Stroke.h:516
void RemoveAllVertices()
Definition: Stroke.cpp:687
virtual ~Stroke()
Definition: Stroke.cpp:436
void RemoveVertex(StrokeVertex *iVertex)
Definition: Stroke.cpp:697
void InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next)
Definition: Stroke.cpp:710
const_vertex_iterator vertices_end() const
Definition: Stroke.cpp:740
std::deque< StrokeVertex * > vertex_container
Definition: Stroke.h:511
virtual Interface0DIterator verticesEnd()
Definition: Stroke.cpp:772
void UpdateLength()
Definition: Stroke.cpp:717
void Render(const StrokeRenderer *iRenderer)
Definition: Stroke.cpp:798
virtual Interface0DIterator pointsBegin(float t=0.0f)
Definition: Stroke.cpp:779
void RenderBasic(const StrokeRenderer *iRenderer)
Definition: Stroke.cpp:806
Stroke & operator=(const Stroke &iBrother)
Definition: Stroke.cpp:453
void setLength(float iLength)
Definition: Stroke.cpp:479
float ComputeSampling(int iNVertices)
Definition: Stroke.cpp:487
StrokeInternal::StrokeVertexIterator strokeVerticesEnd()
Definition: Stroke.cpp:759
StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t=0.0f)
Definition: Stroke.cpp:750
int Resample(int iNPoints)
Definition: Stroke.cpp:521
unsigned int strokeVerticesSize() const
Definition: Stroke.h:837
value_type norm() const
Definition: VecMat.h:95
Material material
static ulong * next
#define N
#define G(x, y, z)
VecMat::Vec3< real > Vec3r
Definition: Geom.h:28
inherits from class Rep
Definition: AppCanvas.cpp:18
static unsigned a[3]
Definition: RandGen.cpp:78
double real
Definition: Precision.h:12
T floor(const T &a)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
return ret