DGtal  1.4.beta
testMesh.cpp
Go to the documentation of this file.
1 
31 #include <iostream>
32 #include "DGtal/base/Common.h"
33 #include "DGtal/helpers/StdDefs.h"
34 #include "DGtal/io/writers/MeshWriter.h"
35 #include "DGtal/shapes/Mesh.h"
37 
38 using namespace std;
39 using namespace DGtal;
40 using namespace DGtal::Z2i;
41 
42 
43 
45 // Functions for testing class Mesh.
47 
51 bool testMesh()
52 {
53 
54  trace.beginBlock ( "Testing Mesh ..." );
55  bool ok = true;
56  trace.beginBlock ( "Testing Mesh contruction ..." );
57  Mesh<Point> aMesh;
58  Point p0=Point(0,0);
59  Point p1=Point(0,1);
60  Point p2=Point(1,2);
61  Point p3=Point(3,2);
62  Point p4=Point(3,3);
63  Point p5=Point(3,4);
64 
65  aMesh.addVertex(p0);
66  aMesh.addVertex(p1);
67  aMesh.addVertex(p2);
68  aMesh.addVertex(p3);
69  aMesh.addVertex(p4);
70  aMesh.addVertex(p5);
71 
72  aMesh.addTriangularFace(0,1,2);
73  aMesh.addTriangularFace(3,4,5);
74 
75  Mesh<Point>::MeshFace tface0 = aMesh.getFace(0);
76  Mesh<Point>::MeshFace tface1 = aMesh.getFace(1);
77  Point p0f0 = aMesh.getVertex(tface0.at(0));
78  Point p1f0 = aMesh.getVertex(tface0.at(1));
79  Point p2f0 = aMesh.getVertex(tface0.at(2));
80 
81  Point p0f1 = aMesh.getVertex(tface1.at(0));
82  Point p1f1 = aMesh.getVertex(tface1.at(1));
83  Point p2f1 = aMesh.getVertex(tface1.at(2));
84  trace.info() << "Set of points" << endl;
85  trace.info() << p0 << p1 << p2 << endl;
86  trace.info() << p3 << p4 << p5 << endl;
87 
88  trace.info() << "Face1 points " << endl;
89  trace.info() << p0f0 << p1f0 << p2f0<< endl;
90 
91  trace.info() << "Face2 points " << endl;
92  trace.info() << p0f1 << p1f1 << p2f1<< endl;
93 
94  //Checking inversion
95  aMesh.invertVertexFaceOrder();
96  aMesh.invertVertexFaceOrder();
97 
98 
99  bool okMeshConstruct = (p0==p0f0) && (p1==p1f0) && (p2==p2f0) &&
100  (p3==p0f1) && (p4==p1f1) && (p5==p2f1) ;
101 
102  trace.endBlock();
103  bool okMeshIterators = true;
104  trace.beginBlock ( "Testing Mesh iterator ..." );
105  unsigned int nb=0;
106  // just testing nb iterations on const iterator
108  it !=aMesh.vertexEnd();
109  it++){
110  nb++;
111  }
112  okMeshIterators = okMeshIterators && (nb == aMesh.nbVertex());
113  if (nb == aMesh.nbVertex())
114  trace.info() << "vertex iteration test ok"<<std::endl;
115 
116  // testing to change vertex on iterator
118  it !=aMesh.vertexEnd();
119  it++){
120  (*it)[0]+=10; (*it)[1]+=5;
121  }
122  // just testing nb iterations on const iterator
123  nb=0;
125  it !=aMesh.faceEnd();
126  it++){
127  nb++;
128  }
129  okMeshIterators = okMeshIterators && (nb == aMesh.nbFaces());
130  if (nb == aMesh.nbFaces())
131  trace.info() << "face iteration test ok"<<std::endl;
132 
133  nb=0;
134  // just testing nb iterations on const iterator
136  it !=aMesh.faceEnd();
137  it++){
138  nb++;
139  }
140  okMeshIterators = okMeshIterators && ((nb == aMesh.nbFaces()) && ((aMesh.getVertex(5))[0]==13)) && aMesh.getFaceBarycenter(0)==Mesh<Point>::RealPoint(31.0/3.0,6.0);
141  if ((nb == aMesh.nbFaces()) && (aMesh.getVertex(5))[0]==13 && aMesh.getFaceBarycenter(0)==Mesh<Point>::RealPoint(31.0/3.0,6.0))
142  trace.info() << "getVertex and getFaceCenter tests ok"<<std::endl;
143 
144  // testing changing color of individual face:
146  bool okMeshColor = (aMesh.getFaceColor(0)==DGtal::Color::White)
147  && (aMesh.getFaceColor(1)==DGtal::Color::Red) ;
148 
149  trace.endBlock();
150 
151  trace.beginBlock ( "Testing Mesh Bouding box and scale change ..." );
152  aMesh.changeScale(2);
153  std::pair<Point, Point> bb = aMesh.getBoundingBox();
154  bool boundingBoxOK = (bb.first == Point(20,10)) && (bb.second == Point(26,18));
155  trace.info() << "bouding box=" << bb.first << " " << bb.second << "(should be (20,10) (26,18)" <<std::endl;
156  trace.endBlock();
157 
158  trace.beginBlock ( "Testing mesh subdivision ..." );
159  Mesh<RealPoint> aMeshR;
160  RealPoint pr0 (0,0);
161  RealPoint pr1 (1,0);
162  RealPoint pr2 (1,1);
163  aMeshR.addVertex(pr0); aMeshR.addVertex(pr1); aMeshR.addVertex(pr2);
164  aMeshR.addTriangularFace(0,1,2);
165  trace.info() << "nb vertices before subdivision: " << aMeshR.nbVertex() << std::endl;
166  trace.info() << "nb faces before subdivision: " << aMeshR.nbFaces() << std::endl;
167  aMeshR.subDivideTriangularFaces(0.5);
168  trace.info() << "nb vertices after subdivision: " << aMeshR.nbVertex() << " (should be 4)"<<std::endl;
169  trace.info() << "nb faces after subdivision: " << aMeshR.nbFaces() << " (should be 3)" <<std::endl;
170  trace.info() << "New point: " << aMeshR.getVertex(aMeshR.nbVertex()-1) << "(should be: "<< RealPoint(2.0/3.0, 1.0/3.0) << ") "<< std::endl;
171  bool okSubDivide = aMeshR.nbVertex()==4 && aMeshR.nbFaces()==3 &&
172  aMeshR.getVertex(aMeshR.nbVertex()-1) == RealPoint(2.0/3.0, 1.0/3.0);
173  trace.info() << (okSubDivide ? "[subdivise OK]":"[subdivise fail]" ) << std::endl;
174  trace.endBlock();
175 
176  trace.beginBlock ( "Testing mesh quad transform ..." );
177  Mesh<RealPoint> aMeshQ;
178  RealPoint pq0 (0,0);
179  RealPoint pq1 (1,0);
180  RealPoint pq2 (1,1);
181  RealPoint pq3 (0,1);
182  aMeshQ.addVertex(pq0); aMeshQ.addVertex(pq1); aMeshQ.addVertex(pq2);
183  aMeshQ.addVertex(pq3);
184  aMeshQ.addQuadFace(0,1,2,3);
185  aMeshQ.quadToTriangularFaces();
186 
187  trace.info() << "nb faces after quad to triangle transform: " << aMeshQ.nbFaces() ;
188  bool okQuadToTrans = aMeshQ.nbFaces() == 2;
189  trace.info() << "(should be 2) "<< (okQuadToTrans? "[ok]": "[error]") << std::endl;
190  trace.endBlock();
191 
192 
193  trace.beginBlock ( "Testing Mesh copy operator ..." );
194  Mesh<Point> aMesh2 = aMesh;
195  Mesh<Point> aMesh3 (aMesh2);
196  bool okMeshCopy = aMesh.nbFaces() == aMesh2.nbFaces() && aMesh.nbVertex() == aMesh2.nbVertex() &&
197  aMesh.nbFaces() == aMesh3.nbFaces() && aMesh.nbVertex() == aMesh3.nbVertex() &&
198  aMesh.getVertex(0) == aMesh2.getVertex(0) && aMesh.getVertex(0) == aMesh3.getVertex(0);
199  trace.info() << (okMeshCopy ? "[copy ok]":"[copy fail]" ) << std::endl;
200  trace.endBlock();
201 
202  trace.beginBlock ( "Testing face removing ..." );
203  Mesh<Point> aMesh4 = aMesh;
205  aMesh4.removeFaces(f);
206  bool okRemoveFace = (aMesh4.nbFaces() == aMesh.nbFaces()-1) && (aMesh4.nbVertex() == aMesh.nbVertex()-3);
207  trace.info() << (okRemoveFace ? "[face remove ok]":"[face remove fail]" ) << std::endl;
208 
209  ok = ok & okMeshConstruct && okMeshIterators && okMeshColor && okMeshCopy && boundingBoxOK &&
210  okSubDivide && okQuadToTrans && okRemoveFace;
211  trace.endBlock();
212  return ok;
213 
214 }
215 
216 
217 
222 {
223 
224  trace.beginBlock ( "Testing Mesh generation ..." );
225  bool ok = true;
226 
227  trace.beginBlock ( "Testing Tube generation ..." );
229  std::vector<Z3i::RealPoint> aSkeleton;
230  aSkeleton.push_back(Z3i::RealPoint(0.0, 0.0, 0.0));
231  aSkeleton.push_back(Z3i::RealPoint(10.0, 0.0, 0.0));
232  aSkeleton.push_back(Z3i::RealPoint(20.0, 0.0, 0.0));
233  aSkeleton.push_back(Z3i::RealPoint(30.0, 0.0, 0.0));
234  aSkeleton.push_back(Z3i::RealPoint(35.0, 5.0, 0.0));
235  aSkeleton.push_back(Z3i::RealPoint(40.0, 10.0, 0.0));
236  aSkeleton.push_back(Z3i::RealPoint(40.0, 20.0, 0.0));
237  aSkeleton.push_back(Z3i::RealPoint(40.0, 30.0, 0.0));
238  aSkeleton.push_back(Z3i::RealPoint(40.0, 35.0, 5.0));
239  aSkeleton.push_back(Z3i::RealPoint(40.0, 40.0, 10.0));
240  aSkeleton.push_back(Z3i::RealPoint(40.0, 40.0, 20.0));
242 
244  Mesh<Z3i::RealPoint> aMesh(true);
245  Mesh<Z3i::RealPoint>::createTubularMesh(aMesh, aSkeleton, 0.5, 0.2, DGtal::Color::Blue);
247 
248  trace.endBlock();
249  trace.info() << "Nb faces: "<< aMesh.nbFaces() << " (sould be 320)" << std::endl;
250  trace.info() << "Nb vertices: "<< aMesh.nbVertex() << " (sould be 352)" << std::endl;
251  bool okMeshTube1 = aMesh.nbFaces() == 320 && aMesh.nbVertex() == 352;
252 
253  trace.beginBlock ( "Testing Tube generation (bis with variable raidii ..." );
254  Mesh<Z3i::RealPoint> aMeshBis(true);
255  std::vector<double> vectRadii;
256  vectRadii.push_back(0.5);
257  vectRadii.push_back(1.5);
258  vectRadii.push_back(2.5);
259  Mesh<Z3i::RealPoint>::createTubularMesh(aMeshBis, aSkeleton, vectRadii, 0.2, DGtal::Color::Green);
260 
261  trace.endBlock();
262  trace.info() << "Nb faces: "<< aMeshBis.nbFaces() << " (sould be 320)" << std::endl;
263  trace.info() << "Nb vertices: "<< aMeshBis.nbVertex() << " (sould be 352)" << std::endl;
264 
265  std::ofstream ofbis ("tubeVariableRadiiGeneratedFromTestMesh.off");
266  DGtal::MeshWriter<Z3i::RealPoint>::export2OFF(ofbis, aMeshBis, true);
267  ofbis.close();
268  bool okMeshTube1bis = aMeshBis.nbFaces() == 320 && aMeshBis.nbVertex() == 352;
269 
270 
271  trace.beginBlock("Testing Mesh from Height sequence");
273  std::vector<double> heightSequence;
274  heightSequence.push_back(0.1);
275  heightSequence.push_back(0.2);
276  heightSequence.push_back(0.15);
277 
278  heightSequence.push_back(1.1);
279  heightSequence.push_back(2.2);
280  heightSequence.push_back(1.15);
281 
282  heightSequence.push_back(0.1);
283  heightSequence.push_back(0.2);
284  heightSequence.push_back(0.15);
286 
288  Mesh<Z3i::RealPoint>::createMeshFromHeightSequence(aMesh, heightSequence, 3, 10, 10, 3, DGtal::Color::Yellow);
290 
291  trace.info() << "Nb faces: "<< aMesh.nbFaces() << " (sould be 324)" << std::endl;
292  trace.info() << "Nb vertices: "<< aMesh.nbVertex() << " (sould be 361)" << std::endl;
293  bool okMeshTube1AndHF = aMesh.nbFaces() == 324 && aMesh.nbVertex() == 361;
294 
296  std::ofstream of ("tubeAndHeighFieldGeneratedFromTestMesh.off");
298  of.close();
300 
301  ok = ok & okMeshTube1 & okMeshTube1bis & okMeshTube1AndHF;
302  trace.endBlock();
303  return ok;
304 }
305 
306 
307 
312 {
313  unsigned int nbok = 0;
314  unsigned int nb = 0;
315 
316  trace.beginBlock("Testing visual tubular mesh generation (shell mesh):");
317  // Generate the center line:
318  std::vector<Z3i::RealPoint> centerline;
319  unsigned int nbPoints = 0;
320  double z = 0.0;
321  double radiusSpirale = 13.0;
322  double radiusTube = 15.0;
323  double alphaMax = 32.0;
324  double reduc = 0.05;
325  for (double alpha = 0; alpha< alphaMax; alpha += 0.1, z += 0.5-reduc)
326  {
327  centerline.push_back(Z3i::RealPoint(radiusSpirale*cos(alpha), radiusSpirale*sin(alpha), z ));
328  nbPoints++;
329  radiusSpirale -=reduc;
330  radiusSpirale = std::max(radiusSpirale, 0.0);
331  }
332  // Generate radius:
333  std::vector<double> vectRadius;
334  for(unsigned int i=0; i<nbPoints; i++)
335  {
336  vectRadius.push_back(radiusTube);
337  radiusTube -=reduc;
338  radiusTube = std::max(radiusTube, 0.0);
339  }
340 
341  DGtal::Mesh<Z3i::RealPoint> theMeshShell(true);
342  DGtal::Mesh<Z3i::RealPoint>::createTubularMesh(theMeshShell, centerline, vectRadius, 0.1);
343 
344  trace.info() << "Mesh generated with " << theMeshShell.nbFaces()
345  << " faces (should be " << (centerline.size()-1)*63 << " )" << std::endl;
346  nb++;
347  nbok += theMeshShell.nbFaces() == (centerline.size()-1)*63;
348  theMeshShell >> "spiraleGeneratedFromTestMesh.off";
349  trace.info() << " [done]" << std::endl;
350  trace.endBlock();
351 
352 
353 
354  trace.beginBlock("Testing visual tubular mesh generation (tube mesh):");
355  std::vector<Z3i::RealPoint> centerLine2;
356  centerLine2.push_back(Z3i::RealPoint(0.0,0.0,0.0));
357  centerLine2.push_back(Z3i::RealPoint(3.3,0.0,0.0));
358  centerLine2.push_back(Z3i::RealPoint(6.6,0.0,0.0));
359  centerLine2.push_back(Z3i::RealPoint(10.0,0.0,0.0));
360  centerLine2.push_back(Z3i::RealPoint(13.3,0.0,0.0));
361  centerLine2.push_back(Z3i::RealPoint(16.6,0.0,0.0));
362  centerLine2.push_back(Z3i::RealPoint(20.0,0.0,0.0));
363  centerLine2.push_back(Z3i::RealPoint(60.0,0.0,0.0));
364  centerLine2.push_back(Z3i::RealPoint(63.3,0.0,0.0));
365  centerLine2.push_back(Z3i::RealPoint(66.6,0.0,0.0));
366  centerLine2.push_back(Z3i::RealPoint(70.0,0.0,0.0));
367  centerLine2.push_back(Z3i::RealPoint(71.7,0.1,0.0));
368  centerLine2.push_back(Z3i::RealPoint(73.4,0.6,0.0));
369  centerLine2.push_back(Z3i::RealPoint(75.0,1.3,0.0));
370  centerLine2.push_back(Z3i::RealPoint(76.4,2.3,0.0));
371  centerLine2.push_back(Z3i::RealPoint(77.6,3.5,0.0));
372  centerLine2.push_back(Z3i::RealPoint(78.6,5.0,0.0));
373  centerLine2.push_back(Z3i::RealPoint(79.3,6.5,0.0));
374  centerLine2.push_back(Z3i::RealPoint(79.8,8.2,0.0));
375  centerLine2.push_back(Z3i::RealPoint(80.0,10.0,0.0));
376  centerLine2.push_back(Z3i::RealPoint(80.0,13.8,0.0));
377  centerLine2.push_back(Z3i::RealPoint(80.0,86.1,0.0));
378  centerLine2.push_back(Z3i::RealPoint(80.0,90.0,0.0));
379  centerLine2.push_back(Z3i::RealPoint(80.1,91.7,-0.1));
380  centerLine2.push_back(Z3i::RealPoint(80.6,93.4,0.1));
381  centerLine2.push_back(Z3i::RealPoint(81.3,95.0,0.1));
382  centerLine2.push_back(Z3i::RealPoint(82.3,96.4,-0.1));
383  centerLine2.push_back(Z3i::RealPoint(83.5,97.6,-0.1));
384 
385  DGtal::Mesh<Z3i::RealPoint> theMeshTube(true);
387  5.0, 0.2, DGtal::Color::Blue);
388 
389  trace.info() << "Mesh generated with " << theMeshTube.nbFaces() << " faces (should be "
390  << (centerLine2.size()-1)*32 << " )" << std::endl;
391  nb++;
392  nbok += theMeshTube.nbFaces() == (centerLine2.size()-1)*32;
393 
394  theMeshTube >> "tubeGeneratedFromTestMesh.off";
395  trace.endBlock();
396 
397  return nb == nbok;
398 
399 }
400 
402 // Standard services - public :
403 
404 int main( int argc, char** argv )
405 {
406  trace.beginBlock ( "Testing class Mesh" );
407  trace.info() << "Args:";
408  for ( int i = 0; i < argc; ++i )
409  trace.info() << " " << argv[ i ];
410  trace.info() << endl;
411 
412  bool res = testMesh() && testMeshGeneration() && testVisualTubularMesh();
413  trace.emphase() << ( res ? "Passed." : "Error." ) << endl;
414  trace.endBlock();
415  return res ? 0 : 1;
416 }
417 // //
static const Color Yellow
Definition: Color.h:422
static const Color Green
Definition: Color.h:417
static const Color Red
Definition: Color.h:416
static const Color White
Definition: Color.h:415
static const Color Blue
Definition: Color.h:419
Aim: This class is defined to represent a surface mesh through a set of vertices and faces....
Definition: Mesh.h:92
const TPoint & getVertex(Index i) const
void addQuadFace(Index indexVertex1, Index indexVertex2, Index indexVertex3, Index indexVertex4, const DGtal::Color &aColor=DGtal::Color::White)
Size nbFaces() const
RealPoint getFaceBarycenter(Index i) const
unsigned int quadToTriangularFaces()
Size nbVertex() const
void changeScale(const typename TPoint::Component aScale)
std::pair< TPoint, TPoint > getBoundingBox() const
void setFaceColor(Index i, const DGtal::Color &aColor)
const Color & getFaceColor(Index i) const
const MeshFace & getFace(Index i) const
FaceStorage::const_iterator faceEnd() const
Definition: Mesh.h:414
void invertVertexFaceOrder()
ConstIterator vertexEnd() const
Definition: Mesh.h:369
std::vector< Index > MeshFace
Definition: Mesh.h:126
void removeFaces(const std::vector< Index > &facesIndex)
double subDivideTriangularFaces(const double minArea)
void addTriangularFace(Index indexVertex1, Index indexVertex2, Index indexVertex3, const DGtal::Color &aColor=DGtal::Color::White)
FaceStorage::const_iterator faceBegin() const
Definition: Mesh.h:402
ConstIterator vertexBegin() const
Definition: Mesh.h:359
static void createTubularMesh(Mesh< TPoint > &aMesh, const std::vector< TPoint > &aSkeleton, const double aRadius, const double angleStep=0.2, const DGtal::Color &aMeshColor=DGtal::Color::White)
void addVertex(const TPoint &vertex)
void beginBlock(const std::string &keyword="")
std::ostream & emphase()
std::ostream & info()
double endBlock()
SMesh::Index Index
Z2i this namespace gathers the standard of types for 2D imagery.
DGtal is the top-level namespace which contains all DGtal functions and types.
Trace trace
Definition: Common.h:153
static bool export2OFF(std::ostream &out, const Mesh< TPoint > &aMesh, bool exportColor=true)
int max(int a, int b)
MyPointD Point
Definition: testClone2.cpp:383
bool testMeshGeneration()
Definition: testMesh.cpp:221
int main(int argc, char **argv)
Definition: testMesh.cpp:404
bool testMesh()
Definition: testMesh.cpp:51
bool testVisualTubularMesh()
Definition: testMesh.cpp:311
PointVector< 3, double > RealPoint