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 //-----------------------------------------------------------------------------
44 template <typename TSpace>
46 DGtal::BoundedLatticePolytope<TSpace>::
52 myValidEdgeConstraints = false;
53 D = Domain( Point::zero, Point::zero );
56 //-----------------------------------------------------------------------------
57 template <typename TSpace>
58 DGtal::BoundedLatticePolytope<TSpace>::
59 BoundedLatticePolytope( std::initializer_list<Point> l )
61 myValidEdgeConstraints = false;
62 init( l.begin(), l.end() );
65 //-----------------------------------------------------------------------------
66 template <typename TSpace>
67 template <typename PointIterator>
68 DGtal::BoundedLatticePolytope<TSpace>::
69 BoundedLatticePolytope( PointIterator itB, PointIterator itE )
71 myValidEdgeConstraints = false;
75 //-----------------------------------------------------------------------------
76 template <typename TSpace>
77 template <typename HalfSpaceIterator>
78 DGtal::BoundedLatticePolytope<TSpace>::
79 BoundedLatticePolytope( 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 //-----------------------------------------------------------------------------
90 template <typename TSpace>
91 template <typename HalfSpaceIterator>
93 DGtal::BoundedLatticePolytope<TSpace>::
94 init( 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 //-----------------------------------------------------------------------------
153 template <typename TSpace>
155 DGtal::BoundedLatticePolytope<TSpace>::
156 internalInitFromTriangle3D( 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 //-----------------------------------------------------------------------------
181 template <typename TSpace>
183 DGtal::BoundedLatticePolytope<TSpace>::
184 internalInitFromSegment3D( 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 //-----------------------------------------------------------------------------
206 template <typename TSpace>
208 DGtal::BoundedLatticePolytope<TSpace>::
209 internalInitFromSegment2D( 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 //-----------------------------------------------------------------------------
223 template <typename TSpace>
224 template <typename PointIterator>
226 DGtal::BoundedLatticePolytope<TSpace>::
227 init( 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 //-----------------------------------------------------------------------------
320 template <typename TSpace>
321 DGtal::BoundedLatticePolytope<TSpace>
322 DGtal::BoundedLatticePolytope<TSpace>::
323 interiorPolytope() const
325 BoundedLatticePolytope P( *this );
326 for ( auto it = P.I.begin(), itE = P.I.end(); it != itE; ++it )
331 //-----------------------------------------------------------------------------
332 template <typename TSpace>
333 DGtal::BoundedLatticePolytope<TSpace>
334 DGtal::BoundedLatticePolytope<TSpace>::
335 closurePolytope() const
337 BoundedLatticePolytope P( *this );
338 for ( auto it = P.I.begin(), itE = P.I.end(); it != itE; ++it )
343 //-----------------------------------------------------------------------------
344 template <typename TSpace>
346 DGtal::BoundedLatticePolytope<TSpace>::
347 cut( 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 //-----------------------------------------------------------------------------
362 template <typename TSpace>
364 DGtal::BoundedLatticePolytope<TSpace>::
365 cut( 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 //-----------------------------------------------------------------------------
387 template <typename TSpace>
389 DGtal::BoundedLatticePolytope<TSpace>::
390 cut( const HalfSpace& hs, bool large, bool valid_edge_constraint )
394 return cut( a, b, large, valid_edge_constraint );
397 //-----------------------------------------------------------------------------
398 template <typename TSpace>
400 DGtal::BoundedLatticePolytope<TSpace>::
401 swap( BoundedLatticePolytope & other )
406 std::swap( D, other.D );
407 std::swap( myValidEdgeConstraints, other.myValidEdgeConstraints );
410 //-----------------------------------------------------------------------------
411 template <typename TSpace>
413 DGtal::BoundedLatticePolytope<TSpace>::
414 isInside( 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 //-----------------------------------------------------------------------------
429 template <typename TSpace>
431 DGtal::BoundedLatticePolytope<TSpace>::
432 isDomainPointInside( 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 //-----------------------------------------------------------------------------
447 template <typename TSpace>
449 DGtal::BoundedLatticePolytope<TSpace>::
450 isInterior( 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 //-----------------------------------------------------------------------------
462 template <typename TSpace>
464 DGtal::BoundedLatticePolytope<TSpace>::
465 isBoundary( 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 //-----------------------------------------------------------------------------
479 template <typename TSpace>
480 typename DGtal::BoundedLatticePolytope<TSpace>::Self&
481 DGtal::BoundedLatticePolytope<TSpace>::
482 operator*=( Integer t )
484 for ( Integer& b : B ) b *= t;
485 D = Domain( D.lowerBound() * t, D.upperBound() * t );
489 //-----------------------------------------------------------------------------
490 template <typename TSpace>
491 typename DGtal::BoundedLatticePolytope<TSpace>::Self&
492 DGtal::BoundedLatticePolytope<TSpace>::
493 operator+=( 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 //-----------------------------------------------------------------------------
507 template <typename TSpace>
508 typename DGtal::BoundedLatticePolytope<TSpace>::Self&
509 DGtal::BoundedLatticePolytope<TSpace>::
510 operator+=( 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 //-----------------------------------------------------------------------------
527 template <typename TSpace>
528 typename DGtal::BoundedLatticePolytope<TSpace>::Self&
529 DGtal::BoundedLatticePolytope<TSpace>::
530 operator+=( 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 //-----------------------------------------------------------------------------
546 template <typename TSpace>
547 typename DGtal::BoundedLatticePolytope<TSpace>::Self&
548 DGtal::BoundedLatticePolytope<TSpace>::
549 operator+=( UnitCell c )
551 for ( Dimension i = 0; i < c.dims.size(); ++i )
552 *this += UnitSegment( c.dims[ i ] );
556 //-----------------------------------------------------------------------------
557 template <typename TSpace>
558 typename DGtal::BoundedLatticePolytope<TSpace>::Self&
559 DGtal::BoundedLatticePolytope<TSpace>::
560 operator+=( RightStrictUnitCell c )
562 for ( Dimension i = 0; i < c.dims.size(); ++i )
563 *this += RightStrictUnitSegment( c.dims[ i ] );
567 //-----------------------------------------------------------------------------
568 template <typename TSpace>
569 typename DGtal::BoundedLatticePolytope<TSpace>::Self&
570 DGtal::BoundedLatticePolytope<TSpace>::
571 operator+=( LeftStrictUnitCell c )
573 for ( Dimension i = 0; i < c.dims.size(); ++i )
574 *this += LeftStrictUnitSegment( c.dims[ i ] );
578 //-----------------------------------------------------------------------------
579 template <typename TSpace>
580 typename DGtal::BoundedLatticePolytope<TSpace>::Integer
581 DGtal::BoundedLatticePolytope<TSpace>::
584 BoundedLatticePolytopeCounter<Space> C( *this );
585 return C.countAlongAxis( C.longestAxis() );
588 //-----------------------------------------------------------------------------
589 template <typename TSpace>
590 typename DGtal::BoundedLatticePolytope<TSpace>::Integer
591 DGtal::BoundedLatticePolytope<TSpace>::
592 countInterior() const
594 BoundedLatticePolytopeCounter<Space> C( *this );
595 return C.countInteriorAlongAxis( C.longestAxis() );
597 //-----------------------------------------------------------------------------
598 template <typename TSpace>
599 typename DGtal::BoundedLatticePolytope<TSpace>::Integer
600 DGtal::BoundedLatticePolytope<TSpace>::
601 countBoundary() const
603 const auto clP = closurePolytope();
604 return clP.count() - countInterior();
606 //-----------------------------------------------------------------------------
607 template <typename TSpace>
608 typename DGtal::BoundedLatticePolytope<TSpace>::Integer
609 DGtal::BoundedLatticePolytope<TSpace>::
610 countWithin( 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 //-----------------------------------------------------------------------------
633 template <typename TSpace>
634 typename DGtal::BoundedLatticePolytope<TSpace>::Integer
635 DGtal::BoundedLatticePolytope<TSpace>::
636 countUpTo( 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 //-----------------------------------------------------------------------------
654 template <typename TSpace>
656 DGtal::BoundedLatticePolytope<TSpace>::
657 getPoints( std::vector<Point>& pts ) const
660 BoundedLatticePolytopeCounter<Space> C( *this );
661 C.getPointsAlongAxis( pts, C.longestAxis() );
663 //-----------------------------------------------------------------------------
664 template <typename TSpace>
666 DGtal::BoundedLatticePolytope<TSpace>::
667 getKPoints( 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 //-----------------------------------------------------------------------------
690 template <typename TSpace>
691 template <typename PointSet>
693 DGtal::BoundedLatticePolytope<TSpace>::
694 insertPoints( PointSet& pts_set ) const
696 std::vector<Point> pts;
698 pts_set.insert( pts.cbegin(), pts.cend() );
700 //-----------------------------------------------------------------------------
701 template <typename TSpace>
702 template <typename PointSet>
704 DGtal::BoundedLatticePolytope<TSpace>::
705 insertKPoints( 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 //-----------------------------------------------------------------------------
727 template <typename TSpace>
729 DGtal::BoundedLatticePolytope<TSpace>::
730 getInteriorPoints( std::vector<Point>& pts ) const
733 BoundedLatticePolytopeCounter<Space> C( *this );
734 C.getInteriorPointsAlongAxis( pts, C.longestAxis() );
736 //-----------------------------------------------------------------------------
737 template <typename TSpace>
739 DGtal::BoundedLatticePolytope<TSpace>::
740 getBoundaryPoints( 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 //-----------------------------------------------------------------------------
788 template <typename TSpace>
789 typename DGtal::BoundedLatticePolytope<TSpace>::Integer
790 DGtal::BoundedLatticePolytope<TSpace>::
791 countByScanning() const
794 for ( const Point & p : D )
795 nb += isDomainPointInside( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
799 //-----------------------------------------------------------------------------
800 template <typename TSpace>
801 typename DGtal::BoundedLatticePolytope<TSpace>::Integer
802 DGtal::BoundedLatticePolytope<TSpace>::
803 countInteriorByScanning() const
806 for ( const Point & p : D )
807 nb += isInterior( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
810 //-----------------------------------------------------------------------------
811 template <typename TSpace>
812 typename DGtal::BoundedLatticePolytope<TSpace>::Integer
813 DGtal::BoundedLatticePolytope<TSpace>::
814 countBoundaryByScanning() const
817 for ( const Point & p : D )
818 nb += isBoundary( p ) ? NumberTraits<Integer>::ONE : NumberTraits<Integer>::ZERO;
821 //-----------------------------------------------------------------------------
822 template <typename TSpace>
823 typename DGtal::BoundedLatticePolytope<TSpace>::Integer
824 DGtal::BoundedLatticePolytope<TSpace>::
825 countWithinByScanning( 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 //-----------------------------------------------------------------------------
834 template <typename TSpace>
835 typename DGtal::BoundedLatticePolytope<TSpace>::Integer
836 DGtal::BoundedLatticePolytope<TSpace>::
837 countUpToByScanning( 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 //-----------------------------------------------------------------------------
847 template <typename TSpace>
849 DGtal::BoundedLatticePolytope<TSpace>::
850 getPointsByScanning( std::vector<Point>& pts ) const
853 for ( const Point & p : D )
854 if ( isDomainPointInside( p ) ) pts.push_back( p );
856 //-----------------------------------------------------------------------------
857 template <typename TSpace>
858 template <typename PointSet>
860 DGtal::BoundedLatticePolytope<TSpace>::
861 insertPointsByScanning( PointSet& pts_set ) const
863 for ( const Point & p : D )
864 if ( isDomainPointInside( p ) ) pts_set.insert( p );
866 //-----------------------------------------------------------------------------
867 template <typename TSpace>
869 DGtal::BoundedLatticePolytope<TSpace>::
870 getInteriorPointsByScanning( std::vector<Point>& pts ) const
873 for ( const Point & p : D )
874 if ( isInterior( p ) ) pts.push_back( p );
876 //-----------------------------------------------------------------------------
877 template <typename TSpace>
879 DGtal::BoundedLatticePolytope<TSpace>::
880 getBoundaryPointsByScanning( std::vector<Point>& pts ) const
883 for ( const Point & p : D )
884 if ( isBoundary( p ) ) pts.push_back( p );
887 //-----------------------------------------------------------------------------
888 template <typename TSpace>
889 const typename DGtal::BoundedLatticePolytope<TSpace>::Domain&
890 DGtal::BoundedLatticePolytope<TSpace>::getDomain() const
895 //-----------------------------------------------------------------------------
896 template <typename TSpace>
898 DGtal::BoundedLatticePolytope<TSpace>::nbHalfSpaces() const
900 return static_cast<unsigned int>(A.size());
903 //-----------------------------------------------------------------------------
904 template <typename TSpace>
905 const typename DGtal::BoundedLatticePolytope<TSpace>::Vector&
906 DGtal::BoundedLatticePolytope<TSpace>::getA( unsigned int i ) const
908 ASSERT( i < nbHalfSpaces() );
912 //-----------------------------------------------------------------------------
913 template <typename TSpace>
914 typename DGtal::BoundedLatticePolytope<TSpace>::Integer
915 DGtal::BoundedLatticePolytope<TSpace>::getB( unsigned int i ) const
917 ASSERT( i < nbHalfSpaces() );
921 //-----------------------------------------------------------------------------
922 template <typename TSpace>
924 DGtal::BoundedLatticePolytope<TSpace>::isLarge( unsigned int i ) const
926 ASSERT( i < nbHalfSpaces() );
930 //-----------------------------------------------------------------------------
931 template <typename TSpace>
932 const typename DGtal::BoundedLatticePolytope<TSpace>::InequalityMatrix&
933 DGtal::BoundedLatticePolytope<TSpace>::getA() const
938 //-----------------------------------------------------------------------------
939 template <typename TSpace>
940 const typename DGtal::BoundedLatticePolytope<TSpace>::InequalityVector&
941 DGtal::BoundedLatticePolytope<TSpace>::getB() const
946 //-----------------------------------------------------------------------------
947 template <typename TSpace>
948 const std::vector<bool>&
949 DGtal::BoundedLatticePolytope<TSpace>::getI() const
954 //-----------------------------------------------------------------------------
955 template <typename TSpace>
957 DGtal::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.
969 template <typename TSpace>
972 DGtal::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.
990 template <typename TSpace>
993 DGtal::BoundedLatticePolytope<TSpace>::isValid() const
995 return ! D.isEmpty();
997 //-----------------------------------------------------------------------------
998 template <typename TSpace>
1001 DGtal::BoundedLatticePolytope<TSpace>::className
1004 return "BoundedLatticePolytope";
1009 ///////////////////////////////////////////////////////////////////////////////
1010 // Implementation of inline functions //
1012 //-----------------------------------------------------------------------------
1013 template <typename TSpace>
1016 DGtal::operator<< ( std::ostream & out,
1017 const BoundedLatticePolytope<TSpace> & object )
1019 object.selfDisplay( out );
1022 //-----------------------------------------------------------------------------
1023 template <typename TSpace>
1024 DGtal::BoundedLatticePolytope<TSpace>
1025 DGtal::operator* ( typename BoundedLatticePolytope<TSpace>::Integer t,
1026 const BoundedLatticePolytope<TSpace> & P )
1028 BoundedLatticePolytope<TSpace> Q = P;
1032 //-----------------------------------------------------------------------------
1033 template <typename TSpace>
1034 DGtal::BoundedLatticePolytope<TSpace>
1035 DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1036 typename BoundedLatticePolytope<TSpace>::UnitSegment s )
1038 BoundedLatticePolytope<TSpace> Q = P;
1042 //-----------------------------------------------------------------------------
1043 template <typename TSpace>
1044 DGtal::BoundedLatticePolytope<TSpace>
1045 DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1046 typename BoundedLatticePolytope<TSpace>::UnitCell c )
1048 BoundedLatticePolytope<TSpace> Q = P;
1052 //-----------------------------------------------------------------------------
1053 template <typename TSpace>
1054 DGtal::BoundedLatticePolytope<TSpace>
1055 DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1056 typename BoundedLatticePolytope<TSpace>::RightStrictUnitSegment s )
1058 BoundedLatticePolytope<TSpace> Q = P;
1062 //-----------------------------------------------------------------------------
1063 template <typename TSpace>
1064 DGtal::BoundedLatticePolytope<TSpace>
1065 DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1066 typename BoundedLatticePolytope<TSpace>::RightStrictUnitCell c )
1068 BoundedLatticePolytope<TSpace> Q = P;
1072 //-----------------------------------------------------------------------------
1073 template <typename TSpace>
1074 DGtal::BoundedLatticePolytope<TSpace>
1075 DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1076 typename BoundedLatticePolytope<TSpace>::LeftStrictUnitSegment s )
1078 BoundedLatticePolytope<TSpace> Q = P;
1082 //-----------------------------------------------------------------------------
1083 template <typename TSpace>
1084 DGtal::BoundedLatticePolytope<TSpace>
1085 DGtal::operator+ ( const BoundedLatticePolytope<TSpace> & P,
1086 typename BoundedLatticePolytope<TSpace>::LeftStrictUnitCell c )
1088 BoundedLatticePolytope<TSpace> Q = P;
1094 ///////////////////////////////////////////////////////////////////////////////