31#if defined(AffineGeometry_RECURSES)
32#error Recursive header files inclusion detected in AffineGeometry.h
35#define AffineGeometry_RECURSES
37#if !defined AffineGeometry_h
39#define AffineGeometry_h
44#include "DGtal/base/Common.h"
45#include "DGtal/kernel/IntegerConverter.h"
46#include "DGtal/kernel/PointVector.h"
47#include "DGtal/arithmetic/IntegerComputer.h"
48#include "DGtal/math/linalg/SimpleMatrix.h"
49#include "DGtal/math/linalg/IntegerMatrixFunctions.h"
54 template <
typename T >
struct AffineGeometry;
56 template <
typename T >
struct AffineBasis;
68 typename TEuclideanRing,
69 typename TContainer=std::array<TEuclideanRing,dim> >
86 template <
typename TInteger >
92 TInteger
g = abs( w[ i ] );
100 template <
typename TOtherPo
int>
115 typename TContainer >
137 template <
typename TOtherPo
int>
141 typedef typename TOtherPoint::Coordinate OtherScalar;
155 typename TContainer >
177 template <
typename TOtherPo
int>
183 result[ i ] =
float( other[ i ] );
201 template <
typename TScalar >
228 ? std::make_pair( b /
g, a /
g )
229 : std::make_pair( -b /
g, -a /
g );
284 ? std::make_pair( b, a )
285 : std::make_pair( -b, -a );
290 double gcd(
double,
double )
312 return ( x > tol ) || ( x < -tol );
337 ? std::make_pair( b, a )
338 : std::make_pair( -b, -a );
365 const double dx = double(x);
366 return (dx > tol) || ( dx < -tol );
371 template <
typename TScalar,
bool Robust >
452 template <
typename TPo
int >
456 typedef typename Point::Coordinate
Scalar;
483 template <
typename TInputPo
int>
505 template <
typename TInputPo
int>
508 affineSubset(
const std::vector<TInputPoint>& X,
const double tolerance = 1e-12 )
512 if ( m == 0 )
return { };
513 if ( m == 1 )
return {
Size( 0 ) };
517 chosen.push_back( 0 );
518 for (
Size i = 1; i < m; i++ )
522 chosen.push_back( i );
548 template <
typename TInputPo
int,
typename TIndexRange>
552 const TIndexRange& I,
553 const double tolerance = 1e-12 )
557 if ( m == 0 )
return { };
558 if ( m == 1 )
return { I[ 0 ] };
562 chosen.push_back( I[ 0 ] );
563 for (
Size i = 1; i < m; i++ )
567 chosen.push_back( I[ i ] );
586 template <
typename TInputPo
int>
588 std::pair< Point, Points >
589 affineBasis(
const std::vector<TInputPoint>& X,
const double tolerance = 1e-12 )
594 if ( m == 0 )
return std::make_pair( Point::zero, basis );
596 if ( m == 1 )
return std::make_pair( o, basis );
599 for (
Size i = 1; i < m; i++ )
605 return std::make_pair( o, basis );
624 template <
typename TInputPo
int,
typename TIndexRange >
626 std::pair< TInputPoint, Points >
628 const TIndexRange& I,
629 const double tolerance = 1e-12 )
634 if ( m == 0 )
return std::make_pair( TInputPoint::zero, basis );
635 if ( m == 1 )
return std::make_pair( X[ I[ 0 ] ], basis );
639 for (
Size i = 1; i < m; i++ )
645 return std::make_pair( X[ I[ 0 ] ], basis );
664 if ( basis.size() >=
dimension )
return Point::zero;
669 Point e_k = Point::base( k );
676 trace.
error() <<
"[AffineGeometry::independentVector]"
677 <<
" Unable to find independent vector." << std::endl;
693 template <
typename TOtherPo
int >
700 if ( basis.size() >=
dimension )
return TOtherPoint::zero;
705 Point e_k = Point::base( k );
710 return TOtherPoint::base( k );
712 trace.
error() <<
"[AffineGeometry::independentVector]"
713 <<
" Unable to find independent vector." << std::endl;
714 return TOtherPoint::zero;
739 const double tolerance = 1e-12 )
742 while ( ( basis.size() + 1 ) <
dimension )
745 basis.push_back( u );
765 template <
typename TInputPo
int >
770 std::vector< Scalar > Np( N.begin(), N.end() );
771 Np.resize( Point::dimension );
775 std::vector< Point >
R(
B.size() );
776 for ( std::size_t i = 0; i <
B.size(); i++ )
777 for ( std::size_t j = 0; j < Point::dimension; j++ )
778 R[ i ][ j ] =
B[ i ][ j ];
806 const double tolerance )
809 for (
const auto& b : basis )
reduceVector( w, b, tolerance );
836 const double tolerance )
847 basis.push_back( w );
866 std::pair< Scalar, Scalar >
874 for (
Size j = 0; j < n; j++)
876 if ( lead == n )
return std::make_pair( mul_w, mul_b );
880 for (
Size j = 0; j < n; j++)
881 w[j] = mul_w * w[j] - mul_b * b[j];
882 return std::make_pair( mul_w, mul_b );
899 std::pair< Scalar, Scalar >
901 Dimension start,
const double tolerance )
908 for (
Size j = start; j < n; j++)
910 if ( lead == n )
return std::make_pair( mul_w, mul_b );
914 for (
Size j = 0; j < n; j++)
915 w[j] = mul_w * w[j] - mul_b * b[j];
916 return std::make_pair( mul_w, mul_b );
940 template <
typename TInputPo
int>
966 if ( ( basis.size() + 1 ) !=
dimension )
return w;
967 const std::size_t m = basis.size();
969 for ( std::size_t i = 0; i < m; ++i )
970 for ( std::size_t j = 0; j < n; ++j )
971 A( i, j ) = basis[ i ][ j ];
972 for ( std::size_t col = 0; col < n; ++col)
975 for ( std::size_t i = 0; i < m; ++i )
978 for ( std::size_t j = 0; j < n; ++j)
979 if ( j != col ) M( i, c++ ) =
A( i, j );
982 if ( (col+
dimension) % 2 == 0 ) w[ col ] = -w[ col ];
999 template <
typename TInternalNumber>
1008 if ( ( basis.size() + 1 ) !=
dimension )
return w;
1009 const std::size_t m = basis.
size();
1011 for ( std::size_t i = 0; i < m; ++i )
1012 for ( std::size_t j = 0; j < n; ++j )
1013 A( i, j ) = basis[ i ][ j ];
1014 for ( std::size_t col = 0; col < n; ++col)
1017 for ( std::size_t i = 0; i < m; ++i )
1020 for ( std::size_t j = 0; j < n; ++j)
1021 if ( j != col ) M( i, c++ ) =
A( i, j );
1024 if ( (col+
dimension) % 2 == 0 ) W[ col ] = -W[ col ];
1051 namespace functions {
1066 template <
typename TPo
int>
1087 template <
typename TPo
int>
1088 std::vector< std::size_t >
1114 template <
typename TPo
int,
typename TIndexRange>
1116 std::vector< std::size_t >
1118 const TIndexRange& I,
1119 const double tolerance = 1e-12 )
1143 template <
typename TPo
int,
typename TInputPo
int>
1146 std::vector< TPoint >& basis,
1147 const std::vector< TInputPoint >& X,
1148 const double tolerance = 1e-12 )
1175 template <
typename TPo
int,
typename TInputPo
int,
typename TIndexRange >
1179 std::vector< TPoint >& basis,
1180 const std::vector< TInputPoint >& X,
1181 const TIndexRange& I,
1182 const double tolerance = 1e-12 )
1200 template <
typename TPo
int>
1203 const double tolerance = 1e-12 )
1232 template <
typename TPo
int>
1237 const double tolerance = 1e-12 )
1259 template <
typename TPo
int >
1264 if ( ( basis.size() + 1 ) != TPoint::dimension )
return TPoint::zero;
1298 template <
typename TPo
int,
typename TInputPo
int,
typename TIndexRange >
1302 const std::vector< TInputPoint >& X,
1303 const TIndexRange& I,
1304 const double tolerance = 1e-12 )
1309 auto subset = Affine::affineSubset( X, I, tolerance );
1310 if ( ( subset.size() ) != TPoint::dimension )
return;
1311 std::vector<TPoint> basis( TPoint::dimension - 1);
1312 for (
auto i = 0; i < basis.size(); i++ )
1313 basis[ i ] = Affine::transform( X[ subset[ i+1 ] ] - X[ subset[ 0 ] ] );
1314 w = Affine::orthogonalVector( basis );
1341 template <
typename TPo
int,
typename TInputPo
int>
1345 const std::vector< TInputPoint >& X,
1346 const double tolerance = 1e-12 )
1352 if ( ( subset.size() ) != TPoint::dimension )
return;
1353 std::vector<TPoint> basis( TPoint::dimension - 1);
1354 for (
auto i = 0; i < basis.size(); i++ )
1355 basis[ i ] = Affine::transform( X[ subset[ i+1 ] ] - X[ subset[ 0 ] ] );
1356 w = Affine::orthogonalVector( basis );
1372 template <
typename TPo
int,
typename TInputPo
int>
1376 const TInputPoint& N,
bool shortened =
false )
1392 template <
typename TPo
int>
1409#undef AffineGeometry_RECURSES
Aim: This class gathers several types and methods to make computation with integers.
static Integer staticGcd(IntegerParamType a, IntegerParamType b)
Aim: Implements basic operations that will be used in Point and Vector classes.
Component Coordinate
Type for Point elements.
static const Dimension dimension
Copy of the static dimension of the Point/Vector.
Aim: implements basic MxN Matrix services (M,N>=1).
static void getOrthogonalLatticeBasis(std::vector< TPoint > &B, const TInputPoint &N, bool shortened=false)
DGtal::int64_t computeAffineDimension(const std::vector< TPoint > &X, const double tolerance=1e-12)
void getAffineBasis(TInputPoint &o, std::vector< TPoint > &basis, const std::vector< TInputPoint > &X, const double tolerance=1e-12)
void getSquaredNormL2(TOutput &n, const std::vector< T > &a)
static void getOrthogonalVector(TPoint &w, const std::vector< TInputPoint > &X, const TIndexRange &I, const double tolerance=1e-12)
std::size_t shortenBasis(std::vector< std::vector< TComponent > > &B)
TPoint computeIndependentVector(const std::vector< TPoint > &basis, const double tolerance=1e-12)
static void getCompleteBasis(std::vector< TPoint > &basis, bool normal_vector, const double tolerance=1e-12)
std::vector< std::vector< TComponent > > computeOrthogonalLattice(std::vector< TComponent > N)
static TPoint computeOrthogonalVectorToBasis(const std::vector< TPoint > &basis)
std::vector< std::size_t > computeAffineSubset(const std::vector< TPoint > &X, const double tolerance=1e-12)
void getDeterminantBareiss(TInternalNumber &result, const SimpleMatrix< TComponent, TN, TN > &matrix)
TPoint computeSimplifiedVector(const TPoint &v)
DGtal is the top-level namespace which contains all DGtal functions and types.
std::int32_t int32_t
signed 32-bit integer.
std::int64_t int64_t
signed 94-bit integer.
DGtal::uint32_t Dimension
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<>, boost::multiprecision::et_off > BigInteger
Aim: Utility class to determine the affine geometry of an input set of points. It provides exact resu...
Aim: Utility class to determine the affine geometry of an input set of points. It provides exact resu...
static std::pair< TInputPoint, Points > affineBasis(const std::vector< TInputPoint > &X, const TIndexRange &I, const double tolerance=1e-12)
static const Point & transform(const Point &w)
static std::pair< Scalar, Scalar > reduceVector(Point &w, const Point &b, Dimension start, const double tolerance)
static Point orthogonalVector(const Points &basis)
static std::pair< Scalar, Scalar > reduceVector(Point &w, const Point &b, const double tolerance)
DGtal::detail::AffineGeometryScalarOperations< Scalar > ScalarOps
static std::vector< Size > affineSubset(const std::vector< TInputPoint > &X, const TIndexRange &I, const double tolerance=1e-12)
static Point transform(const TInputPoint &w)
static const Size dimension
static Point independentVector(const Points &basis, const double tolerance=1e-12)
DGtal::detail::AffineGeometryPointOperations< dimension, Scalar, Container > PointOps
static Point orthogonalVector(const Points &basis)
static bool addIfIndependent(Points &basis, const Point &v, const double tolerance)
static TOtherPoint independentVector(const Points &basis, const double tolerance=1e-12)
static std::vector< Point > orthogonalLatticeBasis(const TInputPoint &N, bool shortened=false)
static DGtal::int64_t affineDimension(const std::vector< TInputPoint > &X, const double tolerance=1e-12)
std::vector< Size > Sizes
type for range of sizes.
Point::Container Container
static void completeBasis(Points &basis, bool normal_vector, const double tolerance=1e-12)
std::vector< Point > Points
type for range of points.
static Point simplifiedVector(Point v)
static Point reductionOnBasis(const Point &v, const Points &basis, const double tolerance)
static std::pair< Point, Points > affineBasis(const std::vector< TInputPoint > &X, const double tolerance=1e-12)
static std::vector< Size > affineSubset(const std::vector< TInputPoint > &X, const double tolerance=1e-12)
static Integer cast(Integer i)
Aim: The traits class for all models of Cinteger.
static void normalizeVector(Point &w, double x)
PointVector< dim, double, TContainer > Point
static Point cast(const TOtherPoint &other)
Specialized version to cast points to other point type.
PointVector< dim, float, TContainer > Point
static Point cast(const TOtherPoint &other)
Specialized version to cast points to other point type.
static void normalizeVector(Point &w, float x)
Aim: Internal class used by AffineGeometry to differentiate operations on lattice points and operatio...
Scalar Integer
In the generic class, the type scalar should be an integral type.
static Point cast(const TOtherPoint &other)
Specialized version to cast points to other point type.
PointVector< dim, TEuclideanRing, TContainer > Point
static void normalizeVector(Point &w, TInteger)
static double lcmPositive(double, double)
static double gcd(double, double)
static bool isNonZero(double x, double tol)
static std::pair< double, double > getMultipliers(double a, double b)
static bool isNonZero(float x, double tol)
static std::pair< float, float > getMultipliers(float a, float b)
static float gcd(float, float)
static float lcmPositive(float, float)
Aim: Internal class used by AffineGeometry to differentiate operations on point coordinates,...
static Integer lcmPositive(Integer a, Integer b)
static bool isNonZero(Integer x, double)
Scalar Integer
In the generic class, the type scalar should be an integral type.
static Integer gcd(Integer a, Integer b)
static std::pair< Integer, Integer > getMultipliers(Integer a, Integer b)