2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * @file BoundedLatticePolytope.ih
19 * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20 * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
24 * Implementation of inline methods defined in BoundedLatticePolytope.h
26 * This file is part of the DGtal library.
30//////////////////////////////////////////////////////////////////////////////
32#include "DGtal/math/linalg/SimpleMatrix.h"
33#include "DGtal/geometry/volumes/BoundedLatticePolytopeCounter.h"
34//////////////////////////////////////////////////////////////////////////////
36///////////////////////////////////////////////////////////////////////////////
37// IMPLEMENTATION of inline methods.
38///////////////////////////////////////////////////////////////////////////////
40///////////////////////////////////////////////////////////////////////////////
41// ----------------------- Standard services ------------------------------
43//-----------------------------------------------------------------------------
44template <typename TSpace>
46DGtal::BoundedLatticePolytope<TSpace>::
52 myValidEdgeConstraints = false;
53 D = Domain( Point::zero, Point::zero );
56//-----------------------------------------------------------------------------
57template <typename TSpace>
58DGtal::BoundedLatticePolytope<TSpace>::
59BoundedLatticePolytope( std::initializer_list<Point> l )
61 myValidEdgeConstraints = false;
62 init( l.begin(), l.end() );
65//-----------------------------------------------------------------------------
66template <typename TSpace>
67template <typename PointIterator>
68DGtal::BoundedLatticePolytope<TSpace>::
69BoundedLatticePolytope( PointIterator itB, PointIterator itE )
71 myValidEdgeConstraints = false;
75//-----------------------------------------------------------------------------
76template <typename TSpace>
77template <typename HalfSpaceIterator>
78DGtal::BoundedLatticePolytope<TSpace>::
79BoundedLatticePolytope( const Domain& domain,
80 HalfSpaceIterator itB, HalfSpaceIterator itE,
81 bool valid_edge_constraints,
82 bool check_duplicate_constraints )
83 : myValidEdgeConstraints( valid_edge_constraints )
85 init( domain, itB, itE,
86 valid_edge_constraints, check_duplicate_constraints );
89//-----------------------------------------------------------------------------
90template <typename TSpace>
91template <typename HalfSpaceIterator>
93DGtal::BoundedLatticePolytope<TSpace>::
94init( const Domain& domain,
95 HalfSpaceIterator itB, HalfSpaceIterator itE,
96 bool valid_edge_constraints,
97 bool check_duplicate_constraints )
100 myValidEdgeConstraints = valid_edge_constraints;
101 const Dimension d = dimension;
102 const Point lo = domain.lowerBound();
103 const Point hi = domain.upperBound();
104 D = Domain( lo, hi );
105 // Add constraints related to sup/inf in x.
106 for ( Dimension s = 0; s < d; ++s )
108 Vector z = Vector::zero;
109 z[ s ] = NumberTraits<Integer>::ONE;
111 B.push_back( hi[ s ] );
112 z[ s ] = -NumberTraits<Integer>::ONE;
114 B.push_back( -lo[ s ] );
117 if ( check_duplicate_constraints )
119 // Add other halfplanes
120 for ( auto it = itB; it != itE; ++it )
122 // Checks that is not inside.
123 const auto a = it->N;
124 const auto b = it->c;
125 const auto itAE = A.begin()+2*d;
126 const auto itF = std::find( A.begin(), itAE , a );
135 const auto k = itF - A.begin();
136 B[ k ] = std::min( B[ k ], b );
141 { // Add other halfplanes
142 for ( auto it = itB; it != itE; ++it )
144 A.push_back( it->N );
145 B.push_back( it->c );
149 I = std::vector<bool>( nb_hp, true ); // inequalities are large
152//-----------------------------------------------------------------------------
153template <typename TSpace>
155DGtal::BoundedLatticePolytope<TSpace>::
156internalInitFromTriangle3D( Point a, Point b, Point c )
161 Vector n = detail::BoundedLatticePolytopeSpecializer< dimension, Integer >::
162 crossProduct( ab, bc );
163 if ( n == Vector::zero ) { clear(); return false; }
165 B.push_back( a.dot( A.back() ) );
168 B.push_back( a.dot( A.back() ) );
169 I = std::vector<bool>( B.size(), true ); // inequalities are large
170 std::vector<Point> pts = { a, b, c };
171 detail::BoundedLatticePolytopeSpecializer< dimension, Integer >::
172 addEdgeConstraint( *this, 0, 1, pts );
173 detail::BoundedLatticePolytopeSpecializer< dimension, Integer >::
174 addEdgeConstraint( *this, 1, 2, pts );
175 detail::BoundedLatticePolytopeSpecializer< dimension, Integer >::
176 addEdgeConstraint( *this, 2, 0, pts );
180//-----------------------------------------------------------------------------
181template <typename TSpace>
183DGtal::BoundedLatticePolytope<TSpace>::
184internalInitFromSegment3D( Point a, Point b )
187 if ( ab == Vector::zero ) return true; // domain and constraints already computed
189 for ( Dimension k = 0; k < 3; ++k )
191 const auto t = Vector::base( k );
192 Vector w = detail::BoundedLatticePolytopeSpecializer< dimension, Integer >::
193 crossProduct( ab, t );
194 if ( w == Vector::zero ) continue;
196 B.push_back( a.dot( w ) );
197 A.push_back( -1 * w );
198 B.push_back( a.dot( A.back() ) );
201 I = std::vector<bool>( 2 * 3 + nb, true ); // inequalities are large
205//-----------------------------------------------------------------------------
206template <typename TSpace>
208DGtal::BoundedLatticePolytope<TSpace>::
209internalInitFromSegment2D( Point a, Point b )
212 if ( ab == Vector::zero ) return true; // domain and constraints already computed
213 Vector n( -ab[ 1 ], ab[ 0 ] );
215 B.push_back( a.dot( n ) );
216 A.push_back( -1 * n );
217 B.push_back( a.dot( A.back() ) );
218 I = std::vector<bool>( 2*2+2, true ); // inequalities are large
222//-----------------------------------------------------------------------------
223template <typename TSpace>
224template <typename PointIterator>
226DGtal::BoundedLatticePolytope<TSpace>::
227init( PointIterator itB, PointIterator itE )
229 typedef SimpleMatrix<Integer,dimension,dimension> Matrix;
231 const Dimension d = dimension;
232 std::vector<Point> pts;
233 for ( ; itB != itE; ++itB ) pts.push_back( *itB );
236 for ( Dimension s = 1; s < pts.size(); ++s )
238 lo = lo.inf( pts[ s ] );
239 hi = hi.sup( pts[ s ] );
241 // Add constraints related to sup/inf in x.
242 for ( Dimension s = 0; s < d; ++s )
244 Vector z = Vector::zero;
245 z[ s ] = NumberTraits<Integer>::ONE;
247 B.push_back( hi[ s ] );
248 z[ s ] = -NumberTraits<Integer>::ONE;
250 B.push_back( -lo[ s ] );
252 D = Domain( lo, hi );
253 if ( pts.size() != d+1 )
254 { // Some degenerated cases are taken into account.
255 myValidEdgeConstraints = true;
257 if ( pts.size() == 3 )
258 return internalInitFromTriangle3D( pts[ 0 ], pts[ 1 ], pts[ 2 ] );
259 else if ( pts.size() == 2 )
260 return internalInitFromSegment3D( pts[ 0 ], pts[ 1 ] );
261 } else if ( d == 2 ) {
262 if ( pts.size() == 2 )
263 return internalInitFromSegment2D( pts[ 0 ], pts[ 1 ] );
265 I = std::vector<bool>( 2*2, true ); // inequalities are large
266 if ( pts.size() == 1 ) return true;
270 // Build Matrix A and Vector b through cofactors
271 I = std::vector<bool>( 3*d+1, true ); // inequalities are large
274 for ( Dimension s = 0; s <= d; ++s )
276 // Build matrix v composed of p_i and vectors p_k - p_i for i and k != p
278 Dimension p = (s+1) % (d+1);
279 for ( Dimension j = 0; j < d; ++j )
280 V.setComponent( 0, j, pts[ p ][ j ] - pts[ s ][ j ] );
281 for ( Dimension k = 1; k < d; ++k )
283 Dimension l = (p+k) % (d+1);
284 for ( Dimension j = 0; j < d; ++j )
285 V.setComponent( k, j, pts[ l ][ j ] - pts[ p ][ j ] );
294 // Form vector [b, 0, ..., 0]
295 Vector z = Vector::zero;
297 a = V.cofactor().transpose() * z;
298 b += a.dot( pts[ s ] );
300 if ( a.dot( pts[ s ] ) > b ) { a *= (Integer) -1; b *= (Integer) -1; }
304 myValidEdgeConstraints = ( dimension == 2 );
305 if ( dimension == 3 )
306 { // One should add edges
307 for ( unsigned int i = 0; i < pts.size(); ++i )
308 for ( unsigned int j = i+1; j < pts.size(); ++j ) {
309 detail::BoundedLatticePolytopeSpecializer< dimension, Integer >::addEdgeConstraint
310 ( *this, i, j, pts );
312 myValidEdgeConstraints = true;
314 // not implemented for dimension > 3
319//-----------------------------------------------------------------------------
320template <typename TSpace>
321DGtal::BoundedLatticePolytope<TSpace>
322DGtal::BoundedLatticePolytope<TSpace>::
323interiorPolytope() const
325 BoundedLatticePolytope P( *this );
326 for ( auto it = P.I.begin(), itE = P.I.end(); it != itE; ++it )
331//-----------------------------------------------------------------------------
332template <typename TSpace>
333DGtal::BoundedLatticePolytope<TSpace>
334DGtal::BoundedLatticePolytope<TSpace>::
335closurePolytope() const
337 BoundedLatticePolytope P( *this );
338 for ( auto it = P.I.begin(), itE = P.I.end(); it != itE; ++it )
343//-----------------------------------------------------------------------------
344template <typename TSpace>
346DGtal::BoundedLatticePolytope<TSpace>::
347cut( Dimension k, bool pos, Integer b, bool large )
349 ASSERT( k < dimension );
350 auto i = 2*k + (pos ? 0 : 1);
351 B[ i ] = std::min( B[ i ], b );
353 Point L = D.lowerBound();
354 Point U = D.upperBound();
355 if ( pos ) U[ k ] = B[ i ];
356 else L[ k ] = -B[ i ];
361//-----------------------------------------------------------------------------
362template <typename TSpace>
364DGtal::BoundedLatticePolytope<TSpace>::
365cut( const Vector& a, Integer b, bool large, bool valid_edge_constraint )
367 // Checks that is not inside.
368 auto it = std::find( A.begin(), A.end(), a );
373 I.push_back( large );
374 myValidEdgeConstraints = myValidEdgeConstraints && valid_edge_constraint; // a cut might invalidate an edge constraint
375 return (unsigned int)(A.size() - 1);
379 auto k = it - A.begin();
380 B[ k ] = std::min( B[ k ], b );
382 myValidEdgeConstraints = myValidEdgeConstraints && valid_edge_constraint; // a cut might invalidate an edge constraint
383 return (unsigned int)k;
386//-----------------------------------------------------------------------------
387template <typename TSpace>
389DGtal::BoundedLatticePolytope<TSpace>::
390cut( const HalfSpace& hs, bool large, bool valid_edge_constraint )
394 return cut( a, b, large, valid_edge_constraint );
397//-----------------------------------------------------------------------------
398template <typename TSpace>
400DGtal::BoundedLatticePolytope<TSpace>::
401swap( BoundedLatticePolytope & other )
406 std::swap( D, other.D );
407 std::swap( myValidEdgeConstraints, other.myValidEdgeConstraints );
410//-----------------------------------------------------------------------------
411template <typename TSpace>
413DGtal::BoundedLatticePolytope<TSpace>::
414isInside( const Point& p ) const
417 for ( Dimension i = 0; i < A.size(); ++i )
421 ? A[ i ].dot( p ) <= B[ i ]
422 : A[ i ].dot( p ) < B[ i ];
423 if ( ! in_half_space ) return false;
428//-----------------------------------------------------------------------------
429template <typename TSpace>
431DGtal::BoundedLatticePolytope<TSpace>::
432isDomainPointInside( const Point& p ) const
435 for ( Dimension i = 2*dimension; i < A.size(); ++i )
439 ? A[ i ].dot( p ) <= B[ i ]
440 : A[ i ].dot( p ) < B[ i ];
441 if ( ! in_half_space ) return false;
446//-----------------------------------------------------------------------------
447template <typename TSpace>
449DGtal::BoundedLatticePolytope<TSpace>::
450isInterior( const Point& p ) const
453 for ( Dimension i = 0; i < A.size(); ++i )
455 bool in_half_space = A[ i ].dot( p ) < B[ i ];
456 if ( ! in_half_space ) return false;
461//-----------------------------------------------------------------------------
462template <typename TSpace>
464DGtal::BoundedLatticePolytope<TSpace>::
465isBoundary( const Point& p ) const
468 bool is_boundary = false;
469 for ( Dimension i = 0; i < A.size(); ++i )
471 auto Ai_dot_p = A[ i ].dot( p );
472 if ( Ai_dot_p == B[ i ] ) is_boundary = true;
473 if ( Ai_dot_p > B[ i ] ) return false;
478//-----------------------------------------------------------------------------
479template <typename TSpace>
480typename DGtal::BoundedLatticePolytope<TSpace>::Self&
481DGtal::BoundedLatticePolytope<TSpace>::
482operator*=( Integer t )
484 for ( Integer& b : B ) b *= t;
485 D = Domain( D.lowerBound() * t, D.upperBound() * t );
489//-----------------------------------------------------------------------------
490template <typename TSpace>
491typename DGtal::BoundedLatticePolytope<TSpace>::Self&
492DGtal::BoundedLatticePolytope<TSpace>::
493operator+=( UnitSegment s )
495 for ( Dimension i = 0; i < A.size(); ++i )
497 if ( A[ i ][ s.k ] > NumberTraits<Integer>::ZERO )
498 B[ i ] += A[ i ][ s.k ];
500 Vector z = Vector::zero;
501 z[ s.k ] = NumberTraits<Integer>::ONE;
502 D = Domain( D.lowerBound(), D.upperBound() + z );
506//-----------------------------------------------------------------------------
507template <typename TSpace>
508typename DGtal::BoundedLatticePolytope<TSpace>::Self&
509DGtal::BoundedLatticePolytope<TSpace>::
510operator+=( StrictUnitSegment s )
512 for ( Dimension i = 0; i < A.size(); ++i )
514 if ( A[ i ][ s.k ] > NumberTraits<Integer>::ZERO )
516 B[ i ] += A[ i ][ s.k ];
519 else if ( A[ i ][ s.k ] < NumberTraits<Integer>::ZERO )
522 Vector z = Vector::zero;
523 z[ s.k ] = NumberTraits<Integer>::ONE;
524 D = Domain( D.lowerBound(), D.upperBound() + z );
528//-----------------------------------------------------------------------------
529template <typename TSpace>
530typename DGtal::BoundedLatticePolytope<TSpace>::Self&
531DGtal::BoundedLatticePolytope<TSpace>::
532operator+=( LeftStrictUnitSegment s )
534 I[ 2*s.k + 1 ] = false;
535 for ( Dimension i = 0; i < A.size(); ++i )
537 if ( A[ i ][ s.k ] > NumberTraits<Integer>::ZERO )
538 B[ i ] += A[ i ][ s.k ];
539 if ( A[ i ][ s.k ] < NumberTraits<Integer>::ZERO )
542 Vector z = Vector::zero;
543 z[ s.k ] = NumberTraits<Integer>::ONE;
544 D = Domain( D.lowerBound() + z, D.upperBound() + z );
548//-----------------------------------------------------------------------------
549template <typename TSpace>
550typename DGtal::BoundedLatticePolytope<TSpace>::Self&
551DGtal::BoundedLatticePolytope<TSpace>::
552operator+=( RightStrictUnitSegment s )
555 for ( Dimension i = 0; i < A.size(); ++i )
557 if ( A[ i ][ s.k ] > NumberTraits<Integer>::ZERO ) {
558 B[ i ] += A[ i ][ s.k ];
562 Vector z = Vector::zero;
563 z[ s.k ] = NumberTraits<Integer>::ONE;
567//-----------------------------------------------------------------------------
568template <typename TSpace>
569typename DGtal::BoundedLatticePolytope<TSpace>::Self&
570DGtal::BoundedLatticePolytope<TSpace>::
571operator+=( UnitCell c )
573 for ( Dimension i = 0; i < c.dims.size(); ++i )
574 *this += UnitSegment( c.dims[ i ] );
578//-----------------------------------------------------------------------------
579template <typename TSpace>
580typename DGtal::BoundedLatticePolytope<TSpace>::Self&
581DGtal::BoundedLatticePolytope<TSpace>::
582operator+=( StrictUnitCell c )
584 for ( Dimension i = 0; i < c.dims.size(); ++i )
585 *this += StrictUnitSegment( c.dims[ i ] );
589//-----------------------------------------------------------------------------
590template <typename TSpace>
591typename DGtal::BoundedLatticePolytope<TSpace>::Self&
592DGtal::BoundedLatticePolytope<TSpace>::
593operator+=( RightStrictUnitCell c )
595 for ( Dimension i = 0; i < c.dims.size(); ++i )
596 *this += RightStrictUnitSegment( c.dims[ i ] );
600//-----------------------------------------------------------------------------
601template <typename TSpace>
602typename DGtal::BoundedLatticePolytope<TSpace>::Self&
603DGtal::BoundedLatticePolytope<TSpace>::
604operator+=( LeftStrictUnitCell c )
606 for ( Dimension i = 0; i < c.dims.size(); ++i )
607 *this += LeftStrictUnitSegment( c.dims[ i ] );
611//-----------------------------------------------------------------------------
612template <typename TSpace>
613typename DGtal::BoundedLatticePolytope<TSpace>::Integer
614DGtal::BoundedLatticePolytope<TSpace>::
617 BoundedLatticePolytopeCounter<Space> C( *this );
618 return C.countAlongAxis( C.longestAxis() );
621//-----------------------------------------------------------------------------
622template <typename TSpace>
623typename DGtal::BoundedLatticePolytope<TSpace>::Integer
624DGtal::BoundedLatticePolytope<TSpace>::
627 BoundedLatticePolytopeCounter<Space> C( *this );
628 return C.countInteriorAlongAxis( C.longestAxis() );
630//-----------------------------------------------------------------------------
631template <typename TSpace>
632typename DGtal::BoundedLatticePolytope<TSpace>::Integer
633DGtal::BoundedLatticePolytope<TSpace>::
636 const auto clP = closurePolytope();
637 return clP.count() - countInterior();
639//-----------------------------------------------------------------------------
640template <typename TSpace>
641typename DGtal::BoundedLatticePolytope<TSpace>::Integer
642DGtal::BoundedLatticePolytope<TSpace>::
643countWithin( Point lo, Point hi ) const
645 BoundedLatticePolytopeCounter<Space> C( *this );
647 lo = lo.sup( D.lowerBound() );
648 hi = hi.inf( D.upperBound() );
649 auto b_size = hi[ 0 ] - lo[ 0 ];
650 for ( Dimension a = 1; a < dimension; a++ )
652 const auto a_size = hi[ a ] - lo[ a ];
653 if ( b_size < a_size ) { b = a; b_size = a_size; }
657 Domain localD( lo, hi );
658 for ( auto&& p : localD )
660 auto II = C.intersectionIntervalAlongAxis( p, b );
661 nb += II.second - II.first;
665//-----------------------------------------------------------------------------
666template <typename TSpace>
667typename DGtal::BoundedLatticePolytope<TSpace>::Integer
668DGtal::BoundedLatticePolytope<TSpace>::
669countUpTo( Integer max) const
671 BoundedLatticePolytopeCounter<Space> C( *this );
672 Dimension a = C.longestAxis();
674 Point lo = D.lowerBound();
675 Point hi = D.upperBound();
677 Domain localD( lo, hi );
678 for ( auto&& p : localD )
680 auto II = C.intersectionIntervalAlongAxis( p, a );
681 nb += II.second - II.first;
682 if ( nb >= max ) return max;
686//-----------------------------------------------------------------------------
687template <typename TSpace>
689DGtal::BoundedLatticePolytope<TSpace>::
690getPoints( std::vector<Point>& pts ) const
693 BoundedLatticePolytopeCounter<Space> C( *this );
694 C.getPointsAlongAxis( pts, C.longestAxis() );
696//-----------------------------------------------------------------------------
697template <typename TSpace>
699DGtal::BoundedLatticePolytope<TSpace>::
700getKPoints( std::vector<Point>& pts, const Point& alpha_shift ) const
703 BoundedLatticePolytopeCounter<Space> C( *this );
704 Dimension a = C.longestAxis();
706 Point lo = D.lowerBound();
707 Point hi = D.upperBound();
709 Domain localD( lo, hi );
710 for ( auto&& p : localD )
712 auto II = C.intersectionIntervalAlongAxis( p, a );
713 Point q( 2*p - alpha_shift );
714 q[ a ] = 2*II.first - alpha_shift[ a ];
715 for ( Integer x = II.first; x < II.second; x++ )
722//-----------------------------------------------------------------------------
723template <typename TSpace>
724template <typename PointSet>
726DGtal::BoundedLatticePolytope<TSpace>::
727insertPoints( PointSet& pts_set ) const
729 std::vector<Point> pts;
731 pts_set.insert( pts.cbegin(), pts.cend() );
733//-----------------------------------------------------------------------------
734template <typename TSpace>
735template <typename PointSet>
737DGtal::BoundedLatticePolytope<TSpace>::
738insertKPoints( PointSet& pts_set, const Point& alpha_shift ) const
740 BoundedLatticePolytopeCounter<Space> C( *this );
741 Dimension a = C.longestAxis();
743 Point lo = D.lowerBound();
744 Point hi = D.upperBound();
746 Domain localD( lo, hi );
747 for ( auto&& p : localD )
749 auto II = C.intersectionIntervalAlongAxis( p, a );
750 Point q( 2*p - alpha_shift );
751 q[ a ] = 2*II.first - alpha_shift[ a ];
752 for ( Integer x = II.first; x < II.second; x++ )
759//-----------------------------------------------------------------------------
760template <typename TSpace>
762DGtal::BoundedLatticePolytope<TSpace>::
763getInteriorPoints( std::vector<Point>& pts ) const
766 BoundedLatticePolytopeCounter<Space> C( *this );
767 C.getInteriorPointsAlongAxis( pts, C.longestAxis() );
769//-----------------------------------------------------------------------------
770template <typename TSpace>
772DGtal::BoundedLatticePolytope<TSpace>::
773getBoundaryPoints( std::vector<Point>& pts ) const
775 const auto clP = closurePolytope();
776 BoundedLatticePolytopeCounter<Space> C ( *this );
777 BoundedLatticePolytopeCounter<Space> clC( clP );
779 const Dimension a = clC.longestAxis();
780 Point lo = clP.getDomain().lowerBound();
781 Point hi = clP.getDomain().upperBound();
783 Domain localD( lo, hi );
784 for ( auto&& p : localD )
786 auto II = C .interiorIntersectionIntervalAlongAxis( p, a );
787 auto clI = clC.intersectionIntervalAlongAxis( p, a );
788 auto nbI = II.second - II.first;
789 auto nbclI = clI.second - clI.first;
790 if ( nbI == nbclI ) continue;
792 trace.error() << "BoundedLatticePolytope::getBoundaryPoints: bad count"
797 for ( Integer x = clI.first; x != clI.second; x++ )
805 if ( clI.first < II.first )
810 if ( clI.second > II.second )
820//-----------------------------------------------------------------------------
821template <typename TSpace>
822typename DGtal::BoundedLatticePolytope<TSpace>::Integer
823DGtal::BoundedLatticePolytope<TSpace>::
824countByScanning() const
827 for ( const Point & p : D )
828 nb += isDomainPointInside( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
832//-----------------------------------------------------------------------------
833template <typename TSpace>
834typename DGtal::BoundedLatticePolytope<TSpace>::Integer
835DGtal::BoundedLatticePolytope<TSpace>::
836countInteriorByScanning() const
839 for ( const Point & p : D )
840 nb += isInterior( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
843//-----------------------------------------------------------------------------
844template <typename TSpace>
845typename DGtal::BoundedLatticePolytope<TSpace>::Integer
846DGtal::BoundedLatticePolytope<TSpace>::
847countBoundaryByScanning() const
850 for ( const Point & p : D )
851 nb += isBoundary( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
854//-----------------------------------------------------------------------------
855template <typename TSpace>
856typename DGtal::BoundedLatticePolytope<TSpace>::Integer
857DGtal::BoundedLatticePolytope<TSpace>::
858countWithinByScanning( Point lo, Point hi ) const
861 Domain D1( lo.sup( D.lowerBound() ), hi.inf( D.upperBound() ) );
862 for ( const Point & p : D1 )
863 nb += isDomainPointInside( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
866//-----------------------------------------------------------------------------
867template <typename TSpace>
868typename DGtal::BoundedLatticePolytope<TSpace>::Integer
869DGtal::BoundedLatticePolytope<TSpace>::
870countUpToByScanning( Integer max) const
873 for ( const Point & p : D ) {
874 nb += isDomainPointInside( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
875 if ( nb >= max ) return max;
879//-----------------------------------------------------------------------------
880template <typename TSpace>
882DGtal::BoundedLatticePolytope<TSpace>::
883getPointsByScanning( std::vector<Point>& pts ) const
886 for ( const Point & p : D )
887 if ( isDomainPointInside( p ) ) pts.push_back( p );
889//-----------------------------------------------------------------------------
890template <typename TSpace>
891template <typename PointSet>
893DGtal::BoundedLatticePolytope<TSpace>::
894insertPointsByScanning( PointSet& pts_set ) const
896 for ( const Point & p : D )
897 if ( isDomainPointInside( p ) ) pts_set.insert( p );
899//-----------------------------------------------------------------------------
900template <typename TSpace>
902DGtal::BoundedLatticePolytope<TSpace>::
903getInteriorPointsByScanning( std::vector<Point>& pts ) const
906 for ( const Point & p : D )
907 if ( isInterior( p ) ) pts.push_back( p );
909//-----------------------------------------------------------------------------
910template <typename TSpace>
912DGtal::BoundedLatticePolytope<TSpace>::
913getBoundaryPointsByScanning( std::vector<Point>& pts ) const
916 for ( const Point & p : D )
917 if ( isBoundary( p ) ) pts.push_back( p );
920//-----------------------------------------------------------------------------
921template <typename TSpace>
922const typename DGtal::BoundedLatticePolytope<TSpace>::Domain&
923DGtal::BoundedLatticePolytope<TSpace>::getDomain() const
928//-----------------------------------------------------------------------------
929template <typename TSpace>
931DGtal::BoundedLatticePolytope<TSpace>::nbHalfSpaces() const
933 return static_cast<unsigned int>(A.size());
936//-----------------------------------------------------------------------------
937template <typename TSpace>
938const typename DGtal::BoundedLatticePolytope<TSpace>::Vector&
939DGtal::BoundedLatticePolytope<TSpace>::getA( unsigned int i ) const
941 ASSERT( i < nbHalfSpaces() );
945//-----------------------------------------------------------------------------
946template <typename TSpace>
947typename DGtal::BoundedLatticePolytope<TSpace>::Integer
948DGtal::BoundedLatticePolytope<TSpace>::getB( unsigned int i ) const
950 ASSERT( i < nbHalfSpaces() );
954//-----------------------------------------------------------------------------
955template <typename TSpace>
957DGtal::BoundedLatticePolytope<TSpace>::isLarge( unsigned int i ) const
959 ASSERT( i < nbHalfSpaces() );
963//-----------------------------------------------------------------------------
964template <typename TSpace>
966DGtal::BoundedLatticePolytope<TSpace>::setLarge( unsigned int i )
968 ASSERT( i < nbHalfSpaces() );
972//-----------------------------------------------------------------------------
973template <typename TSpace>
975DGtal::BoundedLatticePolytope<TSpace>::setStrict( unsigned int i )
977 ASSERT( i < nbHalfSpaces() );
982//-----------------------------------------------------------------------------
983template <typename TSpace>
984const typename DGtal::BoundedLatticePolytope<TSpace>::InequalityMatrix&
985DGtal::BoundedLatticePolytope<TSpace>::getA() const
990//-----------------------------------------------------------------------------
991template <typename TSpace>
992const typename DGtal::BoundedLatticePolytope<TSpace>::InequalityVector&
993DGtal::BoundedLatticePolytope<TSpace>::getB() const
998//-----------------------------------------------------------------------------
999template <typename TSpace>
1000const std::vector<bool>&
1001DGtal::BoundedLatticePolytope<TSpace>::getI() const
1006//-----------------------------------------------------------------------------
1007template <typename TSpace>
1009DGtal::BoundedLatticePolytope<TSpace>::canBeSummed() const
1011 return myValidEdgeConstraints;
1014///////////////////////////////////////////////////////////////////////////////
1015// Interface - public :
1018 * Writes/Displays the object on an output stream.
1019 * @param out the output stream where the object is written.
1021template <typename TSpace>
1024DGtal::BoundedLatticePolytope<TSpace>::selfDisplay ( std::ostream & out ) const
1026 out << "[BoundedLatticePolytope<" << Space::dimension << "> A.rows=" << A.size()
1027 << " valid_edge_constraints=" << myValidEdgeConstraints
1028 << "]" << std::endl;
1029 for ( Dimension i = 0; i < A.size(); ++i )
1032 for ( Dimension j = 0; j < dimension; ++j )
1033 out << " " << A[ i ][ j ];
1034 out << " ] . x " << ( isLarge( i ) ? "<=" : "<" ) << " " << B[ i ] << std::endl;
1039 * Checks the validity/consistency of the object.
1040 * @return 'true' if the object is valid, 'false' otherwise.
1042template <typename TSpace>
1045DGtal::BoundedLatticePolytope<TSpace>::isValid() const
1047 return ! D.isEmpty();
1049//-----------------------------------------------------------------------------
1050template <typename TSpace>
1053DGtal::BoundedLatticePolytope<TSpace>::className
1056 return "BoundedLatticePolytope";
1061///////////////////////////////////////////////////////////////////////////////
1062// Implementation of inline functions //
1064//-----------------------------------------------------------------------------
1065template <typename TSpace>
1068DGtal::operator<< ( std::ostream & out,
1069 const BoundedLatticePolytope<TSpace> & object )
1071 object.selfDisplay( out );
1074//-----------------------------------------------------------------------------
1075template <typename TSpace>
1076DGtal::BoundedLatticePolytope<TSpace>
1077DGtal::operator* ( typename BoundedLatticePolytope<TSpace>::Integer t,
1078 const BoundedLatticePolytope<TSpace> & P )
1080 BoundedLatticePolytope<TSpace> Q = P;
1084//-----------------------------------------------------------------------------
1085template <typename TSpace>
1086DGtal::BoundedLatticePolytope<TSpace>
1087DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1088 typename BoundedLatticePolytope<TSpace>::UnitSegment s )
1090 BoundedLatticePolytope<TSpace> Q = P;
1094//-----------------------------------------------------------------------------
1095template <typename TSpace>
1096DGtal::BoundedLatticePolytope<TSpace>
1097DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1098 typename BoundedLatticePolytope<TSpace>::UnitCell c )
1100 BoundedLatticePolytope<TSpace> Q = P;
1104//-----------------------------------------------------------------------------
1105template <typename TSpace>
1106DGtal::BoundedLatticePolytope<TSpace>
1107DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1108 typename BoundedLatticePolytope<TSpace>::StrictUnitSegment s )
1110 BoundedLatticePolytope<TSpace> Q = P;
1114//-----------------------------------------------------------------------------
1115template <typename TSpace>
1116DGtal::BoundedLatticePolytope<TSpace>
1117DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1118 typename BoundedLatticePolytope<TSpace>::StrictUnitCell c )
1120 BoundedLatticePolytope<TSpace> Q = P;
1124//-----------------------------------------------------------------------------
1125template <typename TSpace>
1126DGtal::BoundedLatticePolytope<TSpace>
1127DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1128 typename BoundedLatticePolytope<TSpace>::RightStrictUnitSegment s )
1130 BoundedLatticePolytope<TSpace> Q = P;
1134//-----------------------------------------------------------------------------
1135template <typename TSpace>
1136DGtal::BoundedLatticePolytope<TSpace>
1137DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1138 typename BoundedLatticePolytope<TSpace>::RightStrictUnitCell c )
1140 BoundedLatticePolytope<TSpace> Q = P;
1144//-----------------------------------------------------------------------------
1145template <typename TSpace>
1146DGtal::BoundedLatticePolytope<TSpace>
1147DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1148 typename BoundedLatticePolytope<TSpace>::LeftStrictUnitSegment s )
1150 BoundedLatticePolytope<TSpace> Q = P;
1154//-----------------------------------------------------------------------------
1155template <typename TSpace>
1156DGtal::BoundedLatticePolytope<TSpace>
1157DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1158 typename BoundedLatticePolytope<TSpace>::LeftStrictUnitCell c )
1160 BoundedLatticePolytope<TSpace> Q = P;
1166///////////////////////////////////////////////////////////////////////////////