/* * ***** BEGIN GPL LICENSE BLOCK ***** * * 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. * * ***** END GPL LICENSE BLOCK ***** */ #ifndef __FREESTYLE_VIEW_MAP_H__ #define __FREESTYLE_VIEW_MAP_H__ /** \file blender/freestyle/intern/view_map/ViewMap.h * \ingroup freestyle * \brief Classes to define a View Map (ViewVertex, ViewEdge, etc.) * \author Stephane Grabli * \date 03/09/2002 */ #include #include "Interface0D.h" #include "Interface1D.h" #include "Silhouette.h" // defines the embedding #include "../geometry/GeomUtils.h" #include "../system/BaseIterator.h" #include "../system/FreestyleConfig.h" #ifdef WITH_CXX_GUARDEDALLOC #include "MEM_guardedalloc.h" #endif namespace Freestyle { /**********************************/ /* */ /* */ /* ViewMap */ /* */ /* */ /**********************************/ /* Density * Mean area depth value * distance to a point */ class ViewVertex; class ViewEdge; class ViewShape; class TVertex; /*! Class defining the ViewMap.*/ class ViewMap { public: typedef vector viewedges_container; typedef vector viewvertices_container; typedef vector viewshapes_container; typedef vector svertices_container; typedef vector fedges_container; typedef map id_to_index_map; private: static ViewMap *_pInstance; viewshapes_container _VShapes; // view shapes viewedges_container _VEdges; // view edges viewvertices_container _VVertices; // view vertices fedges_container _FEdges; // feature edges (embedded edges) svertices_container _SVertices; // embedded vertices BBox _scene3DBBox; // Mapping between the WShape or VShape id to the VShape index in the _VShapes vector. Used in the method // viewShape(int id) to access a shape from its id. id_to_index_map _shapeIdToIndex; public: /*! A field that can be used by the user to store any data. * This field must be reseted afterwards using ResetUserData(). */ void *userdata; /*! Default constructor. */ ViewMap() { _pInstance = this; userdata = NULL; } /*! Destructor. */ virtual ~ViewMap(); /*! Gets the viewedge the nearest to the 2D position specified as argument */ const ViewEdge *getClosestViewEdge(real x, real y) const; /*! Gets the Fedge the nearest to the 2D position specified as argument */ const FEdge *getClosestFEdge(real x, real y) const; /* accessors */ /*! The ViewMap is a singleton class. This static method returns the instance of the ViewMap. */ static inline ViewMap *getInstance() { return _pInstance; } /* Returns the list of ViewShapes of the scene. */ inline viewshapes_container& ViewShapes() { return _VShapes; } /* Returns the list of ViewEdges of the scene. */ inline viewedges_container& ViewEdges() { return _VEdges; } /* Returns the list of ViewVertices of the scene. */ inline viewvertices_container& ViewVertices() { return _VVertices; } /* Returns the list of FEdges of the scene. */ inline fedges_container& FEdges() { return _FEdges; } /* Returns the list of SVertices of the scene. */ inline svertices_container& SVertices() { return _SVertices; } /* Returns an iterator pointing onto the first ViewEdge of the list. */ inline viewedges_container::iterator viewedges_begin() { return _VEdges.begin(); } inline viewedges_container::iterator viewedges_end() { return _VEdges.end(); } inline int viewedges_size() { return _VEdges.size(); } ViewShape *viewShape(unsigned index); id_to_index_map& shapeIdToIndexMap() { return _shapeIdToIndex; } /*! Returns the scene 3D bounding box. */ inline BBox getScene3dBBox() const { return _scene3DBBox; } /* modifiers */ void AddViewShape(ViewShape *iVShape); inline void AddViewEdge(ViewEdge *iVEdge) { _VEdges.push_back(iVEdge); } inline void AddViewVertex(ViewVertex *iVVertex) { _VVertices.push_back(iVVertex); } inline void AddFEdge(FEdge *iFEdge) { _FEdges.push_back(iFEdge); } inline void AddSVertex(SVertex *iSVertex) { _SVertices.push_back(iSVertex); } /*! Sets the scene 3D bounding box. */ inline void setScene3dBBox(const BBox& bbox) { _scene3DBBox = bbox; } /* Creates a T vertex in the view map. * A T vertex is the intersection between 2 FEdges (before these ones are splitted). * The TVertex is a 2D intersection but it corresponds to a 3D point on each of the 2 FEdges. * iA3D * The 3D coordinates of the point corresponding to the intersection on the first edge. * iA2D * The x,y,z 2D coordinates of the projection of iA3D * iFEdgeA * The first FEdge * iB3D * The 3D coordinates of the point corresponding to the intersection on the second edge. * iB2D * The x,y,z 2D coordinates of the projection of iB3D * iFEdgeB * The second FEdge * id * The id that must be given to that TVertex */ TVertex *CreateTVertex(const Vec3r& iA3D, const Vec3r& iA2D, FEdge *iFEdgeA, const Vec3r& iB3D, const Vec3r& iB2D, FEdge *iFEdgeB, const Id& id); /* Updates the structures to take into account the fact that a SVertex must now be considered as a ViewVertex * iVertex * The SVertex on top of which the ViewVertex is built (it is necessarily a NonTVertex because it is a SVertex) * newViewEdges * The new ViewEdges that must be add to the ViewMap */ ViewVertex *InsertViewVertex(SVertex *iVertex, vector& newViewEdges); /* connects a FEdge to the graph trough a SVertex */ //FEdge *Connect(FEdge *ioEdge, SVertex *ioVertex); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMap") #endif }; /**********************************/ /* */ /* */ /* ViewVertex */ /* */ /* */ /**********************************/ class ViewEdge; class SShape; namespace ViewVertexInternal { class edge_const_traits; class edge_nonconst_traits; template class edge_iterator_base; class orientedViewEdgeIterator; } // end of namespace ViewEdgeInternal /*! Class to define a view vertex. * A view vertex is a feature vertex corresponding to a point of the image graph, where the characteristics of an * edge might change (nature, visibility, ...). * A ViewVertex can be of two kinds: a TVertex when it corresponds to the intersection between two ViewEdges or a * NonTVertex when it corresponds to a vertex of the initial input mesh (it is the case for vertices such as corners * for example). Thus, this class can be specialized into two classes, the TVertex class and the NonTVertex class. */ class ViewVertex : public Interface0D { public: // Implementation of Interface0D /*! Returns the string "ViewVertex". */ virtual string getExactTypeName() const { return "ViewVertex"; } public: friend class ViewShape; typedef pair directedViewEdge; // if bool = true, the ViewEdge is incoming typedef vector edges_container; typedef ViewVertexInternal::edge_iterator_base edge_iterator; typedef ViewVertexInternal::edge_iterator_base const_edge_iterator; private: Nature::VertexNature _Nature; public: /*! A field that can be used by the user to store any data. * This field must be reseted afterwards using ResetUserData(). */ void *userdata; /*! Default constructor.*/ inline ViewVertex() { userdata = NULL; _Nature = Nature::VIEW_VERTEX; } inline ViewVertex(Nature::VertexNature nature) { userdata = NULL; _Nature = Nature::VIEW_VERTEX | nature; } protected: /*! Copy constructor. */ inline ViewVertex(ViewVertex& iBrother) { _Nature = iBrother._Nature; iBrother.userdata = this; userdata = NULL; } /*! Cloning method. */ virtual ViewVertex *duplicate() = 0; public: /*! Destructor. */ virtual ~ViewVertex() {} /* accessors */ /*! Returns the nature of the vertex .*/ virtual Nature::VertexNature getNature() const { return _Nature; } /* modifiers */ /*! Sets the nature of the vertex. */ inline void setNature(Nature::VertexNature iNature) { _Nature = iNature; } /* Replaces old edge by new edge */ virtual void Replace(ViewEdge *, ViewEdge *) {} public: /* iterators access */ // allows iteration on the edges that comes from/goes to this vertex in CCW order (order defined in 2D in the // image plan) virtual edge_iterator edges_begin() = 0; virtual const_edge_iterator edges_begin() const = 0; virtual edge_iterator edges_end() = 0; virtual const_edge_iterator edges_end() const = 0; virtual edge_iterator edges_iterator(ViewEdge *iEdge) = 0; virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const = 0; // Iterator access /*! Returns an iterator over the ViewEdges that goes to or comes from this ViewVertex pointing to the first * ViewEdge of the list. The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges * and to get the orientation for each ViewEdge (incoming/outgoing). */ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() = 0; /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, pointing after the last ViewEdge. */ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() = 0; /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge given as argument. */ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) = 0; #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewVertex") #endif }; /**********************************/ /* */ /* */ /* TVertex */ /* */ /* */ /**********************************/ /*! class to define a T vertex, i.e. an intersection between two edges. * It points towards 2 SVertex and 4 View edges. * Among these ViewEdges, 2 are front and 2 are back. * Basically the front edge hides part of the back edge. * So, among the back edges, 1 is of invisibility n and the other of visibility n+1 */ class TVertex : public ViewVertex { public: typedef vector edge_pointers_container; public: // Implementation of Interface0D /*! Returns the string "TVertex". */ virtual string getExactTypeName() const { return "TVertex"; } // Data access methods /* Returns the 3D x coordinate of the vertex. Ambiguous in this case. */ virtual real getX() const { cerr << "Warning: getX() undefined for this point" << endl; return _FrontSVertex->point3D().x(); } virtual real getY() const { cerr << "Warning: getX() undefined for this point" << endl; return _FrontSVertex->point3D().y(); } virtual real getZ() const { cerr << "Warning: getX() undefined for this point" << endl; return _FrontSVertex->point3D().z(); } /*! Returns the 3D point. */ virtual Vec3r getPoint3D() const { cerr << "Warning: getPoint3D() undefined for this point" << endl; return _FrontSVertex->getPoint3D(); } /*! Returns the projected 3D x coordinate of the vertex. */ virtual real getProjectedX() const { return _FrontSVertex->point2D().x(); } /*! Returns the projected 3D y coordinate of the vertex. */ virtual real getProjectedY() const { return _FrontSVertex->point2D().y(); } virtual real getProjectedZ() const { return _FrontSVertex->point2D().z(); } /*! Returns the 2D point. */ virtual Vec2r getPoint2D() const { return _FrontSVertex->getPoint2D(); } /*! Returns the Id of the TVertex. */ virtual Id getId() const { return _Id; } /*! Cast the Interface0D in SVertex if it can be. */ // it can't virtual ViewVertex *castToViewVertex() { return this; } /*! Cast the Interface0D in TVertex if it can be. */ virtual TVertex *castToTVertex() { return this; } private: SVertex *_FrontSVertex; SVertex *_BackSVertex; directedViewEdge _FrontEdgeA; directedViewEdge _FrontEdgeB; directedViewEdge _BackEdgeA; directedViewEdge _BackEdgeB; Id _Id; // id to identify t vertices . these id will be negative in order not to be mixed with NonTVertex ids. edge_pointers_container _sortedEdges; // the list of the four ViewEdges, ordered in CCW order (in the image plan) public: /*! Default constructor.*/ inline TVertex() : ViewVertex(Nature::T_VERTEX) { _FrontSVertex = NULL; _BackSVertex = NULL; _FrontEdgeA.first = 0; _FrontEdgeB.first = 0; _BackEdgeA.first = 0; _BackEdgeB.first = 0; } inline TVertex(SVertex *svFront, SVertex *svBack) : ViewVertex(Nature::T_VERTEX) { _FrontSVertex = svFront; _BackSVertex = svBack; _FrontEdgeA.first = 0; _FrontEdgeB.first = 0; _BackEdgeA.first = 0; _BackEdgeB.first = 0; svFront->setViewVertex(this); svBack->setViewVertex(this); } protected: /*! Copy constructor. */ inline TVertex(TVertex& iBrother) : ViewVertex(iBrother) { _FrontSVertex = iBrother._FrontSVertex; _BackSVertex = iBrother._BackSVertex; _FrontEdgeA = iBrother._FrontEdgeA; _FrontEdgeB = iBrother._FrontEdgeB; _BackEdgeA = iBrother._BackEdgeA; _BackEdgeB = iBrother._BackEdgeB; _sortedEdges = iBrother._sortedEdges; } /*! Cloning method. */ virtual ViewVertex *duplicate() { TVertex *clone = new TVertex(*this); return clone; } public: /* accessors */ /*! Returns the SVertex that is closer to the viewpoint. */ inline SVertex *frontSVertex() { return _FrontSVertex; } /*! Returns the SVertex that is further away from the viewpoint. */ inline SVertex *backSVertex() { return _BackSVertex; } inline directedViewEdge& frontEdgeA() { return _FrontEdgeA; } inline directedViewEdge& frontEdgeB() { return _FrontEdgeB; } inline directedViewEdge& backEdgeA() { return _BackEdgeA; } inline directedViewEdge& backEdgeB() { return _BackEdgeB; } /* modifiers */ /*! Sets the SVertex that is closer to the viewpoint. */ inline void setFrontSVertex(SVertex *iFrontSVertex) { _FrontSVertex = iFrontSVertex; _FrontSVertex->setViewVertex(this); } /*! Sets the SVertex that is further away from the viewpoint. */ inline void setBackSVertex(SVertex *iBackSVertex) { _BackSVertex = iBackSVertex; _BackSVertex->setViewVertex(this); } void setFrontEdgeA(ViewEdge *iFrontEdgeA, bool incoming = true); void setFrontEdgeB(ViewEdge *iFrontEdgeB, bool incoming = true); void setBackEdgeA(ViewEdge *iBackEdgeA, bool incoming = true); void setBackEdgeB(ViewEdge *iBackEdgeB, bool incoming = true); /*! Sets the Id. */ inline void setId(const Id& iId) { _Id = iId; } /*! Returns the SVertex (among the 2) belonging to the FEdge iFEdge */ inline SVertex *getSVertex(FEdge *iFEdge) { const vector& vfEdges = _FrontSVertex->fedges(); vector::const_iterator fe, fend; for (fe = vfEdges.begin(), fend = vfEdges.end(); fe != fend; fe++) { if ((*fe) == iFEdge) return _FrontSVertex; } const vector& vbEdges = _BackSVertex->fedges(); for (fe = vbEdges.begin(), fend = vbEdges.end(); fe != fend; fe++) { if ((*fe) == iFEdge) return _BackSVertex; } return NULL; } virtual void Replace(ViewEdge *iOld, ViewEdge *iNew); /*! returns the mate edge of iEdgeA. * For example, if iEdgeA is frontEdgeA, then frontEdgeB is returned. If iEdgeA is frontEdgeB then frontEdgeA * is returned. Same for back edges */ virtual ViewEdge *mate(ViewEdge *iEdgeA) { if (iEdgeA == _FrontEdgeA.first) return _FrontEdgeB.first; if (iEdgeA == _FrontEdgeB.first) return _FrontEdgeA.first; if (iEdgeA == _BackEdgeA.first) return _BackEdgeB.first; if (iEdgeA == _BackEdgeB.first) return _BackEdgeA.first; return NULL; } /* iterators access */ virtual edge_iterator edges_begin(); virtual const_edge_iterator edges_begin() const; virtual edge_iterator edges_end(); virtual const_edge_iterator edges_end() const; virtual edge_iterator edges_iterator(ViewEdge *iEdge); virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const; /*! Returns an iterator over the ViewEdges that goes to or comes from this ViewVertex pointing to the first * ViewEdge of the list. The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges * and to get the orientation for each ViewEdge (incoming/outgoing). */ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin(); /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, pointing after the last ViewEdge. */ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd(); /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge given as argument. */ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:TVertex") #endif }; /**********************************/ /* */ /* */ /* NonTVertex */ /* */ /* */ /**********************************/ // (non T vertex) /*! View vertex for corners, cusps, etc... * Associated to a single SVertex. * Can be associated to 2 or several view edges */ class NonTVertex : public ViewVertex { public: typedef vector edges_container; public: // Implementation of Interface0D /*! Returns the string "ViewVertex". */ virtual string getExactTypeName() const { return "NonTVertex"; } // Data access methods /*! Returns the 3D x coordinate of the vertex. */ virtual real getX() const { return _SVertex->point3D().x(); } /*! Returns the 3D y coordinate of the vertex. */ virtual real getY() const { return _SVertex->point3D().y(); } /*! Returns the 3D z coordinate of the vertex. */ virtual real getZ() const { return _SVertex->point3D().z(); } /*! Returns the 3D point. */ virtual Vec3r getPoint3D() const { return _SVertex->getPoint3D(); } /*! Returns the projected 3D x coordinate of the vertex. */ virtual real getProjectedX() const { return _SVertex->point2D().x(); } /*! Returns the projected 3D y coordinate of the vertex. */ virtual real getProjectedY() const { return _SVertex->point2D().y(); } /*! Returns the projected 3D z coordinate of the vertex. */ virtual real getProjectedZ() const { return _SVertex->point2D().z(); } /*! Returns the 2D point. */ virtual Vec2r getPoint2D() const { return _SVertex->getPoint2D(); } /*! Returns the Id of the vertex. */ virtual Id getId() const { return _SVertex->getId(); } /*! Cast the Interface0D in SVertex if it can be. */ virtual SVertex *castToSVertex() { return _SVertex; } /*! Cast the Interface0D in ViewVertex if it can be. */ virtual ViewVertex *castToViewVertex() { return this; } /*! Cast the Interface0D in NonTVertex if it can be. */ virtual NonTVertex *castToNonTVertex() { return this; } private: SVertex *_SVertex; edges_container _ViewEdges; public: /*! Default constructor.*/ inline NonTVertex() : ViewVertex(Nature::NON_T_VERTEX) { _SVertex = NULL; } /*! Builds a NonTVertex from a SVertex. */ inline NonTVertex(SVertex *iSVertex) : ViewVertex(Nature::NON_T_VERTEX) { _SVertex = iSVertex; _SVertex->setViewVertex(this); } protected: /*! Copy constructor. */ inline NonTVertex(NonTVertex& iBrother) : ViewVertex(iBrother) { _SVertex = iBrother._SVertex; _SVertex->setViewVertex(this); _ViewEdges = iBrother._ViewEdges; } /*! Cloning method. */ virtual ViewVertex *duplicate() { NonTVertex *clone = new NonTVertex(*this); return clone; } public: /*! destructor. */ virtual ~NonTVertex() {} /* accessors */ /*! Returns the SVertex on top of which this NonTVertex is built. */ inline SVertex *svertex() { return _SVertex; } inline edges_container& viewedges() { return _ViewEdges; } /* modifiers */ /*! Sets the SVertex on top of which this NonTVertex is built. */ inline void setSVertex(SVertex *iSVertex) { _SVertex = iSVertex; _SVertex->setViewVertex(this); } inline void setViewEdges(const vector& iViewEdges) { _ViewEdges = iViewEdges; } void AddIncomingViewEdge(ViewEdge *iVEdge); void AddOutgoingViewEdge(ViewEdge *iVEdge); inline void AddViewEdge(ViewEdge *iVEdge, bool incoming = true) { if (incoming) AddIncomingViewEdge(iVEdge); else AddOutgoingViewEdge(iVEdge); } /* Replaces old edge by new edge */ virtual void Replace(ViewEdge *iOld, ViewEdge *iNew) { edges_container::iterator insertedve; for (edges_container::iterator ve = _ViewEdges.begin(), vend = _ViewEdges.end(); ve != vend; ve++) { if ((ve)->first == iOld) { insertedve = _ViewEdges.insert(ve, directedViewEdge(iNew, ve->second));// inserts e2 before ve. // returns an iterator pointing toward e2. ve is invalidated. // we want to remove e1, but we can't use ve anymore: insertedve++; // insertedve points now to e1 _ViewEdges.erase(insertedve); return; } } } /* iterators access */ virtual edge_iterator edges_begin(); virtual const_edge_iterator edges_begin() const; virtual edge_iterator edges_end(); virtual const_edge_iterator edges_end() const; virtual edge_iterator edges_iterator(ViewEdge *iEdge); virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const; /*! Returns an iterator over the ViewEdges that goes to or comes from this ViewVertex pointing to the first * ViewEdge of the list. The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges * and to get the orientation for each ViewEdge (incoming/outgoing). */ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin(); /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, pointing after the last ViewEdge. */ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd(); /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge given as argument. */ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:NonTVertex") #endif }; /**********************************/ /* */ /* */ /* ViewEdge */ /* */ /* */ /**********************************/ /* Geometry(normals...) * Nature of edges * 2D spaces (1or2, material, z...) * Parent Shape * 3D Shading, material * Importance * Occluders */ class ViewShape; namespace ViewEdgeInternal { template class edge_iterator_base; template class fedge_iterator_base; template class vertex_iterator_base; } // end of namespace ViewEdgeInternal /*! Class defining a ViewEdge. A ViewEdge in an edge of the image graph. it connects two ViewVertex. * It is made by connecting a set of FEdges. */ class ViewEdge : public Interface1D { public: // Implementation of Interface0D /*! Returns the string "ViewEdge". */ virtual string getExactTypeName() const { return "ViewEdge"; } // Data access methods /*! Returns the Id of the vertex. */ virtual Id getId() const { return _Id; } /*! Returns the nature of the ViewEdge. */ virtual Nature::EdgeNature getNature() const { return _Nature; } public: typedef SVertex vertex_type; friend class ViewShape; // for ViewEdge iterator typedef ViewEdgeInternal::edge_iterator_base > edge_iterator; typedef ViewEdgeInternal::edge_iterator_base > const_edge_iterator; // for fedge iterator typedef ViewEdgeInternal::fedge_iterator_base > fedge_iterator; typedef ViewEdgeInternal::fedge_iterator_base > const_fedge_iterator; // for svertex iterator typedef ViewEdgeInternal::vertex_iterator_base > vertex_iterator; typedef ViewEdgeInternal::vertex_iterator_base > const_vertex_iterator; private: ViewVertex *__A; // edge starting vertex ViewVertex *__B; // edge ending vertex Nature::EdgeNature _Nature; // nature of view edge ViewShape *_Shape; // shape to which the view edge belongs FEdge *_FEdgeA; // first edge of the embedded fedges chain FEdge *_FEdgeB; // last edge of the embedded fedges chain Id _Id; unsigned _ChainingTimeStamp; // The silhouette view edge separates 2 2D spaces. The one on the left is necessarly the Shape _Shape (the one to // which this edge belongs to) and _aShape is the one on its right // NOT HANDLED BY THE COPY CONSTRUCTOR ViewShape *_aShape; int _qi; vector _Occluders; bool _isInImage; // tmp Id *_splittingId; public: /*! A field that can be used by the user to store any data. * This field must be reseted afterwards using ResetUserData(). */ void *userdata; /*! Default constructor. */ inline ViewEdge() { __A = NULL; __B = NULL; _FEdgeA = NULL; _FEdgeB = NULL; _ChainingTimeStamp = 0; _qi = 0; _aShape = NULL; userdata = NULL; _splittingId = NULL; _isInImage = true; } inline ViewEdge(ViewVertex *iA, ViewVertex *iB) { __A = iA; __B = iB; _FEdgeA = NULL; _FEdgeB = NULL; _Shape = 0; _ChainingTimeStamp = 0; _qi = 0; _aShape = NULL; userdata = NULL; _splittingId = NULL; _isInImage = true; } inline ViewEdge(ViewVertex *iA, ViewVertex *iB, FEdge *iFEdgeA) { __A = iA; __B = iB; _FEdgeA = iFEdgeA; _FEdgeB = NULL; _Shape = NULL; _ChainingTimeStamp = 0; _qi = 0; _aShape = NULL; userdata = NULL; _splittingId = NULL; _isInImage = true; } inline ViewEdge(ViewVertex *iA, ViewVertex *iB, FEdge *iFEdgeA, FEdge *iFEdgeB, ViewShape *iShape) { __A = iA; __B = iB; _FEdgeA = iFEdgeA; _FEdgeB = iFEdgeB; _Shape = iShape; _ChainingTimeStamp = 0; _qi = 0; _aShape = NULL; userdata = NULL; _splittingId = NULL; _isInImage = true; UpdateFEdges(); // tells every FEdge between iFEdgeA and iFEdgeB that this is theit ViewEdge } //soc protected: /*! Copy constructor. */ inline ViewEdge(ViewEdge& iBrother) { __A = iBrother.__A; __B = iBrother.__B; _FEdgeA = iBrother._FEdgeA; _FEdgeB = iBrother._FEdgeB; _Nature = iBrother._Nature; _Shape = NULL; _Id = iBrother._Id; _ChainingTimeStamp = iBrother._ChainingTimeStamp; _aShape = iBrother._aShape; _qi = iBrother._qi; _splittingId = NULL; _isInImage = iBrother._isInImage; iBrother.userdata = this; userdata = NULL; } /*! Cloning method. */ virtual ViewEdge *duplicate() { ViewEdge *clone = new ViewEdge(*this); return clone; } public: /*! Destructor. */ virtual ~ViewEdge() { #if 0 if (_aFace) { delete _aFace; _aFace = NULL; } #endif // only the last splitted deletes this id if (_splittingId) { if (*_splittingId == _Id) delete _splittingId; } } /* accessors */ /*! Returns the first ViewVertex. */ inline ViewVertex *A() { return __A; } /*! Returns the second ViewVertex. */ inline ViewVertex *B() { return __B; } /*! Returns the first FEdge that constitues this ViewEdge. */ inline FEdge *fedgeA() { return _FEdgeA; } /*! Returns the last FEdge that constitues this ViewEdge. */ inline FEdge *fedgeB() { return _FEdgeB; } /*! Returns the ViewShape to which this ViewEdge belongs to .*/ inline ViewShape *viewShape() { return _Shape; } /*! Returns the shape that is occluded by the ViewShape to which this ViewEdge belongs to. If no object is occluded, * NULL is returned. * \return The occluded ViewShape. */ inline ViewShape *aShape() { return _aShape; } /*! Tells whether this ViewEdge forms a closed loop or not. */ inline bool isClosed() { if (!__B) return true; return false; } /*! Returns the time stamp of this ViewEdge. */ inline unsigned getChainingTimeStamp() { return _ChainingTimeStamp; } inline const ViewShape *aShape() const { return _aShape; } inline const ViewShape *bShape() const { return _Shape; } inline vector& occluders() { return _Occluders; } inline Id *splittingId() { return _splittingId; } inline bool isInImage() const { return _isInImage; } /* modifiers */ /*! Sets the first ViewVertex of the ViewEdge. */ inline void setA(ViewVertex *iA) { __A = iA; } /*! Sets the last ViewVertex of the ViewEdge. */ inline void setB(ViewVertex *iB) { __B = iB; } /*! Sets the nature of the ViewEdge. */ inline void setNature(Nature::EdgeNature iNature) { _Nature = iNature; } /*! Sets the first FEdge of the ViewEdge. */ inline void setFEdgeA(FEdge *iFEdge) { _FEdgeA = iFEdge; } /*! Sets the last FEdge of the ViewEdge. */ inline void setFEdgeB(FEdge *iFEdge) { _FEdgeB = iFEdge; } /*! Sets the ViewShape to which this ViewEdge belongs to.*/ inline void setShape(ViewShape *iVShape) { _Shape = iVShape; } /*! Sets the ViewEdge id. */ inline void setId(const Id& id) { _Id = id; } /*! Sets Viewedge to this for all embedded fedges */ void UpdateFEdges(); /*! Sets the occluded ViewShape */ inline void setaShape(ViewShape *iShape) { _aShape = iShape; } /*! Sets the quantitative invisibility value. */ inline void setQI(int qi) { _qi = qi; } /*! Sets the time stamp value. */ inline void setChainingTimeStamp(unsigned ts) { _ChainingTimeStamp = ts; } inline void AddOccluder(ViewShape *iShape) { _Occluders.push_back(iShape); } inline void setSplittingId(Id *id) { _splittingId = id; } inline void setIsInImage(bool iFlag) { _isInImage = iFlag; } /* stroke interface definition */ inline bool intersect_2d_area(const Vec2r& iMin, const Vec2r& iMax) const { // parse edges to check if one of them is intersection the region: FEdge *current = _FEdgeA; do { if (GeomUtils::intersect2dSeg2dArea(iMin, iMax, Vec2r(current->vertexA()->point2D()[0], current->vertexA()->point2D()[1]), Vec2r(current->vertexB()->point2D()[0], current->vertexB()->point2D()[1]))) { return true; } current = current->nextEdge(); } while ((current != 0) && (current != _FEdgeA)); return false; } inline bool include_in_2d_area(const Vec2r& iMin, const Vec2r& iMax) const { // parse edges to check if all of them are intersection the region: FEdge *current = _FEdgeA; do { if (!GeomUtils::include2dSeg2dArea(iMin, iMax, Vec2r(current->vertexA()->point2D()[0], current->vertexA()->point2D()[1]), Vec2r(current->vertexB()->point2D()[0], current->vertexB()->point2D()[1]))) { return false; } current = current->nextEdge(); } while ((current != 0) && (current != _FEdgeA)); return true; } /* Information access interface */ #if 0 inline Nature::EdgeNature viewedge_nature() const { return getNature(); } float viewedge_length() const; #endif /*! Returns the 2D length of the Viewedge. */ real getLength2D() const; #if 0 inline Material material() const { return _FEdgeA->vertexA()->shape()->material(); } #endif inline int qi() const { return _qi; } inline occluder_container::const_iterator occluders_begin() const { return _Occluders.begin(); } inline occluder_container::const_iterator occluders_end() const { return _Occluders.end(); } inline int occluders_size() const { return _Occluders.size(); } inline bool occluders_empty() const { return _Occluders.empty(); } inline const Polygon3r& occludee() const { return (_FEdgeA->aFace()); } inline const SShape *occluded_shape() const; inline const bool occludee_empty() const { if (_aShape == 0) return true; return false; } //inline real z_discontinuity(int iCombination = 0) const; inline Id shape_id() const { return _FEdgeA->vertexA()->shape()->getId(); } inline const SShape *shape() const { return _FEdgeA->vertexA()->shape(); } inline float shape_importance() const { return _FEdgeA->shape_importance(); } /* iterators access */ // view edge iterator edge_iterator ViewEdge_iterator(); const_edge_iterator ViewEdge_iterator() const; // feature edge iterator fedge_iterator fedge_iterator_begin(); const_fedge_iterator fedge_iterator_begin() const; fedge_iterator fedge_iterator_last(); const_fedge_iterator fedge_iterator_last() const; fedge_iterator fedge_iterator_end(); const_fedge_iterator fedge_iterator_end() const; // embedding vertex iterator const_vertex_iterator vertices_begin() const; vertex_iterator vertices_begin(); const_vertex_iterator vertices_last() const; vertex_iterator vertices_last(); const_vertex_iterator vertices_end() const; vertex_iterator vertices_end(); // Iterator access (Interface1D) /*! Returns an Interface0DIterator to iterate over the SVertex constituting the embedding of this ViewEdge. * The returned Interface0DIterator points to the first SVertex of the ViewEdge. */ virtual Interface0DIterator verticesBegin(); /*! Returns an Interface0DIterator to iterate over the SVertex constituting the embedding of this ViewEdge. * The returned Interface0DIterator points after the last SVertex of the ViewEdge. */ virtual Interface0DIterator verticesEnd(); /*! Returns an Interface0DIterator to iterate over the points of this ViewEdge at a given resolution. * The returned Interface0DIterator points on the first Point of the ViewEdge. * \param t * the sampling value. */ virtual Interface0DIterator pointsBegin(float t = 0.0f); /*! Returns an Interface0DIterator to iterate over the points of this ViewEdge at a given resolution. * The returned Interface0DIterator points after the last Point of the ViewEdge. * \param t * the sampling value. */ virtual Interface0DIterator pointsEnd(float t = 0.0f); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewEdge") #endif }; /**********************************/ /* */ /* */ /* ViewShape */ /* */ /* */ /**********************************/ /*! Class gathering the elements of the ViewMap (ViewVertex, ViewEdge) that are issued from the same input shape. */ class ViewShape { private: vector _Vertices; vector _Edges; SShape *_SShape; public: /*! A field that can be used by the user to store any data. * This field must be reseted afterwards using ResetUserData(). */ void *userdata; /*! Default constructor.*/ inline ViewShape() { userdata = NULL; _SShape = NULL; } /*! Builds a ViewShape from a SShape. */ inline ViewShape(SShape *iSShape) { userdata = NULL; _SShape = iSShape; //_SShape->setViewShape(this); } /*! Copy constructor. */ inline ViewShape(ViewShape& iBrother) { userdata = NULL; vector::iterator vv, vvend; vector::iterator ve, veend; _SShape = iBrother._SShape; vector& vvertices = iBrother.vertices(); // duplicate vertices for (vv = vvertices.begin(), vvend = vvertices.end(); vv != vvend; vv++) { ViewVertex *newVertex = (*vv)->duplicate(); AddVertex(newVertex); } vector& vvedges = iBrother.edges(); // duplicate edges for (ve = vvedges.begin(), veend = vvedges.end(); ve != veend; ve++) { ViewEdge *newEdge = (*ve)->duplicate(); AddEdge(newEdge); // here the shape is set as the edge's shape } //------------------------- // remap edges in vertices: //------------------------- for (vv = _Vertices.begin(), vvend = _Vertices.end(); vv != vvend; vv++) { switch ((*vv)->getNature()) { case Nature::T_VERTEX: { TVertex *v = (TVertex *)(*vv); ViewEdge *veFrontA = (ViewEdge *)(v)->frontEdgeA().first->userdata; ViewEdge *veFrontB = (ViewEdge *)(v)->frontEdgeB().first->userdata; ViewEdge *veBackA = (ViewEdge *)(v)->backEdgeA().first->userdata; ViewEdge *veBackB = (ViewEdge *)(v)->backEdgeB().first->userdata; v->setFrontEdgeA(veFrontA, v->frontEdgeA().second); v->setFrontEdgeB(veFrontB, v->frontEdgeB().second); v->setBackEdgeA(veBackA, v->backEdgeA().second); v->setBackEdgeB(veBackB, v->backEdgeB().second); } break; case Nature::NON_T_VERTEX: { NonTVertex *v = (NonTVertex *)(*vv); vector& vedges = (v)->viewedges(); vector newEdges; for (vector::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { ViewEdge *current = (ViewEdge *)((ve)->first)->userdata; newEdges.push_back(ViewVertex::directedViewEdge(current, ve->second)); } (v)->setViewEdges(newEdges); } break; default: break; } } //------------------------------------- // remap vertices in edges: //------------------------------------- for (ve = _Edges.begin(), veend = _Edges.end(); ve != veend; ve++) { (*ve)->setA((ViewVertex *)((*ve)->A()->userdata)); (*ve)->setB((ViewVertex *)((*ve)->B()->userdata)); //--------------------------------------- // Update all embedded FEdges //--------------------------------------- (*ve)->UpdateFEdges(); } // reset all brothers userdata to NULL: //------------------------------------- //--------- // vertices //--------- for (vv = vvertices.begin(), vvend = vvertices.end(); vv != vvend; vv++) { (*vv)->userdata = NULL; } //------ // edges //------ for (ve = vvedges.begin(), veend = vvedges.end(); ve != veend; ve++) { (*ve)->userdata = NULL; } } /*! Cloning method. */ virtual ViewShape *duplicate() { ViewShape *clone = new ViewShape(*this); return clone; } /*! Destructor. */ virtual ~ViewShape(); /* splits a view edge into several view edges. * fe * The FEdge that gets splitted * iViewVertices * The view vertices corresponding to the different intersections for the edge fe. * This list need to be sorted such as the first view vertex is the farther away from fe->vertexA. * ioNewEdges * The feature edges that are newly created (the initial edges are not included) are added to this list. * ioNewViewEdges * The view edges that are newly created (the initial edges are not included) are added to this list. */ inline void SplitEdge(FEdge *fe, const vector& iViewVertices, vector& ioNewEdges, vector& ioNewViewEdges); /* accessors */ /*! Returns the SShape on top of which this ViewShape is built. */ inline SShape *sshape() { return _SShape; } /*! Returns the SShape on top of which this ViewShape is built. */ inline const SShape *sshape() const { return _SShape; } /*! Returns the list of ViewVertex contained in this ViewShape. */ inline vector& vertices() { return _Vertices; } /*! Returns the list of ViewEdge contained in this ViewShape. */ inline vector& edges() { return _Edges; } /*! Returns the ViewShape id. */ inline Id getId() const { return _SShape->getId(); } /*! Returns the ViewShape id. */ inline const string& getName() const { return _SShape->getName(); } /* modifiers */ /*! Sets the SShape on top of which the ViewShape is built. */ inline void setSShape(SShape *iSShape) { _SShape = iSShape; } /*! Sets the list of ViewVertex contained in this ViewShape. */ inline void setVertices(const vector& iVertices) { _Vertices = iVertices; } /*! Sets the list of ViewEdge contained in this ViewShape. */ inline void setEdges(const vector& iEdges) { _Edges = iEdges; } /*! Adds a ViewVertex to the list. */ inline void AddVertex(ViewVertex *iVertex) { _Vertices.push_back(iVertex); //_SShape->AddNewVertex(iVertex->svertex()); } /*! Adds a ViewEdge to the list */ inline void AddEdge(ViewEdge *iEdge) { _Edges.push_back(iEdge); iEdge->setShape(this); //_SShape->AddNewEdge(iEdge->fedge()); } /* removes the view edge iViewEdge in the View Shape and the associated FEdge chain entry in the underlying SShape */ void RemoveEdge(ViewEdge *iViewEdge); /* removes the view vertex iViewVertex in the View Shape. */ void RemoveVertex(ViewVertex *iViewVertex); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewShape") #endif }; /* ############################################# ############################################# ############################################# ###### ###### ###### I M P L E M E N T A T I O N ###### ###### ###### ############################################# ############################################# ############################################# */ /* for inline functions */ void ViewShape::SplitEdge(FEdge *fe, const vector& iViewVertices, vector& ioNewEdges, vector& ioNewViewEdges) { ViewEdge *vEdge = fe->viewedge(); // We first need to sort the view vertices from farther to closer to fe->vertexA SVertex *sv, *sv2; ViewVertex *vva, *vvb; vector::const_iterator vv, vvend; for (vv = iViewVertices.begin(), vvend = iViewVertices.end(); vv != vvend; vv++) { // Add the viewvertices to the ViewShape AddVertex((*vv)); // retrieve the correct SVertex from the view vertex //-------------------------------------------------- sv = (*vv)->frontSVertex(); sv2 = (*vv)->backSVertex(); if (sv->shape() != sv2->shape()) { if (sv->shape() != _SShape) sv = sv2; } else { // if the shape is the same we can safely differ the two vertices using their ids: if (sv->getId() != fe->vertexA()->getId()) sv = sv2; } vva = vEdge->A(); vvb = vEdge->B(); // We split Fedge AB into AA' and A'B. A' and A'B are created. // AB becomes (address speaking) AA'. B is updated. //-------------------------------------------------- SShape *shape = fe->shape(); // a new edge, A'B is created. FEdge *newEdge = shape->SplitEdgeIn2(fe, sv); /* One of the two FEdges (fe and newEdge) may have a 2D length less than M_EPSILON. * (22 Feb 2011, T.K.) */ ioNewEdges.push_back(newEdge); ViewEdge *newVEdge; if ((vva == 0) || (vvb == 0)) { // that means we're dealing with a closed viewedge (loop) // remove the chain that was starting by the fedge A of vEdge (which is different from fe !!!!) shape->RemoveEdgeFromChain(vEdge->fedgeA()); // we set vEdge->setA(*vv); vEdge->setB(*vv); vEdge->setFEdgeA(newEdge); //FEdge *previousEdge = newEdge->previousEdge(); vEdge->setFEdgeB(fe); newVEdge = vEdge; vEdge->fedgeA()->setViewEdge(newVEdge); } else { // while we create the view edge, it updates the "ViewEdge" pointer of every underlying FEdges to this. newVEdge = new ViewEdge((*vv), vvb); //, newEdge, vEdge->fedgeB()); newVEdge->setNature((fe)->getNature()); newVEdge->setFEdgeA(newEdge); //newVEdge->setFEdgeB(fe); // If our original viewedge is made of one FEdge, then if ((vEdge->fedgeA() == vEdge->fedgeB()) || (fe == vEdge->fedgeB())) newVEdge->setFEdgeB(newEdge); else newVEdge->setFEdgeB(vEdge->fedgeB()); //MODIF Id *newId = vEdge->splittingId(); if (newId == 0) { newId = new Id(vEdge->getId()); vEdge->setSplittingId(newId); } newId->setSecond(newId->getSecond() + 1); newVEdge->setId(*newId); newVEdge->setSplittingId(newId); #if 0 Id id(vEdge->getId().getFirst(), vEdge->getId().getSecond() + 1); newVEdge->setId(vEdge->getId()); vEdge->setId(id); #endif AddEdge(newVEdge); // here this shape is set as the edge's shape // add new edge to the list of new edges passed as argument: ioNewViewEdges.push_back(newVEdge); if (0 != vvb) vvb->Replace((vEdge), newVEdge); // we split the view edge: vEdge->setB((*vv)); vEdge->setFEdgeB(fe); //MODIF // Update fedges so that they point to the new viewedge: newVEdge->UpdateFEdges(); } // check whether this vertex is a front vertex or a back one if (sv == (*vv)->frontSVertex()) { // -- View Vertex A' -- (*vv)->setFrontEdgeA(vEdge, true); (*vv)->setFrontEdgeB(newVEdge, false); } else { // -- View Vertex A' -- (*vv)->setBackEdgeA(vEdge, true); (*vv)->setBackEdgeB(newVEdge, false); } } } /**********************************/ /* */ /* */ /* ViewEdge */ /* */ /* */ /**********************************/ #if 0 inline Vec3r ViewEdge::orientation2d(int iCombination) const { return edge_orientation2d_function(*this, iCombination); } inline Vec3r ViewEdge::orientation3d(int iCombination) const { return edge_orientation3d_function(*this, iCombination); } inline real ViewEdge::z_discontinuity(int iCombination) const { return z_discontinuity_edge_function(*this, iCombination); } inline float ViewEdge::local_average_depth(int iCombination ) const { return local_average_depth_edge_function(*this, iCombination); } inline float ViewEdge::local_depth_variance(int iCombination) const { return local_depth_variance_edge_function(*this, iCombination); } inline real ViewEdge::local_average_density(float sigma, int iCombination) const { return density_edge_function(*this, iCombination); } #endif inline const SShape *ViewEdge::occluded_shape() const { if (0 == _aShape) return 0; return _aShape->sshape(); } #if 0 inline Vec3r ViewEdge::curvature2d_as_vector(int iCombination) const { return curvature2d_as_vector_edge_function(*this, iCombination); } inline real ViewEdge::curvature2d_as_angle(int iCombination) const { return curvature2d_as_angle_edge_function(*this, iCombination); } #endif } /* namespace Freestyle */ #endif // __FREESTYLE_VIEW_MAP_H__