From 43b738796dc74adbb87c254dc7c992f29620b97e Mon Sep 17 00:00:00 2001 From: cignoni Date: Thu, 12 Dec 2013 20:35:27 +0000 Subject: [PATCH] Significantly improved documentation. Refactored a bit some of the Add* for better readability --- vcg/complex/allocate.h | 656 ++++++++++++++++++++--------------------- 1 file changed, 317 insertions(+), 339 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index 1952ebd5..9477d016 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -2,7 +2,7 @@ * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * -* Copyright(C) 2004 \/)\/ * +* Copyright(C) 2004-2014 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -28,43 +28,42 @@ #define __VCGLIB_TRIALLOCATOR namespace vcg { - namespace tri { /** \addtogroup trimesh @{ */ - template - size_t Index(MeshType &m, const typename MeshType::VertexType &v) {return &v-&*m.vert.begin();} - template - size_t Index(MeshType &m, const typename MeshType::FaceType &f) {return &f-&*m.face.begin();} - template - size_t Index(MeshType &m, const typename MeshType::EdgeType &e) {return &e-&*m.edge.begin();} - template - size_t Index(MeshType &m, const typename MeshType::HEdgeType &h) {return &h-&*m.hedge.begin();} +template +size_t Index(MeshType &m, const typename MeshType::VertexType &v) {return &v-&*m.vert.begin();} +template +size_t Index(MeshType &m, const typename MeshType::FaceType &f) {return &f-&*m.face.begin();} +template +size_t Index(MeshType &m, const typename MeshType::EdgeType &e) {return &e-&*m.edge.begin();} +template +size_t Index(MeshType &m, const typename MeshType::HEdgeType &h) {return &h-&*m.hedge.begin();} - template - size_t Index(MeshType &m, const typename MeshType::VertexType *vp) {return vp-&*m.vert.begin();} - template - size_t Index(MeshType &m, const typename MeshType::FaceType * fp) {return fp-&*m.face.begin();} - template - size_t Index(MeshType &m, const typename MeshType::EdgeType* e) {return e-&*m.edge.begin();} - template - size_t Index(MeshType &m, const typename MeshType::HEdgeType* h) {return h-&*m.hedge.begin();} +template +size_t Index(MeshType &m, const typename MeshType::VertexType *vp) {return vp-&*m.vert.begin();} +template +size_t Index(MeshType &m, const typename MeshType::FaceType * fp) {return fp-&*m.face.begin();} +template +size_t Index(MeshType &m, const typename MeshType::EdgeType* e) {return e-&*m.edge.begin();} +template +size_t Index(MeshType &m, const typename MeshType::HEdgeType* h) {return h-&*m.hedge.begin();} - template - void ReorderAttribute(ATTR_CONT &c,std::vector & newVertIndex, MeshType & /* m */){ - typename std::set::iterator ai; - for(ai = c.begin(); ai != c.end(); ++ai) - ((typename MeshType::PointerToAttribute)(*ai)).Reorder(newVertIndex); - } +template +void ReorderAttribute(ATTR_CONT &c,std::vector & newVertIndex, MeshType & /* m */){ + typename std::set::iterator ai; + for(ai = c.begin(); ai != c.end(); ++ai) + ((typename MeshType::PointerToAttribute)(*ai)).Reorder(newVertIndex); +} - template - void ResizeAttribute(ATTR_CONT &c,const int & sz , MeshType &/*m*/){ - typename std::set::iterator ai; - for(ai =c.begin(); ai != c.end(); ++ai) - ((typename MeshType::PointerToAttribute)(*ai)).Resize(sz); - } +template +void ResizeAttribute(ATTR_CONT &c,const int & sz , MeshType &/*m*/){ + typename std::set::iterator ai; + for(ai =c.begin(); ai != c.end(); ++ai) + ((typename MeshType::PointerToAttribute)(*ai)).Resize(sz); +} /*! \brief Class to safely add and delete elements in a mesh. @@ -109,10 +108,12 @@ namespace tri { /*! \brief Accessory class to update pointers after eventual reallocation caused by adding elements. - This class is used when allocating new vertexes and faces to update - the pointers that can be changed when resizing the involved vectors of vertex or faces. - It can also be used to prevent any update of the various mesh fields - (e.g. in case you are building all the connections by hand as in a importer); + This class is used whenever you trigger some allocation operation that can cause the invalidation of the pointers to mesh elements. + Typical situations are when you are allocating new vertexes, edges, halfedges of faces or when you compact + their containers to get rid of deleted elements. + This object allows you to update an invalidate pointer immediately after an action that invalidate it. + \note It can also be used to prevent any update of the various internal pointers caused by an invalidation. + This can be useful in case you are building all the internal connections by hand as it happens in a importer; \sa \ref allocation */ template @@ -120,7 +121,7 @@ namespace tri { { public: PointerUpdater(void) : newBase(0), oldBase(0), newEnd(0), oldEnd(0), preventUpdateFlag(false) { ; } - void Clear(){newBase=oldBase=newEnd=oldEnd=0;} + void Clear(){newBase=oldBase=newEnd=oldEnd=0; remap.clear();} /*! \brief Update a pointer to an element of a mesh after a reallocation The updating is correctly done only if this PointerUpdater have been passed to the corresponing allocation call. \sa \ref allocation @@ -149,10 +150,12 @@ namespace tri { bool preventUpdateFlag; /// when true no update is considered necessary. }; + /* +++++++++++++++ Add Vertices ++++++++++++++++ */ /** \brief Add n vertices to the mesh. Function to add n vertices to the mesh. - The elements are added always to the end of the vector. No attempt of reusing previously deleted element is done. + The elements are added always to the end of the vector. + No attempt of reusing previously deleted element is done. \sa PointerUpdater \param m the mesh to be modified \param n the number of elements to be added @@ -241,6 +244,7 @@ namespace tri { v_ret->P()=p; return v_ret; } + /** \brief Wrapper to AddVertices() to add a single vertex with given coords and color */ static VertexIterator AddVertex(MeshType &m, const CoordType &p, const Color4b &c) @@ -251,8 +255,8 @@ namespace tri { return v_ret; } + /* +++++++++++++++ Add Edges ++++++++++++++++ */ - /* ++++++++++ edges +++++++++++++ */ /** \brief Add n edges to the mesh. Function to add n edges to the mesh. The elements are added always to the end of the vector. No attempt of reusing previously deleted element is done. @@ -319,7 +323,6 @@ namespace tri { return ei; } - /** Function to add n edges to the mesh. First wrapper, with no parameters */ @@ -329,7 +332,7 @@ namespace tri { return AddEdges(m, n,pu); } - /** Function to add n edges to the mesh. + /** Function to add n edges to the mesh. Second Wrapper, with a vector of vertex pointers to be updated. */ static EdgeIterator AddEdges(MeshType &m, int n, std::vector &local_vec) @@ -343,8 +346,8 @@ namespace tri { return v_ret; } + /* +++++++++++++++ Add HalfEdges ++++++++++++++++ */ - /* ++++++++++ hedges +++++++++++++ */ /** Function to add n halfedges to the mesh. The second parameter hold a vector of pointers to pointer to elements of the mesh that should be updated after a possible vector realloc. @@ -447,6 +450,7 @@ namespace tri { return v_ret; } + /* +++++++++++++++ Add Faces ++++++++++++++++ */ /** Function to add a face to the mesh and initializing it with the three given VertexPointers First wrapper, with no parameters @@ -457,15 +461,15 @@ namespace tri { assert(v0>=&m.vert.front() && v0<=&m.vert.back()); assert(v1>=&m.vert.front() && v1<=&m.vert.back()); assert(v2>=&m.vert.front() && v2<=&m.vert.back()); - PointerUpdater pu; - FaceIterator fi = AddFaces(m,1,pu); - fi->V(0)=v0; - fi->V(1)=v1; - fi->V(2)=v2; - return fi; + PointerUpdater pu; + FaceIterator fi = AddFaces(m,1,pu); + fi->V(0)=v0; + fi->V(1)=v1; + fi->V(2)=v2; + return fi; } - /** Function to add n faces to the mesh. + /** \brief Function to add n faces to the mesh. First wrapper, with no parameters */ static FaceIterator AddFaces(MeshType &m, int n) @@ -474,7 +478,7 @@ namespace tri { return AddFaces(m,n,pu); } - /** Function to add n faces to the mesh. + /** \brief Function to add n faces to the mesh. Second Wrapper, with a vector of face pointer to be updated. */ static FaceIterator AddFaces(MeshType &m, int n,std::vector &local_vec) @@ -488,142 +492,128 @@ namespace tri { return f_ret; } - /** Function to add n faces to the mesh. - This is the only full featured function that is able to manage correctly all the internal pointers of the mesh (ff and vf relations). - NOTE: THIS FUNCTION ALSO UPDATE FN + /** \brief Function to add n faces to the mesh. + This is the only full featured function that is able to manage correctly + all the official internal pointers of the mesh (like the VF and FF adjacency relations) + \warning Calling this function can cause the invalidation of any not-managed FacePointer + just because we resize the face vector. + If you have such pointers you need to update them by mean of the PointerUpdater object. + \sa PointerUpdater + \param m the mesh to be modified + \param n the number of elements to be added + \param pu a PointerUpdater initialized so that it can be used to update pointers to edges that could have become invalid after this adding. + \retval the iterator to the first element added. */ static FaceIterator AddFaces(MeshType &m, int n, PointerUpdater &pu) { - FaceIterator last, fi; - if(n == 0) return m.face.end(); - pu.Clear(); - if(m.face.empty()) { - pu.oldBase=0; // if the vector is empty we cannot find the last valid element - } else { - pu.oldBase=&*m.face.begin(); - pu.oldEnd=&m.face.back()+1; - last=m.face.end(); + pu.Clear(); + if(n == 0) return m.face.end(); + if(!m.face.empty()) // if the vector is empty we cannot find the last valid element + { + pu.oldBase=&*m.face.begin(); + pu.oldEnd=&m.face.back()+1; + } + // The actual resize + m.face.resize(m.face.size()+n); + m.fn+=n; + + unsigned int siz=(unsigned int)m.face.size()-n; + FaceIterator firstNewFace = m.face.begin(); + advance(firstNewFace,siz); + + typename std::set::iterator ai; + for(ai = m.face_attr.begin(); ai != m.face_attr.end(); ++ai) + ((PointerToAttribute)(*ai)).Resize(m.face.size()); + + pu.newBase = &*m.face.begin(); + pu.newEnd = &m.face.back()+1; + + if(pu.NeedUpdate()) + { + if(HasFFAdjacency(m)) + { // cycle on all the faces except the new ones + for(FaceIterator fi=m.face.begin();fi!=firstNewFace;++fi) + if(!(*fi).IsD()) + for(int i = 0; i < (*fi).VN(); ++i) + if ((*fi).cFFp(i)!=0) pu.Update((*fi).FFp(i)); } - m.face.resize(m.face.size()+n); - m.fn+=n; + if(HasPerVertexVFAdjacency(m) && HasPerFaceVFAdjacency(m)) + { // cycle on all the faces except the new ones + for(FaceIterator fi=m.face.begin();fi!=firstNewFace;++fi) + if(!(*fi).IsD()) + for(int i = 0; i < (*fi).VN(); ++i) + if ((*fi).cVFp(i)!=0) pu.Update((*fi).VFp(i)); + for (VertexIterator vi=m.vert.begin(); vi!=m.vert.end(); ++vi) + if(!(*vi).IsD() && (*vi).cVFp()!=0) + pu.Update((*vi).VFp()); + } - typename std::set::iterator ai; - for(ai = m.face_attr.begin(); ai != m.face_attr.end(); ++ai) - ((PointerToAttribute)(*ai)).Resize(m.face.size()); - - pu.newBase = &*m.face.begin(); - pu.newEnd = &m.face.back()+1; - - if(pu.NeedUpdate()) + if(HasEFAdjacency(m)) { - int ii = 0; - FaceIterator fi = m.face.begin(); - while(ii= &m.face.front() && &f <= &m.face.back()); - assert(!f.IsD()); - f.SetD(); - --m.fn; - } + */ + static void DeleteFace(MeshType &m, FaceType &f) + { + assert(&f >= &m.face.front() && &f <= &m.face.back()); + assert(!f.IsD()); + f.SetD(); + --m.fn; + } - /** Function to delete a vertex from the mesh. + /** Function to delete a vertex from the mesh. NOTE: THIS FUNCTION ALSO UPDATE vn - */ - static void DeleteVertex(MeshType &m, VertexType &v) - { - assert(&v >= &m.vert.front() && &v <= &m.vert.back()); - assert(!v.IsD()); - v.SetD(); - --m.vn; - } + */ + static void DeleteVertex(MeshType &m, VertexType &v) + { + assert(&v >= &m.vert.front() && &v <= &m.vert.back()); + assert(!v.IsD()); + v.SetD(); + --m.vn; + } - /** Function to delete an edge from the mesh. + /** Function to delete an edge from the mesh. NOTE: THIS FUNCTION ALSO UPDATE en - */ - static void DeleteEdge(MeshType &m, EdgeType &e) - { - assert(&e >= &m.edge.front() && &e <= &m.edge.back()); - assert(!e.IsD()); - e.SetD(); - --m.en; - } + */ + static void DeleteEdge(MeshType &m, EdgeType &e) + { + assert(&e >= &m.edge.front() && &e <= &m.edge.back()); + assert(!e.IsD()); + e.SetD(); + --m.en; + } - /** Function to delete a hedge from the mesh. + /** Function to delete a hedge from the mesh. NOTE: THIS FUNCTION ALSO UPDATE en - */ - static void DeleteHEdge(MeshType &m, HEdgeType &h) - { - assert(!h.IsD()); - h.SetD(); - --m.hn; - } + */ + static void DeleteHEdge(MeshType &m, HEdgeType &h) + { + assert(&h >= &m.hedge.front() && &h <= &m.hedge.back()); + assert(!h.IsD()); + h.SetD(); + --m.hn; + } - /* + /* Function to rearrange the vertex vector according to a given index permutation the permutation is vector such that after calling this function @@ -631,64 +621,63 @@ namespace tri { e.g. newVertIndex[i] is the new index of the vertex i - */ - static void PermutateVertexVector(MeshType &m, PointerUpdater &pu) + */ + static void PermutateVertexVector(MeshType &m, PointerUpdater &pu) + { + if(m.vert.empty()) return; + for(unsigned int i=0;iVN();++i) + { + size_t oldIndex = (*fi).V(i) - pu.oldBase; + assert(pu.oldBase <= (*fi).V(i) && oldIndex < pu.remap.size()); + (*fi).V(i) = pu.newBase+pu.remap[oldIndex]; + } + // Loop on the edges to update the pointers EV relation + if(HasEVAdjacency(m)) + for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) + if(!(*ei).IsD()) + for(unsigned int i=0;i<2;++i) + { + pu.Update((*ei).V(i)); + } + } static void CompactEveryVector( MeshType &m) { @@ -834,110 +823,111 @@ namespace tri { CompactEdgeVector(m,pu); } - /*! - \brief Compact vector of faces removing deleted elements. + /*! + \brief Compact face vector by removing deleted elements. - Deleted elements are put to the end of the vector and the vector is resized. Order between elements is preserved but not their position (hence the PointerUpdater) - Immediately after calling this function the \c IsD() test during the scanning a vector, is no more necessary. - \warning It should not be called when TemporaryData is active (but works correctly if attributes are present) - */ - static void CompactFaceVector( MeshType &m, PointerUpdater &pu ) + Deleted elements are put to the end of the vector and the vector is resized. + Order between elements is preserved, but not their position (hence the PointerUpdater) + Immediately after calling this function the \c IsD() test during the scanning a vector, is no more necessary. + \warning It should not be called when some TemporaryData is active (but works correctly if attributes are present) + */ + static void CompactFaceVector( MeshType &m, PointerUpdater &pu ) + { + // If already compacted fast return please! + if(m.fn==(int)m.face.size()) return; + + // newFaceIndex [ ] gives you the new position of the face in the vector; + pu.remap.resize( m.face.size(),std::numeric_limits::max() ); + + size_t pos=0; + for(size_t i=0;i ] gives you the new position of the face in the vector; - pu.remap.resize( m.face.size(),std::numeric_limits::max() ); - - size_t pos=0; - for(size_t i=0;i - static - void - DeletePerFaceAttribute( MeshType & m,typename MeshType::template PerFaceAttributeHandle & h){ + static void DeletePerFaceAttribute( MeshType & m,typename MeshType::template PerFaceAttributeHandle & h){ typename std::set ::iterator i; for( i = m.face_attr.begin(); i != m.face_attr.end(); ++i) if( (*i)._handle == h._handle ){ @@ -1329,8 +1317,7 @@ public: // Generic DeleteAttribute. // It must not crash if you try to delete a non existing attribute, // because you do not have a way of asking for a handle of an attribute for which you do not know the type. - static - bool DeletePerFaceAttribute( MeshType & m, std::string name){ + static bool DeletePerFaceAttribute( MeshType & m, std::string name){ AttrIterator i; PointerToAttribute h1; h1._name = name; i = m.face_attr.find(h1); @@ -1424,9 +1411,7 @@ public: /*! \brief If the per-mesh attribute exists, delete it. */ template - static - void - DeletePerMeshAttribute( MeshType & m,typename MeshType::template PerMeshAttributeHandle & h){ + static void DeletePerMeshAttribute( MeshType & m,typename MeshType::template PerMeshAttributeHandle & h){ typename std::set ::iterator i; for( i = m.mesh_attr.begin(); i != m.mesh_attr.end(); ++i) if( (*i)._handle == h._handle ){ @@ -1435,8 +1420,7 @@ public: return;} } - static - void DeletePerMeshAttribute( MeshType & m, std::string name){ + static void DeletePerMeshAttribute( MeshType & m, std::string name){ AttrIterator i; PointerToAttribute h1; h1._name = name; i = m.mesh_attr.find(h1); @@ -1446,8 +1430,7 @@ public: } template - static - void FixPaddedPerVertexAttribute (MeshType & m, PointerToAttribute & pa){ + static void FixPaddedPerVertexAttribute (MeshType & m, PointerToAttribute & pa){ // create the container of the right type SimpleTempData* _handle = new SimpleTempData(m.vert); @@ -1474,8 +1457,7 @@ public: pa._padding = 0; } template - static - void FixPaddedPerEdgeAttribute (MeshType & m, PointerToAttribute & pa){ + static void FixPaddedPerEdgeAttribute (MeshType & m, PointerToAttribute & pa){ // create the container of the right type SimpleTempData* _handle = new SimpleTempData(m.edge); @@ -1503,8 +1485,7 @@ public: } template - static - void FixPaddedPerFaceAttribute ( MeshType & m,PointerToAttribute & pa){ + static void FixPaddedPerFaceAttribute ( MeshType & m,PointerToAttribute & pa){ // create the container of the right type SimpleTempData* _handle = new SimpleTempData(m.face); @@ -1533,8 +1514,7 @@ public: template - static - void FixPaddedPerMeshAttribute ( MeshType & /* m */,PointerToAttribute & pa){ + static void FixPaddedPerMeshAttribute ( MeshType & /* m */,PointerToAttribute & pa){ // create the container of the right type Attribute * _handle = new Attribute(); @@ -1556,13 +1536,11 @@ public: pa._padding = 0; } +}; // end Allocator class -}; // end class - - - /*@}*/ - } // End Namespace TriMesh -} // End Namespace vcg +/** @} */ // end doxygen group trimesh +} // end namespace tri +} // end namespace vcg #endif