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+=( LeftStrictUnitSegment s )
512 I[ 2*s.k + 1 ] = false;
513 for ( Dimension i = 0; i < A.size(); ++i )
515 if ( A[ i ][ s.k ] > NumberTraits<Integer>::ZERO )
516 B[ i ] += A[ i ][ s.k ];
517 if ( A[ i ][ s.k ] < NumberTraits<Integer>::ZERO )
520 Vector z = Vector::zero;
521 z[ s.k ] = NumberTraits<Integer>::ONE;
522 D = Domain( D.lowerBound() + z, D.upperBound() + z );
526//-----------------------------------------------------------------------------
527template <typename TSpace>
528typename DGtal::BoundedLatticePolytope<TSpace>::Self&
529DGtal::BoundedLatticePolytope<TSpace>::
530operator+=( RightStrictUnitSegment s )
533 for ( Dimension i = 0; i < A.size(); ++i )
535 if ( A[ i ][ s.k ] > NumberTraits<Integer>::ZERO ) {
536 B[ i ] += A[ i ][ s.k ];
540 Vector z = Vector::zero;
541 z[ s.k ] = NumberTraits<Integer>::ONE;
545//-----------------------------------------------------------------------------
546template <typename TSpace>
547typename DGtal::BoundedLatticePolytope<TSpace>::Self&
548DGtal::BoundedLatticePolytope<TSpace>::
549operator+=( UnitCell c )
551 for ( Dimension i = 0; i < c.dims.size(); ++i )
552 *this += UnitSegment( c.dims[ i ] );
556//-----------------------------------------------------------------------------
557template <typename TSpace>
558typename DGtal::BoundedLatticePolytope<TSpace>::Self&
559DGtal::BoundedLatticePolytope<TSpace>::
560operator+=( RightStrictUnitCell c )
562 for ( Dimension i = 0; i < c.dims.size(); ++i )
563 *this += RightStrictUnitSegment( c.dims[ i ] );
567//-----------------------------------------------------------------------------
568template <typename TSpace>
569typename DGtal::BoundedLatticePolytope<TSpace>::Self&
570DGtal::BoundedLatticePolytope<TSpace>::
571operator+=( LeftStrictUnitCell c )
573 for ( Dimension i = 0; i < c.dims.size(); ++i )
574 *this += LeftStrictUnitSegment( c.dims[ i ] );
578//-----------------------------------------------------------------------------
579template <typename TSpace>
580typename DGtal::BoundedLatticePolytope<TSpace>::Integer
581DGtal::BoundedLatticePolytope<TSpace>::
584 BoundedLatticePolytopeCounter<Space> C( *this );
585 return C.countAlongAxis( C.longestAxis() );
588//-----------------------------------------------------------------------------
589template <typename TSpace>
590typename DGtal::BoundedLatticePolytope<TSpace>::Integer
591DGtal::BoundedLatticePolytope<TSpace>::
594 BoundedLatticePolytopeCounter<Space> C( *this );
595 return C.countInteriorAlongAxis( C.longestAxis() );
597//-----------------------------------------------------------------------------
598template <typename TSpace>
599typename DGtal::BoundedLatticePolytope<TSpace>::Integer
600DGtal::BoundedLatticePolytope<TSpace>::
603 const auto clP = closurePolytope();
604 return clP.count() - countInterior();
606//-----------------------------------------------------------------------------
607template <typename TSpace>
608typename DGtal::BoundedLatticePolytope<TSpace>::Integer
609DGtal::BoundedLatticePolytope<TSpace>::
610countWithin( Point lo, Point hi ) const
612 BoundedLatticePolytopeCounter<Space> C( *this );
614 lo = lo.sup( D.lowerBound() );
615 hi = hi.inf( D.upperBound() );
616 auto b_size = hi[ 0 ] - lo[ 0 ];
617 for ( Dimension a = 1; a < dimension; a++ )
619 const auto a_size = hi[ a ] - lo[ a ];
620 if ( b_size < a_size ) { b = a; b_size = a_size; }
624 Domain localD( lo, hi );
625 for ( auto&& p : localD )
627 auto II = C.intersectionIntervalAlongAxis( p, b );
628 nb += II.second - II.first;
632//-----------------------------------------------------------------------------
633template <typename TSpace>
634typename DGtal::BoundedLatticePolytope<TSpace>::Integer
635DGtal::BoundedLatticePolytope<TSpace>::
636countUpTo( Integer max) const
638 BoundedLatticePolytopeCounter<Space> C( *this );
639 Dimension a = C.longestAxis();
641 Point lo = D.lowerBound();
642 Point hi = D.upperBound();
644 Domain localD( lo, hi );
645 for ( auto&& p : localD )
647 auto II = C.intersectionIntervalAlongAxis( p, a );
648 nb += II.second - II.first;
649 if ( nb >= max ) return max;
653//-----------------------------------------------------------------------------
654template <typename TSpace>
656DGtal::BoundedLatticePolytope<TSpace>::
657getPoints( std::vector<Point>& pts ) const
660 BoundedLatticePolytopeCounter<Space> C( *this );
661 C.getPointsAlongAxis( pts, C.longestAxis() );
663//-----------------------------------------------------------------------------
664template <typename TSpace>
666DGtal::BoundedLatticePolytope<TSpace>::
667getKPoints( std::vector<Point>& pts, const Point& alpha_shift ) const
670 BoundedLatticePolytopeCounter<Space> C( *this );
671 Dimension a = C.longestAxis();
673 Point lo = D.lowerBound();
674 Point hi = D.upperBound();
676 Domain localD( lo, hi );
677 for ( auto&& p : localD )
679 auto II = C.intersectionIntervalAlongAxis( p, a );
680 Point q( 2*p - alpha_shift );
681 q[ a ] = 2*II.first - alpha_shift[ a ];
682 for ( Integer x = II.first; x < II.second; x++ )
689//-----------------------------------------------------------------------------
690template <typename TSpace>
691template <typename PointSet>
693DGtal::BoundedLatticePolytope<TSpace>::
694insertPoints( PointSet& pts_set ) const
696 std::vector<Point> pts;
698 pts_set.insert( pts.cbegin(), pts.cend() );
700//-----------------------------------------------------------------------------
701template <typename TSpace>
702template <typename PointSet>
704DGtal::BoundedLatticePolytope<TSpace>::
705insertKPoints( PointSet& pts_set, const Point& alpha_shift ) const
707 BoundedLatticePolytopeCounter<Space> C( *this );
708 Dimension a = C.longestAxis();
710 Point lo = D.lowerBound();
711 Point hi = D.upperBound();
713 Domain localD( lo, hi );
714 for ( auto&& p : localD )
716 auto II = C.intersectionIntervalAlongAxis( p, a );
717 Point q( 2*p - alpha_shift );
718 q[ a ] = 2*II.first - alpha_shift[ a ];
719 for ( Integer x = II.first; x < II.second; x++ )
726//-----------------------------------------------------------------------------
727template <typename TSpace>
729DGtal::BoundedLatticePolytope<TSpace>::
730getInteriorPoints( std::vector<Point>& pts ) const
733 BoundedLatticePolytopeCounter<Space> C( *this );
734 C.getInteriorPointsAlongAxis( pts, C.longestAxis() );
736//-----------------------------------------------------------------------------
737template <typename TSpace>
739DGtal::BoundedLatticePolytope<TSpace>::
740getBoundaryPoints( std::vector<Point>& pts ) const
742 const auto clP = closurePolytope();
743 BoundedLatticePolytopeCounter<Space> C ( *this );
744 BoundedLatticePolytopeCounter<Space> clC( clP );
746 const Dimension a = clC.longestAxis();
747 Point lo = clP.getDomain().lowerBound();
748 Point hi = clP.getDomain().upperBound();
750 Domain localD( lo, hi );
751 for ( auto&& p : localD )
753 auto II = C .interiorIntersectionIntervalAlongAxis( p, a );
754 auto clI = clC.intersectionIntervalAlongAxis( p, a );
755 auto nbI = II.second - II.first;
756 auto nbclI = clI.second - clI.first;
757 if ( nbI == nbclI ) continue;
759 trace.error() << "BoundedLatticePolytope::getBoundaryPoints: bad count"
764 for ( Integer x = clI.first; x != clI.second; x++ )
772 if ( clI.first < II.first )
777 if ( clI.second > II.second )
787//-----------------------------------------------------------------------------
788template <typename TSpace>
789typename DGtal::BoundedLatticePolytope<TSpace>::Integer
790DGtal::BoundedLatticePolytope<TSpace>::
791countByScanning() const
794 for ( const Point & p : D )
795 nb += isDomainPointInside( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
799//-----------------------------------------------------------------------------
800template <typename TSpace>
801typename DGtal::BoundedLatticePolytope<TSpace>::Integer
802DGtal::BoundedLatticePolytope<TSpace>::
803countInteriorByScanning() const
806 for ( const Point & p : D )
807 nb += isInterior( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
810//-----------------------------------------------------------------------------
811template <typename TSpace>
812typename DGtal::BoundedLatticePolytope<TSpace>::Integer
813DGtal::BoundedLatticePolytope<TSpace>::
814countBoundaryByScanning() const
817 for ( const Point & p : D )
818 nb += isBoundary( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
821//-----------------------------------------------------------------------------
822template <typename TSpace>
823typename DGtal::BoundedLatticePolytope<TSpace>::Integer
824DGtal::BoundedLatticePolytope<TSpace>::
825countWithinByScanning( Point lo, Point hi ) const
828 Domain D1( lo.sup( D.lowerBound() ), hi.inf( D.upperBound() ) );
829 for ( const Point & p : D1 )
830 nb += isDomainPointInside( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
833//-----------------------------------------------------------------------------
834template <typename TSpace>
835typename DGtal::BoundedLatticePolytope<TSpace>::Integer
836DGtal::BoundedLatticePolytope<TSpace>::
837countUpToByScanning( Integer max) const
840 for ( const Point & p : D ) {
841 nb += isDomainPointInside( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
842 if ( nb >= max ) return max;
846//-----------------------------------------------------------------------------
847template <typename TSpace>
849DGtal::BoundedLatticePolytope<TSpace>::
850getPointsByScanning( std::vector<Point>& pts ) const
853 for ( const Point & p : D )
854 if ( isDomainPointInside( p ) ) pts.push_back( p );
856//-----------------------------------------------------------------------------
857template <typename TSpace>
858template <typename PointSet>
860DGtal::BoundedLatticePolytope<TSpace>::
861insertPointsByScanning( PointSet& pts_set ) const
863 for ( const Point & p : D )
864 if ( isDomainPointInside( p ) ) pts_set.insert( p );
866//-----------------------------------------------------------------------------
867template <typename TSpace>
869DGtal::BoundedLatticePolytope<TSpace>::
870getInteriorPointsByScanning( std::vector<Point>& pts ) const
873 for ( const Point & p : D )
874 if ( isInterior( p ) ) pts.push_back( p );
876//-----------------------------------------------------------------------------
877template <typename TSpace>
879DGtal::BoundedLatticePolytope<TSpace>::
880getBoundaryPointsByScanning( std::vector<Point>& pts ) const
883 for ( const Point & p : D )
884 if ( isBoundary( p ) ) pts.push_back( p );
887//-----------------------------------------------------------------------------
888template <typename TSpace>
889const typename DGtal::BoundedLatticePolytope<TSpace>::Domain&
890DGtal::BoundedLatticePolytope<TSpace>::getDomain() const
895//-----------------------------------------------------------------------------
896template <typename TSpace>
898DGtal::BoundedLatticePolytope<TSpace>::nbHalfSpaces() const
900 return static_cast<unsigned int>(A.size());
903//-----------------------------------------------------------------------------
904template <typename TSpace>
905const typename DGtal::BoundedLatticePolytope<TSpace>::Vector&
906DGtal::BoundedLatticePolytope<TSpace>::getA( unsigned int i ) const
908 ASSERT( i < nbHalfSpaces() );
912//-----------------------------------------------------------------------------
913template <typename TSpace>
914typename DGtal::BoundedLatticePolytope<TSpace>::Integer
915DGtal::BoundedLatticePolytope<TSpace>::getB( unsigned int i ) const
917 ASSERT( i < nbHalfSpaces() );
921//-----------------------------------------------------------------------------
922template <typename TSpace>
924DGtal::BoundedLatticePolytope<TSpace>::isLarge( unsigned int i ) const
926 ASSERT( i < nbHalfSpaces() );
930//-----------------------------------------------------------------------------
931template <typename TSpace>
932const typename DGtal::BoundedLatticePolytope<TSpace>::InequalityMatrix&
933DGtal::BoundedLatticePolytope<TSpace>::getA() const
938//-----------------------------------------------------------------------------
939template <typename TSpace>
940const typename DGtal::BoundedLatticePolytope<TSpace>::InequalityVector&
941DGtal::BoundedLatticePolytope<TSpace>::getB() const
946//-----------------------------------------------------------------------------
947template <typename TSpace>
948const std::vector<bool>&
949DGtal::BoundedLatticePolytope<TSpace>::getI() const
954//-----------------------------------------------------------------------------
955template <typename TSpace>
957DGtal::BoundedLatticePolytope<TSpace>::canBeSummed() const
959 return myValidEdgeConstraints;
962///////////////////////////////////////////////////////////////////////////////
963// Interface - public :
966 * Writes/Displays the object on an output stream.
967 * @param out the output stream where the object is written.
969template <typename TSpace>
972DGtal::BoundedLatticePolytope<TSpace>::selfDisplay ( std::ostream & out ) const
974 out << "[BoundedLatticePolytope<" << Space::dimension << "> A.rows=" << A.size()
975 << " valid_edge_constraints=" << myValidEdgeConstraints
977 for ( Dimension i = 0; i < A.size(); ++i )
980 for ( Dimension j = 0; j < dimension; ++j )
981 out << " " << A[ i ][ j ];
982 out << " ] . x <= " << B[ i ] << std::endl;
987 * Checks the validity/consistency of the object.
988 * @return 'true' if the object is valid, 'false' otherwise.
990template <typename TSpace>
993DGtal::BoundedLatticePolytope<TSpace>::isValid() const
995 return ! D.isEmpty();
997//-----------------------------------------------------------------------------
998template <typename TSpace>
1001DGtal::BoundedLatticePolytope<TSpace>::className
1004 return "BoundedLatticePolytope";
1009///////////////////////////////////////////////////////////////////////////////
1010// Implementation of inline functions //
1012//-----------------------------------------------------------------------------
1013template <typename TSpace>
1016DGtal::operator<< ( std::ostream & out,
1017 const BoundedLatticePolytope<TSpace> & object )
1019 object.selfDisplay( out );
1022//-----------------------------------------------------------------------------
1023template <typename TSpace>
1024DGtal::BoundedLatticePolytope<TSpace>
1025DGtal::operator* ( typename BoundedLatticePolytope<TSpace>::Integer t,
1026 const BoundedLatticePolytope<TSpace> & P )
1028 BoundedLatticePolytope<TSpace> Q = P;
1032//-----------------------------------------------------------------------------
1033template <typename TSpace>
1034DGtal::BoundedLatticePolytope<TSpace>
1035DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1036 typename BoundedLatticePolytope<TSpace>::UnitSegment s )
1038 BoundedLatticePolytope<TSpace> Q = P;
1042//-----------------------------------------------------------------------------
1043template <typename TSpace>
1044DGtal::BoundedLatticePolytope<TSpace>
1045DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1046 typename BoundedLatticePolytope<TSpace>::UnitCell c )
1048 BoundedLatticePolytope<TSpace> Q = P;
1052//-----------------------------------------------------------------------------
1053template <typename TSpace>
1054DGtal::BoundedLatticePolytope<TSpace>
1055DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1056 typename BoundedLatticePolytope<TSpace>::RightStrictUnitSegment s )
1058 BoundedLatticePolytope<TSpace> Q = P;
1062//-----------------------------------------------------------------------------
1063template <typename TSpace>
1064DGtal::BoundedLatticePolytope<TSpace>
1065DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1066 typename BoundedLatticePolytope<TSpace>::RightStrictUnitCell c )
1068 BoundedLatticePolytope<TSpace> Q = P;
1072//-----------------------------------------------------------------------------
1073template <typename TSpace>
1074DGtal::BoundedLatticePolytope<TSpace>
1075DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1076 typename BoundedLatticePolytope<TSpace>::LeftStrictUnitSegment s )
1078 BoundedLatticePolytope<TSpace> Q = P;
1082//-----------------------------------------------------------------------------
1083template <typename TSpace>
1084DGtal::BoundedLatticePolytope<TSpace>
1085DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1086 typename BoundedLatticePolytope<TSpace>::LeftStrictUnitCell c )
1088 BoundedLatticePolytope<TSpace> Q = P;
1094///////////////////////////////////////////////////////////////////////////////