Warning, file /include/boost/geometry/algorithms/line_interpolate.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP
0014 #define BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP
0015
0016 #include <type_traits>
0017
0018 #include <boost/range/begin.hpp>
0019 #include <boost/range/end.hpp>
0020 #include <boost/range/value_type.hpp>
0021 #include <boost/variant/apply_visitor.hpp>
0022 #include <boost/variant/static_visitor.hpp>
0023 #include <boost/variant/variant_fwd.hpp>
0024
0025 #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
0026 #include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
0027
0028 #include <boost/geometry/core/exception.hpp>
0029 #include <boost/geometry/core/static_assert.hpp>
0030 #include <boost/geometry/core/tags.hpp>
0031
0032 #include <boost/geometry/geometries/concepts/check.hpp>
0033
0034 #include <boost/geometry/strategies/default_strategy.hpp>
0035 #include <boost/geometry/strategies/detail.hpp>
0036 #include <boost/geometry/strategies/line_interpolate/cartesian.hpp>
0037 #include <boost/geometry/strategies/line_interpolate/geographic.hpp>
0038 #include <boost/geometry/strategies/line_interpolate/spherical.hpp>
0039
0040 #include <boost/geometry/util/constexpr.hpp>
0041 #include <boost/geometry/util/range.hpp>
0042 #include <boost/geometry/util/type_traits.hpp>
0043
0044 #include <boost/geometry/views/segment_view.hpp>
0045
0046 namespace boost { namespace geometry
0047 {
0048
0049
0050 #ifndef DOXYGEN_NO_DETAIL
0051 namespace detail { namespace line_interpolate
0052 {
0053
0054 struct convert_and_push_back
0055 {
0056 template <typename Range, typename Point>
0057 static inline void apply(Point const& p, Range& range)
0058 {
0059 typename boost::range_value<Range>::type p2;
0060 geometry::detail::conversion::convert_point_to_point(p, p2);
0061 range::push_back(range, p2);
0062 }
0063 };
0064
0065 struct convert_and_assign
0066 {
0067 template <typename Point1, typename Point2>
0068 static inline void apply(Point1 const& p1, Point2& p2)
0069 {
0070 geometry::detail::conversion::convert_point_to_point(p1, p2);
0071 }
0072
0073 };
0074
0075
0076
0077
0078
0079
0080 template <typename Policy>
0081 struct interpolate_range
0082 {
0083 template
0084 <
0085 typename Range,
0086 typename Distance,
0087 typename PointLike,
0088 typename Strategies
0089 >
0090 static inline void apply(Range const& range,
0091 Distance const& max_distance,
0092 PointLike & pointlike,
0093 Strategies const& strategies)
0094 {
0095 typedef typename boost::range_value<Range const>::type point_t;
0096
0097 auto it = boost::begin(range);
0098 auto const end = boost::end(range);
0099
0100 if (it == end)
0101 {
0102 BOOST_THROW_EXCEPTION(empty_input_exception());
0103 return;
0104 }
0105 if (max_distance <= 0)
0106 {
0107 Policy::apply(*it, pointlike);
0108 return;
0109 }
0110
0111 auto const pp_strategy = strategies.distance(dummy_point(), dummy_point());
0112 auto const strategy = strategies.line_interpolate(range);
0113
0114 typedef decltype(pp_strategy.apply(
0115 std::declval<point_t>(), std::declval<point_t>())) distance_type;
0116
0117 auto prev = it++;
0118 distance_type repeated_distance = max_distance;
0119 distance_type prev_distance = 0;
0120 distance_type current_distance = 0;
0121 point_t start_p = *prev;
0122
0123 for ( ; it != end ; ++it)
0124 {
0125 distance_type dist = pp_strategy.apply(*prev, *it);
0126 current_distance = prev_distance + dist;
0127
0128 while (current_distance >= repeated_distance)
0129 {
0130 point_t p;
0131 distance_type diff_distance = current_distance - prev_distance;
0132 BOOST_ASSERT(diff_distance != distance_type(0));
0133 strategy.apply(start_p, *it,
0134 (repeated_distance - prev_distance)/diff_distance,
0135 p,
0136 diff_distance);
0137 Policy::apply(p, pointlike);
0138 if BOOST_GEOMETRY_CONSTEXPR (util::is_point<PointLike>::value)
0139 {
0140 return;
0141 }
0142 else
0143 {
0144 start_p = p;
0145 prev_distance = repeated_distance;
0146 repeated_distance += max_distance;
0147 }
0148 }
0149 prev_distance = current_distance;
0150 prev = it;
0151 start_p = *prev;
0152 }
0153
0154
0155
0156 if (repeated_distance == max_distance)
0157 {
0158 Policy::apply(*(end-1), pointlike);
0159 }
0160 }
0161 };
0162
0163 template <typename Policy>
0164 struct interpolate_segment
0165 {
0166 template <typename Segment, typename Distance, typename Pointlike, typename Strategy>
0167 static inline void apply(Segment const& segment,
0168 Distance const& max_distance,
0169 Pointlike & point,
0170 Strategy const& strategy)
0171 {
0172 interpolate_range<Policy>().apply(segment_view<Segment>(segment),
0173 max_distance, point, strategy);
0174 }
0175 };
0176
0177 }}
0178 #endif
0179
0180
0181 #ifndef DOXYGEN_NO_DISPATCH
0182 namespace dispatch
0183 {
0184
0185
0186 template
0187 <
0188 typename Geometry,
0189 typename Pointlike,
0190 typename Tag1 = typename tag<Geometry>::type,
0191 typename Tag2 = typename tag<Pointlike>::type
0192 >
0193 struct line_interpolate
0194 {
0195 BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
0196 "Not implemented for this Geometry type.",
0197 Geometry, Pointlike);
0198 };
0199
0200
0201 template <typename Geometry, typename Pointlike>
0202 struct line_interpolate<Geometry, Pointlike, linestring_tag, point_tag>
0203 : detail::line_interpolate::interpolate_range
0204 <
0205 detail::line_interpolate::convert_and_assign
0206 >
0207 {};
0208
0209 template <typename Geometry, typename Pointlike>
0210 struct line_interpolate<Geometry, Pointlike, linestring_tag, multi_point_tag>
0211 : detail::line_interpolate::interpolate_range
0212 <
0213 detail::line_interpolate::convert_and_push_back
0214 >
0215 {};
0216
0217 template <typename Geometry, typename Pointlike>
0218 struct line_interpolate<Geometry, Pointlike, segment_tag, point_tag>
0219 : detail::line_interpolate::interpolate_segment
0220 <
0221 detail::line_interpolate::convert_and_assign
0222 >
0223 {};
0224
0225 template <typename Geometry, typename Pointlike>
0226 struct line_interpolate<Geometry, Pointlike, segment_tag, multi_point_tag>
0227 : detail::line_interpolate::interpolate_segment
0228 <
0229 detail::line_interpolate::convert_and_push_back
0230 >
0231 {};
0232
0233 }
0234 #endif
0235
0236
0237 namespace resolve_strategy {
0238
0239 template
0240 <
0241 typename Strategies,
0242 bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
0243 >
0244 struct line_interpolate
0245 {
0246 template <typename Geometry, typename Distance, typename Pointlike>
0247 static inline void apply(Geometry const& geometry,
0248 Distance const& max_distance,
0249 Pointlike & pointlike,
0250 Strategies const& strategies)
0251 {
0252 dispatch::line_interpolate
0253 <
0254 Geometry, Pointlike
0255 >::apply(geometry, max_distance, pointlike, strategies);
0256 }
0257 };
0258
0259 template <typename Strategy>
0260 struct line_interpolate<Strategy, false>
0261 {
0262 template <typename Geometry, typename Distance, typename Pointlike>
0263 static inline void apply(Geometry const& geometry,
0264 Distance const& max_distance,
0265 Pointlike & pointlike,
0266 Strategy const& strategy)
0267 {
0268 using strategies::line_interpolate::services::strategy_converter;
0269
0270 dispatch::line_interpolate
0271 <
0272 Geometry, Pointlike
0273 >::apply(geometry, max_distance, pointlike,
0274 strategy_converter<Strategy>::get(strategy));
0275 }
0276 };
0277
0278 template <>
0279 struct line_interpolate<default_strategy, false>
0280 {
0281 template <typename Geometry, typename Distance, typename Pointlike>
0282 static inline void apply(Geometry const& geometry,
0283 Distance const& max_distance,
0284 Pointlike & pointlike,
0285 default_strategy)
0286 {
0287 typedef typename strategies::line_interpolate::services::default_strategy
0288 <
0289 Geometry
0290 >::type strategy_type;
0291
0292 dispatch::line_interpolate
0293 <
0294 Geometry, Pointlike
0295 >::apply(geometry, max_distance, pointlike, strategy_type());
0296 }
0297 };
0298
0299 }
0300
0301
0302 namespace resolve_variant {
0303
0304 template <typename Geometry>
0305 struct line_interpolate
0306 {
0307 template <typename Distance, typename Pointlike, typename Strategy>
0308 static inline void apply(Geometry const& geometry,
0309 Distance const& max_distance,
0310 Pointlike & pointlike,
0311 Strategy const& strategy)
0312 {
0313 return resolve_strategy::line_interpolate
0314 <
0315 Strategy
0316 >::apply(geometry, max_distance, pointlike, strategy);
0317 }
0318 };
0319
0320 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
0321 struct line_interpolate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
0322 {
0323 template <typename Pointlike, typename Strategy>
0324 struct visitor: boost::static_visitor<void>
0325 {
0326 Pointlike const& m_pointlike;
0327 Strategy const& m_strategy;
0328
0329 visitor(Pointlike const& pointlike, Strategy const& strategy)
0330 : m_pointlike(pointlike)
0331 , m_strategy(strategy)
0332 {}
0333
0334 template <typename Geometry, typename Distance>
0335 void operator()(Geometry const& geometry, Distance const& max_distance) const
0336 {
0337 line_interpolate<Geometry>::apply(geometry, max_distance,
0338 m_pointlike, m_strategy);
0339 }
0340 };
0341
0342 template <typename Distance, typename Pointlike, typename Strategy>
0343 static inline void
0344 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
0345 Distance const& max_distance,
0346 Pointlike & pointlike,
0347 Strategy const& strategy)
0348 {
0349 boost::apply_visitor(
0350 visitor<Pointlike, Strategy>(pointlike, strategy),
0351 geometry,
0352 max_distance
0353 );
0354 }
0355 };
0356
0357 }
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392 template
0393 <
0394 typename Geometry,
0395 typename Distance,
0396 typename Pointlike,
0397 typename Strategy
0398 >
0399 inline void line_interpolate(Geometry const& geometry,
0400 Distance const& max_distance,
0401 Pointlike & pointlike,
0402 Strategy const& strategy)
0403 {
0404 concepts::check<Geometry const>();
0405
0406
0407
0408 return resolve_variant::line_interpolate<Geometry>
0409 ::apply(geometry, max_distance, pointlike, strategy);
0410 }
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435 template<typename Geometry, typename Distance, typename Pointlike>
0436 inline void line_interpolate(Geometry const& geometry,
0437 Distance const& max_distance,
0438 Pointlike & pointlike)
0439 {
0440 concepts::check<Geometry const>();
0441
0442
0443
0444 return resolve_variant::line_interpolate<Geometry>
0445 ::apply(geometry, max_distance, pointlike, default_strategy());
0446 }
0447
0448 }}
0449
0450 #endif