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 LatticePolytope2D.ih
19 * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20 * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
21 * @author Emilie Charrier
25 * Implementation of inline methods defined in LatticePolytope2D.h
27 * This file is part of the DGtal library.
31 //////////////////////////////////////////////////////////////////////////////
34 #include "DGtal/kernel/NumberTraits.h"
35 #include "DGtal/kernel/sets/CDigitalSet.h"
36 //////////////////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////////////////
39 // IMPLEMENTATION of inline methods.
40 ///////////////////////////////////////////////////////////////////////////////
42 ///////////////////////////////////////////////////////////////////////////////
43 // ----------------------- Standard services ------------------------------
45 //-----------------------------------------------------------------------------
46 template <typename TSpace, typename TSequence>
48 DGtal::LatticePolytope2D<TSpace,TSequence>::~LatticePolytope2D()
51 //-----------------------------------------------------------------------------
52 template <typename TSpace, typename TSequence>
54 DGtal::LatticePolytope2D<TSpace,TSequence>::LatticePolytope2D()
57 //-----------------------------------------------------------------------------
58 template <typename TSpace, typename TSequence>
60 DGtal::LatticePolytope2D<TSpace,TSequence>::LatticePolytope2D
61 ( const Self & other )
62 : myVertices( other.myVertices )
65 //-----------------------------------------------------------------------------
66 template <typename TSpace, typename TSequence>
68 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Self &
69 DGtal::LatticePolytope2D<TSpace,TSequence>::operator=
70 ( const Self & other )
73 myVertices = other.myVertices;
76 //-----------------------------------------------------------------------------
77 template <typename TSpace, typename TSequence>
79 typename DGtal::LatticePolytope2D<TSpace,TSequence>::ConstIterator
80 DGtal::LatticePolytope2D<TSpace,TSequence>::
83 return myVertices.begin();
85 //-----------------------------------------------------------------------------
86 template <typename TSpace, typename TSequence>
88 typename DGtal::LatticePolytope2D<TSpace,TSequence>::ConstIterator
89 DGtal::LatticePolytope2D<TSpace,TSequence>::
92 return myVertices.end();
94 //-----------------------------------------------------------------------------
95 template <typename TSpace, typename TSequence>
97 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Iterator
98 DGtal::LatticePolytope2D<TSpace,TSequence>::
101 return myVertices.begin();
103 //-----------------------------------------------------------------------------
104 template <typename TSpace, typename TSequence>
106 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Iterator
107 DGtal::LatticePolytope2D<TSpace,TSequence>::
110 return myVertices.end();
112 //-----------------------------------------------------------------------------
113 template <typename TSpace, typename TSequence>
116 DGtal::LatticePolytope2D<TSpace,TSequence>::
119 return myVertices.empty();
121 //-----------------------------------------------------------------------------
122 template <typename TSpace, typename TSequence>
124 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Size
125 DGtal::LatticePolytope2D<TSpace,TSequence>::
128 return myVertices.size();
130 //-----------------------------------------------------------------------------
131 template <typename TSpace, typename TSequence>
133 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Size
134 DGtal::LatticePolytope2D<TSpace,TSequence>::
137 return myVertices.max_size();
139 //-----------------------------------------------------------------------------
140 template <typename TSpace, typename TSequence>
143 DGtal::LatticePolytope2D<TSpace,TSequence>::
148 //-----------------------------------------------------------------------------
149 template <typename TSpace, typename TSequence>
151 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Iterator
152 DGtal::LatticePolytope2D<TSpace,TSequence>::
155 return myVertices.erase( it );
157 //-----------------------------------------------------------------------------
158 template <typename TSpace, typename TSequence>
161 DGtal::LatticePolytope2D<TSpace,TSequence>::
162 swap( LatticePolytope2D & other )
164 myVertices.swap( other.myVertices );
167 //-----------------------------------------------------------------------------
168 template <typename TSpace, typename TSequence>
170 typename DGtal::LatticePolytope2D<TSpace,TSequence>::MyIntegerComputer &
171 DGtal::LatticePolytope2D<TSpace,TSequence>::
177 //-----------------------------------------------------------------------------
178 template <typename TSpace, typename TSequence>
179 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Domain
180 DGtal::LatticePolytope2D<TSpace,TSequence>::
181 boundingBoxDomain() const
183 ConstIterator it = begin();
184 ConstIterator it_end = end();
186 Point supremum = *it;
187 for ( ++it; it != it_end; ++it )
189 infimum = infimum.inf( *it );
190 supremum = supremum.sup( *it );
192 return Domain( infimum, supremum );
194 //-----------------------------------------------------------------------------
195 template <typename TSpace, typename TSequence>
197 DGtal::LatticePolytope2D<TSpace,TSequence>::
200 Iterator it = begin();
201 Iterator it_end = end();
203 while ( it != it_end )
208 while ( ( it != it_end ) && ( _A == *it ) )
211 // Checks case where first vertex is also last vertex.
212 if ( ( size() > 1 ) && ( * begin() == *it_prev ) )
215 //-----------------------------------------------------------------------------
216 template <typename TSpace, typename TSequence>
218 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Iterator
219 DGtal::LatticePolytope2D<TSpace,TSequence>::
220 insertBefore( const Iterator & pos, const Point & K )
222 return myVertices.insert( pos, K );
224 //-----------------------------------------------------------------------------
225 template <typename TSpace, typename TSequence>
228 DGtal::LatticePolytope2D<TSpace,TSequence>::
229 pushBack( const Point & K )
231 myVertices.push_back( K );
233 //-----------------------------------------------------------------------------
234 template <typename TSpace, typename TSequence>
237 DGtal::LatticePolytope2D<TSpace,TSequence>::
238 pushFront( const Point & K )
240 myVertices.push_front( K );
242 //-----------------------------------------------------------------------------
243 template <typename TSpace, typename TSequence>
246 DGtal::LatticePolytope2D<TSpace,TSequence>::
247 push_back( const Point & K )
249 myVertices.push_back( K );
251 //-----------------------------------------------------------------------------
252 template <typename TSpace, typename TSequence>
255 DGtal::LatticePolytope2D<TSpace,TSequence>::
256 push_front( const Point & K )
258 myVertices.push_front( K );
260 //-----------------------------------------------------------------------------
261 template <typename TSpace, typename TSequence>
263 const typename DGtal::LatticePolytope2D<TSpace,TSequence>::Integer &
264 DGtal::LatticePolytope2D<TSpace,TSequence>::
267 _a = NumberTraits<Integer>::ZERO;
268 ConstIterator it = begin();
269 ConstIterator it_end = end();
270 ConstIterator it_next = it; ++it_next;
271 while ( it_next != it_end )
273 _a += _ic.crossProduct( *it, *it_next );
274 it = it_next; ++it_next;
276 _a += _ic.crossProduct( *it, *(begin()) );
279 //-----------------------------------------------------------------------------
280 template <typename TSpace, typename TSequence>
282 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Point3I
283 DGtal::LatticePolytope2D<TSpace,TSequence>::
287 return centroid( _a );
289 //-----------------------------------------------------------------------------
290 template <typename TSpace, typename TSequence>
292 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Point3I
293 DGtal::LatticePolytope2D<TSpace,TSequence>::
294 centroid( const Integer & twice_area ) const
296 _a = _b = NumberTraits<Integer>::ZERO;
297 _A = Point( NumberTraits<Integer>::ZERO, NumberTraits<Integer>::ZERO );
298 ConstIterator it_begin = begin();
299 ConstIterator it = it_begin;
300 ConstIterator it_end = end();
301 if( twice_area > NumberTraits<Integer>::ZERO )
303 _den = 3 * twice_area;
304 ConstIterator it_next = it; ++it_next;
305 while ( it_next != it_end )
307 _ic.getCrossProduct( _c, *it, *it_next );
311 it = it_next; ++it_next;
313 _ic.getCrossProduct( _c, *it, *it_begin );
314 _B = *it + *it_begin;
320 _den = NumberTraits<Integer>::ZERO;
321 for ( ; it != it_end; ++it )
327 return Point3I( _A[ 0 ], _A[ 1 ], _den );
329 //-----------------------------------------------------------------------------
330 template <typename TSpace, typename TSequence>
332 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Integer
333 DGtal::LatticePolytope2D<TSpace,TSequence>::
334 numberBoundaryPoints() const
336 _a = NumberTraits<Integer>::ZERO;
337 ConstIterator it = begin();
338 ConstIterator it_end = end();
339 ConstIterator it_next = it; ++it_next;
340 while ( it_next != it_end )
343 ic().getGcd( _g, _N[ 0 ], _N[ 1 ] );
345 it = it_next; ++it_next;
347 _N = *it - *(begin());
348 ic().getGcd( _g, _N[ 0 ], _N[ 1 ] );
352 //-----------------------------------------------------------------------------
353 template <typename TSpace, typename TSequence>
355 typename DGtal::LatticePolytope2D<TSpace,TSequence>::Integer
356 DGtal::LatticePolytope2D<TSpace,TSequence>::
357 numberInteriorPoints() const
359 _c1 = numberBoundaryPoints();
362 ASSERT( ic().isZero( _c % 2 ) );
365 //-----------------------------------------------------------------------------
366 template <typename TSpace, typename TSequence>
368 typename DGtal::LatticePolytope2D<TSpace,TSequence>::SizeCouple
369 DGtal::LatticePolytope2D<TSpace,TSequence>::
370 findCut( Iterator & it_next_is_outside, Iterator & it_next_is_inside,
371 const HalfSpace & hs )
373 Size nbWithin = (Size) 0; // JOL: problem on macos. unsigned long has no NumberTraits. NumberTraits<Size>::ZERO;
374 Size nb = (Size) 0; // JOL: problem on macos. unsigned long has no NumberTraits. NumberTraits<Size>::ZERO;
375 Iterator it = begin();
376 Iterator it_prev = it;
377 Iterator it_end = end();
378 it_next_is_outside = it_next_is_inside = it_end;
380 return std::make_pair( (Size) 0, (Size) 0 ); // JOL: problem on macos. unsigned long has no NumberTraits. NumberTraits<Size>::ZERO;
381 bool visibility_begin_vtx; // visibility of begin vertex.
382 bool visibility_prev_vtx; // visibility of previous vertex when visiting the list.
383 bool visibility_vtx; // visibility of current vertex when visiting the list.
385 if ( ( visibility_begin_vtx = hs( *it++ ) ) ) ++nbWithin; // Assignment
386 visibility_prev_vtx = visibility_begin_vtx;
387 visibility_vtx = visibility_begin_vtx;
388 for ( ; it != it_end; ++it, ++nb )
390 if ( ( visibility_vtx = hs( *it ) ) ) ++nbWithin; // Assignment
391 if ( visibility_vtx != visibility_prev_vtx )
393 if ( visibility_prev_vtx ) it_next_is_outside = it_prev;
394 else it_next_is_inside = it_prev;
396 visibility_prev_vtx = visibility_vtx;
399 if ( visibility_vtx != visibility_begin_vtx )
401 if ( visibility_vtx ) it_next_is_outside = it_prev;
402 else it_next_is_inside = it_prev;
404 ASSERT( ( nbWithin == 0 ) || ( nbWithin == size() )
405 || ( ( it_next_is_outside != it_end ) && ( it_next_is_inside != it_end )
406 && ( it_next_is_inside != it_next_is_outside ) ) );
407 return std::make_pair( nbWithin, nb );
410 //-----------------------------------------------------------------------------
411 template <typename TSpace, typename TSequence>
414 DGtal::LatticePolytope2D<TSpace,TSequence>::
415 cut( const HalfSpace & hs )
417 Iterator it_next_is_outside;
418 Iterator it_next_is_inside;
419 SizeCouple nbs = findCut( it_next_is_outside, it_next_is_inside, hs );
421 // Take care of easy cases.
422 if ( nbs.first == nbs.second ) { return false; }
423 if ( nbs.first == (Size) 0 ) { clear(); return true; } // JOL see findCut
425 // Otherwise, determines A1B1 and A2B2.
426 twiceArea(); // result in _a;
427 HalfSpace hs1 = halfSpace( it_next_is_outside );
428 HalfSpace hs3 = halfSpace( it_next_is_inside );
430 _A1 = *it_next_is_outside;
431 ++it_next_is_outside;
432 if ( it_next_is_outside == end() ) it_next_is_outside = begin();
433 _B1 = *it_next_is_outside;
434 _B2 = *it_next_is_inside;
436 if ( it_next_is_inside == end() ) it_next_is_inside = begin();
437 _A2 = *it_next_is_inside;
439 // Erases outside vertices.
440 while ( it_next_is_outside != it_next_is_inside )
442 it_next_is_outside = erase( it_next_is_outside );
443 if ( it_next_is_outside == end() ) it_next_is_outside = begin();
445 // Both iterators point on the right place.
446 if ( _a > NumberTraits<Integer>::ZERO )
447 { //convex not reduced to a straight line segment
448 std::insert_iterator<ClockwiseVertexSequence> itOut
449 = std::inserter<ClockwiseVertexSequence>( myVertices, it_next_is_outside );
450 computeConvexHullBorder( itOut, _A1, _A2, hs1, hs, hs3 );
452 else //convex reduced to a straight line segment
454 //compute the new extremity of the straight line segment
457 _a = ( hs.c - hs.N.dot( _A1 ) ) / ( hs.N.dot( _v ) );
459 insertBefore( it_next_is_outside, _A1 );
464 //-----------------------------------------------------------------------------
465 template <typename TSpace, typename TSequence>
467 typename DGtal::LatticePolytope2D<TSpace,TSequence>::HalfSpace
468 DGtal::LatticePolytope2D<TSpace,TSequence>::
469 halfSpace( ConstIterator it ) const
471 Point A( *it ); ++it;
472 if ( it == end() ) it = begin();
473 Point B( *it ); ++it;
474 if ( it == end() ) it = begin();
475 _N[ 0 ] = A[ 1 ] - B[ 1 ];
476 _N[ 1 ] = B[ 0 ] - A[ 0 ];
477 _ic.getDotProduct( _c, _N, A );
478 _ic.getDotProduct( _c1, _N, *it );
484 //simplification of the constraint
485 _ic.getGcd( _g, _N[ 0 ], _N[ 1 ] );
487 return HalfSpace( _N, _ic.floorDiv( _c, _g) );
489 //-----------------------------------------------------------------------------
490 template <typename TSpace, typename TSequence>
492 typename DGtal::LatticePolytope2D<TSpace,TSequence>::HalfSpace
493 DGtal::LatticePolytope2D<TSpace,TSequence>::
494 halfSpace( const Point & A, const Point & B, const Point & inP ) const
496 _N[ 0 ] = A[ 1 ] - B[ 1 ];
497 _N[ 1 ] = B[ 0 ] - A[ 0 ];
498 _ic.getDotProduct( _c, _N, A );
499 _ic.getDotProduct( _c1, _N, inP );
505 //simplification of the constraint
506 _ic.getGcd( _g, _N[ 0 ], _N[ 1 ] );
508 return HalfSpace( _N, _ic.floorDiv( _c, _g) );
512 Computes the set \a aSet all the digital points that belongs to this polygon.
514 @param aSet (returns) the set that contains as output all the
515 digital points of this polygon.
517 @return the number of inserted points.
518 @todo this method is for now not efficient.
520 //-----------------------------------------------------------------------------
521 template <typename TSpace, typename TSequence>
522 template <typename DigitalSet>
524 DGtal::LatticePolytope2D<TSpace,TSequence>::
525 getIncludedDigitalPoints( DigitalSet & aSet ) const
527 BOOST_CONCEPT_ASSERT(( concepts::CDigitalSet< DigitalSet > ));
528 typedef typename DigitalSet::Domain DigitalSetDomain;
529 BOOST_STATIC_ASSERT(( concepts::ConceptUtils::SameType< DigitalSetDomain, Domain >::value ));
530 typedef typename DigitalSetDomain::ConstIterator DomainConstIterator;
531 typedef typename DigitalSet::Iterator DigitalSetIterator;
533 // case 1 : empty polygon.
534 if ( empty() ) return;
535 // case 2 : one vertex.
539 aSet.insert( *begin() );
542 // case 3 : 2 vertices
545 ConstIterator it_vtx = begin();
546 ConstIterator it_vtx2 = it_vtx; ++it_vtx2;
547 HalfSpace hs = halfSpace( it_vtx );
548 Vector orthN( -hs.N[ 1 ], hs.N[ 0 ] );
549 HalfSpace hs_orth( orthN, _ic.dotProduct( orthN, *it_vtx ) );
550 if ( ! hs_orth( *it_vtx2 ) ) hs_orth.negate();
551 HalfSpace hs2 = halfSpace( it_vtx2 );
552 Vector orthN2( -hs2.N[ 1 ], hs2.N[ 0 ] );
553 HalfSpace hs2_orth( orthN2, _ic.dotProduct( orthN2, *it_vtx2 ) );
554 if ( ! hs2_orth( *it_vtx ) ) hs2_orth.negate();
556 for ( DomainConstIterator it = aSet.domain().begin(),
557 it_end = aSet.domain().end(); it != it_end; ++it )
558 if ( hs( *it ) ) aSet.insert( *it );
559 for ( DigitalSetIterator it_set = aSet.begin(), it_set_end = aSet.end();
560 it_set != it_set_end; )
562 DigitalSetIterator it_cur = it_set; ++it_set;
563 if ( ! ( hs_orth( *it_cur )
565 && hs2_orth( *it_cur ) ) )
566 aSet.erase( it_cur );
570 // case 4 : >= 3 vertices
571 ConstIterator it_vtx = begin();
572 ConstIterator it_vtx_end = end();
573 HalfSpace hs = halfSpace( it_vtx );
574 for ( DomainConstIterator it = aSet.domain().begin(),
575 it_end = aSet.domain().end(); it != it_end; ++it )
576 if ( hs( *it ) ) aSet.insert( *it );
578 for ( ; it_vtx != it_vtx_end; ++it_vtx )
580 hs = halfSpace( it_vtx );
581 for ( DigitalSetIterator it_set = aSet.begin(), it_set_end = aSet.end();
582 it_set != it_set_end; )
584 DigitalSetIterator it_cur = it_set; ++it_set;
585 if ( ! hs( *it_cur ) ) aSet.erase( it_cur );
589 //-----------------------------------------------------------------------------
590 template <typename TSpace, typename TSequence>
592 DGtal::LatticePolytope2D<TSpace,TSequence>::
595 Point & inPt, // must belong to hs1.
597 const HalfSpace & hs1,
598 const HalfSpace & hs2 ) const
600 ASSERT( hs1.isOnBoundary( inPt ) );
601 bool exactIntersection;
603 // initialize vector directionVector (not definitive)
606 //compute the intersection of ray (inPt, _DV) with constraint C2
607 _ic.getCoefficientIntersection( _fl, _ce,
608 inPt, _DV, hs2.N, hs2.c );
610 // uses the intersection to compute the first vertex of the upper
611 // convex hull (inside convex hull), i.e. the grid point closest to
612 // C2 and satisfying C2
613 _ic.getDotProduct( _a, inPt, hs2.N );
614 // if ( ( _a > hs2.c ) && ( _fl == NumberTraits<Integer>::ZERO ) )
616 // inPt += _DV * _ce;
619 // else if ( ( ( _a <= hs2.c ) && ( _fl >= NumberTraits<Integer>::ZERO ) )
620 // || ( ( _a > hs2.c2 ) && ( _fl <= NumberTraits<Integer>::ZERO ) ) )
621 if ( ( ( _a <= hs2.c ) && ( _fl >= NumberTraits<Integer>::ZERO ) )
622 || ( ( _a > hs2.c ) && ( _fl < NumberTraits<Integer>::ZERO ) ) )
632 // compute the first vertex of the lower convex hull
633 if ( _fl == _ce ) //integer intersection
636 exactIntersection = true;
641 //initialization of v: valid Bezout vector of u
642 _ic.getValidBezout( v, inPt, _DV, hs1.N, hs1.c, hs2.N, hs2.c, true );
643 exactIntersection = false;
646 #ifdef DEBUG_LatticePolytope2D
647 std::cerr << "[CIP::getFirstPointsOfHull] in=" << inPt
648 << " out=" << outPt << " v=" << v << std::endl;
649 #endif //DEBUG_LatticePolytope2D
650 ASSERT( hs1.isOnBoundary( inPt ) );
651 ASSERT( hs1.isOnBoundary( outPt ) );
652 ASSERT( hs2( inPt ) );
653 ASSERT( ( exactIntersection && hs2( outPt ) ) || ( ! exactIntersection && ! hs2( outPt ) ) );
654 return exactIntersection;
658 Computes the border of the upper and of the lower convex hull
659 from the starting points inPts[0] (up) and outPts[0]
660 down, along the constraint N2.p <= c2 while the vertices
661 satisfy the constraint N3.p <= c3. The vertices of the two
662 borders are stored at the end of inPts and outPts.
664 @param inPts (in, out) as input, contains the first point, as
665 output the sequence of points satisfying \a hs2 and \a hs3.
667 @param outPts (in, out) as input, contains the first point, as
668 output the sequence of points not satisfying \a hs2 and satisfying
671 @param BV the Bezout vector of the vector between inPts[ 0 ] and outPts[ 0 ].
673 @param hs2 the half-space that is approached by the two sequences of points.
674 @param hs3 the limiting half-space which defines the bounds of the approximation.
676 //-----------------------------------------------------------------------------
677 template <typename TSpace, typename TSequence>
679 DGtal::LatticePolytope2D<TSpace,TSequence>::
680 getAllPointsOfHull( std::vector<Point> & inPts,
681 std::vector<Point> & outPts,
683 const HalfSpace & hs2,
684 const HalfSpace & hs3 ) const
686 ASSERT( hs2.N != hs3.N );
688 // _A and _B represents the last computed vertex above and below the constraint resp.
689 // _u, _v pair of Bezout vectors.
691 // initialize A and B
695 // while A and B do not lie on the supporting line of hs2
696 // and satisfies hs3 and while v is not parallel to hs2
697 while ( ( ! hs2.isOnBoundary( _A ) ) // stops if A reaches hs2.
698 && ( hs3( _A ) ) // stops if A does not satisfy hs3.
699 && ( ! hs2.isOnBoundary( _B ) ) // stops if B reaches hs2.
700 && ( hs3( _B ) ) // stops if B does not satisfy hs3.
701 && ( _ic.dotProduct( _v, hs2.N ) != NumberTraits<Integer>::ZERO ) )
703 #ifdef DEBUG_LatticePolytope2D
704 std::cerr << "[CIP::getAllPointsOfHull] A=" << _A
705 << " B=" << _B << " v= " << _v << std::endl;
706 #endif // DEBUG_LatticePolytope2D
707 if ( _ic.dotProduct( _v, hs2.N ) < NumberTraits<Integer>::ZERO )
708 { //------ second configuration, we find a new B --------------------
709 _ic.getCoefficientIntersection( _fl, _ce,
710 _B, _v, hs2.N, hs2.c );
711 _u = _B; _u += _v *_fl;
713 { // Point is still within bounds.
715 outPts.push_back( _B );
716 #ifdef DEBUG_LatticePolytope2D
717 std::cerr << "[CIP::getAllPointsOfHull] add B=" << _B << std::endl;
718 #endif // ifdef DEBUG_LatticePolytope2D
721 { // Point is too far away. Check intersection with hs3 instead.
722 _ic.getCoefficientIntersection( _fl, _ce,
723 _B, _v, hs3.N, hs3.c );
725 outPts.push_back( _B );
726 #ifdef DEBUG_LatticePolytope2D
727 std::cerr << "[CIP::getAllPointsOfHull] add B=" << _B << std::endl;
728 #endif //ifdef DEBUG_LatticePolytope2D
730 break; // necessarily the last point.
734 { //----- first configuration, we find a new A -----------------------
735 _ic.getCoefficientIntersection( _fl, _ce,
736 _A, _v, hs2.N, hs2.c );
737 _u = _A; _u += _v *_fl;
739 { // Point is still within bounds.
741 inPts.push_back( _A );
742 #ifdef DEBUG_LatticePolytope2D
743 std::cerr << "[CIP::getAllPointsOfHull] add A=" << _A << std::endl;
744 #endif //ifdef DEBUG_LatticePolytope2D
747 { // Point is too far away. Check intersection with hs3 instead.
748 _ic.getCoefficientIntersection( _fl, _ce,
749 _A, _v, hs3.N, hs3.c );
751 inPts.push_back( _A );
752 #ifdef DEBUG_LatticePolytope2D
753 std::cerr << "[CIP::getAllPointsOfHull] add A=" << _A << std::endl;
754 #endif //ifdef DEBUG_LatticePolytope2D
756 break; // necessarily the last point.
762 // From _ic.getValidBezout( _A, _u, _v, N2, c2, N2, c2, 0);
764 _ic.getValidBezout( _v, _A, _u, hs2.N, hs2.c, hs2.N, hs2.c, false );
766 // when the loop finishes, we have to complete the computation
767 // of each convex hull
768 // if ( ! hs3( _A ) ) // A does not satisfy C3, we remove it.
770 // else if ( ! hs3( _B ) ) // B does not satisfy C3, we remove it
771 // outPts.pop_back();
773 if ( hs2.isOnBoundary( _A ) ) // A lies on C2 so A is also a vertex of outPts
774 outPts.push_back( _A );
775 else if ( hs2.isOnBoundary( _B ) ) // B lies on C2 so B is also a vertex of inPts
776 inPts.push_back( _B );
780 * compute the convex hull of grid points satisfying the
781 * constraints N1.P<=c1, N2.P<=c2 and N3.P>=c3.
783 * N2.P<=c2 corresponds to the cut two parts of computation: from
784 * constraint 1 to constraint 3 and from constraint 3 to
787 * The computed vertices are inserted at position [pos] in some list.
789 * @param pointRefC1 and pointRefC3 corresponds to grid point lying on
790 * the supporting lines of C1 and of C3 resp.
792 * @param pos corresponds to an iterator in the list of vertices
793 * of the convex, to add the next new vertices
795 * NB: the method also computes grid point satisfying N1.P<=c1 and
796 * N3.P>=c3 but not satisfying N2.P<=c2. They are stored in
797 * "resultdown" of size "nbverticesdown". the algorithm uses
798 * these points that's why they appear in the code.
800 //-----------------------------------------------------------------------------
801 template <typename TSpace, typename TSequence>
802 template <typename OutputIterator>
804 DGtal::LatticePolytope2D<TSpace,TSequence>::
805 computeConvexHullBorder
806 ( OutputIterator itOut,
807 const Point & pointRefC1,
808 const Point & pointRefC3,
809 const HalfSpace & hs1,
810 const HalfSpace & hs2,
811 const HalfSpace & hs3 ) const
813 // _u, _v: vectors u and v to determine the next vertex
814 bool exactIntersection;
815 // initializes A, B, u, v and the two first vertices of resultup and
817 _inPts.resize( 1 ); //to store half convex hull border
818 _outPts.resize( 1 ); //to store half convex hull border
819 _inPts[ 0 ] = pointRefC1;
821 // exactIntersection is equal to one when the intersection of the
822 // supporting lines of C1 and C2 corresponds to an integer point
823 exactIntersection = getFirstPointsOfHull( _v, _inPts[ 0 ], _outPts[ 0 ],
825 if ( ! exactIntersection ) // not integer intersection
827 //computation of the first part of the border
828 getAllPointsOfHull( _inPts, _outPts, _v, hs2, hs3 );
831 for( Size i = 0; i < _inPts.size(); ++i )
832 *itOut++ = _inPts[ i ];
835 // initializes A, B, u, v and the two first vertices of resultup and
839 _inPts[0] = pointRefC3;
840 // exactIntersection is equal to one when the intersection of the
841 // supporting lines of C3 and C2 corresponds to an integer point
842 exactIntersection = getFirstPointsOfHull( _v, _inPts[ 0 ], _outPts[ 0 ],
844 if ( ! exactIntersection ) // not integer intersection
846 //computation of the second part of the border
847 getAllPointsOfHull( _inPts, _outPts, _v, hs2, hs1 ); // check not hs1.
850 for( Size i = _inPts.size(); i != 0; --i )
852 *itOut++ = _inPts[ i - 1 ];
859 ///////////////////////////////////////////////////////////////////////////////
860 // Interface - public :
863 * Writes/Displays the object on an output stream.
864 * @param out the output stream where the object is written.
866 template <typename TSpace, typename TSequence>
869 DGtal::LatticePolytope2D<TSpace,TSequence>::selfDisplay ( std::ostream & out ) const
871 out << "[LatticePolytope2D #Vertices=" << size() << "]";
875 * Checks the validity/consistency of the object.
876 * @return 'true' if the object is valid, 'false' otherwise.
878 template <typename TSpace, typename TSequence>
881 DGtal::LatticePolytope2D<TSpace,TSequence>::isValid() const
885 //-----------------------------------------------------------------------------
886 template <typename TSpace, typename TSequence>
889 DGtal::LatticePolytope2D<TSpace,TSequence>::className
892 return "LatticePolytope2D";
897 ///////////////////////////////////////////////////////////////////////////////
898 // Implementation of inline functions //
900 template <typename TSpace, typename TSequence>
903 DGtal::operator<< ( std::ostream & out,
904 const LatticePolytope2D<TSpace,TSequence> & object )
906 object.selfDisplay( out );
911 ///////////////////////////////////////////////////////////////////////////////