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