VCG Library
trimesh_edge.cpp
1 /****************************************************************************
2 * VCGLib o o *
3 * Visual and Computer Graphics Library o o *
4 * _ O _ *
5 * Copyright(C) 2004-2016 \/)\/ *
6 * Visual Computing Lab /\/| *
7 * ISTI - Italian National Research Council | *
8 * \ *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 * *
22 ****************************************************************************/
23 
24 // This sample requires gl.
25 #ifndef GLU_VERSIONS
26 #ifdef __APPLE__
27 #include <OpenGL/gl.h>
28 #else
29 #ifdef _WIN32
30 #define NOMINMAX
31  #include <windows.h>
32 #endif
33 #include <GL/gl.h>
34 #endif
35 #endif
36 
37 #include<vcg/complex/complex.h>
38 
39 // input output
40 #include<wrap/io_trimesh/import.h>
41 #include<wrap/io_trimesh/export.h>
42 
43 // topology computation
44 #include <vcg/complex/algorithms/update/position.h>
45 #include <vcg/complex/algorithms/update/quality.h>
46 #include <vcg/complex/algorithms/stat.h>
47 
48 #include <vcg/complex/algorithms/intersection.h>
49 #include <vcg/complex/algorithms/refine.h>
50 #include <wrap/gl/glu_tessellator_cap.h>
51 
52 using namespace vcg;
53 using namespace std;
54 
55 class MyEdge;
56 class MyFace;
57 class MyVertex;
58 struct MyUsedTypes : public UsedTypes< Use<MyVertex> ::AsVertexType,
59  Use<MyEdge> ::AsEdgeType,
60  Use<MyFace> ::AsFaceType>{};
61 
62 class MyVertex : public Vertex<MyUsedTypes, vertex::Coord3f, vertex::Normal3f, vertex::Qualityf,vertex::BitFlags >{};
63 class MyFace : public Face< MyUsedTypes, face::FFAdj, face::VertexRef, face::BitFlags >{};
64 class MyEdge : public Edge<MyUsedTypes, edge::VertexRef,edge::BitFlags,edge::EEAdj>{};
65 class MyMesh : public tri::TriMesh< vector<MyVertex>, vector<MyFace> , vector<MyEdge> > {};
66 
67 
68 
69 void CapHole(MyMesh &m, MyMesh &capMesh, bool reverseFlag)
70 {
71  capMesh.Clear();
72  std::vector< std::vector<Point3f> > outlines;
73  std::vector<Point3f> outline;
74 
80  int nv=0;
81 
82  for(size_t i=0;i<m.face.size();i++)
83  {
84  for (int j=0;j<3;j++)
85  if (!m.face[i].IsV() && face::IsBorder(m.face[i],j))
86  {
87  MyFace* startB=&(m.face[i]);
88  vcg::face::Pos<MyFace> p(startB,j);
89  assert(p.IsBorder());
90  do
91  {
92  assert(p.IsManifold());
93  p.F()->SetV();
94  outline.push_back(p.V()->P());
95  p.NextB();
96  nv++;
97  }
98  while(!p.F()->IsV());
99  if (reverseFlag)
100  std::reverse(outline.begin(),outline.end());
101 
102  outlines.push_back(outline);
103  outline.clear();
104  }
105  }
106  if (nv<2) return;
107  MyMesh::VertexIterator vi=vcg::tri::Allocator<MyMesh>::AddVertices(capMesh,nv);
108  for (size_t i=0;i<outlines.size();i++)
109  {
110  for(size_t j=0;j<outlines[i].size();++j,++vi)
111  (&*vi)->P()=outlines[i][j];
112  }
113 
114  std::vector<int> indices;
115  glu_tesselator::tesselate(outlines, indices);
116 
117  std::vector<Point3f> points;
118  glu_tesselator::unroll(outlines, points);
119  MyMesh::FaceIterator fi=tri::Allocator<MyMesh>::AddFaces(capMesh,nv-2);
120  for (size_t i=0; i<indices.size(); i+=3,++fi)
121  {
122  (*&fi)->V(0)=&capMesh.vert[ indices[i+0] ];
123  (*&fi)->V(1)=&capMesh.vert[ indices[i+1] ];
124  (*&fi)->V(2)=&capMesh.vert[ indices[i+2] ];
125  }
128 }
129 
130 
131 
132 
133 bool SplitMesh(MyMesh &m,
134  MyMesh &A, MyMesh &B,
135  Plane3f plane)
136 {
139  tri::QualityMidPointFunctor<MyMesh> slicingfunc(0.0f);
140  tri::QualityEdgePredicate<MyMesh> slicingpred(0.0f);
142  // The Actual Slicing
143  tri::RefineE<MyMesh, tri::QualityMidPointFunctor<MyMesh>, tri::QualityEdgePredicate<MyMesh> > (A, slicingfunc, slicingpred, false);
144 
146 
147  tri::UpdateSelection<MyMesh>::VertexFromQualityRange(A,-std::numeric_limits<float>::max(),0);
149  for(MyMesh::FaceIterator fi=A.face.begin();fi!=A.face.end();++fi)
150  if(!(*fi).IsD() && (*fi).IsS() ) tri::Allocator<MyMesh>::DeleteFace(A,*fi);
152 
153  tri::UpdateSelection<MyMesh>::VertexFromQualityRange(B,0,std::numeric_limits<float>::max());
155  for(MyMesh::FaceIterator fi=B.face.begin();fi!=B.face.end();++fi)
156  if(!(*fi).IsD() && (*fi).IsS() ) tri::Allocator<MyMesh>::DeleteFace(B,*fi);
158 
160 
161  MyMesh Cap;
162  CapHole(A,Cap,0);
164 
165  CapHole(B,Cap,0);
167 
170  return true;
171 }
172 
173 void GetRandPlane(Box3f &bb, Plane3f &plane)
174 {
175  Point3f planeCenter = bb.Center();
176  Point3f planeDir = Point3f(-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX);
177  planeDir.Normalize();
178 
179  plane.Init(planeCenter+planeDir*0.3f*bb.Diag()*float(rand())/RAND_MAX,planeDir);
180 }
181 
182 int main( int argc, char **argv )
183 {
184  if(argc<2)
185  {
186  printf("Usage trimesh_base <meshfilename.ply>\n");
187  return -1;
188  }
189 
190  MyMesh m, // The loaded mesh
191  em, // the 2D polyline representing the section
192  slice, // the planar mesh resulting from the triangulation of the above
193  sliced; // the 3D mesh resulting by the actual slicing of m into two capped sub pieces
194 
195  if(tri::io::ImporterPLY<MyMesh>::Open(m,argv[1])!=0)
196  {
197  printf("Error reading file %s\n",argv[1]);
198  exit(0);
199  }
201  printf("Input mesh vn:%i fn:%i\n",m.VN(),m.FN());
202  srand(time(0));
203 
204  Plane3f slicingPlane;
205  GetRandPlane(m.bbox,slicingPlane);
206  printf("slicing dir %5.2f %5.2f %5.2f\n",slicingPlane.Direction()[0],slicingPlane.Direction()[1],slicingPlane.Direction()[2]);
207  vcg::IntersectionPlaneMesh<MyMesh, MyMesh, float>(m, slicingPlane, em );
209  vcg::tri::CapEdgeMesh(em,slice);
210  printf("Slice mesh has %i vert and %i faces\n", slice.VN(), slice.FN() );
211 
212  MyMesh A,B;
213  SplitMesh(m,A,B,slicingPlane);
214  tri::UpdatePosition<MyMesh>::Translate(A, slicingPlane.Direction()*m.bbox.Diag()/80.0);
215  tri::UpdatePosition<MyMesh>::Translate(B,-slicingPlane.Direction()*m.bbox.Diag()/80.0);
218  printf("Sliced mesh has %i vert and %i faces\n", sliced.VN(), sliced.FN() );
219 
220  tri::io::ExporterPLY<MyMesh>::Save(slice,"slice.ply",false);
221  tri::io::ExporterPLY<MyMesh>::Save(sliced,"sliced.ply",false);
222 
223  return 0;
224 }