35#include "DGtal/base/Common.h"
36#include "DGtal/kernel/SpaceND.h"
37#include "DGtal/geometry/tools/AffineGeometry.h"
38#include "DGtal/geometry/tools/AffineBasis.h"
39#include "DGtalCatch.h"
47std::uniform_real_distribution<double>
uniform(-1.0, 1.0);
49template <
typename RealPo
int>
52 for (
auto& c : x ) c +=
uniform(
g ) * perturbation;
55template <
typename RealPo
int>
56void perturbate( std::vector< RealPoint >& X,
double perturbation )
58 for (
auto& x : X )
perturbate( x, perturbation );
61template <
typename Po
int >
65 std::uniform_int_distribution<int> U(-amplitude, amplitude);
66 std::vector< Point > P;
67 for (
auto n = 0; n < nb; ++n )
70 for (
auto i = 0; i < Point::dimension; i++ )
77template <
typename Po
int >
81 std::uniform_int_distribution<int> U(-10, 10);
86 for (
auto i = 0; i < n; i++ )
89 for (
auto k = 0; k < nb; k++ )
92 for (
auto i = 0; i < m; i++ )
99 std::shuffle( P.begin(), P.end(),
g );
103template <
typename Po
int >
107 std::uniform_real_distribution<double> U(-1., 1.);
112 for (
auto i = 0; i < n; i++ )
115 for (
auto k = 0; k < nb; k++ )
118 for (
auto i = 0; i < m; i++ )
120 double l = 5.* U(
g );
125 std::shuffle( P.begin(), P.end(),
g );
133SCENARIO(
"AffineGeometry< Point2i > unit tests",
"[affine_subset][2i]" )
136 typedef Space::Point
Point;
138 GIVEN(
"Given X = { (0,0), (-4,-1), (16,4), (-3,5), (7,3), (5, -2) } of affine dimension 2" ) {
140 = {
Point(0,0),
Point(-4,-1),
Point(16,4),
Point(-3,5),
Point(7,3),
Point(5, -2) };
141 auto I = Affine::affineSubset( X );
142 THEN(
"It has an affine basis of 3 points" ) {
148 GIVEN(
"Given X = { (0,0), (-4,-1), (-8,-2), (8,2), (16,4), (200,50) } of affine dimension 1" ) {
150 = {
Point(0,0),
Point(-4,-1),
Point(-8,-2),
Point(8,2),
Point(16,4),
Point(200,50) };
151 auto I = Affine::affineSubset( X );
152 THEN(
"It has an affine basis of 2 points" ) {
159SCENARIO(
"AffineGeometry< Point2d > unit tests",
"[affine_subset][2d]" )
162 typedef Space::RealPoint
Point;
164 GIVEN(
"Given X = { (0,0), (-4,-1), (16,4), (-3,5), (7,3), (5, -2) } of affine dimension 2" ) {
166 = {
Point(0,0),
Point(-4,-1),
Point(16,4),
Point(-3,5),
Point(7,3),
Point(5, -2) };
167 auto I = Affine::affineSubset( X );
168 THEN(
"It has an affine basis of 3 points [0,1,3]" ) {
174 GIVEN(
"Given X = { (0,0), (-4,-1), (-8,-2), (8,2), (16,4), (200,50) } of affine dimension 1" ) {
176 = {
Point(0,0),
Point(-4,-1),
Point(-8,-2),
Point(8,2),
Point(16,4),
Point(200,50) };
177 auto I = Affine::affineSubset( X );
178 THEN(
"It has an affine basis of 2 points [0,1]" ) {
183 GIVEN(
"Given a perturbated X = { (0,0), (-4,-1), (16,4), (-3,5), (7,3), (5, -2) } of affine dimension 2 by U[-1e-4,1e-4]" ) {
185 = {
Point(0,0),
Point(-4,-1),
Point(16,4),
Point(-3,5),
Point(7,3),
Point(5, -2) };
187 auto I = Affine::affineSubset( X, 1e-12 );
188 THEN(
"It has an affine basis of 3 points [0,1,x]" ) {
193 GIVEN(
"Given a perturbated X = { (0,0), (-4,-1), (-8,-2), (8,2), (16,4), (200,50) } of affine dimension 1 by U[-1e-4,1e-4]" ) {
195 = {
Point(0,0),
Point(-4,-1),
Point(-8,-2),
Point(8,2),
Point(16,4),
Point(200,50) };
197 auto I = Affine::affineSubset( X, 1e-12 );
198 THEN(
"It has an affine basis of 3 points [0,1,x]" ) {
203 GIVEN(
"Given a perturbated X = { (0,0), (-4,-1), (-8,-2), (8,2), (16,4), (200,50) } of affine dimension 1 by U[-1e-11,1e-11]" ) {
205 = {
Point(0,0),
Point(-4,-1),
Point(-8,-2),
Point(8,2),
Point(16,4),
Point(200,50) };
207 auto I = Affine::affineSubset( X, 1e-7 );
208 THEN(
"It has an affine basis of 2 points [0,1] if tolerance is 1e-7" ) {
216SCENARIO(
"AffineGeometry< Point2i > orthogonal tests",
"[orthogonal_vector][2i]" )
219 typedef Space::Point
Point;
221 GIVEN(
"Given basis B = { (7,3) } " ) {
222 std::vector<Point>
B = {
Point(7,3) };
223 Affine::completeBasis(
B,
true );
224 THEN(
"The complete basis has dimension 2" ) {
228 THEN(
"The last vector is non null and orthogonal to all the others" ) {
230 REQUIRE(
B.back().normInfinity() > 0 );
240SCENARIO(
"AffineGeometry< Point3i > unit tests",
"[affine_subset][3i]" )
243 typedef Space::Point
Point;
245 GIVEN(
"Given X = { (1, 0, 0), (2, 1, 0), (3, 1, 1), (3, 2, 0), (5, 2, 2), (4, 2, 1)} of affine dimension 2" ) {
247 = {
Point{1, 0, 0},
Point{2, 1, 0},
Point{3, 1, 1},
Point{3, 2, 0},
Point{5, 2, 2},
Point{4, 2, 1} };
249 auto I = Affine::affineSubset( X );
250 THEN(
"It has an affine basis of 3 points" ) {
256 GIVEN(
"Given X = { (1, 0, 0), (2, 1, 0), (3, 1, 1), (3, 2, 0), (5, 2, 2), (4, 2, 1), (7, 3, 2)} of affine dimension 3" ) {
258 = {
Point{1, 0, 0},
Point{2, 1, 0},
Point{3, 1, 1},
Point{3, 2, 0},
Point{5, 2, 2},
Point{4, 2, 1},
Point{7, 3, 2} };
260 auto I = Affine::affineSubset( X );
261 THEN(
"It has an affine basis of 4 points" ) {
268 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 1 lattice vectors" ) {
269 std::vector< Point > V = {
Point{ 3, 1, 0 } };
271 auto I = Affine::affineSubset( X );
272 THEN(
"It has an affine basis of 2 points" ) {
277 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 2 lattice vectors" ) {
278 std::vector< Point > V = {
Point{ 3, 1, 0 },
Point{ -2, -1, 2 } };
280 auto I = Affine::affineSubset( X );
281 THEN(
"It has an affine basis of 3 points" ) {
286 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 3 lattice vectors" ) {
287 std::vector< Point > V = {
Point{ 3, 1, 0 },
Point{ -2, -1, 2 },
Point{ -1, 4, 3 } };
289 auto I = Affine::affineSubset( X );
290 THEN(
"It has an affine basis of 4 points" ) {
297SCENARIO(
"AffineGeometry< Point3i > orthogonal tests",
"[orthogonal_vector][3i]" )
300 typedef Space::Point
Point;
302 GIVEN(
"Given basis B = { (7,3,1), (2,-5,1) } " ) {
303 std::vector<Point>
B = {
Point(7,3,1),
Point( 2,-5,1) };
304 Point n =
B[ 0 ].crossProduct(
B[ 1 ] );
305 Affine::completeBasis(
B,
true );
306 THEN(
"The complete basis has dimension 3" ) {
310 THEN(
"The last vector is non null and orthogonal to all the others" ) {
312 REQUIRE(
B.back().normInfinity() > 0 );
316 THEN(
"The last vector is the cross product of the two others" ) {
321 GIVEN(
"Given basis B = { (7,3,1) } " ) {
322 std::vector<Point>
B = {
Point(7,3,1) };
323 Affine::completeBasis(
B,
true );
324 THEN(
"The complete basis has dimension 3" ) {
328 THEN(
"The mid vector is non null and trivial" ) {
332 THEN(
"The last vector is non null and orthogonal to all the others" ) {
334 REQUIRE(
B.back().normInfinity() > 0 );
338 THEN(
"The last vector is the cross product of the two others" ) {
339 Point n =
B[ 0 ].crossProduct(
B[ 1 ] );
350SCENARIO(
"AffineGeometry< Point4i > unit tests",
"[affine_subset][4i]" )
353 typedef Space::Point
Point;
354 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 1 lattice vectors" ) {
355 std::vector< Point > V = {
Point{ 3, 1, 0, 2 } };
359 std::vector< Point >
B;
361 THEN(
"It has an affine basis of 2 points" ) {
365 THEN(
"It has an affine basis of 1 vector" ) {
370 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 2 lattice vectors" ) {
371 std::vector< Point > V = {
Point{ 3, 1, 0, 2 },
Point{ -2, -1, 2, 7 } };
375 std::vector< Point >
B;
377 THEN(
"It has an affine basis of 3 points" ) {
381 THEN(
"It has an affine basis of 2 vectors" ) {
385 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 3 lattice vectors" ) {
386 std::vector< Point > V = {
Point{ 3, 1, 0, 2 },
Point{ -2, -1, 2, 7 },
Point{ -1, 4, 3, -1 } };
390 std::vector< Point >
B;
392 THEN(
"It has an affine basis of 4 points" ) {
396 THEN(
"It has an affine basis of 3 vectors" ) {
400 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 4 lattice vectors" ) {
401 std::vector< Point > V = {
Point{ 3, 1, 0, 2 },
Point{ -2, -1, 2, 7 },
Point{ -1, 4, 3, -1 },
Point{ 2, 1, -3, -4 } };
405 std::vector< Point >
B;
407 THEN(
"It has an affine basis of 5 points" ) {
411 THEN(
"It has an affine basis of 4 vectors" ) {
417SCENARIO(
"AffineGeometry< Point4d > unit tests",
"[affine_subset][4d]" )
422 typedef Space::RealPoint
Point;
423 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 1 lattice vectors" ) {
424 std::vector< Point > V = {
Point{ 3, 1, 0, 2 } };
428 std::vector< Point >
B;
430 THEN(
"It has an affine subset of 2 points" ) {
434 THEN(
"It has an affine basis of 1 vector" ) {
438 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 2 lattice vectors" ) {
439 std::vector< Point > V = {
Point{ 3, 1, 0, 2 },
Point{ -2, -1, 2, 7 } };
443 std::vector< Point >
B;
445 THEN(
"It has an affine subset of 3 points" ) {
449 THEN(
"It has an affine basis of 2 vectors" ) {
453 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 3 lattice vectors" ) {
454 std::vector< Point > V = {
Point{ 3, 1, 0, 2 },
Point{ -2, -1, 2, 7 },
Point{ -1, 4, 3, -1 } };
458 std::vector< Point >
B;
460 THEN(
"It has an affine subset of 4 points" ) {
464 THEN(
"It has an affine basis of 3 vectors" ) {
468 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 4 lattice vectors" ) {
469 std::vector< Point > V = {
Point{ 3, 1, 0, 2 },
Point{ -2, -1, 2, 7 },
Point{ -1, 4, 3, -1 },
Point{ 2, 1, -3, -4 } };
473 std::vector< Point >
B;
475 THEN(
"It has an affine subset of 5 points" ) {
479 THEN(
"It has an affine basis of 4 vectors" ) {
485SCENARIO(
"AffineGeometry< Point4i > orthogonal tests",
"[orthogonal_vector][4i]" )
488 typedef Space::Point
Point;
490 GIVEN(
"Given basis B = { (7,3,1,0), (2,-5,1,2), (-1,2,2,-3) } " ) {
491 std::vector<Point>
B = {
Point(7,3,1,0),
Point(2,-5,1,2),
Point(-1,2,2,-3) };
492 Affine::completeBasis(
B,
true );
493 THEN(
"The complete basis has dimension 4" ) {
497 THEN(
"The last vector is non null and orthogonal to all the others" ) {
499 REQUIRE(
B.back().normInfinity() > 0 );
505 GIVEN(
"Given basis B = { (7,3,1,0), (2,-5,1,2) } " ) {
506 std::vector<Point>
B = {
Point(7,3,1,0),
Point(2,-5,1,2) };
507 Affine::completeBasis(
B,
true );
508 THEN(
"The complete basis has dimension 4" ) {
512 THEN(
"The third vector is non null and trivial" ) {
516 THEN(
"The last vector is non null and orthogonal to all the others" ) {
518 REQUIRE(
B.back().normInfinity() > 0 );
527SCENARIO(
"AffineGeometry< Z3 > bug",
"[affine_geom][3d]" )
530 typedef Space::Point
Point;
531 std::vector< Point > X = { {-46, 38, -43}, {27, -89, 20}, {53, 26, -57} };
533 std::vector< Point >
B;
537 WHEN(
"Computing orthogonal vector" ) {
539 THEN(
"It is non null" ) {
543 THEN(
"It corresponds to the reduced cross product" ) {
551SCENARIO(
"AffineGeometry< Z3 > orthogonality",
"[affine_geom][3d]" )
554 typedef Space::Point
Point;
556 WHEN(
"Computing orthogonal vector to multiple random points" ) {
557 std::vector< Point > X = makeRandomVectors<Point>( 100, 50 );
558 std::size_t nb = 300;
559 std::size_t nb_equal = 0;
560 std::size_t nb_C_zero = 0;
561 std::size_t nb_N_zero = 0;
562 for (
auto i = 0; i < nb; i++ )
564 std::vector< Point > Y = { X[ rand() % 100 ], X[ rand() % 100 ], X[ rand() % 100 ] };
569 nb_equal += (sC == N) ? 1 : 0;
571 std::cout <<
"Y = " << Y[0] <<
" " << Y[1] <<
" " << Y[ 2 ]
572 <<
" sC = " << sC <<
" N = " << N <<
"\n";
573 nb_C_zero += ( C == Point::zero ) ? 1 : 0;
574 nb_N_zero += ( N == Point::zero ) ? 1 : 0;
576 THEN(
"They corresponds to the reduced cross product" ) {
578 REQUIRE( nb_C_zero == nb_N_zero );
void getAffineBasis(TInputPoint &o, std::vector< TPoint > &basis, const std::vector< TInputPoint > &X, const double tolerance=1e-12)
static void getOrthogonalVector(TPoint &w, const std::vector< TInputPoint > &X, const TIndexRange &I, const double tolerance=1e-12)
static TPoint computeOrthogonalVectorToBasis(const std::vector< TPoint > &basis)
std::vector< std::size_t > computeAffineSubset(const std::vector< TPoint > &X, const double tolerance=1e-12)
TPoint computeSimplifiedVector(const TPoint &v)
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.
Aim: Utility class to determine the affine geometry of an input set of points. It provides exact resu...
void perturbate(RealPoint &x, double perturbation)
std::vector< Point > makeRandomLatticePointsFromDirVectors(int nb, const vector< Point > &V)
std::vector< Point > makeRandomRealPointsFromDirVectors(int nb, const vector< Point > &V)
std::vector< Point > makeRandomVectors(int nb, int amplitude)
std::uniform_real_distribution< double > uniform(-1.0, 1.0)
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]")