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
17 #pragma once
18
19 /** \file
20 * \ingroup freestyle
21 * \brief Classes to define a silhouette structure
22 */
23
24 #include <float.h>
25 #include <iostream>
26 #include <set>
27 #include <string>
28 #include <vector>
29
30 #include "Interface0D.h"
31 #include "Interface1D.h"
32
33 #include "../geometry/BBox.h"
34 #include "../geometry/Geom.h"
35 #include "../geometry/Polygon.h"
36
37 #include "../scene_graph/FrsMaterial.h"
38
39 #include "../system/Exception.h"
40 #include "../system/FreestyleConfig.h"
41
42 #include "../winged_edge/Curvature.h"
43
44 #ifdef WITH_CXX_GUARDEDALLOC
45 # include "MEM_guardedalloc.h"
46 #endif
47
48 using namespace std;
49
50 namespace Freestyle {
51
52 using namespace Geometry;
53
54 class ViewShape;
55 typedef vector<ViewShape *> occluder_container;
56
57 /**********************************/
58 /* */
59 /* */
60 /* SVertex */
61 /* */
62 /* */
63 /**********************************/
64
65 class FEdge;
66 class ViewVertex;
67 class SShape;
68
69 /*! Class to define a vertex of the embedding. */
70 class SVertex : public Interface0D {
71 public: // Implementation of Interface0D
72 /*! Returns the string "SVertex" .*/
getExactTypeName()73 virtual string getExactTypeName() const
74 {
75 return "SVertex";
76 }
77
78 // Data access methods
79 /*! Returns the 3D x coordinate of the vertex .*/
getX()80 virtual real getX() const
81 {
82 return _Point3D.x();
83 }
84
85 /*! Returns the 3D y coordinate of the vertex .*/
getY()86 virtual real getY() const
87 {
88 return _Point3D.y();
89 }
90
91 /*! Returns the 3D z coordinate of the vertex .*/
getZ()92 virtual real getZ() const
93 {
94 return _Point3D.z();
95 }
96
97 /*! Returns the 3D point. */
getPoint3D()98 virtual Vec3r getPoint3D() const
99 {
100 return _Point3D;
101 }
102
103 /*! Returns the projected 3D x coordinate of the vertex .*/
getProjectedX()104 virtual real getProjectedX() const
105 {
106 return _Point2D.x();
107 }
108
109 /*! Returns the projected 3D y coordinate of the vertex .*/
getProjectedY()110 virtual real getProjectedY() const
111 {
112 return _Point2D.y();
113 }
114
115 /*! Returns the projected 3D z coordinate of the vertex .*/
getProjectedZ()116 virtual real getProjectedZ() const
117 {
118 return _Point2D.z();
119 }
120
121 /*! Returns the 2D point. */
getPoint2D()122 virtual Vec2r getPoint2D() const
123 {
124 return Vec2r(_Point2D.x(), _Point2D.y());
125 }
126
127 /*! Returns the FEdge that lies between this Svertex and the Interface0D given as argument. */
128 virtual FEdge *getFEdge(Interface0D &);
129
130 /*! Returns the Id of the vertex .*/
getId()131 virtual Id getId() const
132 {
133 return _Id;
134 }
135
136 /*! Returns the nature of the vertex .*/
137 virtual Nature::VertexNature getNature() const;
138
139 /*! Cast the Interface0D in SVertex if it can be. */
140 virtual SVertex *castToSVertex();
141
142 /*! Cast the Interface0D in ViewVertex if it can be. */
143 virtual ViewVertex *castToViewVertex();
144
145 /*! Cast the Interface0D in NonTVertex if it can be. */
146 virtual NonTVertex *castToNonTVertex();
147
148 /*! Cast the Interface0D in TVertex if it can be. */
149 virtual TVertex *castToTVertex();
150
151 public:
152 typedef vector<FEdge *> fedges_container;
153
154 private:
155 Id _Id;
156 Vec3r _Point3D;
157 Vec3r _Point2D;
158 set<Vec3r> _Normals;
159 vector<FEdge *> _FEdges; // the edges containing this vertex
160 SShape *_Shape; // the shape to which belongs the vertex
161 ViewVertex *_pViewVertex; // The associated viewvertex, in case there is one.
162 #if 0
163 real _curvatureFredo;
164 Vec2r _directionFredo;
165 #endif
166 CurvatureInfo *_curvature_info;
167
168 public:
169 /*! A field that can be used by the user to store any data.
170 * This field must be reset afterwards using ResetUserData().
171 */
172 void *userdata;
173
174 /*! Default constructor.*/
SVertex()175 inline SVertex()
176 {
177 _Id = 0;
178 userdata = NULL;
179 _Shape = NULL;
180 _pViewVertex = 0;
181 _curvature_info = 0;
182 }
183
184 /*! Builds a SVertex from 3D coordinates and an Id. */
SVertex(const Vec3r & iPoint3D,const Id & id)185 inline SVertex(const Vec3r &iPoint3D, const Id &id)
186 {
187 _Point3D = iPoint3D;
188 _Id = id;
189 userdata = NULL;
190 _Shape = NULL;
191 _pViewVertex = 0;
192 _curvature_info = 0;
193 }
194
195 /*! Copy constructor. */
SVertex(SVertex & iBrother)196 inline SVertex(SVertex &iBrother)
197 {
198 _Id = iBrother._Id;
199 _Point3D = iBrother.point3D();
200 _Point2D = iBrother.point2D();
201 _Normals = iBrother._Normals;
202 _FEdges = iBrother.fedges();
203 _Shape = iBrother.shape();
204 _pViewVertex = iBrother._pViewVertex;
205 if (!(iBrother._curvature_info)) {
206 _curvature_info = 0;
207 }
208 else {
209 _curvature_info = new CurvatureInfo(*(iBrother._curvature_info));
210 }
211 iBrother.userdata = this;
212 userdata = 0;
213 }
214
215 /*! Destructor. */
~SVertex()216 virtual ~SVertex()
217 {
218 if (_curvature_info) {
219 delete _curvature_info;
220 }
221 }
222
223 /*! Cloning method. */
duplicate()224 virtual SVertex *duplicate()
225 {
226 SVertex *clone = new SVertex(*this);
227 return clone;
228 }
229
230 /*! operator == */
231 virtual bool operator==(const SVertex &iBrother)
232 {
233 return ((_Point2D == iBrother._Point2D) && (_Point3D == iBrother._Point3D));
234 }
235
236 /* accessors */
point3D()237 inline const Vec3r &point3D() const
238 {
239 return _Point3D;
240 }
241
point2D()242 inline const Vec3r &point2D() const
243 {
244 return _Point2D;
245 }
246
247 /*! Returns the set of normals for this Vertex.
248 * In a smooth surface, a vertex has exactly one normal.
249 * In a sharp surface, a vertex can have any number of normals.
250 */
normals()251 inline set<Vec3r> normals()
252 {
253 return _Normals;
254 }
255
256 /*! Returns the number of different normals for this vertex. */
normalsSize()257 inline unsigned normalsSize() const
258 {
259 return _Normals.size();
260 }
261
fedges()262 inline const vector<FEdge *> &fedges()
263 {
264 return _FEdges;
265 }
266
fedges_begin()267 inline fedges_container::iterator fedges_begin()
268 {
269 return _FEdges.begin();
270 }
271
fedges_end()272 inline fedges_container::iterator fedges_end()
273 {
274 return _FEdges.end();
275 }
276
shape()277 inline SShape *shape()
278 {
279 return _Shape;
280 }
281
z()282 inline real z() const
283 {
284 return _Point2D[2];
285 }
286
287 /*! If this SVertex is also a ViewVertex, this method returns a pointer onto this ViewVertex.
288 * 0 is returned otherwise.
289 */
viewvertex()290 inline ViewVertex *viewvertex()
291 {
292 return _pViewVertex;
293 }
294
295 /*! modifiers */
296 /*! Sets the 3D coordinates of the SVertex. */
setPoint3D(const Vec3r & iPoint3D)297 inline void setPoint3D(const Vec3r &iPoint3D)
298 {
299 _Point3D = iPoint3D;
300 }
301
302 /*! Sets the 3D projected coordinates of the SVertex. */
setPoint2D(const Vec3r & iPoint2D)303 inline void setPoint2D(const Vec3r &iPoint2D)
304 {
305 _Point2D = iPoint2D;
306 }
307
308 /*! Adds a normal to the Svertex's set of normals. If the same normal is already in the set,
309 * nothing changes. */
AddNormal(const Vec3r & iNormal)310 inline void AddNormal(const Vec3r &iNormal)
311 {
312 _Normals.insert(iNormal); // if iNormal in the set already exists, nothing is done
313 }
314
setCurvatureInfo(CurvatureInfo * ci)315 void setCurvatureInfo(CurvatureInfo *ci)
316 {
317 if (_curvature_info) { // Q. is this an error condition? (T.K. 02-May-2011)
318 delete _curvature_info;
319 }
320 _curvature_info = ci;
321 }
322
getCurvatureInfo()323 const CurvatureInfo *getCurvatureInfo() const
324 {
325 return _curvature_info;
326 }
327
328 #if 0
329 /* Fredo's normal and curvature*/
330 void setCurvatureFredo(real c)
331 {
332 _curvatureFredo = c;
333 }
334
335 void setDirectionFredo(Vec2r d)
336 {
337 _directionFredo = d;
338 }
339
340 real curvatureFredo()
341 {
342 return _curvatureFredo;
343 }
344
345 const Vec2r directionFredo()
346 {
347 return _directionFredo;
348 }
349 #endif
350
351 /*! Sets the Id */
setId(const Id & id)352 inline void setId(const Id &id)
353 {
354 _Id = id;
355 }
356
setFEdges(const vector<FEdge * > & iFEdges)357 inline void setFEdges(const vector<FEdge *> &iFEdges)
358 {
359 _FEdges = iFEdges;
360 }
361
setShape(SShape * iShape)362 inline void setShape(SShape *iShape)
363 {
364 _Shape = iShape;
365 }
366
setViewVertex(ViewVertex * iViewVertex)367 inline void setViewVertex(ViewVertex *iViewVertex)
368 {
369 _pViewVertex = iViewVertex;
370 }
371
372 /*! Add an FEdge to the list of edges emanating from this SVertex. */
AddFEdge(FEdge * iFEdge)373 inline void AddFEdge(FEdge *iFEdge)
374 {
375 _FEdges.push_back(iFEdge);
376 }
377
378 /*! Remove an FEdge from the list of edges emanating from this SVertex. */
RemoveFEdge(FEdge * iFEdge)379 inline void RemoveFEdge(FEdge *iFEdge)
380 {
381 for (vector<FEdge *>::iterator fe = _FEdges.begin(), fend = _FEdges.end(); fe != fend; fe++) {
382 if (iFEdge == (*fe)) {
383 _FEdges.erase(fe);
384 break;
385 }
386 }
387 }
388
389 /* replaces edge 1 by edge 2 in the list of edges */
Replace(FEdge * e1,FEdge * e2)390 inline void Replace(FEdge *e1, FEdge *e2)
391 {
392 vector<FEdge *>::iterator insertedfe;
393 for (vector<FEdge *>::iterator fe = _FEdges.begin(), fend = _FEdges.end(); fe != fend; fe++) {
394 if ((*fe) == e1) {
395 insertedfe = _FEdges.insert(fe, e2); // inserts e2 before fe.
396 // returns an iterator pointing toward e2. fe is invalidated.
397 // we want to remove e1, but we can't use fe anymore:
398 ++insertedfe; // insertedfe points now to e1
399 _FEdges.erase(insertedfe);
400 return;
401 }
402 }
403 }
404
405 public:
406 /* Information access interface */
407 FEdge *fedge(); // for non T vertex
408
point2d()409 inline const Vec3r &point2d() const
410 {
411 return point2D();
412 }
413
point3d()414 inline const Vec3r &point3d() const
415 {
416 return point3D();
417 }
418
normal()419 inline Vec3r normal() const
420 {
421 if (_Normals.size() == 1) {
422 return (*(_Normals.begin()));
423 }
424 Exception::raiseException();
425 return *(_Normals.begin());
426 }
427
428 // Material material() const ;
429 Id shape_id() const;
430 const SShape *shape() const;
431 float shape_importance() const;
432
433 int qi() const;
434 occluder_container::const_iterator occluders_begin() const;
435 occluder_container::const_iterator occluders_end() const;
436 bool occluders_empty() const;
437 int occluders_size() const;
438 const Polygon3r &occludee() const;
439 const SShape *occluded_shape() const;
440 bool occludee_empty() const;
441 real z_discontinuity() const;
442 #if 0
443 inline float local_average_depth() const;
444 inline float local_depth_variance() const;
445 inline real local_average_density(float sigma = 2.3f) const;
446 inline Vec3r shaded_color() const;
447 inline Vec3r orientation2d() const;
448 inline Vec3r orientation3d() const;
449 inline Vec3r curvature2d_as_vector() const;
450 /*! angle in radians */
451 inline real curvature2d_as_angle() const;
452 #endif
453
454 #ifdef WITH_CXX_GUARDEDALLOC
455 MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SVertex")
456 #endif
457 };
458
459 /**********************************/
460 /* */
461 /* */
462 /* FEdge */
463 /* */
464 /* */
465 /**********************************/
466
467 class ViewEdge;
468
469 /*! Base Class for feature edges.
470 * This FEdge can represent a silhouette, a crease, a ridge/valley, a border or a suggestive
471 * contour. For silhouettes, the FEdge is oriented such as, the visible face lies on the left of
472 * the edge. For borders, the FEdge is oriented such as, the face lies on the left of the edge. An
473 * FEdge can represent an initial edge of the mesh or runs across a face of the initial mesh
474 * depending on the smoothness or sharpness of the mesh. This class is specialized into a smooth
475 * and a sharp version since their properties slightly vary from one to the other.
476 */
477 class FEdge : public Interface1D {
478 public: // Implementation of Interface0D
479 /*! Returns the string "FEdge". */
getExactTypeName()480 virtual string getExactTypeName() const
481 {
482 return "FEdge";
483 }
484
485 // Data access methods
486
487 /*! Returns the 2D length of the FEdge. */
getLength2D()488 virtual real getLength2D() const
489 {
490 if (!_VertexA || !_VertexB) {
491 return 0;
492 }
493 return (_VertexB->getPoint2D() - _VertexA->getPoint2D()).norm();
494 }
495
496 /*! Returns the Id of the FEdge. */
getId()497 virtual Id getId() const
498 {
499 return _Id;
500 }
501
502 public:
503 // An edge can only be of one kind (SILHOUETTE or BORDER, etc...)
504 // For an multi-nature edge there must be several different FEdge.
505 // DEBUG:
506 // Vec3r A;
507 // Vec3r u;
508 // vector<Polygon3r> _Occludees;
509 // Vec3r intersection;
510 // vector<Vec3i> _Cells;
511
512 protected:
513 SVertex *_VertexA;
514 SVertex *_VertexB;
515 Id _Id;
516 Nature::EdgeNature _Nature;
517 // vector<Polygon3r> _Occluders; // visibility // NOT HANDLED BY THE COPY CONSTRUCTOR!!
518
519 FEdge *_NextEdge; // next edge on the chain
520 FEdge *_PreviousEdge;
521 ViewEdge *_ViewEdge;
522 // Sometimes we need to deport the visibility computation onto another edge. For example the
523 // exact edges use edges of the mesh to compute their visibility
524
525 Polygon3r _aFace; // The occluded face which lies on the right of a silhouette edge
526 Vec3r _occludeeIntersection;
527 bool _occludeeEmpty;
528
529 bool _isSmooth;
530
531 bool _isInImage;
532
533 bool _isTemporary;
534
535 public:
536 /*! A field that can be used by the user to store any data.
537 * This field must be reset afterwards using ResetUserData().
538 */
539 void *userdata;
540
541 /*! Default constructor */
FEdge()542 inline FEdge()
543 {
544 userdata = NULL;
545 _VertexA = NULL;
546 _VertexB = NULL;
547 _Nature = Nature::NO_FEATURE;
548 _NextEdge = NULL;
549 _PreviousEdge = NULL;
550 _ViewEdge = NULL;
551 //_hasVisibilityPoint = false;
552 _occludeeEmpty = true;
553 _isSmooth = false;
554 _isInImage = true;
555 _isTemporary = false;
556 }
557
558 /*! Builds an FEdge going from vA to vB. */
FEdge(SVertex * vA,SVertex * vB)559 inline FEdge(SVertex *vA, SVertex *vB)
560 {
561 userdata = NULL;
562 _VertexA = vA;
563 _VertexB = vB;
564 _Nature = Nature::NO_FEATURE;
565 _NextEdge = NULL;
566 _PreviousEdge = NULL;
567 _ViewEdge = NULL;
568 //_hasVisibilityPoint = false;
569 _occludeeEmpty = true;
570 _isSmooth = false;
571 _isInImage = true;
572 _isTemporary = false;
573 }
574
575 /*! Copy constructor */
FEdge(FEdge & iBrother)576 inline FEdge(FEdge &iBrother)
577 {
578 _VertexA = iBrother.vertexA();
579 _VertexB = iBrother.vertexB();
580 _NextEdge = iBrother.nextEdge();
581 _PreviousEdge = iBrother._PreviousEdge;
582 _Nature = iBrother.getNature();
583 _Id = iBrother._Id;
584 _ViewEdge = iBrother._ViewEdge;
585 //_hasVisibilityPoint = iBrother._hasVisibilityPoint;
586 //_VisibilityPointA = iBrother._VisibilityPointA;
587 //_VisibilityPointB = iBrother._VisibilityPointB;
588 _aFace = iBrother._aFace;
589 _occludeeEmpty = iBrother._occludeeEmpty;
590 _isSmooth = iBrother._isSmooth;
591 _isInImage = iBrother._isInImage;
592 _isTemporary = iBrother._isTemporary;
593 iBrother.userdata = this;
594 userdata = 0;
595 }
596
597 /*! Destructor */
~FEdge()598 virtual ~FEdge()
599 {
600 }
601
602 /*! Cloning method. */
duplicate()603 virtual FEdge *duplicate()
604 {
605 FEdge *clone = new FEdge(*this);
606 return clone;
607 }
608
609 /* accessors */
610 /*! Returns the first SVertex. */
vertexA()611 inline SVertex *vertexA()
612 {
613 return _VertexA;
614 }
615
616 /*! Returns the second SVertex. */
vertexB()617 inline SVertex *vertexB()
618 {
619 return _VertexB;
620 }
621
622 /*! Returns the first SVertex if i=0, the second SVertex if i=1. */
623 inline SVertex *operator[](const unsigned short int &i) const
624 {
625 return (i % 2 == 0) ? _VertexA : _VertexB;
626 }
627
628 /*! Returns the nature of the FEdge. */
getNature()629 inline Nature::EdgeNature getNature() const
630 {
631 return _Nature;
632 }
633
634 /*! Returns the FEdge following this one in the ViewEdge.
635 * If this FEdge is the last of the ViewEdge, 0 is returned.
636 */
nextEdge()637 inline FEdge *nextEdge()
638 {
639 return _NextEdge;
640 }
641
642 /*! Returns the Edge preceding this one in the ViewEdge.
643 * If this FEdge is the first one of the ViewEdge, 0 is returned.
644 */
previousEdge()645 inline FEdge *previousEdge()
646 {
647 return _PreviousEdge;
648 }
649
shape()650 inline SShape *shape()
651 {
652 return _VertexA->shape();
653 }
654
655 #if 0
656 inline int invisibility() const
657 {
658 return _Occluders.size();
659 }
660 #endif
661
662 int invisibility() const;
663
664 #if 0
665 inline const vector<Polygon3r> &occluders() const
666 {
667 return _Occluders;
668 }
669 #endif
670
671 /*! Returns a pointer to the ViewEdge to which this FEdge belongs to. */
viewedge()672 inline ViewEdge *viewedge() const
673 {
674 return _ViewEdge;
675 }
676
center3d()677 inline Vec3r center3d()
678 {
679 return Vec3r((_VertexA->point3D() + _VertexB->point3D()) / 2.0);
680 }
681
center2d()682 inline Vec3r center2d()
683 {
684 return Vec3r((_VertexA->point2D() + _VertexB->point2D()) / 2.0);
685 }
686
687 #if 0
688 inline bool hasVisibilityPoint() const
689 {
690 return _hasVisibilityPoint;
691 }
692
693 inline Vec3r visibilityPointA() const
694 {
695 return _VisibilityPointA;
696 }
697
698 inline Vec3r visibilityPointB() const
699 {
700 return _VisibilityPointB;
701 }
702 #endif
703
aFace()704 inline const Polygon3r &aFace() const
705 {
706 return _aFace;
707 }
708
getOccludeeIntersection()709 inline const Vec3r &getOccludeeIntersection()
710 {
711 return _occludeeIntersection;
712 }
713
getOccludeeEmpty()714 inline bool getOccludeeEmpty()
715 {
716 return _occludeeEmpty;
717 }
718
719 /*! Returns true if this FEdge is a smooth FEdge. */
isSmooth()720 inline bool isSmooth() const
721 {
722 return _isSmooth;
723 }
724
isInImage()725 inline bool isInImage() const
726 {
727 return _isInImage;
728 }
729
isTemporary()730 inline bool isTemporary() const
731 {
732 return _isTemporary;
733 }
734
735 /* modifiers */
736 /*! Sets the first SVertex. */
setVertexA(SVertex * vA)737 inline void setVertexA(SVertex *vA)
738 {
739 _VertexA = vA;
740 }
741
742 /*! Sets the second SVertex. */
setVertexB(SVertex * vB)743 inline void setVertexB(SVertex *vB)
744 {
745 _VertexB = vB;
746 }
747
748 /*! Sets the FEdge Id . */
setId(const Id & id)749 inline void setId(const Id &id)
750 {
751 _Id = id;
752 }
753
754 /*! Sets the pointer to the next FEdge. */
setNextEdge(FEdge * iEdge)755 inline void setNextEdge(FEdge *iEdge)
756 {
757 _NextEdge = iEdge;
758 }
759
760 /*! Sets the pointer to the previous FEdge. */
setPreviousEdge(FEdge * iEdge)761 inline void setPreviousEdge(FEdge *iEdge)
762 {
763 _PreviousEdge = iEdge;
764 }
765
766 /*! Sets the nature of this FEdge. */
setNature(Nature::EdgeNature iNature)767 inline void setNature(Nature::EdgeNature iNature)
768 {
769 _Nature = iNature;
770 }
771
772 #if 0
773 inline void AddOccluder(Polygon3r &iPolygon)
774 {
775 _Occluders.push_back(iPolygon);
776 }
777 #endif
778
779 /*! Sets the ViewEdge to which this FEdge belongs to. */
setViewEdge(ViewEdge * iViewEdge)780 inline void setViewEdge(ViewEdge *iViewEdge)
781 {
782 _ViewEdge = iViewEdge;
783 }
784
785 #if 0
786 inline void setHasVisibilityPoint(bool iBool)
787 {
788 _hasVisibilityPoint = iBool;
789 }
790
791 inline void setVisibilityPointA(const Vec3r &iPoint)
792 {
793 _VisibilityPointA = iPoint;
794 }
795
796 inline void setVisibilityPointB(const Vec3r &iPoint)
797 {
798 _VisibilityPointB = iPoint;
799 }
800 #endif
801
setaFace(Polygon3r & iFace)802 inline void setaFace(Polygon3r &iFace)
803 {
804 _aFace = iFace;
805 }
806
setOccludeeIntersection(const Vec3r & iPoint)807 inline void setOccludeeIntersection(const Vec3r &iPoint)
808 {
809 _occludeeIntersection = iPoint;
810 }
811
setOccludeeEmpty(bool iempty)812 inline void setOccludeeEmpty(bool iempty)
813 {
814 _occludeeEmpty = iempty;
815 }
816
817 /*! Sets the flag telling whether this FEdge is smooth or sharp.
818 * true for Smooth, false for Sharp.
819 */
setSmooth(bool iFlag)820 inline void setSmooth(bool iFlag)
821 {
822 _isSmooth = iFlag;
823 }
824
setIsInImage(bool iFlag)825 inline void setIsInImage(bool iFlag)
826 {
827 _isInImage = iFlag;
828 }
829
setTemporary(bool iFlag)830 inline void setTemporary(bool iFlag)
831 {
832 _isTemporary = iFlag;
833 }
834
835 /* checks whether two FEdge have a common vertex.
836 * Returns a pointer on the common vertex if it exists, NULL otherwise.
837 */
CommonVertex(FEdge * iEdge1,FEdge * iEdge2)838 static inline SVertex *CommonVertex(FEdge *iEdge1, FEdge *iEdge2)
839 {
840 if ((NULL == iEdge1) || (NULL == iEdge2)) {
841 return NULL;
842 }
843
844 SVertex *sv1 = iEdge1->vertexA();
845 SVertex *sv2 = iEdge1->vertexB();
846 SVertex *sv3 = iEdge2->vertexA();
847 SVertex *sv4 = iEdge2->vertexB();
848
849 if ((sv1 == sv3) || (sv1 == sv4)) {
850 return sv1;
851 }
852 else if ((sv2 == sv3) || (sv2 == sv4)) {
853 return sv2;
854 }
855
856 return NULL;
857 }
858
min2d()859 inline const SVertex *min2d() const
860 {
861 if (_VertexA->point2D() < _VertexB->point2D()) {
862 return _VertexA;
863 }
864 else {
865 return _VertexB;
866 }
867 }
868
max2d()869 inline const SVertex *max2d() const
870 {
871 if (_VertexA->point2D() < _VertexB->point2D()) {
872 return _VertexB;
873 }
874 else {
875 return _VertexA;
876 }
877 }
878
879 /* Information access interface */
880
881 // Material material() const;
882 Id shape_id() const;
883 const SShape *shape() const;
884 float shape_importance() const;
885
qi()886 inline const int qi() const
887 {
888 return invisibility();
889 }
890
891 occluder_container::const_iterator occluders_begin() const;
892 occluder_container::const_iterator occluders_end() const;
893 bool occluders_empty() const;
894 int occluders_size() const;
895
occludee()896 inline const Polygon3r &occludee() const
897 {
898 return aFace();
899 }
900
901 const SShape *occluded_shape() const;
902
903 #if 0
904 inline const bool occludee_empty() const
905 {
906 return _occludeeEmpty;
907 }
908 #endif
909
910 bool occludee_empty() const;
911 real z_discontinuity() const;
912
913 #if 0
914 inline float local_average_depth(int iCombination = 0) const;
915 inline float local_depth_variance(int iCombination = 0) const;
916 inline real local_average_density(float sigma = 2.3f, int iCombination = 0) const;
917 inline Vec3r shaded_color(int iCombination = 0) const
918 {
919 }
920 #endif
921
922 int viewedge_nature() const;
923
924 // float viewedge_length() const;
925
orientation2d()926 inline Vec3r orientation2d() const
927 {
928 return Vec3r(_VertexB->point2d() - _VertexA->point2d());
929 }
930
orientation3d()931 inline Vec3r orientation3d() const
932 {
933 return Vec3r(_VertexB->point3d() - _VertexA->point3d());
934 }
935
936 #if 0
937 inline real curvature2d() const
938 {
939 return viewedge()->curvature2d((_VertexA->point2d() + _VertexB->point2d()) / 2.0);
940 }
941
942 inline Vec3r curvature2d_as_vector(int iCombination = 0) const;
943
944 /* angle in degrees*/
945 inline real curvature2d_as_angle(int iCombination = 0) const;
946 #endif
947
948 // Iterator access (Interface1D)
949 /*! Returns an iterator over the 2 (!) SVertex pointing to the first SVertex. */
950 virtual inline Interface0DIterator verticesBegin();
951
952 /*! Returns an iterator over the 2 (!) SVertex pointing after the last SVertex. */
953 virtual inline Interface0DIterator verticesEnd();
954
955 /*! Returns an iterator over the FEdge points, pointing to the first point. The difference with
956 * verticesBegin() is that here we can iterate over points of the FEdge at a any given sampling.
957 * Indeed, for each iteration, a virtual point is created.
958 * \param t:
959 * The sampling with which we want to iterate over points of this FEdge.
960 */
961 virtual inline Interface0DIterator pointsBegin(float t = 0.0f);
962
963 /*! Returns an iterator over the FEdge points, pointing after the last point. The difference with
964 * verticesEnd() is that here we can iterate over points of the FEdge at a any given sampling.
965 * Indeed, for each iteration, a virtual point is created.
966 * \param t:
967 * The sampling with which we want to iterate over points of this FEdge.
968 */
969 virtual inline Interface0DIterator pointsEnd(float t = 0.0f);
970
971 #ifdef WITH_CXX_GUARDEDALLOC
972 MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdge")
973 #endif
974 };
975
976 //
977 // SVertexIterator
978 //
979 /////////////////////////////////////////////////
980
981 namespace FEdgeInternal {
982
983 class SVertexIterator : public Interface0DIteratorNested {
984 public:
SVertexIterator()985 SVertexIterator()
986 {
987 _vertex = NULL;
988 _edge = NULL;
989 }
990
SVertexIterator(const SVertexIterator & vi)991 SVertexIterator(const SVertexIterator &vi)
992 {
993 _vertex = vi._vertex;
994 _edge = vi._edge;
995 }
996
SVertexIterator(SVertex * v,FEdge * edge)997 SVertexIterator(SVertex *v, FEdge *edge)
998 {
999 _vertex = v;
1000 _edge = edge;
1001 }
1002
1003 SVertexIterator &operator=(const SVertexIterator &vi)
1004 {
1005 _vertex = vi._vertex;
1006 _edge = vi._edge;
1007 return *this;
1008 }
1009
getExactTypeName()1010 virtual string getExactTypeName() const
1011 {
1012 return "SVertexIterator";
1013 }
1014
1015 virtual SVertex &operator*()
1016 {
1017 return *_vertex;
1018 }
1019
1020 virtual SVertex *operator->()
1021 {
1022 return &(operator*());
1023 }
1024
1025 virtual SVertexIterator &operator++()
1026 {
1027 increment();
1028 return *this;
1029 }
1030
1031 virtual SVertexIterator operator++(int)
1032 {
1033 SVertexIterator ret(*this);
1034 increment();
1035 return ret;
1036 }
1037
1038 virtual SVertexIterator &operator--()
1039 {
1040 decrement();
1041 return *this;
1042 }
1043
1044 virtual SVertexIterator operator--(int)
1045 {
1046 SVertexIterator ret(*this);
1047 decrement();
1048 return ret;
1049 }
1050
increment()1051 virtual int increment()
1052 {
1053 if (_vertex == _edge->vertexB()) {
1054 _vertex = 0;
1055 return 0;
1056 }
1057 _vertex = _edge->vertexB();
1058 return 0;
1059 }
1060
decrement()1061 virtual int decrement()
1062 {
1063 if (_vertex == _edge->vertexA()) {
1064 _vertex = 0;
1065 return 0;
1066 }
1067 _vertex = _edge->vertexA();
1068 return 0;
1069 }
1070
isBegin()1071 virtual bool isBegin() const
1072 {
1073 return _vertex == _edge->vertexA();
1074 }
1075
isEnd()1076 virtual bool isEnd() const
1077 {
1078 return _vertex == _edge->vertexB();
1079 }
1080
1081 virtual bool operator==(const Interface0DIteratorNested &it) const
1082 {
1083 const SVertexIterator *it_exact = dynamic_cast<const SVertexIterator *>(&it);
1084 if (!it_exact) {
1085 return false;
1086 }
1087 return ((_vertex == it_exact->_vertex) && (_edge == it_exact->_edge));
1088 }
1089
t()1090 virtual float t() const
1091 {
1092 if (_vertex == _edge->vertexA()) {
1093 return 0.0f;
1094 }
1095 return ((float)_edge->getLength2D());
1096 }
u()1097 virtual float u() const
1098 {
1099 if (_vertex == _edge->vertexA()) {
1100 return 0.0f;
1101 }
1102 return 1.0f;
1103 }
1104
copy()1105 virtual SVertexIterator *copy() const
1106 {
1107 return new SVertexIterator(*this);
1108 }
1109
1110 private:
1111 SVertex *_vertex;
1112 FEdge *_edge;
1113 };
1114
1115 } // end of namespace FEdgeInternal
1116
1117 // Iterator access (implementation)
1118
verticesBegin()1119 Interface0DIterator FEdge::verticesBegin()
1120 {
1121 Interface0DIterator ret(new FEdgeInternal::SVertexIterator(_VertexA, this));
1122 return ret;
1123 }
1124
verticesEnd()1125 Interface0DIterator FEdge::verticesEnd()
1126 {
1127 Interface0DIterator ret(new FEdgeInternal::SVertexIterator(0, this));
1128 return ret;
1129 }
1130
pointsBegin(float)1131 Interface0DIterator FEdge::pointsBegin(float /*t*/)
1132 {
1133 return verticesBegin();
1134 }
1135
pointsEnd(float)1136 Interface0DIterator FEdge::pointsEnd(float /*t*/)
1137 {
1138 return verticesEnd();
1139 }
1140
1141 /*! Class defining a sharp FEdge. A Sharp FEdge corresponds to an initial edge of the input mesh.
1142 * It can be a silhouette, a crease or a border. If it is a crease edge, then it is bordered
1143 * by two faces of the mesh. Face a lies on its right whereas Face b lies on its left.
1144 * If it is a border edge, then it doesn't have any face on its right, and thus Face a = 0.
1145 */
1146 class FEdgeSharp : public FEdge {
1147 protected:
1148 Vec3r _aNormal; // When following the edge, normal of the right face
1149 Vec3r _bNormal; // When following the edge, normal of the left face
1150 unsigned _aFrsMaterialIndex;
1151 unsigned _bFrsMaterialIndex;
1152 bool _aFaceMark;
1153 bool _bFaceMark;
1154
1155 public:
1156 /*! Returns the string "FEdgeSharp" . */
getExactTypeName()1157 virtual string getExactTypeName() const
1158 {
1159 return "FEdgeSharp";
1160 }
1161
1162 /*! Default constructor. */
FEdgeSharp()1163 inline FEdgeSharp() : FEdge()
1164 {
1165 _aFrsMaterialIndex = _bFrsMaterialIndex = 0;
1166 _aFaceMark = _bFaceMark = false;
1167 }
1168
1169 /*! Builds an FEdgeSharp going from vA to vB. */
FEdgeSharp(SVertex * vA,SVertex * vB)1170 inline FEdgeSharp(SVertex *vA, SVertex *vB) : FEdge(vA, vB)
1171 {
1172 _aFrsMaterialIndex = _bFrsMaterialIndex = 0;
1173 _aFaceMark = _bFaceMark = false;
1174 }
1175
1176 /*! Copy constructor. */
FEdgeSharp(FEdgeSharp & iBrother)1177 inline FEdgeSharp(FEdgeSharp &iBrother) : FEdge(iBrother)
1178 {
1179 _aNormal = iBrother._aNormal;
1180 _bNormal = iBrother._bNormal;
1181 _aFrsMaterialIndex = iBrother._aFrsMaterialIndex;
1182 _bFrsMaterialIndex = iBrother._bFrsMaterialIndex;
1183 _aFaceMark = iBrother._aFaceMark;
1184 _bFaceMark = iBrother._bFaceMark;
1185 }
1186
1187 /*! Destructor. */
~FEdgeSharp()1188 virtual ~FEdgeSharp()
1189 {
1190 }
1191
1192 /*! Cloning method. */
duplicate()1193 virtual FEdge *duplicate()
1194 {
1195 FEdge *clone = new FEdgeSharp(*this);
1196 return clone;
1197 }
1198
1199 /*! Returns the normal to the face lying on the right of the FEdge. If this FEdge is a border,
1200 * it has no Face on its right and therefore, no normal.
1201 */
normalA()1202 inline const Vec3r &normalA()
1203 {
1204 return _aNormal;
1205 }
1206
1207 /*! Returns the normal to the face lying on the left of the FEdge. */
normalB()1208 inline const Vec3r &normalB()
1209 {
1210 return _bNormal;
1211 }
1212
1213 /*! Returns the index of the material of the face lying on the
1214 * right of the FEdge. If this FEdge is a border,
1215 * it has no Face on its right and therefore, no material.
1216 */
aFrsMaterialIndex()1217 inline unsigned aFrsMaterialIndex() const
1218 {
1219 return _aFrsMaterialIndex;
1220 }
1221
1222 /*! Returns the material of the face lying on the right of the FEdge. If this FEdge is a border,
1223 * it has no Face on its right and therefore, no material.
1224 */
1225 const FrsMaterial &aFrsMaterial() const;
1226
1227 /*! Returns the index of the material of the face lying on the left of the FEdge. */
bFrsMaterialIndex()1228 inline unsigned bFrsMaterialIndex() const
1229 {
1230 return _bFrsMaterialIndex;
1231 }
1232
1233 /*! Returns the material of the face lying on the left of the FEdge. */
1234 const FrsMaterial &bFrsMaterial() const;
1235
1236 /*! Returns the face mark of the face lying on the right of the FEdge.
1237 * If this FEdge is a border, it has no Face on its right and thus false is returned.
1238 */
aFaceMark()1239 inline bool aFaceMark() const
1240 {
1241 return _aFaceMark;
1242 }
1243
1244 /*! Returns the face mark of the face lying on the left of the FEdge. */
bFaceMark()1245 inline bool bFaceMark() const
1246 {
1247 return _bFaceMark;
1248 }
1249
1250 /*! Sets the normal to the face lying on the right of the FEdge. */
setNormalA(const Vec3r & iNormal)1251 inline void setNormalA(const Vec3r &iNormal)
1252 {
1253 _aNormal = iNormal;
1254 }
1255
1256 /*! Sets the normal to the face lying on the left of the FEdge. */
setNormalB(const Vec3r & iNormal)1257 inline void setNormalB(const Vec3r &iNormal)
1258 {
1259 _bNormal = iNormal;
1260 }
1261
1262 /*! Sets the index of the material lying on the right of the FEdge.*/
setaFrsMaterialIndex(unsigned i)1263 inline void setaFrsMaterialIndex(unsigned i)
1264 {
1265 _aFrsMaterialIndex = i;
1266 }
1267
1268 /*! Sets the index of the material lying on the left of the FEdge.*/
setbFrsMaterialIndex(unsigned i)1269 inline void setbFrsMaterialIndex(unsigned i)
1270 {
1271 _bFrsMaterialIndex = i;
1272 }
1273
1274 /*! Sets the face mark of the face lying on the right of the FEdge. */
setaFaceMark(bool iFaceMark)1275 inline void setaFaceMark(bool iFaceMark)
1276 {
1277 _aFaceMark = iFaceMark;
1278 }
1279
1280 /*! Sets the face mark of the face lying on the left of the FEdge. */
setbFaceMark(bool iFaceMark)1281 inline void setbFaceMark(bool iFaceMark)
1282 {
1283 _bFaceMark = iFaceMark;
1284 }
1285
1286 #ifdef WITH_CXX_GUARDEDALLOC
1287 MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSharp")
1288 #endif
1289 };
1290
1291 /*! Class defining a smooth edge. This kind of edge typically runs across a face of the input mesh.
1292 * It can be a silhouette, a ridge or valley, a suggestive contour.
1293 */
1294 class FEdgeSmooth : public FEdge {
1295 protected:
1296 Vec3r _Normal;
1297 unsigned _FrsMaterialIndex;
1298 #if 0
1299 bool _hasVisibilityPoint;
1300 Vec3r _VisibilityPointA; // The edge on which the visibility will be computed represented
1301 Vec3r _VisibilityPointB; // using its 2 extremity points A and B
1302 #endif
1303 void *_Face; // In case of exact silhouette, Face is the WFace crossed by Fedge
1304 // NOT HANDLED BY THE COPY CONSTRUCTEUR
1305 bool _FaceMark;
1306
1307 public:
1308 /*! Returns the string "FEdgeSmooth" . */
getExactTypeName()1309 virtual string getExactTypeName() const
1310 {
1311 return "FEdgeSmooth";
1312 }
1313
1314 /*! Default constructor. */
FEdgeSmooth()1315 inline FEdgeSmooth() : FEdge()
1316 {
1317 _Face = NULL;
1318 _FaceMark = false;
1319 _FrsMaterialIndex = 0;
1320 _isSmooth = true;
1321 }
1322
1323 /*! Builds an FEdgeSmooth going from vA to vB. */
FEdgeSmooth(SVertex * vA,SVertex * vB)1324 inline FEdgeSmooth(SVertex *vA, SVertex *vB) : FEdge(vA, vB)
1325 {
1326 _Face = NULL;
1327 _FaceMark = false;
1328 _FrsMaterialIndex = 0;
1329 _isSmooth = true;
1330 }
1331
1332 /*! Copy constructor. */
FEdgeSmooth(FEdgeSmooth & iBrother)1333 inline FEdgeSmooth(FEdgeSmooth &iBrother) : FEdge(iBrother)
1334 {
1335 _Normal = iBrother._Normal;
1336 _Face = iBrother._Face;
1337 _FaceMark = iBrother._FaceMark;
1338 _FrsMaterialIndex = iBrother._FrsMaterialIndex;
1339 _isSmooth = true;
1340 }
1341
1342 /*! Destructor. */
~FEdgeSmooth()1343 virtual ~FEdgeSmooth()
1344 {
1345 }
1346
1347 /*! Cloning method. */
duplicate()1348 virtual FEdge *duplicate()
1349 {
1350 FEdge *clone = new FEdgeSmooth(*this);
1351 return clone;
1352 }
1353
face()1354 inline void *face() const
1355 {
1356 return _Face;
1357 }
1358
1359 /*! Returns the face mark of the face it is running across. */
faceMark()1360 inline bool faceMark() const
1361 {
1362 return _FaceMark;
1363 }
1364
1365 /*! Returns the normal to the Face it is running across. */
normal()1366 inline const Vec3r &normal()
1367 {
1368 return _Normal;
1369 }
1370
1371 /*! Returns the index of the material of the face it is running across. */
frs_materialIndex()1372 inline unsigned frs_materialIndex() const
1373 {
1374 return _FrsMaterialIndex;
1375 }
1376
1377 /*! Returns the material of the face it is running across. */
1378 const FrsMaterial &frs_material() const;
1379
setFace(void * iFace)1380 inline void setFace(void *iFace)
1381 {
1382 _Face = iFace;
1383 }
1384
1385 /*! Sets the face mark of the face it is running across. */
setFaceMark(bool iFaceMark)1386 inline void setFaceMark(bool iFaceMark)
1387 {
1388 _FaceMark = iFaceMark;
1389 }
1390
1391 /*! Sets the normal to the Face it is running across. */
setNormal(const Vec3r & iNormal)1392 inline void setNormal(const Vec3r &iNormal)
1393 {
1394 _Normal = iNormal;
1395 }
1396
1397 /*! Sets the index of the material of the face it is running across. */
setFrsMaterialIndex(unsigned i)1398 inline void setFrsMaterialIndex(unsigned i)
1399 {
1400 _FrsMaterialIndex = i;
1401 }
1402
1403 #ifdef WITH_CXX_GUARDEDALLOC
1404 MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSmooth")
1405 #endif
1406 };
1407
1408 /**********************************/
1409 /* */
1410 /* */
1411 /* SShape */
1412 /* */
1413 /* */
1414 /**********************************/
1415
1416 /*! Class to define a feature shape. It is the gathering of feature elements from an identified
1417 * input shape */
1418 class SShape {
1419 private:
1420 vector<FEdge *> _chains; // list of fedges that are chains starting points.
1421 vector<SVertex *> _verticesList; // list of all vertices
1422 vector<FEdge *> _edgesList; // list of all edges
1423 Id _Id;
1424 string _Name;
1425 string _LibraryPath;
1426 BBox<Vec3r> _BBox;
1427 vector<FrsMaterial> _FrsMaterials;
1428
1429 float _importance;
1430
1431 ViewShape *_ViewShape;
1432
1433 public:
1434 /*! A field that can be used by the user to store any data.
1435 * This field must be reset afterwards using ResetUserData().
1436 */
1437 void *userdata; // added by E.T.
1438
1439 /*! Default constructor */
SShape()1440 inline SShape()
1441 {
1442 userdata = NULL;
1443 _importance = 0.0f;
1444 _ViewShape = NULL;
1445 }
1446
1447 /*! Copy constructor */
SShape(SShape & iBrother)1448 inline SShape(SShape &iBrother)
1449 {
1450 userdata = NULL;
1451 _Id = iBrother._Id;
1452 _Name = iBrother._Name;
1453 _LibraryPath = iBrother._LibraryPath;
1454 _BBox = iBrother.bbox();
1455 _FrsMaterials = iBrother._FrsMaterials;
1456 _importance = iBrother._importance;
1457 _ViewShape = iBrother._ViewShape;
1458
1459 //---------
1460 // vertices
1461 //---------
1462 vector<SVertex *>::iterator sv, svend;
1463 vector<SVertex *> &verticesList = iBrother.getVertexList();
1464 for (sv = verticesList.begin(), svend = verticesList.end(); sv != svend; sv++) {
1465 SVertex *newv = new SVertex(*(*sv));
1466 newv->setShape(this);
1467 _verticesList.push_back(newv);
1468 }
1469
1470 //------
1471 // edges
1472 //------
1473 vector<FEdge *>::iterator e, eend;
1474 vector<FEdge *> &edgesList = iBrother.getEdgeList();
1475 for (e = edgesList.begin(), eend = edgesList.end(); e != eend; e++) {
1476 FEdge *newe = (*e)->duplicate();
1477 _edgesList.push_back(newe);
1478 }
1479
1480 //-------------------------
1481 // starting chain edges
1482 //-------------------------
1483 vector<FEdge *>::iterator fe, fend;
1484 vector<FEdge *> &fedges = iBrother.getChains();
1485 for (fe = fedges.begin(), fend = fedges.end(); fe != fend; fe++) {
1486 _chains.push_back((FEdge *)((*fe)->userdata));
1487 }
1488
1489 //-------------------------
1490 // remap edges in vertices:
1491 //-------------------------
1492 for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) {
1493 const vector<FEdge *> &fedgeList = (*sv)->fedges();
1494 vector<FEdge *> newfedgelist;
1495 for (vector<FEdge *>::const_iterator fed = fedgeList.begin(), fedend = fedgeList.end();
1496 fed != fedend;
1497 fed++) {
1498 FEdge *current = *fed;
1499 newfedgelist.push_back((FEdge *)current->userdata);
1500 }
1501 (*sv)->setFEdges(newfedgelist);
1502 }
1503
1504 //-------------------------------------
1505 // remap vertices and nextedge in edges:
1506 //-------------------------------------
1507 for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) {
1508 (*e)->setVertexA((SVertex *)((*e)->vertexA()->userdata));
1509 (*e)->setVertexB((SVertex *)((*e)->vertexB()->userdata));
1510 (*e)->setNextEdge((FEdge *)((*e)->nextEdge()->userdata));
1511 (*e)->setPreviousEdge((FEdge *)((*e)->previousEdge()->userdata));
1512 }
1513
1514 // reset all brothers userdata to NULL:
1515 //-------------------------------------
1516 //---------
1517 // vertices
1518 //---------
1519 for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) {
1520 (*sv)->userdata = NULL;
1521 }
1522
1523 //------
1524 // edges
1525 //------
1526 for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) {
1527 (*e)->userdata = NULL;
1528 }
1529 }
1530
1531 /*! Cloning method. */
duplicate()1532 virtual SShape *duplicate()
1533 {
1534 SShape *clone = new SShape(*this);
1535 return clone;
1536 }
1537
1538 /*! Destructor. */
~SShape()1539 virtual inline ~SShape()
1540 {
1541 vector<SVertex *>::iterator sv, svend;
1542 vector<FEdge *>::iterator e, eend;
1543 if (0 != _verticesList.size()) {
1544 for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) {
1545 delete (*sv);
1546 }
1547 _verticesList.clear();
1548 }
1549
1550 if (0 != _edgesList.size()) {
1551 for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) {
1552 delete (*e);
1553 }
1554 _edgesList.clear();
1555 }
1556
1557 //! Clear the chains list
1558 //-----------------------
1559 if (0 != _chains.size()) {
1560 _chains.clear();
1561 }
1562 }
1563
1564 /*! Adds a FEdge to the list of FEdges. */
AddEdge(FEdge * iEdge)1565 inline void AddEdge(FEdge *iEdge)
1566 {
1567 _edgesList.push_back(iEdge);
1568 }
1569
1570 /*! Adds a SVertex to the list of SVertex of this Shape.
1571 * The SShape attribute of the SVertex is also set to 'this'.
1572 */
AddNewVertex(SVertex * iv)1573 inline void AddNewVertex(SVertex *iv)
1574 {
1575 iv->setShape(this);
1576 _verticesList.push_back(iv);
1577 }
1578
AddChain(FEdge * iEdge)1579 inline void AddChain(FEdge *iEdge)
1580 {
1581 _chains.push_back(iEdge);
1582 }
1583
CreateSVertex(const Vec3r & P3D,const Vec3r & P2D,const Id & id)1584 inline SVertex *CreateSVertex(const Vec3r &P3D, const Vec3r &P2D, const Id &id)
1585 {
1586 SVertex *Ia = new SVertex(P3D, id);
1587 Ia->setPoint2D(P2D);
1588 AddNewVertex(Ia);
1589 return Ia;
1590 }
1591
1592 /*! Splits an edge into several edges.
1593 * The edge's vertices are passed rather than the edge itself. This way, all feature edges
1594 * (SILHOUETTE, CREASE, BORDER) are split in the same time. The processed edges are flagged as
1595 * done (using the user-data flag).One single new vertex is created whereas several split edges
1596 * might created for the different kinds of edges. These new elements are added to the lists
1597 * maintained by the shape.
1598 * New chains are also created.
1599 * ioA
1600 * The first vertex for the edge that gets split.
1601 * ioB
1602 * The second vertex for the edge that gets split.
1603 * iParameters
1604 * A vector containing 2D real vectors indicating the parameters giving the intersections
1605 * coordinates in 3D and in 2D. These intersections points must be sorted from B to A. Each
1606 * parameter defines the intersection point I as I=A+T*AB. T<0 and T>1 are then incorrect insofar
1607 * as they give intersections points that lie outside the segment. ioNewEdges The edges that are
1608 * newly created (the initial edges are not included) are added to this list.
1609 */
SplitEdge(FEdge * fe,const vector<Vec2r> & iParameters,vector<FEdge * > & ioNewEdges)1610 inline void SplitEdge(FEdge *fe, const vector<Vec2r> &iParameters, vector<FEdge *> &ioNewEdges)
1611 {
1612 SVertex *ioA = fe->vertexA();
1613 SVertex *ioB = fe->vertexB();
1614 Vec3r A = ioA->point3D();
1615 Vec3r B = ioB->point3D();
1616 Vec3r a = ioA->point2D();
1617 Vec3r b = ioB->point2D();
1618
1619 Vec3r newpoint3d, newpoint2d;
1620 vector<SVertex *> intersections;
1621 real t, T;
1622 for (vector<Vec2r>::const_iterator p = iParameters.begin(), pend = iParameters.end();
1623 p != pend;
1624 p++) {
1625 T = (*p)[0];
1626 t = (*p)[1];
1627
1628 if ((t < 0) || (t > 1)) {
1629 cerr << "Warning: Intersection out of range for edge " << ioA->getId() << " - "
1630 << ioB->getId() << endl;
1631 }
1632
1633 // compute the 3D and 2D coordinates for the intersections points:
1634 newpoint3d = Vec3r(A + T * (B - A));
1635 newpoint2d = Vec3r(a + t * (b - a));
1636
1637 // create new SVertex:
1638 // (we keep B's id)
1639 SVertex *newVertex = new SVertex(newpoint3d, ioB->getId());
1640 newVertex->setPoint2D(newpoint2d);
1641
1642 // Add this vertex to the intersections list:
1643 intersections.push_back(newVertex);
1644
1645 // Add this vertex to this sshape:
1646 AddNewVertex(newVertex);
1647 }
1648
1649 for (vector<SVertex *>::iterator sv = intersections.begin(), svend = intersections.end();
1650 sv != svend;
1651 sv++) {
1652 // SVertex *svA = fe->vertexA();
1653 SVertex *svB = fe->vertexB();
1654
1655 // We split edge AB into AA' and A'B. A' and A'B are created.
1656 // AB becomes (address speaking) AA'. B is updated.
1657 //--------------------------------------------------
1658 // The edge AB becomes edge AA'.
1659 (fe)->setVertexB((*sv));
1660 // a new edge, A'B is created.
1661 FEdge *newEdge;
1662 if (fe->isSmooth()) {
1663 newEdge = new FEdgeSmooth((*sv), svB);
1664 FEdgeSmooth *se = dynamic_cast<FEdgeSmooth *>(newEdge);
1665 FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(fe);
1666 se->setFrsMaterialIndex(fes->frs_materialIndex());
1667 }
1668 else {
1669 newEdge = new FEdgeSharp((*sv), svB);
1670 FEdgeSharp *se = dynamic_cast<FEdgeSharp *>(newEdge);
1671 FEdgeSharp *fes = dynamic_cast<FEdgeSharp *>(fe);
1672 se->setaFrsMaterialIndex(fes->aFrsMaterialIndex());
1673 se->setbFrsMaterialIndex(fes->bFrsMaterialIndex());
1674 }
1675
1676 newEdge->setNature((fe)->getNature());
1677
1678 // to build a new chain:
1679 AddChain(newEdge);
1680 // add the new edge to the sshape edges list.
1681 AddEdge(newEdge);
1682 // add new edge to the list of new edges passed as argument:
1683 ioNewEdges.push_back(newEdge);
1684
1685 // update edge A'B for the next pointing edge
1686 newEdge->setNextEdge((fe)->nextEdge());
1687 fe->nextEdge()->setPreviousEdge(newEdge);
1688 Id id(fe->getId().getFirst(), fe->getId().getSecond() + 1);
1689 newEdge->setId(fe->getId());
1690 fe->setId(id);
1691
1692 // update edge AA' for the next pointing edge
1693 // ioEdge->setNextEdge(newEdge);
1694 (fe)->setNextEdge(NULL);
1695
1696 // update vertex pointing edges list:
1697 // -- vertex B --
1698 svB->Replace((fe), newEdge);
1699 // -- vertex A' --
1700 (*sv)->AddFEdge((fe));
1701 (*sv)->AddFEdge(newEdge);
1702 }
1703 }
1704
1705 /* splits an edge into 2 edges. The new vertex and edge are added to the sshape list of vertices
1706 * and edges a new chain is also created. returns the new edge. ioEdge The edge that gets
1707 * splitted newpoint x,y,z coordinates of the new point.
1708 */
SplitEdgeIn2(FEdge * ioEdge,SVertex * ioNewVertex)1709 inline FEdge *SplitEdgeIn2(FEdge *ioEdge, SVertex *ioNewVertex)
1710 {
1711 // soc unused - SVertex *A = ioEdge->vertexA();
1712 SVertex *B = ioEdge->vertexB();
1713
1714 // We split edge AB into AA' and A'B. A' and A'B are created.
1715 // AB becomes (address speaking) AA'. B is updated.
1716 //--------------------------------------------------
1717 // a new edge, A'B is created.
1718 FEdge *newEdge;
1719 if (ioEdge->isSmooth()) {
1720 newEdge = new FEdgeSmooth(ioNewVertex, B);
1721 FEdgeSmooth *se = dynamic_cast<FEdgeSmooth *>(newEdge);
1722 FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(ioEdge);
1723 se->setNormal(fes->normal());
1724 se->setFrsMaterialIndex(fes->frs_materialIndex());
1725 se->setFaceMark(fes->faceMark());
1726 }
1727 else {
1728 newEdge = new FEdgeSharp(ioNewVertex, B);
1729 FEdgeSharp *se = dynamic_cast<FEdgeSharp *>(newEdge);
1730 FEdgeSharp *fes = dynamic_cast<FEdgeSharp *>(ioEdge);
1731 se->setNormalA(fes->normalA());
1732 se->setNormalB(fes->normalB());
1733 se->setaFrsMaterialIndex(fes->aFrsMaterialIndex());
1734 se->setbFrsMaterialIndex(fes->bFrsMaterialIndex());
1735 se->setaFaceMark(fes->aFaceMark());
1736 se->setbFaceMark(fes->bFaceMark());
1737 }
1738 newEdge->setNature(ioEdge->getNature());
1739
1740 if (ioEdge->nextEdge() != 0) {
1741 ioEdge->nextEdge()->setPreviousEdge(newEdge);
1742 }
1743
1744 // update edge A'B for the next pointing edge
1745 newEdge->setNextEdge(ioEdge->nextEdge());
1746 // update edge A'B for the previous pointing edge
1747 newEdge->setPreviousEdge(0); // because it is now a TVertex
1748 Id id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond() + 1);
1749 newEdge->setId(ioEdge->getId());
1750 ioEdge->setId(id);
1751
1752 // update edge AA' for the next pointing edge
1753 ioEdge->setNextEdge(0); // because it is now a TVertex
1754
1755 // update vertex pointing edges list:
1756 // -- vertex B --
1757 B->Replace(ioEdge, newEdge);
1758 // -- vertex A' --
1759 ioNewVertex->AddFEdge(ioEdge);
1760 ioNewVertex->AddFEdge(newEdge);
1761
1762 // to build a new chain:
1763 AddChain(newEdge);
1764 AddEdge(newEdge); // FIXME ??
1765
1766 // The edge AB becomes edge AA'.
1767 ioEdge->setVertexB(ioNewVertex);
1768
1769 if (ioEdge->isSmooth()) {
1770 ((FEdgeSmooth *)newEdge)->setFace(((FEdgeSmooth *)ioEdge)->face());
1771 }
1772
1773 return newEdge;
1774 }
1775
1776 /*! Sets the Bounding Box of the Shape */
setBBox(const BBox<Vec3r> & iBBox)1777 inline void setBBox(const BBox<Vec3r> &iBBox)
1778 {
1779 _BBox = iBBox;
1780 }
1781
1782 /*! Compute the bbox of the sshape */
ComputeBBox()1783 inline void ComputeBBox()
1784 {
1785 if (0 == _verticesList.size()) {
1786 return;
1787 }
1788
1789 Vec3r firstVertex = _verticesList[0]->point3D();
1790 real XMax = firstVertex[0];
1791 real YMax = firstVertex[1];
1792 real ZMax = firstVertex[2];
1793
1794 real XMin = firstVertex[0];
1795 real YMin = firstVertex[1];
1796 real ZMin = firstVertex[2];
1797
1798 vector<SVertex *>::iterator v, vend;
1799 // parse all the coordinates to find the Xmax, YMax, ZMax
1800 for (v = _verticesList.begin(), vend = _verticesList.end(); v != vend; v++) {
1801 Vec3r vertex = (*v)->point3D();
1802 // X
1803 real x = vertex[0];
1804 if (x > XMax) {
1805 XMax = x;
1806 }
1807 else if (x < XMin) {
1808 XMin = x;
1809 }
1810
1811 // Y
1812 real y = vertex[1];
1813 if (y > YMax) {
1814 YMax = y;
1815 }
1816 else if (y < YMin) {
1817 YMin = y;
1818 }
1819
1820 // Z
1821 real z = vertex[2];
1822 if (z > ZMax) {
1823 ZMax = z;
1824 }
1825 else if (z < ZMin) {
1826 ZMin = z;
1827 }
1828 }
1829
1830 setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
1831 }
1832
RemoveEdgeFromChain(FEdge * iEdge)1833 inline void RemoveEdgeFromChain(FEdge *iEdge)
1834 {
1835 for (vector<FEdge *>::iterator fe = _chains.begin(), feend = _chains.end(); fe != feend;
1836 fe++) {
1837 if (iEdge == (*fe)) {
1838 _chains.erase(fe);
1839 break;
1840 }
1841 }
1842 }
1843
RemoveEdge(FEdge * iEdge)1844 inline void RemoveEdge(FEdge *iEdge)
1845 {
1846 for (vector<FEdge *>::iterator fe = _edgesList.begin(), feend = _edgesList.end(); fe != feend;
1847 fe++) {
1848 if (iEdge == (*fe)) {
1849 _edgesList.erase(fe);
1850 break;
1851 }
1852 }
1853 }
1854
1855 /* accessors */
1856 /*! Returns the list of SVertex of the Shape. */
getVertexList()1857 inline vector<SVertex *> &getVertexList()
1858 {
1859 return _verticesList;
1860 }
1861
1862 /*! Returns the list of FEdges of the Shape. */
getEdgeList()1863 inline vector<FEdge *> &getEdgeList()
1864 {
1865 return _edgesList;
1866 }
1867
getChains()1868 inline vector<FEdge *> &getChains()
1869 {
1870 return _chains;
1871 }
1872
1873 /*! Returns the bounding box of the shape. */
bbox()1874 inline const BBox<Vec3r> &bbox()
1875 {
1876 return _BBox;
1877 }
1878
1879 /*! Returns the ith material of the shape. */
frs_material(unsigned i)1880 inline const FrsMaterial &frs_material(unsigned i) const
1881 {
1882 return _FrsMaterials[i];
1883 }
1884
1885 /*! Returns the list of materials of the Shape. */
frs_materials()1886 inline const vector<FrsMaterial> &frs_materials() const
1887 {
1888 return _FrsMaterials;
1889 }
1890
viewShape()1891 inline ViewShape *viewShape()
1892 {
1893 return _ViewShape;
1894 }
1895
importance()1896 inline float importance() const
1897 {
1898 return _importance;
1899 }
1900
1901 /*! Returns the Id of the Shape. */
getId()1902 inline Id getId() const
1903 {
1904 return _Id;
1905 }
1906
1907 /*! Returns the name of the Shape. */
getName()1908 inline const string &getName() const
1909 {
1910 return _Name;
1911 }
1912
1913 /*! Returns the library path of the Shape. */
getLibraryPath()1914 inline const string &getLibraryPath() const
1915 {
1916 return _LibraryPath;
1917 }
1918
1919 /* Modififers */
1920 /*! Sets the Id of the shape.*/
setId(Id id)1921 inline void setId(Id id)
1922 {
1923 _Id = id;
1924 }
1925
1926 /*! Sets the name of the shape.*/
setName(const string & name)1927 inline void setName(const string &name)
1928 {
1929 _Name = name;
1930 }
1931
1932 /*! Sets the library path of the shape.*/
setLibraryPath(const string & path)1933 inline void setLibraryPath(const string &path)
1934 {
1935 _LibraryPath = path;
1936 }
1937
1938 /*! Sets the list of materials for the shape */
setFrsMaterials(const vector<FrsMaterial> & iMaterials)1939 inline void setFrsMaterials(const vector<FrsMaterial> &iMaterials)
1940 {
1941 _FrsMaterials = iMaterials;
1942 }
1943
setViewShape(ViewShape * iShape)1944 inline void setViewShape(ViewShape *iShape)
1945 {
1946 _ViewShape = iShape;
1947 }
1948
setImportance(float importance)1949 inline void setImportance(float importance)
1950 {
1951 _importance = importance;
1952 }
1953
1954 #ifdef WITH_CXX_GUARDEDALLOC
1955 MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SShape")
1956 #endif
1957 };
1958
1959 } /* namespace Freestyle */
1960