DGtal  1.5.beta
testNormalCycleComputer.cpp
Go to the documentation of this file.
1 
31 #include <iostream>
32 #include <vector>
33 #include <algorithm>
34 #include "DGtal/base/Common.h"
35 #include "DGtal/kernel/SpaceND.h"
36 #include "DGtal/shapes/SurfaceMesh.h"
37 #include "DGtal/shapes/SurfaceMeshHelper.h"
38 #include "DGtal/geometry/meshes/NormalCycleComputer.h"
39 #include "DGtalCatch.h"
41 
42 using namespace std;
43 using namespace DGtal;
44 
45 
47 // Functions for testing class NormalCycleComputer.
49 
50 SCENARIO( "NormalCycleComputer sphere tests", "[nc][sphere]" )
51 {
52  using namespace Z3i;
56 
57  SM sphere = SMH::makeSphere( 1.0, RealPoint { 0.0, 0.0, 0.0 }, 10, 10,
58  SMH::NormalsType::FACE_NORMALS );
59  NCComputer nc_computer ( sphere );
60  GIVEN( "A discretized sphere of radius 1 with 10x10 quadrangles and triangles" ) {
61  THEN( "Its total mu0 measure is close to 4*pi (area)" ) {
62  auto mu0 = nc_computer .computeMu0();
63  double total_area = mu0.measure();
64  Approx sphere_area = Approx( 4.0 * M_PI ).epsilon(0.05);
65  REQUIRE( total_area == sphere_area );
66  }
67  THEN( "Its total mu1 measure is close to 8*pi (twice mean curvature)" ) {
68  auto mu1 = nc_computer .computeMu1();
69  double total_mu1 = mu1.measure();
70  Approx twice_mean_c = Approx( 8.0 * M_PI ).epsilon(0.05);
71  REQUIRE( total_mu1 == twice_mean_c );
72  }
73  THEN( "Its total mu2 measure is close to 4*pi (Gaussian curvature)" ) {
74  auto mu2 = nc_computer .computeMu2();
75  double total_mu2 = mu2.measure();
76  Approx gaussian_c = Approx( 4.0 * M_PI ).epsilon(0.05);
77  REQUIRE( total_mu2 == gaussian_c );
78  }
79  }
80 }
81 
82 SCENARIO( "NormalCycleComputer Schwarz lantern tests", "[nc][lantern]" )
83 {
84  using namespace Z3i;
88 
89  SM lantern = SMH::makeLantern( 1.0, 1.0, RealPoint { 0.0, 0.0, 0.0 }, 30, 12,
90  SMH::NormalsType::VERTEX_NORMALS );
91  NCComputer nc_computer ( lantern );
92  GIVEN( "A discretized lantern of radius 1 with 30x12x2 triangles" ) {
93  THEN( "Its total mu0 measure is close to 2*pi (area)" ) {
94  auto mu0 = nc_computer .computeMu0();
95  double total_area = mu0.measure();
96  Approx lantern_area = Approx( 2.0 * M_PI ).epsilon(0.05);
97  REQUIRE( total_area != lantern_area );
98  }
99  THEN( "Its total mu1 measure is not close to 2*pi (twice mean curvature)" ) {
100  auto mu1 = nc_computer .computeMu1();
101  double total_mu1 = mu1.measure();
102  Approx twice_mean_c = Approx( 2.0 * M_PI ).epsilon(0.05);
103  REQUIRE( total_mu1 != twice_mean_c );
104  }
105  THEN( "Its total mu2 measure not close to 0 (Gaussian curvature)" ) {
106  auto mu2 = nc_computer .computeMu2();
107  double total_mu2 = mu2.measure();
108  Approx gaussian_c = Approx( 0.0 ).epsilon(0.05);
109  REQUIRE( total_mu2 != gaussian_c );
110  }
111  }
112 }
113 
114 
115 SCENARIO( "NormalCycleComputer convergence tests", "[nc][convergence]" )
116 {
117  using namespace Z3i;
121 
122  GIVEN( "A sphere of radius 1 discretized finer and finer" ) {
123  THEN( "The total mu0 measure tends toward the sphere area" ) {
124  std::vector< double > errors_mu0;
125  for ( unsigned int n = 10; n < 50; n += 10 )
126  {
127  SM sphere = SMH::makeSphere( 1.0, RealPoint { 0.0, 0.0, 0.0 }, n, n,
128  SMH::NormalsType::VERTEX_NORMALS );
129  NCComputer nc_computer ( sphere );
130  auto mu0 = nc_computer .computeMu0();
131  errors_mu0.push_back( mu0.measure() );
132  }
133  double sphere_area = 4.0 * M_PI;
134  for ( auto & v : errors_mu0 ) v = fabs( v - sphere_area ) / sphere_area;
135  for ( auto i = 0; i < (int)errors_mu0.size()-1; i++ ) {
136  REQUIRE( errors_mu0[ i+1 ] < errors_mu0[ i ] );
137  }
138  }
139  }
140  GIVEN( "A sphere of radius 1 discretized finer and finer" ) {
141  THEN( "The total mu1 measure tends toward twice the sphere area" ) {
142  std::vector< double > errors_mu1;
143  for ( unsigned int n = 10; n < 50; n += 10 )
144  {
145  SM sphere = SMH::makeSphere( 1.0, RealPoint { 0.0, 0.0, 0.0 }, n, n,
146  SMH::NormalsType::VERTEX_NORMALS );
147  NCComputer nc_computer ( sphere );
148  auto mu1 = nc_computer .computeMu1();
149  errors_mu1.push_back( mu1.measure() );
150  }
151  double sphere_twice_mc = 8.0 * M_PI;
152  for ( auto & v : errors_mu1 ) v = fabs( v - sphere_twice_mc ) / sphere_twice_mc;
153  for ( auto i = 0; i < (int)errors_mu1.size()-1; i++ ) {
154  REQUIRE( errors_mu1[ i+1 ] < errors_mu1[ i ] );
155  }
156  }
157  }
158  GIVEN( "A sphere of radius 1 discretized finer and finer" ) {
159  THEN( "The total mu2 measure is the sphere area" ) {
160  std::vector< double > errors_mu2;
161  for ( unsigned int n = 10; n < 50; n += 10 )
162  {
163  SM sphere = SMH::makeSphere( 1.0, RealPoint { 0.0, 0.0, 0.0 }, n, n,
164  SMH::NormalsType::VERTEX_NORMALS );
165  NCComputer nc_computer ( sphere );
166  auto mu2 = nc_computer .computeMu2();
167  errors_mu2.push_back( mu2.measure() );
168  }
169  double sphere_gauss_c = 4.0 * M_PI;
170  for ( auto & v : errors_mu2 ) v = fabs( v - sphere_gauss_c ) / sphere_gauss_c;
171  for ( size_t i = 0; i < errors_mu2.size(); i++ ) {
172  REQUIRE( errors_mu2[ i ] == Approx( 0.0 ).margin( 1e-8 ) );
173  }
174  }
175  }
176 }
177 
178 // //
DGtal is the top-level namespace which contains all DGtal functions and types.
Aim: Utility class to compute curvatures measures induced by (1) the normal cycle induced by a Surfac...
Aim: An helper class for building classical meshes.
Aim: Represents an embedded mesh as faces and a list of vertices. Vertices may be shared among faces ...
Definition: SurfaceMesh.h:92
GIVEN("A cubical complex with random 3-cells")
SCENARIO("NormalCycleComputer sphere tests", "[nc][sphere]")
REQUIRE(domain.isInside(aPoint))