From b662f747a0ac05133af21f9de3469f8aeaae4992 Mon Sep 17 00:00:00 2001 From: "T.Alderighi" Date: Fri, 4 May 2018 12:08:32 +0200 Subject: [PATCH] bootstrapping tetra as trimesh component --- vcg/complex/allocate.h | 548 +++++++++++++++++++++++++++- vcg/complex/append.h | 78 +++- vcg/complex/base.h | 154 +++++++- vcg/complex/complex.h | 2 + vcg/complex/exception.h | 15 + vcg/complex/foreach.h | 46 +++ vcg/container/derivation_chain.h | 14 + vcg/simplex/tetrahedron/component.h | 54 +-- 8 files changed, 854 insertions(+), 57 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index ea5255db..142a105b 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -41,6 +41,9 @@ template size_t Index(MeshType &m, const typename MeshType::EdgeType &e) {return &e-&*m.edge.begin();} template size_t Index(MeshType &m, const typename MeshType::HEdgeType &h) {return &h-&*m.hedge.begin();} +template +size_t Index(MeshType &m, const typename MeshType::TetraType &t) { return &t - &*m.tetra.begin(); } + template size_t Index(MeshType &m, const typename MeshType::VertexType *vp) {return vp-&*m.vert.begin();} @@ -50,6 +53,9 @@ template size_t Index(MeshType &m, const typename MeshType::EdgeType* e) {return e-&*m.edge.begin();} template size_t Index(MeshType &m, const typename MeshType::HEdgeType* h) {return h-&*m.hedge.begin();} +template +size_t Index(MeshType &m, const typename MeshType::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()) ); } @@ -59,6 +65,8 @@ 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::HEdgeType *hp) { return ( m.hedge.size() > 0 && (hp >= &*m.hedge.begin()) && (hp <= &m.hedge.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 */){ @@ -106,8 +114,12 @@ public: typedef typename MeshType::HEdgeIterator HEdgeIterator; typedef typename MeshType::HEdgeContainer HEdgeContainer; - typedef typename MeshType::CoordType CoordType; + 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; @@ -174,9 +186,12 @@ public: static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater &pu) { VertexIterator last; - if(n == 0) return m.vert.end(); + 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 + + 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; @@ -201,9 +216,12 @@ public: for (EdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei) if(!(*ei).IsD()) { - if(HasEVAdjacency (m)) { pu.Update((*ei).V(0)); pu.Update((*ei).V(1));} + // if(HasEVAdjacency (m)) + pu.Update((*ei).V(0)); + pu.Update((*ei).V(1)); // if(HasEVAdjacency(m)) pu.Update((*ei).EVp()); } + HEdgeIterator hi; for (hi=m.hedge.begin(); hi!=m.hedge.end(); ++hi) if(!(*hi).IsD()) @@ -214,6 +232,12 @@ public: } } + 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)); + // e poiche' lo spazio e' cambiato si ricalcola anche last da zero } size_t siz=(size_t)(m.vert.size()-n); @@ -662,6 +686,196 @@ public: return firstNewFace; } + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //:::::::::::::::::TETRAS ADDER FUNCTIONS::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + + /** \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 (TetraIterator 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++; + + v0->P() = p0; + v1->P() = p1; + v2->P() = p2; + v3->P() = p3; + + 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. @@ -709,6 +923,17 @@ public: --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 @@ -745,6 +970,15 @@ public: } else m.vert [ pu.remap[i] ].VEClear(); } + if (HasVTAdjacency(m)) + { + if (m.vert[i].IsVTInitialized()) + { + m.vert[ pu.remap[i] ].VTp() = m.vert[i].cVTp(); + m.vert[ pu.remap[i] ].VTi() = m.vert[i].cVTi(); + } + else m.vert[ pu.remap[i] ].VTClear(); + } } } @@ -774,8 +1008,17 @@ public: 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)) + // Loop on the tetras to update the pointers TV relation (vertex refs) + for(TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) + if(!(*ti).IsD()) + for(int i = 0; i < 4; ++i) + { + size_t oldIndex = (*ti).V(i) - pu.oldBase; + assert(pu.oldBase <= (*ti).V(i) && oldIndex < pu.remap.size()); + (*ti).V(i) = pu.newBase+pu.remap[oldIndex]; + } + // Loop on the edges to update the pointers EV relation (vertex refs) + // if(HasEVAdjacency(m)) for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) if(!(*ei).IsD()) { @@ -784,14 +1027,14 @@ public: } } - static void CompactEveryVector( MeshType &m) + 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) @@ -885,6 +1128,15 @@ public: m.edge[ pu.remap[i] ].EEp(1) = m.edge[i].cEEp(1); m.edge[ pu.remap[i] ].EEi(1) = m.edge[i].cEEi(1); } + if(HasEFAdjacency(m)) +// if (m.edge[i].cEEp(0)!=0) + { + m.edge[ pu.remap[i] ].EFp(0) = m.edge[i].cEFp(0); + m.edge[ pu.remap[i] ].EFi(0) = m.edge[i].cEFi(0); + m.edge[ pu.remap[i] ].EFp(1) = m.edge[i].cEFp(1); + m.edge[ pu.remap[i] ].EFi(1) = m.edge[i].cEFi(1); + } + } } @@ -918,6 +1170,8 @@ public: pu.Update((*ei).VEp(i)); if(HasEEAdjacency(m)) pu.Update((*ei).EEp(i)); + if(HasEFAdjacency(m)) + pu.Update((*ei).EFp(i)); } } @@ -1046,6 +1300,125 @@ public: CompactFaceVector(m,pu); } +/*! + \brief Compact tetra 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 CompactTetraVector(MeshType & m, PointerUpdater & pu) + { + //nothing to do + if (size_t(m.tn) == m.tetra.size()) + return; + + //init the remap + pu.remap.resize(m.tetra.size(), std::numeric_limits::max()); + + //cycle over all the tetras, pos is the last not D() position, I is the index + //when pos != i and !tetra[i].IsD() => we need to compact and update adj + size_t pos = 0; + for (size_t i = 0; i < m.tetra.size(); ++i) + { + if (!m.tetra.IsD()) + { + if (pos != i) + { + //import data + m.tetra[pos].ImportData(m.tetra[i]); + //import vertex refs + for (int j = 0; j < 4; ++j) + m.tetra[pos].V(j) = m.tetra[i].cV(j); + //import VT adj + if (HasVTAdjacency(m)) + for (int j = 0; j < 4; ++j) + { + if (m.tetra[i].IsVTInitialized(j)) + { + m.tetra[pos].VTp(j) = m.tetra[i].VTp(j); + m.tetra[pos].VTi(j) = m.tetra[i].VTi(j); + } + else + m.tetra[pos].VTClear(); + } + //import TT adj + if (HasTTAdjacency(m)) + for (int j = 0; j < 4; ++j) + { + m.tetra[pos].TTp(j) = m.tetra[i].cTTp(j); + m.tetra[pos].TTi(j) = m.tetra[i].cTTi(j); + } + } + //update remapping and advance pos + pu.remap[i] = pos; + ++pos; + } + } + + assert(size_t(m.tn) == pos); + //reorder the optional attributes in m.tetra_attr + ReorderAttribute(m.tetra_attr, pu.remap, m); + // resize the optional atttributes in m.tetra_attr to reflect the changes + ResizeAttribute(m.tetra_attr, m.tn, m); + + // Loop on the tetras to correct VT and TT relations + pu.oldBase = &m.tetra[0]; + pu.oldEnd = &m.tetra.back() + 1; + + m.tetra.resize(m.tn); + pu.newBase = (m.tetra.empty()) ? 0 : &m.tetra[0]; + pu.newEnd = (m.tetra.empty()) ? 0 : &m.tetra.back() + 1; + + TetraPointer tbase = &m.tetra[0]; + + //Loop on the vertices to correct VT relation (since we moved things around) + if (HasVTAdjacency(m)) + { + for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!(*vi).IsD()) + { + if ((*vi).IsVTInitialized() && (*vi).VTp() != 0) + { + size_t oldIndex = (*vi).cVTp() - tbase; + assert(tbase <= (*vi).cVTp() && oldIndex < pu.remap.size()); + (*vi).VTp() = tbase + pu.remap[oldIndex]; + } + } + } + + // Loop on the tetras to correct the VT and TT relations + for (TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) + if (!(*ti).IsD()) + { + //VT + if (HasVTAdjacency(m)) + for (int i = 0; i < 4; ++i) + if ((*ti).IsVTInitialized(i) && (*ti).VTp(i) != 0) + { + size_t oldIndex = (*ti).VTp(i) - fbase; + assert(tbase <= (*ti).VTp(i) && oldIndex < pu.remap.size()); + (*ti).VTp(i) = tbase + pu.remap[oldIndex]; + } + //TT + if (HasTTAdjacency(m)) + for (int i = 0; i < 4; ++i) + if ((*ti).cTTp(i) != 0) + { + size_t oldIndex = (*ti).TTp(i) - tbase; + assert(tbase <= (*ti).TTp(i) && oldIndex < pu.remap.size()); + (*ti).TTp(i) = tbase + pu.remap[oldIndex]; + } + } + } + + /*! \brief Wrapper without the PointerUpdater. */ + static void CompactTetraVector(MeshType &m) + { + PointerUpdater pu; + CompactTetraVector(m, pu); + } public: @@ -1441,6 +1814,136 @@ public: 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 Mesh Attributes template static @@ -1632,7 +2135,36 @@ public: 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){ diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 25d63929..484ed9cb 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -46,19 +46,24 @@ public: typedef typename MeshLeft::EdgeType EdgeLeft; typedef typename MeshLeft::FaceType FaceLeft; typedef typename MeshLeft::HEdgeType HEdgeLeft; + typedef typename MeshLeft::TetraType TetraLeft; typedef typename MeshLeft::VertexPointer VertexPointerLeft; typedef typename MeshLeft::VertexIterator VertexIteratorLeft; typedef typename MeshLeft::EdgeIterator EdgeIteratorLeft; typedef typename MeshLeft::HEdgeIterator HEdgeIteratorLeft; typedef typename MeshLeft::FaceIterator FaceIteratorLeft; + typedef typename MeshLeft::TetraIterator TetraIteratorLeft; - typedef typename ConstMeshRight::ScalarType ScalarRight; - typedef typename ConstMeshRight::CoordType CoordRight; - typedef typename ConstMeshRight::VertexType VertexRight; - typedef typename ConstMeshRight::EdgeType EdgeRight; - typedef typename ConstMeshRight::HEdgeType HEdgeRight; - typedef typename ConstMeshRight::FaceType FaceRight; + typedef typename ConstMeshRight::ScalarType ScalarRight; + typedef typename ConstMeshRight::CoordType CoordRight; + typedef typename ConstMeshRight::VertexType VertexRight; + typedef typename ConstMeshRight::EdgeType EdgeRight; + typedef typename ConstMeshRight::HEdgeType HEdgeRight; + typedef typename ConstMeshRight::FaceType FaceRight; + typedef typename ConstMeshRight::TetraType TetraRight; + typedef typename ConstMeshRight::TetraPointer TetraPointerRight; + typedef typename ConstMeshRight::TetraIterator TetraIteratorRight; typedef typename ConstMeshRight::VertexPointer VertexPointerRight; typedef typename ConstMeshRight::VertexIterator VertexIteratorRight; typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight; @@ -68,7 +73,7 @@ public: struct Remap{ static size_t InvalidIndex() { return std::numeric_limits::max(); } - std::vector vert,face,edge, hedge; + std::vector vert, face, edge, hedge, tetra; }; static void ImportVertexAdj(MeshLeft &ml, ConstMeshRight &mr, VertexLeft &vl, VertexRight &vr, Remap &remap ){ @@ -91,6 +96,13 @@ public: vl.VHp() = &ml.hedge[remap.hedge[Index(mr,vr.cVHp())]]; vl.VHi() = vr.VHi(); } + + // Vertex to Tetra Adj + if(HasVTAdjacency(ml) && HasVTAdjacency(mr) && vr.cVTp() != 0){ + size_t i = Index(mr, vr.cVTp()); + vl.VTp() = (i > ml.edge.size()) ? 0 : &ml.tetra[remap.tetra[i]]; + vl.VTi() = vr.VTi(); + } } static void ImportEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap) @@ -177,6 +189,21 @@ public: hl.HPp() = &ml.hedge[remap.hedge[Index(mr,hr.cHPp())]]; } + static void ImportTetraAdj(MeshLeft &ml, ConstMeshRight &mr, TetraLeft &tl, const TetraRight &tr, Remap &remap ) + { + // Tetra to Tetra Adj + if(HasTTAdjacency(ml) && HasTTAdjacency(mr)){ + assert(tl.TN() == tr.TN()); + for( int vi = 0; vi < 4; ++vi ){ + size_t idx = remap.tetra[Index(mr,tr.cTTp(vi))]; + if(idx != Remap::InvalidIndex()){ + tl.TTp(vi) = &ml.tetra[idx]; + tl.TTi(vi) = tr.cTTi(vi); + } + } + } +} + // Append Right Mesh to the Left Mesh // Append::Mesh(ml, mr) is equivalent to ml += mr. // Note MeshRigth could be costant... @@ -275,6 +302,16 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, (*hp).ImportData(*(hi)); remap.hedge[ind]=Index(ml,*hp); } + + remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex()); + for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) + if (!(*ti).IsD() && (!selected || (*ti).IsS())) { + size_t idx = Index(mr, *ti); + assert (remap.tetra[ind] == Remap::InvalidIndex()); + TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); + (*tp).ImportData(*ti); + remap.tetra[idx] = Index(ml, *tp); + } // phase 2. // copy data from ml to its corresponding elements in ml and adjacencies @@ -324,6 +361,21 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, if(!(*hi).IsD() && (!selected || (*hi).IsS())){ ml.hedge[remap.hedge[Index(mr,*hi)]].ImportData(*hi); ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,*hi)]],*hi,remap,selected); + } + + //tetra + for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) + if(!(*ti).IsD() && (!selected || (*ti).IsS())) + { + TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,*ti)]]; + + if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ + for(int i = 0; i < 4; ++i) + tl.V(i) = &ml.vert[remap.vert[Index(mr,ti->cV(i))]]; + } + tl.ImportData(*ti); + if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,*ti)]], *ti, remap); + } // phase 3. @@ -381,6 +433,18 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, } } + // per tetra attributes + for(al = ml.tetra_attr.begin(); al != ml.tetra_attr.end(); ++al) + if(!(*al)._name.empty()){ + ar = mr.tetra_attr.find(*al); + if(ar!= mr.tetra_attr.end()){ + id_r = 0; + for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti, ++id_r) + if( !(*ti).IsD() && (!selected || (*ti).IsS())) + memcpy((*al)._handle->At(remap.tetra[Index(mr, *ti)]),(*ar)._handle->At(id_r), + (*al)._handle->SizeOf()); + } + } // per mesh attributes // if both ml and mr have an attribute with the same name, no action is done // if mr has an attribute that is NOT present in ml, the attribute is added to ml diff --git a/vcg/complex/base.h b/vcg/complex/base.h index 13bab188..074bac0c 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -62,6 +62,8 @@ namespace tri { typedef std::vector< typename TYPESPOOL::EdgeType > CONTE; typedef std::vector< typename TYPESPOOL::FaceType > CONTF; typedef std::vector< typename TYPESPOOL::HEdgeType > CONTH; + typedef std::vector CONTT; + typedef CONTV VertContainer; typedef typename CONTV::value_type VertexType; @@ -90,6 +92,13 @@ namespace tri { typedef typename CONTH::iterator HEdgeIterator; typedef typename CONTH::const_iterator ConstHEdgeIterator; + 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; + }; @@ -137,7 +146,18 @@ namespace tri { typedef typename HEdgeContainer::value_type * HEdgePointer; typedef typename HEdgeContainer::iterator HEdgeIterator; typedef typename HEdgeContainer::const_iterator ConstHEdgeIterator; -}; + }; + + 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;}; }; @@ -146,15 +166,16 @@ struct DummyContainer{struct value_type{ typedef int IAm;}; }; As explained in \ref basic_concepts, this class is templated over a list of container of simplexes (like vertex, face, edges) */ -template < class Container0 = DummyContainer, class Container1 = DummyContainer, class Container2 = DummyContainer, class Container3 = DummyContainer > +template < class Container0 = DummyContainer, class Container1 = DummyContainer, class Container2 = DummyContainer, class Container3 = DummyContainer, class Container4 = DummyContainer > class TriMesh - : public MArity4< BaseMeshTypeHolder, Container0, Der ,Container1, Der, Container2, Der, Container3, Der>{ + : public MArity5< BaseMeshTypeHolder, Container0, Der ,Container1, Der, Container2, Der, Container3, Der, Container4, Der >{ public: typedef typename TriMesh::ScalarType ScalarType; typedef typename TriMesh::VertContainer VertContainer; typedef typename TriMesh::EdgeContainer EdgeContainer; typedef typename TriMesh::FaceContainer FaceContainer; + typedef typename TriMesh::TetraContainer TetraContainer; // types for vertex typedef typename TriMesh::VertexType VertexType; @@ -184,9 +205,16 @@ class TriMesh typedef typename TriMesh::HEdgeContainer HEdgeContainer; typedef typename TriMesh::ConstHEdgeIterator ConstHEdgeIterator; + // types for tetra + typedef typename TriMesh::TetraType TetraType; + typedef typename TriMesh::TetraPointer TetraPointer; + typedef typename TriMesh::TetraIterator TetraIterator; + typedef typename TriMesh::TetraContainer TetraContainer; + typedef typename TriMesh::ConstTetraIterator ConstTetraIterator; + typedef vcg::PointerToAttribute PointerToAttribute; - typedef TriMesh MeshType; + typedef TriMesh MeshType; typedef Box3 BoxType; @@ -218,6 +246,13 @@ class TriMesh /// Current number of halfedges; inline int HN() const { return hn; } + /// 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; @@ -234,7 +269,7 @@ class TriMesh std::set< PointerToAttribute > edge_attr; std::set< PointerToAttribute > face_attr; std::set< PointerToAttribute > mesh_attr; - + std::set< PointerToAttribute > tetra_attr; template @@ -282,6 +317,14 @@ class TriMesh 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: @@ -309,6 +352,11 @@ class TriMesh 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 @@ -346,12 +394,14 @@ public: 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());} + int MemUsed() const {return Mem(vert.size(),face.size(), tetra.size());} inline int MemNeeded() const {return Mem(vn,fn);} @@ -370,6 +420,7 @@ public: en = 0; fn = 0; hn = 0; + tn = 0; imark = 0; C()=Color4b::Gray; } @@ -391,6 +442,10 @@ public: 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(); @@ -399,7 +454,7 @@ public: bool IsEmpty() const { - return vert.empty() && edge.empty() && face.empty(); + return vert.empty() && edge.empty() && face.empty() && tetra.empty(); } int & SimplexNumber(){ return fn;} @@ -434,6 +489,18 @@ template inline void InitVertexIMark(MeshType & m) 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() */ @@ -449,6 +516,12 @@ template inline bool IsMarked(MeshType & m, typename MeshType:: @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 */ @@ -459,6 +532,12 @@ template inline void Mark(MeshType & m, typename MeshType::Vert @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 @@ -479,13 +558,17 @@ template inline void UnMarkAll(MeshType & m) template < class VertexType> bool VertexVectorHasVFAdjacency (const std::vector &) { return VertexType::HasVFAdjacency(); } template < class VertexType> bool VertexVectorHasVEAdjacency (const std::vector &) { return VertexType::HasVEAdjacency(); } +template < class VertexType> bool VertexVectorHasVTAdjacency (const std::vector &) { return VertexType::HasVTAdjacency(); } template < class EdgeType > bool EdgeVectorHasVEAdjacency (const std::vector &) { return EdgeType::HasVEAdjacency(); } -template < class EdgeType > bool EdgeVectorHasEEAdjacency (const std::vector &) { return EdgeType::HasEEAdjacency(); } +template < class EdgeType > bool EdgeVectorHasEEAdjacency (const std::vector &) { return EdgeType::HasEEAdjacency(); } +template < class EdgeType > bool EdgeVectorHasEFAdjacency (const std::vector &) { return EdgeType::HasEFAdjacency(); } template < class FaceType > bool FaceVectorHasVFAdjacency (const std::vector &) { return FaceType::HasVFAdjacency(); } template < class TriMeshType> bool HasPerVertexVFAdjacency (const TriMeshType &m) { return tri::VertexVectorHasVFAdjacency(m.vert); } template < class TriMeshType> bool HasPerVertexVEAdjacency (const TriMeshType &m) { return tri::VertexVectorHasVEAdjacency(m.vert); } +template < class TriMeshType> bool HasPerVertexVTAdjacency (const TriMeshType &m) { return tetra::VertexVectorHasVTAdjacency(m.vert); } template < class TriMeshType> bool HasPerEdgeVEAdjacency (const TriMeshType &m) { return tri::EdgeVectorHasVEAdjacency (m.edge); } +template < class TriMeshType> bool HasPerEdgeEFAdjacency (const TriMeshType &m) { return tri::EdgeVectorHasEFAdjacency (m.edge); } template < class TriMeshType> bool HasPerFaceVFAdjacency (const TriMeshType &m) { return tri::FaceVectorHasVFAdjacency (m.face); } @@ -549,14 +632,30 @@ template < class TriMeshType> bool HasPerFaceColor (const TriMeshType &m) template < class TriMeshType> bool HasPerFaceMark (const TriMeshType &m) { return tri::FaceVectorHasPerFaceMark (m.face); } template < class TriMeshType> bool HasPerFaceQuality (const TriMeshType &m) { return tri::FaceVectorHasPerFaceQuality (m.face); } template < class TriMeshType> bool HasPerFaceCurvatureDir(const TriMeshType &m) { return tri::FaceVectorHasPerFaceCurvatureDir(m.face); } + + +template < class TetraType> bool TetraVectorHasPerTetraFlags (const std::vector &) { return TetraType::HasFlags (); } +template < class TetraType> bool TetraVectorHasPerTetraColor (const std::vector &) { return TetraType::HasColor (); } +template < class TetraType> bool TetraVectorHasPerTetraMark (const std::vector &) { return TetraType::HasMark (); } +template < class TetraType> bool TetraVectorHasPerTetraQuality(const std::vector &) { return TetraType::HasQuality(); } +template < class TetraType> bool TetraVectorHasVTAdjacency (const std::vector &) { return TetraType::HasVTAdjacency(); } +template < class TetraType> bool TetraVectorHasTTAdjacency (const std::vector &) { return TetraType::HasTTAdjacency(); } + +template < class TriMeshType> bool HasPerTetraFlags (const TriMeshType &m) { return tri::FaceVectorHasPerTetraFlags (m.face); } +template < class TriMeshType> bool HasPerTetraColor (const TriMeshType &m) { return tri::FaceVectorHasPerTetraColor (m.face); } +template < class TriMeshType> bool HasPerTetraMark (const TriMeshType &m) { return tri::FaceVectorHasPerTetraMark (m.face); } +template < class TriMeshType> bool HasPerTetraQuality (const TriMeshType &m) { return tri::FaceVectorHasPerTetraQuality (m.face); } + template < class TriMeshType> bool HasFFAdjacency (const TriMeshType &m) { return tri::FaceVectorHasFFAdjacency (m.face); } template < class TriMeshType> bool HasEEAdjacency (const TriMeshType &m) { return tri::EdgeVectorHasEEAdjacency (m.edge); } template < class TriMeshType> bool HasFEAdjacency (const TriMeshType &m) { return tri::FaceVectorHasFEAdjacency (m.face); } +template < class TriMeshType> bool HasEFAdjacency (const TriMeshType &m) { return tri::FaceVectorHasFEAdjacency(m.face) && tri::EdgeVectorHasEFAdjacency(m.edge); } template < class TriMeshType> bool HasFVAdjacency (const TriMeshType &m) { return tri::FaceVectorHasFVAdjacency (m.face); } - template < class TriMeshType> bool HasVFAdjacency (const TriMeshType &m) { return tri::FaceVectorHasVFAdjacency (m.face) && tri::VertexVectorHasVFAdjacency(m.vert); } template < class TriMeshType> bool HasVEAdjacency (const TriMeshType &m) { return tri::EdgeVectorHasVEAdjacency (m.edge) && tri::VertexVectorHasVEAdjacency(m.vert); } - +template < class TriMeshType> bool HasTVAdjacency (const TriMeshType &m) { return tri::TetraVectorHasVTAdjacency(m.tetra); } +template < class TriMeshType> bool HasVTAdjacency (const TriMeshType &m) { return tri::VertexVectorHasVTAdjacency(m.vert) && tri::TetraVectorHasVTAdjacency(m.tetra); } +template < class TriMeshType> bool HasTTAdjacency (const TriMeshType &m) { return tri::TetraVectorHasTTAdjacency(m.tetra); } //template < class CType0, class CType1, class CType2 , class CType3> @@ -630,6 +729,16 @@ bool HasPerFaceAttribute(const MeshType &m, std::string name){ 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< typename MeshType::PointerToAttribute>::const_iterator ai; @@ -648,13 +757,20 @@ template void RequireFaceCompactness (MeshType &m) { template void RequireEdgeCompactness (MeshType &m) { if(m.edge.size()!=size_t(m.en)) throw vcg::MissingCompactnessException("Edge Vector Contains deleted elements"); } - -template void RequireCompactness (MeshType &m) { - RequireVertexCompactness(m); - RequireFaceCompactness (m); - RequireEdgeCompactness (m); +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); +} + +//todo require tetramesh template void RequireTriangularMesh (MeshType &m ) { if( tri::HasPolyInfo( m ) ) throw vcg::MissingTriangularRequirementException("");} template void RequirePolygonalMesh (MeshType &m ) { if(!tri::HasPolyInfo( m ) ) throw vcg::MissingPolygonalRequirementException("");} @@ -664,6 +780,8 @@ template void RequireFFAdjacency (MeshType &m) { if(!tri::Ha template void RequireEEAdjacency (MeshType &m) { if(!tri::HasEEAdjacency (m)) throw vcg::MissingComponentException("EEAdjacency"); } template void RequireFEAdjacency (MeshType &m) { if(!tri::HasFEAdjacency (m)) throw vcg::MissingComponentException("FEAdjacency"); } template void RequireFHAdjacency (MeshType &m) { if(!tri::HasFHAdjacency (m)) throw vcg::MissingComponentException("FHAdjacency"); } +template void RequireVTAdjacency (MeshType &m) { if(!tri::HasVTAdjacency (m)) throw vcg::MissingComponentException("VTAdjacency"); } +template void RequireTTAdjacency (MeshType &m) { if(!tri::HasTTAdjacency (m)) throw vcg::MissingComponentException("TTAdjacency"); } template void RequirePerVertexQuality (MeshType &m) { if(!tri::HasPerVertexQuality (m)) throw vcg::MissingComponentException("PerVertexQuality "); } template void RequirePerVertexNormal (MeshType &m) { if(!tri::HasPerVertexNormal (m)) throw vcg::MissingComponentException("PerVertexNormal "); } @@ -692,9 +810,15 @@ template void RequirePerFaceWedgeColor (MeshType &m) { if(!tr template void RequirePerFaceWedgeNormal (MeshType &m) { if(!tri::HasPerWedgeNormal (m)) throw vcg::MissingComponentException("PerFaceWedgeNormal "); } template void RequirePerFaceWedgeTexCoord(MeshType &m) { if(!tri::HasPerWedgeTexCoord(m)) throw vcg::MissingComponentException("PerFaceWedgeTexCoord"); } +template void RequirePerTetraFlags (MeshType &m) { if(!tri::HasPerTetraFlags (m)) throw vcg::MissingComponentException("PerTetraFlags "); } +template void RequirePerTetraColor (MeshType &m) { if(!tri::HasPerTetraColor (m)) throw vcg::MissingComponentException("PerTetraColor "); } +template void RequirePerTetraMark (MeshType &m) { if(!tri::HasPerTetraMark (m)) throw vcg::MissingComponentException("PerTetraMark "); } +template void RequirePerTetraQuality (MeshType &m) { if(!tri::HasPerTetraQuality (m)) throw vcg::MissingComponentException("PerTetraQuality "); } + 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 RequirePerTetraAttribute(MeshType &m, const char *name) { if(!HasPerTetraAttribute(m,name)) throw vcg::MissingComponentException("PerTetra attribute"); } template void RequirePerMeshAttribute(MeshType &m, const char *name) { if(!HasPerMeshAttribute(m,name)) throw vcg::MissingComponentException("PerMesh attribute"); } /*@}*/ diff --git a/vcg/complex/complex.h b/vcg/complex/complex.h index ebc3dc1e..f8745bca 100644 --- a/vcg/complex/complex.h +++ b/vcg/complex/complex.h @@ -50,6 +50,8 @@ #include #include #include +#include +// #include #include #include #include diff --git a/vcg/complex/exception.h b/vcg/complex/exception.h index f98446eb..b42c4c37 100644 --- a/vcg/complex/exception.h +++ b/vcg/complex/exception.h @@ -83,6 +83,21 @@ public: } }; +class MissingTetrahedralRequirementException : public std::runtime_error +{ +public: + MissingTetrahedralRequirementException(const std::string &err):std::runtime_error(err) + { + std::cout << "Mesh has to be composed by tetrahedras -" << err << "- \n"; + } + + virtual const char *what() const throw () + { + static char buf[128]="Mesh has to be composed by tetrahedras"; + return buf; + } +}; + class MissingPreconditionException : public std::runtime_error { public: diff --git a/vcg/complex/foreach.h b/vcg/complex/foreach.h index 530a63fd..aa94b4f4 100644 --- a/vcg/complex/foreach.h +++ b/vcg/complex/foreach.h @@ -156,7 +156,53 @@ inline void ForEachEdge(MeshType &m, std::function +inline void ForEachTetra(const MeshType &m, std::function action) +{ + if(m.tn == (int) m.tetra.size()) + { + for(auto ti = m.tetra.begin(); ti! = m.tetra.end(); ++ti) { + action(*ti); + } + } + else + { + for(auto ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) + if(!(*ti).IsD()) + { + action(*ti); + } + } +} + +template +inline void ForEachTetra(MeshType &m, std::function action) +{ + if(m.tn == (int) m.tetra.size()) + { + for(auto ti = m.tetra.begin(); ti! = m.tetra.end(); ++ti) { + action(*ti); + } + } + else + { + for(auto ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) + if(!(*ti).IsD()) + { + action(*ti); + } + } +} /** @} */ // end doxygen group trimesh } // end namespace tri diff --git a/vcg/container/derivation_chain.h b/vcg/container/derivation_chain.h index 13667b2f..a73ed2c4 100644 --- a/vcg/container/derivation_chain.h +++ b/vcg/container/derivation_chain.h @@ -173,6 +173,20 @@ template < template class D> class MArity4: public D,TD > {}; +template < + class Base, + class TA, + template class A, + class TB, + template class B, + class TC, + template class C, + class TD, + template class D, + class TE, + template class E> + class MArity5: public E, TE> {}; + class DumClass {}; diff --git a/vcg/simplex/tetrahedron/component.h b/vcg/simplex/tetrahedron/component.h index 862d521e..815f39c1 100644 --- a/vcg/simplex/tetrahedron/component.h +++ b/vcg/simplex/tetrahedron/component.h @@ -55,13 +55,13 @@ public: static bool HasVertexRef() { return false; } static bool HasTVAdjacency() { return false; } - //Empty normals - typedef typename T::VertexType::NormalType NormalType; - NormalType &N(const int & ){ static NormalType dummynormal(0, 0, 0); assert(0); return dummynormal; } - const NormalType cN(const int & ) const { static NormalType dummynormal(0, 0, 0); assert(0); return dummynormal; } + // //Empty normals + // typedef typename T::VertexType::NormalType NormalType; + // NormalType &N(const int & ){ static NormalType dummynormal(0, 0, 0); assert(0); return dummynormal; } + // const NormalType cN(const int & ) const { static NormalType dummynormal(0, 0, 0); assert(0); return dummynormal; } - static bool HasFaceNormal() { return false; } - static bool HasFaceNormalOcc() { return false; } + // static bool HasFaceNormal() { return false; } + // static bool HasFaceNormalOcc() { return false; } //Empty color typedef vcg::Color4b ColorType; @@ -223,33 +223,33 @@ public: // }; -template class FaceNormal: public T { -public: - typedef A NormalType; +// template class FaceNormal: public T { +// public: +// typedef A NormalType; - inline NormalType N(const int & i){ assert((i>=0)&&(i < 4)); return _facenormals[i]; } - inline NormalType cN(const int & i) const { assert((i>=0)&&(i < 4)); return _facenormals[i]; } - static bool HasFaceNormals() { return true; } - static bool HasFaceNormalOcc() { return false; } +// inline NormalType N(const int & i){ assert((i>=0)&&(i < 4)); return _facenormals[i]; } +// inline NormalType cN(const int & i) const { assert((i>=0)&&(i < 4)); return _facenormals[i]; } +// static bool HasFaceNormals() { return true; } +// static bool HasFaceNormalOcc() { return false; } - template - void ImportData(const RightValueType & rightT) - { - if(rightT.IsNormalEnabled()) N().Import(rightT.cN()); - T::ImportData(rightT); - } +// template +// void ImportData(const RightValueType & rightT) +// { +// if(rightT.IsNormalEnabled()) N().Import(rightT.cN()); +// T::ImportData(rightT); +// } - static void Name(std::vector & name){name.push_back(std::string("FaceNormal"));T::Name(name);} +// static void Name(std::vector & name){name.push_back(std::string("FaceNormal"));T::Name(name);} -private: - NormalType _facenormals[4]; -}; +// private: +// NormalType _facenormals[4]; +// }; -template class FaceNormal3f: public FaceNormal{ -public:static void Name(std::vector & name){name.push_back(std::string("FaceNormal3f"));T::Name(name);} }; +//template class FaceNormal3f: public FaceNormal{ +//public:static void Name(std::vector & name){name.push_back(std::string("FaceNormal3f"));T::Name(name);} }; -template class FaceNormal3d: public FaceNormal{ -public:static void Name(std::vector & name){name.push_back(std::string("FaceNormal3d"));T::Name(name);} }; +//template class FaceNormal3d: public FaceNormal{ +//public:static void Name(std::vector & name){name.push_back(std::string("FaceNormal3d"));T::Name(name);} }; /*------------------------- FLAGS -----------------------------------------*/ // template class EmptyBitFlags: public T {