diff --git a/vcg/complex/base.h b/vcg/complex/base.h index 65cfb4a9..13bab188 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -64,7 +64,7 @@ namespace tri { typedef std::vector< typename TYPESPOOL::HEdgeType > CONTH; typedef CONTV VertContainer; - typedef _Vertex VertexType; + typedef typename CONTV::value_type VertexType; typedef typename TYPESPOOL::VertexPointer VertexPointer; typedef const typename TYPESPOOL::VertexPointer ConstVertexPointer; typedef bool CoordType; diff --git a/vcg/complex/tetrahedron/allocate.h b/vcg/complex/tetrahedron/allocate.h index 36909635..6a6bd72a 100644 --- a/vcg/complex/tetrahedron/allocate.h +++ b/vcg/complex/tetrahedron/allocate.h @@ -225,7 +225,7 @@ public: } for (TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) - if (!(*ti.IsD())) + if (!(*ti).IsD()) for (int i = 0; i < 4; ++i) if ((*ti).cV(i) != 0) pu.Update((*ti).V(i)); @@ -660,12 +660,12 @@ public: 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()); - } +// 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; } @@ -699,7 +699,7 @@ public: else { pu.oldBase = &*m.tetra.begin(); - pu.oldEnd = &*m.tetra.back() + 1; + pu.oldEnd = &m.tetra.back() + 1; } //resize the tetra list and update tetra count @@ -719,7 +719,7 @@ public: //do the update pu.newBase = &*m.tetra.begin(); - pu.newEnd = &*m.tetra.back() + 1; + pu.newEnd = &m.tetra.back() + 1; if (pu.NeedUpdate()) { if (HasVTAdjacency(m)) @@ -739,9 +739,8 @@ public: } //do edge and face adjacency - if (HasTTAdjacency(m)) - for (TetraPointer ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) + for (TetraIterator ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) if (!ti->IsD()) { pu.Update(ti->TTp(0)); @@ -804,6 +803,11 @@ public: 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); } @@ -920,19 +924,6 @@ public: } -//TODO: - // static void PermutateTetraVector(MeshType & m, PointerUpdater & pu) - // { - // if (m.tetra.empty()) - // return; - // for (size_t i = 0; i < m.tetra.size(); ++i) - // { - // if (pu.remap[i] < size_t(m.tn)) - // { - - // } - // } - // } /* Function to rearrange the vertex vector according to a given index permutation the permutation is vector such that after calling this function @@ -1159,6 +1150,7 @@ public: CompactEdgeVector(m, pu); } + /*! \brief Compact face vector by removing deleted elements. @@ -1278,6 +1270,127 @@ 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: /*! \brief Check if an handle to a Per-Vertex Attribute is valid */ diff --git a/vcg/complex/tetrahedron/append.h b/vcg/complex/tetrahedron/append.h new file mode 100644 index 00000000..1639d73d --- /dev/null +++ b/vcg/complex/tetrahedron/append.h @@ -0,0 +1,456 @@ +/**************************************************************************** +* 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_TETRAAPPEND +#define __VCGLIB_TETRAAPPEND + +#ifndef __VCG_TETRA_MESH +#error "This file should not be included alone. It is automatically included by complex.h" +#endif + +namespace vcg { +namespace tetra { +/** \ingroup trimesh */ +/*! \brief Class to safely duplicate and append (portion of) meshes. + +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 of a mesh to another one. +\sa \ref allocation +*/ +template +class Append +{ +public: + typedef typename MeshLeft::ScalarType ScalarLeft; + typedef typename MeshLeft::CoordType CoordLeft; + typedef typename MeshLeft::VertexType VertexLeft; + typedef typename MeshLeft::EdgeType EdgeLeft; + typedef typename MeshLeft::FaceType FaceLeft; + typedef typename MeshLeft::TetraType TetraLeft; +// typedef typename MeshLeft::HEdgeType HEdgeLeft; + 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 MeshLeft::TetraPointer TetraPointerLeft; + + + 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::VertexPointer VertexPointerRight; + typedef typename ConstMeshRight::VertexIterator VertexIteratorRight; + typedef typename ConstMeshRight::EdgeIterator EdgeIteratorRight; +// typedef typename ConstMeshRight::HEdgeIterator HEdgeIteratorRight; + typedef typename ConstMeshRight::FaceIterator FaceIteratorRight; + typedef typename ConstMeshRight::FacePointer FacePointerRight; + typedef typename ConstMeshRight::TetraType TetraTypeRight; + typedef typename ConstMeshRight::TetraPointer TetraPointerRight; + typedef typename ConstMeshRight::TetraIterator TetraIteratorRight; + + + struct Remap{ + static size_t InvalidIndex() { return std::numeric_limits::max(); } + std::vector vert,face,edge, /*hedge,*/ tetra; + }; + + static void ImportVertexAdj(MeshLeft &ml, ConstMeshRight &mr, VertexLeft &vl, VertexRight &vr, Remap &remap ){ + // Vertex to Edge Adj + if(HasVEAdjacency(ml) && HasVEAdjacency(mr) && vr.cVEp() != 0){ + size_t i = Index(mr,vr.cVEp()); + vl.VEp() = (i>ml.edge.size())? 0 : &ml.edge[remap.edge[i]]; + vl.VEi() = vr.VEi(); + } + + // Vertex to Face Adj + if(HasPerVertexVFAdjacency(ml) && HasPerVertexVFAdjacency(mr) && vr.cVFp() != 0 ){ + size_t i = Index(mr,vr.cVFp()); + vl.VFp() = (i>ml.face.size())? 0 :&ml.face[remap.face[i]]; + vl.VFi() = vr.VFi(); + } + + if (HasPerVertexVTAdjacency(ml) && HasPerVertexVTAdjacency(mr) && vr.cVTp() != 0) { + size_t i = Index(mr, vr.cVTp()); + vl.VTp() = (i > ml.tetra.size()) ? 0 : &ml.tetra[remap.tetra[i]]; + vl.VTi() = vt.VTi(); + } + // // Vertex to HEdge Adj + // if(HasVHAdjacency(ml) && HasVHAdjacency(mr) && vr.cVHp() != 0){ + // vl.VHp() = &ml.hedge[remap.hedge[Index(mr,vr.cVHp())]]; + // vl.VHi() = vr.VHi(); + // } + } + + static void ImportEdgeAdj(MeshLeft &ml, ConstMeshRight &mr, EdgeLeft &el, const EdgeRight &er, Remap &remap) + { + // Edge to Edge Adj + if(HasEEAdjacency(ml) && HasEEAdjacency(mr)) + for(unsigned int vi = 0; vi < 2; ++vi) + { + size_t idx = Index(mr,er.cEEp(vi)); + el.EEp(vi) = (idx>ml.edge.size())? 0 : &ml.edge[remap.edge[idx]]; + el.EEi(vi) = er.cEEi(vi); + } + + // Edge to Face Adj + if(HasEFAdjacency(ml) && HasEFAdjacency(mr)){ + size_t idx = Index(mr,er.cEFp()); + el.EFp() = (idx>ml.face.size())? 0 :&ml.face[remap.face[idx]]; + el.EFi() = er.cEFi(); + } + + // // Edge to HEdge Adj + // if(HasEHAdjacency(ml) && HasEHAdjacency(mr)) + // el.EHp() = &ml.hedge[remap.hedge[Index(mr,er.cEHp())]]; + } + + + static void ImportFaceAdj(MeshLeft &ml, ConstMeshRight &mr, FaceLeft &fl, const FaceRight &fr, Remap &remap ) + { + // Face to Edge Adj + if(HasFEAdjacency(ml) && HasFEAdjacency(mr)){ + assert(fl.VN() == fr.VN()); + for( int vi = 0; vi < fl.VN(); ++vi ){ + size_t idx = remap.edge[Index(mr,fr.cFEp(vi))]; + if(idx!=Remap::InvalidIndex()) + fl.FEp(vi) = &ml.edge[idx]; + } + } + + // Face to Face Adj + if(HasFFAdjacency(ml) && HasFFAdjacency(mr)){ + assert(fl.VN() == fr.VN()); + for( int vi = 0; vi < fl.VN(); ++vi ){ + size_t idx = remap.face[Index(mr,fr.cFFp(vi))]; + if(idx!=Remap::InvalidIndex()){ + fl.FFp(vi) = &ml.face[idx]; + fl.FFi(vi) = fr.cFFi(vi); + } + } + } + + // // Face to HEedge Adj + // if(HasFHAdjacency(ml) && HasFHAdjacency(mr)) + // fl.FHp() = &ml.hedge[remap.hedge[Index(mr,fr.cFHp())]]; + } + + static void ImportTetraAdj(MeshLeft & ml, ConstMeshRight & mr, TetraLeft & tl, const TetraTypeRight &tr, Remap &remap ) + { + // TT Adj + if(HasTTAdjacency(ml) && HasTTAdjacency(mr)){ + 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) = fr.cTTi(vi); + } + } + } + + // // Face to HEedge Adj + // if(HasFHAdjacency(ml) && HasFHAdjacency(mr)) + // 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*/ ){ +// // HEdge to Vertex Adj +// if(HasHVAdjacency(ml) && HasHVAdjacency(mr)) +// hl.HVp() = &ml.vert[remap.vert[Index(mr,hr.cHVp())]]; + +// // HEdge to Edge Adj +// if(HasHEAdjacency(ml) && HasHEAdjacency(mr)){ +// size_t idx = Index(mr,hr.cHEp()) ; +// hl.HEp() = (idx>ml.edge.size())? 0 : &ml.edge[remap.edge[idx]]; +// } + +// // HEdge to Face Adj +// if(HasHFAdjacency(ml) && HasHFAdjacency(mr)){ +// size_t idx = Index(mr,hr.cHFp()); +// hl.HFp() = (idx>ml.face.size())? 0 :&ml.face[remap.face[idx]]; +// } + + +// // HEdge to Opposite HEdge Adj +// if(HasHOppAdjacency(ml) && HasHOppAdjacency(mr)) +// hl.HOp() = &ml.hedge[remap.hedge[Index(mr,hr.cHOp())]]; + +// // HEdge to Next HEdge Adj +// if(HasHNextAdjacency(ml) && HasHNextAdjacency(mr)) +// hl.HNp() = &ml.hedge[remap.hedge[Index(mr,hr.cHNp())]]; + +// // HEdge to Next HEdge Adj +// if(HasHPrevAdjacency(ml) && HasHPrevAdjacency(mr)) +// hl.HPp() = &ml.hedge[remap.hedge[Index(mr,hr.cHPp())]]; +// } + +// Append Right Mesh to the Left Mesh +// Append::Mesh(ml, mr) is equivalent to ml += mr. +// Note MeshRigth could be costant... + /*! \brief %Append the second mesh to the first one. + + The first mesh is not destroyed and no attempt of avoid duplication of already present elements is done. + If requested only the selected elements are appended to the first one. + The second mesh is not changed at all (it could be constant) with the exception of the selection (see below note). + + \note If the the selection of the vertexes is not consistent with the face selection + the append could build faces referencing non existent vertices + so it is mandatory that the selection of the vertices reflects the loose selection + from edges and faces (e.g. if a face is selected then all its vertices must be selected). + + \note Attributes. This function will copy only those attributes that are present in both meshes. + Two attributes in different meshes are considered the same iff 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 + + */ + +//TODO: +static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, const bool adjFlag = false) +{ + // Note that if the the selection of the vertexes is not consistent with the face selection + // the append could build faces referencing non existent vertices + // so it is mandatory that the selection of the vertices reflects the loose selection + // from edges and faces (e.g. if a face is selected all its vertices must be selected). + // note the use of the parameter for preserving existing vertex selection. + if(selected) + { + assert(adjFlag == false || ml.IsEmpty()); // It is rather meaningless to partially copy adj relations. + tri::UpdateSelection::VertexFromEdgeLoose(mr,true); + tri::UpdateSelection::VertexFromFaceLoose(mr,true); + } + + // 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); + + for(VertexIteratorRight vi=mr.vert.begin(); vi!=mr.vert.end(); ++vi) + { + if(!(*vi).IsD() && (!selected || (*vi).IsS())) + { + size_t ind=Index(mr,*vi); + 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); + + for(EdgeIteratorRight ei=mr.edge.begin(); ei!=mr.edge.end(); ++ei) + if(!(*ei).IsD() && (!selected || (*ei).IsS())){ + size_t ind=Index(mr,*ei); + 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); + + for(FaceIteratorRight fi=mr.face.begin(); fi!=mr.face.end(); ++fi) + if(!(*fi).IsD() && (!selected || (*fi).IsS())){ + size_t ind=Index(mr,*fi); + remap.face[ind]=int(Index(ml,*fp)); + ++fp; + } + + // hedge + remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex()); + for(HEdgeIteratorRight hi=mr.hedge.begin(); hi!=mr.hedge.end(); ++hi) + if(!(*hi).IsD() && (!selected || (*hi).IsS())){ + size_t ind=Index(mr,*hi); + assert(remap.hedge[ind]==Remap::InvalidIndex()); + HEdgeIteratorLeft hp = Allocator::AddHEdges(ml,1); + (*hp).ImportData(*(hi)); + remap.hedge[ind]=Index(ml,*hp); + } + + // phase 2. + // copy data from ml to its corresponding elements in ml and adjacencies + + // vertex + for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi) + if( !(*vi).IsD() && (!selected || (*vi).IsS())){ + ml.vert[remap.vert[Index(mr,*vi)]].ImportData(*vi); + if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,*vi)]],*vi,remap); + } + + // edge + for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei) + if(!(*ei).IsD() && (!selected || (*ei).IsS())){ + ml.edge[remap.edge[Index(mr,*ei)]].ImportData(*ei); + // Edge to Vertex Adj + EdgeLeft &el = ml.edge[remap.edge[Index(mr,*ei)]]; + if(HasEVAdjacency(ml) && HasEVAdjacency(mr)){ + el.V(0) = &ml.vert[remap.vert[Index(mr,ei->cV(0))]]; + el.V(1) = &ml.vert[remap.vert[Index(mr,ei->cV(1))]]; + } + if(adjFlag) ImportEdgeAdj(ml,mr,el,*ei,remap); + } + + // face + const size_t textureOffset = ml.textures.size(); + bool WTFlag = HasPerWedgeTexCoord(mr) && (textureOffset>0); + for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi) + if(!(*fi).IsD() && (!selected || (*fi).IsS())) + { + FaceLeft &fl = ml.face[remap.face[Index(mr,*fi)]]; + fl.Alloc(fi->VN()); + if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ + for(int i = 0; i < fl.VN(); ++i) + fl.V(i) = &ml.vert[remap.vert[Index(mr,fi->cV(i))]]; + } + fl.ImportData(*fi); + 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,*fi)]],*fi,remap); + + } + + // hedge + for(HEdgeIteratorRight hi=mr.hedge.begin();hi!=mr.hedge.end();++hi) + 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); + } + + // 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(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r) + if( !(*vi).IsD() && (!selected || (*vi).IsS())) + memcpy((*al)._handle->At(remap.vert[Index(mr,*vi)]),(*ar)._handle->At(id_r), + (*al)._handle->SizeOf()); + } + } + + // 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(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r) + if( !(*ei).IsD() && (!selected || (*ei).IsS())) + memcpy((*al)._handle->At(remap.edge[Index(mr,*ei)]),(*ar)._handle->At(id_r), + (*al)._handle->SizeOf()); + } + } + + // 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(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r) + if( !(*fi).IsD() && (!selected || (*fi).IsS())) + memcpy((*al)._handle->At(remap.face[Index(mr,*fi)]),(*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 + //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. +*/ +static void MeshCopy(MeshLeft& ml, ConstMeshRight& mr, bool selected=false, const bool adjFlag = false) +{ + ml.Clear(); + Mesh(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() + */ +static void Selected(MeshLeft& ml, ConstMeshRight& mr) +{ + Mesh(ml,mr,true); +} + +}; // end of class Append + + + + + +} // End Namespace tri +} // End Namespace vcg + + +#endif + + diff --git a/vcg/complex/tetrahedron/base.h b/vcg/complex/tetrahedron/base.h index befa0448..c01c6c2b 100644 --- a/vcg/complex/tetrahedron/base.h +++ b/vcg/complex/tetrahedron/base.h @@ -29,22 +29,22 @@ 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) +//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); } +// 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)){}; -}; +// PointerToAttribute() : _type(typeid(void)){}; +//}; namespace tetra { @@ -195,7 +195,7 @@ class TetraMesh typedef typename TetraMesh::TetraType TetraType; typedef typename TetraMesh::TetraPointer TetraPointer; typedef typename TetraMesh::ConstTetraPointer ConstTetraPointer; - typedef typename TetraMesh::TetraIterator TetraIterator + typedef typename TetraMesh::TetraIterator TetraIterator; typedef typename TetraMesh::ConstTetraIterator ConstTetraIterator; typedef vcg::PointerToAttribute PointerToAttribute; @@ -402,7 +402,8 @@ class TetraMesh vn = 0; en = 0; fn = 0; - hn = 0; + tn = 0; +// hn = 0; imark = 0; C() = Color4b::Gray; } @@ -692,17 +693,19 @@ bool HasFVAdjacency(const TetraMeshType &m) { return tetra::FaceVectorHasFVAdjac //:::::::::::TETRA:::::::::::::::: template bool TetraVectorHasVTAdjacency(const std::vector &) { return TetraType::HasVTAdjacency(); } +template +bool TetraVectorHasTTAdjacency(const std::vector &) { return TetraType::HasTTAdjacency(); } 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 +bool HasTTAdjacency(const TetraMeshType &m) { return tetra::TetraVectorHasTTAdjacency(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();} diff --git a/vcg/complex/tetrahedron/complex.h b/vcg/complex/tetrahedron/complex.h index a2cbecbe..8a28cdfc 100644 --- a/vcg/complex/tetrahedron/complex.h +++ b/vcg/complex/tetrahedron/complex.h @@ -24,6 +24,7 @@ #ifndef __VCG_TETRA_MESH_H #define __VCG_TETRA_MESH_H #define __VCG_TETRA_MESH +#define __VCG_MESH #include #include @@ -43,13 +44,13 @@ #include #include #include +#include #include -#include +#include #include #include #include #include -#include #include #include #include @@ -61,5 +62,7 @@ #include #undef __VCG_TETRA_MESH +#undef __VCG_MESH + #endif diff --git a/vcg/complex/used_types.h b/vcg/complex/used_types.h index b47cfdbe..04daf9bb 100755 --- a/vcg/complex/used_types.h +++ b/vcg/complex/used_types.h @@ -92,11 +92,11 @@ template