Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add triangle to convexity helper #1717

Merged
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
07b3ba4
Add compute3DTriangle in ConvexityHelper
JacquesOlivierLachaud Feb 19, 2024
e7fc366
Make 3D triangles Minkowski summable
JacquesOlivierLachaud Feb 19, 2024
daa1559
Working version of full subconvexity for 3 points forming a non degen…
JacquesOlivierLachaud Feb 20, 2024
71895e0
Working on degenerated cases
JacquesOlivierLachaud Feb 20, 2024
cce290c
Degenerated cases are now ok
JacquesOlivierLachaud Feb 20, 2024
640607b
Fix bad method name in doc
JacquesOlivierLachaud Feb 20, 2024
a828721
Update doc
JacquesOlivierLachaud Feb 20, 2024
a7d1140
Update doc
JacquesOlivierLachaud Feb 20, 2024
4e184cf
Merge branch 'master' of github.com:DGtal-team/DGtal into AddTriangle…
JacquesOlivierLachaud Feb 20, 2024
438ad9f
Update ChangeLog
JacquesOlivierLachaud Feb 20, 2024
191bfe9
Fix assertion
JacquesOlivierLachaud Feb 20, 2024
1bada15
Fix shadow parameter
JacquesOlivierLachaud Feb 20, 2024
f1862ed
Fix out of domain problem in full subconvexity check
JacquesOlivierLachaud Feb 20, 2024
797c37f
Check speed update
JacquesOlivierLachaud Feb 20, 2024
bd31286
Merge branch 'master' into AddTriangleToConvexityHelper
dcoeurjo Mar 3, 2024
0a4b709
Fix typo
JacquesOlivierLachaud Mar 3, 2024
1cb2036
Merge branch 'master' of github.com:DGtal-team/DGtal into AddTriangle…
JacquesOlivierLachaud Mar 3, 2024
8fda9a5
Merge branch 'master' into AddTriangleToConvexityHelper
dcoeurjo Mar 9, 2024
1757f18
Merge branch 'master' into AddTriangleToConvexityHelper
dcoeurjo Mar 27, 2024
a6cc9ae
Merge branch 'master' into AddTriangleToConvexityHelper
dcoeurjo Jun 3, 2024
1c7b8a3
Fix conflict in ChangeLog
JacquesOlivierLachaud Jun 5, 2024
6db3502
Fix conflict in ChangeLog
JacquesOlivierLachaud Jun 5, 2024
21e7f81
Fix BoundedLatticePointCounter::interiorIntersectionIntervalAlongAxis…
JacquesOlivierLachaud Jun 6, 2024
4aaf867
Fix typo
JacquesOlivierLachaud Jun 6, 2024
749b4c6
Merge branch 'master' of github.com:DGtal-team/DGtal into AddTriangle…
JacquesOlivierLachaud Jun 6, 2024
2d155b3
Fix ChangeLog
JacquesOlivierLachaud Jun 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,17 @@
- Fixing install path of CPM in the DGtalConfig.cmake.in (David Coeurjolly,
[#1713](https://github.com/DGtal-team/DGtal/pull/1713))


- *Topology package*
- Fix KhalimskySpaceND to get it work with BigInteger (Tristan Roussillon,
[#1681](https://github.com/DGtal-team/DGtal/pull/1681)

- *Geometry package*
- Fix Issue #1676 in testStabbingCircleComputer (Tristan Roussillon,
[#1688](https://github.com/DGtal-team/DGtal/pull/1688)
- Add creation of polytopes from segment and triangles in
JacquesOlivierLachaud marked this conversation as resolved.
Show resolved Hide resolved
ConvexityHelper and 3-5xfaster full subconvexity tests for triangles
in DigitalConvexity (Jacques-Olivier Lachaud,
[#1717](https://github.com/DGtal-team/DGtal/pull/1717))

- *IO*
- Fix of the `getHSV` method in the `Color` class. (David Coeurjolly,
Expand Down
18 changes: 14 additions & 4 deletions src/DGtal/geometry/doc/moduleDigitalConvexity.dox
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@ Lattice point retrieval services:
- BoundedLatticePolytope::getBoundaryPoints outputs the lattice points on the boundary of the polytope
- BoundedLatticePolytope::insertPoints inserts the lattice points in the polytope into some point set

The class ConvexityHelper also provides several static methods related to BoundedLatticePolytope:
- ConvexityHelper::computeLatticePolytope computes a BoundedLatticePolytope from an arbitrary range of points (use QuickHull algorithm, \see moduleQuickHull).
- ConvexityHelper::compute3DTriangle computes the BoundedLatticePolytope enclosing a 3D triangle (faster way than above, but limited to 3D triangles).
- ConvexityHelper::computeDegeneratedTriangle computes the BoundedLatticePolytope enclosing a degenerated triangle (the three points are aligned or non distinct, but may lie in arbitrary dimension).
- ConvexityHelper::computeSegment computes the BoundedLatticePolytope enclosing a segment in arbitrary dimension.


@subsection dgtal_dconvexity_sec22 Building a set of lattice cells from digital points

Expand Down Expand Up @@ -304,8 +310,8 @@ bool ok = simplex_cover.subset( point_cover ); // true

Morphological services (since 1.3):
- DigitalConvexity::makePolytope( const PointRange& X, bool safe ) const builds the tightest polytope enclosing the digital set \a X
- DigitalConvexity::isFullyConvex( const PointRange& X, bool convex0, bool safe ) const checks the full convexity of the digital set \a X
- DigitalConvexity::is0Convex( const PointRange& X, bool safe ) const checks the usual digital convexity (H-convexity or 0-convexity) of the digital set \a X
- DigitalConvexity::isFullyConvex( const PointRange& X, bool convex0 ) const checks the full convexity of the digital set \a X
- DigitalConvexity::is0Convex( const PointRange& X ) const checks the usual digital convexity (H-convexity or 0-convexity) of the digital set \a X
- DigitalConvexity::U( Dimension i, const PointRange& X ) const performs the digital Minkowski sum of \a X along direction \a i

The following snippet shows that a 4D ball is indeed fully convex.
Expand Down Expand Up @@ -334,9 +340,13 @@ Convexity services:
- DigitalConvexity::isKConvex tells if a given polytope is k-convex
- DigitalConvexity::isFullyConvex tells if a given polytope is fully convex
- DigitalConvexity::isKSubconvex tells if a given polytope is k-subconvex to some cell cover (i.e. k-tangent)
- DigitalConvexity::isKSubconvex( const Point&, const Point&, const CellGeometry&, const Dimension ) const tells if the Euclidean straight segment \f$ \lbrack a,b \rbrack \f$ is k-subconvex (i.e. k-tangent) to the given cell cover.
- DigitalConvexity::isKSubconvex( const Point& a, const Point& b, const CellGeometry& C, const Dimension k ) const tells if the Euclidean straight segment \f$ \lbrack a,b \rbrack \f$ is k-subconvex (i.e. k-tangent) to the given cell cover.
- DigitalConvexity::isFullySubconvex tells if a given polytope is fully subconvex to some cell cover
- DigitalConvexity::isFullySubconvex( const Point&, const Point&, const CellGeometry& ) const tells if the Euclidean straight segment \f$ \lbrack a,b \rbrack \f$ is fully k-subconvex (i.e. tangent) to the given cell cover.
- DigitalConvexity::isFullySubconvex( const Point& a, const Point& b, const CellGeometry& C ) const tells if the Euclidean straight segment \f$ \lbrack a,b \rbrack \f$ is fully k-subconvex (i.e. tangent) to the given cell cover.
- DigitalConvexity::isFullySubconvex( const LatticePolytope& P, const LatticeSet& StarX ) const tells if a given polytope is fully subconvex to a set of cells, represented as a LatticeSetByIntervals.
- DigitalConvexity::isFullySubconvex( const PointRange& Y, const LatticeSet& StarX ) const tells is the given range of points is fully subconvex to a set of cells, represented as a LatticeSetByIntervals.
- DigitalConvexity::isFullySubconvex( const Point& a, const Point& b, const LatticeSet& StarX ) const tells if the given pair of points is fully subconvex to a set of cells, represented as a LatticeSetByIntervals (three times faster than previous generic method).
- DigitalConvexity::isFullySubconvex( const Point& a, const Point& b, const Point& c, const LatticeSet& StarX ) const tells if the given triplets of points is fully subconvex to a set of cells, represented as a LatticeSetByIntervals (five times faster than previous generic method).

@subsection dgtal_dconvexity_sec25 Ehrhart polynomial of a lattice polytope

Expand Down
46 changes: 45 additions & 1 deletion src/DGtal/geometry/volumes/ConvexityHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,51 @@ namespace DGtal
static
PointRange
computeDegeneratedConvexHullVertices( PointRange& input_points );


/// Computes the lattice polytope enclosing a triangle in
/// dimension 3. Takes care of degeneracies (non distinct points
/// or alignment).
///
/// @param a any point
/// @param b any point
/// @param c any point
///
/// @param[in] make_minkowski_summable Other constraints are added
/// so that we can perform axis aligned Minkowski sums on this
/// polytope. Useful for checking full convexity (see
/// moduleDigitalConvexity).
///
/// @return the tightiest bounded lattice polytope
/// (i.e. H-representation) including the given range of points.
static
LatticePolytope
compute3DTriangle( const Point& a, const Point& b, const Point& c,
bool make_minkowski_summable = false );

/// Computes the lattice polytope enclosing a degenerated
/// triangle. The points must be aligned (or non distinct).
///
/// @param a any point
/// @param b any point
/// @param c any point
///
/// @return the tightiest bounded lattice polytope
/// (i.e. H-representation) including the given range of points.
static
LatticePolytope
computeDegeneratedTriangle( const Point& a, const Point& b, const Point& c );

/// Computes the lattice polytope enclosing a segment.
///
/// @param a any point
/// @param b any point
///
/// @return the tightiest bounded lattice polytope
/// (i.e. H-representation) including the given range of
/// points. It is always Minkowski summable.
static
LatticePolytope
computeSegment( const Point& a, const Point& b );

/// @}

Expand Down
133 changes: 129 additions & 4 deletions src/DGtal/geometry/volumes/ConvexityHelper.ih
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,129 @@ computeDegeneratedLatticePolytope
false, false );
}

//-----------------------------------------------------------------------------
template < int dim, typename TInteger, typename TInternalInteger >
typename DGtal::ConvexityHelper< dim, TInteger, TInternalInteger>::LatticePolytope
DGtal::ConvexityHelper< dim, TInteger, TInternalInteger>::compute3DTriangle
( const Point& a, const Point& b, const Point& c,
bool make_minkowski_summable )
{
if constexpr( dim != 3 ) return LatticePolytope();
using Op = detail::BoundedRationalPolytopeSpecializer< dimension, Integer>;
typedef typename LatticePolytope::Domain Domain;
typedef typename LatticePolytope::HalfSpace PolytopeHalfSpace;
// Compute domain
const Vector ab = b - a;
const Vector bc = c - b;
const Vector ca = a - c;
const Vector n = Op::crossProduct( ab, bc );
if ( n == Vector::zero )
return computeDegeneratedTriangle( a, b, c );
const Point low = a.inf( b ).inf( c );
const Point high = a.sup( b ).sup( c );
// Initialize polytope
std::vector< PolytopeHalfSpace > PHS;
PHS.reserve( make_minkowski_summable ? 11 : 5 );
const Integer n_a = n.dot( a );
const Vector u = Op::crossProduct( ab, n );
const Vector v = Op::crossProduct( bc, n );
const Vector w = Op::crossProduct( ca, n );
PHS.emplace_back( n, n_a );
PHS.emplace_back( -n, -n_a );
if ( ! make_minkowski_summable )
{ // It is enough to have one constraint per edge.
PHS.emplace_back( u, u.dot( a ) );
PHS.emplace_back( v, v.dot( b ) );
PHS.emplace_back( w, w.dot( c ) );
}
else
{ // Compute additionnal constraints on edges so that the
// Minkowski sum with axis-aligned edges is valid.
for ( Integer d = -1; d <= 1; d += 2 )
for ( Dimension k = 0; k < dim; k++ )
{
const Vector i = Vector::base( k, d );
const Vector eab = Op::crossProduct( ab, i );
const Integer eab_a = eab.dot( a );
if ( eab.dot( c ) < eab_a ) // c must be below plane (a,eab)
PHS.emplace_back( eab, eab_a );
const Vector ebc = Op::crossProduct( bc, i );
const Integer ebc_b = ebc.dot( b );
if ( ebc.dot( a ) < ebc_b ) // a must be below plane (b,ebc)
PHS.emplace_back( ebc, ebc_b );
const Vector eca = Op::crossProduct( ca, i );
const Integer eca_c = eca.dot( c );
if ( eca.dot( b ) < eca_c ) // b must be below plane (c,eca)
PHS.emplace_back( eca, eca_c );
}
}
return LatticePolytope( Domain( low, high ),
PHS.cbegin(), PHS.cend(),
make_minkowski_summable, false );
}

//-----------------------------------------------------------------------------
template < int dim, typename TInteger, typename TInternalInteger >
typename DGtal::ConvexityHelper< dim, TInteger, TInternalInteger>::LatticePolytope
DGtal::ConvexityHelper< dim, TInteger, TInternalInteger>::
computeDegeneratedTriangle
( const Point& a, const Point& b, const Point& c )
{
if ( a == b ) return computeSegment( a, c );
if ( ( a == c ) || ( b == c ) ) return computeSegment( a, b );
// The three points are distinct, hence aligned. One is in-between the two others.
const Point low = a.inf( b ).inf( c );
const Point high = a.sup( b ).sup( c );
for ( Dimension k = 0; k < dim; k++ )
{
const auto lk = low [ k ];
const auto hk = high[ k ];
if ( ( a[ k ] != lk ) && ( a[ k ] != hk ) ) return computeSegment( b, c );
if ( ( b[ k ] != lk ) && ( b[ k ] != hk ) ) return computeSegment( a, c );
if ( ( c[ k ] != lk ) && ( c[ k ] != hk ) ) return computeSegment( a, b );
}
trace.error() << "[ConvexityHelper::computeSegmentFromDegeneratedTriangle] "
<< "Should never arrive here." << std::endl;
return computeSegment( a, a );
}

//-----------------------------------------------------------------------------
template < int dim, typename TInteger, typename TInternalInteger >
typename DGtal::ConvexityHelper< dim, TInteger, TInternalInteger>::LatticePolytope
DGtal::ConvexityHelper< dim, TInteger, TInternalInteger>::computeSegment
( const Point& a, const Point& b )
{
if constexpr( dim != 3 ) return LatticePolytope();
using Op = detail::BoundedRationalPolytopeSpecializer< dimension, Integer>;
typedef typename LatticePolytope::Domain Domain;
typedef typename LatticePolytope::HalfSpace PolytopeHalfSpace;
// Compute domain
const Point low = a.inf( b );
const Point high = a.sup( b );
const Vector ab = b - a;
bool degenerate = ( ab == Vector::zero );
// Initialize polytope
std::vector< PolytopeHalfSpace > PHS;
if ( degenerate )
return LatticePolytope( Domain( low, high ), PHS.cbegin(), PHS.cend(), true, false );
PHS.reserve( 2*dim );
// Compute additionnal constraints on edges so that the
// Minkowski sum with axis-aligned edges is valid.
for ( Integer d = -1; d <= 1; d += 2 )
for ( Dimension k = 0; k < dim; k++ )
{
const Vector i = Vector::base( k, d );
const Vector e = Op::crossProduct( ab, i );
if ( e != Vector::zero )
{
const Integer e_a = e.dot( a );
PHS.emplace_back( e, e_a );
}
}
return LatticePolytope( Domain( low, high ), PHS.cbegin(), PHS.cend(), true, false );
}


//-----------------------------------------------------------------------------
template < int dim, typename TInteger, typename TInternalInteger >
typename DGtal::ConvexityHelper< dim, TInteger, TInternalInteger>::PointRange
Expand Down Expand Up @@ -306,10 +429,12 @@ computeLatticePolytope
// Compute domain
Point l = input_points[ 0 ];
Point u = input_points[ 0 ];
for ( const auto& p : input_points ) {
l = l.inf( p );
u = u.sup( p );
}
for ( std::size_t i = 1; i < input_points.size(); i++ )
{
const auto& p = input_points[ i ];
l = l.inf( p );
u = u.sup( p );
}
Domain domain( l, u );
// Compute convex hull
ConvexHull hull;
Expand Down
44 changes: 43 additions & 1 deletion src/DGtal/geometry/volumes/DigitalConvexity.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,24 @@ namespace DGtal
/// generic since the two other methods require a Minkowski
/// summable polytope, i.e. `P.canBeSummed() == true`.
bool isFullySubconvex( const PointRange& Y, const LatticeSet& StarX ) const;


/// Tells if the non-degenerated 3D triangle a,b,c is digitally
/// fully subconvex to some lattice set \a Star_X, i.e. the cell
/// cover of some set X represented by lattice points.
///
/// @param a any 3D point (distinct from the two others)
/// @param b any 3D point (distinct from the two others)
/// @param c any 3D point (distinct from the two others)
///
/// @param StarX any lattice set representing an open cubical complex.
/// @return 'true' iff Y is digitally fully subconvex to X.
///
/// @note This method is supposed to be faster than the others,
/// but is limited to 3D triangles.
bool isFullySubconvex( const Point& a, const Point& b, const Point& c,
const LatticeSet& StarX ) const;


/// Tells if a given segment from \a a to \a b is digitally
/// k-subconvex (i.e. k-tangent) to some cell cover \a C. The
Expand Down Expand Up @@ -491,7 +509,7 @@ namespace DGtal
/// polytope and then checking if it subconvex.
bool isFullySubconvex( const Point& a, const Point& b,
const LatticeSet& StarX ) const;

/// Given a range of distinct points \a X, computes the tightiest
/// polytope that enclosed it. Note that this polytope may contain
/// more lattice points than the given input points.
Expand Down Expand Up @@ -537,6 +555,30 @@ namespace DGtal
LatticeSet StarCvxH( const PointRange& X,
Dimension axis = dimension ) const;

/// Builds the cell complex `Star(CvxH({a,b,c}))` for `a,b,c` a
/// non-degenerate 3D triangle, represented as a lattice set (stacked
/// row representation).
///
/// @param a any 3D point (distinct from the two others)
/// @param b any 3D point (distinct from the two others)
/// @param c any 3D point (distinct from the two others)
///
/// @param axis specifies the projection axis for the row
/// representation if below space dimension, otherwise chooses the
/// axis that minimizes memory/computations.
///
/// @return the range of cells touching the triangle `abc`,
/// represented as a lattice set (cells are represented with
/// Khalimsky coordinates). If the triangle is degenerate (a,b,c
/// not distinct or aligned), then it returns an empty range of
/// cells.
///
/// @note It is useful to specify an axis if you wish later to
/// compare or make operations with several lattice sets. They
/// must indeed have the same axis.
LatticeSet StarCvxH( const Point& a, const Point& b, const Point& c,
Dimension axis = dimension ) const;

/// Computes the number of cells in Star(CvxH(X)) for X a digital set.
///
/// @param X any range of lattice points
Expand Down
Loading
Loading