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//////////////////////////////////////////////////////////////////////////////
34///////////////////////////////////////////////////////////////////////////////
35// IMPLEMENTATION of inline methods.
36///////////////////////////////////////////////////////////////////////////////
38///////////////////////////////////////////////////////////////////////////////
39// ----------------------------------------------------------------------------
40template <typename TPoint, typename TOrientationFunctor>
42DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::MelkmanConvexHull( Alias<Functor> aFunctor )
44 myBackwardPredicate( aFunctor ),
45 myForwardPredicate( aFunctor )
49// ----------------------------------------------------------------------------
50template <typename TPoint, typename TOrientationFunctor>
52DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::MelkmanConvexHull()
54 myBackwardPredicate(myDefaultFunctor),
55 myForwardPredicate(myDefaultFunctor)
59// ----------------------------------------------------------------------------
60template <typename TPoint, typename TOrientationFunctor>
63DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::add(const Point& aPoint)
66 using namespace DGtal::functions::Hull2D;
68 if (myContainer.size() < 4)
70 if (myContainer.size() == 0)
72 myFirstPoint = aPoint;
74 myContainer.push_back( aPoint );
75 myContainer.push_front( aPoint );
77 else if (myContainer.size() == 2)
79 myContainer.pop_back();
80 myContainer.push_back( aPoint );
81 myContainer.push_front( aPoint );
83 else if (myContainer.size() == 3)
85 //required to deal with the case where the k first input points are aligned.
86 if ( !myBackwardPredicate( *boost::next(myContainer.rbegin()), myContainer.back(), aPoint ) )
87 myContainer.pop_back();
88 myContainer.push_back( aPoint );
89 if ( !myForwardPredicate( *boost::next(myContainer.begin()), myContainer.front(), aPoint ) )
90 myContainer.pop_front();
91 myContainer.push_front( aPoint );
96 if ( ( !myBackwardPredicate( *boost::next(myContainer.rbegin()), myContainer.back(), aPoint ) ||
97 !myForwardPredicate( *boost::next(myContainer.begin()), myContainer.front(), aPoint ) ) )
100 updateHullWithAdaptedStack( backStack(myContainer), aPoint, myBackwardPredicate );
101 myContainer.push_back( aPoint );
104 updateHullWithAdaptedStack( frontStack(myContainer), aPoint, myForwardPredicate );
105 myContainer.push_front( aPoint );
110// ----------------------------------------------------------------------------
111template <typename TPoint, typename TOrientationFunctor>
113typename DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::ConstIterator
114DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::begin() const
116 if (myContainer.size() == 0)
117 return myContainer.end();
119 return boost::next(myContainer.begin());
122// ----------------------------------------------------------------------------
123template <typename TPoint, typename TOrientationFunctor>
125typename DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::ConstIterator
126DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::end() const
128 return myContainer.end();
131// ----------------------------------------------------------------------------
132template <typename TPoint, typename TOrientationFunctor>
135DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::selfDisplay ( std::ostream & out ) const
137 out << "[MelkmanConvexHull]" << " #";
138 if ( myContainer.size() == 0 )
139 out << " 0 " << std::endl;
141 out << myContainer.size() - 1 << std::endl;
142 std::copy( myContainer.begin(), myContainer.end(),
143 std::ostream_iterator<Point>( out, "," ) );
147// ----------------------------------------------------------------------------
148template <typename TPoint, typename TOrientationFunctor>
151DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::isValid() const
156// ----------------------------------------------------------------------------
157template <typename TPoint, typename TOrientationFunctor>
159DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>&
160DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::operator= (const Self & mch)
162 myContainer = mch.myContainer;
166// ----------------------------------------------------------------------------
167template <typename TPoint, typename TOrientationFunctor>
170DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::operator[](unsigned int i) const
172 ASSERT( i < myContainer.size() );
173 return myContainer[i];
176// ----------------------------------------------------------------------------
177template <typename TPoint, typename TOrientationFunctor>
180DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::size() const
182 // by definition the first and last points of the deque are the same.
183 return ( myContainer.size()-1u );
186// ----------------------------------------------------------------------------
187template <typename TPoint, typename TOrientationFunctor>
190DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::clear()
195// ----------------------------------------------------------------------------
196template <typename TPoint, typename TOrientationFunctor>
199DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::reverse()
201 // if convexhull is reduced into a single segment no need to reverse anything.
202 if(myContainer.size()<=3)
204 TPoint theLast = myContainer.back();
205 myContainer.pop_back();
206 bool foundFirst = myContainer.back() == myFirstPoint;
208 myContainer.push_front(myContainer.back());
209 myContainer.pop_back();
210 foundFirst = myContainer.back() == myFirstPoint;
212 myContainer.push_front(myContainer.back());
213 myFirstPoint = theLast;
217///////////////////////////////////////////////////////////////////////////////
218// Implementation of inline functions //
220template <typename TPoint, typename TOrientationFunctor>
223DGtal::operator<< ( std::ostream & out,
224 const MelkmanConvexHull<TPoint, TOrientationFunctor> & object )
226 object.selfDisplay( out );
230///////////////////////////////////////////////////////////////////////////////
231template <typename ForwardIterator,
232 typename OutputIterator,
235void DGtal::functions::Hull2D::
236melkmanConvexHullAlgorithm(const ForwardIterator& itb, const ForwardIterator& ite,
240 BOOST_CONCEPT_ASSERT(( boost_concepts::ForwardTraversalConcept<ForwardIterator> ));
241 BOOST_CONCEPT_ASSERT(( boost_concepts::ReadableIteratorConcept<ForwardIterator> ));
242 typedef typename DGtal::IteratorCirculatorTraits<ForwardIterator>::Value Point;
243 BOOST_CONCEPT_ASSERT(( boost_concepts::IncrementableIteratorConcept<OutputIterator> ));
244 BOOST_CONCEPT_ASSERT(( boost_concepts::WritableIteratorConcept<OutputIterator,Point> ));
249 //convex hull computation with Melkman's algorithm
250 DGtal::MelkmanConvexHull<Point, Functor> ch( aFunctor );
251 for (ForwardIterator it = itb; it != ite; ++it)
254 std::copy( ch.begin(), ch.end(), res );
258///////////////////////////////////////////////////////////////////////////////