VCG Library
trimesh_closest.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 // stuff to define the mesh
25 #include <vcg/complex/complex.h>
26 #include <vcg/simplex/face/component_ep.h>
27 #include <vcg/complex/algorithms/update/component_ep.h>
28 #include <vcg/complex/algorithms/point_sampling.h>
29 
30 #include <wrap/io_trimesh/import.h>
31 #include <wrap/io_trimesh/export_ply.h>
32 
33 
34 class BaseVertex;
35 class BaseEdge;
36 class BaseFace;
37 
38 struct BaseUsedTypes: public vcg::UsedTypes<vcg::Use<BaseVertex>::AsVertexType,vcg::Use<BaseEdge>::AsEdgeType,vcg::Use<BaseFace>::AsFaceType>{};
39 
40 class BaseVertex : public vcg::Vertex< BaseUsedTypes,
41  vcg::vertex::Coord3f, vcg::vertex::Normal3f, vcg::vertex::BitFlags > {};
42 
43 class BaseEdge : public vcg::Edge< BaseUsedTypes> {};
44 
45 class BaseFace : public vcg::Face< BaseUsedTypes,
46  vcg::face::Normal3f, vcg::face::VertexRef, vcg::face::BitFlags, vcg::face::Mark, vcg::face::EmptyEdgePlane > {};
47 
48 class BaseMesh : public vcg::tri::TriMesh<std::vector<BaseVertex>, std::vector<BaseFace> > {};
49 
50 
51 class RTVertex;
52 class RTEdge;
53 class RTFace;
54 
55 struct RTUsedTypes: public vcg::UsedTypes<vcg::Use<RTVertex>::AsVertexType,vcg::Use<RTEdge>::AsEdgeType,vcg::Use<RTFace>::AsFaceType>{};
56 
57 class RTVertex : public vcg::Vertex< RTUsedTypes,
58  vcg::vertex::Coord3f, vcg::vertex::Normal3f, vcg::vertex::BitFlags > {};
59 
60 class RTEdge : public vcg::Edge< RTUsedTypes> {};
61 
62 class RTFace : public vcg::Face< RTUsedTypes,
63  vcg::face::Normal3f, vcg::face::VertexRef, vcg::face::EdgePlane, vcg::face::Mark, vcg::face::BitFlags > {};
64 
65 class RTMesh : public vcg::tri::TriMesh<std::vector<RTVertex>, std::vector<RTFace> > {};
66 
67 
68 using namespace vcg;
69 
70 void Usage()
71 {
72  printf( "\nUsage: trimesh_closest mesh.ply samplenum sampledistance(as fraction of bboxdiag)");
73  exit(-1);
74 }
75 
76 // Testing of closest point on a mesh functionalities
77 // Two main options
78 // - using or not precomputed edges and planes
79 // - using the simple wrapper or the basic functions of the grid.
80 // - using the fn as size of the grid or the edge lenght as cell side
81 
82 template <class MeshType, bool useEdge,bool useWrap, bool useFaceNumForGrid>
83 bool UnitTest_Closest(const char *filename1, int sampleNum, float dispPerc, std::vector<int> resultVec)
84 {
85  MeshType mr;
86  typedef typename MeshType::ScalarType ScalarType;
87  typedef typename MeshType::CoordType CoordType;
88  typedef typename MeshType::FaceType FaceType;
89  typedef GridStaticPtr<FaceType, ScalarType> TriMeshGrid;
90 
91  int startOpen=clock();
92  int err=vcg::tri::io::Importer<MeshType>::Open(mr,filename1);
94 // tri::UpdateNormals<MeshType>::PerFaceNormalized(mr);
96  float dispAbs = mr.bbox.Diag()*dispPerc;
97  if(err)
98  {
99  std::cerr << "Unable to open mesh " << filename1 << " : " << vcg::tri::io::Importer<MeshType>::ErrorMsg(err) << std::endl;
100  exit(-1);
101  }
102  int endOpen = clock();
103  printf("Loading %6.3f - ",float(endOpen-startOpen)/CLOCKS_PER_SEC);
104 
105  int startSampling = clock();
106 
107  std::vector<Point3f> MontecarloSamples;
108  // First step build the sampling
109  typedef tri::TrivialSampler<MeshType> BaseSampler;
110  BaseSampler mcSampler(MontecarloSamples);
113  math::MarsenneTwisterRNG rnd;
114  rnd.initialize(123);
115  for(size_t i=0;i<MontecarloSamples.size();++i)
116  {
117  Point3f pp(rnd.generate01(),rnd.generate01(),rnd.generate01());
118  pp = (pp+Point3f(-0.5f,-0.5f,-0.5f))*2.0f;
119  pp*=rnd.generate01()*dispAbs;
120  MontecarloSamples[i]+=pp;
121  }
122  int endSampling = clock();
123 
124  printf("Sampling %6.3f - ",float(endSampling-startSampling)/CLOCKS_PER_SEC);
125 
126  int startGridInit = clock();
127  TriMeshGrid TRGrid;
128  if(useFaceNumForGrid)
129  {
130  TRGrid.Set(mr.face.begin(),mr.face.end(),mr.FN()*2);
131  }
132  else
133  {
134  float avgEdge = tri::Stat<MeshType>::ComputeEdgeLengthAverage(mr);
135  TRGrid.SetWithRadius(mr.face.begin(),mr.face.end(),avgEdge*2);
136  }
137 
138  if(useEdge)
140 
141  int endGridInit = clock();
142  printf("Grid Init %6.3f - ",float(endGridInit-startGridInit)/CLOCKS_PER_SEC);
143 
144  const ScalarType maxDist=std::max(dispAbs*10.0f,mr.bbox.Diag()/1000.f);
145  CoordType closest;
146  ScalarType dist;
147  int startGridQuery = clock();
148  double avgDist=0;
149  resultVec.resize(MontecarloSamples.size());
150  if(useEdge && useWrap)
151  for(size_t i=0;i<MontecarloSamples.size();++i)
152  {
153  resultVec[i]=tri::Index(mr,tri::GetClosestFaceEP(mr,TRGrid,MontecarloSamples[i], maxDist,dist,closest));
154  if(resultVec[i]) avgDist += double(dist);
155  }
156  if(!useEdge && useWrap)
157  for(size_t i=0;i<MontecarloSamples.size();++i)
158  {
159  resultVec[i]=tri::Index(mr,tri::GetClosestFaceBase(mr,TRGrid,MontecarloSamples[i], maxDist,dist,closest));
160  if(resultVec[i]) avgDist += double(dist);
161  }
162  if(useEdge && !useWrap)
163  {
164  typedef tri::FaceTmark<MeshType> MarkerFace;
165  MarkerFace mf;
166  mf.SetMesh(&mr);
167  face::PointDistanceBaseFunctor<ScalarType> PDistFunct;
168  for(size_t i=0;i<MontecarloSamples.size();++i)
169  {
170  resultVec[i]=tri::Index(mr,TRGrid.GetClosest(PDistFunct,mf,MontecarloSamples[i],maxDist,dist,closest));
171  if(resultVec[i]) avgDist += double(dist);
172  }
173  }
174  if(!useEdge && !useWrap)
175  {
176  typedef tri::FaceTmark<MeshType> MarkerFace;
177  MarkerFace mf;
178  mf.SetMesh(&mr);
179  face::PointDistanceBaseFunctor<ScalarType> PDistFunct;
180  for(size_t i=0;i<MontecarloSamples.size();++i)
181  {
182  resultVec[i]=tri::Index(mr,TRGrid.GetClosest(PDistFunct,mf,MontecarloSamples[i],maxDist,dist,closest));
183  if(resultVec[i]) avgDist += double(dist);
184  }
185  }
186 
187  int endGridQuery = clock();
188  printf("Grid Size %3i %3i %3i - ",TRGrid.siz[0],TRGrid.siz[1],TRGrid.siz[2]);
189  printf("Avg dist %6.9lf - ",avgDist / float(MontecarloSamples.size()));
190  printf("Grid Query %6.3f \n", float(endGridQuery-startGridQuery)/CLOCKS_PER_SEC);
191  return true;
192 }
193 
194 int main(int argc ,char**argv)
195 {
196  if(argc<3) Usage();
197  float dispPerc = atof(argv[3]);
198  int sampleNum = atoi(argv[2]);
199  std::vector<int> resultVecRT11;
200  std::vector<int> resultVecRT01;
201  std::vector<int> resultVecRT00;
202  std::vector<int> resultVecRT10;
203  std::vector<int> resultVecBS01;
204  std::vector<int> resultVecBS00;
205  UnitTest_Closest<RTMesh, true, true, true> (argv[1],sampleNum,dispPerc,resultVecRT11);
206  UnitTest_Closest<RTMesh, true, true, false> (argv[1],sampleNum,dispPerc,resultVecRT11);
207  UnitTest_Closest<RTMesh, true, false, true> (argv[1],sampleNum,dispPerc,resultVecRT01);
208  UnitTest_Closest<RTMesh, true, false, false> (argv[1],sampleNum,dispPerc,resultVecRT00);
209  UnitTest_Closest<RTMesh, false, true, true> (argv[1],sampleNum,dispPerc,resultVecRT10);
210  UnitTest_Closest<RTMesh, false, true, false> (argv[1],sampleNum,dispPerc,resultVecRT10);
211  UnitTest_Closest<RTMesh, false, false, true> (argv[1],sampleNum,dispPerc,resultVecRT10);
212  UnitTest_Closest<RTMesh, false, false, false> (argv[1],sampleNum,dispPerc,resultVecRT10);
213 
214  UnitTest_Closest<BaseMesh,false, true, true> (argv[1],sampleNum,dispPerc,resultVecBS01);
215  UnitTest_Closest<BaseMesh,false, true, false> (argv[1],sampleNum,dispPerc,resultVecBS01);
216  UnitTest_Closest<BaseMesh,false, false, true>(argv[1],sampleNum,dispPerc,resultVecBS01);
217  UnitTest_Closest<BaseMesh,false, false, false>(argv[1],sampleNum,dispPerc,resultVecBS01);
218 
219  for(size_t i=0;i<resultVecRT11.size();++i)
220  {
221  if(resultVecRT11[i]!=resultVecRT01[i]) printf("%lu is diff",i);
222  if(resultVecRT11[i]!=resultVecRT00[i]) printf("%lu is diff",i);
223  if(resultVecRT11[i]!=resultVecRT10[i]) printf("%lu is diff",i);
224  if(resultVecRT11[i]!=resultVecBS00[i]) printf("%lu is diff",i);
225  if(resultVecRT11[i]!=resultVecBS01[i]) printf("%lu is diff",i);
226  }
227  return 0;
228 }