Loading [MathJax]/extensions/TeX/AMSsymbols.js
DGtal 2.0.0
testConvexityHelper.cpp
Go to the documentation of this file.
1
16
29
31#include <iostream>
32#include <vector>
33#include <algorithm>
34#include "DGtal/base/Common.h"
35#include "DGtal/kernel/SpaceND.h"
36#include "DGtal/geometry/volumes/ConvexityHelper.h"
37#include "DGtal/shapes/SurfaceMesh.h"
38#include "DGtalCatch.h"
40
41using namespace std;
42using namespace DGtal;
43
44
46// Functions for testing class ConvexityHelper in 2D.
48
49SCENARIO( "ConvexityHelper< 2 > unit tests",
50 "[convexity_helper][lattice_polytope][2d]" )
51{
52 typedef ConvexityHelper< 2 > Helper;
53 typedef Helper::Point Point;
54 typedef ConvexCellComplex< Point > CvxCellComplex;
55 GIVEN( "Given a star { (0,0), (-4,-1), (-3,5), (7,3), (5, -2) } " ) {
56 std::vector<Point> V
57 = { Point(0,0), Point(-4,-1), Point(-3,5), Point(7,3), Point(5, -2) };
58 WHEN( "Computing its lattice polytope" ){
59 const auto P = Helper::computeLatticePolytope( V, false, true );
60 CAPTURE( P );
61 THEN( "The polytope is valid and has 4 non trivial facets" ) {
62 REQUIRE( P.nbHalfSpaces() - 4 == 4 );
63 }
64 THEN( "The polytope is Minkowski summable" ) {
65 REQUIRE( P.canBeSummed() );
66 }
67 THEN( "The polytope contains the input points" ) {
68 REQUIRE( P.isInside( V[ 0 ] ) );
69 REQUIRE( P.isInside( V[ 1 ] ) );
70 REQUIRE( P.isInside( V[ 2 ] ) );
71 REQUIRE( P.isInside( V[ 3 ] ) );
72 REQUIRE( P.isInside( V[ 4 ] ) );
73 }
74 THEN( "The polytope contains 58 points" ) {
75 REQUIRE( P.count() == 58 );
76 }
77 THEN( "The interior of the polytope contains 53 points" ) {
78 REQUIRE( P.countInterior() == 53 );
79 }
80 THEN( "The boundary of the polytope contains 5 points" ) {
81 REQUIRE( P.countBoundary() == 5 );
82 }
83 }
84 }
85 GIVEN( "Given a square with an additional outside vertex " ) {
86 std::vector<Point> V
87 = { Point(-10,-10), Point(10,-10), Point(-10,10), Point(10,10),
88 Point(0,18) };
89 WHEN( "Computing its Delaunay cell complex" ){
90 CvxCellComplex complex;
91 bool ok = Helper::computeDelaunayCellComplex( complex, V, false );
92 CAPTURE( complex );
93 THEN( "The complex has 2 cells, 6 faces, 5 vertices" ) {
94 REQUIRE( ok );
95 REQUIRE( complex.nbCells() == 2 );
96 REQUIRE( complex.nbFaces() == 6 );
97 REQUIRE( complex.nbVertices() == 5 );
98 }
99 THEN( "The faces of cells are finite" ) {
100 bool ok_finite = true;
101 for ( CvxCellComplex::Size c = 0; c < complex.nbCells(); ++c ) {
102 const auto faces = complex.cellFaces( c );
103 for ( auto f : faces )
104 ok_finite = ok_finite && ! complex.isInfinite( complex.faceCell( f ) );
105 }
106 REQUIRE( ok_finite );
107 }
108 THEN( "The opposite of faces of cells are infinite except two" ) {
109 int nb_finite = 0;
110 for ( CvxCellComplex::Size c = 0; c < complex.nbCells(); ++c ) {
111 const auto faces = complex.cellFaces( c );
112 for ( auto f : faces ) {
113 const auto opp_f = complex.opposite( f );
114 nb_finite += complex.isInfinite( complex.faceCell( opp_f ) ) ? 0 : 1;
115 }
116 }
117 REQUIRE( nb_finite == 2 );
118 }
119 }
120 }
121 GIVEN( "Given a degenerated polytope { (0,0), (3,-1), (9,-3), (-6,2) } " ) {
122 std::vector<Point> V
123 = { Point(0,0), Point(3,-1), Point(9,-3), Point(-6,2) };
124 WHEN( "Computing its lattice polytope" ){
125 const auto P = Helper::computeLatticePolytope( V, false, true );
126 CAPTURE( P );
127 THEN( "The polytope is valid and has 2 non trivial facets" ) {
128 REQUIRE( P.nbHalfSpaces() - 4 == 2 );
129 }
130 THEN( "The polytope contains 6 points" ) {
131 REQUIRE( P.count() == 6 );
132 }
133 THEN( "The polytope contains no interior points" ) {
134 REQUIRE( P.countInterior() == 0 );
135 }
136 }
137 WHEN( "Computing the vertices of its convex hull" ){
138 auto X = Helper::computeConvexHullVertices( V, false );
139 std::sort( X.begin(), X.end() );
140 CAPTURE( X );
141 THEN( "The polytope is a segment defined by two points" ) {
142 REQUIRE( X.size() == 2 );
143 REQUIRE( X[ 0 ] == Point(-6, 2) );
144 REQUIRE( X[ 1 ] == Point( 9,-3) );
145 }
146 }
147 }
148 GIVEN( "Given a degenerated simplex { (4,0), (7,2), (-5,-6) } " ) {
149 std::vector<Point> V
150 = { Point(4,0), Point(7,2), Point(-5,-6) };
151 WHEN( "Computing its lattice polytope" ){
152 const auto P = Helper::computeLatticePolytope( V, false, true );
153 CAPTURE( P );
154 THEN( "The polytope is valid and has 2 non trivial facets" ) {
155 REQUIRE( P.nbHalfSpaces() - 4 == 2 );
156 }
157 THEN( "The polytope contains 5 points" ) {
158 REQUIRE( P.count() == 5 );
159 }
160 THEN( "The polytope contains no interior points" ) {
161 REQUIRE( P.countInterior() == 0 );
162 }
163 }
164 WHEN( "Computing the vertices of its convex hull" ){
165 auto X = Helper::computeConvexHullVertices( V, false );
166 std::sort( X.begin(), X.end() );
167 CAPTURE( X );
168 THEN( "The polytope is a segment defined by two points" ) {
169 REQUIRE( X.size() == 2 );
170 REQUIRE( X[ 0 ] == Point(-5,-6) );
171 REQUIRE( X[ 1 ] == Point( 7, 2) );
172 }
173 }
174 }
175}
176
178// Functions for testing class ConvexityHelper in 3D.
180
181SCENARIO( "ConvexityHelper< 3 > unit tests",
182 "[convexity_helper][3d]" )
183{
184 typedef ConvexityHelper< 3 > Helper;
185 typedef Helper::Point Point;
186 typedef Helper::RealPoint RealPoint;
187 typedef Helper::RealVector RealVector;
189 typedef PolygonalSurface< Point > LatticePolySurf;
190 typedef ConvexCellComplex< Point > CvxCellComplex;
191 GIVEN( "Given an octahedron star { (0,0,0), (-2,0,0), (2,0,0), (0,-2,0), (0,2,0), (0,0,-2), (0,0,2) } " ) {
192 std::vector<Point> V
193 = { Point(0,0,0), Point(-2,0,0), Point(2,0,0), Point(0,-2,0), Point(0,2,0),
194 Point(0,0,-2), Point(0,0,2) };
195 WHEN( "Computing its lattice polytope" ){
196 const auto P = Helper::computeLatticePolytope( V, false, true );
197 CAPTURE( P );
198 THEN( "The polytope is valid and has 8 non trivial facets plus 12 edge constraints" ) {
199 REQUIRE( P.nbHalfSpaces() - 6 == 20 );
200 }
201 THEN( "The polytope is Minkowski summable" ) {
202 REQUIRE( P.canBeSummed() );
203 }
204 THEN( "The polytope contains the input points" ) {
205 REQUIRE( P.isInside( V[ 0 ] ) );
206 REQUIRE( P.isInside( V[ 1 ] ) );
207 REQUIRE( P.isInside( V[ 2 ] ) );
208 REQUIRE( P.isInside( V[ 3 ] ) );
209 REQUIRE( P.isInside( V[ 4 ] ) );
210 REQUIRE( P.isInside( V[ 5 ] ) );
211 REQUIRE( P.isInside( V[ 6 ] ) );
212 }
213 THEN( "The polytope contains 25 points" ) {
214 REQUIRE( P.count() == 25 );
215 }
216 THEN( "The interior of the polytope contains 7 points" ) {
217 REQUIRE( P.countInterior() == 7 );
218 }
219 THEN( "The boundary of the polytope contains 18 points" ) {
220 REQUIRE( P.countBoundary() == 18 );
221 }
222 }
223 WHEN( "Computing the boundary of its convex hull as a SurfaceMesh" ){
224 SMesh smesh;
225 bool ok = Helper::computeConvexHullBoundary( smesh, V, false );
226 CAPTURE( smesh );
227 THEN( "The surface mesh is valid and has 6 vertices, 12 edges and 8 faces" ) {
228 REQUIRE( ok );
229 REQUIRE( smesh.nbVertices() == 6 );
230 REQUIRE( smesh.nbEdges() == 12 );
231 REQUIRE( smesh.nbFaces() == 8 );
232 }
233 THEN( "The surface mesh has the topology of a sphere" ) {
234 REQUIRE( smesh.Euler() == 2 );
235 REQUIRE( smesh.computeManifoldBoundaryEdges().size() == 0 );
236 REQUIRE( smesh.computeNonManifoldEdges().size() == 0 );
237 }
238 }
239 WHEN( "Computing the boundary of its convex hull as a lattice PolygonalSurface" ){
240 LatticePolySurf lpsurf;
241 bool ok = Helper::computeConvexHullBoundary( lpsurf, V, false );
242 CAPTURE( lpsurf );
243 THEN( "The polygonal surface is valid and has 6 vertices, 12 edges and 8 faces" ) {
244 REQUIRE( ok );
245 REQUIRE( lpsurf.nbVertices() == 6 );
246 REQUIRE( lpsurf.nbEdges() == 12 );
247 REQUIRE( lpsurf.nbFaces() == 8 );
248 REQUIRE( lpsurf.nbArcs() == 24 );
249 }
250 THEN( "The polygonal surface has the topology of a sphere and no boundary" ) {
251 REQUIRE( lpsurf.Euler() == 2 );
252 REQUIRE( lpsurf.allBoundaryArcs().size() == 0 );
253 REQUIRE( lpsurf.allBoundaryVertices().size() == 0 );
254 }
255 }
256 WHEN( "Computing its convex hull as a ConvexCellComplex" ){
257 CvxCellComplex complex;
258 bool ok = Helper::computeConvexHullCellComplex( complex, V, false );
259 CAPTURE( complex );
260 THEN( "The convex cell complex is valid and has 6 vertices, 8 faces and 1 finite cell" ) {
261 REQUIRE( ok );
262 REQUIRE( complex.nbVertices() == 6 );
263 REQUIRE( complex.nbFaces() == 8 );
264 REQUIRE( complex.nbCells() == 1 );
265 }
266 }
267 WHEN( "Computing the vertices of its convex hull" ){
268 const auto X = Helper::computeConvexHullVertices( V, false );
269 CAPTURE( X );
270 THEN( "The polytope has 6 vertices" ) {
271 REQUIRE( X.size() == 6 );
272 }
273 }
274 }
275 GIVEN( "Given a cube with an additional outside vertex " ) {
276 std::vector<Point> V
277 = { Point(-10,-10,-10), Point(10,-10,-10), Point(-10,10,-10), Point(10,10,-10),
278 Point(-10,-10,10), Point(10,-10,10), Point(-10,10,10), Point(10,10,10),
279 Point(0,0,18) };
280 WHEN( "Computing its Delaunay cell complex" ){
281 CvxCellComplex complex;
282 bool ok = Helper::computeDelaunayCellComplex( complex, V, false );
283 CAPTURE( complex );
284 THEN( "The complex has 2 cells, 10 faces, 9 vertices" ) {
285 REQUIRE( ok );
286 REQUIRE( complex.nbCells() == 2 );
287 REQUIRE( complex.nbFaces() == 10 );
288 REQUIRE( complex.nbVertices() == 9 );
289 }
290 THEN( "The faces of cells are finite" ) {
291 bool ok_finite = true;
292 for ( CvxCellComplex::Size c = 0; c < complex.nbCells(); ++c ) {
293 const auto faces = complex.cellFaces( c );
294 for ( auto f : faces )
295 ok_finite = ok_finite && ! complex.isInfinite( complex.faceCell( f ) );
296 }
297 REQUIRE( ok_finite );
298 }
299 THEN( "The opposite of faces of cells are infinite except two" ) {
300 int nb_finite = 0;
301 for ( CvxCellComplex::Size c = 0; c < complex.nbCells(); ++c ) {
302 const auto faces = complex.cellFaces( c );
303 for ( auto f : faces ) {
304 const auto opp_f = complex.opposite( f );
305 nb_finite += complex.isInfinite( complex.faceCell( opp_f ) ) ? 0 : 1;
306 }
307 }
308 REQUIRE( nb_finite == 2 );
309 }
310 }
311 WHEN( "Computing the vertices of its convex hull" ){
312 const auto X = Helper::computeConvexHullVertices( V, false );
313 CAPTURE( X );
314 THEN( "The polytope has 9 vertices" ) {
315 REQUIRE( X.size() == 9 );
316 }
317 }
318 }
319 GIVEN( "Given a degenerated 1d polytope { (0,0,1), (3,-1,2), (9,-3,4), (-6,2,-1) } " ) {
320 std::vector<Point> V
321 = { Point(0,0,1), Point(3,-1,2), Point(9,-3,4), Point(-6,2,-1) };
322 WHEN( "Computing its lattice polytope" ){
323 const auto P = Helper::computeLatticePolytope( V, false, true );
324 CAPTURE( P );
325 THEN( "The polytope is valid and has 6 non trivial facets" ) {
326 REQUIRE( P.nbHalfSpaces() - 6 == 6 );
327 }
328 THEN( "The polytope contains 6 points" ) {
329 REQUIRE( P.count() == 6 );
330 }
331 THEN( "The polytope contains no interior points" ) {
332 REQUIRE( P.countInterior() == 0 );
333 }
334 }
335 WHEN( "Computing the vertices of its convex hull" ){
336 auto X = Helper::computeConvexHullVertices( V, false );
337 std::sort( X.begin(), X.end() );
338 CAPTURE( X );
339 THEN( "The polytope is a segment defined by two points" ) {
340 REQUIRE( X.size() == 2 );
341 REQUIRE( X[ 0 ] == Point(-6, 2,-1) );
342 REQUIRE( X[ 1 ] == Point( 9,-3, 4) );
343 }
344 }
345 }
346 GIVEN( "Given a degenerated 1d simplex { (1,0,-1), Point(4,-1,-2), Point(10,-3,-4) } " ) {
347 std::vector<Point> V
348 = { Point(1,0,-1), Point(4,-1,-2), Point(10,-3,-4) };
349 WHEN( "Computing its lattice polytope" ){
350 const auto P = Helper::computeLatticePolytope( V, false, true );
351 CAPTURE( P );
352 THEN( "The polytope is valid and has 6 non trivial facets" ) {
353 REQUIRE( P.nbHalfSpaces() - 6 == 6 );
354 }
355 THEN( "The polytope contains 4 points" ) {
356 REQUIRE( P.count() == 4 );
357 }
358 THEN( "The polytope contains no interior points" ) {
359 REQUIRE( P.countInterior() == 0 );
360 }
361 }
362 WHEN( "Computing the vertices of its convex hull" ){
363 auto X = Helper::computeConvexHullVertices( V, false );
364 std::sort( X.begin(), X.end() );
365 CAPTURE( X );
366 THEN( "The polytope is a segment defined by two points" ) {
367 REQUIRE( X.size() == 2 );
368 REQUIRE( X[ 0 ] == Point( 1, 0,-1) );
369 REQUIRE( X[ 1 ] == Point(10,-3,-4) );
370 }
371 }
372 }
373 GIVEN( "Given a degenerated 2d polytope { (2,1,0), (1,0,1), (1,2,1), (0,1,2), (0,3,2) } " ) {
374 std::vector<Point> V
375 = { Point(2,1,0), Point(1,0,1), Point(1,2,1), Point(0,1,2), Point(0,3,2) };
376 WHEN( "Computing its lattice polytope" ){
377 const auto P = Helper::computeLatticePolytope( V, false, true );
378 CAPTURE( P );
379 THEN( "The polytope is valid and has more than 6 non trivial facets" ) {
380 REQUIRE( P.nbHalfSpaces() - 6 == 6 );
381 }
382 THEN( "The polytope contains 7 points" ) {
383 REQUIRE( P.count() == 7 );
384 }
385 THEN( "The polytope contains no interior points" ) {
386 REQUIRE( P.countInterior() == 0 );
387 }
388 }
389 WHEN( "Computing the vertices of its convex hull" ){
390 auto X = Helper::computeConvexHullVertices( V, false );
391 std::sort( X.begin(), X.end() );
392 CAPTURE( X );
393 THEN( "The polytope is a quad" ) {
394 REQUIRE( X.size() == 4 );
395 REQUIRE( X[ 0 ] == Point( 0, 1, 2) );
396 REQUIRE( X[ 1 ] == Point( 0, 3, 2) );
397 REQUIRE( X[ 2 ] == Point( 1, 0, 1) );
398 REQUIRE( X[ 3 ] == Point( 2, 1, 0) );
399 }
400 }
401 }
402 GIVEN( "Given a degenerated 2d simplex { (2,1,0), (1,0,1), (1,5,1), (0,3,2) } " ) {
403 std::vector<Point> V
404 = { Point(2,1,0), Point(1,0,1), Point(1,5,1), Point(0,3,2) };
405 WHEN( "Computing its lattice polytope" ){
406 const auto P = Helper::computeLatticePolytope( V, false, true );
407 CAPTURE( P );
408 THEN( "The polytope is valid and has more than 6 non trivial facets" ) {
409 REQUIRE( P.nbHalfSpaces() - 6 == 6 );
410 }
411 THEN( "The polytope contains 8 points" ) {
412 REQUIRE( P.count() == 8 );
413 }
414 THEN( "The polytope contains no interior points" ) {
415 REQUIRE( P.countInterior() == 0 );
416 }
417 }
418 WHEN( "Computing the vertices of its convex hull" ){
419 auto X = Helper::computeConvexHullVertices( V, false );
420 std::sort( X.begin(), X.end() );
421 CAPTURE( X );
422 THEN( "The polytope is a quad" ) {
423 REQUIRE( X.size() == 4 );
424 REQUIRE( X[ 0 ] == Point( 0, 3, 2) );
425 REQUIRE( X[ 1 ] == Point( 1, 0, 1) );
426 REQUIRE( X[ 2 ] == Point( 1, 5, 1) );
427 REQUIRE( X[ 3 ] == Point( 2, 1, 0) );
428 }
429 }
430 }
431}
432
433
435// Functions for testing class ConvexityHelper in 3D.
437
438SCENARIO( "ConvexityHelper< 3 > triangle tests",
439 "[convexity_helper][triangle][3d]" )
440{
441 typedef ConvexityHelper< 3 > Helper;
442 typedef Helper::Point Point;
443 typedef Helper::Vector Vector;
444 GIVEN( "Given non degenerated triplets of points" ) {
445 Helper::LatticePolytope P;
446 Helper::LatticePolytope T;
447 Point a, b, c;
448 Vector n;
449 int nb_total = 0;
450 int nb_ok = 0;
451 int nbi_ok = 0;
452 int nb_P = 0, nb_T = 0, nbi_P = 0, nbi_T = 0;
453 for ( int i = 0; i < 20; i++ )
454 {
455 do {
456 a = Point( rand() % 10, rand() % 10, rand() % 10 );
457 b = Point( rand() % 10, rand() % 10, rand() % 10 );
458 c = Point( rand() % 10, rand() % 10, rand() % 10 );
459 n = (b-a).crossProduct(c-a);
460 } while ( n == Vector::zero );
461 std::vector<Point> V = { a, b, c };
462 P = Helper::computeLatticePolytope( V, false, false );
463 T = Helper::compute3DTriangle( a, b, c );
464 nb_P = P.count();
465 nb_T = T.count();
466 nbi_P = P.countInterior();
467 nbi_T = T.countInterior();
468 nb_total += 1;
469 nb_ok += ( nb_P == nb_T ) ? 1 : 0;
470 nbi_ok += ( nbi_P == 0 && nbi_T == 0 ) ? 1 : 0;
471 if ( ( nb_ok != nb_total ) || ( nbi_ok != nb_total ) ) break;
472 }
473 CAPTURE( a ); CAPTURE( b ); CAPTURE( c ); CAPTURE( n );
474 CAPTURE( P ); CAPTURE( T );
475 CAPTURE( nb_P ); CAPTURE( nb_T ); CAPTURE( nbi_P ); CAPTURE( nbi_T );
476 WHEN( "Computing their tightiest polytope or triangle" ) {
477 THEN( "They have the same number of inside points" ) {
478 REQUIRE( nb_ok == nb_total );
479 }
480 THEN( "They do not have interior points" ) {
481 REQUIRE( nbi_ok == nb_total );
482 }
483 }
484 }
485
486 GIVEN( "Given non degenerated triplets of points" ) {
487 typedef Helper::LatticePolytope::UnitSegment UnitSegment;
488 Helper::LatticePolytope P;
489 Helper::LatticePolytope T;
490 Point a, b, c;
491 Vector n;
492 int nb_total = 0;
493 int nb_ok = 0;
494 int nbi_ok = 0;
495 int nb_P = 0, nb_T = 0, nbi_P = 0, nbi_T = 0;
496 for ( int i = 0; i < 20; i++ )
497 {
498 do {
499 a = Point( rand() % 10, rand() % 10, rand() % 10 );
500 b = Point( rand() % 10, rand() % 10, rand() % 10 );
501 c = Point( rand() % 10, rand() % 10, rand() % 10 );
502 n = (b-a).crossProduct(c-a);
503 } while ( n == Vector::zero );
504 std::vector<Point> V = { a, b, c };
505 P = Helper::computeLatticePolytope( V, false, true );
506 T = Helper::compute3DTriangle( a, b, c, true );
507 for ( Dimension k = 0; k < 3; k++ )
508 {
509 P += UnitSegment( k );
510 T += UnitSegment( k );
511 }
512 nb_P = P.count();
513 nb_T = T.count();
514 nbi_P = P.countInterior();
515 nbi_T = T.countInterior();
516 nb_total += 1;
517 nb_ok += ( nb_P == nb_T ) ? 1 : 0;
518 nbi_ok += ( nbi_P == nbi_T ) ? 1 : 0;
519 if ( ( nb_ok != nb_total ) || ( nbi_ok != nb_total ) ) break;
520 }
521 CAPTURE( a ); CAPTURE( b ); CAPTURE( c ); CAPTURE( n );
522 CAPTURE( P ); CAPTURE( T );
523 CAPTURE( nb_P ); CAPTURE( nb_T ); CAPTURE( nbi_P ); CAPTURE( nbi_T );
524 WHEN( "Computing their tightiest polytope or triangle, dilated by a cube" ) {
525 THEN( "They have the same number of inside points" ) {
526 REQUIRE( nb_ok == nb_total );
527 }
528 THEN( "They have the same number of interior points" ) {
529 REQUIRE( nbi_ok == nb_total );
530 }
531 }
532 }
533}
534
535
536SCENARIO( "ConvexityHelper< 3 > degenerated triangle tests",
537 "[convexity_helper][triangle][degenerate][3d]" )
538{
539 typedef ConvexityHelper< 3 > Helper;
540 typedef Helper::Point Point;
541 typedef Helper::Vector Vector;
542 GIVEN( "Given degenerated triplets of points" ) {
543 Helper::LatticePolytope P;
544 Helper::LatticePolytope T;
545 Point a, b, c;
546 Vector n;
547 int nb_total = 0;
548 int nb_ok = 0;
549 int nbi_ok = 0;
550 int nb_P = 0, nb_T = 0, nbi_P = 0, nbi_T = 0;
551 for ( int i = 0; i < 20; i++ )
552 {
553 do {
554 a = Point( rand() % 10, rand() % 10, rand() % 10 );
555 b = Point( rand() % 10, rand() % 10, rand() % 10 );
556 c = Point( rand() % 10, rand() % 10, rand() % 10 );
557 n = (b-a).crossProduct(c-a);
558 } while ( n != Vector::zero );
559 std::vector<Point> V = { a, b, c };
560 P = Helper::computeLatticePolytope( V, true, false );
561 T = Helper::compute3DTriangle( a, b, c );
562 nb_P = P.count();
563 nb_T = T.count();
564 nbi_P = P.countInterior();
565 nbi_T = T.countInterior();
566 nb_total += 1;
567 nb_ok += ( nb_P == nb_T ) ? 1 : 0;
568 nbi_ok += ( nbi_P == 0 && nbi_T == 0 ) ? 1 : 0;
569 if ( ( nb_ok != nb_total ) || ( nbi_ok != nb_total ) ) break;
570 }
571 CAPTURE( a ); CAPTURE( b ); CAPTURE( c ); CAPTURE( n );
572 CAPTURE( P ); CAPTURE( T );
573 CAPTURE( nb_P ); CAPTURE( nb_T ); CAPTURE( nbi_P ); CAPTURE( nbi_T );
574 WHEN( "Computing their tightiest polytope or triangle" ) {
575 THEN( "They have the same number of inside points" ) {
576 REQUIRE( nb_ok == nb_total );
577 }
578 THEN( "They do not have interior points" ) {
579 REQUIRE( nbi_ok == nb_total );
580 }
581 }
582 }
583
584 GIVEN( "Given degenerated triplets of points" ) {
585 typedef Helper::LatticePolytope::UnitSegment UnitSegment;
586 Helper::LatticePolytope P;
587 Helper::LatticePolytope T;
588 Point a, b, c;
589 Vector n;
590 int nb_total = 0;
591 int nb_ok = 0;
592 int nbi_ok = 0;
593 int nb_P = 0, nb_T = 0, nbi_P = 0, nbi_T = 0;
594 for ( int i = 0; i < 20; i++ )
595 {
596 do {
597 a = Point( rand() % 10, rand() % 10, rand() % 10 );
598 b = Point( rand() % 10, rand() % 10, rand() % 10 );
599 c = Point( rand() % 10, rand() % 10, rand() % 10 );
600 n = (b-a).crossProduct(c-a);
601 } while ( n != Vector::zero );
602 std::vector<Point> V = { a, b, c };
603 P = Helper::computeLatticePolytope( V, true, true );
604 T = Helper::compute3DTriangle( a, b, c, true );
605 for ( Dimension k = 0; k < 3; k++ )
606 {
607 P += UnitSegment( k );
608 T += UnitSegment( k );
609 }
610 nb_P = P.count();
611 nb_T = T.count();
612 nbi_P = P.countInterior();
613 nbi_T = T.countInterior();
614 nb_total += 1;
615 nb_ok += ( nb_P == nb_T ) ? 1 : 0;
616 nbi_ok += ( nbi_P == nbi_T ) ? 1 : 0;
617 if ( ( nb_ok != nb_total ) || ( nbi_ok != nb_total ) ) break;
618 }
619 CAPTURE( a ); CAPTURE( b ); CAPTURE( c ); CAPTURE( n );
620 CAPTURE( P ); CAPTURE( T );
621 CAPTURE( nb_P ); CAPTURE( nb_T ); CAPTURE( nbi_P ); CAPTURE( nbi_T );
622 WHEN( "Computing their tightiest polytope or triangle, dilated by a cube" ) {
623 THEN( "They have the same number of inside points" ) {
624 REQUIRE( nb_ok == nb_total );
625 }
626 THEN( "They have the same number of interior points" ) {
627 REQUIRE( nbi_ok == nb_total );
628 }
629 }
630 }
631}
Aim: Represents a polygon mesh, i.e. a 2-dimensional combinatorial surface whose faces are (topologic...
SurfaceMesh< RealPoint, RealVector > SMesh
DGtal is the top-level namespace which contains all DGtal functions and types.
auto crossProduct(PointVector< 3, LeftEuclideanRing, LeftContainer > const &lhs, PointVector< 3, RightEuclideanRing, RightContainer > const &rhs) -> decltype(DGtal::constructFromArithmeticConversion(lhs, rhs))
Cross product of two 3D Points/Vectors.
DGtal::uint32_t Dimension
Definition Common.h:119
STL namespace.
Aim: represents a d-dimensional complex in a d-dimensional space with the following properties and re...
Aim: Provides a set of functions to facilitate the computation of convex hulls and polytopes,...
long Euler() const
Size nbFaces() const
Size nbEdges() const
Edges computeManifoldBoundaryEdges() const
Size nbVertices() const
Edges computeNonManifoldEdges() const
MyPointD Point
CAPTURE(thicknessHV)
GIVEN("A cubical complex with random 3-cells")
REQUIRE(domain.isInside(aPoint))
PointVector< 3, double > RealPoint
SCENARIO("UnorderedSetByBlock< PointVector< 2, int > unit tests with 32 bits blocks", "[unorderedsetbyblock][2d]")