DGtal 1.3.0
Loading...
Searching...
No Matches
testTriangulatedSurface.cpp
Go to the documentation of this file.
1
31#include <iostream>
32#include <algorithm>
33#include "DGtal/base/Common.h"
34#include "ConfigTest.h"
35#include "DGtalCatch.h"
36#include "DGtal/helpers/StdDefs.h"
37#include "DGtal/kernel/PointVector.h"
38#include "DGtal/graph/CUndirectedSimpleGraph.h"
39#include "DGtal/graph/BreadthFirstVisitor.h"
40#include "DGtal/shapes/TriangulatedSurface.h"
41#include "DGtal/shapes/MeshHelpers.h"
43
44using namespace std;
45using namespace DGtal;
46
48// Functions for testing class TriangulatedSurface.
50
55typedef TriMesh::Arc ArcT; //Arc already defined in wingdi.h
59
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}
72
73SCENARIO( "TriangulatedSurface< RealPoint3 > build tests", "[trisurf][build]" )
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;
165 TriMesh 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}
182
183SCENARIO( "TriangulatedSurface< RealPoint3 > flip tests", "[trisurf][flip]" )
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}
215
216SCENARIO( "TriangulatedSurface< RealPoint3 > concept check tests", "[trisurf][concepts]" )
217{
218 BOOST_CONCEPT_ASSERT(( concepts::CUndirectedSimpleGraph< TriMesh > ));
219}
220
Aim: This class is useful to perform a breadth-first exploration of a graph given a starting point or...
const Node & current() const
static bool mesh2TriangulatedSurface(const Mesh< Point > &mesh, TriangulatedSurface< Point > &trisurf)
static void triangulatedSurface2Mesh(const TriangulatedSurface< Point > &trisurf, Mesh< Point > &mesh)
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
Aim: Implements basic operations that will be used in Point and Vector classes.
Definition: PointVector.h:593
Aim: Represents a triangulated surface. The topology is stored with a half-edge data structure....
Size degree(const Vertex &v) const
VertexRange verticesOfFacesAroundArc(const Arc a) const
VertexRange allBoundaryVertices() const
ConstIterator begin() const
HalfEdgeDataStructure::HalfEdgeIndex Arc
std::vector< Vertex > VertexRange
HalfEdgeDataStructure::FaceIndex Face
Vertex head(const Arc &a) const
bool isFlippable(const Arc a) const
Arc arc(const Vertex &t, const Vertex &h) const
ArcRange arcsAroundFace(const Face &f) const
ArcRange allBoundaryArcs() const
void flip(const Arc a)
VertexIndex addVertex(const Point &vdata)
FaceIndex addTriangle(VertexIndex v0, VertexIndex v1, VertexIndex v2)
VertexRange verticesAroundFace(const Face &f) const
Face faceAroundArc(const Arc &a) const
DGtal is the top-level namespace which contains all DGtal functions and types.
STL namespace.
Aim: Represents the concept of local graph: each vertex has neighboring vertices, but we do not neces...
GIVEN("A cubical complex with random 3-cells")
REQUIRE(domain.isInside(aPoint))
TriMesh::VertexRange VertexRange
TriMesh::PositionsMap PositionsMap
TriMesh::Face Face
TriMesh::Arc ArcT
TriangulatedSurface< RealPoint > TriMesh
PointVector< 3, double > RealPoint
TriMesh::ArcRange ArcRange
TriMesh makeTwoTriangles()
TriMesh::Vertex Vertex
SCENARIO("UnorderedSetByBlock< PointVector< 2, int > unit tests with 32 bits blocks", "[unorderedsetbyblock][2d]")