]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/algorithms/line_interpolate.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / line_interpolate.hpp
CommitLineData
92f5a8d4
TL
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
20effc67 3// Copyright (c) 2018-2020 Oracle and/or its affiliates.
92f5a8d4
TL
4
5// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
6// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
7
8// Use, modification and distribution is subject to the Boost Software License,
9// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
10// http://www.boost.org/LICENSE_1_0.txt)
11
12#ifndef BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP
13#define BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP
14
15#include <iterator>
20effc67 16#include <type_traits>
92f5a8d4
TL
17
18#include <boost/range/begin.hpp>
19#include <boost/range/end.hpp>
20#include <boost/range/iterator.hpp>
21#include <boost/range/value_type.hpp>
22
23#include <boost/geometry/core/cs.hpp>
24#include <boost/geometry/core/closure.hpp>
20effc67 25#include <boost/geometry/core/static_assert.hpp>
92f5a8d4
TL
26#include <boost/geometry/core/tags.hpp>
27
28#include <boost/geometry/geometries/concepts/check.hpp>
29
30#include <boost/geometry/algorithms/assign.hpp>
31#include <boost/geometry/algorithms/length.hpp>
32#include <boost/geometry/strategies/default_strategy.hpp>
33#include <boost/geometry/strategies/line_interpolate.hpp>
34
35namespace boost { namespace geometry
36{
37
38
39#ifndef DOXYGEN_NO_DETAIL
40namespace detail { namespace line_interpolate
41{
42
43struct convert_and_push_back
44{
45 template <typename Range, typename Point>
46 inline void apply(Point const& p, Range& range)
47 {
48 typename boost::range_value<Range>::type p2;
49 geometry::detail::conversion::convert_point_to_point(p, p2);
50 range::push_back(range, p2);
51 }
52};
53
54struct convert_and_assign
55{
56 template <typename Point1, typename Point2>
57 inline void apply(Point1 const& p1, Point2& p2)
58 {
59 geometry::detail::conversion::convert_point_to_point(p1, p2);
60 }
61
62};
63
64
65/*!
66\brief Internal, calculates interpolation point of a linestring using iterator pairs and
67 specified strategy
68*/
69template <typename Policy>
70struct interpolate_range
71{
72 template
73 <
74 typename Range,
75 typename Distance,
76 typename PointLike,
77 typename Strategy
78 >
79 static inline void apply(Range const& range,
80 Distance const& max_distance,
81 PointLike & pointlike,
82 Strategy const& strategy)
83 {
84 Policy policy;
85
86 typedef typename boost::range_iterator<Range const>::type iterator_t;
87 typedef typename boost::range_value<Range const>::type point_t;
88
89 iterator_t it = boost::begin(range);
90 iterator_t end = boost::end(range);
91
92 if (it == end) // empty(range)
93 {
94 BOOST_THROW_EXCEPTION(empty_input_exception());
95 return;
96 }
97 if (max_distance <= 0) //non positive distance
98 {
99 policy.apply(*it, pointlike);
100 return;
101 }
102
103 iterator_t prev = it++;
104 Distance repeated_distance = max_distance;
105 Distance prev_distance = 0;
106 Distance current_distance = 0;
107 point_t start_p = *prev;
108
109 for ( ; it != end ; ++it)
110 {
111 Distance dist = strategy.get_distance_pp_strategy().apply(*prev, *it);
112 current_distance = prev_distance + dist;
113
114 while (current_distance >= repeated_distance)
115 {
116 point_t p;
117 Distance diff_distance = current_distance - prev_distance;
118 BOOST_ASSERT(diff_distance != Distance(0));
119 strategy.apply(start_p, *it,
120 (repeated_distance - prev_distance)/diff_distance,
121 p,
122 diff_distance);
123 policy.apply(p, pointlike);
20effc67 124 if (std::is_same<PointLike, point_t>::value)
92f5a8d4
TL
125 {
126 return;
127 }
128 start_p = p;
129 prev_distance = repeated_distance;
130 repeated_distance += max_distance;
131 }
132 prev_distance = current_distance;
133 prev = it;
134 start_p = *prev;
135 }
136
137 // case when max_distance is larger than linestring's length
138 // return the last point in range (range is not empty)
139 if (repeated_distance == max_distance)
140 {
141 policy.apply(*(end-1), pointlike);
142 }
143 }
144};
145
146template <typename Policy>
147struct interpolate_segment
148{
149 template <typename Segment, typename Distance, typename Pointlike, typename Strategy>
150 static inline void apply(Segment const& segment,
151 Distance const& max_distance,
152 Pointlike & point,
153 Strategy const& strategy)
154 {
155 interpolate_range<Policy>().apply(segment_view<Segment>(segment),
156 max_distance, point, strategy);
157 }
158};
159
160}} // namespace detail::line_interpolate
161#endif // DOXYGEN_NO_DETAIL
162
163
164#ifndef DOXYGEN_NO_DISPATCH
165namespace dispatch
166{
167
168
169template
170<
171 typename Geometry,
172 typename Pointlike,
173 typename Tag1 = typename tag<Geometry>::type,
174 typename Tag2 = typename tag<Pointlike>::type
175>
176struct line_interpolate
177{
20effc67
TL
178 BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
179 "Not implemented for this Geometry type.",
180 Geometry, Pointlike);
92f5a8d4
TL
181};
182
183
184template <typename Geometry, typename Pointlike>
185struct line_interpolate<Geometry, Pointlike, linestring_tag, point_tag>
186 : detail::line_interpolate::interpolate_range
187 <
188 detail::line_interpolate::convert_and_assign
189 >
190{};
191
192template <typename Geometry, typename Pointlike>
193struct line_interpolate<Geometry, Pointlike, linestring_tag, multi_point_tag>
194 : detail::line_interpolate::interpolate_range
195 <
196 detail::line_interpolate::convert_and_push_back
197 >
198{};
199
200template <typename Geometry, typename Pointlike>
201struct line_interpolate<Geometry, Pointlike, segment_tag, point_tag>
202 : detail::line_interpolate::interpolate_segment
203 <
204 detail::line_interpolate::convert_and_assign
205 >
206{};
207
208template <typename Geometry, typename Pointlike>
209struct line_interpolate<Geometry, Pointlike, segment_tag, multi_point_tag>
210 : detail::line_interpolate::interpolate_segment
211 <
212 detail::line_interpolate::convert_and_push_back
213 >
214{};
215
216} // namespace dispatch
217#endif // DOXYGEN_NO_DISPATCH
218
219
220namespace resolve_strategy {
221
222struct line_interpolate
223{
224 template
225 <
226 typename Geometry,
227 typename Distance,
228 typename Pointlike,
229 typename Strategy
230 >
231 static inline void apply(Geometry const& geometry,
232 Distance const& max_distance,
233 Pointlike & pointlike,
234 Strategy const& strategy)
235 {
236 dispatch::line_interpolate<Geometry, Pointlike>::apply(geometry,
237 max_distance,
238 pointlike,
239 strategy);
240 }
241
242 template <typename Geometry, typename Distance, typename Pointlike>
243 static inline void apply(Geometry const& geometry,
244 Distance const& max_distance,
245 Pointlike & pointlike,
246 default_strategy)
247 {
248 typedef typename strategy::line_interpolate::services::default_strategy
249 <
250 typename cs_tag<Geometry>::type
251 >::type strategy_type;
252
253 dispatch::line_interpolate<Geometry, Pointlike>::apply(geometry,
254 max_distance,
255 pointlike,
256 strategy_type());
257 }
258};
259
260} // namespace resolve_strategy
261
262
263namespace resolve_variant {
264
265template <typename Geometry>
266struct line_interpolate
267{
268 template <typename Distance, typename Pointlike, typename Strategy>
269 static inline void apply(Geometry const& geometry,
270 Distance const& max_distance,
271 Pointlike & pointlike,
272 Strategy const& strategy)
273 {
274 return resolve_strategy::line_interpolate::apply(geometry,
275 max_distance,
276 pointlike,
277 strategy);
278 }
279};
280
281template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
282struct line_interpolate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
283{
284 template <typename Pointlike, typename Strategy>
285 struct visitor: boost::static_visitor<void>
286 {
287 Pointlike const& m_pointlike;
288 Strategy const& m_strategy;
289
290 visitor(Pointlike const& pointlike, Strategy const& strategy)
291 : m_pointlike(pointlike)
292 , m_strategy(strategy)
293 {}
294
295 template <typename Geometry, typename Distance>
296 void operator()(Geometry const& geometry, Distance const& max_distance) const
297 {
298 line_interpolate<Geometry>::apply(geometry, max_distance,
299 m_pointlike, m_strategy);
300 }
301 };
302
303 template <typename Distance, typename Pointlike, typename Strategy>
304 static inline void
305 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
306 double const& max_distance,
307 Pointlike & pointlike,
308 Strategy const& strategy)
309 {
310 boost::apply_visitor(
311 visitor<Pointlike, Strategy>(pointlike, strategy),
312 geometry,
313 max_distance
314 );
315 }
316};
317
318} // namespace resolve_variant
319
320/*!
321\brief Returns one or more points interpolated along a LineString \brief_strategy
322\ingroup line_interpolate
323\tparam Geometry Any type fulfilling a LineString concept
324\tparam Distance A numerical distance measure
325\tparam Pointlike Any type fulfilling Point or Multipoint concept
326\tparam Strategy A type fulfilling a LineInterpolatePointStrategy concept
327\param geometry Input geometry
328\param max_distance Distance threshold (in units depending on coordinate system)
329representing the spacing between the points
330\param pointlike Output: either a Point (exactly one point will be constructed) or
331a MultiPoint (depending on the max_distance one or more points will be constructed)
332\param strategy line_interpolate strategy to be used for interpolation of
333points
334
335\qbk{[include reference/algorithms/line_interpolate.qbk]}
336
337\qbk{distinguish,with strategy}
338
339\qbk{
340[heading Available Strategies]
341\* [link geometry.reference.strategies.strategy_line_interpolate_cartesian Cartesian]
342\* [link geometry.reference.strategies.strategy_line_interpolate_spherical Spherical]
343\* [link geometry.reference.strategies.strategy_line_interpolate_geographic Geographic]
344
345[heading Example]
346[line_interpolate_strategy]
347[line_interpolate_strategy_output]
348
349[heading See also]
350\* [link geometry.reference.algorithms.densify densify]
351}
352 */
353template
354<
355 typename Geometry,
356 typename Distance,
357 typename Pointlike,
358 typename Strategy
359>
360inline void line_interpolate(Geometry const& geometry,
361 Distance const& max_distance,
362 Pointlike & pointlike,
363 Strategy const& strategy)
364{
365 concepts::check<Geometry const>();
366
367 // detail::throw_on_empty_input(geometry);
368
369 return resolve_variant::line_interpolate<Geometry>
370 ::apply(geometry, max_distance, pointlike, strategy);
371}
372
373
374/*!
375\brief Returns one or more points interpolated along a LineString.
376\ingroup line_interpolate
377\tparam Geometry Any type fulfilling a LineString concept
378\tparam Distance A numerical distance measure
379\tparam Pointlike Any type fulfilling Point or Multipoint concept
380\param geometry Input geometry
381\param max_distance Distance threshold (in units depending on coordinate system)
382representing the spacing between the points
383\param pointlike Output: either a Point (exactly one point will be constructed) or
384a MultiPoint (depending on the max_distance one or more points will be constructed)
385
386\qbk{[include reference/algorithms/line_interpolate.qbk]
387
388[heading Example]
389[line_interpolate]
390[line_interpolate_output]
391
392[heading See also]
393\* [link geometry.reference.algorithms.densify densify]
394}
395 */
396template<typename Geometry, typename Distance, typename Pointlike>
397inline void line_interpolate(Geometry const& geometry,
398 Distance const& max_distance,
399 Pointlike & pointlike)
400{
401 concepts::check<Geometry const>();
402
403 // detail::throw_on_empty_input(geometry);
404
405 return resolve_variant::line_interpolate<Geometry>
406 ::apply(geometry, max_distance, pointlike, default_strategy());
407}
408
409}} // namespace boost::geometry
410
411#endif // BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP