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