DGtal  1.5.beta
testTriangulatedSurface.cpp File Reference
#include <iostream>
#include <algorithm>
#include "DGtal/base/Common.h"
#include "ConfigTest.h"
#include "DGtalCatch.h"
#include "DGtal/helpers/StdDefs.h"
#include "DGtal/kernel/PointVector.h"
#include "DGtal/graph/CUndirectedSimpleGraph.h"
#include "DGtal/graph/BreadthFirstVisitor.h"
#include "DGtal/shapes/TriangulatedSurface.h"
#include "DGtal/shapes/MeshHelpers.h"
Include dependency graph for testTriangulatedSurface.cpp:

Go to the source code of this file.

Typedefs

typedef PointVector< 3, double > RealPoint
 
typedef TriangulatedSurface< RealPointTriMesh
 
typedef TriMesh::VertexRange VertexRange
 
typedef TriMesh::ArcRange ArcRange
 
typedef TriMesh::Arc ArcT
 
typedef TriMesh::Face Face
 
typedef TriMesh::Vertex Vertex
 
typedef TriMesh::PositionsMap PositionsMap
 

Functions

TriMesh makeTwoTriangles ()
 
 SCENARIO ("TriangulatedSurface< RealPoint3 > build tests", "[trisurf][build]")
 
 SCENARIO ("TriangulatedSurface< RealPoint3 > flip tests", "[trisurf][flip]")
 
 SCENARIO ("TriangulatedSurface< RealPoint3 > concept check tests", "[trisurf][concepts]")
 

Detailed Description

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Author
Jacques-Olivier Lachaud (jacqu.nosp@m.es-o.nosp@m.livie.nosp@m.r.la.nosp@m.chaud.nosp@m.@uni.nosp@m.v-sav.nosp@m.oie..nosp@m.fr ) Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
Date
2017/02/06

Functions for testing class TriangulatedSurface.

This file is part of the DGtal library.

Definition in file testTriangulatedSurface.cpp.

Typedef Documentation

◆ ArcRange

Definition at line 54 of file testTriangulatedSurface.cpp.

◆ ArcT

typedef TriMesh::Arc ArcT

Definition at line 55 of file testTriangulatedSurface.cpp.

◆ Face

Examples
shapes/exampleSurfaceMesh.cpp.

Definition at line 56 of file testTriangulatedSurface.cpp.

◆ PositionsMap

◆ RealPoint

◆ TriMesh

◆ Vertex

◆ VertexRange

Function Documentation

◆ makeTwoTriangles()

TriMesh makeTwoTriangles ( )

Definition at line 60 of file testTriangulatedSurface.cpp.

61 {
62  TriMesh mesh;
63  mesh.addVertex( RealPoint( 0, 0, 0 ) );
64  mesh.addVertex( RealPoint( 1, 0, 0 ) );
65  mesh.addVertex( RealPoint( 0, 1, 0 ) );
66  mesh.addVertex( RealPoint( 1, 1, 1 ) );
67  mesh.addTriangle( 0, 1, 2 );
68  mesh.addTriangle( 2, 1, 3 );
69  mesh.build();
70  return mesh;
71 }
Aim: Represents a triangulated surface. The topology is stored with a half-edge data structure....
VertexIndex addVertex(const Point &vdata)
FaceIndex addTriangle(VertexIndex v0, VertexIndex v1, VertexIndex v2)
PointVector< 3, double > RealPoint

References DGtal::TriangulatedSurface< TPoint >::addTriangle(), DGtal::TriangulatedSurface< TPoint >::addVertex(), and DGtal::TriangulatedSurface< TPoint >::build().

Referenced by SCENARIO().

◆ SCENARIO() [1/3]

SCENARIO ( "TriangulatedSurface< RealPoint3 > build tests"  ,
""  [trisurf][build] 
)

Definition at line 73 of file testTriangulatedSurface.cpp.

74 {
75  GIVEN( "Two triangles incident by an edge" ) {
76  TriMesh trimesh = makeTwoTriangles();
77  THEN( "The mesh has 4 vertices, v0 has 2 neighbors, v1 has 3 neighbors, etc" ) {
78  REQUIRE( trimesh.size() == 4 );
79  REQUIRE( trimesh.degree( 0 ) == 2 );
80  REQUIRE( trimesh.degree( 1 ) == 3 );
81  REQUIRE( trimesh.degree( 2 ) == 3 );
82  REQUIRE( trimesh.degree( 3 ) == 2 );
83  }
84  THEN( "Euler number is 1 as is the Euler number of a disk." )
85  {
86  REQUIRE( trimesh.nbVertices() == 4 );
87  REQUIRE( trimesh.nbEdges() == 5 );
88  REQUIRE( trimesh.nbFaces() == 2 );
89  REQUIRE( trimesh.Euler() == 1 );
90  }
91  THEN( "Breadth-first visiting the mesh from vertex 3, visit 3, then {1,2}, then 0." )
92  {
93  BreadthFirstVisitor< TriMesh > visitor( trimesh, 3 );
94  std::vector<unsigned long> vertices;
95  std::vector<unsigned long> distances;
96  while ( ! visitor.finished() )
97  {
98  vertices.push_back( visitor.current().first );
99  distances.push_back( visitor.current().second );
100  visitor.expand();
101  }
102  REQUIRE( vertices.size() == 4 );
103  REQUIRE( distances.size() == 4 );
104  int expected_vertices1[] = { 3, 1, 2, 0};
105  int expected_vertices2[] = { 3, 2, 1, 0};
106  int expected_distance [] = { 0, 1, 1, 2};
107  bool vertices_ok
108  = std::equal( vertices.begin(), vertices.end(), expected_vertices1 )
109  || std::equal( vertices.begin(), vertices.end(), expected_vertices2 );
110  REQUIRE( vertices_ok );
111  bool distances_ok
112  = std::equal( distances.begin(), distances.end(), expected_distance );
113  REQUIRE( distances_ok );
114  }
115  THEN( "The mesh has 4 boundary vertices" ) {
116  VertexRange bv = trimesh.allBoundaryVertices();
117  std::sort( bv.begin(), bv.end() );
118  int expected_bv [] = { 0, 1, 2, 3};
119  REQUIRE( bv.size() == 4 );
120  bool bv_ok = std::equal( bv.begin(), bv.end(), expected_bv );
121  REQUIRE( bv_ok );
122  }
123  THEN( "The mesh has 4 boundary arcs" ) {
124  ArcRange ba = trimesh.allBoundaryArcs();
125  REQUIRE( ba.size() == 4 );
126  }
127  THEN( "The face along (1,2) is a triangle (0,1,2)" ) {
128  ArcT a12 = trimesh.arc( 1, 2 );
129  Face f = trimesh.faceAroundArc( a12 );
130  ArcRange A = trimesh.arcsAroundFace( f );
131  VertexRange T = trimesh.verticesAroundFace( f );
132  REQUIRE( A.size() == 3 );
133  REQUIRE( T.size() == 3 );
134  REQUIRE( trimesh.head( A[ 0 ] ) == T[ 0 ] );
135  REQUIRE( trimesh.head( A[ 1 ] ) == T[ 1 ] );
136  REQUIRE( trimesh.head( A[ 2 ] ) == T[ 2 ] );
137  std::sort( T.begin(), T.end() );
138  REQUIRE( T[ 0 ] == 0 );
139  REQUIRE( T[ 1 ] == 1 );
140  REQUIRE( T[ 2 ] == 2 );
141  }
142  THEN( "The face along (2,1) is a triangle (2,1,3)" ) {
143  ArcT a21 = trimesh.arc( 2, 1 );
144  Face f = trimesh.faceAroundArc( a21 );
145  VertexRange T = trimesh.verticesAroundFace( f );
146  REQUIRE( T.size() == 3 );
147  std::sort( T.begin(), T.end() );
148  REQUIRE( T[ 0 ] == 1 );
149  REQUIRE( T[ 1 ] == 2 );
150  REQUIRE( T[ 2 ] == 3 );
151  }
152  THEN( "The mesh has the barycenter (0.5, 0.5, 0.25) " ) {
153  PositionsMap positions = trimesh.positions();
154  RealPoint b;
155  for ( Vertex v = 0; v < trimesh.size(); ++v )
156  b += positions( v );
157  b /= 4;
158  REQUIRE( b[ 0 ] == 0.5 );
159  REQUIRE( b[ 1 ] == 0.5 );
160  REQUIRE( b[ 2 ] == 0.25 );
161  }
162  THEN( "We can convert the triangulated surface to a mesh and vice versa" ) {
163  Mesh<RealPoint> mesh;
164  MeshHelpers::triangulatedSurface2Mesh( trimesh, mesh );
165  TriMesh trimesh2;
166  MeshHelpers::mesh2TriangulatedSurface( mesh, trimesh2 );
167  REQUIRE( mesh.nbVertex() == trimesh.nbVertices() );
168  REQUIRE( mesh.nbFaces() == trimesh.nbFaces() );
169  REQUIRE( trimesh2.nbVertices() == trimesh.nbVertices() );
170  REQUIRE( trimesh2.nbArcs() == trimesh.nbArcs() );
171  REQUIRE( trimesh2.nbFaces() == trimesh.nbFaces() );
172  }
173  THEN( "We can iterate over the vertices" ) {
174  PositionsMap positions = trimesh.positions();
175  RealPoint exp_positions[] = { { 0,0,0 }, { 1,0,0 }, { 0,1,0 }, { 1,1,1 } };
176  for ( auto it = trimesh.begin(), itE = trimesh.end(); it != itE; ++it ) {
177  REQUIRE( positions[ *it ] == exp_positions[ *it ] );
178  }
179  }
180  }
181 }
Aim: This class is useful to perform a breadth-first exploration of a graph given a starting point or...
Aim: This class is defined to represent a surface mesh through a set of vertices and faces....
Definition: Mesh.h:92
Size nbFaces() const
Size nbVertex() const
Size degree(const Vertex &v) const
VertexRange allBoundaryVertices() const
ConstIterator begin() const
Vertex head(const Arc &a) const
Arc arc(const Vertex &t, const Vertex &h) const
ArcRange arcsAroundFace(const Face &f) const
ArcRange allBoundaryArcs() const
VertexRange verticesAroundFace(const Face &f) const
Face faceAroundArc(const Arc &a) const
std::pair< typename graph_traits< DGtal::DigitalSurface< TDigitalSurfaceContainer > >::vertex_iterator, typename graph_traits< DGtal::DigitalSurface< TDigitalSurfaceContainer > >::vertex_iterator > vertices(const DGtal::DigitalSurface< TDigitalSurfaceContainer > &digSurf)
GIVEN("A cubical complex with random 3-cells")
REQUIRE(domain.isInside(aPoint))
TriMesh::VertexRange VertexRange
TriMesh::Face Face
TriMesh::Arc ArcT
TriMesh::ArcRange ArcRange
TriMesh makeTwoTriangles()
TriMesh::Vertex Vertex

References DGtal::TriangulatedSurface< TPoint >::allBoundaryArcs(), DGtal::TriangulatedSurface< TPoint >::allBoundaryVertices(), DGtal::TriangulatedSurface< TPoint >::arc(), DGtal::TriangulatedSurface< TPoint >::arcsAroundFace(), DGtal::TriangulatedSurface< TPoint >::begin(), DGtal::BreadthFirstVisitor< TGraph, TMarkSet >::current(), DGtal::TriangulatedSurface< TPoint >::degree(), DGtal::TriangulatedSurface< TPoint >::end(), DGtal::TriangulatedSurface< TPoint >::Euler(), DGtal::BreadthFirstVisitor< TGraph, TMarkSet >::expand(), DGtal::TriangulatedSurface< TPoint >::faceAroundArc(), DGtal::BreadthFirstVisitor< TGraph, TMarkSet >::finished(), GIVEN(), DGtal::TriangulatedSurface< TPoint >::head(), makeTwoTriangles(), DGtal::TriangulatedSurface< TPoint >::nbArcs(), DGtal::TriangulatedSurface< TPoint >::nbEdges(), DGtal::Mesh< TPoint >::nbFaces(), DGtal::TriangulatedSurface< TPoint >::nbFaces(), DGtal::Mesh< TPoint >::nbVertex(), DGtal::TriangulatedSurface< TPoint >::nbVertices(), DGtal::TriangulatedSurface< TPoint >::positions(), REQUIRE(), DGtal::TriangulatedSurface< TPoint >::size(), and DGtal::TriangulatedSurface< TPoint >::verticesAroundFace().

◆ SCENARIO() [2/3]

SCENARIO ( "TriangulatedSurface< RealPoint3 > concept check tests"  ,
""  [trisurf][concepts] 
)

Definition at line 216 of file testTriangulatedSurface.cpp.

217 {
218  BOOST_CONCEPT_ASSERT(( concepts::CUndirectedSimpleGraph< TriMesh > ));
219 }
Aim: Represents the concept of local graph: each vertex has neighboring vertices, but we do not neces...

◆ SCENARIO() [3/3]

SCENARIO ( "TriangulatedSurface< RealPoint3 > flip tests"  ,
""  [trisurf][flip] 
)

Definition at line 183 of file testTriangulatedSurface.cpp.

184 {
185  GIVEN( "Two triangles incident by an edge" ) {
186  TriMesh trimesh = makeTwoTriangles();
187  auto nbv = trimesh.nbVertices();
188  auto nbe = trimesh.nbEdges();
189  auto nbf = trimesh.nbFaces();
190  int nbfl = 0;
191  ArcT afl = 0;
192  for ( ArcT a = 0; a < trimesh.nbArcs(); a++ )
193  if ( trimesh.isFlippable( a ) ) {
194  nbfl++;
195  afl = a;
196  }
197  THEN( "Only two arcs are flippable" ){
198  REQUIRE( nbfl == 2 );
199  }
200  THEN( "The mesh has same number of vertices, edges, faces after flip." ) {
201  trimesh.flip( afl );
202  REQUIRE( trimesh.nbVertices() == nbv );
203  REQUIRE( trimesh.nbEdges() == nbe );
204  REQUIRE( trimesh.nbFaces() == nbf );
205  }
206  THEN( "Edge (1,2) has 4 vertices around, in order (2,0,1,3)." ) {
207  VertexRange V = trimesh.verticesOfFacesAroundArc( trimesh.arc( 1, 2 ) );
208  int expected_V [] = { 2, 0, 1, 3};
209  REQUIRE( V.size() == 4 );
210  bool V_ok = std::equal( V.begin(), V.end(), expected_V );
211  REQUIRE( V_ok );
212  }
213  }
214 }
VertexRange verticesOfFacesAroundArc(const Arc a) const
bool isFlippable(const Arc a) const
void flip(const Arc a)

References DGtal::TriangulatedSurface< TPoint >::arc(), DGtal::TriangulatedSurface< TPoint >::flip(), GIVEN(), DGtal::TriangulatedSurface< TPoint >::isFlippable(), makeTwoTriangles(), DGtal::TriangulatedSurface< TPoint >::nbArcs(), DGtal::TriangulatedSurface< TPoint >::nbEdges(), DGtal::TriangulatedSurface< TPoint >::nbFaces(), DGtal::TriangulatedSurface< TPoint >::nbVertices(), REQUIRE(), and DGtal::TriangulatedSurface< TPoint >::verticesOfFacesAroundArc().