/**************************************************************************** * 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. * * * ****************************************************************************/ // This sample requires gl. #ifndef GLU_VERSIONS #ifdef __APPLE__ #include #else #ifdef _WIN32 #define NOMINMAX #include #endif #include #endif #endif #include // input output #include #include // topology computation #include #include #include #include #include #include using namespace vcg; using namespace std; class MyEdge; class MyFace; class MyVertex; struct MyUsedTypes : public UsedTypes< Use ::AsVertexType, Use ::AsEdgeType, Use ::AsFaceType>{}; class MyVertex : public Vertex{}; class MyFace : public Face< MyUsedTypes, face::FFAdj, face::VertexRef, face::BitFlags >{}; class MyEdge : public Edge{}; class MyMesh : public tri::TriMesh< vector, vector , vector > {}; void CapHole(MyMesh &m, MyMesh &capMesh, bool reverseFlag) { capMesh.Clear(); std::vector< std::vector > outlines; std::vector outline; tri::Allocator::CompactVertexVector(m); tri::Allocator::CompactFaceVector(m); tri::UpdateFlags::FaceClearV(m); tri::UpdateFlags::VertexClearV(m); tri::UpdateTopology::FaceFace(m); int nv=0; for(size_t i=0;i p(startB,j); assert(p.IsBorder()); do { assert(p.IsManifold()); p.F()->SetV(); outline.push_back(p.V()->P()); p.NextB(); nv++; } while(!p.F()->IsV()); if (reverseFlag) std::reverse(outline.begin(),outline.end()); outlines.push_back(outline); outline.clear(); } } if (nv<2) return; MyMesh::VertexIterator vi=vcg::tri::Allocator::AddVertices(capMesh,nv); for (size_t i=0;iP()=outlines[i][j]; } std::vector indices; glu_tesselator::tesselate(outlines, indices); std::vector points; glu_tesselator::unroll(outlines, points); MyMesh::FaceIterator fi=tri::Allocator::AddFaces(capMesh,nv-2); for (size_t i=0; iV(0)=&capMesh.vert[ indices[i+0] ]; (*&fi)->V(1)=&capMesh.vert[ indices[i+1] ]; (*&fi)->V(2)=&capMesh.vert[ indices[i+2] ]; } tri::Clean::RemoveDuplicateVertex(capMesh); tri::UpdateBounding::Box(capMesh); } bool SplitMesh(MyMesh &m, /// The mesh that has to be splitted. It is NOT changed MyMesh &A, MyMesh &B, /// The two resulting pieces, correct only if true is returned Plane3f plane) { tri::Append::Mesh(A,m); tri::UpdateQuality::VertexFromPlane(A, plane); tri::QualityMidPointFunctor slicingfunc(0.0f); tri::QualityEdgePredicate slicingpred(0.0f); tri::UpdateTopology::FaceFace(A); // The Actual Slicing tri::RefineE, tri::QualityEdgePredicate > (A, slicingfunc, slicingpred, false); tri::Append::Mesh(B,A); tri::UpdateSelection::VertexFromQualityRange(A,-std::numeric_limits::max(),0); tri::UpdateSelection::FaceFromVertexStrict(A); for(MyMesh::FaceIterator fi=A.face.begin();fi!=A.face.end();++fi) if(!(*fi).IsD() && (*fi).IsS() ) tri::Allocator::DeleteFace(A,*fi); tri::Clean::RemoveUnreferencedVertex(A); tri::UpdateSelection::VertexFromQualityRange(B,0,std::numeric_limits::max()); tri::UpdateSelection::FaceFromVertexStrict(B); for(MyMesh::FaceIterator fi=B.face.begin();fi!=B.face.end();++fi) if(!(*fi).IsD() && (*fi).IsS() ) tri::Allocator::DeleteFace(B,*fi); tri::Clean::RemoveUnreferencedVertex(B); tri::UpdateTopology::FaceFace(m); MyMesh Cap; CapHole(A,Cap,0); tri::Append::Mesh(A,Cap); CapHole(B,Cap,0); tri::Append::Mesh(B,Cap); tri::Clean::RemoveDuplicateVertex(A); tri::Clean::RemoveDuplicateVertex(B); return true; } void GetRandPlane(Box3f &bb, Plane3f &plane) { Point3f planeCenter = bb.Center(); Point3f planeDir = Point3f(-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX); planeDir.Normalize(); plane.Init(planeCenter+planeDir*0.3f*bb.Diag()*float(rand())/RAND_MAX,planeDir); } int main( int argc, char **argv ) { if(argc<2) { printf("Usage trimesh_base \n"); return -1; } MyMesh m, // The loaded mesh em, // the 2D polyline representing the section slice, // the planar mesh resulting from the triangulation of the above sliced; // the 3D mesh resulting by the actual slicing of m into two capped sub pieces if(tri::io::ImporterPLY::Open(m,argv[1])!=0) { printf("Error reading file %s\n",argv[1]); exit(0); } tri::UpdateBounding::Box(m); printf("Input mesh vn:%i fn:%i\n",m.VN(),m.FN()); srand(time(0)); Plane3f slicingPlane; GetRandPlane(m.bbox,slicingPlane); printf("slicing dir %5.2f %5.2f %5.2f\n",slicingPlane.Direction()[0],slicingPlane.Direction()[1],slicingPlane.Direction()[2]); vcg::IntersectionPlaneMesh(m, slicingPlane, em ); tri::Clean::RemoveDuplicateVertex(em); vcg::tri::CapEdgeMesh(em,slice); printf("Slice mesh has %i vert and %i faces\n", slice.VN(), slice.FN() ); MyMesh A,B; SplitMesh(m,A,B,slicingPlane); tri::UpdatePosition::Translate(A, slicingPlane.Direction()*m.bbox.Diag()/80.0); tri::UpdatePosition::Translate(B,-slicingPlane.Direction()*m.bbox.Diag()/80.0); tri::Append::Mesh(sliced,A); tri::Append::Mesh(sliced,B); printf("Sliced mesh has %i vert and %i faces\n", sliced.VN(), sliced.FN() ); tri::io::ExporterPLY::Save(slice,"slice.ply",false); tri::io::ExporterPLY::Save(sliced,"sliced.ply",false); return 0; }