annotate DEPENDENCIES/generic/include/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp @ 125:34e428693f5d vext

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