diff --git a/vcg/complex/all_types.h b/vcg/complex/all_types.h index 11d8319e..eb84e56c 100755 --- a/vcg/complex/all_types.h +++ b/vcg/complex/all_types.h @@ -30,6 +30,7 @@ struct AllTypes{ struct AEdgeType {}; struct AFaceType {}; struct AHEdgeType {}; + struct ATetraType {}; }; diff --git a/vcg/complex/tetrahedron/allocate.h b/vcg/complex/tetrahedron/allocate.h new file mode 100644 index 00000000..4ce0baac --- /dev/null +++ b/vcg/complex/tetrahedron/allocate.h @@ -0,0 +1,2109 @@ +/*************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004-2016 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#ifndef __VCGLIB_TETRAALLOCATOR +#define __VCGLIB_TETRAALLOCATOR + +#ifndef __VCG_TETRA_MESH +#error "This file should not be included alone. It is automatically included by complex.h" +#endif + +namespace vcg +{ +namespace tetra +{ +/** \addtogroup tetramesh +@{ +*/ + +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::TetraType &t) { return &t - &*m.tetra.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::TetraType *t) { return t - &*m.tetra.begin(); } + +template +bool IsValidPointer(MeshType &m, const typename MeshType::VertexType *vp) { return (m.vert.size() > 0 && (vp >= &*m.vert.begin()) && (vp <= &m.vert.back())); } +template +bool IsValidPointer(MeshType &m, const typename MeshType::EdgeType *ep) { return (m.edge.size() > 0 && (ep >= &*m.edge.begin()) && (ep <= &m.edge.back())); } +template +bool IsValidPointer(MeshType &m, const typename MeshType::FaceType *fp) { return (m.face.size() > 0 && (fp >= &*m.face.begin()) && (fp <= &m.face.back())); } +template +bool IsValidPointer(MeshType &m, const typename MeshType::TetraType *tp) { return (m.tetra.size() > 0 && (tp >= &*m.tetra.begin()) && (tp <= &m.tetra.back())); } + +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, size_t 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. + + Adding elements to a mesh, like faces and vertices can involve the reallocation of the vectors of the involved elements. + This class provide the only safe methods to add elements. + It also provide an accessory class vcg::tri::PointerUpdater for updating pointers to mesh elements that are kept by the user. + */ +template +class Allocator +{ + +public: + typedef typename MeshType::VertexType VertexType; + typedef typename MeshType::VertexPointer VertexPointer; + typedef typename MeshType::VertexIterator VertexIterator; + typedef typename MeshType::VertContainer VertContainer; + + typedef typename MeshType::EdgeType EdgeType; + typedef typename MeshType::EdgePointer EdgePointer; + typedef typename MeshType::EdgeIterator EdgeIterator; + typedef typename MeshType::EdgeContainer EdgeContainer; + + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::FacePointer FacePointer; + typedef typename MeshType::FaceIterator FaceIterator; + typedef typename MeshType::FaceContainer FaceContainer; + + typedef typename MeshType::TetraType TetraType; + typedef typename MeshType::TetraPointer TetraPointer; + typedef typename MeshType::TetraIterator TetraIterator; + typedef typename MeshType::TetraContainer TetraContainer; + + typedef typename MeshType::CoordType CoordType; + + typedef typename MeshType::PointerToAttribute PointerToAttribute; + typedef typename std::set::iterator AttrIterator; + typedef typename std::set::const_iterator AttrConstIterator; + typedef typename std::set::iterator PAIte; + + /*! + \brief Accessory class to update pointers after eventual reallocation caused by adding elements. + + 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 + class PointerUpdater + { + public: + PointerUpdater(void) : newBase(0), oldBase(0), newEnd(0), oldEnd(0), preventUpdateFlag(false) { ; } + 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 + */ + void Update(SimplexPointerType &vp) + { + //if(vp>=newBase && vp oldEnd) + return; + assert(vp >= oldBase); + assert(vp < oldEnd); + vp = newBase + (vp - oldBase); + if (!remap.empty()) + vp = newBase + remap[vp - newBase]; + } + /*! + \brief return true if the allocation operation that initialized this PointerUpdater has caused a reallocation + */ + bool NeedUpdate() + { + if ((oldBase && newBase != oldBase && !preventUpdateFlag) || !remap.empty()) + return true; + else + return false; + } + + SimplexPointerType newBase; + SimplexPointerType oldBase; + SimplexPointerType newEnd; + SimplexPointerType oldEnd; + std::vector remap; // this vector keep the new position of an element. Uninitialized elements have max_int value to denote an element that has not to be remapped. + + 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. + \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 vertices that could have become invalid after this adding. + \retval the iterator to the first element added. + */ + static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater &pu) + { + VertexIterator last; + if (n == 0) + return m.vert.end(); + pu.Clear(); + if (m.vert.empty()) + pu.oldBase = 0; // if the vector is empty we cannot find the last valid element + else + { + pu.oldBase = &*m.vert.begin(); + pu.oldEnd = &m.vert.back() + 1; + } + + m.vert.resize(m.vert.size() + n); + m.vn += int(n); + + typename std::set::iterator ai; + for (ai = m.vert_attr.begin(); ai != m.vert_attr.end(); ++ai) + ((PointerToAttribute)(*ai)).Resize(m.vert.size()); + + pu.newBase = &*m.vert.begin(); + pu.newEnd = &m.vert.back() + 1; + if (pu.NeedUpdate()) + { + for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + if (!(*fi).IsD()) + for (int i = 0; i < (*fi).VN(); ++i) + if ((*fi).cV(i) != 0) + pu.Update((*fi).V(i)); + + for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei) + if (!(*ei).IsD()) + { + pu.Update((*ei).V(0)); + pu.Update((*ei).V(1)); + // if(HasEVAdjacency(m)) + } + + for (TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) + if (!(*ti.IsD())) + for (int i = 0; i < 4; ++i) + if ((*ti).cV(i) != 0) + pu.Update((*ti).V(i)); + // HEdgeIterator hi; + // for (hi=m.hedge.begin(); hi!=m.hedge.end(); ++hi) + // if(!(*hi).IsD()) + // { + // if(HasHVAdjacency (m)) + // { + // pu.Update((*hi).HVp()); + // } + // } + + // e poiche' lo spazio e' cambiato si ricalcola anche last da zero + } + size_t siz = (size_t)(m.vert.size() - n); + + last = m.vert.begin(); + advance(last, siz); + + return last; // deve restituire l'iteratore alla prima faccia aggiunta; + } + + /** \brief Wrapper to AddVertices(); no PointerUpdater + */ + static VertexIterator AddVertices(MeshType &m, size_t n) + { + PointerUpdater pu; + return AddVertices(m, n, pu); + } + + /** \brief Wrapper to AddVertices() no PointerUpdater but a vector of VertexPointer pointers to be updated + */ + static VertexIterator AddVertices(MeshType &m, size_t n, std::vector &local_vec) + { + PointerUpdater pu; + VertexIterator v_ret = AddVertices(m, n, pu); + + typename std::vector::iterator vi; + for (vi = local_vec.begin(); vi != local_vec.end(); ++vi) + pu.Update(**vi); + return v_ret; + } + + /** \brief Wrapper to AddVertices() to add a single vertex with given coords + */ + static VertexIterator AddVertex(MeshType &m, const CoordType &p) + { + VertexIterator v_ret = AddVertices(m, 1); + v_ret->P() = p; + return v_ret; + } + + /** \brief Wrapper to AddVertices() to add a single vertex with given coords and normal + */ + static VertexIterator AddVertex(MeshType &m, const CoordType &p, const CoordType &n) + { + VertexIterator v_ret = AddVertices(m, 1); + v_ret->P() = p; + v_ret->N() = n; + 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) + { + VertexIterator v_ret = AddVertices(m, 1); + v_ret->P() = p; + v_ret->C() = c; + return v_ret; + } + + /* +++++++++++++++ Add 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. + \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 EdgeIterator AddEdges(MeshType &m, size_t n, PointerUpdater &pu) + { + if (n == 0) + return m.edge.end(); + pu.Clear(); + if (m.edge.empty()) + pu.oldBase = 0; // if the vector is empty we cannot find the last valid element + else + { + pu.oldBase = &*m.edge.begin(); + pu.oldEnd = &m.edge.back() + 1; + } + + m.edge.resize(m.edge.size() + n); + m.en += int(n); + size_t siz = (size_t)(m.edge.size() - n); + EdgeIterator firstNewEdge = m.edge.begin(); + advance(firstNewEdge, siz); + + typename std::set::iterator ai; + for (ai = m.edge_attr.begin(); ai != m.edge_attr.end(); ++ai) + ((typename MeshType::PointerToAttribute)(*ai)).Resize(m.edge.size()); + + pu.newBase = &*m.edge.begin(); + pu.newEnd = &m.edge.back() + 1; + if (pu.NeedUpdate()) + { + if (HasFEAdjacency(m)) + for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + { + if (!(*fi).IsD()) + for (int i = 0; i < (*fi).VN(); ++i) + if ((*fi).cFEp(i) != 0) + pu.Update((*fi).FEp(i)); + } + + if (HasVEAdjacency(m)) + { + for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!(*vi).IsD()) + if ((*vi).cVEp() != 0) + pu.Update((*vi).VEp()); + for (EdgeIterator ei = m.edge.begin(); ei != firstNewEdge; ++ei) + if (!(*ei).IsD()) + { + if ((*ei).cVEp(0) != 0) + pu.Update((*ei).VEp(0)); + if ((*ei).cVEp(1) != 0) + pu.Update((*ei).VEp(1)); + } + } + + //if(HasTEAdjacency(m)) + //.... + + // if(HasHEAdjacency(m)) + // for (HEdgeIterator hi=m.hedge.begin(); hi!=m.hedge.end(); ++hi) + // if(!(*hi).IsD()) + // if ((*hi).cHEp()!=0) pu.Update((*hi).HEp()); + } + + return firstNewEdge; // deve restituire l'iteratore alla prima faccia aggiunta; + } + + /** Function to add a single edge to the mesh. and initializing it with two VertexPointer + */ + static EdgeIterator AddEdge(MeshType &m, VertexPointer v0, VertexPointer v1) + { + EdgeIterator ei = AddEdges(m, 1); + ei->V(0) = v0; + ei->V(1) = v1; + return ei; + } + + /** Function to add a single edge to the mesh. and initializing it with two indexes to the vertexes + */ + static EdgeIterator AddEdge(MeshType &m, size_t v0, size_t v1) + { + assert(v0 != v1); + assert(v0 >= 0 && v0 < m.vert.size()); + assert(v1 >= 0 && v1 < m.vert.size()); + return AddEdge(m, &(m.vert[v0]), &(m.vert[v1])); + } + + /** Function to add a face to the mesh and initializing it with the three given coords + */ + static EdgeIterator AddEdge(MeshType &m, CoordType p0, CoordType p1) + { + VertexIterator vi = AddVertices(m, 2); + EdgeIterator ei = AddEdges(m, 1); + vi->P() = p0; + ei->V(0) = &*vi++; + vi->P() = p1; + ei->V(1) = &*vi++; + return ei; + } + + /** Function to add n edges to the mesh. + First wrapper, with no parameters + */ + static EdgeIterator AddEdges(MeshType &m, size_t n) + { + PointerUpdater pu; + return AddEdges(m, n, pu); + } + + /** Function to add n edges to the mesh. + Second Wrapper, with a vector of vertex pointers to be updated. + */ + static EdgeIterator AddEdges(MeshType &m, size_t n, std::vector &local_vec) + { + PointerUpdater pu; + EdgeIterator v_ret = AddEdges(m, n, pu); + + typename std::vector::iterator ei; + for (ei = local_vec.begin(); ei != local_vec.end(); ++ei) + pu.Update(**ei); + return v_ret; + } + + /* +++++++++++++++ Add HalfEdges ++++++++++++++++ */ + + // /** 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. + // \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 HEdgeIterator AddHEdges(MeshType &m, size_t n, PointerUpdater &pu) + // { + // HEdgeIterator last; + // if(n == 0) return m.hedge.end(); + // pu.Clear(); + // if(m.hedge.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element + // else { + // pu.oldBase=&*m.hedge.begin(); + // pu.oldEnd=&m.hedge.back()+1; + // } + + // m.hedge.resize(m.hedge.size()+n); + // m.hn+=int(n); + + // pu.newBase = &*m.hedge.begin(); + // pu.newEnd = &m.hedge.back()+1; + + // if(pu.NeedUpdate()) + // { + // if(HasFHAdjacency(m)) { + // for (FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi) + // { + // if(!(*fi).IsD() && (*fi).FHp()) + // pu.Update((*fi).FHp()); + // } + // } + // if(HasVHAdjacency(m)) { + // for (VertexIterator vi=m.vert.begin(); vi!=m.vert.end(); ++vi) + // if(!(*vi).IsD() && (*vi).cVHp()!=0) + // pu.Update((*vi).VHp()); + // } + // if(HasEHAdjacency(m)) { + // for (EdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei) + // if(!(*ei).IsD() && (*ei).cEHp()!=0) + // pu.Update((*ei).EHp()); + // } + + // int ii = 0; + // HEdgeIterator hi = m.hedge.begin(); + // while(ii < m.hn - int(n))// cycle on all the faces except the new ones + // { + // if(!(*hi).IsD()) + // { + // if(HasHNextAdjacency(m)) pu.Update((*hi).HNp()); + // if(HasHPrevAdjacency(m)) pu.Update((*hi).HPp()); + // if(HasHOppAdjacency(m)) pu.Update((*hi).HOp()); + // ++ii; + // } + // ++hi; + // } + // } + // size_t siz = (size_t)(m.hedge.size()-n); + + // last = m.hedge.begin(); + // advance(last,siz); + + // return last;// deve restituire l'iteratore alla prima faccia aggiunta; + // } + + // /** Function to add n vertices to the mesh. + // First wrapper, with no parameters + // */ + // static HEdgeIterator AddHEdges(MeshType &m, size_t n) + // { + // PointerUpdater pu; + // return AddHEdges(m, n,pu); + // } + + // /** Function to add n vertices to the mesh. + // Second Wrapper, with a vector of vertex pointers to be updated. + // */ + // static HEdgeIterator AddHEdges(MeshType &m, size_t n, std::vector &local_vec) + // { + // PointerUpdater pu; + // HEdgeIterator v_ret = AddHEdges(m, n,pu); + + // typename std::vector::iterator ei; + // for(ei=local_vec.begin();ei!=local_vec.end();++ei) + // pu.Update(**ei); + // return v_ret; + // } + + /* +++++++++++++++ Add Faces ++++++++++++++++ */ + + /** Function to add a face to the mesh and initializing it with the three given VertexPointers + */ + static FaceIterator AddFace(MeshType &m, VertexPointer v0, VertexPointer v1, VertexPointer v2) + { + assert(m.vert.size() > 0); + assert((v0 != v1) && (v1 != v2) && (v0 != v2)); + 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->Alloc(3); + fi->V(0) = v0; + fi->V(1) = v1; + fi->V(2) = v2; + return fi; + } + + /** Function to add a face to the mesh and initializing it with three indexes + */ + static FaceIterator AddFace(MeshType &m, size_t v0, size_t v1, size_t v2) + { + assert((v0 != v1) && (v1 != v2) && (v0 != v2)); + assert(v0 >= 0 && v0 < m.vert.size()); + assert(v1 >= 0 && v1 < m.vert.size()); + assert(v2 >= 0 && v2 < m.vert.size()); + return AddFace(m, &(m.vert[v0]), &(m.vert[v1]), &(m.vert[v2])); + } + /** Function to add a face to the mesh and initializing it with the three given coords + */ + static FaceIterator AddFace(MeshType &m, CoordType p0, CoordType p1, CoordType p2) + { + VertexIterator vi = AddVertices(m, 3); + FaceIterator fi = AddFaces(m, 1); + fi->Alloc(3); + vi->P() = p0; + fi->V(0) = &*vi++; + vi->P() = p1; + fi->V(1) = &*vi++; + vi->P() = p2; + fi->V(2) = &*vi; + return fi; + } + + /** \brief Function to add n faces to the mesh. + First wrapper, with no parameters + */ + static FaceIterator AddFaces(MeshType &m, size_t n) + { + PointerUpdater pu; + return AddFaces(m, n, pu); + } + + /** \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, size_t n, std::vector &local_vec) + { + PointerUpdater pu; + FaceIterator f_ret = AddFaces(m, n, pu); + + typename std::vector::iterator fi; + for (fi = local_vec.begin(); fi != local_vec.end(); ++fi) + pu.Update(**fi); + return f_ret; + } + + /** \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, size_t n, PointerUpdater &pu) + { + 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 += int(n); + + size_t siz = (size_t)(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)); + } + + 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()); + } + + if (HasEFAdjacency(m)) + { + for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei) + if (!(*ei).IsD() && (*ei).cEFp() != 0) + pu.Update((*ei).EFp()); + } + + if (HasHFAdjacency(m)) + { + for (HEdgeIterator hi = m.hedge.begin(); hi != m.hedge.end(); ++hi) + if (!(*hi).IsD() && (*hi).cHFp() != 0) + pu.Update((*hi).HFp()); + } + } + return firstNewFace; + } + + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //:::::::::::::::::TETRAS ADDER FUNCTIONS::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //do all the other adder funcitons + + /** \brief Function to add n tetras 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 VT and TT adjacency relations) + \warning Calling this function can cause the invalidation of any not-managed TetraPointer + 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 tetras that could have become invalid after this adding. + \retval the iterator to the first element added. + */ + static TetraIterator AddTetras(MeshType &m, size_t n, PointerUpdater &pu) + { + //nothing to do + if (n == 0) + return m.tetra.end(); + + //prepare the pointerupdater info + pu.Clear(); + if (m.tetra.empty()) + pu.oldBase = 0; + else + { + pu.oldBase = &*m.tetra.begin(); + pu.oldEnd = &*m.tetra.back() + 1; + } + + //resize the tetra list and update tetra count + m.tetra.resize(m.tetra.size() + n); + m.tn += n; + + //get the old size and advance to the first new tetrahedron position + size_t oldSize = (size_t)(m.tetra.size() - n); + + TetraIterator firstNewTetra = m.tetra.begin(); + advance(firstNewTetra, oldSize); + + //for each attribute make adapt the list size + typename std::set::iterator ai; + for (ai = m.tetra_attr.begin(); ai != m.tetra_attr.end(); ++ai) + ((typename MeshType::PointerToAttribute)(*ai)).Resize(m.tetra.size()); + + //do the update + pu.newBase = &*m.tetra.begin(); + pu.newEnd = &*m.tetra.back() + 1; + if (pu.NeedUpdate()) + { + if (HasVTAdjacency(m)) + { + for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!vi->IsD()) + pu.Update(vi->VTp()); + + for (TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) + if (!ti->IsD()) + { + pu.Update(ti->VTp(0)); + pu.Update(ti->VTp(1)); + pu.Update(ti->VTp(2)); + pu.Update(ti->VTp(3)); + } + } + + //do edge and face adjacency + + if (HasTTAdjacency(m)) + for (TetraPointer ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) + if (!ti->IsD()) + { + pu.Update(ti->TTp(0)); + pu.Update(ti->TTp(1)); + pu.Update(ti->TTp(2)); + pu.Update(ti->TTp(3)); + } + } + + return firstNewTetra; + } + +//TODO: ADD 4 FACES then add tetra + /** Function to add a face to the mesh and initializing it with the three given VertexPointers + */ + static TetraIterator AddTetra(MeshType &m, VertexPointer v0, VertexPointer v1, VertexPointer v2, VertexPointer v3) + { + assert(m.vert.size() > 0); + assert((v0 != v1) && (v0 != v2) && (v0 != v3) && (v1 != v2) && (v1 != v3) && (v2 != v3)); + 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()); + assert(v3 >= &m.vert.front() && v3 <= &m.vert.back()); + + AddFace(m, v0, v1, v2); + AddFace(m, v0, v3, v1); + AddFace(m, v0, v2, v3); + AddFace(m, v1, v3, v2); + + PointerUpdater pu; + TetraIterator ti = AddTetras(m, 1, pu); + ti->V(0) = v0; + ti->V(1) = v1; + ti->V(2) = v2; + ti->V(3) = v3; + return ti; + } + + /** Function to add a face to the mesh and initializing it with three indexes + */ + static TetraIterator AddTetra(MeshType &m, const size_t v0, const size_t v1, const size_t v2, const size_t v3) + { + assert(m.vert.size() > 0); + assert((v0 != v1) && (v0 != v2) && (v0 != v3) && (v1 != v2) && (v1 != v3) && (v2 != v3)); + assert(v0 >= 0 && v0 < m.vert.size()); + assert(v1 >= 0 && v1 < m.vert.size()); + assert(v2 >= 0 && v2 < m.vert.size()); + assert(v3 >= 0 && v3 < m.vert.size()); + + return AddTetra(m, &(m.vert[v0]), &(m.vert[v1]), &(m.vert[v2]), &(m.vert[v3])); + } + /** Function to add a face to the mesh and initializing it with the three given coords + */ + static TetraIterator AddTetra(MeshType &m, const CoordType & p0, const CoordType & p1, const CoordType & p2, const CoordType & p3) + { + VertexIterator vi = AddVertices(m, 4); + + VertexPointer v0 = &*vi++; + VertexPointer v1 = &*vi++; + VertexPointer v2 = &*vi++; + VertexPointer v3 = &*vi++; + + return AddTetra(m, v0, v1, v2, v3); + } + +//requires no duplicate vertices on faces you use + static TetraIterator AddTetra(MeshType &m, const FaceType & f0, const FaceType & f1, const FaceType & f2, const FaceType & f3) + { + assert(m.face.size() > 0); + assert((f0 != f1) && (f0 != f2) && (f0 != f3) && (f1 != f2) && (f1 != f3) && (f2 != f3)); + assert(f1 >= 0 && f1 < m.face.size()); + assert(f2 >= 0 && f2 < m.face.size()); + assert(f3 >= 0 && f3 < m.face.size()); + assert(f0 >= 0 && f0 < m.face.size()); + //TODO: decide if you want to address this like this + //ERROR: can't use position...so..could force to have no dup verts..and use pointers or avoid this kind of thing + assert(f0.V(0) == f1.V(0) && f0.V(0) == f2.V(0) && //v0 + f0.V(1) == f1.V(2) && f0.V(1) == f3.V(0) && //v1 + f0.V(2) == f2.V(1) && f0.V(2) == f3.V(2) && //v2 + f1.V(1) == f2.V(2) && f1.V(1) == f3.V(1) ) //v3 + + //add a tetra...and set vertices correctly + PointerUpdater pu; + TetraIterator ti = AddTetras(m, 1, pu); + ti->V(0) = f0.V(0); + ti->V(1) = f0.V(1); + ti->V(2) = f0.V(2); + ti->V(3) = f1.V(1); + + return ti; + } + + /** \brief Function to add n faces to the mesh. + First wrapper, with no parameters + */ + static TetraIterator AddTetras(MeshType &m, size_t n) + { + PointerUpdater pu; + return AddTetras(m, n, pu); + } + + /** \brief Function to add n faces to the mesh. + Second Wrapper, with a vector of face pointer to be updated. + */ + static TetraIterator AddTetras(MeshType &m, size_t n, std::vector &local_vec) + { + PointerUpdater pu; + TetraIterator t_ret = AddTetras(m, n, pu); + + typename std::vector::iterator fi; + for (ti = local_vec.begin(); ti != local_vec.end(); ++ti) + pu.Update(**ti); + return t_ret; + } + + + + + /* +++++++++++++++ Deleting ++++++++++++++++ */ + + /** Function to delete a face from the mesh. + NOTE: THIS FUNCTION ALSO UPDATE FN + */ + static void DeleteFace(MeshType &m, FaceType &f) + { + assert(&f >= &m.face.front() && &f <= &m.face.back()); + assert(!f.IsD()); + f.Dealloc(); + f.SetD(); + --m.fn; + } + + /** 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; + } + + /** 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; + } + + // /** Function to delete a hedge from the mesh. + // NOTE: THIS FUNCTION ALSO UPDATE en + // */ + // 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 delete a tetra from the mesh. + NOTE: THIS FUNCTION ALSO UPDATE tn + */ + static void DeleteTetra(MeshType &m, TetraType &t) + { + assert(&t >= &m.tetra.front() && &t <= &m.tetra.back()); + assert(!t.IsD()); + t.SetD(); + --m.tn; + } + + /* + Function to rearrange the vertex vector according to a given index permutation + the permutation is vector such that after calling this function + + m.vert[ newVertIndex[i] ] = m.vert[i]; + + e.g. newVertIndex[i] is the new index of the vertex i + + */ + static void PermutateVertexVector(MeshType &m, PointerUpdater &pu) + { + if (m.vert.empty()) + return; + for (size_t i = 0; i < m.vert.size(); ++i) + { + if (pu.remap[i] < size_t(m.vn)) + { + assert(!m.vert[i].IsD()); + m.vert[pu.remap[i]].ImportData(m.vert[i]); + if (HasVFAdjacency(m)) + { + if (m.vert[i].IsVFInitialized()) + { + m.vert[pu.remap[i]].VFp() = m.vert[i].cVFp(); + m.vert[pu.remap[i]].VFi() = m.vert[i].cVFi(); + } + else + m.vert[pu.remap[i]].VFClear(); + } + if (HasVEAdjacency(m)) + { + if (m.vert[i].IsVEInitialized()) + { + m.vert[pu.remap[i]].VEp() = m.vert[i].cVEp(); + m.vert[pu.remap[i]].VEi() = m.vert[i].cVEi(); + } + else + m.vert[pu.remap[i]].VEClear(); + } + } + } + + // reorder the optional atttributes in m.vert_attr to reflect the changes + ReorderAttribute(m.vert_attr, pu.remap, m); + + // setup the pointer updater + pu.oldBase = &m.vert[0]; + pu.oldEnd = &m.vert.back() + 1; + + // resize + m.vert.resize(m.vn); + + // setup the pointer updater + pu.newBase = (m.vert.empty()) ? 0 : &m.vert[0]; + pu.newEnd = (m.vert.empty()) ? 0 : &m.vert.back() + 1; + + // resize the optional atttributes in m.vert_attr to reflect the changes + ResizeAttribute(m.vert_attr, m.vn, m); + + // Loop on the face to update the pointers FV relation (vertex refs) + for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + if (!(*fi).IsD()) + for (int i = 0; i < fi->VN(); ++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()) + { + pu.Update((*ei).V(0)); + pu.Update((*ei).V(1)); + } + } + + static void CompactEveryVector(MeshType &m) + { + CompactVertexVector(m); + CompactEdgeVector(m); + CompactFaceVector(m); + CompactTetraVector(m); + } + + /*! + \brief Compact vector of vertices 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) + After calling this function the \c IsD() test in 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 CompactVertexVector(MeshType &m, PointerUpdater &pu) + { + // If already compacted fast return please! + if (m.vn == (int)m.vert.size()) + return; + + // newVertIndex [ ] gives you the new position of the vertex in the vector; + pu.remap.resize(m.vert.size(), std::numeric_limits::max()); + + size_t pos = 0; + size_t i = 0; + + for (i = 0; i < m.vert.size(); ++i) + { + if (!m.vert[i].IsD()) + { + pu.remap[i] = pos; + ++pos; + } + } + assert((int)pos == m.vn); + + PermutateVertexVector(m, pu); + } + + /*! \brief Wrapper without the PointerUpdater. */ + static void CompactVertexVector(MeshType &m) + { + PointerUpdater pu; + CompactVertexVector(m, pu); + } + + /*! + \brief Compact vector of edges 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) + After calling this function the \c IsD() test in 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 CompactEdgeVector(MeshType &m, PointerUpdater &pu) + { + // If already compacted fast return please! + if (m.en == (int)m.edge.size()) + return; + + // remap [ ] gives you the new position of the edge in the vector; + pu.remap.resize(m.edge.size(), std::numeric_limits::max()); + + size_t pos = 0; + size_t i = 0; + + for (i = 0; i < m.edge.size(); ++i) + { + if (!m.edge[i].IsD()) + { + pu.remap[i] = pos; + ++pos; + } + } + assert((int)pos == m.en); + + // the actual copying of the data. + for (size_t i = 0; i < m.edge.size(); ++i) + { + if (pu.remap[i] < size_t(m.en)) // uninitialized entries in the remap vector has max_int value; + { + assert(!m.edge[i].IsD()); + m.edge[pu.remap[i]].ImportData(m.edge[i]); + // copy the vertex reference (they are not data!) + m.edge[pu.remap[i]].V(0) = m.edge[i].cV(0); + m.edge[pu.remap[i]].V(1) = m.edge[i].cV(1); + // Now just copy the adjacency pointers (without changing them, to be done later) + if (HasVEAdjacency(m)) + //if (m.edge[i].cVEp(0)!=0) + { + m.edge[pu.remap[i]].VEp(0) = m.edge[i].cVEp(0); + m.edge[pu.remap[i]].VEi(0) = m.edge[i].cVEi(0); + m.edge[pu.remap[i]].VEp(1) = m.edge[i].cVEp(1); + m.edge[pu.remap[i]].VEi(1) = m.edge[i].cVEi(1); + } + if (HasEEAdjacency(m)) + // if (m.edge[i].cEEp(0)!=0) + { + m.edge[pu.remap[i]].EEp(0) = m.edge[i].cEEp(0); + m.edge[pu.remap[i]].EEi(0) = m.edge[i].cEEi(0); + m.edge[pu.remap[i]].EEp(1) = m.edge[i].cEEp(1); + m.edge[pu.remap[i]].EEi(1) = m.edge[i].cEEi(1); + } + } + } + + // reorder the optional attributes in m.vert_attr to reflect the changes + ReorderAttribute(m.edge_attr, pu.remap, m); + + // setup the pointer updater + pu.oldBase = &m.edge[0]; + pu.oldEnd = &m.edge.back() + 1; + + // THE resize + m.edge.resize(m.en); + + // setup the pointer updater + pu.newBase = (m.edge.empty()) ? 0 : &m.edge[0]; + pu.newEnd = (m.edge.empty()) ? 0 : &m.edge.back() + 1; + + // resize the optional atttributes in m.vert_attr to reflect the changes + ResizeAttribute(m.edge_attr, m.en, m); + + // Loop on the vertices to update the pointers of VE relation + if (HasVEAdjacency(m)) + for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!(*vi).IsD()) + pu.Update((*vi).VEp()); + + // Loop on the edges to update the pointers EE VE relation + for (EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei) + for (unsigned int i = 0; i < 2; ++i) + { + if (HasVEAdjacency(m)) + pu.Update((*ei).VEp(i)); + if (HasEEAdjacency(m)) + pu.Update((*ei).EEp(i)); + } + } + + /*! \brief Wrapper without the PointerUpdater. */ + static void CompactEdgeVector(MeshType &m) + { + PointerUpdater pu; + CompactEdgeVector(m, pu); + } + + /*! + \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 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 < m.face.size(); ++i) + { + if (!m.face[i].IsD()) + { + if (pos != i) + { + m.face[pos].ImportData(m.face[i]); + if (FaceType::HasPolyInfo()) + { + m.face[pos].Dealloc(); + m.face[pos].Alloc(m.face[i].VN()); + } + for (int j = 0; j < m.face[i].VN(); ++j) + m.face[pos].V(j) = m.face[i].V(j); + + if (HasVFAdjacency(m)) + for (int j = 0; j < m.face[i].VN(); ++j) + { + if (m.face[i].IsVFInitialized(j)) + { + m.face[pos].VFp(j) = m.face[i].cVFp(j); + m.face[pos].VFi(j) = m.face[i].cVFi(j); + } + else + m.face[pos].VFClear(j); + } + if (HasFFAdjacency(m)) + for (int j = 0; j < m.face[i].VN(); ++j) + { + m.face[pos].FFp(j) = m.face[i].cFFp(j); + m.face[pos].FFi(j) = m.face[i].cFFi(j); + } + } + pu.remap[i] = pos; + ++pos; + } + } + assert((int)pos == m.fn); + + // reorder the optional atttributes in m.face_attr to reflect the changes + ReorderAttribute(m.face_attr, pu.remap, m); + + FacePointer fbase = &m.face[0]; + + // Loop on the vertices to correct VF relation + if (HasVFAdjacency(m)) + { + for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!(*vi).IsD()) + { + if ((*vi).IsVFInitialized() && (*vi).VFp() != 0) + { + size_t oldIndex = (*vi).cVFp() - fbase; + assert(fbase <= (*vi).cVFp() && oldIndex < pu.remap.size()); + (*vi).VFp() = fbase + pu.remap[oldIndex]; + } + } + } + + // Loop on the faces to correct VF and FF relations + pu.oldBase = &m.face[0]; + pu.oldEnd = &m.face.back() + 1; + for (size_t i = m.fn; i < m.face.size(); ++i) + m.face[i].Dealloc(); + m.face.resize(m.fn); + pu.newBase = (m.face.empty()) ? 0 : &m.face[0]; + pu.newEnd = (m.face.empty()) ? 0 : &m.face.back() + 1; + + // resize the optional atttributes in m.face_attr to reflect the changes + ResizeAttribute(m.face_attr, m.fn, m); + + // now we update the various (not null) face pointers (inside VF and FF relations) + for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + if (!(*fi).IsD()) + { + if (HasVFAdjacency(m)) + for (int i = 0; i < (*fi).VN(); ++i) + if ((*fi).IsVFInitialized(i) && (*fi).VFp(i) != 0) + { + size_t oldIndex = (*fi).VFp(i) - fbase; + assert(fbase <= (*fi).VFp(i) && oldIndex < pu.remap.size()); + (*fi).VFp(i) = fbase + pu.remap[oldIndex]; + } + if (HasFFAdjacency(m)) + for (int i = 0; i < (*fi).VN(); ++i) + if ((*fi).cFFp(i) != 0) + { + size_t oldIndex = (*fi).FFp(i) - fbase; + assert(fbase <= (*fi).FFp(i) && oldIndex < pu.remap.size()); + (*fi).FFp(i) = fbase + pu.remap[oldIndex]; + } + } + } + + /*! \brief Wrapper without the PointerUpdater. */ + static void CompactFaceVector(MeshType &m) + { + PointerUpdater pu; + CompactFaceVector(m, pu); + } + +public: + /*! \brief Check if an handle to a Per-Vertex Attribute is valid + */ + template + static bool IsValidHandle(MeshType &m, const typename MeshType::template PerVertexAttributeHandle &a) + { + if (a._handle == NULL) + return false; + for (AttrIterator i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i) + if ((*i).n_attr == a.n_attr) + return true; + return false; + } + + /*! \brief Add a Per-Vertex Attribute of the given ATTR_TYPE with the given name. + + No attribute with that name must exists (even of different type) + */ + template + static + typename MeshType::template PerVertexAttributeHandle + AddPerVertexAttribute(MeshType &m, std::string name) + { + PAIte i; + PointerToAttribute h; + h._name = name; + if (!name.empty()) + { + i = m.vert_attr.find(h); + assert(i == m.vert_attr.end()); // an attribute with this name exists + } + + h._sizeof = sizeof(ATTR_TYPE); + h._padding = 0; + h._handle = new SimpleTempData(m.vert); + h._type = typeid(ATTR_TYPE); + m.attrn++; + h.n_attr = m.attrn; + std::pair res = m.vert_attr.insert(h); + return typename MeshType::template PerVertexAttributeHandle(res.first->_handle, res.first->n_attr); + } + + template + static typename MeshType::template PerVertexAttributeHandle + AddPerVertexAttribute(MeshType &m) + { + return AddPerVertexAttribute(m, std::string("")); + } + + /*! \brief gives a handle to a per-vertex attribute with a given name and ATTR_TYPE + \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. + Otherwise return a hanlde to a newly created. + */ + template + static + typename MeshType::template PerVertexAttributeHandle + GetPerVertexAttribute(MeshType &m, std::string name = std::string("")) + { + typename MeshType::template PerVertexAttributeHandle h; + if (!name.empty()) + { + h = FindPerVertexAttribute(m, name); + if (IsValidHandle(m, h)) + return h; + } + return AddPerVertexAttribute(m, name); + } + + /*! \brief Try to retrieve an handle to an attribute with a given name and ATTR_TYPE + \returns a invalid handle if no attribute with that name and type exists. + */ + template + static typename MeshType::template PerVertexAttributeHandle + FindPerVertexAttribute(MeshType &m, const std::string &name) + { + assert(!name.empty()); + PointerToAttribute h1; + h1._name = name; + typename std::set::iterator i; + + i = m.vert_attr.find(h1); + if (i != m.vert_attr.end()) + if ((*i)._sizeof == sizeof(ATTR_TYPE)) + { + if ((*i)._padding != 0) + { + PointerToAttribute attr = (*i); // copy the PointerToAttribute + m.vert_attr.erase(i); // remove it from the set + FixPaddedPerVertexAttribute(m, attr); + std::pair new_i = m.vert_attr.insert(attr); // insert the modified PointerToAttribute + assert(new_i.second); + i = new_i.first; + } + return typename MeshType::template PerVertexAttributeHandle((*i)._handle, (*i).n_attr); + } + return typename MeshType::template PerVertexAttributeHandle(NULL, 0); + } + + /*! \brief query the mesh for all the attributes per vertex + \returns the name of all attributes with a non-empy name. + */ + template + static void GetAllPerVertexAttribute(MeshType &m, std::vector &all) + { + all.clear(); + typename std::set::const_iterator i; + for (i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i) + if (!(*i)._name.empty()) + { + typename MeshType::template PerVertexAttributeHandle hh; + hh = Allocator::template FindPerVertexAttribute(m, (*i)._name); + if (IsValidHandle(m, hh)) + all.push_back((*i)._name); + } + } + + template + static void + ClearPerVertexAttribute(MeshType &m, typename MeshType::template PerVertexAttributeHandle &h, const ATTR_TYPE &initVal = ATTR_TYPE()) + { + typename std::set::iterator i; + for (i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i) + if ((*i)._handle == h._handle) + { + for (typename MeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + h[vi] = initVal; + return; + } + assert(0); + } + + /*! \brief If the per-vertex attribute exists, delete it. + */ + template + static void + DeletePerVertexAttribute(MeshType &m, typename MeshType::template PerVertexAttributeHandle &h) + { + typename std::set::iterator i; + for (i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i) + if ((*i)._handle == h._handle) + { + delete ((SimpleTempData *)(*i)._handle); + m.vert_attr.erase(i); + return; + } + } + + // 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 DeletePerVertexAttribute(MeshType &m, std::string name) + { + AttrIterator i; + PointerToAttribute h1; + h1._name = name; + i = m.vert_attr.find(h1); + if (i == m.vert_attr.end()) + return false; + delete ((SimpleTempDataBase *)(*i)._handle); + m.vert_attr.erase(i); + return true; + } + + /// Per Edge Attributes + template + static bool IsValidHandle(MeshType &m, const typename MeshType::template PerEdgeAttributeHandle &a) + { + if (a._handle == NULL) + return false; + for (AttrIterator i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i) + if ((*i).n_attr == a.n_attr) + return true; + return false; + } + + template + static + typename MeshType::template PerEdgeAttributeHandle + AddPerEdgeAttribute(MeshType &m, std::string name) + { + PAIte i; + PointerToAttribute h; + h._name = name; + if (!name.empty()) + { + i = m.edge_attr.find(h); + assert(i == m.edge_attr.end()); // an attribute with this name exists + } + h._sizeof = sizeof(ATTR_TYPE); + h._padding = 0; + // h._typename = typeid(ATTR_TYPE).name(); + h._handle = new SimpleTempData(m.edge); + h._type = typeid(ATTR_TYPE); + m.attrn++; + h.n_attr = m.attrn; + std::pair res = m.edge_attr.insert(h); + return typename MeshType::template PerEdgeAttributeHandle(res.first->_handle, res.first->n_attr); + } + + template + static + typename MeshType::template PerEdgeAttributeHandle + AddPerEdgeAttribute(MeshType &m) + { + return AddPerEdgeAttribute(m, std::string("")); + } + + /*! \brief gives a handle to a per-edge attribute with a given name and ATTR_TYPE + \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. + Otherwise return a hanlde to a newly created. + */ + template + static + typename MeshType::template PerEdgeAttributeHandle + GetPerEdgeAttribute(MeshType &m, std::string name = std::string("")) + { + typename MeshType::template PerEdgeAttributeHandle h; + if (!name.empty()) + { + h = FindPerEdgeAttribute(m, name); + if (IsValidHandle(m, h)) + return h; + } + return AddPerEdgeAttribute(m, name); + } + + template + static + typename MeshType::template PerEdgeAttributeHandle + FindPerEdgeAttribute(MeshType &m, const std::string &name) + { + assert(!name.empty()); + PointerToAttribute h1; + h1._name = name; + typename std::set::const_iterator i; + + i = m.edge_attr.find(h1); + if (i != m.edge_attr.end()) + if ((*i)._sizeof == sizeof(ATTR_TYPE)) + { + if ((*i)._padding != 0) + { + PointerToAttribute attr = (*i); // copy the PointerToAttribute + m.edge_attr.erase(i); // remove it from the set + FixPaddedPerEdgeAttribute(m, attr); + std::pair new_i = m.edge_attr.insert(attr); // insert the modified PointerToAttribute + assert(new_i.second); + i = new_i.first; + } + return typename MeshType::template PerEdgeAttributeHandle((*i)._handle, (*i).n_attr); + } + + return typename MeshType::template PerEdgeAttributeHandle(NULL, 0); + } + + template + static void GetAllPerEdgeAttribute(const MeshType &m, std::vector &all) + { + all.clear(); + typename std::set::const_iterator i; + for (i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i) + if (!(*i)._name.empty()) + { + typename MeshType::template PerEdgeAttributeHandle hh; + hh = Allocator::template FindPerEdgeAttribute(m, (*i)._name); + if (IsValidHandle(m, hh)) + all.push_back((*i)._name); + } + } + + /*! \brief If the per-edge attribute exists, delete it. + */ + template + static void + DeletePerEdgeAttribute(MeshType &m, typename MeshType::template PerEdgeAttributeHandle &h) + { + typename std::set::iterator i; + for (i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i) + if ((*i)._handle == h._handle) + { + delete ((SimpleTempData *)(*i)._handle); + m.edge_attr.erase(i); + return; + } + } + + // 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 DeletePerEdgeAttribute(MeshType &m, std::string name) + { + AttrIterator i; + PointerToAttribute h1; + h1._name = name; + i = m.edge_attr.find(h1); + if (i == m.edge_attr.end()) + return false; + delete ((SimpleTempDataBase *)(*i)._handle); + m.edge_attr.erase(i); + return true; + } + + /// Per Tetra Attributes + template + static bool IsValidHandle(MeshType & m, const typename MeshType::template PerTetraAttributeHandle & a) + { + if (a._handle == NULL) + return false; + for (AttrIterator i = m.tetra_attr.begin(); i != m.tetra_attr.end(); ++i) + if ((*i).n_attr == a.n_attr) + return true; + return false; + } + + template + static typename MeshType::template PerTetraAttributeHandle AddPerTetraAttribute(MeshType & m, std::string name) + { + PAIte i; + PointerToAttribute h; + h._name = name; + if (!name.empty()) + { + i = m.tetra_attr.find(h); + assert(i == m.tetra_attr.end()); + } + + h._sizeof = sizeof(ATTR_TYPE); + h._padding = 0; + h._handle = new SimpleTempData(m.tetra); + h._type = typeid(ATTR_TYPE); + m.attrn++; + h.n_attr = m.attrn; + std::pair res = m.tetra_attr.insert(h); + return typename MeshType::template PerTetraAttributeHandle(res.first->_handle, res.first->n_attr); + } + + template + static typename MeshType::template PerTetraAttributeHandle AddPerTetraAttribute(MeshType &m) + { + return AddPerTetraAttribute(m, std::string("")); + } + + /*! \brief gives a handle to a per-tetra attribute with a given name and ATTR_TYPE + \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. + Otherwise return a hanlde to a newly created. + */ + template + static typename MeshType::template PerTetraAttributeHandle GetPerTetraAttribute(MeshType &m, std::string name = std::string("")) + { + typename MeshType::template PerTetraAttributeHandle h; + if (!name.empty()) + { + h = FindPerTetraAttribute(m, name); + if (IsValidHandle(m, h)) + return h; + } + return AddPerTetraAttribute(m, name); + } + + template + static typename MeshType::template PerTetraAttributeHandle FindPerTetraAttribute(MeshType &m, const std::string &name) + { + assert(!name.empty()); + PointerToAttribute h1; + h1._name = name; + typename std::set::iterator i; + + i = m.tetra_attr.find(h1); + if (i != m.tetra_attr.end()) + if ((*i)._sizeof == sizeof(ATTR_TYPE)) + { + if ((*i)._padding != 0) + { + PointerToAttribute attr = (*i); // copy the PointerToAttribute + m.tetra_attr.erase(i); // remove it from the set + FixPaddedPerTetraAttribute(m, attr); + std::pair new_i = m.tetra_attr.insert(attr); // insert the modified PointerToAttribute + assert(new_i.second); + i = new_i.first; + } + return typename MeshType::template PerTetraAttributeHandle((*i)._handle, (*i).n_attr); + } + return typename MeshType::template PerTetraAttributeHandle(NULL, 0); + } + + template + static void GetAllPerTetraAttribute(MeshType &m, std::vector &all) + { + all.clear(); + typename std::set::const_iterator i; + for (i = m.tetra_attr.begin(); i != m.tetra_attr.end(); ++i) + if (!(*i)._name.empty()) + { + typename MeshType::template PerTetraAttributeHandle hh; + hh = Allocator::template FindPerTetraAttribute(m, (*i)._name); + if (IsValidHandle(m, hh)) + all.push_back((*i)._name); + } + } + + /*! \brief If the per-face attribute exists, delete it. + */ + template + static void DeletePerTetraAttribute(MeshType &m, typename MeshType::template PerTetraAttributeHandle &h) + { + typename std::set::iterator i; + for (i = m.tetra_attr.begin(); i != m.tetra_attr.end(); ++i) + if ((*i)._handle == h._handle) + { + delete ((SimpleTempData *)(*i)._handle); + m.tetra_attr.erase(i); + return; + } + } + + // 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 DeletePerTetraAttribute(MeshType &m, std::string name) + { + AttrIterator i; + PointerToAttribute h1; + h1._name = name; + i = m.tetra_attr.find(h1); + if (i == m.tetra_attr.end()) + return false; + delete ((SimpleTempDataBase *)(*i)._handle); + m.tetra_attr.erase(i); + return true; + } + + + /// Per Face Attributes + template + static bool IsValidHandle(MeshType &m, const typename MeshType::template PerFaceAttributeHandle &a) + { + if (a._handle == NULL) + return false; + for (AttrIterator i = m.face_attr.begin(); i != m.face_attr.end(); ++i) + if ((*i).n_attr == a.n_attr) + return true; + return false; + } + + template + static + typename MeshType::template PerFaceAttributeHandle + AddPerFaceAttribute(MeshType &m, std::string name) + { + PAIte i; + PointerToAttribute h; + h._name = name; + if (!name.empty()) + { + i = m.face_attr.find(h); + assert(i == m.face_attr.end()); // an attribute with this name exists + } + + h._sizeof = sizeof(ATTR_TYPE); + h._padding = 0; + h._handle = new SimpleTempData(m.face); + h._type = typeid(ATTR_TYPE); + m.attrn++; + h.n_attr = m.attrn; + std::pair res = m.face_attr.insert(h); + return typename MeshType::template PerFaceAttributeHandle(res.first->_handle, res.first->n_attr); + } + + template + static + typename MeshType::template PerFaceAttributeHandle + AddPerFaceAttribute(MeshType &m) + { + return AddPerFaceAttribute(m, std::string("")); + } + + /*! \brief gives a handle to a per-edge attribute with a given name and ATTR_TYPE + \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. + Otherwise return a hanlde to a newly created. + */ + template + static + typename MeshType::template PerFaceAttributeHandle + GetPerFaceAttribute(MeshType &m, std::string name = std::string("")) + { + typename MeshType::template PerFaceAttributeHandle h; + if (!name.empty()) + { + h = FindPerFaceAttribute(m, name); + if (IsValidHandle(m, h)) + return h; + } + return AddPerFaceAttribute(m, name); + } + + template + static + typename MeshType::template PerFaceAttributeHandle + FindPerFaceAttribute(MeshType &m, const std::string &name) + { + assert(!name.empty()); + PointerToAttribute h1; + h1._name = name; + typename std::set::iterator i; + + i = m.face_attr.find(h1); + if (i != m.face_attr.end()) + if ((*i)._sizeof == sizeof(ATTR_TYPE)) + { + if ((*i)._padding != 0) + { + PointerToAttribute attr = (*i); // copy the PointerToAttribute + m.face_attr.erase(i); // remove it from the set + FixPaddedPerFaceAttribute(m, attr); + std::pair new_i = m.face_attr.insert(attr); // insert the modified PointerToAttribute + assert(new_i.second); + i = new_i.first; + } + return typename MeshType::template PerFaceAttributeHandle((*i)._handle, (*i).n_attr); + } + return typename MeshType::template PerFaceAttributeHandle(NULL, 0); + } + + template + static void GetAllPerFaceAttribute(MeshType &m, std::vector &all) + { + all.clear(); + typename std::set::const_iterator i; + for (i = m.face_attr.begin(); i != m.face_attr.end(); ++i) + if (!(*i)._name.empty()) + { + typename MeshType::template PerFaceAttributeHandle hh; + hh = Allocator::template FindPerFaceAttribute(m, (*i)._name); + if (IsValidHandle(m, hh)) + all.push_back((*i)._name); + } + } + + /*! \brief If the per-face attribute exists, delete it. + */ + template + 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) + { + delete ((SimpleTempData *)(*i)._handle); + m.face_attr.erase(i); + return; + } + } + + // 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) + { + AttrIterator i; + PointerToAttribute h1; + h1._name = name; + i = m.face_attr.find(h1); + if (i == m.face_attr.end()) + return false; + delete ((SimpleTempDataBase *)(*i)._handle); + m.face_attr.erase(i); + return true; + } + + /// Per Mesh Attributes + template + static bool IsValidHandle(MeshType &m, const typename MeshType::template PerMeshAttributeHandle &a) + { + if (a._handle == NULL) + return false; + for (AttrIterator i = m.mesh_attr.begin(); i != m.mesh_attr.end(); ++i) + if ((*i).n_attr == a.n_attr) + return true; + return false; + } + + template + static + typename MeshType::template PerMeshAttributeHandle + AddPerMeshAttribute(MeshType &m, std::string name) + { + PAIte i; + PointerToAttribute h; + h._name = name; + if (!name.empty()) + { + i = m.mesh_attr.find(h); + assert(i == m.mesh_attr.end()); // an attribute with this name exists + } + h._sizeof = sizeof(ATTR_TYPE); + h._padding = 0; + h._handle = new Attribute(); + h._type = typeid(ATTR_TYPE); + m.attrn++; + h.n_attr = m.attrn; + std::pair res = m.mesh_attr.insert(h); + return typename MeshType::template PerMeshAttributeHandle(res.first->_handle, res.first->n_attr); + } + + /*! \brief gives a handle to a per-edge attribute with a given name and ATTR_TYPE + \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. + Otherwise return a hanlde to a newly created. + */ + template + static + typename MeshType::template PerMeshAttributeHandle + GetPerMeshAttribute(MeshType &m, std::string name = std::string("")) + { + typename MeshType::template PerMeshAttributeHandle h; + if (!name.empty()) + { + h = FindPerMeshAttribute(m, name); + if (IsValidHandle(m, h)) + return h; + } + return AddPerMeshAttribute(m, name); + } + + template + static + typename MeshType::template PerMeshAttributeHandle + FindPerMeshAttribute(MeshType &m, const std::string &name) + { + assert(!name.empty()); + PointerToAttribute h1; + h1._name = name; + typename std::set::iterator i; + + i = m.mesh_attr.find(h1); + if (i != m.mesh_attr.end()) + if ((*i)._sizeof == sizeof(ATTR_TYPE)) + { + if ((*i)._padding != 0) + { + PointerToAttribute attr = (*i); // copy the PointerToAttribute + m.mesh_attr.erase(i); // remove it from the set + FixPaddedPerMeshAttribute(m, attr); + std::pair new_i = m.mesh_attr.insert(attr); // insert the modified PointerToAttribute + assert(new_i.second); + i = new_i.first; + } + + return typename MeshType::template PerMeshAttributeHandle((*i)._handle, (*i).n_attr); + } + + return typename MeshType::template PerMeshAttributeHandle(NULL, 0); + } + + template + static void GetAllPerMeshAttribute(const MeshType &m, std::vector &all) + { + typename std::set::iterator i; + for (i = m.mesh_attr.begin(); i != m.mesh_attr.end(); ++i) + if ((*i)._sizeof == sizeof(ATTR_TYPE)) + all.push_back((*i)._name); + } + + /*! \brief If the per-mesh attribute exists, delete it. + */ + template + 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) + { + delete ((Attribute *)(*i)._handle); + m.mesh_attr.erase(i); + return; + } + } + + // 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 DeletePerMeshAttribute(MeshType &m, std::string name) + { + AttrIterator i; + PointerToAttribute h1; + h1._name = name; + i = m.mesh_attr.find(h1); + if (i == m.mesh_attr.end()) + return false; + delete ((SimpleTempDataBase *)(*i)._handle); + m.mesh_attr.erase(i); + return true; + } + + template + static void FixPaddedPerVertexAttribute(MeshType &m, PointerToAttribute &pa) + { + + // create the container of the right type + SimpleTempData *_handle = new SimpleTempData(m.vert); + + // copy the padded container in the new one + _handle->Resize(m.vert.size()); + for (size_t i = 0; i < m.vert.size(); ++i) + { + ATTR_TYPE *dest = &(*_handle)[i]; + char *ptr = (char *)(((SimpleTempDataBase *)pa._handle)->DataBegin()); + memcpy((void *)dest, + (void *)&(ptr[i * pa._sizeof]), sizeof(ATTR_TYPE)); + } + + // remove the padded container + delete ((SimpleTempDataBase *)pa._handle); + + // update the pointer to data + pa._sizeof = sizeof(ATTR_TYPE); + + // update the pointer to data + pa._handle = _handle; + + // zero the padding + pa._padding = 0; + } + template + static void FixPaddedPerEdgeAttribute(MeshType &m, PointerToAttribute &pa) + { + + // create the container of the right type + SimpleTempData *_handle = new SimpleTempData(m.edge); + + // copy the padded container in the new one + _handle->Resize(m.edge.size()); + for (size_t i = 0; i < m.edge.size(); ++i) + { + ATTR_TYPE *dest = &(*_handle)[i]; + char *ptr = (char *)(((SimpleTempDataBase *)pa._handle)->DataBegin()); + memcpy((void *)dest, + (void *)&(ptr[i * pa._sizeof]), sizeof(ATTR_TYPE)); + } + + // remove the padded container + delete ((SimpleTempDataBase *)pa._handle); + + // update the pointer to data + pa._sizeof = sizeof(ATTR_TYPE); + + // update the pointer to data + pa._handle = _handle; + + // zero the padding + pa._padding = 0; + } + + template + static void FixPaddedPerFaceAttribute(MeshType &m, PointerToAttribute &pa) + { + + // create the container of the right type + SimpleTempData *_handle = new SimpleTempData(m.face); + + // copy the padded container in the new one + _handle->Resize(m.face.size()); + for (size_t i = 0; i < m.face.size(); ++i) + { + ATTR_TYPE *dest = &(*_handle)[i]; + char *ptr = (char *)(((SimpleTempDataBase *)pa._handle)->DataBegin()); + memcpy((void *)dest, + (void *)&(ptr[i * pa._sizeof]), sizeof(ATTR_TYPE)); + } + + // remove the padded container + delete ((SimpleTempDataBase *)pa._handle); + + // update the pointer to data + pa._sizeof = sizeof(ATTR_TYPE); + + // update the pointer to data + pa._handle = _handle; + + // zero the padding + pa._padding = 0; + } + + template + static void FixPaddedPerTetraAttribute(MeshType &m, PointerToAttribute &pa) + { + + // create the container of the right type + SimpleTempData *_handle = new SimpleTempData(m.tetra); + + // copy the padded container in the new one + _handle->Resize(m.tetra.size()); + for (size_t i = 0; i < m.tetra.size(); ++i) + { + ATTR_TYPE *dest = &(*_handle)[i]; + char *ptr = (char *)(((SimpleTempDataBase *)pa._handle)->DataBegin()); + memcpy((void *)dest, + (void *)&(ptr[i * pa._sizeof]), sizeof(ATTR_TYPE)); + } + + // remove the padded container + delete ((SimpleTempDataBase *)pa._handle); + + // update the pointer to data + pa._sizeof = sizeof(ATTR_TYPE); + + // update the pointer to data + pa._handle = _handle; + + // zero the padding + pa._padding = 0; + } + + template + static void FixPaddedPerMeshAttribute(MeshType & /* m */, PointerToAttribute &pa) + { + + // create the container of the right type + Attribute *_handle = new Attribute(); + + // copy the padded container in the new one + char *ptr = (char *)(((Attribute *)pa._handle)->DataBegin()); + memcpy((void *)_handle->attribute, (void *)&(ptr[0]), sizeof(ATTR_TYPE)); + + // remove the padded container + delete ((Attribute *)pa._handle); + + // update the pointer to data + pa._sizeof = sizeof(ATTR_TYPE); + + // update the pointer to data + pa._handle = _handle; + + // zero the padding + pa._padding = 0; + } + +}; // end Allocator class + +/** @} */ // end doxygen group trimesh +} // end namespace tri +} // end namespace vcg + +#endif diff --git a/vcg/complex/tetrahedron/base.h b/vcg/complex/tetrahedron/base.h new file mode 100644 index 00000000..befa0448 --- /dev/null +++ b/vcg/complex/tetrahedron/base.h @@ -0,0 +1,1062 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004-2016 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#ifndef __VCG_TETRA_MESH +#error "This file should not be included alone. It is automatically included by complex.h" +#endif +#ifndef __VCG_TETRA_COMPLEX_BASE +#define __VCG_TETRA_COMPLEX_BASE + +namespace vcg +{ + +class PointerToAttribute +{ + public: + SimpleTempDataBase *_handle; // pointer to the SimpleTempData that stores the attribute + std::string _name; // name of the attribute + int _sizeof; // size of the attribute type (used only with VMI loading) + int _padding; // padding (used only with VMI loading) + + int n_attr; // unique ID of the attribute + std::type_index _type; + void Resize(size_t sz) { ((SimpleTempDataBase *)_handle)->Resize(sz); } + void Reorder(std::vector &newVertIndex) { ((SimpleTempDataBase *)_handle)->Reorder(newVertIndex); } + bool operator<(const PointerToAttribute b) const { return (_name.empty() && b._name.empty()) ? (_handle < b._handle) : (_name < b._name); } + + PointerToAttribute() : _type(typeid(void)){}; +}; + +namespace tetra +{ +/** \addtogroup TetraMesh */ +/*@{*/ + +/* MeshTypeHolder is a class which is used to define the types in the mesh +*/ + +template +struct BaseMeshTypeHolder +{ + + typedef bool ScalarType; + typedef std::vector CONTV; + typedef std::vector CONTE; + typedef std::vector CONTF; + typedef std::vector CONTT; + + typedef CONTV VertContainer; + typedef _Vertex VertexType; + typedef typename TYPESPOOL::VertexPointer VertexPointer; + typedef const typename TYPESPOOL::VertexPointer ConstVertexPointer; + typedef bool CoordType; + typedef typename CONTV::iterator VertexIterator; + typedef typename CONTV::const_iterator ConstVertexIterator; + + typedef CONTE EdgeContainer; + typedef typename CONTE::value_type EdgeType; + typedef typename TYPESPOOL::EdgePointer EdgePointer; + typedef typename CONTE::iterator EdgeIterator; + typedef typename CONTE::const_iterator ConstEdgeIterator; + + typedef CONTF FaceContainer; + typedef typename CONTF::value_type FaceType; + typedef typename CONTF::const_iterator ConstFaceIterator; + typedef typename CONTF::iterator FaceIterator; + typedef typename TYPESPOOL::FacePointer FacePointer; + typedef const typename TYPESPOOL::FacePointer ConstFacePointer; + + typedef CONTT TetraContainer; + typedef typename CONTT::value_type TetraType; + typedef typename TYPESPOOL::TetraPointer TetraPointer; + typedef const typename TYPESPOOL::TetraPointer ConstTetraPointer; + typedef typename CONTT::iterator TetraIterator; + typedef typename CONTT::const_iterator ConstTetraIterator; +}; + +template +struct MeshTypeHolder : public T +{ +}; + +template +struct MeshTypeHolder : public T +{ + typedef CONT VertContainer; + typedef typename VertContainer::value_type VertexType; + typedef VertexType *VertexPointer; + typedef const VertexType *ConstVertexPointer; + typedef typename VertexType::ScalarType ScalarType; + typedef typename VertexType::CoordType CoordType; + typedef typename VertContainer::iterator VertexIterator; + typedef typename VertContainer::const_iterator ConstVertexIterator; +}; + +template +struct MeshTypeHolder : public T +{ + typedef CONT EdgeContainer; + typedef typename EdgeContainer::value_type EdgeType; + typedef typename EdgeContainer::value_type *EdgePointer; + typedef typename EdgeContainer::iterator EdgeIterator; + typedef typename EdgeContainer::const_iterator ConstEdgeIterator; +}; + +template +struct MeshTypeHolder : public T +{ + typedef CONT FaceContainer; + typedef typename FaceContainer::value_type FaceType; + typedef typename FaceContainer::const_iterator ConstFaceIterator; + typedef typename FaceContainer::iterator FaceIterator; + typedef FaceType *FacePointer; + typedef const FaceType *ConstFacePointer; +}; + +template +struct MeshTypeHolder : public T +{ + typedef CONT TetraContainer; + typedef typename TetraContainer::value_type TetraType; + typedef TetraType *TetraPointer; + typedef const TetraType *ConstTetraPointer; + typedef typename TetraContainer::iterator TetraIterator; + typedef typename TetraContainer::const_iterator ConstTetraIterator; +}; + +template +struct Der : public MeshTypeHolder +{ +}; +struct DummyContainer +{ + struct value_type + { + typedef int IAm; + }; +}; +/** \brief The official \b mesh class + +As explained in \ref basic_concepts, this class is templated over a list of container of simplexes (like vertex, face, edges) + */ + +template +class TetraMesh + : public MArity4, Container0, Der, Container1, Der, Container2, Der, Container3, Der> +{ + public: + typedef typename TetraMesh::ScalarType ScalarType; + typedef typename TetraMesh::VertContainer VertContainer; + typedef typename TetraMesh::EdgeContainer EdgeContainer; + typedef typename TetraMesh::FaceContainer FaceContainer; + typedef typename TetraMesh::TetraContainer TetraContainer; + + // types for vertex + typedef typename TetraMesh::VertexType VertexType; + typedef typename TetraMesh::VertexPointer VertexPointer; + typedef typename TetraMesh::ConstVertexPointer ConstVertexPointer; + typedef typename TetraMesh::CoordType CoordType; + typedef typename TetraMesh::VertexIterator VertexIterator; + typedef typename TetraMesh::ConstVertexIterator ConstVertexIterator; + + // types for edge + typedef typename TetraMesh::EdgeType EdgeType; + typedef typename TetraMesh::EdgePointer EdgePointer; + typedef typename TetraMesh::EdgeIterator EdgeIterator; + typedef typename TetraMesh::ConstEdgeIterator ConstEdgeIterator; + + //types for face + typedef typename TetraMesh::FaceType FaceType; + typedef typename TetraMesh::ConstFaceIterator ConstFaceIterator; + typedef typename TetraMesh::FaceIterator FaceIterator; + typedef typename TetraMesh::FacePointer FacePointer; + typedef typename TetraMesh::ConstFacePointer ConstFacePointer; + + // types for hedge + typedef typename TetraMesh::TetraType TetraType; + typedef typename TetraMesh::TetraPointer TetraPointer; + typedef typename TetraMesh::ConstTetraPointer ConstTetraPointer; + typedef typename TetraMesh::TetraIterator TetraIterator + typedef typename TetraMesh::ConstTetraIterator ConstTetraIterator; + + typedef vcg::PointerToAttribute PointerToAttribute; + + typedef TetraMesh MeshType; + + typedef Box3 BoxType; + + /// Container of vertices, usually a vector. + VertContainer vert; + /// Current number of vertices; this member is for internal use only. You should always use the VN() member + int vn; + /// Current number of vertices + inline int VN() const { return vn; } + + /// Container of edges, usually a vector. + EdgeContainer edge; + /// Current number of edges; this member is for internal use only. You should always use the EN() member + int en; + /// Current number of edges + inline int EN() const { return en; } + + /// Container of faces, usually a vector. + FaceContainer face; + /// Current number of faces; this member is for internal use only. You should always use the FN() member + int fn; + /// Current number of faces + inline int FN() const { return fn; } + + /// Container of tetras, usually a vector. + TetraContainer tetra; + /// Current number of tetras; this member is for internal use only. You should always use the TN() member + int tn; + /// Current number of tetras; + inline int TN() const { return tn; } + + /// Bounding box of the mesh + Box3 bbox; + + /// Nomi di textures + // + std::vector textures; + // + std::vector normalmaps; + + int attrn; // total numer of attribute created + + std::set vert_attr; + std::set edge_attr; + std::set face_attr; + std::set tetra_attr; + std::set mesh_attr; + + template + class AttributeHandle + { + public: + AttributeHandle() { _handle = (SimpleTempData *)NULL; } + AttributeHandle(void *ah, const int &n) : _handle((SimpleTempData *)ah), n_attr(n) {} + AttributeHandle operator=(const PointerToAttribute &pva) + { + _handle = (SimpleTempData *)pva._handle; + n_attr = pva.n_attr; + return (*this); + } + + //pointer to the SimpleTempData that stores the attribute + SimpleTempData *_handle; + + // its attribute number + int n_attr; + + // access function + template + ATTR_TYPE &operator[](const RefType &i) { return (*_handle)[i]; } + void resize(size_t /*size*/){}; + }; + + template + class PerVertexAttributeHandle : public AttributeHandle + { + public: + PerVertexAttributeHandle() : AttributeHandle() {} + PerVertexAttributeHandle(void *ah, const int &n) : AttributeHandle(ah, n) {} + }; + + template + class PerFaceAttributeHandle : public AttributeHandle + { + public: + PerFaceAttributeHandle() : AttributeHandle() {} + PerFaceAttributeHandle(void *ah, const int &n) : AttributeHandle(ah, n) {} + }; + + template + class PerEdgeAttributeHandle : public AttributeHandle + { + public: + PerEdgeAttributeHandle() : AttributeHandle() {} + PerEdgeAttributeHandle(void *ah, const int &n) : AttributeHandle(ah, n) {} + }; + + template + class PerTetraAttributeHandle : public AttributeHandle + { + public: + PerTetraAttributeHandle() : AttributeHandle() {} + PerTetraAttributeHandle(void *ah, const int &n) : AttributeHandle(ah, n) {} + }; + + + template + class PerMeshAttributeHandle + { + public: + PerMeshAttributeHandle() { _handle = NULL; } + PerMeshAttributeHandle(void *ah, const int &n) : _handle((Attribute *)ah), n_attr(n) {} + PerMeshAttributeHandle operator=(const PerMeshAttributeHandle &pva) + { + _handle = (Attribute *)pva._handle; + n_attr = pva.n_attr; + return (*this); + } + + Attribute *_handle; + int n_attr; + ATTR_TYPE &operator()() { return *((Attribute *)_handle)->attribute; } + }; + + // Some common Handle typedefs to simplify use + typedef typename MeshType::template PerVertexAttributeHandle PerVertexScalarHandle; + typedef typename MeshType::template PerVertexAttributeHandle PerVertexIntHandle; + typedef typename MeshType::template PerVertexAttributeHandle PerVertexBoolHandle; + typedef typename MeshType::template PerVertexAttributeHandle PerVertexCoordHandle; + + typedef typename MeshType::template PerFaceAttributeHandle PerFaceScalarHandle; + typedef typename MeshType::template PerFaceAttributeHandle PerFaceIntHandle; + typedef typename MeshType::template PerFaceAttributeHandle PerFaceBoolHandle; + typedef typename MeshType::template PerFaceAttributeHandle PerFaceCoordHandle; + + typedef typename MeshType::template PerTetraAttributeHandle PerTetraScalarHandle; + typedef typename MeshType::template PerTetraAttributeHandle PerTetraIntHandle; + typedef typename MeshType::template PerTetraAttributeHandle PerTetraBoolHandle; + typedef typename MeshType::template PerTetraAttributeHandle PerTetraCoordHandle; + + // the camera member (that should keep the intrinsics) is no more needed since 2006, when intrisncs moved into the Shot structure + //Camera camera; // intrinsic + Shot shot; // intrinsic && extrinsic + + private: + /// The per-mesh color. Not very useful and meaningful... + Color4b c; + + public: + inline const Color4b &C() const { return c; } + inline Color4b &C() { return c; } + inline Color4b cC() const { return c; } + + /// Default constructor + TetraMesh() + { + Clear(); + } + + /// destructor + ~TetraMesh() + { + Clear(); + } + + int Mem(const int &nv, const int &nf, const int &nt) const + { + typename std::set::const_iterator i; + int size = 0; + size += sizeof(TetraMesh) + sizeof(VertexType) * nv + sizeof(FaceType) * nf + sizeof(TetraType) * nt; + + for (i = vert_attr.begin(); i != vert_attr.end(); ++i) + size += ((SimpleTempDataBase *)(*i)._handle)->SizeOf() * nv; + for (i = edge_attr.begin(); i != edge_attr.end(); ++i) + size += ((SimpleTempDataBase *)(*i)._handle)->SizeOf() * en; + for (i = face_attr.begin(); i != face_attr.end(); ++i) + size += ((SimpleTempDataBase *)(*i)._handle)->SizeOf() * nf; + for (i = tetra_attr.begin(); i != tetra_attr.end(); ++i) + size += ((SimpleTempDataBase *)(*i)._handle)->SizeOf() * nt; + for (i = mesh_attr.begin(); i != mesh_attr.end(); ++i) + size += ((SimpleTempDataBase *)(*i)._handle)->SizeOf(); + + return size; + } + int MemUsed() const { return Mem(vert.size(), face.size(), tetra.size()); } + inline int MemNeeded() const { return Mem(vn, fn, tn); } + + /// Function to destroy the mesh + void Clear() + { + for (FaceIterator fi = face.begin(); fi != face.end(); ++fi) + (*fi).Dealloc(); + vert.clear(); + face.clear(); + edge.clear(); + tetra.clear(); + // textures.clear(); + // normalmaps.clear(); + vn = 0; + en = 0; + fn = 0; + hn = 0; + imark = 0; + C() = Color4b::Gray; + } + + void ClearAttributes() + { + // Clear attributes + typename std::set::iterator i; + for (i = vert_attr.begin(); i != vert_attr.end(); ++i) + delete ((SimpleTempDataBase *)(*i)._handle); + vert_attr.clear(); + + for (i = edge_attr.begin(); i != edge_attr.end(); ++i) + delete ((SimpleTempDataBase *)(*i)._handle); + edge_attr.clear(); + + for (i = face_attr.begin(); i != face_attr.end(); ++i) + delete ((SimpleTempDataBase *)(*i)._handle); + face_attr.clear(); + + for (i = tetra_attr.begin(); i != tetra_attr.end(); ++i) + delete ((SimpleTempDataBase *)(*i)._handle); + tetra_attr.clear(); + + for (i = mesh_attr.begin(); i != mesh_attr.end(); ++i) + delete ((SimpleTempDataBase *)(*i)._handle); + mesh_attr.clear(); + attrn = 0; + } + + bool IsEmpty() const + { + return vert.empty() && edge.empty() && face.empty() && tetra.empty(); + } + + int &TetraNumber() { return tn; } + int &SimplexNumber() { return fn; } + int &VertexNumber() { return vn; } + + /// The incremental mark + int imark; + + private: + // TetraMesh cannot be copied. Use Append (see vcg/complex/append.h) + TetraMesh operator=(const TetraMesh & /*m*/) + { + assert(0); + return TetraMesh(); + } + TetraMesh(const TetraMesh &) {} + +}; // end class Mesh + +/// Initialize the imark-system of the faces +template +inline void InitFaceIMark(MeshType &m) +{ + typename MeshType::FaceIterator f; + + for (f = m.face.begin(); f != m.face.end(); ++f) + if (!(*f).IsD() && (*f).IsR() && (*f).IsW()) + (*f).InitIMark(); +} + +/// Initialize the imark-system of the vertices +template +inline void InitVertexIMark(MeshType &m) +{ + typename MeshType::VertexIterator vi; + + for (vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!(*vi).IsD() && (*vi).IsRW()) + (*vi).InitIMark(); +} + +///initialize the imark-sysyem of the tetras +template +inline void InitTetraIMark(MeshType &m) +{ + typename MeshType::TetraIterator ti; + + for (ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) + if (!(*ti).IsD() && (*ti).IsRW()) + (*ti).InitIMark(); +} +/** \brief Access function to the incremental mark. + You should not use this member directly. In most of the case just use IsMarked() and Mark() +*/ +template +inline int &IMark(MeshType &m) { return m.imark; } + +/** \brief Check if the vertex incremental mark matches the one of the mesh. + @param m the mesh containing the element + @param v Vertex pointer */ +template +inline bool IsMarked(MeshType &m, typename MeshType::ConstVertexPointer v) { return v->cIMark() == m.imark; } + +/** \brief Check if the face incremental mark matches the one of the mesh. + @param m the mesh containing the element + @param f Face pointer */ +template +inline bool IsMarked(MeshType &m, typename MeshType::ConstFacePointer f) { return f->cIMark() == m.imark; } + +/** \brief Check if the tetra incremental mark matches the one of the mesh. + @param m the mesh containing the element + @param t tetra pointer */ +template +inline bool IsMarked(MeshType &m, typename MeshType::ConstTetraPointer t) { return t->cIMark() == m.imark; } + +/** \brief Set the vertex incremental mark of the vertex to the one of the mesh. + @param m the mesh containing the element + @param v Vertex pointer */ +template +inline void Mark(MeshType &m, typename MeshType::VertexPointer v) { v->IMark() = m.imark; } + +/** \brief Set the face incremental mark of the vertex to the one of the mesh. + @param m the mesh containing the element + @param f Vertex pointer */ +template +inline void Mark(MeshType &m, typename MeshType::FacePointer f) { f->IMark() = m.imark; } + +/** \brief Set the tetra incremental mark to the one of the mesh. + @param m the mesh containing the element + @param t tetra pointer */ +template +inline void Mark(MeshType &m, typename MeshType::TetraPointer t) { t->IMark() = m.imark; } + +/** \brief Unmark, in constant time, all the elements (face and vertices) of a mesh. + @param m the mesh containing the element + + In practice this function just increment the internal counter that stores the value for which an element is considered marked; + therefore all the mesh elements become immediately un-mmarked. + */ +template +inline void UnMarkAll(MeshType &m) +{ + ++m.imark; +} + +//template < class CType0, class CType1 , class CType2, class CType3> +//bool HasPerVertexVEAdjacency (const TetraMesh < CType0, CType1, CType2, CType3> & /*m*/) {return TetraMesh < CType0 , CType1, CType2, CType3>::VertContainer::value_type::HasVEAdjacency();} +//template < class CType0, class CType1, class CType2 , class CType3> +//bool HasPerEdgeVEAdjacency (const TetraMesh < CType0, CType1, CType2, CType3> & /*m*/) {return TetraMesh < CType0 , CType1, CType2, CType3>::EdgeContainer::value_type::HasVEAdjacency();} + +//TODO: ADD FT ET ADJACENCY +template +bool VertexVectorHasVFAdjacency(const std::vector &) { return VertexType::HasVFAdjacency(); } +template +bool VertexVectorHasVEAdjacency(const std::vector &) { return VertexType::HasVEAdjacency(); } +template +bool VertexVectorHasVTAdjacency(const std::vector &) { return VertexType::HasVTAdjacency(); } +template +bool EdgeVectorHasVEAdjacency(const std::vector &) { return EdgeType::HasVEAdjacency(); } +template +bool EdgeVectorHasEEAdjacency(const std::vector &) { return EdgeType::HasEEAdjacency(); } +template +bool FaceVectorHasVFAdjacency(const std::vector &) { return FaceType::HasVFAdjacency(); } + +template +bool HasPerVertexVFAdjacency(const TetraMeshType &m) { return tetra::VertexVectorHasVFAdjacency(m.vert); } +template +bool HasPerVertexVEAdjacency(const TetraMeshType &m) { return tetra::VertexVectorHasVEAdjacency(m.vert); } +template +bool HasPerVertexVTAdjacency(const TetraMeshType &m) { return tetra::VertexVectorHasVTAdjacency(m.vert); } +template +bool HasPerEdgeVEAdjacency(const TetraMeshType &m) { return tetra::EdgeVectorHasVEAdjacency(m.edge); } +template +bool HasPerFaceVFAdjacency(const TetraMeshType &m) { return tetra::FaceVectorHasVFAdjacency(m.face); } + +template +bool VertexVectorHasPerVertexQuality(const std::vector &) { return VertexType::HasQuality(); } +template +bool VertexVectorHasPerVertexNormal(const std::vector &) { return VertexType::HasNormal(); } +template +bool VertexVectorHasPerVertexColor(const std::vector &) { return VertexType::HasColor(); } +template +bool VertexVectorHasPerVertexMark(const std::vector &) { return VertexType::HasMark(); } +template +bool VertexVectorHasPerVertexFlags(const std::vector &) { return VertexType::HasFlags(); } +template +bool VertexVectorHasPerVertexRadius(const std::vector &) { return VertexType::HasRadius(); } +template +bool VertexVectorHasPerVertexCurvature(const std::vector &) { return VertexType::HasCurvature(); } +template +bool VertexVectorHasPerVertexCurvatureDir(const std::vector &) { return VertexType::HasCurvatureDir(); } +template +bool VertexVectorHasPerVertexTexCoord(const std::vector &) { return VertexType::HasTexCoord(); } + +template +bool HasPerVertexQuality(const TetraMeshType &m) { return tetra::VertexVectorHasPerVertexQuality(m.vert); } +template +bool HasPerVertexNormal(const TetraMeshType &m) { return tetra::VertexVectorHasPerVertexNormal(m.vert); } +template +bool HasPerVertexColor(const TetraMeshType &m) { return tetra::VertexVectorHasPerVertexColor(m.vert); } +template +bool HasPerVertexMark(const TetraMeshType &m) { return tetra::VertexVectorHasPerVertexMark(m.vert); } +template +bool HasPerVertexFlags(const TetraMeshType &m) { return tetra::VertexVectorHasPerVertexFlags(m.vert); } +template +bool HasPerVertexRadius(const TetraMeshType &m) { return tetra::VertexVectorHasPerVertexRadius(m.vert); } +template +bool HasPerVertexCurvature(const TetraMeshType &m) { return tetra::VertexVectorHasPerVertexCurvature(m.vert); } +template +bool HasPerVertexCurvatureDir(const TetraMeshType &m) { return tetra::VertexVectorHasPerVertexCurvatureDir(m.vert); } +template +bool HasPerVertexTexCoord(const TetraMeshType &m) { return tetra::VertexVectorHasPerVertexTexCoord(m.vert); } + +template +bool EdgeVectorHasPerEdgeQuality(const std::vector &) { return EdgeType::HasQuality(); } +template +bool EdgeVectorHasPerEdgeNormal(const std::vector &) { return EdgeType::HasNormal(); } +template +bool EdgeVectorHasPerEdgeColor(const std::vector &) { return EdgeType::HasColor(); } +template +bool EdgeVectorHasPerEdgeMark(const std::vector &) { return EdgeType::HasMark(); } +template +bool EdgeVectorHasPerEdgeFlags(const std::vector &) { return EdgeType::HasFlags(); } + +template +bool HasPerEdgeQuality(const TetraMeshType &m) { return tetra::EdgeVectorHasPerEdgeQuality(m.edge); } +template +bool HasPerEdgeNormal(const TetraMeshType &m) { return tetra::EdgeVectorHasPerEdgeNormal(m.edge); } +template +bool HasPerEdgeColor(const TetraMeshType &m) { return tetra::EdgeVectorHasPerEdgeColor(m.edge); } +template +bool HasPerEdgeMark(const TetraMeshType &m) { return tetra::EdgeVectorHasPerEdgeMark(m.edge); } +template +bool HasPerEdgeFlags(const TetraMeshType &m) { return tetra::EdgeVectorHasPerEdgeFlags(m.edge); } + +template +bool FaceVectorHasPerWedgeColor(const std::vector &) { return FaceType::HasWedgeColor(); } +template +bool FaceVectorHasPerWedgeNormal(const std::vector &) { return FaceType::HasWedgeNormal(); } +template +bool FaceVectorHasPerWedgeTexCoord(const std::vector &) { return FaceType::HasWedgeTexCoord(); } + +template +bool HasPerWedgeColor(const TetraMeshType &m) { return tetra::FaceVectorHasPerWedgeColor(m.face); } +template +bool HasPerWedgeNormal(const TetraMeshType &m) { return tetra::FaceVectorHasPerWedgeNormal(m.face); } +template +bool HasPerWedgeTexCoord(const TetraMeshType &m) { return tetra::FaceVectorHasPerWedgeTexCoord(m.face); } + +// template +// bool HasPolyInfo(const TetraMesh & /*m*/) { return TetraMesh::FaceContainer::value_type::HasPolyInfo(); } + +template +bool FaceVectorHasPerFaceFlags(const std::vector &) { return FaceType::HasFlags(); } +template +bool FaceVectorHasPerFaceNormal(const std::vector &) { return FaceType::HasNormal(); } +template +bool FaceVectorHasPerFaceColor(const std::vector &) { return FaceType::HasColor(); } +template +bool FaceVectorHasPerFaceMark(const std::vector &) { return FaceType::HasMark(); } +template +bool FaceVectorHasPerFaceQuality(const std::vector &) { return FaceType::HasQuality(); } +template +bool FaceVectorHasFFAdjacency(const std::vector &) { return FaceType::HasFFAdjacency(); } +template +bool FaceVectorHasFEAdjacency(const std::vector &) { return FaceType::HasFEAdjacency(); } +template +bool FaceVectorHasFVAdjacency(const std::vector &) { return FaceType::HasFVAdjacency(); } +template +bool FaceVectorHasPerFaceCurvatureDir(const std::vector &) { return FaceType::HasCurvatureDir(); } + +template +bool HasPerFaceFlags(const TetraMeshType &m) { return tetra::FaceVectorHasPerFaceFlags(m.face); } +template +bool HasPerFaceNormal(const TetraMeshType &m) { return tetra::FaceVectorHasPerFaceNormal(m.face); } +template +bool HasPerFaceColor(const TetraMeshType &m) { return tetra::FaceVectorHasPerFaceColor(m.face); } +template +bool HasPerFaceMark(const TetraMeshType &m) { return tetra::FaceVectorHasPerFaceMark(m.face); } +template +bool HasPerFaceQuality(const TetraMeshType &m) { return tetra::FaceVectorHasPerFaceQuality(m.face); } +template +bool HasPerFaceCurvatureDir(const TetraMeshType &m) { return tetra::FaceVectorHasPerFaceCurvatureDir(m.face); } +template +bool HasFFAdjacency(const TetraMeshType &m) { return tetra::FaceVectorHasFFAdjacency(m.face); } +template +bool HasEEAdjacency(const TetraMeshType &m) { return tetra::EdgeVectorHasEEAdjacency(m.edge); } +template +bool HasFEAdjacency(const TetraMeshType &m) { return tetra::FaceVectorHasFEAdjacency(m.face); } +template +bool HasFVAdjacency(const TetraMeshType &m) { return tetra::FaceVectorHasFVAdjacency(m.face); } + +//:::::::::::TETRA:::::::::::::::: +template +bool TetraVectorHasVTAdjacency(const std::vector &) { return TetraType::HasVTAdjacency(); } + +template +bool HasTVAdjacency(const TetraMeshType &m) { return tetra::TetraVectorHasVTAdjacency(m.tetra); } + +template +bool HasVFAdjacency(const TetraMeshType &m) { return tetra::FaceVectorHasVFAdjacency(m.face) && tetra::VertexVectorHasVFAdjacency(m.vert); } +template +bool HasVEAdjacency(const TetraMeshType &m) { return tetra::EdgeVectorHasVEAdjacency(m.edge) && tetra::VertexVectorHasVEAdjacency(m.vert); } +template +bool HasVTAdjacency(const TetraMeshType &m) { return tetra::VertexVectorHasVTAdjacency(m.vert) && tetra::TetraVectorHasVTAdjacency(m.tetra); } + +//template < class CType0, class CType1, class CType2 , class CType3> +//bool HasVEAdjacency (const TetraMesh < CType0, CType1, CType2, CType3> & /*m*/) {return TetraMesh < CType0 , CType1, CType2, CType3>::VertContainer::value_type::HasVEAdjacency();} + +// template +// bool HasVHAdjacency(const TetraMesh & /*m*/) { return TetraMesh::VertContainer::value_type::HasVHAdjacency(); } + +template +bool HasEVAdjacency(const TetraMesh & /*m*/) { return TetraMesh::EdgeType::HasEVAdjacency(); } + +//template < class CType0, class CType1, class CType2 , class CType3> +//bool HasEEAdjacency (const TetraMesh < CType0, CType1, CType2, CType3> & /*m*/) {return TetraMesh < CType0 , CType1, CType2, CType3>::EdgeType::HasEEAdjacency();} + +template +bool HasEFAdjacency(const TetraMesh & /*m*/) { return TetraMesh::EdgeType::HasEFAdjacency(); } + +// template +// bool HasEHAdjacency(const TetraMesh & /*m*/) { return TetraMesh::EdgeType::HasEHAdjacency(); } + +// template +// bool HasFHAdjacency(const TetraMesh & /*m*/) { return TetraMesh::FaceType::HasFHAdjacency(); } + +// template +// bool HasHVAdjacency(const TetraMesh & /*m*/) { return TetraMesh::HEdgeType::HasHVAdjacency(); } + +// template +// bool HasHEAdjacency(const TetraMesh & /*m*/) { return TetraMesh::HEdgeType::HasHEAdjacency(); } + +// template +// bool HasHFAdjacency(const TetraMesh & /*m*/) { return TetraMesh::HEdgeType::HasHFAdjacency(); } + +// template +// bool HasHNextAdjacency(const TetraMesh & /*m*/) { return TetraMesh::HEdgeType::HasHNextAdjacency(); } + +// template +// bool HasHPrevAdjacency(const TetraMesh & /*m*/) { return TetraMesh::HEdgeType::HasHPrevAdjacency(); } + +// template +// bool HasHOppAdjacency(const TetraMesh & /*m*/) { return TetraMesh::HEdgeType::HasHOppAdjacency(); } + +// //template < class CType0, class CType1 , class CType2, class CType3> +//bool HasVFAdjacency (const TetraMesh < CType0 , CType1, CType2, CType3> & m ) { +// // gcc 4.4: if the expressions assigned to a1 and a2 are replaced in the assert we get a compilation error +// // for the macro assert +// bool a1 = TetraMesh < CType0 , CType1, CType2, CType3>::FaceContainer::value_type::HasVFAdjacency(); +// bool a2 = TetraMesh < CType0 , CType1, CType2, CType3>::VertContainer::value_type::HasVFAdjacency(); +// // a1 and a2 are still evaluated but not referenced, this causes a warning +// (void)a1; +// (void)a2; +// assert(a1==a2); +// +// return vcg::tetra::HasPerVertexVFAdjacency< CType0, CType1 , CType2, CType3>(m) && +// vcg::tetra::HasPerFaceVFAdjacency< CType0, CType1 , CType2, CType3>(m) ; +//} + +template +bool HasPerVertexAttribute(const MeshType &m, std::string name) +{ + typename std::set::const_iterator ai; + typename MeshType::PointerToAttribute h; + h._name = name; + ai = m.vert_attr.find(h); + return (ai != m.vert_attr.end()); +} +template +bool HasPerFaceAttribute(const MeshType &m, std::string name) +{ + typename std::set::const_iterator ai; + typename MeshType::PointerToAttribute h; + h._name = name; + ai = m.face_attr.find(h); + return (ai != m.face_attr.end()); +} + +template +bool HasPerTetraAttribute(const MeshType &m, std::string name) +{ + typename std::set::const_iterator ai; + typename MeshType::PointerToAttribute h; + h._name = name; + ai = m.tetra_attr.find(h); + return (ai != m.tetra_attr.end()); +} + +template +bool HasPerMeshAttribute(const MeshType &m, std::string name) +{ + typename std::set::const_iterator ai; + typename MeshType::PointerToAttribute h; + h._name = name; + ai = m.mesh_attr.find(h); + return (ai != m.mesh_attr.end()); +} + +template +void RequireVertexCompactness(MeshType &m) +{ + if (m.vert.size() != size_t(m.vn)) + throw vcg::MissingCompactnessException("Vertex Vector Contains deleted elements"); +} +template +void RequireFaceCompactness(MeshType &m) +{ + if (m.face.size() != size_t(m.fn)) + throw vcg::MissingCompactnessException("Face Vector Contains deleted elements"); +} +template +void RequireEdgeCompactness(MeshType &m) +{ + if (m.edge.size() != size_t(m.en)) + throw vcg::MissingCompactnessException("Edge Vector Contains deleted elements"); +} + +template +void RequireTetraCompactness(MeshType &m) +{ + if (m.tetra.size() != size_t(m.tn)) + throw vcg::MissingCompactnessException("Tetra Vector Contains deleted elements"); +} + +template +void RequireCompactness(MeshType &m) +{ + RequireVertexCompactness(m); + RequireFaceCompactness(m); + RequireEdgeCompactness(m); + RequireTetraCompactness(m); +} + +template +void RequireTriangularMesh(MeshType &m) +{ + // if (tetra::HasPolyInfo(m)) + throw vcg::MissingTriangularRequirementException(""); +} +template +void RequirePolygonalMesh(MeshType &m) +{ + // if (!tetra::HasPolyInfo(m)) + throw vcg::MissingPolygonalRequirementException(""); +} + +template +void RequireVFAdjacency(MeshType &m) +{ + if (!tetra::HasVFAdjacency(m)) + throw vcg::MissingComponentException("VFAdjacency"); +} +template +void RequireVEAdjacency(MeshType &m) +{ + if (!tetra::HasVEAdjacency(m)) + throw vcg::MissingComponentException("VEAdjacency"); +} +template +void RequireFFAdjacency(MeshType &m) +{ + if (!tetra::HasFFAdjacency(m)) + throw vcg::MissingComponentException("FFAdjacency"); +} +template +void RequireEEAdjacency(MeshType &m) +{ + if (!tetra::HasEEAdjacency(m)) + throw vcg::MissingComponentException("EEAdjacency"); +} +template +void RequireFEAdjacency(MeshType &m) +{ + if (!tetra::HasFEAdjacency(m)) + throw vcg::MissingComponentException("FEAdjacency"); +} +template +void RequireVTAdjacency(MeshType &m) +{ + if (!tetra::HasVTAdjacency(m)) + throw vcg::MissingComponentException("VTAdjacency"); +} +// template +// void RequireFHAdjacency(MeshType &m) +// { +// if (!tetra::HasFHAdjacency(m)) +// throw vcg::MissingComponentException("FHAdjacency"); +// } + +template +void RequirePerVertexQuality(MeshType &m) +{ + if (!tetra::HasPerVertexQuality(m)) + throw vcg::MissingComponentException("PerVertexQuality "); +} +template +void RequirePerVertexNormal(MeshType &m) +{ + if (!tetra::HasPerVertexNormal(m)) + throw vcg::MissingComponentException("PerVertexNormal "); +} +template +void RequirePerVertexColor(MeshType &m) +{ + if (!tetra::HasPerVertexColor(m)) + throw vcg::MissingComponentException("PerVertexColor "); +} +template +void RequirePerVertexMark(MeshType &m) +{ + if (!tetra::HasPerVertexMark(m)) + throw vcg::MissingComponentException("PerVertexMark "); +} +template +void RequirePerVertexFlags(MeshType &m) +{ + if (!tetra::HasPerVertexFlags(m)) + throw vcg::MissingComponentException("PerVertexFlags "); +} +template +void RequirePerVertexRadius(MeshType &m) +{ + if (!tetra::HasPerVertexRadius(m)) + throw vcg::MissingComponentException("PerVertexRadius "); +} +template +void RequirePerVertexCurvature(MeshType &m) +{ + if (!tetra::HasPerVertexCurvature(m)) + throw vcg::MissingComponentException("PerVertexCurvature "); +} +template +void RequirePerVertexCurvatureDir(MeshType &m) +{ + if (!tetra::HasPerVertexCurvatureDir(m)) + throw vcg::MissingComponentException("PerVertexCurvatureDir"); +} +template +void RequirePerVertexTexCoord(MeshType &m) +{ + if (!tetra::HasPerVertexTexCoord(m)) + throw vcg::MissingComponentException("PerVertexTexCoord "); +} + +template +void RequirePerEdgeQuality(MeshType &m) +{ + if (!tetra::HasPerEdgeQuality(m)) + throw vcg::MissingComponentException("PerEdgeQuality "); +} +template +void RequirePerEdgeNormal(MeshType &m) +{ + if (!tetra::HasPerEdgeNormal(m)) + throw vcg::MissingComponentException("PerEdgeNormal "); +} +template +void RequirePerEdgeColor(MeshType &m) +{ + if (!tetra::HasPerEdgeColor(m)) + throw vcg::MissingComponentException("PerEdgeColor "); +} +template +void RequirePerEdgeMark(MeshType &m) +{ + if (!tetra::HasPerEdgeMark(m)) + throw vcg::MissingComponentException("PerEdgeMark "); +} +template +void RequirePerEdgeFlags(MeshType &m) +{ + if (!tetra::HasPerEdgeFlags(m)) + throw vcg::MissingComponentException("PerEdgeFlags "); +} + +template +void RequirePerFaceFlags(MeshType &m) +{ + if (!tetra::HasPerFaceFlags(m)) + throw vcg::MissingComponentException("PerFaceFlags "); +} +template +void RequirePerFaceNormal(MeshType &m) +{ + if (!tetra::HasPerFaceNormal(m)) + throw vcg::MissingComponentException("PerFaceNormal "); +} +template +void RequirePerFaceColor(MeshType &m) +{ + if (!tetra::HasPerFaceColor(m)) + throw vcg::MissingComponentException("PerFaceColor "); +} +template +void RequirePerFaceMark(MeshType &m) +{ + if (!tetra::HasPerFaceMark(m)) + throw vcg::MissingComponentException("PerFaceMark "); +} +template +void RequirePerFaceQuality(MeshType &m) +{ + if (!tetra::HasPerFaceQuality(m)) + throw vcg::MissingComponentException("PerFaceQuality "); +} +template +void RequirePerFaceCurvatureDir(MeshType &m) +{ + if (!tetra::HasPerFaceCurvatureDir(m)) + throw vcg::MissingComponentException("PerFaceCurvatureDir"); +} + +template +void RequirePerFaceWedgeColor(MeshType &m) +{ + if (!tetra::HasPerWedgeColor(m)) + throw vcg::MissingComponentException("PerFaceWedgeColor "); +} +template +void RequirePerFaceWedgeNormal(MeshType &m) +{ + if (!tetra::HasPerWedgeNormal(m)) + throw vcg::MissingComponentException("PerFaceWedgeNormal "); +} +template +void RequirePerFaceWedgeTexCoord(MeshType &m) +{ + if (!tetra::HasPerWedgeTexCoord(m)) + throw vcg::MissingComponentException("PerFaceWedgeTexCoord"); +} + +template +void RequirePerVertexAttribute(MeshType &m, const char *name) +{ + if (!HasPerVertexAttribute(m, name)) + throw vcg::MissingComponentException("PerVertex attribute"); +} +template +void RequirePerEdgeAttribute(MeshType &m, const char *name) +{ + if (!HasPerEdgeAttribute(m, name)) + throw vcg::MissingComponentException("PerEdge attribute"); +} +template +void RequirePerFaceAttribute(MeshType &m, const char *name) +{ + if (!HasPerFaceAttribute(m, name)) + throw vcg::MissingComponentException("PerFace attribute"); +} +template +void RequirePerMeshAttribute(MeshType &m, const char *name) +{ + if (!HasPerMeshAttribute(m, name)) + throw vcg::MissingComponentException("PerMesh attribute"); +} + +/*@}*/ +/*@}*/ +} // end namespace +} // end namespace + +#endif // BASE_H diff --git a/vcg/complex/tetrahedron/complex.h b/vcg/complex/tetrahedron/complex.h new file mode 100644 index 00000000..a2cbecbe --- /dev/null +++ b/vcg/complex/tetrahedron/complex.h @@ -0,0 +1,65 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004-2016 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef __VCG_TETRA_MESH_H +#define __VCG_TETRA_MESH_H +#define __VCG_TETRA_MESH + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef __VCG_TETRA_MESH +#endif + diff --git a/vcg/complex/used_types.h b/vcg/complex/used_types.h index 4741974a..b47cfdbe 100755 --- a/vcg/complex/used_types.h +++ b/vcg/complex/used_types.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,8 @@ #include #include #include +#include +#include #include #include @@ -52,13 +55,14 @@ namespace vcg{ struct _Vertex; struct _Edge ; struct _Face ; +struct _Tetra ; struct _HEdge ; struct DummyTypes{ typedef _Vertex VertexType; // simplex types typedef _Edge EdgeType; typedef _Face FaceType; - typedef char TetraType; + typedef _Tetra TetraType; typedef _HEdge HEdgeType; // connector types typedef vcg::Point3 CoordType; @@ -92,6 +96,7 @@ template