From b482aa3cbed5489f43aa97921c3603c6e69971fc Mon Sep 17 00:00:00 2001 From: nico Date: Mon, 23 Jan 2017 17:22:44 +0100 Subject: [PATCH] first version of Dual meshing with sample application --- .../polygonmesh_dual/polygonmesh_dual.cpp | 121 ++++++++++ .../polygonmesh_dual/polygonmesh_dual.pro | 7 + vcg/complex/algorithms/dual_meshing.h | 207 ++++++++++++++++++ 3 files changed, 335 insertions(+) create mode 100644 apps/sample/polygonmesh_dual/polygonmesh_dual.cpp create mode 100644 apps/sample/polygonmesh_dual/polygonmesh_dual.pro create mode 100644 vcg/complex/algorithms/dual_meshing.h diff --git a/apps/sample/polygonmesh_dual/polygonmesh_dual.cpp b/apps/sample/polygonmesh_dual/polygonmesh_dual.cpp new file mode 100644 index 00000000..4bd9b0c3 --- /dev/null +++ b/apps/sample/polygonmesh_dual/polygonmesh_dual.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +* 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. * +* * +****************************************************************************/ + +#include + +/*include the algorithms for updating: */ +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +using namespace vcg; +using namespace std; + +// forward declarations +class TFace; +class TVertex; + +struct TUsedTypes: public vcg::UsedTypes< vcg::Use::AsVertexType, vcg::Use::AsFaceType >{}; + +/* Definition of a mesh of triangles +*/ +class TVertex : public Vertex< TUsedTypes, + vertex::BitFlags, + vertex::Coord3f, + vertex::Normal3f, + vertex::Mark >{}; + +class TFace : public Face< TUsedTypes, + face::VertexRef, // three pointers to vertices + face::Normal3f, // normal + face::BitFlags, // flags + face::FFAdj // three pointers to adjacent faces +> {}; + +/* the mesh is a container of vertices and a container of faces */ +class TMesh : public vcg::tri::TriMesh< vector, vector > {}; + + +/* Definition of a mesh of polygons that also supports half-edges +*/ +class PFace; +class PVertex; + +struct PUsedTypes: public vcg::UsedTypes ::AsVertexType, + vcg::Use ::AsFaceType>{}; + +class PVertex:public vcg::Vertex< PUsedTypes, + vcg::vertex::Coord3f, + vcg::vertex::Normal3f, + vcg::vertex::Mark, + vcg::vertex::BitFlags>{} ; + +class PFace:public vcg::Face< + PUsedTypes + ,vcg::face::PolyInfo // this is necessary if you use component in vcg/simplex/face/component_polygon.h + // It says "this class is a polygon and the memory for its components (e.g. pointer to its vertices + // will be allocated dynamically") + ,vcg::face::PFVAdj // Pointer to the vertices (just like FVAdj ) + ,vcg::face::PFVAdj + ,vcg::face::PFFAdj // Pointer to edge-adjacent face (just like FFAdj ) + ,vcg::face::BitFlags // bit flags + ,vcg::face::Normal3f // normal +> {}; + +class PMesh: public + vcg::tri::TriMesh< + std::vector, // the vector of vertices + std::vector // the vector of faces + >{}; + +TMesh primalT; +PMesh primal,dual; + +int main(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + + vcg::tri::Sphere(primalT,2); + vcg::tri::PolygonSupport::ImportFromTriMesh(primal,primalT); + + vcg::tri::DualMeshing::MakeDual(primal,dual); + vcg::tri::io::ExporterOBJ::Save(dual,"./dual.obj",vcg::tri::io::Mask::IOM_BITPOLYGONAL); + + vcg::tri::DualMeshing::MakeDual(dual,primal); + vcg::tri::io::ExporterOBJ::Save(primal,"./dual_dual.obj",vcg::tri::io::Mask::IOM_BITPOLYGONAL); + +} + + + diff --git a/apps/sample/polygonmesh_dual/polygonmesh_dual.pro b/apps/sample/polygonmesh_dual/polygonmesh_dual.pro new file mode 100644 index 00000000..e92bf0b3 --- /dev/null +++ b/apps/sample/polygonmesh_dual/polygonmesh_dual.pro @@ -0,0 +1,7 @@ +\macx: QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 +QMAKE_MAC_SDK = macosx10.9 +CONFIG += c++11 + +include(../common.pri) +TARGET = polygonmesh_base +SOURCES += polygonmesh_dual.cpp ../../../wrap/ply/plylib.cpp diff --git a/vcg/complex/algorithms/dual_meshing.h b/vcg/complex/algorithms/dual_meshing.h new file mode 100644 index 00000000..8d15673a --- /dev/null +++ b/vcg/complex/algorithms/dual_meshing.h @@ -0,0 +1,207 @@ +/**************************************************************************** +* 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