DGtal 1.3.0
Loading...
Searching...
No Matches
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
42using namespace std;
43using namespace DGtal;
44
45
47// Functions for testing class CorrectedNormalCurrentComputer.
49
50SCENARIO( "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
93SCENARIO( "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
136SCENARIO( "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
178SCENARIO( "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
221SCENARIO( "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 < 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 < 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 < errors_mu2.size()-1; i++ ) {
278 REQUIRE( errors_mu2[ i+1 ] < errors_mu2[ i ] );
279 }
280 }
281 }
282}
283
284SCENARIO( "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 < 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 < errors_mu1.size()-1; i++ ) {
323 REQUIRE( errors_mu1[ i+1 ] < errors_mu1[ i ] );
324 }
325 }
326 }
327}
328
329// //
Aim: Implements basic operations that will be used in Point and Vector classes.
Definition: PointVector.h:593
DGtal is the top-level namespace which contains all DGtal functions and types.
STL namespace.
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
GIVEN("A cubical complex with random 3-cells")
REQUIRE(domain.isInside(aPoint))
SCENARIO("UnorderedSetByBlock< PointVector< 2, int > unit tests with 32 bits blocks", "[unorderedsetbyblock][2d]")