annotate DEPENDENCIES/generic/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp @ 35:86bb97521df4

Update subrepos & merge as appropriate
author Chris Cannam
date Wed, 06 Aug 2014 16:05:55 +0100
parents 2665513ce2d3
children c530137014c0
rev   line source
Chris@16 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@16 2
Chris@16 3 // Copyright (c) 1995, 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
Chris@16 4 // Copyright (c) 1995 Maarten Hilferink, Amsterdam, the Netherlands
Chris@16 5
Chris@16 6 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
Chris@16 7 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
Chris@16 8
Chris@16 9 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 10 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 11 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 12
Chris@16 13 #ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
Chris@16 14 #define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
Chris@16 15
Chris@16 16
Chris@16 17 #include <cstddef>
Chris@16 18 #include <vector>
Chris@16 19
Chris@16 20 #include <boost/range.hpp>
Chris@16 21
Chris@16 22 #include <boost/geometry/core/cs.hpp>
Chris@16 23 #include <boost/geometry/strategies/distance.hpp>
Chris@16 24
Chris@16 25
Chris@16 26
Chris@16 27 //#define GL_DEBUG_DOUGLAS_PEUCKER
Chris@16 28
Chris@16 29 #ifdef GL_DEBUG_DOUGLAS_PEUCKER
Chris@16 30 #include <boost/geometry/io/dsv/write.hpp>
Chris@16 31 #endif
Chris@16 32
Chris@16 33
Chris@16 34 namespace boost { namespace geometry
Chris@16 35 {
Chris@16 36
Chris@16 37 namespace strategy { namespace simplify
Chris@16 38 {
Chris@16 39
Chris@16 40
Chris@16 41 #ifndef DOXYGEN_NO_DETAIL
Chris@16 42 namespace detail
Chris@16 43 {
Chris@16 44
Chris@16 45 /*!
Chris@16 46 \brief Small wrapper around a point, with an extra member "included"
Chris@16 47 \details
Chris@16 48 It has a const-reference to the original point (so no copy here)
Chris@16 49 \tparam the enclosed point type
Chris@16 50 */
Chris@16 51 template<typename Point>
Chris@16 52 struct douglas_peucker_point
Chris@16 53 {
Chris@16 54 Point const& p;
Chris@16 55 bool included;
Chris@16 56
Chris@16 57 inline douglas_peucker_point(Point const& ap)
Chris@16 58 : p(ap)
Chris@16 59 , included(false)
Chris@16 60 {}
Chris@16 61
Chris@16 62 // Necessary for proper compilation
Chris@16 63 inline douglas_peucker_point<Point> operator=(douglas_peucker_point<Point> const& )
Chris@16 64 {
Chris@16 65 return douglas_peucker_point<Point>(*this);
Chris@16 66 }
Chris@16 67 };
Chris@16 68 }
Chris@16 69 #endif // DOXYGEN_NO_DETAIL
Chris@16 70
Chris@16 71
Chris@16 72 /*!
Chris@16 73 \brief Implements the simplify algorithm.
Chris@16 74 \ingroup strategies
Chris@16 75 \details The douglas_peucker strategy simplifies a linestring, ring or
Chris@16 76 vector of points using the well-known Douglas-Peucker algorithm.
Chris@16 77 \tparam Point the point type
Chris@16 78 \tparam PointDistanceStrategy point-segment distance strategy to be used
Chris@16 79 \note This strategy uses itself a point-segment-distance strategy which
Chris@16 80 can be specified
Chris@16 81 \author Barend and Maarten, 1995/1996
Chris@16 82 \author Barend, revised for Generic Geometry Library, 2008
Chris@16 83 */
Chris@16 84
Chris@16 85 /*
Chris@16 86 For the algorithm, see for example:
Chris@16 87 - http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
Chris@16 88 - http://www2.dcs.hull.ac.uk/CISRG/projects/Royal-Inst/demos/dp.html
Chris@16 89 */
Chris@16 90 template
Chris@16 91 <
Chris@16 92 typename Point,
Chris@16 93 typename PointDistanceStrategy
Chris@16 94 >
Chris@16 95 class douglas_peucker
Chris@16 96 {
Chris@16 97 public :
Chris@16 98
Chris@16 99 // See also ticket 5954 https://svn.boost.org/trac/boost/ticket/5954
Chris@16 100 // Comparable is currently not possible here because it has to be compared to the squared of max_distance, and more.
Chris@16 101 // For now we have to take the real distance.
Chris@16 102 typedef PointDistanceStrategy distance_strategy_type;
Chris@16 103 // typedef typename strategy::distance::services::comparable_type<PointDistanceStrategy>::type distance_strategy_type;
Chris@16 104
Chris@16 105 typedef typename strategy::distance::services::return_type
Chris@16 106 <
Chris@16 107 distance_strategy_type,
Chris@16 108 Point, Point
Chris@16 109 >::type return_type;
Chris@16 110
Chris@16 111 private :
Chris@16 112 typedef detail::douglas_peucker_point<Point> dp_point_type;
Chris@16 113 typedef typename std::vector<dp_point_type>::iterator iterator_type;
Chris@16 114
Chris@16 115
Chris@16 116 static inline void consider(iterator_type begin,
Chris@16 117 iterator_type end,
Chris@16 118 return_type const& max_dist, int& n,
Chris@16 119 distance_strategy_type const& ps_distance_strategy)
Chris@16 120 {
Chris@16 121 std::size_t size = end - begin;
Chris@16 122
Chris@16 123 // size must be at least 3
Chris@16 124 // because we want to consider a candidate point in between
Chris@16 125 if (size <= 2)
Chris@16 126 {
Chris@16 127 #ifdef GL_DEBUG_DOUGLAS_PEUCKER
Chris@16 128 if (begin != end)
Chris@16 129 {
Chris@16 130 std::cout << "ignore between " << dsv(begin->p)
Chris@16 131 << " and " << dsv((end - 1)->p)
Chris@16 132 << " size=" << size << std::endl;
Chris@16 133 }
Chris@16 134 std::cout << "return because size=" << size << std::endl;
Chris@16 135 #endif
Chris@16 136 return;
Chris@16 137 }
Chris@16 138
Chris@16 139 iterator_type last = end - 1;
Chris@16 140
Chris@16 141 #ifdef GL_DEBUG_DOUGLAS_PEUCKER
Chris@16 142 std::cout << "find between " << dsv(begin->p)
Chris@16 143 << " and " << dsv(last->p)
Chris@16 144 << " size=" << size << std::endl;
Chris@16 145 #endif
Chris@16 146
Chris@16 147
Chris@16 148 // Find most far point, compare to the current segment
Chris@16 149 //geometry::segment<Point const> s(begin->p, last->p);
Chris@16 150 return_type md(-1.0); // any value < 0
Chris@16 151 iterator_type candidate;
Chris@16 152 for(iterator_type it = begin + 1; it != last; ++it)
Chris@16 153 {
Chris@16 154 return_type dist = ps_distance_strategy.apply(it->p, begin->p, last->p);
Chris@16 155
Chris@16 156 #ifdef GL_DEBUG_DOUGLAS_PEUCKER
Chris@16 157 std::cout << "consider " << dsv(it->p)
Chris@16 158 << " at " << double(dist)
Chris@16 159 << ((dist > max_dist) ? " maybe" : " no")
Chris@16 160 << std::endl;
Chris@16 161
Chris@16 162 #endif
Chris@16 163 if (dist > md)
Chris@16 164 {
Chris@16 165 md = dist;
Chris@16 166 candidate = it;
Chris@16 167 }
Chris@16 168 }
Chris@16 169
Chris@16 170 // If a point is found, set the include flag
Chris@16 171 // and handle segments in between recursively
Chris@16 172 if (md > max_dist)
Chris@16 173 {
Chris@16 174 #ifdef GL_DEBUG_DOUGLAS_PEUCKER
Chris@16 175 std::cout << "use " << dsv(candidate->p) << std::endl;
Chris@16 176 #endif
Chris@16 177
Chris@16 178 candidate->included = true;
Chris@16 179 n++;
Chris@16 180
Chris@16 181 consider(begin, candidate + 1, max_dist, n, ps_distance_strategy);
Chris@16 182 consider(candidate, end, max_dist, n, ps_distance_strategy);
Chris@16 183 }
Chris@16 184 }
Chris@16 185
Chris@16 186
Chris@16 187 public :
Chris@16 188
Chris@16 189 template <typename Range, typename OutputIterator>
Chris@16 190 static inline OutputIterator apply(Range const& range,
Chris@16 191 OutputIterator out, double max_distance)
Chris@16 192 {
Chris@16 193 distance_strategy_type strategy;
Chris@16 194
Chris@16 195 // Copy coordinates, a vector of references to all points
Chris@16 196 std::vector<dp_point_type> ref_candidates(boost::begin(range),
Chris@16 197 boost::end(range));
Chris@16 198
Chris@16 199 // Include first and last point of line,
Chris@16 200 // they are always part of the line
Chris@16 201 int n = 2;
Chris@16 202 ref_candidates.front().included = true;
Chris@16 203 ref_candidates.back().included = true;
Chris@16 204
Chris@16 205 // Get points, recursively, including them if they are further away
Chris@16 206 // than the specified distance
Chris@16 207 consider(boost::begin(ref_candidates), boost::end(ref_candidates), max_distance, n, strategy);
Chris@16 208
Chris@16 209 // Copy included elements to the output
Chris@16 210 for(typename std::vector<dp_point_type>::const_iterator it
Chris@16 211 = boost::begin(ref_candidates);
Chris@16 212 it != boost::end(ref_candidates);
Chris@16 213 ++it)
Chris@16 214 {
Chris@16 215 if (it->included)
Chris@16 216 {
Chris@16 217 // copy-coordinates does not work because OutputIterator
Chris@16 218 // does not model Point (??)
Chris@16 219 //geometry::convert(it->p, *out);
Chris@16 220 *out = it->p;
Chris@16 221 out++;
Chris@16 222 }
Chris@16 223 }
Chris@16 224 return out;
Chris@16 225 }
Chris@16 226
Chris@16 227 };
Chris@16 228
Chris@16 229 }} // namespace strategy::simplify
Chris@16 230
Chris@16 231
Chris@16 232 namespace traits {
Chris@16 233
Chris@16 234 template <typename P>
Chris@16 235 struct point_type<strategy::simplify::detail::douglas_peucker_point<P> >
Chris@16 236 {
Chris@16 237 typedef P type;
Chris@16 238 };
Chris@16 239
Chris@16 240 } // namespace traits
Chris@16 241
Chris@16 242
Chris@16 243 }} // namespace boost::geometry
Chris@16 244
Chris@16 245 #endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP