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