diff --git a/vcg/complex/algorithms/update/selection.h b/vcg/complex/algorithms/update/selection.h index ae9d4d04..221db704 100644 --- a/vcg/complex/algorithms/update/selection.h +++ b/vcg/complex/algorithms/update/selection.h @@ -183,6 +183,7 @@ typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::EdgeIterator EdgeIterator; +typedef typename MeshType::EdgeType EdgeType; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; @@ -269,39 +270,41 @@ static void Clear(MeshType &m) } /// \brief This function returns the number of selected faces. -static size_t FaceCount(MeshType &m) +static size_t FaceCount(const MeshType &m) { size_t selCnt=0; - for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) - if(!(*fi).IsD() && (*fi).IsS()) ++selCnt; + ForEachFace(m, [&](const FaceType& f){ + if(f.IsS()) ++selCnt; + }); return selCnt; } /// \brief This function returns the number of selected edges. -static size_t EdgeCount(MeshType &m) +static size_t EdgeCount(const MeshType &m) { size_t selCnt=0; - for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) - if(!(*ei).IsD() && (*ei).IsS()) ++selCnt; + ForEachEdge(m, [&](const EdgeType& e){ + if(e.IsS()) ++selCnt; + }); return selCnt; } /// \brief This function returns the number of selected vertices. -static size_t VertexCount(MeshType &m) +static size_t VertexCount(const MeshType &m) { size_t selCnt=0; - for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) - if(!(*vi).IsD() && (*vi).IsS()) ++selCnt; + ForEachVertex(m, [&](const VertexType& v){ + if(v.IsS()) ++selCnt; + }); return selCnt; } /// \brief This function returns the number of selected tetras. -static size_t TetraCount (MeshType & m) +static size_t TetraCount (const MeshType & m) { size_t selCnt = 0; - ForEachTetra(m, [&selCnt] (TetraType & t) { - if (t.IsS()) - ++selCnt; + ForEachTetra(m, [&] (const TetraType & t) { + if (t.IsS()) ++selCnt; }); return selCnt; diff --git a/vcg/complex/append.h b/vcg/complex/append.h index 047214f9..02580a4b 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -76,7 +76,7 @@ public: std::vector vert, face, edge, hedge, tetra; }; - static void ImportVertexAdj(MeshLeft &ml, ConstMeshRight &mr, VertexLeft &vl, VertexRight &vr, Remap &remap ){ + static void ImportVertexAdj(MeshLeft &ml, const ConstMeshRight &mr, VertexLeft &vl, const VertexRight &vr, Remap &remap ){ // Vertex to Edge Adj if(HasVEAdjacency(ml) && HasVEAdjacency(mr) && vr.cVEp() != 0){ size_t i = Index(mr,vr.cVEp()); @@ -105,7 +105,7 @@ public: } } - static void ImportEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap) + static void ImportEdgeAdj(MeshLeft &ml, const ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap) { // Edge to Edge Adj if(HasEEAdjacency(ml) && HasEEAdjacency(mr)) @@ -129,7 +129,7 @@ public: } - static void ImportFaceAdj(MeshLeft &ml, ConstMeshRight &mr, FaceLeft &fl, const FaceRight &fr, Remap &remap ) + static void ImportFaceAdj(MeshLeft &ml, const ConstMeshRight &mr, FaceLeft &fl, const FaceRight &fr, Remap &remap ) { // Face to Edge Adj if(HasFEAdjacency(ml) && HasFEAdjacency(mr)){ @@ -183,7 +183,7 @@ public: fl.FHp() = &ml.hedge[remap.hedge[Index(mr,fr.cFHp())]]; } - static void ImportHEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, HEdgeLeft &hl, const HEdgeRight &hr, Remap &remap, bool /*sel*/ ){ + static void ImportHEdgeAdj(MeshLeft &ml, const ConstMeshRight &mr, HEdgeLeft &hl, const HEdgeRight &hr, Remap &remap, bool /*sel*/ ){ // HEdge to Vertex Adj if(HasHVAdjacency(ml) && HasHVAdjacency(mr)) hl.HVp() = &ml.vert[remap.vert[Index(mr,hr.cHVp())]]; @@ -214,7 +214,7 @@ 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 ) + static void ImportTetraAdj(MeshLeft &ml, const ConstMeshRight &mr, TetraLeft &tl, const TetraRight &tr, Remap &remap ) { // Tetra to Tetra Adj if(HasTTAdjacency(ml) && HasTTAdjacency(mr)){ @@ -476,6 +476,270 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, // } } +/** + * @brief MeshAppendConst + * @param ml + * @param mr + * + * This is function is similar with the Mesh function, but does not + * never update selections. In some cases, after the append, + * selection of vertices may be inconsistent with face selection, + * as explained above. + * To avoid this, before using this function, call the following functions: + * + * \code{.cpp} + * vcg::tri::UpdateSelection::VertexFromEdgeLoose(mr,true); + * vcg::tri::UpdateSelection::VertexFromFaceLoose(mr,true); + * \endcode + * + * or, use the Mesh function that takes a non-const Right Mesh argument. + */ +static void MeshAppendConst( + MeshLeft& ml, + const ConstMeshRight& mr, + const bool selected = false, + const bool adjFlag = false) +{ + // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr + // and build the remapping for all + + Remap remap; + + // vertex + remap.vert.resize(mr.vert.size(), Remap::InvalidIndex()); + VertexIteratorLeft vp; + size_t svn = UpdateSelection::VertexCount(mr); + if(selected) + vp=Allocator::AddVertices(ml,int(svn)); + else + vp=Allocator::AddVertices(ml,mr.vn); + + ForEachVertex(mr, [&](const VertexRight& v) + { + if(!selected || v.IsS()) + { + size_t ind=Index(mr,v); + remap.vert[ind]=int(Index(ml,*vp)); + ++vp; + } + }); + // edge + remap.edge.resize(mr.edge.size(), Remap::InvalidIndex()); + EdgeIteratorLeft ep; + size_t sen = UpdateSelection::EdgeCount(mr); + if(selected) ep=Allocator::AddEdges(ml,sen); + else ep=Allocator::AddEdges(ml,mr.en); + + ForEachEdge(mr, [&](const EdgeRight& e) + { + if(!selected || e.IsS()){ + size_t ind=Index(mr,e); + remap.edge[ind]=int(Index(ml,*ep)); + ++ep; + } + }); + + // face + remap.face.resize(mr.face.size(), Remap::InvalidIndex()); + FaceIteratorLeft fp; + size_t sfn = UpdateSelection::FaceCount(mr); + if(selected) fp=Allocator::AddFaces(ml,sfn); + else fp=Allocator::AddFaces(ml,mr.fn); + + ForEachFace(mr, [&](const FaceRight& f) + { + if(!selected || f.IsS()){ + size_t ind=Index(mr,f); + remap.face[ind]=int(Index(ml,*fp)); + ++fp; + } + }); + + // hedge + remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex()); + + ForEachHEdge(mr, [&](const HEdgeRight& he) + { + if(!selected || he.IsS()){ + size_t ind=Index(mr,he); + assert(remap.hedge[ind]==Remap::InvalidIndex()); + HEdgeIteratorLeft hp = Allocator::AddHEdges(ml,1); + (*hp).ImportData(he); + remap.hedge[ind]=Index(ml,*hp); + } + }); + + remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex()); + + ForEachTetra(mr, [&](const TetraRight& t) + { + if (!selected || t.IsS()) { + size_t idx = Index(mr, t); + assert (remap.tetra[idx] == Remap::InvalidIndex()); + TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); + (*tp).ImportData(t); + remap.tetra[idx] = Index(ml, *tp); + } + }); + + // phase 2. + // copy data from mr to its corresponding elements in ml and adjacencies + + // vertex + ForEachVertex(mr, [&](const VertexRight& v) + { + if(!selected || v.IsS()){ + ml.vert[remap.vert[Index(mr,v)]].ImportData(v); + if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,v)]],v,remap); + } + }); + + // edge + ForEachEdge(mr, [&](const EdgeRight& e) + { + if(!selected || e.IsS()){ + ml.edge[remap.edge[Index(mr,e)]].ImportData(e); + // Edge to Vertex Adj + EdgeLeft &el = ml.edge[remap.edge[Index(mr,e)]]; + if(HasEVAdjacency(ml) && HasEVAdjacency(mr)){ + el.V(0) = &ml.vert[remap.vert[Index(mr,e.cV(0))]]; + el.V(1) = &ml.vert[remap.vert[Index(mr,e.cV(1))]]; + } + if(adjFlag) ImportEdgeAdj(ml,mr,el,e,remap); + } + }); + + // face + const size_t textureOffset = ml.textures.size(); + bool WTFlag = HasPerWedgeTexCoord(mr) && (textureOffset>0); + ForEachFace(mr, [&](const FaceRight& f) + { + if(!selected || f.IsS()) + { + FaceLeft &fl = ml.face[remap.face[Index(mr,f)]]; + fl.Alloc(f.VN()); + if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ + for(int i = 0; i < fl.VN(); ++i) + fl.V(i) = &ml.vert[remap.vert[Index(mr,f.cV(i))]]; + } + fl.ImportData(f); + if(WTFlag) + for(int i = 0; i < fl.VN(); ++i) + fl.WT(i).n() += short(textureOffset); + if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,f)]],f,remap); + + } + }); + + // hedge + ForEachHEdge(mr, [&](const HEdgeRight& he) + { + if(!selected || he.IsS()){ + ml.hedge[remap.hedge[Index(mr,he)]].ImportData(he); + ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,he)]],he,remap,selected); + } + }); + + //tetra + ForEachTetra(mr, [&](const TetraRight& t) + { + if(!selected || t.IsS()) + { + TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,t)]]; + + if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ + for(int i = 0; i < 4; ++i) + tl.V(i) = &ml.vert[remap.vert[Index(mr,t.cV(i))]]; + } + tl.ImportData(t); + if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,t)]], t, remap); + + } + }); + + // phase 3. + // take care of other per mesh data: textures, attributes + + // At the end concatenate the vector with texture names. + ml.textures.insert(ml.textures.end(),mr.textures.begin(),mr.textures.end()); + + // Attributes. Copy only those attributes that are present in both meshes + // Two attributes in different meshes are considered the same if they have the same + // name and the same type. This may be deceiving because they could in fact have + // different semantic, but this is up to the developer. + // If the left mesh has attributes that are not in the right mesh, their values for the elements + // of the right mesh will be uninitialized + + unsigned int id_r; + typename std::set< PointerToAttribute >::iterator al, ar; + + // per vertex attributes + for(al = ml.vert_attr.begin(); al != ml.vert_attr.end(); ++al) + if(!(*al)._name.empty()){ + ar = mr.vert_attr.find(*al); + if(ar!= mr.vert_attr.end()){ + id_r = 0; + for (auto v: mr.vert){ + if( !v.IsD() && (!selected || v.IsS())) + (*al)._handle->CopyValue(remap.vert[Index(mr,v)], id_r, (*ar)._handle); + ++id_r; + } + } + } + + // per edge attributes + for(al = ml.edge_attr.begin(); al != ml.edge_attr.end(); ++al) + if(!(*al)._name.empty()){ + ar = mr.edge_attr.find(*al); + if(ar!= mr.edge_attr.end()){ + id_r = 0; + for (auto e: mr.edge){ + if( !e.IsD() && (!selected || e.IsS())) + (*al)._handle->CopyValue(remap.edge[Index(mr,e)], id_r, (*ar)._handle); + ++id_r; + } + } + } + + // per face attributes + for(al = ml.face_attr.begin(); al != ml.face_attr.end(); ++al) + if(!(*al)._name.empty()){ + ar = mr.face_attr.find(*al); + if(ar!= mr.face_attr.end()){ + id_r = 0; + for (auto f: mr.face) { + if( !f.IsD() && (!selected || f.IsS())) + (*al)._handle->CopyValue(remap.face[Index(mr,f)], id_r, (*ar)._handle); + ++id_r; + } + } + } + + // 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 (auto t: mr.tetra) { + if( !t.IsD() && (!selected || t.IsS())) + (*al)._handle->CopyValue(remap.tetra[Index(mr, t)], id_r, (*ar)._handle); + ++id_r; + } + } + } + + // 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 + //for(ar = mr.mesh_attr.begin(); ar != mr.mesh_attr.end(); ++ar) + // if(!(*ar)._name.empty()){ + // al = ml.mesh_attr.find(*ar); + // if(al== ml.mesh_attr.end()) + // //... + // } +} + /*! \brief Copy the second mesh over the first one. The first mesh is destroyed. If requested only the selected elements are copied. */ @@ -485,6 +749,13 @@ static void MeshCopy(MeshLeft& ml, ConstMeshRight& mr, bool selected=false, cons Mesh(ml,mr,selected,adjFlag); ml.bbox.Import(mr.bbox); } + +static void MeshCopyConst(MeshLeft& ml, const ConstMeshRight& mr, bool selected=false, const bool adjFlag = false) +{ + ml.Clear(); + MeshAppendConst(ml,mr,selected,adjFlag); + ml.bbox.Import(mr.bbox); +} /*! \brief %Append only the selected elements of second mesh to the first one. It is just a wrap of the main Append::Mesh() diff --git a/vcg/complex/foreach.h b/vcg/complex/foreach.h index 156d3489..a062e41c 100644 --- a/vcg/complex/foreach.h +++ b/vcg/complex/foreach.h @@ -34,8 +34,24 @@ namespace tri { @{ */ -template -inline void ForEachFacePos(MeshType &m, std::function &)> action) +template +inline void ForEachFacePos(const MeshType &m, Callable action) +{ + typedef typename face::Pos PosType; + + for(auto fi=m.face.begin();fi!=m.face.end();++fi) + if(!(*fi).IsD()) + { + for(int i=0;i<3;++i) + { + PosType pi(&*fi,i); + action(pi); + } + } +} + +template +inline void ForEachFacePos(MeshType &m, Callable action) { typedef typename face::Pos PosType; @@ -60,8 +76,8 @@ inline void ForEachFacePos(MeshType &m, std::function -inline void ForEachFace(const MeshType &m, std::function action) +template +inline void ForEachFace(const MeshType &m, Callable action) { if(m.fn == (int) m.face.size()) { @@ -79,8 +95,8 @@ inline void ForEachFace(const MeshType &m, std::function -inline void ForEachFace(MeshType &m, std::function action) +template +inline void ForEachFace(MeshType &m, Callable action) { if(m.fn == (int) m.face.size()) { @@ -108,8 +124,27 @@ inline void ForEachFace(MeshType &m, std::function -inline void ForEachVertex(MeshType &m, std::function action) +template +inline void ForEachVertex(const MeshType &m, Callable action) +{ + if(m.vn == (int) m.vert.size()) + { + for(auto vi=m.vert.begin();vi!=m.vert.end();++vi) { + action(*vi); + } + } + else + { + for(auto vi=m.vert.begin();vi!=m.vert.end();++vi) + if(!(*vi).IsD()) + { + action(*vi); + } + } +} + +template +inline void ForEachVertex(MeshType &m, Callable action) { if(m.vn == (int) m.vert.size()) { @@ -127,6 +162,54 @@ inline void ForEachVertex(MeshType &m, std::function +inline void ForEachHEdge(const MeshType &m, Callable action) +{ + if(m.hn == (int) m.hedge.size()) + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) { + action(*hei); + } + } + else + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) + if(!(*hei).IsD()) + { + action(*hei); + } + } +} + +template +inline void ForEachHEdge(MeshType &m, Callable action) +{ + if(m.hn == (int) m.hedge.size()) + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) { + action(*hei); + } + } + else + { + for(auto hei=m.hedge.begin();hei!=m.hedge.end();++hei) + if(!(*hei).IsD()) + { + action(*hei); + } + } +} + /** * ForEachEdge Helper * to traverse all the vertexes of a mesh you can simply write something like: @@ -137,8 +220,27 @@ inline void ForEachVertex(MeshType &m, std::function -inline void ForEachEdge(MeshType &m, std::function action) +template +inline void ForEachEdge(const MeshType &m, Callable action) +{ + if(m.en == (int) m.edge.size()) + { + for(auto ei=m.edge.begin();ei!=m.edge.end();++ei) { + action(*ei); + } + } + else + { + for(auto ei=m.edge.begin();ei!=m.edge.end();++ei) + if(!(*ei).IsD()) + { + action(*ei); + } + } +} + +template +inline void ForEachEdge(MeshType &m, Callable action) { if(m.en == (int) m.edge.size()) { @@ -166,8 +268,8 @@ inline void ForEachEdge(MeshType &m, std::function -inline void ForEachTetra(const MeshType &m, std::function action) +template +inline void ForEachTetra(const MeshType &m, Callable action) { if(m.tn == (int) m.tetra.size()) { @@ -185,8 +287,8 @@ inline void ForEachTetra(const MeshType &m, std::function -inline void ForEachTetra(MeshType &m, std::function action) +template +inline void ForEachTetra(MeshType &m, Callable action) { if(m.tn == (int) m.tetra.size()) { diff --git a/vcg/simplex/edge/component.h b/vcg/simplex/edge/component.h index a78ca4c6..69d32765 100644 --- a/vcg/simplex/edge/component.h +++ b/vcg/simplex/edge/component.h @@ -78,6 +78,7 @@ public: typename T::EdgePointer &VEp(const int & ) { static typename T::EdgePointer ep=0; assert(0); return ep; } typename T::EdgePointer cVEp(const int & ) const { static typename T::EdgePointer ep=0; assert(0); return ep; } int &VEi(const int &){static int z=0; assert(0); return z;} + int VEi(const int &) const {static int z=0; assert(0); return z;} int cVEi(const int &) const {static int z=0; assert(0); return z;} static bool HasVEAdjacency() { return false; } @@ -278,6 +279,7 @@ public: typename T::EdgePointer &VEp(const int & i) {return _ep[i]; } typename T::EdgePointer cVEp(const int & i) const {return _ep[i]; } int &VEi(const int & i){ return _zp[i];} + int VEi(const int & i)const {return _zp[i];} int cVEi(const int &i )const {return _zp[i];} template < class LeftV> diff --git a/vcg/simplex/face/component.h b/vcg/simplex/face/component.h index ebdc3739..da731066 100644 --- a/vcg/simplex/face/component.h +++ b/vcg/simplex/face/component.h @@ -114,6 +114,7 @@ public: typename T::HEdgePointer &FHp() { static typename T::HEdgePointer fp=0; assert(0); return fp; } typename T::HEdgePointer cFHp() const { static typename T::HEdgePointer fp=0; assert(0); return fp; } char &VFi(int) { static char z=0; assert(0); return z;} + char VFi(int) const { static char z=0; assert(0); return z;} char &FFi(int) { static char z=0; assert(0); return z;} char cVFi(int) const { static char z=0; assert(0); return z;} char cFFi(int) const { static char z=0; assert(0); return z;} diff --git a/vcg/simplex/face/component_ocf.h b/vcg/simplex/face/component_ocf.h index bf4c3fb1..a09e84f7 100644 --- a/vcg/simplex/face/component_ocf.h +++ b/vcg/simplex/face/component_ocf.h @@ -408,6 +408,11 @@ public: return (*this).Base().AV[(*this).Index()]._zp[j]; } + char VFi(const int j) const { + assert((*this).Base().VFAdjacencyEnabled); + return (*this).Base().AV[(*this).Index()]._zp[j]; + } + char cVFi(const int j) const { assert((*this).Base().VFAdjacencyEnabled); return (*this).Base().AV[(*this).Index()]._zp[j]; diff --git a/vcg/simplex/face/component_polygon.h b/vcg/simplex/face/component_polygon.h index dde27016..8ac67f47 100644 --- a/vcg/simplex/face/component_polygon.h +++ b/vcg/simplex/face/component_polygon.h @@ -136,6 +136,7 @@ public: typename T::FacePointer const VFp(const int j) const { assert(j>=0 && jVN()); return _vfpP[j]; } typename T::FacePointer const cVFp(const int j) const { assert(j>=0 && jVN()); return _vfpP[j]; } char &VFi(const int j) {return _vfiP[j]; } + char VFi(const int j) const {return _vfiP[j]; } template void ImportData(const LeftF & leftF){T::ImportData(leftF);} inline void Alloc(const int & ns) { diff --git a/vcg/simplex/tetrahedron/component.h b/vcg/simplex/tetrahedron/component.h index d2d8c878..7cd9781d 100644 --- a/vcg/simplex/tetrahedron/component.h +++ b/vcg/simplex/tetrahedron/component.h @@ -47,7 +47,7 @@ public: //Empty vertexref inline typename T::VertexType * & V( const int ) { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::VertexType * const & V( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } - inline const typename T::VertexType * cV( const int ) { assert(0); static typename T::VertexType *vp=0; return vp; } + inline const typename T::VertexType * cV( const int ) const { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::CoordType & P( const int ) { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } inline const typename T::CoordType & P( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } inline const typename T::CoordType &cP( const int ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } @@ -112,6 +112,7 @@ public: typename T::TetraPointer const cTTp( const int ) const { static typename T::TetraPointer const tp=0; assert(0); return tp; } char & VTi( const int ) { static char z=0; assert(0); return z; } + char VTi( const int ) const { static char z=0; assert(0); return z; } char cVTi( const int ) const { static char z=0; assert(0); return z; } char & TTi( const int ) { static char z=0; assert(0); return z; } char cTTi( const int ) const { static char z=0; assert(0); return z; } diff --git a/vcg/simplex/vertex/component.h b/vcg/simplex/vertex/component.h index 1a95aca9..1914dbbd 100644 --- a/vcg/simplex/vertex/component.h +++ b/vcg/simplex/vertex/component.h @@ -99,6 +99,7 @@ public: typename TT::TetraPointer &VTp() { static typename TT::TetraPointer tp = 0; assert(0); return tp; } typename TT::TetraPointer cVTp() const { static typename TT::TetraPointer tp = 0; assert(0); return tp; } int &VTi() { static int z = 0; assert(0); return z; } + int VTi() const { static int z = 0; assert(0); return z; } int cVTi() const { static int z = 0; assert(0); return z; } static bool HasVTAdjacency() { return false; } bool IsVTInitialized() const {return static_cast(this)->cVTi()!=-1;} @@ -112,6 +113,7 @@ public: typename TT::FacePointer &VFp() { static typename TT::FacePointer fp=0; assert(0); return fp; } typename TT::FacePointer cVFp() const { static typename TT::FacePointer fp=0; assert(0); return fp; } int &VFi() { static int z=-1; assert(0); return z;} + int VFi() const { static int z=-1; assert(0); return z;} int cVFi() const { static int z=-1; assert(0); return z;} bool IsNull() const { return true; } static bool HasVFAdjacency() { return false; } @@ -126,6 +128,7 @@ public: typename TT::EdgePointer &VEp() { static typename TT::EdgePointer ep=0; assert(0); return ep; } typename TT::EdgePointer cVEp() const { static typename TT::EdgePointer ep=0; assert(0); return ep; } int &VEi() { static int z=-1; return z;} + int VEi() const { static int z=-1; return z;} int cVEi() const { static int z=-1; return z;} static bool HasVEAdjacency() { return false; } bool IsVEInitialized() const {return static_cast(this)->cVEi()!=-1;} @@ -138,6 +141,7 @@ public: typename TT::HEdgePointer &VHp() { static typename TT::HEdgePointer ep=0; assert(0); return ep; } typename TT::HEdgePointer cVHp() const { static typename TT::HEdgePointer ep=0; assert(0); return ep; } int &VHi() { static int z=0; return z;} + int VHi() const { static int z=0; return z;} int cVHi() const { static int z=0; return z;} static bool HasVHAdjacency() { return false; } @@ -531,6 +535,7 @@ public: typename T::EdgePointer &VEp() {return _ep; } typename T::EdgePointer cVEp() const {return _ep; } int &VEi() {return _zp; } + int VEi() const {return _zp; } int cVEi() const {return _zp; } template < class RightValueType> void ImportData(const RightValueType & rVert ) { T::ImportData( rVert); } @@ -559,6 +564,7 @@ Note that if you use this component it is expected that on the Face you use also typename T::FacePointer &VFp() { return _fp; } typename T::FacePointer cVFp() const { return _fp; } int &VFi() { return _zp; } + int VFi() const { return _zp; } int cVFi() const { return _zp; } bool IsNull() const { return _zp==-1;} template < class RightValueType> diff --git a/vcg/simplex/vertex/component_ocf.h b/vcg/simplex/vertex/component_ocf.h index 72b42fbd..35572cbc 100644 --- a/vcg/simplex/vertex/component_ocf.h +++ b/vcg/simplex/vertex/component_ocf.h @@ -285,6 +285,10 @@ public: assert((*this).Base().VFAdjacencyEnabled); return (*this).Base().AV[(*this).Index()]._zp; } + int VFi() const { + assert((*this).Base().VFAdjacencyEnabled); + return (*this).Base().AV[(*this).Index()]._zp; + } int cVFi() const { if(! (*this).Base().VFAdjacencyEnabled ) return -1; return (*this).Base().AV[(*this).Index()]._zp;