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 // ----------------------------------------------------------------------------
42 template <typename TPoint, typename TOrientationFunctor>
44 DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::MelkmanConvexHull( Alias<Functor> aFunctor )
46 myBackwardPredicate( aFunctor ),
47 myForwardPredicate( aFunctor )
51 // ----------------------------------------------------------------------------
52 template <typename TPoint, typename TOrientationFunctor>
54 DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::MelkmanConvexHull()
56 myBackwardPredicate(myDefaultFunctor),
57 myForwardPredicate(myDefaultFunctor)
61 // ----------------------------------------------------------------------------
62 template <typename TPoint, typename TOrientationFunctor>
65 DGtal::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 // ----------------------------------------------------------------------------
113 template <typename TPoint, typename TOrientationFunctor>
115 typename DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::ConstIterator
116 DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::begin() const
118 if (myContainer.size() == 0)
119 return myContainer.end();
121 return boost::next(myContainer.begin());
124 // ----------------------------------------------------------------------------
125 template <typename TPoint, typename TOrientationFunctor>
127 typename DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::ConstIterator
128 DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::end() const
130 return myContainer.end();
133 // ----------------------------------------------------------------------------
134 template <typename TPoint, typename TOrientationFunctor>
137 DGtal::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 // ----------------------------------------------------------------------------
150 template <typename TPoint, typename TOrientationFunctor>
153 DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::isValid() const
158 // ----------------------------------------------------------------------------
159 template <typename TPoint, typename TOrientationFunctor>
161 DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>&
162 DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::operator= (const Self & mch)
164 myContainer = mch.myContainer;
168 // ----------------------------------------------------------------------------
169 template <typename TPoint, typename TOrientationFunctor>
172 DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::operator[](unsigned int i) const
174 ASSERT( i < myContainer.size() );
175 return myContainer[i];
178 // ----------------------------------------------------------------------------
179 template <typename TPoint, typename TOrientationFunctor>
182 DGtal::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 // ----------------------------------------------------------------------------
189 template <typename TPoint, typename TOrientationFunctor>
192 DGtal::MelkmanConvexHull<TPoint, TOrientationFunctor>::clear()
197 // ----------------------------------------------------------------------------
198 template <typename TPoint, typename TOrientationFunctor>
201 DGtal::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 //
222 template <typename TPoint, typename TOrientationFunctor>
225 DGtal::operator<< ( std::ostream & out,
226 const MelkmanConvexHull<TPoint, TOrientationFunctor> & object )
228 object.selfDisplay( out );
232 ///////////////////////////////////////////////////////////////////////////////
233 template <typename ForwardIterator,
234 typename OutputIterator,
237 void DGtal::functions::Hull2D::
238 melkmanConvexHullAlgorithm(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 ///////////////////////////////////////////////////////////////////////////////