DGtal  1.4.2
testMeshVoxelization.cpp
Go to the documentation of this file.
1 
28 #include <iostream>
29 #include "ConfigTest.h"
30 #include "DGtalCatch.h"
31 #include "DGtal/shapes/MeshVoxelizer.h"
32 #include "DGtal/kernel/sets/CDigitalSet.h"
33 #include "DGtal/kernel/domains/HyperRectDomain.h"
34 #include "DGtal/io/readers/MeshReader.h"
35 #include "DGtal/io/Display3D.h"
36 #include "DGtal/io/readers/MeshReader.h"
37 #include "DGtal/io/boards/Board3D.h"
39 
40 using namespace DGtal;
41 using namespace Z3i;
42 
43 TEST_CASE("Basic voxelization test", "[voxelization]")
44 {
45  using PointR3 = PointVector<3, double>;
46  using VectorR3 = PointVector<3, double>;
47  using PointR2 = PointVector<2, double>;
48  using PointZ3 = PointVector<3, int>;
49 
50  using MeshVoxelizer26 = MeshVoxelizer< DigitalSet, 26>;
51  using MeshVoxelizer6 = MeshVoxelizer< DigitalSet, 6>;
52 
53  using TriOr = MeshVoxelizer6::TriangleOrientation;
54 
55  // ---------------------------------------------------------
56  SECTION("Test distance point/plan 3D")
57  {
58  // Triangle ABC in R3
59  const PointR3 A(38.6908 , 14.5441 , -0.71205);
60  const PointR3 B(34.6171 , 13.5999 , 2.44455);
61  const PointR3 C(37.4205 , 2.44239 , 6.31301);
62 
63  // Point v
64  const PointZ3 v(35, 2, 5);
65 
66  const VectorR3 e1 = A - B;
67  const VectorR3 e2 = A - C;
68 
69  double distance = MeshVoxelizer6::distance(A, e1.crossProduct(e2), v);
70 
71  REQUIRE( 2.40 < distance );
72  REQUIRE( distance < 2.41 );
73  }
74 
75  // ---------------------------------------------------------
76  SECTION("Test if 2D point is inside triangle 2D")
77  {
78  // Triangle ABC in R2
79  PointR2 A(1.0, 1.0);
80  PointR2 B(2.0, 3.0);
81  PointR2 C(3.0, 1.0);
82 
83  typedef InHalfPlaneBySimple3x3Matrix<PointR2, double> OrientationFunctor;
84  OrientationFunctor orientationFunctor;
85 
86  //geometric predicate
87  PredicateFromOrientationFunctor2<OrientationFunctor> pointPredicate( orientationFunctor );
88 
89  if(! pointPredicate(A, B, C))
90  {
91  std::swap(A, C);
92  }
93 
94  // Test if point v is inside triangle ABC
95  // 0 : outside
96  // 1 : inside
97  // 2 : on edge
98  // 3 : on vertex
99  PointR2 v;
100 
101  v[0] = 3.0;
102  v[1] = 3.0;
103  REQUIRE(MeshVoxelizer6::pointIsInside2DTriangle(A, B, C, v) == TriOr::TRIANGLE_OUTSIDE);
104 
105  v[0] = 2.0;
106  v[1] = 2.0;
107  REQUIRE(MeshVoxelizer6::pointIsInside2DTriangle(A, B, C, v) == TriOr::TRIANGLE_INSIDE);
108 
109  v[0] = 2;
110  v[1] = 1;
111  REQUIRE(MeshVoxelizer6::pointIsInside2DTriangle(A, B, C, v) == TriOr::TRIANGLE_ONEDGE);
112 
113  v[0] = 3;
114  v[1] = 1;
115  REQUIRE(MeshVoxelizer6::pointIsInside2DTriangle(A, B, C, v) == TriOr::TRIANGLE_ONVERTEX);
116 
117  // another case
118  A = { 16.3299, 0. };
119  B = { 0., 16.3299 };
120  C = { -16.3299, 0. };
121  v = { -17., 0.};
122  REQUIRE(MeshVoxelizer6::pointIsInside2DTriangle(A, B, C, v) == TriOr::TRIANGLE_OUTSIDE);
123 
124  // another case
125  A = { -0.891282, 9.91201 };
126  B = { -1.40823, 9.91261 };
127  C = { -1.36963, 9.37414 };
128  v = { -1.16961, 9.83039 };
129  REQUIRE(MeshVoxelizer6::pointIsInside2DTriangle(A, B, C, v) == TriOr::TRIANGLE_INSIDE);
130  }
131 
132  // ---------------------------------------------------------
133  SECTION("Test if 3D point is inside voxel")
134  {
135  // Triangle ABC in R2
136  PointR3 P(-0.89, 9.91, 0.86);
137  PointZ3 v(-1, 10, 1);
138 
139  REQUIRE(MeshVoxelizer6::pointIsInsideVoxel(P, v) == true); // inside
140 
141  P[0] = -1.41;
142  P[1] = 9.91;
143  REQUIRE(MeshVoxelizer6::pointIsInsideVoxel(P, v) == true); // inside
144 
145  P[0] = -1.37;
146  P[1] = 9.37;
147  REQUIRE(MeshVoxelizer6::pointIsInsideVoxel(P, v) == false); // outside
148 
149  P[0] = -1.17;
150  P[1] = 9.83;
151  P[2] = 0;
152  REQUIRE(MeshVoxelizer6::pointIsInsideVoxel(P, v) == false); // outside
153  }
154 
155  // ---------------------------------------------------------
156  SECTION("26-sep voxelization of a single triangle")
157  {
158  Domain domain(Point(0,0,0), Point(10,10,10));
159  DigitalSet outputSet(domain);
160  MeshVoxelizer26 voxelizer;
161 
162  voxelizer.voxelize(outputSet, Point(5,0,0), Point(0,5,0), Point(0,0,5));
164  for(auto p: outputSet)
165  board << p ;
166  board.saveOBJ("triangle26-dig.obj");
167 
168  REQUIRE( outputSet.size() == 46 );
169  }
170 
171  // ---------------------------------------------------------
172  SECTION("6-sep voxelization of a single triangle")
173  {
174  Domain domain(Point(0,0,0), Point(10,10,10));
175  DigitalSet outputSet(domain);
176  MeshVoxelizer6 voxelizer;
177 
178  voxelizer.voxelize(outputSet, Point(5,0,0), Point(0,5,0), Point(0,0,5));
180  for(auto p: outputSet)
181  board << p ;
182  board.saveOBJ("triangle6-dig.obj");
183 
184  REQUIRE( outputSet.size() == 21 );
185  }
186 
187  // ---------------------------------------------------------
188  SECTION("6-sep voxelization of a OFF cube mesh")
189  {
190  //Importing OFF mesh
191  Mesh<Z3i::RealPoint> inputMesh;
192  MeshReader<Z3i::RealPoint>::importOFFFile(testPath +"/samples/box.off" , inputMesh);
193  Z3i::Domain domain( Point().diagonal(-30), Point().diagonal(30));
194  DigitalSet outputSet(domain);
195  MeshVoxelizer6 voxelizer;
196 
197  CAPTURE(inputMesh.nbFaces());
198 
199  voxelizer.voxelize(outputSet, inputMesh, 10.0 );
201  for(auto p: outputSet)
202  board << p ;
203  board.saveOBJ("box6-dig.obj");
204 
205  CAPTURE(outputSet.size());
206  //hard coded test.
207  REQUIRE( outputSet.size() == 2562 );
208  }
209  // ---------------------------------------------------------
210  SECTION("26-sep voxelization of a OFF cube mesh")
211  {
212  //Importing OFF mesh
213  Mesh<Z3i::RealPoint> inputMesh;
214  MeshReader<Z3i::RealPoint>::importOFFFile(testPath +"/samples/box.off" , inputMesh);
215  Z3i::Domain domain( Point().diagonal(-30), Point().diagonal(30));
216  DigitalSet outputSet(domain);
217  MeshVoxelizer26 voxelizer;
218 
219  CAPTURE(inputMesh.nbFaces());
220 
221  voxelizer.voxelize(outputSet, inputMesh, 10.0 );
223  for(auto p: outputSet)
224  board << p ;
225  board.saveOBJ("box26-dig.obj");
226 
227  CAPTURE(outputSet.size());
228  //hard coded test.
229  REQUIRE( outputSet.size() == 4162 );
230  }
231 }
The class Board3D is a type of Display3D which export the figures in the format OBJ/MTL when calling ...
Definition: Board3D.h:82
void saveOBJ(const std::string &filename, const bool isNormalized=false)
Aim: A wrapper class around a STL associative container for storing sets of digital points within som...
Aim: Class that implements an orientation functor, ie. it provides a way to compute the orientation o...
Aim: A class for computing the digitization of a triangle or a Mesh.
Definition: MeshVoxelizer.h:80
Aim: This class is defined to represent a surface mesh through a set of vertices and faces....
Definition: Mesh.h:92
Size nbFaces() const
Aim: Small adapter to models of COrientationFunctor2. It is a model of concepts::CPointPredicate....
Space::Point Point
Definition: StdDefs.h:168
DGtal is the top-level namespace which contains all DGtal functions and types.
static bool importOFFFile(const std::string &filename, DGtal::Mesh< TPoint > &aMesh, bool invertVertexOrder=false, bool onlyFaceVertex=false)
CAPTURE(thicknessHV)
TEST_CASE("Basic voxelization test", "[voxelization]")
Domain domain
SECTION("Testing constant forward iterators")
REQUIRE(domain.isInside(aPoint))