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/PolygonalSurface.h"
41 #include "DGtal/shapes/MeshHelpers.h"
45 using namespace DGtal;
79 SCENARIO(
"PolygonalSurface< RealPoint3 > build tests",
"[polysurf][build]" )
85 typedef PolygonMesh::Arc Arc;
89 GIVEN(
"A box with an open side" ) {
90 PolygonMesh polymesh =
makeBox();
91 THEN(
"The mesh has 10 vertices, v0 has 3 neighbors, v1 has 3 neighbors, etc" ) {
92 REQUIRE( polymesh.size() == 10 );
93 REQUIRE( polymesh.degree( 0 ) == 3 );
94 REQUIRE( polymesh.degree( 1 ) == 3 );
95 REQUIRE( polymesh.degree( 2 ) == 3 );
96 REQUIRE( polymesh.degree( 3 ) == 3 );
97 REQUIRE( polymesh.degree( 4 ) == 4 );
98 REQUIRE( polymesh.degree( 5 ) == 4 );
99 REQUIRE( polymesh.degree( 6 ) == 3 );
100 REQUIRE( polymesh.degree( 7 ) == 3 );
101 REQUIRE( polymesh.degree( 8 ) == 2 );
102 REQUIRE( polymesh.degree( 9 ) == 2 );
104 THEN(
"Euler number is 1 as is the Euler number of a disk." )
106 REQUIRE( polymesh.nbVertices() == 10 );
107 REQUIRE( polymesh.nbEdges() == 15 );
108 REQUIRE( polymesh.nbFaces() == 6 );
109 REQUIRE( polymesh.Euler() == 1 );
111 THEN(
"Breadth-first visiting the mesh from vertex 0, visit {0}, then {1,2,4}, then {3,5,6,9}, then {7,8}." )
114 std::vector<unsigned long> vertices;
115 std::vector<unsigned long> distances;
118 vertices.push_back( visitor.
current().first );
119 distances.push_back( visitor.
current().second );
122 REQUIRE( vertices.size() == 10 );
123 REQUIRE( distances.size() == 10 );
124 int expected_vertices[] = { 0, 1, 2, 4, 3, 5, 6, 9, 7, 8 };
125 int expected_distance[] = { 0, 1, 1, 1, 2, 2, 2, 2, 3, 3 };
126 auto itb = vertices.begin();
127 std::sort( itb+1, itb+4 );
128 std::sort( itb+4, itb+8 );
129 std::sort( itb+8, itb+10 );
131 = std::equal( vertices.begin(), vertices.end(), expected_vertices );
134 = std::equal( distances.begin(), distances.end(), expected_distance );
137 THEN(
"The mesh has 6 boundary vertices" ) {
139 std::sort( bv.begin(), bv.end() );
140 int expected_bv [] = { 4, 5, 6, 7, 8, 9 };
142 bool bv_ok = std::equal( bv.begin(), bv.end(), expected_bv );
145 THEN(
"The mesh has 6 boundary arcs" ) {
146 ArcRange ba = polymesh.allBoundaryArcs();
149 THEN(
"The face along (1,3) is a quadrangle (1,3,7,5)" ) {
150 Arc a13 = polymesh.arc( 1, 3 );
151 Face f = polymesh.faceAroundArc( a13 );
152 ArcRange A = polymesh.arcsAroundFace( f );
156 REQUIRE( polymesh.head( A[ 0 ] ) == T[ 0 ] );
157 REQUIRE( polymesh.head( A[ 1 ] ) == T[ 1 ] );
158 REQUIRE( polymesh.head( A[ 2 ] ) == T[ 2 ] );
159 REQUIRE( polymesh.head( A[ 3 ] ) == T[ 3 ] );
160 std::sort( T.begin(), T.end() );
166 THEN(
"The face along (3,1) is a quadrangle (3,1,0,2)" ) {
167 Arc a31 = polymesh.arc( 3, 1 );
168 Face f = polymesh.faceAroundArc( a31 );
171 std::sort( T.begin(), T.end() );
177 THEN(
"The lower part of the mesh has the barycenter (0.5, 0.5, 0.5) " ) {
180 for (
Vertex v = 0; v < 8; ++v )
187 THEN(
"We can convert the triangulated surface to a mesh and vice versa" ) {
189 MeshHelpers::polygonalSurface2Mesh( polymesh, mesh );
190 PolygonMesh polymesh2;
191 MeshHelpers::mesh2PolygonalSurface( mesh, polymesh2 );
194 REQUIRE( polymesh2.nbVertices() == polymesh.nbVertices() );
195 REQUIRE( polymesh2.nbArcs() == polymesh.nbArcs() );
196 REQUIRE( polymesh2.nbFaces() == polymesh.nbFaces() );
198 THEN(
"We can iterate over the vertices" ) {
200 RealPoint exp_positions[] = { { 0,0,0 }, { 1,0,0 }, { 0,1,0 }, { 1,1,0 },
201 { 0,0,1 }, { 1,0,1 }, { 0,1,1 }, { 1,1,1 },
202 { 1,0,2 }, { 0,0,2 } };
203 for (
auto it = polymesh.begin(), itE = polymesh.end(); it != itE; ++it ) {
204 REQUIRE( positions[ *it ] == exp_positions[ *it ] );
210 SCENARIO(
"PolygonalSurface< RealPoint3 > concept check tests",
"[polysurf][concepts]" )
Aim: This class is useful to perform a breadth-first exploration of a graph given a starting point or...
const Node & current() const
Aim: This class is defined to represent a surface mesh through a set of vertices and faces....
Aim: Represents a polygon mesh, i.e. a 2-dimensional combinatorial surface whose faces are (topologic...
DGtal is the top-level namespace which contains all DGtal functions and types.
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")
HalfEdgeDataStructure::PolygonalFace PolygonalFace
PolygonalSurface< PointVector< 3, double > > makeBox()
SCENARIO("PolygonalSurface< RealPoint3 > build tests", "[polysurf][build]")
REQUIRE(domain.isInside(aPoint))
TriMesh::VertexRange VertexRange
TriMesh::PositionsMap PositionsMap
PointVector< 3, double > RealPoint
TriMesh::ArcRange ArcRange