DGtal  1.5.beta
testCorrectedNormalCurrentComputer.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/CorrectedNormalCurrentComputer.h"
39 #include "DGtalCatch.h"
41 
42 using namespace std;
43 using namespace DGtal;
44 
45 
47 // Functions for testing class CorrectedNormalCurrentComputer.
49 
50 SCENARIO( "CorrectedNormalCurrentComputer interpolated curvature measures on sphere tests", "[icnc][sphere]" )
51 {
52  using namespace Z3i;
56 
57  SM sphere = SMH::makeSphere( 1.0, RealPoint { 0.0, 0.0, 0.0 }, 20, 20,
58  SMH::NormalsType::VERTEX_NORMALS );
59  CNCComputer cnc_computer ( sphere, false );
60  CNCComputer cncu_computer( sphere, true );
61  GIVEN( "A discretized sphere of radius 1 with 20x20x2 triangles" ) {
62  THEN( "Its total mu0 measure is close to 4*pi (area)" ) {
63  auto mu0 = cnc_computer .computeMu0();
64  auto mu0_u = cncu_computer.computeMu0();
65  double total_area = mu0.measure();
66  double total_area_u = mu0_u.measure();
67  Approx sphere_area = Approx( 4.0 * M_PI ).epsilon(0.05);
68  REQUIRE( total_area == sphere_area );
69  REQUIRE( total_area_u == sphere_area );
70  }
71  THEN( "Its total mu1 measure is close to 8*pi (twice mean curvature)" ) {
72  auto mu1 = cnc_computer .computeMu1();
73  auto mu1_u = cncu_computer.computeMu1();
74  double total_mu1 = mu1.measure();
75  double total_mu1_u = mu1_u.measure();
76  Approx twice_mean_c = Approx( 8.0 * M_PI ).epsilon(0.05);
77  REQUIRE( total_mu1 == twice_mean_c );
78  REQUIRE( total_mu1_u == twice_mean_c );
79  }
80  THEN( "Its total mu2 measure is close to 4*pi (Gaussian curvature)" ) {
81  auto mu2 = cnc_computer .computeMu2();
82  auto mu2_u = cncu_computer.computeMu2();
83  double total_mu2 = mu2.measure();
84  double total_mu2_u = mu2_u.measure();
85  Approx gaussian_c = Approx( 4.0 * M_PI ).epsilon(0.05);
86  REQUIRE( total_mu2 == gaussian_c );
87  Approx exact_gaussian_c = Approx( 4.0 * M_PI ).epsilon(0.000005);
88  REQUIRE( total_mu2_u == exact_gaussian_c );
89  }
90  }
91 }
92 
93 SCENARIO( "CorrectedNormalCurrentComputer face-constant curvature measures on sphere tests", "[ccnc][sphere]" )
94 {
95  using namespace Z3i;
99 
100  SM sphere = SMH::makeSphere( 1.0, RealPoint { 0.0, 0.0, 0.0 }, 20, 20,
101  SMH::NormalsType::FACE_NORMALS );
102  CNCComputer cnc_computer ( sphere, false );
103  CNCComputer cncu_computer( sphere, true );
104  GIVEN( "A discretized sphere of radius 1 with 20x20x2 triangles" ) {
105  THEN( "Its total mu0 measure is close to 4*pi (area)" ) {
106  auto mu0 = cnc_computer .computeMu0();
107  auto mu0_u = cncu_computer.computeMu0();
108  double total_area = mu0.measure();
109  double total_area_u = mu0_u.measure();
110  Approx sphere_area = Approx( 4.0 * M_PI ).epsilon(0.05);
111  REQUIRE( total_area == sphere_area );
112  REQUIRE( total_area_u == sphere_area );
113  }
114  THEN( "Its total mu1 measure is close to 8*pi (twice mean curvature)" ) {
115  auto mu1 = cnc_computer .computeMu1();
116  auto mu1_u = cncu_computer.computeMu1();
117  double total_mu1 = mu1.measure();
118  double total_mu1_u = mu1_u.measure();
119  Approx twice_mean_c = Approx( 8.0 * M_PI ).epsilon(0.05);
120  REQUIRE( total_mu1 == twice_mean_c );
121  REQUIRE( total_mu1_u == twice_mean_c );
122  }
123  THEN( "Its total mu2 measure is close to 4*pi (Gaussian curvature)" ) {
124  auto mu2 = cnc_computer .computeMu2();
125  auto mu2_u = cncu_computer.computeMu2();
126  double total_mu2 = mu2.measure();
127  double total_mu2_u = mu2_u.measure();
128  Approx gaussian_c = Approx( 4.0 * M_PI ).epsilon(0.05);
129  REQUIRE( total_mu2 == gaussian_c );
130  Approx exact_gaussian_c = Approx( 4.0 * M_PI ).epsilon(0.000005);
131  REQUIRE( total_mu2_u == exact_gaussian_c );
132  }
133  }
134 }
135 
136 SCENARIO( "CorrectedNormalCurrentComputer interpolated curvature measures on Schwarz lantern tests", "[icnc][lantern]" )
137 {
138  using namespace Z3i;
142 
143  SM lantern = SMH::makeLantern( 1.0, 1.0, RealPoint { 0.0, 0.0, 0.0 }, 30, 12,
144  SMH::NormalsType::VERTEX_NORMALS );
145  CNCComputer cnc_computer ( lantern, false );
146  CNCComputer cncu_computer( lantern, true );
147  GIVEN( "A discretized lantern of radius 1 with 30x12x2 triangles" ) {
148  THEN( "Its total mu0 measure is close to 2*pi (area)" ) {
149  auto mu0 = cnc_computer .computeMu0();
150  auto mu0_u = cncu_computer.computeMu0();
151  double total_area = mu0.measure();
152  double total_area_u = mu0_u.measure();
153  Approx lantern_area = Approx( 2.0 * M_PI ).epsilon(0.05);
154  REQUIRE( total_area == lantern_area );
155  REQUIRE( total_area_u == lantern_area );
156  }
157  THEN( "Its total mu1 measure is close to 2*pi (twice mean curvature)" ) {
158  auto mu1 = cnc_computer .computeMu1();
159  auto mu1_u = cncu_computer.computeMu1();
160  double total_mu1 = mu1.measure();
161  double total_mu1_u = mu1_u.measure();
162  Approx twice_mean_c = Approx( 2.0 * M_PI ).epsilon(0.05);
163  REQUIRE( total_mu1 == twice_mean_c );
164  REQUIRE( total_mu1_u == twice_mean_c );
165  }
166  THEN( "Its total mu2 measure is close to 0 (Gaussian curvature)" ) {
167  auto mu2 = cnc_computer .computeMu2();
168  auto mu2_u = cncu_computer.computeMu2();
169  double total_mu2 = mu2.measure();
170  double total_mu2_u = mu2_u.measure();
171  Approx exact_gaussian_c = Approx( 0.0 ).epsilon(0.000005);
172  REQUIRE( total_mu2 == exact_gaussian_c );
173  REQUIRE( total_mu2_u == exact_gaussian_c );
174  }
175  }
176 }
177 
178 SCENARIO( "CorrectedNormalCurrentComputer face-constant curvature measures on Schwarz lantern tests", "[ccnc][lantern]" )
179 {
180  using namespace Z3i;
184 
185  SM lantern = SMH::makeLantern( 1.0, 1.0, RealPoint { 0.0, 0.0, 0.0 }, 30, 12,
186  SMH::NormalsType::FACE_NORMALS );
187  CNCComputer cnc_computer ( lantern, false );
188  CNCComputer cncu_computer( lantern, true );
189  GIVEN( "A discretized lantern of radius 1 with 30x12x2 triangles" ) {
190  THEN( "Its total mu0 measure is close to 2*pi (area)" ) {
191  auto mu0 = cnc_computer .computeMu0();
192  auto mu0_u = cncu_computer.computeMu0();
193  double total_area = mu0.measure();
194  double total_area_u = mu0_u.measure();
195  Approx lantern_area = Approx( 2.0 * M_PI ).epsilon(0.05);
196  REQUIRE( total_area == lantern_area );
197  REQUIRE( total_area_u == lantern_area );
198  }
199  THEN( "Its total mu1 measure is close to 2*pi (twice mean curvature)" ) {
200  auto mu1 = cnc_computer .computeMu1();
201  auto mu1_u = cncu_computer.computeMu1();
202  double total_mu1 = mu1.measure();
203  double total_mu1_u = mu1_u.measure();
204  Approx twice_mean_c = Approx( 2.0 * M_PI ).epsilon(0.05);
205  REQUIRE( total_mu1 == twice_mean_c );
206  REQUIRE( total_mu1_u == twice_mean_c );
207  }
208  THEN( "Its total mu2 measure is close to 0 (Gaussian curvature)" ) {
209  auto mu2 = cnc_computer .computeMu2();
210  auto mu2_u = cncu_computer.computeMu2();
211  double total_mu2 = mu2.measure();
212  double total_mu2_u = mu2_u.measure();
213  Approx exact_gaussian_c = Approx( 0.0 ).epsilon(0.000005);
214  REQUIRE( total_mu2 == exact_gaussian_c );
215  REQUIRE( total_mu2_u == exact_gaussian_c );
216  }
217  }
218 }
219 
220 
221 SCENARIO( "CorrectedNormalCurrentComputer ICNC convergence tests", "[icnc][convergence]" )
222 {
223  using namespace Z3i;
227 
228  GIVEN( "A sphere of radius 1 discretized finer and finer" ) {
229  THEN( "The total mu0 measure tends toward the sphere area" ) {
230  std::vector< double > errors_mu0;
231  for ( unsigned int n = 10; n < 50; n += 10 )
232  {
233  SM sphere = SMH::makeSphere( 1.0, RealPoint { 0.0, 0.0, 0.0 }, n, n,
234  SMH::NormalsType::VERTEX_NORMALS );
235  CNCComputer cnc_computer ( sphere, false );
236  auto mu0 = cnc_computer .computeMu0();
237  errors_mu0.push_back( mu0.measure() );
238  }
239  double sphere_area = 4.0 * M_PI;
240  for ( auto & v : errors_mu0 ) v = fabs( v - sphere_area ) / sphere_area;
241  for ( auto i = 0; i < (int)errors_mu0.size()-1; i++ ) {
242  REQUIRE( errors_mu0[ i+1 ] < errors_mu0[ i ] );
243  }
244  }
245  }
246  GIVEN( "A sphere of radius 1 discretized finer and finer" ) {
247  THEN( "The total mu1 measure tends toward twice the sphere area" ) {
248  std::vector< double > errors_mu1;
249  for ( unsigned int n = 10; n < 50; n += 10 )
250  {
251  SM sphere = SMH::makeSphere( 1.0, RealPoint { 0.0, 0.0, 0.0 }, n, n,
252  SMH::NormalsType::VERTEX_NORMALS );
253  CNCComputer cnc_computer ( sphere, false );
254  auto mu1 = cnc_computer .computeMu1();
255  errors_mu1.push_back( mu1.measure() );
256  }
257  double sphere_twice_mc = 8.0 * M_PI;
258  for ( auto & v : errors_mu1 ) v = fabs( v - sphere_twice_mc ) / sphere_twice_mc;
259  for ( auto i = 0; i < (int)errors_mu1.size()-1; i++ ) {
260  REQUIRE( errors_mu1[ i+1 ] < errors_mu1[ i ] );
261  }
262  }
263  }
264  GIVEN( "A sphere of radius 1 discretized finer and finer" ) {
265  THEN( "The total mu2 measure tends toward the sphere area" ) {
266  std::vector< double > errors_mu2;
267  for ( unsigned int n = 10; n < 50; n += 10 )
268  {
269  SM sphere = SMH::makeSphere( 1.0, RealPoint { 0.0, 0.0, 0.0 }, n, n,
270  SMH::NormalsType::VERTEX_NORMALS );
271  CNCComputer cnc_computer ( sphere, false );
272  auto mu2 = cnc_computer .computeMu2();
273  errors_mu2.push_back( mu2.measure() );
274  }
275  double sphere_gauss_c = 4.0 * M_PI;
276  for ( auto & v : errors_mu2 ) v = fabs( v - sphere_gauss_c ) / sphere_gauss_c;
277  for ( auto i = 0; i < (int)errors_mu2.size()-1; i++ ) {
278  REQUIRE( errors_mu2[ i+1 ] < errors_mu2[ i ] );
279  }
280  }
281  }
282 }
283 
284 SCENARIO( "CorrectedNormalCurrentComputer CCNC convergence tests", "[ccnc][convergence]" )
285 {
286  using namespace Z3i;
290 
291  GIVEN( "A sphere of radius 1 discretized finer and finer" ) {
292  THEN( "The total mu0 measure tends toward the sphere area" ) {
293  std::vector< double > errors_mu0;
294  for ( unsigned int n = 10; n < 50; n += 10 )
295  {
296  SM sphere = SMH::makeSphere( 1.0, RealPoint { 0.0, 0.0, 0.0 }, n, n,
297  SMH::NormalsType::FACE_NORMALS );
298  CNCComputer cnc_computer ( sphere, false );
299  auto mu0 = cnc_computer .computeMu0();
300  errors_mu0.push_back( mu0.measure() );
301  }
302  double sphere_area = 4.0 * M_PI;
303  for ( auto & v : errors_mu0 ) v = fabs( v - sphere_area ) / sphere_area;
304  for ( auto i = 0; i < (int)errors_mu0.size()-1; i++ ) {
305  REQUIRE( errors_mu0[ i+1 ] < errors_mu0[ i ] );
306  }
307  }
308  }
309  GIVEN( "A sphere of radius 1 discretized finer and finer" ) {
310  THEN( "The total mu1 measure tends toward twice the sphere area" ) {
311  std::vector< double > errors_mu1;
312  for ( unsigned int n = 10; n < 50; n += 10 )
313  {
314  SM sphere = SMH::makeSphere( 1.0, RealPoint { 0.0, 0.0, 0.0 }, n, n,
315  SMH::NormalsType::FACE_NORMALS );
316  CNCComputer cnc_computer ( sphere, false );
317  auto mu1 = cnc_computer .computeMu1();
318  errors_mu1.push_back( mu1.measure() );
319  }
320  double sphere_twice_mc = 8.0 * M_PI;
321  for ( auto & v : errors_mu1 ) v = fabs( v - sphere_twice_mc ) / sphere_twice_mc;
322  for ( auto i = 0; i < (int)errors_mu1.size()-1; i++ ) {
323  REQUIRE( errors_mu1[ i+1 ] < errors_mu1[ i ] );
324  }
325  }
326  }
327 }
328 
329 // //
DGtal is the top-level namespace which contains all DGtal functions and types.
Aim: Utility class to compute curvature measures induced by (1) a corrected normal current defined by...
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
SCENARIO("CorrectedNormalCurrentComputer interpolated curvature measures on sphere tests", "[icnc][sphere]")
GIVEN("A cubical complex with random 3-cells")
REQUIRE(domain.isInside(aPoint))