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 MelkmanConvexHull.ih
19 * @author Tristan Roussillon (\c tristan.roussillon@liris.cnrs.fr )
20 * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
24 * Implementation of inline methods defined in MelkmanConvexHull.h
26 * This file is part of the DGtal library.
30//////////////////////////////////////////////////////////////////////////////
32#include <boost/utility.hpp>
33#include <boost/next_prior.hpp>
34//////////////////////////////////////////////////////////////////////////////
36///////////////////////////////////////////////////////////////////////////////
37// IMPLEMENTATION of inline methods.
38///////////////////////////////////////////////////////////////////////////////
40///////////////////////////////////////////////////////////////////////////////
41// ----------------------------------------------------------------------------
42template <typename TPoint, typename TOrientationFunctor>
44DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::MelkmanConvexHull( Alias<Functor> aFunctor )
46 myBackwardPredicate( aFunctor ),
47 myForwardPredicate( aFunctor )
51// ----------------------------------------------------------------------------
52template <typename TPoint, typename TOrientationFunctor>
54DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::MelkmanConvexHull()
56 myBackwardPredicate(myDefaultFunctor),
57 myForwardPredicate(myDefaultFunctor)
61// ----------------------------------------------------------------------------
62template <typename TPoint, typename TOrientationFunctor>
65DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::add(const Point& aPoint)
68 using namespace DGtal::functions::Hull2D;
70 if (myContainer.size() < 4)
72 if (myContainer.size() == 0)
74 myFirstPoint = aPoint;
76 myContainer.push_back( aPoint );
77 myContainer.push_front( aPoint );
79 else if (myContainer.size() == 2)
81 myContainer.pop_back();
82 myContainer.push_back( aPoint );
83 myContainer.push_front( aPoint );
85 else if (myContainer.size() == 3)
87 //required to deal with the case where the k first input points are aligned.
88 if ( !myBackwardPredicate( *boost::next(myContainer.rbegin()), myContainer.back(), aPoint ) )
89 myContainer.pop_back();
90 myContainer.push_back( aPoint );
91 if ( !myForwardPredicate( *boost::next(myContainer.begin()), myContainer.front(), aPoint ) )
92 myContainer.pop_front();
93 myContainer.push_front( aPoint );
98 if ( ( !myBackwardPredicate( *boost::next(myContainer.rbegin()), myContainer.back(), aPoint ) ||
99 !myForwardPredicate( *boost::next(myContainer.begin()), myContainer.front(), aPoint ) ) )
102 updateHullWithAdaptedStack( backStack(myContainer), aPoint, myBackwardPredicate );
103 myContainer.push_back( aPoint );
106 updateHullWithAdaptedStack( frontStack(myContainer), aPoint, myForwardPredicate );
107 myContainer.push_front( aPoint );
112// ----------------------------------------------------------------------------
113template <typename TPoint, typename TOrientationFunctor>
115typename DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::ConstIterator
116DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::begin() const
118 if (myContainer.size() == 0)
119 return myContainer.end();
121 return boost::next(myContainer.begin());
124// ----------------------------------------------------------------------------
125template <typename TPoint, typename TOrientationFunctor>
127typename DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::ConstIterator
128DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::end() const
130 return myContainer.end();
133// ----------------------------------------------------------------------------
134template <typename TPoint, typename TOrientationFunctor>
137DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::selfDisplay ( std::ostream & out ) const
139 out << "[MelkmanConvexHull]" << " #";
140 if ( myContainer.size() == 0 )
141 out << " 0 " << std::endl;
143 out << myContainer.size() - 1 << std::endl;
144 std::copy( myContainer.begin(), myContainer.end(),
145 std::ostream_iterator<Point>( out, "," ) );
149// ----------------------------------------------------------------------------
150template <typename TPoint, typename TOrientationFunctor>
153DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::isValid() const
158// ----------------------------------------------------------------------------
159template <typename TPoint, typename TOrientationFunctor>
161DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>&
162DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::operator= (const Self & mch)
164 myContainer = mch.myContainer;
168// ----------------------------------------------------------------------------
169template <typename TPoint, typename TOrientationFunctor>
172DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::operator[](unsigned int i) const
174 ASSERT( i < myContainer.size() );
175 return myContainer[i];
178// ----------------------------------------------------------------------------
179template <typename TPoint, typename TOrientationFunctor>
182DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::size() const
184 // by definition the first and last points of the deque are the same.
185 return ( myContainer.size()-1u );
188// ----------------------------------------------------------------------------
189template <typename TPoint, typename TOrientationFunctor>
192DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::clear()
197// ----------------------------------------------------------------------------
198template <typename TPoint, typename TOrientationFunctor>
201DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::reverse()
203 // if convexhull is reduced into a single segment no need to reverse anything.
204 if(myContainer.size()<=3)
206 TPoint theLast = myContainer.back();
207 myContainer.pop_back();
208 bool foundFirst = myContainer.back() == myFirstPoint;
210 myContainer.push_front(myContainer.back());
211 myContainer.pop_back();
212 foundFirst = myContainer.back() == myFirstPoint;
214 myContainer.push_front(myContainer.back());
215 myFirstPoint = theLast;
219///////////////////////////////////////////////////////////////////////////////
220// Implementation of inline functions //
222template <typename TPoint, typename TOrientationFunctor>
225DGtal::operator<< ( std::ostream & out,
226 const MelkmanConvexHull<TPoint, TOrientationFunctor> & object )
228 object.selfDisplay( out );
232///////////////////////////////////////////////////////////////////////////////
233template <typename ForwardIterator,
234 typename OutputIterator,
237void DGtal::functions::Hull2D::
238melkmanConvexHullAlgorithm(const ForwardIterator& itb, const ForwardIterator& ite,
242 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<ForwardIterator> ));
243 BOOST_CONCEPT_ASSERT(( boost_concepts::ReadableIteratorConcept<ForwardIterator> ));
244 typedef typename DGtal::IteratorCirculatorTraits<ForwardIterator>::Value Point;
245 BOOST_CONCEPT_ASSERT(( boost_concepts::IncrementableIteratorConcept<OutputIterator> ));
246 BOOST_CONCEPT_ASSERT(( boost_concepts::WritableIteratorConcept<OutputIterator,Point> ));
251 //convex hull computation with Melkman's algorithm
252 DGtal::MelkmanConvexHull<Point, Functor> ch( aFunctor );
253 for (ForwardIterator it = itb; it != ite; ++it)
256 std::copy( ch.begin(), ch.end(), res );
260///////////////////////////////////////////////////////////////////////////////