diff --git a/include/boost/geometry/algorithms/line_interpolate.hpp b/include/boost/geometry/algorithms/line_interpolate.hpp index bdbc03624..ec2da35bb 100644 --- a/include/boost/geometry/algorithms/line_interpolate.hpp +++ b/include/boost/geometry/algorithms/line_interpolate.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2018-2020 Oracle and/or its affiliates. +// Copyright (c) 2018-2021 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 @@ -20,6 +20,9 @@ #include #include +#include +#include + #include #include #include @@ -27,10 +30,9 @@ #include -#include -#include -#include -#include +#include +#include +#include namespace boost { namespace geometry { @@ -74,12 +76,12 @@ struct interpolate_range typename Range, typename Distance, typename PointLike, - typename Strategy + typename Strategies > static inline void apply(Range const& range, Distance const& max_distance, PointLike & pointlike, - Strategy const& strategy) + Strategies const& strategies) { Policy policy; @@ -100,6 +102,9 @@ struct interpolate_range return; } + auto const pp_strategy = strategies.distance(dummy_point(), dummy_point()); + auto const strategy = strategies.line_interpolate(range); + iterator_t prev = it++; Distance repeated_distance = max_distance; Distance prev_distance = 0; @@ -108,7 +113,7 @@ struct interpolate_range for ( ; it != end ; ++it) { - Distance dist = strategy.get_distance_pp_strategy().apply(*prev, *it); + Distance dist = pp_strategy.apply(*prev, *it); current_distance = prev_distance + dist; while (current_distance >= repeated_distance) @@ -219,41 +224,63 @@ struct line_interpolate namespace resolve_strategy { +template +< + typename Strategies, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct line_interpolate { - template - < - typename Geometry, - typename Distance, - typename Pointlike, - typename Strategy - > + template + static inline void apply(Geometry const& geometry, + Distance const& max_distance, + Pointlike & pointlike, + Strategies const& strategies) + { + dispatch::line_interpolate + < + Geometry, Pointlike + >::apply(geometry, max_distance, pointlike, strategies); + } +}; + +template +struct line_interpolate +{ + template static inline void apply(Geometry const& geometry, Distance const& max_distance, Pointlike & pointlike, Strategy const& strategy) - { - dispatch::line_interpolate::apply(geometry, - max_distance, - pointlike, - strategy); - } + { + using strategies::line_interpolate::services::strategy_converter; + dispatch::line_interpolate + < + Geometry, Pointlike + >::apply(geometry, max_distance, pointlike, + strategy_converter::get(strategy)); + } +}; + +template <> +struct line_interpolate +{ template static inline void apply(Geometry const& geometry, Distance const& max_distance, Pointlike & pointlike, default_strategy) { - typedef typename strategy::line_interpolate::services::default_strategy + typedef typename strategies::line_interpolate::services::default_strategy < - typename cs_tag::type + Geometry >::type strategy_type; - dispatch::line_interpolate::apply(geometry, - max_distance, - pointlike, - strategy_type()); + dispatch::line_interpolate + < + Geometry, Pointlike + >::apply(geometry, max_distance, pointlike, strategy_type()); } }; @@ -271,10 +298,10 @@ struct line_interpolate Pointlike & pointlike, Strategy const& strategy) { - return resolve_strategy::line_interpolate::apply(geometry, - max_distance, - pointlike, - strategy); + return resolve_strategy::line_interpolate + < + Strategy + >::apply(geometry, max_distance, pointlike, strategy); } }; @@ -303,7 +330,7 @@ struct line_interpolate > template static inline void apply(boost::variant const& geometry, - double const& max_distance, + Distance const& max_distance, Pointlike & pointlike, Strategy const& strategy) { @@ -318,7 +345,7 @@ struct line_interpolate > } // namespace resolve_variant /*! -\brief Returns one or more points interpolated along a LineString \brief_strategy +\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 @@ -372,7 +399,7 @@ inline void line_interpolate(Geometry const& geometry, /*! -\brief Returns one or more points interpolated along a LineString. +\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 diff --git a/include/boost/geometry/strategies/geographic/line_interpolate.hpp b/include/boost/geometry/strategies/geographic/line_interpolate.hpp index d5f0e04c9..5f1604714 100644 --- a/include/boost/geometry/strategies/geographic/line_interpolate.hpp +++ b/include/boost/geometry/strategies/geographic/line_interpolate.hpp @@ -101,6 +101,11 @@ public: set_from_radian<1>(p, dir_r.lat2); } + inline Spheroid model() const + { + return m_spheroid; + } + private: Spheroid m_spheroid; }; diff --git a/include/boost/geometry/strategies/line_interpolate/cartesian.hpp b/include/boost/geometry/strategies/line_interpolate/cartesian.hpp new file mode 100644 index 000000000..e2ed7d3c4 --- /dev/null +++ b/include/boost/geometry/strategies/line_interpolate/cartesian.hpp @@ -0,0 +1,78 @@ +// Boost.Geometry + +// Copyright (c) 2021, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_CARTESIAN_HPP +#define BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_CARTESIAN_HPP + + +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace line_interpolate +{ + +template +struct cartesian + : public strategies::detail::cartesian_base +{ + template + static auto distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::distance::pythagoras(); + } + + template + static auto line_interpolate(Geometry const&) + { + return strategy::line_interpolate::cartesian(); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::line_interpolate::cartesian<>; +}; + + +template +struct strategy_converter > +{ + static auto get(strategy::line_interpolate::cartesian const&) + { + return strategies::line_interpolate::cartesian(); + } +}; + + +} // namespace services + +}} // namespace strategies::line_interpolate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_CARTESIAN_HPP diff --git a/include/boost/geometry/strategies/line_interpolate/geographic.hpp b/include/boost/geometry/strategies/line_interpolate/geographic.hpp new file mode 100644 index 000000000..a9e4f1cb9 --- /dev/null +++ b/include/boost/geometry/strategies/line_interpolate/geographic.hpp @@ -0,0 +1,97 @@ +// Boost.Geometry + +// Copyright (c) 2021, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_GEOGRAPHIC_HPP +#define BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_GEOGRAPHIC_HPP + + +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace line_interpolate +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +class geographic + : public strategies::detail::geographic_base +{ + using base_t = strategies::detail::geographic_base; + +public: + geographic() = default; + + explicit geographic(Spheroid const& spheroid) + : base_t(spheroid) + {} + + template + auto distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) const + { + return strategy::distance::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + auto line_interpolate(Geometry const&) const + { + return strategy::line_interpolate::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::line_interpolate::geographic<>; +}; + + +template +struct strategy_converter > +{ + static auto get(strategy::line_interpolate::geographic const& s) + { + return strategies::line_interpolate::geographic(s.model()); + } +}; + + +} // namespace services + +}} // namespace strategies::line_interpolate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_GEOGRAPHIC_HPP diff --git a/include/boost/geometry/strategies/line_interpolate/services.hpp b/include/boost/geometry/strategies/line_interpolate/services.hpp new file mode 100644 index 000000000..95ba215bc --- /dev/null +++ b/include/boost/geometry/strategies/line_interpolate/services.hpp @@ -0,0 +1,54 @@ +// Boost.Geometry + +// Copyright (c) 2021, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_SERVICES_HPP +#define BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_SERVICES_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace line_interpolate +{ + +namespace services +{ + +template +< + typename Geometry, + typename CSTag = typename geometry::cs_tag::type +> +struct default_strategy +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this Geometry's coordinate systems.", + Geometry, CSTag); +}; + +template +struct strategy_converter +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this Strategy.", + Strategy); +}; + + +} // namespace services + +}} // namespace strategies::line_interpolate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_SERVICES_HPP diff --git a/include/boost/geometry/strategies/line_interpolate/spherical.hpp b/include/boost/geometry/strategies/line_interpolate/spherical.hpp new file mode 100644 index 000000000..8a5ec3ef3 --- /dev/null +++ b/include/boost/geometry/strategies/line_interpolate/spherical.hpp @@ -0,0 +1,94 @@ +// Boost.Geometry + +// Copyright (c) 2021, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_SPHERICAL_HPP +#define BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_SPHERICAL_HPP + + +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace line_interpolate +{ + +template +< + typename RadiusTypeOrSphere = double, + typename CalculationType = void +> +class spherical + : public strategies::detail::spherical_base +{ + using base_t = strategies::detail::spherical_base; + +public: + spherical() = default; + + template + explicit spherical(RadiusOrSphere const& radius_or_sphere) + : base_t(radius_or_sphere) + {} + + template + auto distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) const + { + return strategy::distance::haversine + < + typename base_t::radius_type, CalculationType + >(base_t::radius()); + } + + template + auto line_interpolate(Geometry const&) const + { + // NOTE: radius is ignored, but pass it just in case + return strategy::line_interpolate::spherical(base_t::radius()); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::line_interpolate::spherical<>; +}; + + +template +struct strategy_converter > +{ + static auto get(strategy::line_interpolate::spherical const& s) + { + typedef typename strategy::line_interpolate::spherical::radius_type radius_type; + return strategies::line_interpolate::spherical(s.radius()); + } +}; + +} // namespace services + +}} // namespace strategies::line_interpolate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_SPHERICAL_HPP diff --git a/include/boost/geometry/strategies/spherical/line_interpolate.hpp b/include/boost/geometry/strategies/spherical/line_interpolate.hpp index 2d602c0e0..1951787be 100644 --- a/include/boost/geometry/strategies/spherical/line_interpolate.hpp +++ b/include/boost/geometry/strategies/spherical/line_interpolate.hpp @@ -1,8 +1,9 @@ // Boost.Geometry -// Copyright (c) 2018, Oracle and/or its affiliates. +// Copyright (c) 2018-2021, 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 // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -95,6 +96,12 @@ public: calc_t a = angle01 * fraction; formula.compute_point(a, p); } + + inline radius_type radius() const + { + return m_strategy.radius(); + } + private : DistanceStrategy m_strategy; };