/**************************************************************************** * 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_DUAL_MESH #define __VCGLIB_DUAL_MESH #include #include #include #include namespace vcg { namespace tri { template class DualMeshing { typedef typename PolyMeshType::VertexType VertexType; typedef typename PolyMeshType::FaceType FaceType; typedef typename PolyMeshType::CoordType CoordType; typedef typename PolyMeshType::ScalarType ScalarType; static void ComposeFace(VertexType &startV, FaceType &startF, std::map, int> &EdgeMap, const std::vector &FaceMap, const PolyMeshType &primal, std::vector &vertSeq) { vcg::face::Pos startP(&startF,&startV); //get the star of pos std::vector > posVec; vcg::face::VFOrderedStarFF(startP,posVec); for (size_t i=0;i firstPos=posVec[0]; firstPos.FlipE(); assert(firstPos.IsBorder()); int indexVt0=vcg::tri::Index(primal,firstPos.V()); int indexVt1=vcg::tri::Index(primal,firstPos.VFlip()); std::pair key(std::min(indexVt0,indexVt1), std::max(indexVt0,indexVt1)); assert(EdgeMap.count(key)>0); int indexV0=EdgeMap[key]; vcg::face::Pos lastPos=posVec.back(); assert(lastPos.IsBorder()); indexVt0=vcg::tri::Index(primal,lastPos.V()); indexVt1=vcg::tri::Index(primal,lastPos.VFlip()); key=std::pair (std::min(indexVt0,indexVt1), std::max(indexVt0,indexVt1)); assert(EdgeMap.count(key)>0); int indexV1=EdgeMap[key]; vertSeq.push_back(indexV1); vertSeq.push_back(indexV0); } } static void CreateBorderEdgeVert(PolyMeshType &primal, PolyMeshType &dual, std::map, int> &VertMap) { VertMap.clear(); vcg::tri::UpdateFlags::VertexClearB(primal); for (size_t i=0;iSetB(); v1->SetB(); int V0Index=vcg::tri::Index(primal,v0); int V1Index=vcg::tri::Index(primal,v1); CoordType pos=(v0->P()+v1->P())/2; vcg::tri::Allocator::AddVertex(dual,pos); std::pair key(std::min(V0Index,V1Index), std::max(V0Index,V1Index)); VertMap[key]=dual.vert.size()-1; } } static void CreateFaceVert(PolyMeshType &primal, PolyMeshType &dual, std::vector &VertMap, std::vector &VertFace, bool snapBorder) { VertMap.clear(); VertMap.resize(primal.face.size(),-1); VertFace.clear(); VertFace.resize(primal.vert.size(),-1); for (size_t i=0;i BorderPos; for (int j=0;jIsB())continue; pos+=primal.face[i].P(j); num++; } if (num>0) pos/=num; } if (num==0) { for (int j=0;jP(); int indexV=vcg::tri::Index(primal,primal.face[i].V(j)); if (VertFace[indexV]!=-1)continue; VertFace[indexV]=i; } pos/=(ScalarType)primal.face[i].VN(); } vcg::tri::Allocator::AddVertex(dual,pos); VertMap[i]=dual.vert.size()-1; } } public: static void MakeDual(PolyMeshType &primal, PolyMeshType &dual, bool snapBorder=true) { dual.Clear(); vcg::tri::RequirePolygonalMesh(primal); vcg::tri::RequirePolygonalMesh(dual); vcg::tri::RequireFFAdjacency(primal); vcg::tri::UpdateTopology::FaceFace(primal); std::map, int> VertEdgeMap; CreateBorderEdgeVert(primal,dual,VertEdgeMap); std::vector VertFaceMap,VertFace; CreateFaceVert(primal,dual,VertFaceMap,VertFace,snapBorder); for (size_t i=0;i VertSeq; ComposeFace(primal.vert[i],*firstF,VertEdgeMap,VertFaceMap,primal,VertSeq); vcg::tri::Allocator::AddFaces(dual,1); dual.face.back().Alloc(VertSeq.size()); for (size_t j=0;j::RemoveUnreferencedVertex(dual); } }; } } #endif // __VCGLIB_DUAL_MESH