/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __FREESTYLE_W_EDGE_H__ #define __FREESTYLE_W_EDGE_H__ /** \file * \ingroup freestyle * \brief Classes to define a Winged Edge data structure. */ #include #include #include "../geometry/Geom.h" #include "../scene_graph/FrsMaterial.h" #include "../system/FreestyleConfig.h" #include "BLI_math.h" #ifdef WITH_CXX_GUARDEDALLOC # include "MEM_guardedalloc.h" #endif using namespace std; namespace Freestyle { using namespace Geometry; /********************************** * * * * * WVertex * * * * * **********************************/ class WOEdge; class WEdge; class WShape; class WFace; class WVertex { protected: int _Id; // an identificator Vec3f _Vertex; vector _EdgeList; WShape *_Shape; // the shape to which the vertex belongs bool _Smooth; // flag to indicate whether the Vertex belongs to a smooth edge or not short _Border; // 1 -> border, 0 -> no border, -1 -> not set public: void *userdata; // designed to store specific user data inline WVertex(const Vec3f &v) { _Id = 0; _Vertex = v; userdata = NULL; _Shape = NULL; _Smooth = true; _Border = -1; } /*! Copy constructor */ WVertex(WVertex &iBrother); virtual WVertex *duplicate(); virtual ~WVertex() { } /*! accessors */ inline Vec3f &GetVertex() { return _Vertex; } inline vector &GetEdges() { return _EdgeList; } inline int GetId() { return _Id; } inline WShape *shape() const { return _Shape; } inline bool isSmooth() const { return _Smooth; } bool isBoundary(); /*! modifiers */ inline void setVertex(const Vec3f &v) { _Vertex = v; } inline void setEdges(const vector &iEdgeList) { _EdgeList = iEdgeList; } inline void setId(int id) { _Id = id; } inline void setShape(WShape *iShape) { _Shape = iShape; } inline void setSmooth(bool b) { _Smooth = b; } inline void setBorder(bool b) { if (b) { _Border = 1; } else { _Border = 0; } } /*! Adds an edge to the edges list */ void AddEdge(WEdge *iEdge); virtual void ResetUserData() { userdata = NULL; } public: /*! Iterator to iterate over a vertex incoming edges in the CCW order*/ #if defined(__GNUC__) && (__GNUC__ < 3) class incoming_edge_iterator : public input_iterator #else class incoming_edge_iterator : public iterator #endif { private: WVertex *_vertex; // WOEdge *_begin; WOEdge *_current; public: #if defined(__GNUC__) && (__GNUC__ < 3) inline incoming_edge_iterator() : input_iterator() { } #else inline incoming_edge_iterator() : iterator() { } #endif virtual ~incoming_edge_iterator(){}; // soc protected: friend class WVertex; inline incoming_edge_iterator(WVertex *iVertex, WOEdge *iBegin, WOEdge *iCurrent) #if defined(__GNUC__) && (__GNUC__ < 3) : input_iterator() #else : iterator() #endif { _vertex = iVertex; _begin = iBegin; _current = iCurrent; } public: inline incoming_edge_iterator(const incoming_edge_iterator &iBrother) #if defined(__GNUC__) && (__GNUC__ < 3) : input_iterator(iBrother) #else : iterator(iBrother) #endif { _vertex = iBrother._vertex; _begin = iBrother._begin; _current = iBrother._current; } public: // operators // operator corresponding to ++i virtual incoming_edge_iterator &operator++() { increment(); return *this; } // operator corresponding to i++ virtual incoming_edge_iterator operator++(int) { incoming_edge_iterator tmp = *this; increment(); return tmp; } // comparibility virtual bool operator!=(const incoming_edge_iterator &b) const { return ((_current) != (b._current)); } virtual bool operator==(const incoming_edge_iterator &b) const { return ((_current) == (b._current)); } // dereferencing virtual WOEdge *operator*(); // virtual WOEdge **operator->(); protected: virtual void increment(); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WVertex:incoming_edge_iterator") #endif }; /*! Iterator to iterate over a vertex faces in the CCW order */ #if defined(__GNUC__) && (__GNUC__ < 3) class face_iterator : public input_iterator #else class face_iterator : public iterator #endif { private: incoming_edge_iterator _edge_it; public: #if defined(__GNUC__) && (__GNUC__ < 3) inline face_iterator() : input_iterator() { } #else inline face_iterator() : iterator() { } #endif virtual ~face_iterator(){}; // soc protected: friend class WVertex; inline face_iterator(incoming_edge_iterator it) #if defined(__GNUC__) && (__GNUC__ < 3) : input_iterator() #else : iterator() #endif { _edge_it = it; } public: inline face_iterator(const face_iterator &iBrother) #if defined(__GNUC__) && (__GNUC__ < 3) : input_iterator(iBrother) #else : iterator(iBrother) #endif { _edge_it = iBrother._edge_it; } public: // operators // operator corresponding to ++i virtual face_iterator &operator++() { increment(); return *this; } // operator corresponding to i++ virtual face_iterator operator++(int) { face_iterator tmp = *this; increment(); return tmp; } // comparibility virtual bool operator!=(const face_iterator &b) const { return ((_edge_it) != (b._edge_it)); } virtual bool operator==(const face_iterator &b) const { return ((_edge_it) == (b._edge_it)); } // dereferencing virtual WFace *operator*(); // virtual WOEdge **operator->(); protected: inline void increment() { ++_edge_it; } #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WVertex:face_iterator") #endif }; public: /*! iterators access */ virtual incoming_edge_iterator incoming_edges_begin(); virtual incoming_edge_iterator incoming_edges_end(); virtual face_iterator faces_begin() { return face_iterator(incoming_edges_begin()); } virtual face_iterator faces_end() { return face_iterator(incoming_edges_end()); } #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WVertex") #endif }; /********************************** * * * * * WOEdge * * * * * **********************************/ class WFace; class WEdge; class WOEdge { protected: #if 0 WOEdge *_paCWEdge; // edge reached when traveling clockwise on aFace from the edge WOEdge *_pbCWEdge; // edge reached when traveling clockwise on bFace from the edge WOEdge *_paCCWEdge; // edge reached when traveling counterclockwise on aFace from the edge WOEdge *_pbCCWEdge; // edge reached when traveling counterclockwise on bFace from the edge #endif WVertex *_paVertex; // starting vertex WVertex *_pbVertex; // ending vertex WFace *_paFace; // when following the edge, face on the right WFace *_pbFace; // when following the edge, face on the left WEdge *_pOwner; // Edge Vec3f _vec; float _angle; public: void *userdata; inline WOEdge() { #if 0 _paCWEdge = NULL; _pbCWEdge = NULL; _paCCWEdge = NULL; _pbCCWEdge = NULL; #endif _paVertex = NULL; _pbVertex = NULL; _paFace = NULL; _pbFace = NULL; _pOwner = NULL; userdata = NULL; } virtual ~WOEdge(){}; // soc /*! copy constructor */ WOEdge(WOEdge &iBrother); virtual WOEdge *duplicate(); /*! accessors */ #if 0 inline WOEdge *GetaCWEdge() { return _paCWEdge; } inline WOEdge *GetbCWEdge() { return _pbCWEdge; } inline WOEdge *GetaCCWEdge() { return _paCCWEdge; } inline WOEdge *GetbCCWEdge() { return _pbCCWEdge; } #endif inline WVertex *GetaVertex() { return _paVertex; } inline WVertex *GetbVertex() { return _pbVertex; } inline WFace *GetaFace() { return _paFace; } inline WFace *GetbFace() { return _pbFace; } inline WEdge *GetOwner() { return _pOwner; } inline const Vec3f &GetVec() { return _vec; } inline const float GetAngle() { return _angle; } /*! modifiers */ #if 0 inline void SetaCWEdge(WOEdge *pe) { _paCWEdge = pe; } inline void SetbCWEdge(WOEdge *pe) { _pbCWEdge = pe; } inline void SetaCCWEdge(WOEdge *pe) { _paCCWEdge = pe; } inline void SetbCCCWEdge(WOEdge *pe) { _pbCCWEdge = pe; } #endif inline void setVecAndAngle(); inline void setaVertex(WVertex *pv) { _paVertex = pv; setVecAndAngle(); } inline void setbVertex(WVertex *pv) { _pbVertex = pv; setVecAndAngle(); } inline void setaFace(WFace *pf) { _paFace = pf; setVecAndAngle(); } inline void setbFace(WFace *pf) { _pbFace = pf; setVecAndAngle(); } inline void setOwner(WEdge *pe) { _pOwner = pe; } /*! Retrieves the list of edges in CW order */ inline void RetrieveCWOrderedEdges(vector &oEdges); WOEdge *twin(); WOEdge *getPrevOnFace(); virtual void ResetUserData() { userdata = NULL; } #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WOEdge") #endif }; /********************************** * * * * * WEdge * * * * * **********************************/ class WEdge { protected: WOEdge *_paOEdge; // first oriented edge WOEdge *_pbOEdge; // second oriented edge short _nOEdges; // number of oriented edges associated with this edge. (1 means border edge) bool _Mark; // user-specified edge mark for feature edge detection int _Id; // Identifier for the edge public: void *userdata; // designed to store specific user data inline WEdge() { _paOEdge = NULL; _pbOEdge = NULL; _nOEdges = 0; userdata = NULL; } inline WEdge(WOEdge *iOEdge) { _paOEdge = iOEdge; _pbOEdge = NULL; _nOEdges = 1; userdata = NULL; } inline WEdge(WOEdge *iaOEdge, WOEdge *ibOEdge) { _paOEdge = iaOEdge; _pbOEdge = ibOEdge; _nOEdges = 2; userdata = NULL; } /*! Copy constructor */ WEdge(WEdge &iBrother); virtual WEdge *duplicate(); virtual ~WEdge() { if (_paOEdge) { delete _paOEdge; _paOEdge = NULL; } if (_pbOEdge) { delete _pbOEdge; _pbOEdge = NULL; } } /*! checks whether two WEdge have a common vertex. * Returns a pointer on the common vertex if it exists, NULL otherwise. */ static inline WVertex *CommonVertex(WEdge *iEdge1, WEdge *iEdge2) { if (!iEdge1 || !iEdge2) { return NULL; } WVertex *wv1 = iEdge1->GetaOEdge()->GetaVertex(); WVertex *wv2 = iEdge1->GetaOEdge()->GetbVertex(); WVertex *wv3 = iEdge2->GetaOEdge()->GetaVertex(); WVertex *wv4 = iEdge2->GetaOEdge()->GetbVertex(); if ((wv1 == wv3) || (wv1 == wv4)) { return wv1; } else if ((wv2 == wv3) || (wv2 == wv4)) { return wv2; } return NULL; } /*! accessors */ inline WOEdge *GetaOEdge() { return _paOEdge; } inline WOEdge *GetbOEdge() { return _pbOEdge; } inline short GetNumberOfOEdges() { return _nOEdges; } inline bool GetMark() { return _Mark; } inline int GetId() { return _Id; } inline WVertex *GetaVertex() { return _paOEdge->GetaVertex(); } inline WVertex *GetbVertex() { return _paOEdge->GetbVertex(); } inline WFace *GetaFace() { return _paOEdge->GetaFace(); } inline WFace *GetbFace() { return _paOEdge->GetbFace(); } inline WOEdge *GetOtherOEdge(WOEdge *iOEdge) { if (iOEdge == _paOEdge) { return _pbOEdge; } else { return _paOEdge; } } /*! modifiers */ inline void setaOEdge(WOEdge *iEdge) { _paOEdge = iEdge; } inline void setbOEdge(WOEdge *iEdge) { _pbOEdge = iEdge; } inline void AddOEdge(WOEdge *iEdge) { if (!_paOEdge) { _paOEdge = iEdge; _nOEdges++; return; } if (!_pbOEdge) { _pbOEdge = iEdge; _nOEdges++; return; } } inline void setNumberOfOEdges(short n) { _nOEdges = n; } inline void setMark(bool mark) { _Mark = mark; } inline void setId(int id) { _Id = id; } virtual void ResetUserData() { userdata = NULL; } #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WEdge") #endif }; /********************************** * * * * * WFace * * * * * **********************************/ class WFace { protected: vector _OEdgeList; // list of oriented edges of bording the face Vec3f _Normal; // normal to the face // in case there is a normal per vertex. // The normal number i corresponds to the aVertex of the oedge number i, for that face vector _VerticesNormals; vector _VerticesTexCoords; int _Id; unsigned _FrsMaterialIndex; bool _Mark; // Freestyle face mark (if true, feature edges on this face are ignored) public: void *userdata; inline WFace() { userdata = NULL; _FrsMaterialIndex = 0; } /*! copy constructor */ WFace(WFace &iBrother); virtual WFace *duplicate(); virtual ~WFace() { } /*! accessors */ inline const vector &getEdgeList() { return _OEdgeList; } inline WOEdge *GetOEdge(int i) { return _OEdgeList[i]; } inline Vec3f &GetNormal() { return _Normal; } inline int GetId() { return _Id; } inline unsigned frs_materialIndex() const { return _FrsMaterialIndex; } inline bool GetMark() const { return _Mark; } const FrsMaterial &frs_material(); /*! The vertex of index i corresponds to the a vertex of the edge of index i */ inline WVertex *GetVertex(unsigned int index) { #if 0 if (index >= _OEdgeList.size()) { return NULL; } #endif return _OEdgeList[index]->GetaVertex(); } /*! returns the index at which iVertex is stored in the array. * returns -1 if iVertex doesn't belong to the face. */ inline int GetIndex(WVertex *iVertex) { int index = 0; for (vector::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) { if ((*woe)->GetaVertex() == iVertex) { return index; } ++index; } return -1; } inline void RetrieveVertexList(vector &oVertices) { for (vector::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) { oVertices.push_back((*woe)->GetaVertex()); } } inline void RetrieveBorderFaces(vector &oWFaces) { for (vector::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) { WFace *af; if ((af = (*woe)->GetaFace())) { oWFaces.push_back(af); } } } inline WFace *GetBordingFace(int index) { #if 0 if (index >= _OEdgeList.size()) { return NULL; } #endif return _OEdgeList[index]->GetaFace(); } inline WFace *GetBordingFace(WOEdge *iOEdge) { return iOEdge->GetaFace(); } inline vector &GetPerVertexNormals() { return _VerticesNormals; } inline vector &GetPerVertexTexCoords() { return _VerticesTexCoords; } /*! Returns the normal of the vertex of index index */ inline Vec3f &GetVertexNormal(int index) { return _VerticesNormals[index]; } /*! Returns the tex coords of the vertex of index index */ inline Vec2f &GetVertexTexCoords(int index) { return _VerticesTexCoords[index]; } /*! Returns the normal of the vertex iVertex for that face */ inline Vec3f &GetVertexNormal(WVertex *iVertex) { int i = 0; int index = 0; for (vector::const_iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) { if ((*woe)->GetaVertex() == iVertex) { index = i; break; } ++i; } return _VerticesNormals[index]; } inline WOEdge *GetNextOEdge(WOEdge *iOEdge) { bool found = false; vector::iterator woe, woend, woefirst; woefirst = _OEdgeList.begin(); for (woe = woefirst, woend = _OEdgeList.end(); woe != woend; ++woe) { if (found) { return (*woe); } if ((*woe) == iOEdge) { found = true; } } // We left the loop. That means that the first OEdge was the good one: if (found) { return (*woefirst); } return NULL; } WOEdge *GetPrevOEdge(WOEdge *iOEdge); inline int numberOfEdges() const { return _OEdgeList.size(); } inline int numberOfVertices() const { return _OEdgeList.size(); } /*! Returns true if the face has one ot its edge which is a border edge */ inline bool isBorder() const { for (vector::const_iterator woe = _OEdgeList.begin(), woeend = _OEdgeList.end(); woe != woeend; ++woe) { if ((*woe)->GetOwner()->GetbOEdge() == 0) { return true; } } return false; } /*! modifiers */ inline void setEdgeList(const vector &iEdgeList) { _OEdgeList = iEdgeList; } inline void setNormal(const Vec3f &iNormal) { _Normal = iNormal; } inline void setNormalList(const vector &iNormalsList) { _VerticesNormals = iNormalsList; } inline void setTexCoordsList(const vector &iTexCoordsList) { _VerticesTexCoords = iTexCoordsList; } inline void setId(int id) { _Id = id; } inline void setFrsMaterialIndex(unsigned iMaterialIndex) { _FrsMaterialIndex = iMaterialIndex; } inline void setMark(bool iMark) { _Mark = iMark; } /*! designed to build a specialized WEdge for use in MakeEdge */ virtual WEdge *instanciateEdge() const { return new WEdge; } /*! Builds an oriented edge * Returns the built edge. * v1, v2 * Vertices at the edge's extremities * The edge is oriented from v1 to v2. */ virtual WOEdge *MakeEdge(WVertex *v1, WVertex *v2); /*! Adds an edge to the edges list */ inline void AddEdge(WOEdge *iEdge) { _OEdgeList.push_back(iEdge); } /*! For triangles, returns the edge opposite to the vertex in e. * returns false if the face is not a triangle or if the vertex is not found */ bool getOppositeEdge(const WVertex *v, WOEdge *&e); /*! compute the area of the face */ float getArea(); WShape *getShape(); virtual void ResetUserData() { userdata = NULL; } #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WFace") #endif }; /********************************** * * * * * WShape * * * * * **********************************/ class WShape { protected: vector _VertexList; vector _EdgeList; vector _FaceList; int _Id; string _Name; string _LibraryPath; static unsigned _SceneCurrentId; #if 0 Vec3f _min; Vec3f _max; #endif vector _FrsMaterials; #if 0 float _meanEdgeSize; #endif public: inline WShape() { #if 0 _meanEdgeSize = 0; #endif _Id = _SceneCurrentId; _SceneCurrentId++; } /*! copy constructor */ WShape(WShape &iBrother); virtual WShape *duplicate(); virtual ~WShape() { if (_EdgeList.size() != 0) { vector::iterator e; for (e = _EdgeList.begin(); e != _EdgeList.end(); ++e) { delete (*e); } _EdgeList.clear(); } if (_VertexList.size() != 0) { vector::iterator v; for (v = _VertexList.begin(); v != _VertexList.end(); ++v) { delete (*v); } _VertexList.clear(); } if (_FaceList.size() != 0) { vector::iterator f; for (f = _FaceList.begin(); f != _FaceList.end(); ++f) { delete (*f); } _FaceList.clear(); } } /*! accessors */ inline vector &getEdgeList() { return _EdgeList; } inline vector &getVertexList() { return _VertexList; } inline vector &GetFaceList() { return _FaceList; } inline unsigned GetId() { return _Id; } #if 0 inline void bbox(Vec3f &min, Vec3f &max) { min = _min; max = _max; } #endif inline const FrsMaterial &frs_material(unsigned i) const { return _FrsMaterials[i]; } inline const vector &frs_materials() const { return _FrsMaterials; } #if 0 inline const float getMeanEdgeSize() const { return _meanEdgeSize; } #endif inline const string &getName() const { return _Name; } inline const string &getLibraryPath() const { return _LibraryPath; } /*! modifiers */ static inline void setCurrentId(const unsigned id) { _SceneCurrentId = id; } inline void setEdgeList(const vector &iEdgeList) { _EdgeList = iEdgeList; } inline void setVertexList(const vector &iVertexList) { _VertexList = iVertexList; } inline void setFaceList(const vector &iFaceList) { _FaceList = iFaceList; } inline void setId(int id) { _Id = id; } #if 0 inline void setBBox(const Vec3f &min, const Vec3f &max) { _min = min; _max = max; } #endif inline void setFrsMaterial(const FrsMaterial &frs_material, unsigned i) { _FrsMaterials[i] = frs_material; } inline void setFrsMaterials(const vector &iMaterials) { _FrsMaterials = iMaterials; } inline void setName(const string &name) { _Name = name; } inline void setLibraryPath(const string &path) { _LibraryPath = path; } /*! designed to build a specialized WFace for use in MakeFace */ virtual WFace *instanciateFace() const { return new WFace; } /*! adds a new face to the shape * returns the built face. * iVertexList * List of face's vertices. These vertices are not added to the WShape vertex list; they are * supposed to be already stored when calling MakeFace. The order in which the vertices are * stored in the list determines the face's edges orientation and (so) the face orientation. * iMaterialIndex * The material index for this face */ virtual WFace *MakeFace(vector &iVertexList, vector &iFaceEdgeMarksList, unsigned iMaterialIndex); /*! adds a new face to the shape. The difference with the previous method is that this one is * designed to build a WingedEdge structure for which there are per vertex normals, opposed to * per face normals. returns the built face. iVertexList List of face's vertices. These vertices * are not added to the WShape vertex list; they are supposed to be already stored when calling * MakeFace. The order in which the vertices are stored in the list determines the face's edges * orientation and (so) the face orientation. iMaterialIndex The materialIndex for this face * iNormalsList * The list of normals, iNormalsList[i] corresponding to the normal of the vertex * iVertexList[i] for that face. iTexCoordsList The list of tex coords, iTexCoordsList[i] * corresponding to the normal of the vertex iVertexList[i] for that face. */ virtual WFace *MakeFace(vector &iVertexList, vector &iNormalsList, vector &iTexCoordsList, vector &iFaceEdgeMarksList, unsigned iMaterialIndex); inline void AddEdge(WEdge *iEdge) { _EdgeList.push_back(iEdge); } inline void AddFace(WFace *iFace) { _FaceList.push_back(iFace); } inline void AddVertex(WVertex *iVertex) { iVertex->setShape(this); _VertexList.push_back(iVertex); } inline void ResetUserData() { for (vector::iterator v = _VertexList.begin(), vend = _VertexList.end(); v != vend; v++) { (*v)->ResetUserData(); } for (vector::iterator e = _EdgeList.begin(), eend = _EdgeList.end(); e != eend; e++) { (*e)->ResetUserData(); // manages WOEdge: WOEdge *oe = (*e)->GetaOEdge(); if (oe) { oe->ResetUserData(); } oe = (*e)->GetbOEdge(); if (oe) { oe->ResetUserData(); } } for (vector::iterator f = _FaceList.begin(), fend = _FaceList.end(); f != fend; f++) { (*f)->ResetUserData(); } } #if 0 inline void ComputeBBox() { _min = _VertexList[0]->GetVertex(); _max = _VertexList[0]->GetVertex(); Vec3f v; for (vector::iterator wv = _VertexList.begin(), wvend = _VertexList.end(); wv != wvend; wv++) { for (unsigned int i = 0; i < 3; i++) { v = (*wv)->GetVertex(); if (v[i] < _min[i]) { _min[i] = v[i]; } if (v[i] > _max[i]) { _max[i] = v[i]; } } } } #endif #if 0 inline float ComputeMeanEdgeSize() { _meanEdgeSize = _meanEdgeSize / _EdgeList.size(); return _meanEdgeSize; } #else real ComputeMeanEdgeSize() const; #endif protected: /*! * Builds the face passed as argument (which as already been allocated) * - iVertexList * List of face's vertices. These vertices are not added to the WShape vertex list; * they are supposed to be already stored when calling MakeFace. * The order in which the vertices are stored in the list determines * the face's edges orientation and (so) the face orientation. * - iMaterialIndex * The material index for this face * - face * The Face that is filled in */ virtual WFace *MakeFace(vector &iVertexList, vector &iFaceEdgeMarksList, unsigned iMaterialIndex, WFace *face); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WShape") #endif }; /********************************** * * * * * WingedEdge * * * * * **********************************/ class WingedEdge { public: WingedEdge() { _numFaces = 0; } ~WingedEdge() { clear(); } void clear() { for (vector::iterator it = _wshapes.begin(); it != _wshapes.end(); it++) { delete *it; } _wshapes.clear(); _numFaces = 0; } void addWShape(WShape *wshape) { _wshapes.push_back(wshape); _numFaces += wshape->GetFaceList().size(); } vector &getWShapes() { return _wshapes; } unsigned getNumFaces() { return _numFaces; } private: vector _wshapes; unsigned _numFaces; #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WingedEdge") #endif }; /* * ############################################# * ############################################# * ############################################# * ###### ###### * ###### I M P L E M E N T A T I O N ###### * ###### ###### * ############################################# * ############################################# * ############################################# */ /* for inline functions */ void WOEdge::RetrieveCWOrderedEdges(vector &oEdges) { WOEdge *currentOEdge = this; do { WOEdge *nextOEdge = currentOEdge->GetbFace()->GetNextOEdge(currentOEdge); oEdges.push_back(nextOEdge->GetOwner()); currentOEdge = nextOEdge->GetOwner()->GetOtherOEdge(nextOEdge); } while (currentOEdge && (currentOEdge->GetOwner() != GetOwner())); } inline void WOEdge::setVecAndAngle() { if (_paVertex && _pbVertex) { _vec = _pbVertex->GetVertex() - _paVertex->GetVertex(); if (_paFace && _pbFace) { float sine = (_pbFace->GetNormal() ^ _paFace->GetNormal()) * _vec / _vec.norm(); if (sine >= 1.0) { _angle = M_PI / 2.0; return; } if (sine <= -1.0) { _angle = -M_PI / 2.0; return; } _angle = ::asin(sine); } } } } /* namespace Freestyle */ #endif // __FREESTYLE_W_EDGE_H__