summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/line_interpolate.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/algorithms/line_interpolate.hpp')
-rw-r--r--boost/geometry/algorithms/line_interpolate.hpp411
1 files changed, 411 insertions, 0 deletions
diff --git a/boost/geometry/algorithms/line_interpolate.hpp b/boost/geometry/algorithms/line_interpolate.hpp
new file mode 100644
index 0000000000..1de92a0b62
--- /dev/null
+++ b/boost/geometry/algorithms/line_interpolate.hpp
@@ -0,0 +1,411 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2018, 2019 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP
+
+#include <iterator>
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/iterator.hpp>
+#include <boost/range/value_type.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/line_interpolate.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace line_interpolate
+{
+
+struct convert_and_push_back
+{
+ template <typename Range, typename Point>
+ inline void apply(Point const& p, Range& range)
+ {
+ typename boost::range_value<Range>::type p2;
+ geometry::detail::conversion::convert_point_to_point(p, p2);
+ range::push_back(range, p2);
+ }
+};
+
+struct convert_and_assign
+{
+ template <typename Point1, typename Point2>
+ inline void apply(Point1 const& p1, Point2& p2)
+ {
+ geometry::detail::conversion::convert_point_to_point(p1, p2);
+ }
+
+};
+
+
+/*!
+\brief Internal, calculates interpolation point of a linestring using iterator pairs and
+ specified strategy
+*/
+template <typename Policy>
+struct interpolate_range
+{
+ template
+ <
+ typename Range,
+ typename Distance,
+ typename PointLike,
+ typename Strategy
+ >
+ static inline void apply(Range const& range,
+ Distance const& max_distance,
+ PointLike & pointlike,
+ Strategy const& strategy)
+ {
+ Policy policy;
+
+ typedef typename boost::range_iterator<Range const>::type iterator_t;
+ typedef typename boost::range_value<Range const>::type point_t;
+
+ iterator_t it = boost::begin(range);
+ iterator_t end = boost::end(range);
+
+ if (it == end) // empty(range)
+ {
+ BOOST_THROW_EXCEPTION(empty_input_exception());
+ return;
+ }
+ if (max_distance <= 0) //non positive distance
+ {
+ policy.apply(*it, pointlike);
+ return;
+ }
+
+ iterator_t prev = it++;
+ Distance repeated_distance = max_distance;
+ Distance prev_distance = 0;
+ Distance current_distance = 0;
+ point_t start_p = *prev;
+
+ for ( ; it != end ; ++it)
+ {
+ Distance dist = strategy.get_distance_pp_strategy().apply(*prev, *it);
+ current_distance = prev_distance + dist;
+
+ while (current_distance >= repeated_distance)
+ {
+ point_t p;
+ Distance diff_distance = current_distance - prev_distance;
+ BOOST_ASSERT(diff_distance != Distance(0));
+ strategy.apply(start_p, *it,
+ (repeated_distance - prev_distance)/diff_distance,
+ p,
+ diff_distance);
+ policy.apply(p, pointlike);
+ if (boost::is_same<PointLike, point_t>::value)
+ {
+ return;
+ }
+ start_p = p;
+ prev_distance = repeated_distance;
+ repeated_distance += max_distance;
+ }
+ prev_distance = current_distance;
+ prev = it;
+ start_p = *prev;
+ }
+
+ // case when max_distance is larger than linestring's length
+ // return the last point in range (range is not empty)
+ if (repeated_distance == max_distance)
+ {
+ policy.apply(*(end-1), pointlike);
+ }
+ }
+};
+
+template <typename Policy>
+struct interpolate_segment
+{
+ template <typename Segment, typename Distance, typename Pointlike, typename Strategy>
+ static inline void apply(Segment const& segment,
+ Distance const& max_distance,
+ Pointlike & point,
+ Strategy const& strategy)
+ {
+ interpolate_range<Policy>().apply(segment_view<Segment>(segment),
+ max_distance, point, strategy);
+ }
+};
+
+}} // namespace detail::line_interpolate
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Geometry,
+ typename Pointlike,
+ typename Tag1 = typename tag<Geometry>::type,
+ typename Tag2 = typename tag<Pointlike>::type
+>
+struct line_interpolate
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+
+template <typename Geometry, typename Pointlike>
+struct line_interpolate<Geometry, Pointlike, linestring_tag, point_tag>
+ : detail::line_interpolate::interpolate_range
+ <
+ detail::line_interpolate::convert_and_assign
+ >
+{};
+
+template <typename Geometry, typename Pointlike>
+struct line_interpolate<Geometry, Pointlike, linestring_tag, multi_point_tag>
+ : detail::line_interpolate::interpolate_range
+ <
+ detail::line_interpolate::convert_and_push_back
+ >
+{};
+
+template <typename Geometry, typename Pointlike>
+struct line_interpolate<Geometry, Pointlike, segment_tag, point_tag>
+ : detail::line_interpolate::interpolate_segment
+ <
+ detail::line_interpolate::convert_and_assign
+ >
+{};
+
+template <typename Geometry, typename Pointlike>
+struct line_interpolate<Geometry, Pointlike, segment_tag, multi_point_tag>
+ : detail::line_interpolate::interpolate_segment
+ <
+ detail::line_interpolate::convert_and_push_back
+ >
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_strategy {
+
+struct line_interpolate
+{
+ template
+ <
+ typename Geometry,
+ typename Distance,
+ typename Pointlike,
+ typename Strategy
+ >
+ static inline void apply(Geometry const& geometry,
+ Distance const& max_distance,
+ Pointlike & pointlike,
+ Strategy const& strategy)
+ {
+ dispatch::line_interpolate<Geometry, Pointlike>::apply(geometry,
+ max_distance,
+ pointlike,
+ strategy);
+ }
+
+ template <typename Geometry, typename Distance, typename Pointlike>
+ static inline void apply(Geometry const& geometry,
+ Distance const& max_distance,
+ Pointlike & pointlike,
+ default_strategy)
+ {
+ typedef typename strategy::line_interpolate::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type strategy_type;
+
+ dispatch::line_interpolate<Geometry, Pointlike>::apply(geometry,
+ max_distance,
+ pointlike,
+ strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
+namespace resolve_variant {
+
+template <typename Geometry>
+struct line_interpolate
+{
+ template <typename Distance, typename Pointlike, typename Strategy>
+ static inline void apply(Geometry const& geometry,
+ Distance const& max_distance,
+ Pointlike & pointlike,
+ Strategy const& strategy)
+ {
+ return resolve_strategy::line_interpolate::apply(geometry,
+ max_distance,
+ pointlike,
+ strategy);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct line_interpolate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Pointlike, typename Strategy>
+ struct visitor: boost::static_visitor<void>
+ {
+ Pointlike const& m_pointlike;
+ Strategy const& m_strategy;
+
+ visitor(Pointlike const& pointlike, Strategy const& strategy)
+ : m_pointlike(pointlike)
+ , m_strategy(strategy)
+ {}
+
+ template <typename Geometry, typename Distance>
+ void operator()(Geometry const& geometry, Distance const& max_distance) const
+ {
+ line_interpolate<Geometry>::apply(geometry, max_distance,
+ m_pointlike, m_strategy);
+ }
+ };
+
+ template <typename Distance, typename Pointlike, typename Strategy>
+ static inline void
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ double const& max_distance,
+ Pointlike & pointlike,
+ Strategy const& strategy)
+ {
+ boost::apply_visitor(
+ visitor<Pointlike, Strategy>(pointlike, strategy),
+ geometry,
+ max_distance
+ );
+ }
+};
+
+} // namespace resolve_variant
+
+/*!
+\brief Returns one or more points interpolated along a LineString \brief_strategy
+\ingroup line_interpolate
+\tparam Geometry Any type fulfilling a LineString concept
+\tparam Distance A numerical distance measure
+\tparam Pointlike Any type fulfilling Point or Multipoint concept
+\tparam Strategy A type fulfilling a LineInterpolatePointStrategy concept
+\param geometry Input geometry
+\param max_distance Distance threshold (in units depending on coordinate system)
+representing the spacing between the points
+\param pointlike Output: either a Point (exactly one point will be constructed) or
+a MultiPoint (depending on the max_distance one or more points will be constructed)
+\param strategy line_interpolate strategy to be used for interpolation of
+points
+
+\qbk{[include reference/algorithms/line_interpolate.qbk]}
+
+\qbk{distinguish,with strategy}
+
+\qbk{
+[heading Available Strategies]
+\* [link geometry.reference.strategies.strategy_line_interpolate_cartesian Cartesian]
+\* [link geometry.reference.strategies.strategy_line_interpolate_spherical Spherical]
+\* [link geometry.reference.strategies.strategy_line_interpolate_geographic Geographic]
+
+[heading Example]
+[line_interpolate_strategy]
+[line_interpolate_strategy_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.densify densify]
+}
+ */
+template
+<
+ typename Geometry,
+ typename Distance,
+ typename Pointlike,
+ typename Strategy
+>
+inline void line_interpolate(Geometry const& geometry,
+ Distance const& max_distance,
+ Pointlike & pointlike,
+ Strategy const& strategy)
+{
+ concepts::check<Geometry const>();
+
+ // detail::throw_on_empty_input(geometry);
+
+ return resolve_variant::line_interpolate<Geometry>
+ ::apply(geometry, max_distance, pointlike, strategy);
+}
+
+
+/*!
+\brief Returns one or more points interpolated along a LineString.
+\ingroup line_interpolate
+\tparam Geometry Any type fulfilling a LineString concept
+\tparam Distance A numerical distance measure
+\tparam Pointlike Any type fulfilling Point or Multipoint concept
+\param geometry Input geometry
+\param max_distance Distance threshold (in units depending on coordinate system)
+representing the spacing between the points
+\param pointlike Output: either a Point (exactly one point will be constructed) or
+a MultiPoint (depending on the max_distance one or more points will be constructed)
+
+\qbk{[include reference/algorithms/line_interpolate.qbk]
+
+[heading Example]
+[line_interpolate]
+[line_interpolate_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.densify densify]
+}
+ */
+template<typename Geometry, typename Distance, typename Pointlike>
+inline void line_interpolate(Geometry const& geometry,
+ Distance const& max_distance,
+ Pointlike & pointlike)
+{
+ concepts::check<Geometry const>();
+
+ // detail::throw_on_empty_input(geometry);
+
+ return resolve_variant::line_interpolate<Geometry>
+ ::apply(geometry, max_distance, pointlike, default_strategy());
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP