From 5e6f5ee2a131f2fcd83ef96bb6f8307f1e72023c Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Thu, 27 Aug 2020 13:39:10 +0300 Subject: [PATCH 01/55] [algorithms] [strategies] Pass side as strategy to convex hull and use hull_graham_andrew as algorithm --- .../boost/geometry/algorithms/convex_hull.hpp | 59 ++++++++++++------- .../agnostic/hull_graham_andrew.hpp | 8 ++- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/include/boost/geometry/algorithms/convex_hull.hpp b/include/boost/geometry/algorithms/convex_hull.hpp index 26bb8509e..d191f0eb4 100644 --- a/include/boost/geometry/algorithms/convex_hull.hpp +++ b/include/boost/geometry/algorithms/convex_hull.hpp @@ -62,12 +62,21 @@ struct hull_insert // of output-iterator-type, from hull_to_geometry) template static inline OutputIterator apply(Geometry const& geometry, - OutputIterator out, Strategy const& strategy) + OutputIterator out, + Strategy const& strategy) { - typename Strategy::state_type state; + typedef typename strategy::convex_hull::graham_andrew + < + Geometry, + typename point_type::type + > ConvexHullAlgorithm; + + ConvexHullAlgorithm algorithm; + typename ConvexHullAlgorithm::state_type state; + + algorithm.apply(geometry, state, strategy); + algorithm.result(state, out, Order == clockwise, Closure != open); - strategy.apply(geometry, state); - strategy.result(state, out, Order == clockwise, Closure != open); return out; } }; @@ -114,8 +123,9 @@ template struct convex_hull { template - static inline void apply(Box const& box, OutputGeometry& out, - Strategy const& ) + static inline void apply(Box const& box, + OutputGeometry& out, + Strategy const& ) { static bool const Close = geometry::closure::value == closed; @@ -154,7 +164,7 @@ struct convex_hull OutputGeometry& out, Strategy const& strategy) { - BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); + //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); dispatch::convex_hull::apply(geometry, out, strategy); } @@ -163,10 +173,10 @@ struct convex_hull OutputGeometry& out, default_strategy) { - typedef typename strategy_convex_hull< - Geometry, - typename point_type::type - >::type strategy_type; + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type strategy_type; apply(geometry, out, strategy_type()); } @@ -179,7 +189,7 @@ struct convex_hull_insert OutputIterator& out, Strategy const& strategy) { - BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); + //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); return dispatch::convex_hull_insert< geometry::point_order::value, @@ -192,10 +202,10 @@ struct convex_hull_insert OutputIterator& out, default_strategy) { - typedef typename strategy_convex_hull< - Geometry, - typename point_type::type - >::type strategy_type; + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type strategy_type; return apply(geometry, out, strategy_type()); } @@ -210,7 +220,9 @@ template struct convex_hull { template - static inline void apply(Geometry const& geometry, OutputGeometry& out, Strategy const& strategy) + static inline void apply(Geometry const& geometry, + OutputGeometry& out, + Strategy const& strategy) { concepts::check_concepts_and_equal_dimensions< const Geometry, @@ -247,7 +259,8 @@ struct convex_hull > OutputGeometry& out, Strategy const& strategy) { - boost::apply_visitor(visitor(out, strategy), geometry); + boost::apply_visitor(visitor(out, strategy), + geometry); } }; @@ -255,7 +268,9 @@ template struct convex_hull_insert { template - static inline OutputIterator apply(Geometry const& geometry, OutputIterator& out, Strategy const& strategy) + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator& out, + Strategy const& strategy) { // Concept: output point type = point type of input geometry concepts::check(); @@ -339,8 +354,10 @@ template inline OutputIterator convex_hull_insert(Geometry const& geometry, OutputIterator out, Strategy const& strategy) { - return resolve_variant::convex_hull_insert - ::apply(geometry, out, strategy); + return resolve_variant::convex_hull_insert + < + Geometry + >::apply(geometry, out, strategy); } diff --git a/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp b/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp index d948f5240..5ecc3d2a0 100644 --- a/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp +++ b/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp @@ -190,8 +190,10 @@ private: public: typedef partitions state_type; - - inline void apply(InputGeometry const& geometry, partitions& state) const + template + inline void apply(InputGeometry const& geometry, + partitions& state, + Strategy& side) const { // First pass. // Get min/max (in most cases left / right) points @@ -217,7 +219,7 @@ public: container_type lower_points, upper_points; // TODO: User-defiend CS-specific side strategy - typename strategy::side::services::default_strategy::type side; + //typename strategy::side::services::default_strategy::type side; // Bounding left/right points // Second pass, now that extremes are found, assign all points From af7f29166f4d88c5bef24dc5d343b5c8fd121e0f Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Mon, 31 Aug 2020 18:39:50 +0300 Subject: [PATCH 02/55] [strategy] Precise area strategy for cartesian CS --- .../strategy/cartesian/precise_area.hpp | 117 ++++++++++++++++++ include/boost/geometry/util/precise_math.hpp | 4 + 2 files changed, 121 insertions(+) create mode 100644 include/boost/geometry/strategy/cartesian/precise_area.hpp create mode 100644 include/boost/geometry/util/precise_math.hpp diff --git a/include/boost/geometry/strategy/cartesian/precise_area.hpp b/include/boost/geometry/strategy/cartesian/precise_area.hpp new file mode 100644 index 000000000..472deca23 --- /dev/null +++ b/include/boost/geometry/strategy/cartesian/precise_area.hpp @@ -0,0 +1,117 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_AREA_ACCURATE_HPP +#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_AREA_ACCURATE_HPP + +#include + +//#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace area +{ + +/*! +\brief Cartesian area calculation +\ingroup strategies +\details Calculates cartesian area using the trapezoidal rule and precise summation +\tparam CalculationType \tparam_calculation + +\qbk{ +[heading See also] +[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)] +} + +*/ +template +< + typename CalculationType = void +> +class precise_cartesian +{ +public : + template + struct result_type + : strategy::area::detail::result_type + < + Geometry, + CalculationType + > + {}; + + template + class state + { + friend class precise_cartesian; + + typedef typename result_type::type return_type; + + public: + inline state() + : sum1(0) + , sum2(0) + { + // Strategy supports only 2D areas + assert_dimension(); + } + + private: + inline return_type area() const + { + return_type const two = 2; + return (sum1 + sum2) / two; + } + + return_type sum1; + return_type sum2; + }; + + template + static inline void apply(PointOfSegment const& p1, + PointOfSegment const& p2, + state& st) + { + typedef typename state::return_type return_type; + + auto det = (return_type(get<0>(p1)) + return_type(get<0>(p2))) + * (return_type(get<1>(p1)) - return_type(get<1>(p2))); + + auto res = boost::geometry::detail::precise_math::two_sum(st.sum1, det); + + st.sum1 = res[0]; + st.sum2 += res[1]; + } + + template + static inline typename result_type::type + result(state& st) + { + return st.area(); + } + +}; + + +}} // namespace strategy::area + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_ACCURATE_HPP diff --git a/include/boost/geometry/util/precise_math.hpp b/include/boost/geometry/util/precise_math.hpp new file mode 100644 index 000000000..2063f21fb --- /dev/null +++ b/include/boost/geometry/util/precise_math.hpp @@ -0,0 +1,4 @@ +#ifndef PRECISE_MATH_HPP +#define PRECISE_MATH_HPP + +#endif // PRECISE_MATH_HPP From 1a67d84bea64acc26cb7d66667644d97878cf3de Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Mon, 31 Aug 2020 18:43:45 +0300 Subject: [PATCH 03/55] Move precise math in util --- .../cartesian/detail/precise_math.hpp | 614 ----------------- .../strategies/cartesian/in_circle_robust.hpp | 2 +- .../strategies/cartesian/side_robust.hpp | 2 +- .../strategy/cartesian/precise_area.hpp | 2 +- include/boost/geometry/util/precise_math.hpp | 616 +++++++++++++++++- 5 files changed, 616 insertions(+), 620 deletions(-) delete mode 100644 include/boost/geometry/extensions/triangulation/strategies/cartesian/detail/precise_math.hpp diff --git a/include/boost/geometry/extensions/triangulation/strategies/cartesian/detail/precise_math.hpp b/include/boost/geometry/extensions/triangulation/strategies/cartesian/detail/precise_math.hpp deleted file mode 100644 index c70762097..000000000 --- a/include/boost/geometry/extensions/triangulation/strategies/cartesian/detail/precise_math.hpp +++ /dev/null @@ -1,614 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. - -// Contributed and/or modified by Tinko Bartels, -// as part of Google Summer of Code 2019 program. - -// 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_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP -#define BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP - -#include -#include -#include -#include - -#include - -// The following code is based on "Adaptive Precision Floating-Point Arithmetic -// and Fast Robust Geometric Predicates" by Richard Shewchuk, -// J. Discrete Comput Geom (1997) 18: 305. https://doi.org/10.1007/PL00009321 - -namespace boost { namespace geometry -{ - -namespace detail { namespace precise_math -{ - -// See Theorem 6, page 6 -template -< - typename RealNumber -> -inline std::array fast_two_sum(RealNumber const a, - RealNumber const b) -{ - RealNumber x = a + b; - RealNumber b_virtual = x - a; - return {{x, b - b_virtual}}; -} - -// See Theorem 7, page 7 - 8 -template -< - typename RealNumber -> -inline std::array two_sum(RealNumber const a, - RealNumber const b) -{ - RealNumber x = a + b; - RealNumber b_virtual = x - a; - RealNumber a_virtual = x - b_virtual; - RealNumber b_roundoff = b - b_virtual; - RealNumber a_roundoff = a - a_virtual; - RealNumber y = a_roundoff + b_roundoff; - return {{ x, y }}; -} - -// See bottom of page 8 -template -< - typename RealNumber -> -inline RealNumber two_diff_tail(RealNumber const a, - RealNumber const b, - RealNumber const x) -{ - RealNumber b_virtual = a - x; - RealNumber a_virtual = x + b_virtual; - RealNumber b_roundoff = b_virtual - b; - RealNumber a_roundoff = a - a_virtual; - return a_roundoff + b_roundoff; -} - -// see bottom of page 8 -template -< - typename RealNumber -> -inline std::array two_diff(RealNumber const a, - RealNumber const b) -{ - RealNumber x = a - b; - RealNumber y = two_diff_tail(a, b, x); - return {{ x, y }}; -} - -// see theorem 18, page 19 -template -< - typename RealNumber -> -inline RealNumber two_product_tail(RealNumber const a, - RealNumber const b, - RealNumber const x) -{ - return std::fma(a, b, -x); -} - -// see theorem 18, page 19 -template -< - typename RealNumber -> -inline std::array two_product(RealNumber const a, - RealNumber const b) -{ - RealNumber x = a * b; - RealNumber y = two_product_tail(a, b, x); - return {{ x , y }}; -} - -// see theorem 12, figure 7, page 11 - 12, -// this is the 2 by 2 case for the corresponding diff-method -// note that this method takes input in descending order of magnitude and -// returns components in ascending order of magnitude -template -< - typename RealNumber -> -inline std::array two_two_expansion_diff( - std::array const a, - std::array const b) -{ - std::array h; - std::array Qh = two_diff(a[1], b[1]); - h[0] = Qh[1]; - Qh = two_sum( a[0], Qh[0] ); - RealNumber _j = Qh[0]; - Qh = two_diff(Qh[1], b[0]); - h[1] = Qh[1]; - Qh = two_sum( _j, Qh[0] ); - h[2] = Qh[1]; - h[3] = Qh[0]; - return h; -} - -// see theorem 13, figure 8. This implementation uses zero elimination as -// suggested on page 17, second to last paragraph. Returns the number of -// non-zero components in the result and writes the result to h. -// the merger into a single sequence g is done implicitly -template -< - typename RealNumber, - std::size_t InSize1, - std::size_t InSize2, - std::size_t OutSize -> -inline int fast_expansion_sum_zeroelim( - std::array const& e, - std::array const& f, - std::array & h, - int m = InSize1, - int n = InSize2) -{ - std::array Qh; - int i_e = 0, i_f = 0, i_h = 0; - if (std::abs(f[0]) > std::abs(e[0])) - { - Qh[0] = e[i_e++]; - } - else - { - Qh[0] = f[i_f++]; - } - i_h = 0; - if ((i_e < m) && (i_f < n)) - { - if (std::abs(f[i_f]) > std::abs(e[i_e])) - { - Qh = fast_two_sum(e[i_e++], Qh[0]); - } - else - { - Qh = fast_two_sum(f[i_f++], Qh[0]); - } - if (Qh[1] != 0.0) - { - h[i_h++] = Qh[1]; - } - while ((i_e < m) && (i_f < n)) - { - if (std::abs(f[i_f]) > std::abs(e[i_e])) - { - Qh = two_sum(Qh[0], e[i_e++]); - } - else - { - Qh = two_sum(Qh[0], f[i_f++]); - } - if (Qh[1] != 0.0) - { - h[i_h++] = Qh[1]; - } - } - } - while (i_e < m) - { - Qh = two_sum(Qh[0], e[i_e++]); - if (Qh[1] != 0.0) - { - h[i_h++] = Qh[1]; - } - } - while (i_f < n) - { - Qh = two_sum(Qh[0], f[i_f++]); - if (Qh[1] != 0.0) - { - h[i_h++] = Qh[1]; - } - } - if ((Qh[0] != 0.0) || (i_h == 0)) - { - h[i_h++] = Qh[0]; - } - return i_h; -} - -// see theorem 19, figure 13, page 20 - 21. This implementation uses zero -// elimination as suggested on page 17, second to last paragraph. Returns the -// number of non-zero components in the result and writes the result to h. -template -< - typename RealNumber, - std::size_t InSize -> -inline int scale_expansion_zeroelim( - std::array const& e, - RealNumber const b, - std::array & h, - int e_non_zeros = InSize) -{ - std::array Qh = two_product(e[0], b); - int i_h = 0; - if (Qh[1] != 0) - { - h[i_h++] = Qh[1]; - } - for (int i_e = 1; i_e < e_non_zeros; i_e++) - { - std::array Tt = two_product(e[i_e], b); - Qh = two_sum(Qh[0], Tt[1]); - if (Qh[1] != 0) - { - h[i_h++] = Qh[1]; - } - Qh = fast_two_sum(Tt[0], Qh[0]); - if (Qh[1] != 0) - { - h[i_h++] = Qh[1]; - } - } - if ((Qh[0] != 0.0) || (i_h == 0)) - { - h[i_h++] = Qh[0]; - } - return i_h; -} - -template -struct vec2d -{ - RealNumber x; - RealNumber y; -}; - -template -< - typename RealNumber, - std::size_t Robustness -> -inline RealNumber orient2dtail(vec2d const& p1, - vec2d const& p2, - vec2d const& p3, - std::array& t1, - std::array& t2, - std::array& t3, - std::array& t4, - std::array& t5_01, - std::array& t6_01, - RealNumber const& magnitude - ) -{ - t5_01[1] = two_product_tail(t1[0], t2[0], t5_01[0]); - t6_01[1] = two_product_tail(t3[0], t4[0], t6_01[0]); - std::array tA_03 = two_two_expansion_diff(t5_01, t6_01); - RealNumber det = std::accumulate(tA_03.begin(), tA_03.end(), static_cast(0)); - if(Robustness == 1) return det; - // see p.39, mind the different definition of epsilon for error bound - RealNumber B_relative_bound = - (1 + 3 * std::numeric_limits::epsilon()) - * std::numeric_limits::epsilon(); - RealNumber absolute_bound = B_relative_bound * magnitude; - if (std::abs(det) >= absolute_bound) - { - return det; //B estimate - } - t1[1] = two_diff_tail(p1.x, p3.x, t1[0]); - t2[1] = two_diff_tail(p2.y, p3.y, t2[0]); - t3[1] = two_diff_tail(p1.y, p3.y, t3[0]); - t4[1] = two_diff_tail(p2.x, p3.x, t4[0]); - - if ((t1[1] == 0) && (t3[1] == 0) && (t2[1] == 0) && (t4[1] == 0)) - { - return det; //If all tails are zero, there is noething else to compute - } - RealNumber sub_bound = - (1.5 + 2 * std::numeric_limits::epsilon()) - * std::numeric_limits::epsilon(); - // see p.39, mind the different definition of epsilon for error bound - RealNumber C_relative_bound = - (2.25 + 8 * std::numeric_limits::epsilon()) - * std::numeric_limits::epsilon() - * std::numeric_limits::epsilon(); - absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det); - det += (t1[0] * t2[1] + t2[0] * t1[1]) - (t3[0] * t4[1] + t4[0] * t3[1]); - if (Robustness == 2 || std::abs(det) >= absolute_bound) - { - return det; //C estimate - } - std::array D_left; - int D_left_nz; - { - std::array t5_23 = two_product(t1[1], t2[0]); - std::array t6_23 = two_product(t3[1], t4[0]); - std::array tA_47 = two_two_expansion_diff(t5_23, t6_23); - D_left_nz = fast_expansion_sum_zeroelim(tA_03, tA_47, D_left); - } - std::array D_right; - int D_right_nz; - { - std::array t5_45 = two_product(t1[0], t2[1]); - std::array t6_45 = two_product(t3[0], t4[1]); - std::array tA_8_11 = two_two_expansion_diff(t5_45, t6_45); - std::array t5_67 = two_product(t1[1], t2[1]); - std::array t6_67 = two_product(t3[1], t4[1]); - std::array tA_12_15 = two_two_expansion_diff(t5_67, t6_67); - D_right_nz = fast_expansion_sum_zeroelim(tA_8_11, tA_12_15, D_right); - } - std::array D; - int D_nz = fast_expansion_sum_zeroelim(D_left, D_right, D, D_left_nz, D_right_nz); - // only return component of highest magnitude because we mostly care about the sign. - return(D[D_nz - 1]); -} - -// see page 38, Figure 21 for the calculations, notation follows the notation in the figure. -template -< - typename RealNumber, - std::size_t Robustness = 3 -> -inline RealNumber orient2d(vec2d const& p1, - vec2d const& p2, - vec2d const& p3) -{ - if(Robustness == 0) - { - return (p1.x - p3.x) * (p2.y - p3.y) - (p1.y - p3.y) * (p2.x - p3.x); - } - std::array t1, t2, t3, t4; - t1[0] = p1.x - p3.x; - t2[0] = p2.y - p3.y; - t3[0] = p1.y - p3.y; - t4[0] = p2.x - p3.x; - std::array t5_01, t6_01; - t5_01[0] = t1[0] * t2[0]; - t6_01[0] = t3[0] * t4[0]; - RealNumber det = t5_01[0] - t6_01[0]; - RealNumber const magnitude = std::abs(t5_01[0]) + std::abs(t6_01[0]); - - // see p.39, mind the different definition of epsilon for error bound - RealNumber const A_relative_bound = - (1.5 + 4 * std::numeric_limits::epsilon()) - * std::numeric_limits::epsilon(); - RealNumber absolute_bound = A_relative_bound * magnitude; - if ( std::abs(det) >= absolute_bound ) - { - return det; //A estimate - } - - if ( (t5_01[0] > 0 && t6_01[0] <= 0) || (t5_01[0] < 0 && t6_01[0] >= 0) ) - { - //if diagonal and antidiagonal have different sign, the sign of det is - //obvious - return det; - } - return orient2dtail(p1, p2, p3, t1, t2, t3, t4, t5_01, t6_01, magnitude); -} - -// This method adaptively computes increasingly precise approximations of the following -// determinant using Laplace expansion along the last column. -// det A = -// | p1_x - p4_x p1_y - p4_y ( p1_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 | -// | p2_x - p4_x p2_y - p4_y ( p2_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 | -// | p3_x - p4_x p3_y - p4_y ( p3_x - p4_x ) ^ 2 + ( p3_y - p4_y ) ^ 2 | -// = a_13 * C_13 + a_23 * C_23 + a_33 * C_33 -// where a_ij is the i-j-entry and C_ij is the i_j Cofactor - -template -< - typename RealNumber, - std::size_t Robustness = 2 -> -RealNumber incircle(std::array const& p1, - std::array const& p2, - std::array const& p3, - std::array const& p4) -{ - RealNumber A_11 = p1[0] - p4[0]; - RealNumber A_21 = p2[0] - p4[0]; - RealNumber A_31 = p3[0] - p4[0]; - RealNumber A_12 = p1[1] - p4[1]; - RealNumber A_22 = p2[1] - p4[1]; - RealNumber A_32 = p3[1] - p4[1]; - - std::array A_21_x_A_32, - A_31_x_A_22, - A_31_x_A_12, - A_11_x_A_32, - A_11_x_A_22, - A_21_x_A_12; - A_21_x_A_32[0] = A_21 * A_32; - A_31_x_A_22[0] = A_31 * A_22; - RealNumber A_13 = A_11 * A_11 + A_12 * A_12; - - A_31_x_A_12[0] = A_31 * A_12; - A_11_x_A_32[0] = A_11 * A_32; - RealNumber A_23 = A_21 * A_21 + A_22 * A_22; - - A_11_x_A_22[0] = A_11 * A_22; - A_21_x_A_12[0] = A_21 * A_12; - RealNumber A_33 = A_31 * A_31 + A_32 * A_32; - - RealNumber det = A_13 * (A_21_x_A_32[0] - A_31_x_A_22[0]) - + A_23 * (A_31_x_A_12[0] - A_11_x_A_32[0]) - + A_33 * (A_11_x_A_22[0] - A_21_x_A_12[0]); - if(Robustness == 0) return det; - - RealNumber magnitude = - (std::abs(A_21_x_A_32[0]) + std::abs(A_31_x_A_22[0])) * A_13 - + (std::abs(A_31_x_A_12[0]) + std::abs(A_11_x_A_32[0])) * A_23 - + (std::abs(A_11_x_A_22[0]) + std::abs(A_21_x_A_12[0])) * A_33; - RealNumber A_relative_bound = - (5 + 24 * std::numeric_limits::epsilon()) - * std::numeric_limits::epsilon(); - RealNumber absolute_bound = A_relative_bound * magnitude; - if (std::abs(det) > absolute_bound) - { - return det; - } - // (p2_x - p4_x) * (p3_y - p4_y) - A_21_x_A_32[1] = two_product_tail(A_21, A_32, A_21_x_A_32[0]); - // (p3_x - p4_x) * (p2_y - p4_y) - A_31_x_A_22[1] = two_product_tail(A_31, A_22, A_31_x_A_22[0]); - // (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) - std::array C_13 = two_two_expansion_diff(A_21_x_A_32, A_31_x_A_22); - std::array C_13_x_A11; - // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx ) - int C_13_x_A11_nz = scale_expansion_zeroelim(C_13, A_11, C_13_x_A11); - std::array C_13_x_A11_sq; - // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx ) * (ax - dx) - int C_13_x_A11_sq_nz = scale_expansion_zeroelim(C_13_x_A11, - A_11, - C_13_x_A11_sq, - C_13_x_A11_nz); - - std::array C_13_x_A12; - // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy ) - int C_13_x_A12_nz = scale_expansion_zeroelim(C_13, A_12, C_13_x_A12); - - std::array C_13_x_A12_sq; - // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy ) * ( ay - dy ) - int C_13_x_A12_sq_nz = scale_expansion_zeroelim(C_13_x_A12, A_12, - C_13_x_A12_sq, - C_13_x_A12_nz); - - std::array A_13_x_C13; - // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) - // * ( ( ay - dy ) * ( ay - dy ) + ( ax - dx ) * (ax - dx) ) - int A_13_x_C13_nz = fast_expansion_sum_zeroelim(C_13_x_A11_sq, - C_13_x_A12_sq, - A_13_x_C13, - C_13_x_A11_sq_nz, - C_13_x_A12_sq_nz); - - // (cx - dx) * (ay - dy) - A_31_x_A_12[1] = two_product_tail(A_31, A_12, A_31_x_A_12[0]); - // (ax - dx) * (cy - dy) - A_11_x_A_32[1] = two_product_tail(A_11, A_32, A_11_x_A_32[0]); - // (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) - std::array C_23 = two_two_expansion_diff(A_31_x_A_12, - A_11_x_A_32); - std::array C_23_x_A_21; - // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx ) - int C_23_x_A_21_nz = scale_expansion_zeroelim(C_23, A_21, C_23_x_A_21); - std::array C_23_x_A_21_sq; - // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx ) * ( bx - dx ) - int C_23_x_A_21_sq_nz = scale_expansion_zeroelim(C_23_x_A_21, A_21, - C_23_x_A_21_sq, - C_23_x_A_21_nz); - std::array C_23_x_A_22; - // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy ) - int C_23_x_A_22_nz = scale_expansion_zeroelim(C_23, A_22, C_23_x_A_22); - std::array C_23_x_A_22_sq; - // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy ) * ( by - dy ) - int C_23_x_A_22_sq_nz = scale_expansion_zeroelim(C_23_x_A_22, A_22, - C_23_x_A_22_sq, - C_23_x_A_22_nz); - std::array A_23_x_C_23; - // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) - // * ( ( bx - dx ) * ( bx - dx ) + ( by - dy ) * ( by - dy ) ) - int A_23_x_C_23_nz = fast_expansion_sum_zeroelim(C_23_x_A_21_sq, - C_23_x_A_22_sq, - A_23_x_C_23, - C_23_x_A_21_sq_nz, - C_23_x_A_22_sq_nz); - - // (ax - dx) * (by - dy) - A_11_x_A_22[1] = two_product_tail(A_11, A_22, A_11_x_A_22[0]); - // (bx - dx) * (ay - dy) - A_21_x_A_12[1] = two_product_tail(A_21, A_12, A_21_x_A_12[0]); - // (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) - std::array C_33 = two_two_expansion_diff(A_11_x_A_22, - A_21_x_A_12); - std::array C_33_x_A31; - // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx ) - int C_33_x_A31_nz = scale_expansion_zeroelim(C_33, A_31, C_33_x_A31); - std::array C_33_x_A31_sq; - // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx ) * ( cx - dx ) - int C_33_x_A31_sq_nz = scale_expansion_zeroelim(C_33_x_A31, A_31, - C_33_x_A31_sq, - C_33_x_A31_nz); - std::array C_33_x_A_32; - // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy ) - int C_33_x_A_32_nz = scale_expansion_zeroelim(C_33, A_32, C_33_x_A_32); - std::array C_33_x_A_32_sq; - // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy ) * ( cy - dy ) - int C_33_x_A_32_sq_nz = scale_expansion_zeroelim(C_33_x_A_32, A_32, - C_33_x_A_32_sq, - C_33_x_A_32_nz); - - std::array A_33_x_C_33; - int A_33_x_C_33_nz = fast_expansion_sum_zeroelim(C_33_x_A31_sq, - C_33_x_A_32_sq, - A_33_x_C_33, - C_33_x_A31_sq_nz, - C_33_x_A_32_sq_nz); - std::array A_13_x_C13_p_A_13_x_C13; - int A_13_x_C13_p_A_13_x_C13_nz = fast_expansion_sum_zeroelim( - A_13_x_C13, A_23_x_C_23, - A_13_x_C13_p_A_13_x_C13, - A_13_x_C13_nz, - A_23_x_C_23_nz); - std::array det_expansion; - int det_expansion_nz = fast_expansion_sum_zeroelim( - A_13_x_C13_p_A_13_x_C13, - A_33_x_C_33, - det_expansion, - A_13_x_C13_p_A_13_x_C13_nz, - A_33_x_C_33_nz); - - det = std::accumulate(det_expansion.begin(), - det_expansion.begin() + det_expansion_nz, - static_cast(0)); - if(Robustness == 1) return det; - RealNumber B_relative_bound = - (2 + 12 * std::numeric_limits::epsilon()) - * std::numeric_limits::epsilon(); - absolute_bound = B_relative_bound * magnitude; - if (std::abs(det) >= absolute_bound) - { - return det; - } - RealNumber A_11tail = two_diff_tail(p1[0], p4[0], A_11); - RealNumber A_12tail = two_diff_tail(p1[1], p4[1], A_12); - RealNumber A_21tail = two_diff_tail(p2[0], p4[0], A_21); - RealNumber A_22tail = two_diff_tail(p2[1], p4[1], A_22); - RealNumber A_31tail = two_diff_tail(p3[0], p4[0], A_31); - RealNumber A_32tail = two_diff_tail(p3[1], p4[1], A_32); - if ((A_11tail == 0) && (A_21tail == 0) && (A_31tail == 0) - && (A_12tail == 0) && (A_22tail == 0) && (A_32tail == 0)) - { - return det; - } - // RealNumber sub_bound = (1.5 + 2.0 * std::numeric_limits::epsilon()) - // * std::numeric_limits::epsilon(); - // RealNumber C_relative_bound = (11.0 + 72.0 * std::numeric_limits::epsilon()) - // * std::numeric_limits::epsilon() - // * std::numeric_limits::epsilon(); - //absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det); - det += ((A_11 * A_11 + A_12 * A_12) * ((A_21 * A_32tail + A_32 * A_21tail) - - (A_22 * A_31tail + A_31 * A_22tail)) - + 2 * (A_11 * A_11tail + A_12 * A_12tail) * (A_21 * A_32 - A_22 * A_31)) - + ((A_21 * A_21 + A_22 * A_22) * ((A_31 * A_12tail + A_12 * A_31tail) - - (A_32 * A_11tail + A_11 * A_32tail)) - + 2 * (A_21 * A_21tail + A_22 * A_22tail) * (A_31 * A_12 - A_32 * A_11)) - + ((A_31 * A_31 + A_32 * A_32) * ((A_11 * A_22tail + A_22 * A_11tail) - - (A_12 * A_21tail + A_21 * A_12tail)) - + 2 * (A_31 * A_31tail + A_32 * A_32tail) * (A_11 * A_22 - A_12 * A_21)); - //if (std::abs(det) >= absolute_bound) - //{ - return det; - //} -} - -}} // namespace detail::precise_math - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP diff --git a/include/boost/geometry/extensions/triangulation/strategies/cartesian/in_circle_robust.hpp b/include/boost/geometry/extensions/triangulation/strategies/cartesian/in_circle_robust.hpp index f5a32edc5..63f70c50d 100644 --- a/include/boost/geometry/extensions/triangulation/strategies/cartesian/in_circle_robust.hpp +++ b/include/boost/geometry/extensions/triangulation/strategies/cartesian/in_circle_robust.hpp @@ -12,7 +12,7 @@ #ifndef BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_IN_CIRCLE_ROBUST_HPP #define BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_IN_CIRCLE_ROBUST_HPP -#include +#include namespace boost { namespace geometry { diff --git a/include/boost/geometry/extensions/triangulation/strategies/cartesian/side_robust.hpp b/include/boost/geometry/extensions/triangulation/strategies/cartesian/side_robust.hpp index 59228c060..ca478048f 100644 --- a/include/boost/geometry/extensions/triangulation/strategies/cartesian/side_robust.hpp +++ b/include/boost/geometry/extensions/triangulation/strategies/cartesian/side_robust.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include namespace boost { namespace geometry { diff --git a/include/boost/geometry/strategy/cartesian/precise_area.hpp b/include/boost/geometry/strategy/cartesian/precise_area.hpp index 472deca23..8ecb55030 100644 --- a/include/boost/geometry/strategy/cartesian/precise_area.hpp +++ b/include/boost/geometry/strategy/cartesian/precise_area.hpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include namespace boost { namespace geometry { diff --git a/include/boost/geometry/util/precise_math.hpp b/include/boost/geometry/util/precise_math.hpp index 2063f21fb..c70762097 100644 --- a/include/boost/geometry/util/precise_math.hpp +++ b/include/boost/geometry/util/precise_math.hpp @@ -1,4 +1,614 @@ -#ifndef PRECISE_MATH_HPP -#define PRECISE_MATH_HPP +// Boost.Geometry (aka GGL, Generic Geometry Library) -#endif // PRECISE_MATH_HPP +// Copyright (c) 2019 Tinko Bartels, Berlin, Germany. + +// Contributed and/or modified by Tinko Bartels, +// as part of Google Summer of Code 2019 program. + +// 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_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP +#define BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP + +#include +#include +#include +#include + +#include + +// The following code is based on "Adaptive Precision Floating-Point Arithmetic +// and Fast Robust Geometric Predicates" by Richard Shewchuk, +// J. Discrete Comput Geom (1997) 18: 305. https://doi.org/10.1007/PL00009321 + +namespace boost { namespace geometry +{ + +namespace detail { namespace precise_math +{ + +// See Theorem 6, page 6 +template +< + typename RealNumber +> +inline std::array fast_two_sum(RealNumber const a, + RealNumber const b) +{ + RealNumber x = a + b; + RealNumber b_virtual = x - a; + return {{x, b - b_virtual}}; +} + +// See Theorem 7, page 7 - 8 +template +< + typename RealNumber +> +inline std::array two_sum(RealNumber const a, + RealNumber const b) +{ + RealNumber x = a + b; + RealNumber b_virtual = x - a; + RealNumber a_virtual = x - b_virtual; + RealNumber b_roundoff = b - b_virtual; + RealNumber a_roundoff = a - a_virtual; + RealNumber y = a_roundoff + b_roundoff; + return {{ x, y }}; +} + +// See bottom of page 8 +template +< + typename RealNumber +> +inline RealNumber two_diff_tail(RealNumber const a, + RealNumber const b, + RealNumber const x) +{ + RealNumber b_virtual = a - x; + RealNumber a_virtual = x + b_virtual; + RealNumber b_roundoff = b_virtual - b; + RealNumber a_roundoff = a - a_virtual; + return a_roundoff + b_roundoff; +} + +// see bottom of page 8 +template +< + typename RealNumber +> +inline std::array two_diff(RealNumber const a, + RealNumber const b) +{ + RealNumber x = a - b; + RealNumber y = two_diff_tail(a, b, x); + return {{ x, y }}; +} + +// see theorem 18, page 19 +template +< + typename RealNumber +> +inline RealNumber two_product_tail(RealNumber const a, + RealNumber const b, + RealNumber const x) +{ + return std::fma(a, b, -x); +} + +// see theorem 18, page 19 +template +< + typename RealNumber +> +inline std::array two_product(RealNumber const a, + RealNumber const b) +{ + RealNumber x = a * b; + RealNumber y = two_product_tail(a, b, x); + return {{ x , y }}; +} + +// see theorem 12, figure 7, page 11 - 12, +// this is the 2 by 2 case for the corresponding diff-method +// note that this method takes input in descending order of magnitude and +// returns components in ascending order of magnitude +template +< + typename RealNumber +> +inline std::array two_two_expansion_diff( + std::array const a, + std::array const b) +{ + std::array h; + std::array Qh = two_diff(a[1], b[1]); + h[0] = Qh[1]; + Qh = two_sum( a[0], Qh[0] ); + RealNumber _j = Qh[0]; + Qh = two_diff(Qh[1], b[0]); + h[1] = Qh[1]; + Qh = two_sum( _j, Qh[0] ); + h[2] = Qh[1]; + h[3] = Qh[0]; + return h; +} + +// see theorem 13, figure 8. This implementation uses zero elimination as +// suggested on page 17, second to last paragraph. Returns the number of +// non-zero components in the result and writes the result to h. +// the merger into a single sequence g is done implicitly +template +< + typename RealNumber, + std::size_t InSize1, + std::size_t InSize2, + std::size_t OutSize +> +inline int fast_expansion_sum_zeroelim( + std::array const& e, + std::array const& f, + std::array & h, + int m = InSize1, + int n = InSize2) +{ + std::array Qh; + int i_e = 0, i_f = 0, i_h = 0; + if (std::abs(f[0]) > std::abs(e[0])) + { + Qh[0] = e[i_e++]; + } + else + { + Qh[0] = f[i_f++]; + } + i_h = 0; + if ((i_e < m) && (i_f < n)) + { + if (std::abs(f[i_f]) > std::abs(e[i_e])) + { + Qh = fast_two_sum(e[i_e++], Qh[0]); + } + else + { + Qh = fast_two_sum(f[i_f++], Qh[0]); + } + if (Qh[1] != 0.0) + { + h[i_h++] = Qh[1]; + } + while ((i_e < m) && (i_f < n)) + { + if (std::abs(f[i_f]) > std::abs(e[i_e])) + { + Qh = two_sum(Qh[0], e[i_e++]); + } + else + { + Qh = two_sum(Qh[0], f[i_f++]); + } + if (Qh[1] != 0.0) + { + h[i_h++] = Qh[1]; + } + } + } + while (i_e < m) + { + Qh = two_sum(Qh[0], e[i_e++]); + if (Qh[1] != 0.0) + { + h[i_h++] = Qh[1]; + } + } + while (i_f < n) + { + Qh = two_sum(Qh[0], f[i_f++]); + if (Qh[1] != 0.0) + { + h[i_h++] = Qh[1]; + } + } + if ((Qh[0] != 0.0) || (i_h == 0)) + { + h[i_h++] = Qh[0]; + } + return i_h; +} + +// see theorem 19, figure 13, page 20 - 21. This implementation uses zero +// elimination as suggested on page 17, second to last paragraph. Returns the +// number of non-zero components in the result and writes the result to h. +template +< + typename RealNumber, + std::size_t InSize +> +inline int scale_expansion_zeroelim( + std::array const& e, + RealNumber const b, + std::array & h, + int e_non_zeros = InSize) +{ + std::array Qh = two_product(e[0], b); + int i_h = 0; + if (Qh[1] != 0) + { + h[i_h++] = Qh[1]; + } + for (int i_e = 1; i_e < e_non_zeros; i_e++) + { + std::array Tt = two_product(e[i_e], b); + Qh = two_sum(Qh[0], Tt[1]); + if (Qh[1] != 0) + { + h[i_h++] = Qh[1]; + } + Qh = fast_two_sum(Tt[0], Qh[0]); + if (Qh[1] != 0) + { + h[i_h++] = Qh[1]; + } + } + if ((Qh[0] != 0.0) || (i_h == 0)) + { + h[i_h++] = Qh[0]; + } + return i_h; +} + +template +struct vec2d +{ + RealNumber x; + RealNumber y; +}; + +template +< + typename RealNumber, + std::size_t Robustness +> +inline RealNumber orient2dtail(vec2d const& p1, + vec2d const& p2, + vec2d const& p3, + std::array& t1, + std::array& t2, + std::array& t3, + std::array& t4, + std::array& t5_01, + std::array& t6_01, + RealNumber const& magnitude + ) +{ + t5_01[1] = two_product_tail(t1[0], t2[0], t5_01[0]); + t6_01[1] = two_product_tail(t3[0], t4[0], t6_01[0]); + std::array tA_03 = two_two_expansion_diff(t5_01, t6_01); + RealNumber det = std::accumulate(tA_03.begin(), tA_03.end(), static_cast(0)); + if(Robustness == 1) return det; + // see p.39, mind the different definition of epsilon for error bound + RealNumber B_relative_bound = + (1 + 3 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon(); + RealNumber absolute_bound = B_relative_bound * magnitude; + if (std::abs(det) >= absolute_bound) + { + return det; //B estimate + } + t1[1] = two_diff_tail(p1.x, p3.x, t1[0]); + t2[1] = two_diff_tail(p2.y, p3.y, t2[0]); + t3[1] = two_diff_tail(p1.y, p3.y, t3[0]); + t4[1] = two_diff_tail(p2.x, p3.x, t4[0]); + + if ((t1[1] == 0) && (t3[1] == 0) && (t2[1] == 0) && (t4[1] == 0)) + { + return det; //If all tails are zero, there is noething else to compute + } + RealNumber sub_bound = + (1.5 + 2 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon(); + // see p.39, mind the different definition of epsilon for error bound + RealNumber C_relative_bound = + (2.25 + 8 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon() + * std::numeric_limits::epsilon(); + absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det); + det += (t1[0] * t2[1] + t2[0] * t1[1]) - (t3[0] * t4[1] + t4[0] * t3[1]); + if (Robustness == 2 || std::abs(det) >= absolute_bound) + { + return det; //C estimate + } + std::array D_left; + int D_left_nz; + { + std::array t5_23 = two_product(t1[1], t2[0]); + std::array t6_23 = two_product(t3[1], t4[0]); + std::array tA_47 = two_two_expansion_diff(t5_23, t6_23); + D_left_nz = fast_expansion_sum_zeroelim(tA_03, tA_47, D_left); + } + std::array D_right; + int D_right_nz; + { + std::array t5_45 = two_product(t1[0], t2[1]); + std::array t6_45 = two_product(t3[0], t4[1]); + std::array tA_8_11 = two_two_expansion_diff(t5_45, t6_45); + std::array t5_67 = two_product(t1[1], t2[1]); + std::array t6_67 = two_product(t3[1], t4[1]); + std::array tA_12_15 = two_two_expansion_diff(t5_67, t6_67); + D_right_nz = fast_expansion_sum_zeroelim(tA_8_11, tA_12_15, D_right); + } + std::array D; + int D_nz = fast_expansion_sum_zeroelim(D_left, D_right, D, D_left_nz, D_right_nz); + // only return component of highest magnitude because we mostly care about the sign. + return(D[D_nz - 1]); +} + +// see page 38, Figure 21 for the calculations, notation follows the notation in the figure. +template +< + typename RealNumber, + std::size_t Robustness = 3 +> +inline RealNumber orient2d(vec2d const& p1, + vec2d const& p2, + vec2d const& p3) +{ + if(Robustness == 0) + { + return (p1.x - p3.x) * (p2.y - p3.y) - (p1.y - p3.y) * (p2.x - p3.x); + } + std::array t1, t2, t3, t4; + t1[0] = p1.x - p3.x; + t2[0] = p2.y - p3.y; + t3[0] = p1.y - p3.y; + t4[0] = p2.x - p3.x; + std::array t5_01, t6_01; + t5_01[0] = t1[0] * t2[0]; + t6_01[0] = t3[0] * t4[0]; + RealNumber det = t5_01[0] - t6_01[0]; + RealNumber const magnitude = std::abs(t5_01[0]) + std::abs(t6_01[0]); + + // see p.39, mind the different definition of epsilon for error bound + RealNumber const A_relative_bound = + (1.5 + 4 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon(); + RealNumber absolute_bound = A_relative_bound * magnitude; + if ( std::abs(det) >= absolute_bound ) + { + return det; //A estimate + } + + if ( (t5_01[0] > 0 && t6_01[0] <= 0) || (t5_01[0] < 0 && t6_01[0] >= 0) ) + { + //if diagonal and antidiagonal have different sign, the sign of det is + //obvious + return det; + } + return orient2dtail(p1, p2, p3, t1, t2, t3, t4, t5_01, t6_01, magnitude); +} + +// This method adaptively computes increasingly precise approximations of the following +// determinant using Laplace expansion along the last column. +// det A = +// | p1_x - p4_x p1_y - p4_y ( p1_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 | +// | p2_x - p4_x p2_y - p4_y ( p2_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 | +// | p3_x - p4_x p3_y - p4_y ( p3_x - p4_x ) ^ 2 + ( p3_y - p4_y ) ^ 2 | +// = a_13 * C_13 + a_23 * C_23 + a_33 * C_33 +// where a_ij is the i-j-entry and C_ij is the i_j Cofactor + +template +< + typename RealNumber, + std::size_t Robustness = 2 +> +RealNumber incircle(std::array const& p1, + std::array const& p2, + std::array const& p3, + std::array const& p4) +{ + RealNumber A_11 = p1[0] - p4[0]; + RealNumber A_21 = p2[0] - p4[0]; + RealNumber A_31 = p3[0] - p4[0]; + RealNumber A_12 = p1[1] - p4[1]; + RealNumber A_22 = p2[1] - p4[1]; + RealNumber A_32 = p3[1] - p4[1]; + + std::array A_21_x_A_32, + A_31_x_A_22, + A_31_x_A_12, + A_11_x_A_32, + A_11_x_A_22, + A_21_x_A_12; + A_21_x_A_32[0] = A_21 * A_32; + A_31_x_A_22[0] = A_31 * A_22; + RealNumber A_13 = A_11 * A_11 + A_12 * A_12; + + A_31_x_A_12[0] = A_31 * A_12; + A_11_x_A_32[0] = A_11 * A_32; + RealNumber A_23 = A_21 * A_21 + A_22 * A_22; + + A_11_x_A_22[0] = A_11 * A_22; + A_21_x_A_12[0] = A_21 * A_12; + RealNumber A_33 = A_31 * A_31 + A_32 * A_32; + + RealNumber det = A_13 * (A_21_x_A_32[0] - A_31_x_A_22[0]) + + A_23 * (A_31_x_A_12[0] - A_11_x_A_32[0]) + + A_33 * (A_11_x_A_22[0] - A_21_x_A_12[0]); + if(Robustness == 0) return det; + + RealNumber magnitude = + (std::abs(A_21_x_A_32[0]) + std::abs(A_31_x_A_22[0])) * A_13 + + (std::abs(A_31_x_A_12[0]) + std::abs(A_11_x_A_32[0])) * A_23 + + (std::abs(A_11_x_A_22[0]) + std::abs(A_21_x_A_12[0])) * A_33; + RealNumber A_relative_bound = + (5 + 24 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon(); + RealNumber absolute_bound = A_relative_bound * magnitude; + if (std::abs(det) > absolute_bound) + { + return det; + } + // (p2_x - p4_x) * (p3_y - p4_y) + A_21_x_A_32[1] = two_product_tail(A_21, A_32, A_21_x_A_32[0]); + // (p3_x - p4_x) * (p2_y - p4_y) + A_31_x_A_22[1] = two_product_tail(A_31, A_22, A_31_x_A_22[0]); + // (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) + std::array C_13 = two_two_expansion_diff(A_21_x_A_32, A_31_x_A_22); + std::array C_13_x_A11; + // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx ) + int C_13_x_A11_nz = scale_expansion_zeroelim(C_13, A_11, C_13_x_A11); + std::array C_13_x_A11_sq; + // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx ) * (ax - dx) + int C_13_x_A11_sq_nz = scale_expansion_zeroelim(C_13_x_A11, + A_11, + C_13_x_A11_sq, + C_13_x_A11_nz); + + std::array C_13_x_A12; + // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy ) + int C_13_x_A12_nz = scale_expansion_zeroelim(C_13, A_12, C_13_x_A12); + + std::array C_13_x_A12_sq; + // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy ) * ( ay - dy ) + int C_13_x_A12_sq_nz = scale_expansion_zeroelim(C_13_x_A12, A_12, + C_13_x_A12_sq, + C_13_x_A12_nz); + + std::array A_13_x_C13; + // ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) + // * ( ( ay - dy ) * ( ay - dy ) + ( ax - dx ) * (ax - dx) ) + int A_13_x_C13_nz = fast_expansion_sum_zeroelim(C_13_x_A11_sq, + C_13_x_A12_sq, + A_13_x_C13, + C_13_x_A11_sq_nz, + C_13_x_A12_sq_nz); + + // (cx - dx) * (ay - dy) + A_31_x_A_12[1] = two_product_tail(A_31, A_12, A_31_x_A_12[0]); + // (ax - dx) * (cy - dy) + A_11_x_A_32[1] = two_product_tail(A_11, A_32, A_11_x_A_32[0]); + // (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) + std::array C_23 = two_two_expansion_diff(A_31_x_A_12, + A_11_x_A_32); + std::array C_23_x_A_21; + // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx ) + int C_23_x_A_21_nz = scale_expansion_zeroelim(C_23, A_21, C_23_x_A_21); + std::array C_23_x_A_21_sq; + // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx ) * ( bx - dx ) + int C_23_x_A_21_sq_nz = scale_expansion_zeroelim(C_23_x_A_21, A_21, + C_23_x_A_21_sq, + C_23_x_A_21_nz); + std::array C_23_x_A_22; + // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy ) + int C_23_x_A_22_nz = scale_expansion_zeroelim(C_23, A_22, C_23_x_A_22); + std::array C_23_x_A_22_sq; + // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy ) * ( by - dy ) + int C_23_x_A_22_sq_nz = scale_expansion_zeroelim(C_23_x_A_22, A_22, + C_23_x_A_22_sq, + C_23_x_A_22_nz); + std::array A_23_x_C_23; + // ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) + // * ( ( bx - dx ) * ( bx - dx ) + ( by - dy ) * ( by - dy ) ) + int A_23_x_C_23_nz = fast_expansion_sum_zeroelim(C_23_x_A_21_sq, + C_23_x_A_22_sq, + A_23_x_C_23, + C_23_x_A_21_sq_nz, + C_23_x_A_22_sq_nz); + + // (ax - dx) * (by - dy) + A_11_x_A_22[1] = two_product_tail(A_11, A_22, A_11_x_A_22[0]); + // (bx - dx) * (ay - dy) + A_21_x_A_12[1] = two_product_tail(A_21, A_12, A_21_x_A_12[0]); + // (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) + std::array C_33 = two_two_expansion_diff(A_11_x_A_22, + A_21_x_A_12); + std::array C_33_x_A31; + // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx ) + int C_33_x_A31_nz = scale_expansion_zeroelim(C_33, A_31, C_33_x_A31); + std::array C_33_x_A31_sq; + // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx ) * ( cx - dx ) + int C_33_x_A31_sq_nz = scale_expansion_zeroelim(C_33_x_A31, A_31, + C_33_x_A31_sq, + C_33_x_A31_nz); + std::array C_33_x_A_32; + // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy ) + int C_33_x_A_32_nz = scale_expansion_zeroelim(C_33, A_32, C_33_x_A_32); + std::array C_33_x_A_32_sq; + // ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy ) * ( cy - dy ) + int C_33_x_A_32_sq_nz = scale_expansion_zeroelim(C_33_x_A_32, A_32, + C_33_x_A_32_sq, + C_33_x_A_32_nz); + + std::array A_33_x_C_33; + int A_33_x_C_33_nz = fast_expansion_sum_zeroelim(C_33_x_A31_sq, + C_33_x_A_32_sq, + A_33_x_C_33, + C_33_x_A31_sq_nz, + C_33_x_A_32_sq_nz); + std::array A_13_x_C13_p_A_13_x_C13; + int A_13_x_C13_p_A_13_x_C13_nz = fast_expansion_sum_zeroelim( + A_13_x_C13, A_23_x_C_23, + A_13_x_C13_p_A_13_x_C13, + A_13_x_C13_nz, + A_23_x_C_23_nz); + std::array det_expansion; + int det_expansion_nz = fast_expansion_sum_zeroelim( + A_13_x_C13_p_A_13_x_C13, + A_33_x_C_33, + det_expansion, + A_13_x_C13_p_A_13_x_C13_nz, + A_33_x_C_33_nz); + + det = std::accumulate(det_expansion.begin(), + det_expansion.begin() + det_expansion_nz, + static_cast(0)); + if(Robustness == 1) return det; + RealNumber B_relative_bound = + (2 + 12 * std::numeric_limits::epsilon()) + * std::numeric_limits::epsilon(); + absolute_bound = B_relative_bound * magnitude; + if (std::abs(det) >= absolute_bound) + { + return det; + } + RealNumber A_11tail = two_diff_tail(p1[0], p4[0], A_11); + RealNumber A_12tail = two_diff_tail(p1[1], p4[1], A_12); + RealNumber A_21tail = two_diff_tail(p2[0], p4[0], A_21); + RealNumber A_22tail = two_diff_tail(p2[1], p4[1], A_22); + RealNumber A_31tail = two_diff_tail(p3[0], p4[0], A_31); + RealNumber A_32tail = two_diff_tail(p3[1], p4[1], A_32); + if ((A_11tail == 0) && (A_21tail == 0) && (A_31tail == 0) + && (A_12tail == 0) && (A_22tail == 0) && (A_32tail == 0)) + { + return det; + } + // RealNumber sub_bound = (1.5 + 2.0 * std::numeric_limits::epsilon()) + // * std::numeric_limits::epsilon(); + // RealNumber C_relative_bound = (11.0 + 72.0 * std::numeric_limits::epsilon()) + // * std::numeric_limits::epsilon() + // * std::numeric_limits::epsilon(); + //absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det); + det += ((A_11 * A_11 + A_12 * A_12) * ((A_21 * A_32tail + A_32 * A_21tail) + - (A_22 * A_31tail + A_31 * A_22tail)) + + 2 * (A_11 * A_11tail + A_12 * A_12tail) * (A_21 * A_32 - A_22 * A_31)) + + ((A_21 * A_21 + A_22 * A_22) * ((A_31 * A_12tail + A_12 * A_31tail) + - (A_32 * A_11tail + A_11 * A_32tail)) + + 2 * (A_21 * A_21tail + A_22 * A_22tail) * (A_31 * A_12 - A_32 * A_11)) + + ((A_31 * A_31 + A_32 * A_32) * ((A_11 * A_22tail + A_22 * A_11tail) + - (A_12 * A_21tail + A_21 * A_12tail)) + + 2 * (A_31 * A_31tail + A_32 * A_32tail) * (A_11 * A_22 - A_12 * A_21)); + //if (std::abs(det) >= absolute_bound) + //{ + return det; + //} +} + +}} // namespace detail::precise_math + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP From 7d76f162077b543b535eae7257a965e4aa504826 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Mon, 31 Aug 2020 18:57:50 +0300 Subject: [PATCH 04/55] [tests] Add inaccurate area test cases --- test/algorithms/area/area.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/algorithms/area/area.cpp b/test/algorithms/area/area.cpp index ce4115049..14e11680a 100644 --- a/test/algorithms/area/area.cpp +++ b/test/algorithms/area/area.cpp @@ -33,6 +33,8 @@ #include +#include + template void test_polygon() { @@ -175,6 +177,34 @@ void test_large_integers() BOOST_CHECK_CLOSE(int_area, double_area, 0.0001); } +struct precise_cartesian : bg::strategies::detail::cartesian_base +{ + template + static auto area(Geometry const&) + { + return bg::strategy::area::precise_cartesian<>(); + } +}; + +void test_inaccurate_cases() +{ + typedef bg::model::point point_type; + + bg::model::polygon poly; + + bg::read_wkt("POLYGON((0.10000000000000001 0.10000000000000001,\ + 0.20000000000000001 0.20000000000000004,\ + 0.79999999999999993 0.80000000000000004,\ + 1.267650600228229e30 1.2676506002282291e30,\ + 0.10000000000000001 0.10000000000000001))", poly); + + double inaccurate = bg::area(poly); + double accurate = bg::area(poly, precise_cartesian()); + + BOOST_CHECK_CLOSE(inaccurate, 0, 0.0001); + BOOST_CHECK_CLOSE(accurate, -0.315, 0.0001); +} + void test_variant() { typedef bg::model::point double_point_type; From 0a2316eb513c0804e0d2334307037bec94d86ae7 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Tue, 1 Sep 2020 16:13:24 +0300 Subject: [PATCH 05/55] [strategy] Precise area strategy details clarification --- include/boost/geometry/strategy/cartesian/precise_area.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/geometry/strategy/cartesian/precise_area.hpp b/include/boost/geometry/strategy/cartesian/precise_area.hpp index 8ecb55030..b0a3ba852 100644 --- a/include/boost/geometry/strategy/cartesian/precise_area.hpp +++ b/include/boost/geometry/strategy/cartesian/precise_area.hpp @@ -29,7 +29,8 @@ namespace strategy { namespace area /*! \brief Cartesian area calculation \ingroup strategies -\details Calculates cartesian area using the trapezoidal rule and precise summation +\details Calculates cartesian area using the trapezoidal rule and precise + summation (useful to increase precision with floating point arithmetic) \tparam CalculationType \tparam_calculation \qbk{ From 9aedfc4987f86da122b6162ff9ca8262632bf187 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Tue, 8 Sep 2020 18:57:42 +0300 Subject: [PATCH 06/55] [algorithms] [strategies] Move Graham Andrew convex hull algorithm to algorithms from agnostic strategies --- .../boost/geometry/algorithms/convex_hull.hpp | 377 +---------------- .../detail/convex_hull/graham_andrew.hpp} | 42 +- .../detail/convex_hull/interface.hpp | 394 ++++++++++++++++++ .../boost/geometry/strategies/strategies.hpp | 1 - 4 files changed, 414 insertions(+), 400 deletions(-) rename include/boost/geometry/{strategies/agnostic/hull_graham_andrew.hpp => algorithms/detail/convex_hull/graham_andrew.hpp} (90%) create mode 100644 include/boost/geometry/algorithms/detail/convex_hull/interface.hpp diff --git a/include/boost/geometry/algorithms/convex_hull.hpp b/include/boost/geometry/algorithms/convex_hull.hpp index d191f0eb4..d23f6a47f 100644 --- a/include/boost/geometry/algorithms/convex_hull.hpp +++ b/include/boost/geometry/algorithms/convex_hull.hpp @@ -4,11 +4,12 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2014, 2015. -// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2015, 2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -20,373 +21,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP #define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include - -#include - -#include -#include -#include - - -namespace boost { namespace geometry -{ - - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace convex_hull -{ - -template -struct hull_insert -{ - - // Member template function (to avoid inconvenient declaration - // of output-iterator-type, from hull_to_geometry) - template - static inline OutputIterator apply(Geometry const& geometry, - OutputIterator out, - Strategy const& strategy) - { - typedef typename strategy::convex_hull::graham_andrew - < - Geometry, - typename point_type::type - > ConvexHullAlgorithm; - - ConvexHullAlgorithm algorithm; - typename ConvexHullAlgorithm::state_type state; - - algorithm.apply(geometry, state, strategy); - algorithm.result(state, out, Order == clockwise, Closure != open); - - return out; - } -}; - -struct hull_to_geometry -{ - template - static inline void apply(Geometry const& geometry, OutputGeometry& out, - Strategy const& strategy) - { - hull_insert - < - geometry::point_order::value, - geometry::closure::value - >::apply(geometry, - range::back_inserter( - // Handle linestring, ring and polygon the same: - detail::as_range - < - typename range_type::type - >(out)), strategy); - } -}; - -}} // namespace detail::convex_hull -#endif // DOXYGEN_NO_DETAIL - - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - - -template -< - typename Geometry, - typename Tag = typename tag::type -> -struct convex_hull - : detail::convex_hull::hull_to_geometry -{}; - -template -struct convex_hull -{ - template - static inline void apply(Box const& box, - OutputGeometry& out, - Strategy const& ) - { - static bool const Close - = geometry::closure::value == closed; - static bool const Reverse - = geometry::point_order::value == counterclockwise; - - // A hull for boxes is trivial. Any strategy is (currently) skipped. - boost::array::type, 4> range; - geometry::detail::assign_box_corners_oriented(box, range); - geometry::append(out, range); - if (BOOST_GEOMETRY_CONDITION(Close)) - { - geometry::append(out, *boost::begin(range)); - } - } -}; - - - -template -struct convex_hull_insert - : detail::convex_hull::hull_insert -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - -namespace resolve_strategy { - -struct convex_hull -{ - template - static inline void apply(Geometry const& geometry, - OutputGeometry& out, - Strategy const& strategy) - { - //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); - dispatch::convex_hull::apply(geometry, out, strategy); - } - - template - static inline void apply(Geometry const& geometry, - OutputGeometry& out, - default_strategy) - { - typedef typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type strategy_type; - - apply(geometry, out, strategy_type()); - } -}; - -struct convex_hull_insert -{ - template - static inline OutputIterator apply(Geometry const& geometry, - OutputIterator& out, - Strategy const& strategy) - { - //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); - - return dispatch::convex_hull_insert< - geometry::point_order::value, - geometry::closure::value - >::apply(geometry, out, strategy); - } - - template - static inline OutputIterator apply(Geometry const& geometry, - OutputIterator& out, - default_strategy) - { - typedef typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type strategy_type; - - return apply(geometry, out, strategy_type()); - } -}; - -} // namespace resolve_strategy - - -namespace resolve_variant { - -template -struct convex_hull -{ - template - static inline void apply(Geometry const& geometry, - OutputGeometry& out, - Strategy const& strategy) - { - concepts::check_concepts_and_equal_dimensions< - const Geometry, - OutputGeometry - >(); - - resolve_strategy::convex_hull::apply(geometry, out, strategy); - } -}; - -template -struct convex_hull > -{ - template - struct visitor: boost::static_visitor - { - OutputGeometry& m_out; - Strategy const& m_strategy; - - visitor(OutputGeometry& out, Strategy const& strategy) - : m_out(out), m_strategy(strategy) - {} - - template - void operator()(Geometry const& geometry) const - { - convex_hull::apply(geometry, m_out, m_strategy); - } - }; - - template - static inline void - apply(boost::variant const& geometry, - OutputGeometry& out, - Strategy const& strategy) - { - boost::apply_visitor(visitor(out, strategy), - geometry); - } -}; - -template -struct convex_hull_insert -{ - template - static inline OutputIterator apply(Geometry const& geometry, - OutputIterator& out, - Strategy const& strategy) - { - // Concept: output point type = point type of input geometry - concepts::check(); - concepts::check::type>(); - - return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy); - } -}; - -template -struct convex_hull_insert > -{ - template - struct visitor: boost::static_visitor - { - OutputIterator& m_out; - Strategy const& m_strategy; - - visitor(OutputIterator& out, Strategy const& strategy) - : m_out(out), m_strategy(strategy) - {} - - template - OutputIterator operator()(Geometry const& geometry) const - { - return convex_hull_insert::apply(geometry, m_out, m_strategy); - } - }; - - template - static inline OutputIterator - apply(boost::variant const& geometry, - OutputIterator& out, - Strategy const& strategy) - { - return boost::apply_visitor(visitor(out, strategy), geometry); - } -}; - -} // namespace resolve_variant - - -template -inline void convex_hull(Geometry const& geometry, - OutputGeometry& out, Strategy const& strategy) -{ - if (geometry::is_empty(geometry)) - { - // Leave output empty - return; - } - - resolve_variant::convex_hull::apply(geometry, out, strategy); -} - - -/*! -\brief \brief_calc{convex hull} -\ingroup convex_hull -\details \details_calc{convex_hull,convex hull}. -\tparam Geometry the input geometry type -\tparam OutputGeometry the output geometry type -\param geometry \param_geometry, input geometry -\param hull \param_geometry \param_set{convex hull} - -\qbk{[include reference/algorithms/convex_hull.qbk]} - */ -template -inline void convex_hull(Geometry const& geometry, - OutputGeometry& hull) -{ - geometry::convex_hull(geometry, hull, default_strategy()); -} - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace convex_hull -{ - - -template -inline OutputIterator convex_hull_insert(Geometry const& geometry, - OutputIterator out, Strategy const& strategy) -{ - return resolve_variant::convex_hull_insert - < - Geometry - >::apply(geometry, out, strategy); -} - - -/*! -\brief Calculate the convex hull of a geometry, output-iterator version -\ingroup convex_hull -\tparam Geometry the input geometry type -\tparam OutputIterator: an output-iterator -\param geometry the geometry to calculate convex hull from -\param out an output iterator outputing points of the convex hull -\note This overloaded version outputs to an output iterator. -In this case, nothing is known about its point-type or - about its clockwise order. Therefore, the input point-type - and order are copied - - */ -template -inline OutputIterator convex_hull_insert(Geometry const& geometry, - OutputIterator out) -{ - return convex_hull_insert(geometry, out, default_strategy()); -} - - -}} // namespace detail::convex_hull -#endif // DOXYGEN_NO_DETAIL - - -}} // namespace boost::geometry - +#include +#include #endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP diff --git a/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp b/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp similarity index 90% rename from include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp rename to include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp index 5ecc3d2a0..c49b721ab 100644 --- a/include/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp +++ b/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp @@ -5,6 +5,7 @@ // This file was modified by Oracle on 2014-2020. // Modifications copyright (c) 2014-2020 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 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -14,8 +15,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP -#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_GRAHAM_ANDREW_HPP +#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_GRAHAM_ANDREW_HPP #include @@ -40,14 +41,10 @@ namespace boost { namespace geometry { -namespace strategy { namespace convex_hull -{ - #ifndef DOXYGEN_NO_DETAIL -namespace detail +namespace detail { namespace convex_hull { - template inline void get_extremes(Geometry const& geometry, Point& left, Point& right, @@ -214,23 +211,20 @@ public: // TODO: User-defined CS-specific less-compare geometry::less less; - detail::get_extremes(geometry, most_left, most_right, less); + detail::convex_hull::get_extremes(geometry, most_left, most_right, less); container_type lower_points, upper_points; - // TODO: User-defiend CS-specific side strategy - //typename strategy::side::services::default_strategy::type side; - // Bounding left/right points // Second pass, now that extremes are found, assign all points // in either lower, either upper - detail::assign_ranges(geometry, most_left, most_right, + detail::convex_hull::assign_ranges(geometry, most_left, most_right, lower_points, upper_points, side); // Sort both collections, first on x(, then on y) - detail::sort(lower_points, less); - detail::sort(upper_points, less); + detail::convex_hull::sort(lower_points, less); + detail::convex_hull::sort(upper_points, less); // And decide which point should be in the final hull build_half_hull<-1>(lower_points, state.m_lower_hull, @@ -306,8 +300,10 @@ private: template - static inline void output_ranges(container_type const& first, container_type const& second, - OutputIterator out, bool closed) + static inline void output_ranges(container_type const& first, + container_type const& second, + OutputIterator out, + bool closed) { std::copy(boost::begin(first), boost::end(first), out); @@ -329,18 +325,8 @@ private: } }; -}} // namespace strategy::convex_hull - - -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS -template -struct strategy_convex_hull -{ - typedef strategy::convex_hull::graham_andrew type; -}; -#endif +} // namespace convex_hull }} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_GRAHAM_ANDREW_HPP diff --git a/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp b/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp new file mode 100644 index 000000000..03b6d4a56 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp @@ -0,0 +1,394 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014, 2015, 2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// 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_CONVEX_HULL_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace convex_hull +{ + +template +struct hull_insert +{ + + // Member template function (to avoid inconvenient declaration + // of output-iterator-type, from hull_to_geometry) + template + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator out, + Strategy const& strategy) + { + typedef graham_andrew + < + Geometry, + typename point_type::type + > ConvexHullAlgorithm; + + ConvexHullAlgorithm algorithm; + typename ConvexHullAlgorithm::state_type state; + + algorithm.apply(geometry, state, strategy); + algorithm.result(state, out, Order == clockwise, Closure != open); + + return out; + } +}; + +struct hull_to_geometry +{ + template + static inline void apply(Geometry const& geometry, OutputGeometry& out, + Strategy const& strategy) + { + hull_insert + < + geometry::point_order::value, + geometry::closure::value + >::apply(geometry, + range::back_inserter( + // Handle linestring, ring and polygon the same: + detail::as_range + < + typename range_type::type + >(out)), strategy); + } +}; + +}} // namespace detail::convex_hull +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Geometry, + typename Tag = typename tag::type +> +struct convex_hull + : detail::convex_hull::hull_to_geometry +{}; + +template +struct convex_hull +{ + template + static inline void apply(Box const& box, + OutputGeometry& out, + Strategy const& ) + { + static bool const Close + = geometry::closure::value == closed; + static bool const Reverse + = geometry::point_order::value == counterclockwise; + + // A hull for boxes is trivial. Any strategy is (currently) skipped. + boost::array::type, 4> range; + geometry::detail::assign_box_corners_oriented(box, range); + geometry::append(out, range); + if (BOOST_GEOMETRY_CONDITION(Close)) + { + geometry::append(out, *boost::begin(range)); + } + } +}; + + + +template +struct convex_hull_insert + : detail::convex_hull::hull_insert +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_strategy { + +struct convex_hull +{ + template + static inline void apply(Geometry const& geometry, + OutputGeometry& out, + Strategy const& strategy) + { + //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); + dispatch::convex_hull::apply(geometry, out, strategy); + } + + template + static inline void apply(Geometry const& geometry, + OutputGeometry& out, + default_strategy) + { + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type strategy_type; + + apply(geometry, out, strategy_type()); + } +}; + +struct convex_hull_insert +{ + template + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator& out, + Strategy const& strategy) + { + //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); + + return dispatch::convex_hull_insert< + geometry::point_order::value, + geometry::closure::value + >::apply(geometry, out, strategy); + } + + template + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator& out, + default_strategy) + { + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type strategy_type; + + return apply(geometry, out, strategy_type()); + } +}; + +} // namespace resolve_strategy + + +namespace resolve_variant { + +template +struct convex_hull +{ + template + static inline void apply(Geometry const& geometry, + OutputGeometry& out, + Strategy const& strategy) + { + concepts::check_concepts_and_equal_dimensions< + const Geometry, + OutputGeometry + >(); + + resolve_strategy::convex_hull::apply(geometry, out, strategy); + } +}; + +template +struct convex_hull > +{ + template + struct visitor: boost::static_visitor + { + OutputGeometry& m_out; + Strategy const& m_strategy; + + visitor(OutputGeometry& out, Strategy const& strategy) + : m_out(out), m_strategy(strategy) + {} + + template + void operator()(Geometry const& geometry) const + { + convex_hull::apply(geometry, m_out, m_strategy); + } + }; + + template + static inline void + apply(boost::variant const& geometry, + OutputGeometry& out, + Strategy const& strategy) + { + boost::apply_visitor(visitor(out, strategy), + geometry); + } +}; + +template +struct convex_hull_insert +{ + template + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator& out, + Strategy const& strategy) + { + // Concept: output point type = point type of input geometry + concepts::check(); + concepts::check::type>(); + + return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy); + } +}; + +template +struct convex_hull_insert > +{ + template + struct visitor: boost::static_visitor + { + OutputIterator& m_out; + Strategy const& m_strategy; + + visitor(OutputIterator& out, Strategy const& strategy) + : m_out(out), m_strategy(strategy) + {} + + template + OutputIterator operator()(Geometry const& geometry) const + { + return convex_hull_insert::apply(geometry, m_out, m_strategy); + } + }; + + template + static inline OutputIterator + apply(boost::variant const& geometry, + OutputIterator& out, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(out, strategy), geometry); + } +}; + +} // namespace resolve_variant + + +template +inline void convex_hull(Geometry const& geometry, + OutputGeometry& out, Strategy const& strategy) +{ + if (geometry::is_empty(geometry)) + { + // Leave output empty + return; + } + + resolve_variant::convex_hull::apply(geometry, out, strategy); +} + + +/*! +\brief \brief_calc{convex hull} +\ingroup convex_hull +\details \details_calc{convex_hull,convex hull}. +\tparam Geometry the input geometry type +\tparam OutputGeometry the output geometry type +\param geometry \param_geometry, input geometry +\param hull \param_geometry \param_set{convex hull} + +\qbk{[include reference/algorithms/convex_hull.qbk]} + */ +template +inline void convex_hull(Geometry const& geometry, + OutputGeometry& hull) +{ + geometry::convex_hull(geometry, hull, default_strategy()); +} + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace convex_hull +{ + + +template +inline OutputIterator convex_hull_insert(Geometry const& geometry, + OutputIterator out, Strategy const& strategy) +{ + return resolve_variant::convex_hull_insert + < + Geometry + >::apply(geometry, out, strategy); +} + + +/*! +\brief Calculate the convex hull of a geometry, output-iterator version +\ingroup convex_hull +\tparam Geometry the input geometry type +\tparam OutputIterator: an output-iterator +\param geometry the geometry to calculate convex hull from +\param out an output iterator outputing points of the convex hull +\note This overloaded version outputs to an output iterator. +In this case, nothing is known about its point-type or + about its clockwise order. Therefore, the input point-type + and order are copied + + */ +template +inline OutputIterator convex_hull_insert(Geometry const& geometry, + OutputIterator out) +{ + return convex_hull_insert(geometry, out, default_strategy()); +} + + +}} // namespace detail::convex_hull +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP diff --git a/include/boost/geometry/strategies/strategies.hpp b/include/boost/geometry/strategies/strategies.hpp index f02b9adbe..e2b6d4ab2 100644 --- a/include/boost/geometry/strategies/strategies.hpp +++ b/include/boost/geometry/strategies/strategies.hpp @@ -112,7 +112,6 @@ #include #include -#include #include #include #include From 79411643aae72a72bda247d44993f35a3861e18a Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Tue, 15 Sep 2020 17:08:05 +0300 Subject: [PATCH 07/55] [strategies] Create cartesian umbrella strategy for convex hull --- .../detail/convex_hull/graham_andrew.hpp | 10 ++-- .../detail/convex_hull/interface.hpp | 11 ++++- .../boost/geometry/strategies/cartesian.hpp | 1 + .../strategies/convex_hull/cartesian.hpp | 49 +++++++++++++++++++ .../strategies/convex_hull/services.hpp | 49 +++++++++++++++++++ .../spherical/side_by_cross_track.hpp | 10 ++++ 6 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 include/boost/geometry/strategies/convex_hull/cartesian.hpp create mode 100644 include/boost/geometry/strategies/convex_hull/services.hpp diff --git a/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp b/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp index c49b721ab..58cd7a763 100644 --- a/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp +++ b/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp @@ -190,7 +190,7 @@ public: template inline void apply(InputGeometry const& geometry, partitions& state, - Strategy& side) const + Strategy& strategy) const { // First pass. // Get min/max (in most cases left / right) points @@ -215,12 +215,14 @@ public: container_type lower_points, upper_points; + auto side_strategy = strategy.side(geometry); + // Bounding left/right points // Second pass, now that extremes are found, assign all points // in either lower, either upper detail::convex_hull::assign_ranges(geometry, most_left, most_right, lower_points, upper_points, - side); + side_strategy); // Sort both collections, first on x(, then on y) detail::convex_hull::sort(lower_points, less); @@ -229,10 +231,10 @@ public: // And decide which point should be in the final hull build_half_hull<-1>(lower_points, state.m_lower_hull, most_left, most_right, - side); + side_strategy); build_half_hull<1>(upper_points, state.m_upper_hull, most_left, most_right, - side); + side_strategy); } diff --git a/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp b/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp index 03b6d4a56..bd2d1dd8e 100644 --- a/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp +++ b/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp @@ -34,9 +34,9 @@ #include -#include -#include +#include #include +#include #include @@ -175,10 +175,17 @@ struct convex_hull OutputGeometry& out, default_strategy) { + /* typedef typename strategy::side::services::default_strategy < typename cs_tag::type >::type strategy_type; + */ + + typedef typename strategies::convex_hull::services::default_strategy + < + Geometry + >::type strategy_type; apply(geometry, out, strategy_type()); } diff --git a/include/boost/geometry/strategies/cartesian.hpp b/include/boost/geometry/strategies/cartesian.hpp index 68e6a96b2..e32afc59c 100644 --- a/include/boost/geometry/strategies/cartesian.hpp +++ b/include/boost/geometry/strategies/cartesian.hpp @@ -12,6 +12,7 @@ #include +#include #include #include diff --git a/include/boost/geometry/strategies/convex_hull/cartesian.hpp b/include/boost/geometry/strategies/convex_hull/cartesian.hpp new file mode 100644 index 000000000..8ad66a850 --- /dev/null +++ b/include/boost/geometry/strategies/convex_hull/cartesian.hpp @@ -0,0 +1,49 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP +#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace convex_hull +{ + +template +struct cartesian : strategies::detail::cartesian_base +{ + template + static auto side(Geometry const&) + { + return strategy::side::side_by_triangle(); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::convex_hull::cartesian<>; +}; + +} // namespace services + +}} // namespace strategies::convex_hull + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP diff --git a/include/boost/geometry/strategies/convex_hull/services.hpp b/include/boost/geometry/strategies/convex_hull/services.hpp new file mode 100644 index 000000000..7dfd42147 --- /dev/null +++ b/include/boost/geometry/strategies/convex_hull/services.hpp @@ -0,0 +1,49 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SERVICES_HPP +#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SERVICES_HPP + + +#include + +#include + + +namespace boost { namespace geometry +{ + + +namespace strategies { namespace convex_hull { + +namespace services +{ + +template +< + typename Geometry, + typename CSTag = typename geometry::cs_tag::type +> +struct default_strategy +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM + , (types) + ); +}; + +} // namespace services + +}} // namespace strategies::convex_hull + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SERVICES_HPP diff --git a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp index 2b195e96f..99e6aad1d 100644 --- a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp @@ -71,9 +71,19 @@ public : calc_t crs_AD = geometry::formula::spherical_azimuth (lon1, lat1, lon, lat).azimuth; + if (crs_AD == 0) + { + return 0; + } + calc_t crs_AB = geometry::formula::spherical_azimuth (lon1, lat1, lon2, lat2).azimuth; + if (crs_AB == 0) + { + return 0; + } + calc_t XTD = asin(sin(d1) * sin(crs_AD - crs_AB)); return math::equals(XTD, 0) ? 0 : XTD < 0 ? 1 : -1; From 1f31c0915cf1f4ecb59f58774212005d5e87e77e Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Tue, 15 Sep 2020 18:23:36 +0300 Subject: [PATCH 08/55] [strategies] Create spherical/geographic umbrella strategies for convex hull --- .../detail/convex_hull/interface.hpp | 11 +-- .../strategies/convex_hull/cartesian.hpp | 3 +- .../strategies/convex_hull/geographic.hpp | 71 +++++++++++++++++++ .../strategies/convex_hull/spherical.hpp | 55 ++++++++++++++ .../boost/geometry/strategies/geographic.hpp | 1 + .../boost/geometry/strategies/spherical.hpp | 1 + 6 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 include/boost/geometry/strategies/convex_hull/geographic.hpp create mode 100644 include/boost/geometry/strategies/convex_hull/spherical.hpp diff --git a/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp b/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp index bd2d1dd8e..47088a4ca 100644 --- a/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp +++ b/include/boost/geometry/algorithms/detail/convex_hull/interface.hpp @@ -175,13 +175,6 @@ struct convex_hull OutputGeometry& out, default_strategy) { - /* - typedef typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type strategy_type; - */ - typedef typename strategies::convex_hull::services::default_strategy < Geometry @@ -211,9 +204,9 @@ struct convex_hull_insert OutputIterator& out, default_strategy) { - typedef typename strategy::side::services::default_strategy + typedef typename strategies::convex_hull::services::default_strategy < - typename cs_tag::type + Geometry >::type strategy_type; return apply(geometry, out, strategy_type()); diff --git a/include/boost/geometry/strategies/convex_hull/cartesian.hpp b/include/boost/geometry/strategies/convex_hull/cartesian.hpp index 8ad66a850..cc5c30c31 100644 --- a/include/boost/geometry/strategies/convex_hull/cartesian.hpp +++ b/include/boost/geometry/strategies/convex_hull/cartesian.hpp @@ -22,8 +22,9 @@ namespace strategies { namespace convex_hull { template -struct cartesian : strategies::detail::cartesian_base +class cartesian : strategies::detail::cartesian_base { +public: template static auto side(Geometry const&) { diff --git a/include/boost/geometry/strategies/convex_hull/geographic.hpp b/include/boost/geometry/strategies/convex_hull/geographic.hpp new file mode 100644 index 000000000..665cd7864 --- /dev/null +++ b/include/boost/geometry/strategies/convex_hull/geographic.hpp @@ -0,0 +1,71 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_GEOGRAPHIC_HPP +#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_GEOGRAPHIC_HPP + + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace convex_hull +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +class geographic : strategies::detail::geographic_base +{ + using base_t = strategies::detail::geographic_base; + +public: + geographic() + : base_t() + {} + + explicit geographic(Spheroid const& spheroid) + : base_t(spheroid) + {} + + template + static auto side(Geometry const&) + { + return strategy::side::geographic + < + FormulaPolicy, + Spheroid, + CalculationType + >(); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::convex_hull::geographic<>; +}; + +} // namespace services + +}} // namespace strategies::convex_hull + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_GEOGRAPHIC_HPP diff --git a/include/boost/geometry/strategies/convex_hull/spherical.hpp b/include/boost/geometry/strategies/convex_hull/spherical.hpp new file mode 100644 index 000000000..acbee9c1b --- /dev/null +++ b/include/boost/geometry/strategies/convex_hull/spherical.hpp @@ -0,0 +1,55 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SPHERICAL_HPP +#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SPHERICAL_HPP + + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace convex_hull +{ + +template +< + typename RadiusTypeOrSphere = double, + typename CalculationType = void +> +class spherical : strategies::detail::spherical_base +{ +public: + template + static auto side(Geometry const&) + { + return strategy::side::spherical_side_formula(); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::convex_hull::spherical<>; +}; + +} // namespace services + +}} // namespace strategies::convex_hull + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_SPHERICAL_HPP diff --git a/include/boost/geometry/strategies/geographic.hpp b/include/boost/geometry/strategies/geographic.hpp index 642fcd798..621d5d725 100644 --- a/include/boost/geometry/strategies/geographic.hpp +++ b/include/boost/geometry/strategies/geographic.hpp @@ -12,6 +12,7 @@ #include +#include #include #include diff --git a/include/boost/geometry/strategies/spherical.hpp b/include/boost/geometry/strategies/spherical.hpp index 9d7ff7dfa..7641723cc 100644 --- a/include/boost/geometry/strategies/spherical.hpp +++ b/include/boost/geometry/strategies/spherical.hpp @@ -12,6 +12,7 @@ #include +#include #include #include From eae06f70dfb2f499810564a636039ec6474c10ac Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Wed, 16 Sep 2020 11:34:26 +0300 Subject: [PATCH 09/55] [tests] Move convex hull tests to new directory and adjust them to use the new strategy --- test/algorithms/Jamfile | 1 + test/algorithms/convex_hull/Jamfile | 15 ++++++ .../{ => convex_hull}/convex_hull.cpp | 2 +- .../{ => convex_hull}/convex_hull_multi.cpp | 2 +- .../{ => convex_hull}/test_convex_hull.hpp | 54 +++++++++++-------- 5 files changed, 51 insertions(+), 23 deletions(-) create mode 100644 test/algorithms/convex_hull/Jamfile rename test/algorithms/{ => convex_hull}/convex_hull.cpp (98%) rename test/algorithms/{ => convex_hull}/convex_hull_multi.cpp (98%) rename test/algorithms/{ => convex_hull}/test_convex_hull.hpp (83%) diff --git a/test/algorithms/Jamfile b/test/algorithms/Jamfile index 0ff096c95..787a56fc5 100644 --- a/test/algorithms/Jamfile +++ b/test/algorithms/Jamfile @@ -67,6 +67,7 @@ test-suite boost-geometry-algorithms build-project area ; build-project buffer ; build-project covered_by ; +build-project convex_hull ; build-project crosses ; build-project detail ; build-project disjoint ; diff --git a/test/algorithms/convex_hull/Jamfile b/test/algorithms/convex_hull/Jamfile new file mode 100644 index 000000000..9413077b1 --- /dev/null +++ b/test/algorithms/convex_hull/Jamfile @@ -0,0 +1,15 @@ +# Boost.Geometry (aka GGL, Generic Geometry Library) +# +# Copyright (c) 2020 Oracle and/or its affiliates. +# +# Contributed and/or modified by Vissarion Fisikopoulos, 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) + +test-suite boost-geometry-algorithms-convex_hull + : + [ run convex_hull.cpp : : : : algorithms_convex_hull ] + [ run convex_hull_multi.cpp : : : : algorithms_convex_hull_multi ] + ; diff --git a/test/algorithms/convex_hull.cpp b/test/algorithms/convex_hull/convex_hull.cpp similarity index 98% rename from test/algorithms/convex_hull.cpp rename to test/algorithms/convex_hull/convex_hull.cpp index 0ca1bcb7b..936d5ab79 100644 --- a/test/algorithms/convex_hull.cpp +++ b/test/algorithms/convex_hull/convex_hull.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include "test_convex_hull.hpp" #include #include diff --git a/test/algorithms/convex_hull_multi.cpp b/test/algorithms/convex_hull/convex_hull_multi.cpp similarity index 98% rename from test/algorithms/convex_hull_multi.cpp rename to test/algorithms/convex_hull/convex_hull_multi.cpp index eaf0ddc8d..32dddafb0 100644 --- a/test/algorithms/convex_hull_multi.cpp +++ b/test/algorithms/convex_hull/convex_hull_multi.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include "test_convex_hull.hpp" #include #include diff --git a/test/algorithms/test_convex_hull.hpp b/test/algorithms/convex_hull/test_convex_hull.hpp similarity index 83% rename from test/algorithms/test_convex_hull.hpp rename to test/algorithms/convex_hull/test_convex_hull.hpp index a3ab82df4..f0668ba05 100644 --- a/test/algorithms/test_convex_hull.hpp +++ b/test/algorithms/convex_hull/test_convex_hull.hpp @@ -104,35 +104,45 @@ void test_convex_hull(Geometry const& geometry, bool const is_original_closed = resolve_variant::get_closure(geometry) != bg::open; static bool const is_hull_closed = bg::closure::value != bg::open; - // convex_hull_insert() uses the original Geometry as a source of the info about the order and closure - std::size_t const size_hull_from_orig = is_original_closed ? size_hull_closed : size_hull_closed - 1; - std::size_t const size_hull = is_hull_closed ? size_hull_closed : size_hull_closed - 1; + // convex_hull_insert() uses the original Geometry as a source of the info + // about the order and closure + std::size_t const size_hull_from_orig = is_original_closed ? + size_hull_closed : size_hull_closed - 1; + std::size_t const size_hull = is_hull_closed ? size_hull_closed : + size_hull_closed - 1; Hull hull; // Test version with output iterator - bg::detail::convex_hull::convex_hull_insert(geometry, std::back_inserter(hull.outer())); - check_convex_hull(geometry, hull, size_original, size_hull_from_orig, expected_area, expected_perimeter, reverse); + bg::detail::convex_hull::convex_hull_insert(geometry, + std::back_inserter(hull.outer())); + check_convex_hull(geometry, hull, size_original, size_hull_from_orig, + expected_area, expected_perimeter, reverse); // Test version with ring as output bg::clear(hull); bg::convex_hull(geometry, hull.outer()); - check_convex_hull(geometry, hull, size_original, size_hull, expected_area, expected_perimeter, false); + check_convex_hull(geometry, hull, size_original, size_hull, expected_area, + expected_perimeter, false); // Test version with polygon as output bg::clear(hull); bg::convex_hull(geometry, hull); - check_convex_hull(geometry, hull, size_original, size_hull, expected_area, expected_perimeter, false); + check_convex_hull(geometry, hull, size_original, size_hull, expected_area, + expected_perimeter, false); // Test version with strategy bg::clear(hull); bg::convex_hull(geometry, hull.outer(), Strategy()); - check_convex_hull(geometry, hull, size_original, size_hull, expected_area, expected_perimeter, false); + check_convex_hull(geometry, hull, size_original, size_hull, expected_area, + expected_perimeter, false); // Test version with output iterator and strategy bg::clear(hull); - bg::detail::convex_hull::convex_hull_insert(geometry, std::back_inserter(hull.outer()), Strategy()); - check_convex_hull(geometry, hull, size_original, size_hull_from_orig, expected_area, expected_perimeter, reverse); + bg::detail::convex_hull::convex_hull_insert(geometry, + std::back_inserter(hull.outer()), Strategy()); + check_convex_hull(geometry, hull, size_original, size_hull_from_orig, + expected_area, expected_perimeter, reverse); } @@ -148,18 +158,16 @@ void test_geometry_order(std::string const& wkt, Closed > hull_type; - typedef bg::strategy::convex_hull::graham_andrew - < - Geometry, - typename bg::point_type::type - > strategy_type; + typedef boost::geometry::strategies::convex_hull::cartesian<> strategy_type; Geometry geometry; bg::read_wkt(wkt, geometry); boost::variant v(geometry); - test_convex_hull(geometry, size_original, size_hull_closed, expected_area, expected_perimeter, !Clockwise); - test_convex_hull(v, size_original, size_hull_closed, expected_area, expected_perimeter, !Clockwise); + test_convex_hull(geometry, size_original, + size_hull_closed, expected_area, expected_perimeter, !Clockwise); + test_convex_hull(v, size_original, + size_hull_closed, expected_area, expected_perimeter, !Clockwise); } template @@ -167,10 +175,14 @@ void test_geometry(std::string const& wkt, std::size_t size_original, std::size_t size_hull_closed, double expected_area, double expected_perimeter = -1.0) { - test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); + test_geometry_order(wkt, size_original, + size_hull_closed, expected_area, expected_perimeter); + test_geometry_order(wkt, size_original, + size_hull_closed, expected_area, expected_perimeter); + test_geometry_order(wkt, size_original, + size_hull_closed, expected_area, expected_perimeter); + test_geometry_order(wkt, size_original, + size_hull_closed, expected_area, expected_perimeter); } template From 6873db554909c4468c81d53b4f968596c444c375 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Wed, 23 Sep 2020 12:44:41 +0300 Subject: [PATCH 10/55] [tests] Convex hull non cartesian tests added --- .../geometry/strategies/geographic/side.hpp | 7 ++ test/algorithms/convex_hull/Jamfile | 1 + test/algorithms/convex_hull/convex_hull.cpp | 20 +++--- .../convex_hull/convex_hull_multi.cpp | 27 +++++--- .../convex_hull/convex_hull_sph_geo.cpp | 69 +++++++++++++++++++ .../convex_hull/test_convex_hull.hpp | 38 ++++++---- 6 files changed, 130 insertions(+), 32 deletions(-) create mode 100644 test/algorithms/convex_hull/convex_hull_sph_geo.cpp diff --git a/include/boost/geometry/strategies/geographic/side.hpp b/include/boost/geometry/strategies/geographic/side.hpp index bbcf64f82..67080d725 100644 --- a/include/boost/geometry/strategies/geographic/side.hpp +++ b/include/boost/geometry/strategies/geographic/side.hpp @@ -27,6 +27,8 @@ #include #include +#include + #include #include @@ -120,6 +122,11 @@ public: typedef typename FormulaPolicy::template inverse inverse_formula; + if (geometry::equals(p, p1) || geometry::equals(p, p2)) + { + return 0; + } + calc_t a1p = azimuth(p1, p, m_model); calc_t a12 = azimuth(p1, p2, m_model); diff --git a/test/algorithms/convex_hull/Jamfile b/test/algorithms/convex_hull/Jamfile index 9413077b1..e13d9a1b2 100644 --- a/test/algorithms/convex_hull/Jamfile +++ b/test/algorithms/convex_hull/Jamfile @@ -12,4 +12,5 @@ test-suite boost-geometry-algorithms-convex_hull : [ run convex_hull.cpp : : : : algorithms_convex_hull ] [ run convex_hull_multi.cpp : : : : algorithms_convex_hull_multi ] + [ run convex_hull_sph_geo.cpp : : : : algorithms_convex_hull_sph_geo ] ; diff --git a/test/algorithms/convex_hull/convex_hull.cpp b/test/algorithms/convex_hull/convex_hull.cpp index 936d5ab79..b854c2695 100644 --- a/test/algorithms/convex_hull/convex_hull.cpp +++ b/test/algorithms/convex_hull/convex_hull.cpp @@ -29,43 +29,45 @@ template void test_all() { + typedef boost::geometry::strategies::convex_hull::cartesian<> strategy; + // from sample linestring - test_geometry >( + test_geometry, strategy >( "linestring(1.1 1.1, 2.5 2.1, 3.1 3.1, 4.9 1.1, 3.1 1.9)", 5, 4, 3.8); // rectangular, with concavity - test_geometry >( + test_geometry, strategy >( "polygon((1 1, 1 4, 3 4, 3 3, 4 3, 4 4, 5 4, 5 1, 1 1))", 9, 5, 12.0); // from sample polygon, with concavity - test_geometry >( + test_geometry, strategy >( "polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,3.4 2.0, 4.1 3.0" ", 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))", 12, 8, 5.245); - test_geometry >( + test_geometry, strategy >( "polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,3.4 2.0, 4.1 3.0" ", 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))", 12, 8, 5.245); - test_geometry >("box(0 0,2 2)", 4, 5, 4); + test_geometry, strategy >("box(0 0,2 2)", 4, 5, 4); // https://svn.boost.org/trac/boost/ticket/6443 { - test_geometry >( + test_geometry, strategy >( "polygon((0 0, 2 0))", // note that this polygon is very invalid 2, 4, 0, 4); } // degenerated hulls - test_geometry >( + test_geometry, strategy >( "multipoint(0 0)", 1, 4, 0, 0); - test_geometry >( + test_geometry, strategy >( "multipoint(0 0, 2 0)", 2, 4, 0, 4); - test_geometry >( + test_geometry, strategy >( "linestring(0 0, 2 0)", 2, 4, 0, 4); diff --git a/test/algorithms/convex_hull/convex_hull_multi.cpp b/test/algorithms/convex_hull/convex_hull_multi.cpp index 32dddafb0..e3b0ad68f 100644 --- a/test/algorithms/convex_hull/convex_hull_multi.cpp +++ b/test/algorithms/convex_hull/convex_hull_multi.cpp @@ -43,33 +43,38 @@ template void test_all() { + typedef boost::geometry::strategies::convex_hull::cartesian<> strategy; + typedef bg::model::multi_point

mp; typedef bg::model::multi_linestring > ml; typedef bg::model::multi_polygon > mpoly; // All points below in upper-points and lower-points - test_geometry("MULTIPOINT((0 0),(5 0),(1 1),(4 1))", 0, 5, 4.0); - test_geometry("MULTIPOINT((0 1),(5 1),(1 0),(4 0))", 0, 5, 4.0); + test_geometry("MULTIPOINT((0 0),(5 0),(1 1),(4 1))", 0, 5, 4.0); + test_geometry("MULTIPOINT((0 1),(5 1),(1 0),(4 0))", 0, 5, 4.0); - // All points in vertical line (this delivers an empty polygon with 3 points and closing point for closed) - test_geometry("MULTIPOINT((1 0),(5 0),(3 0),(4 0),(2 0))", 0, 4, 0.0); + // All points in vertical line (this delivers an empty polygon with 3 points + // and closing point for closed) + test_geometry("MULTIPOINT((1 0),(5 0),(3 0),(4 0),(2 0))", 0, 4, 0.0); // One point only - test_geometry("MULTIPOINT((1 0))", 0, 4, 0.0); + test_geometry("MULTIPOINT((1 0))", 0, 4, 0.0); // Problem of 6019, reproduced by the convex hull robustness test: - test_geometry("MULTIPOINT((2 9),(1 3),(9 4),(1 1),(1 0),(7 9),(2 5),(3 7),(3 6),(2 4))", + test_geometry("MULTIPOINT((2 9),(1 3),(9 4),(1 1),(1 0),(7 9),(2 5),(3 7),(3 6),(2 4))", 0, 6, 48.0); // Ticket 6019: - test_geometry("MULTIPOINT((0 53),(0 103),(0 53),(0 3),(0 3),(0 0),(1 0),(1 1),(2 1),(2 0),(2 0),(2 0),(3 0),(3 1),(4 1),(4 0),(5 0),(0 3),(10 3),(10 2),(10 2),(10 2),(5 2),(5 0),(5 0),(55 0),(105 0))", + test_geometry("MULTIPOINT((0 53),(0 103),(0 53),(0 3),(0 3),(0 0),(1 0),\ + (1 1),(2 1),(2 0),(2 0),(2 0),(3 0),(3 1),(4 1),(4 0),(5 0),(0 3),\ + (10 3),(10 2),(10 2),(10 2),(5 2),(5 0),(5 0),(55 0),(105 0))", 0, 4, 5407.5); // Ticket 6021: - test_geometry("multipoint((0 53), (0 103), (1 53))", 3, 4, 25); + test_geometry("multipoint((0 53), (0 103), (1 53))", 3, 4, 25); - test_geometry("multipoint((1.1 1.1), (2.5 2.1), (3.1 3.1), (4.9 1.1), (3.1 1.9))", 5, 4, 3.8); - test_geometry("multilinestring((2 4, 3 4, 3 5), (4 3,4 4,5 4))", 6, 5, 3.0); - test_geometry("multipolygon(((1 4,1 6,2 5,3 5,4 6,4 4,1 4)), ((4 2,4 3,6 3,6 2,4 2)))", 12, 7, 14.0); + test_geometry("multipoint((1.1 1.1), (2.5 2.1), (3.1 3.1), (4.9 1.1), (3.1 1.9))", 5, 4, 3.8); + test_geometry("multilinestring((2 4, 3 4, 3 5), (4 3,4 4,5 4))", 6, 5, 3.0); + test_geometry("multipolygon(((1 4,1 6,2 5,3 5,4 6,4 4,1 4)), ((4 2,4 3,6 3,6 2,4 2)))", 12, 7, 14.0); test_empty_input(); test_empty_input(); diff --git a/test/algorithms/convex_hull/convex_hull_sph_geo.cpp b/test/algorithms/convex_hull/convex_hull_sph_geo.cpp new file mode 100644 index 000000000..33dfef803 --- /dev/null +++ b/test/algorithms/convex_hull/convex_hull_sph_geo.cpp @@ -0,0 +1,69 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2020 Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fisikopoulos, 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) + +#include +#include + +#include "test_convex_hull.hpp" + +#include +#include + + +void test_all() +{ + typedef bg::model::point > + SphericalPoint; + typedef bg::model::point > GeoPoint; + + test_geometry_sph_geo + < + bg::model::polygon, + bg::model::polygon + >("polygon((0 0,2 1,2 -1,0 0))", 4, 4, + 0.00060931217091786914, 24621363089.253811); + + test_geometry_sph_geo + < + bg::model::polygon, + bg::model::polygon + >("polygon((0 0,1 1,0 1,0 0))", 4, 4, + 0.00015229324228191774, 6153992621.4098225); + + //polygon crossing antimeridian + test_geometry_sph_geo + < + bg::model::polygon, + bg::model::polygon + >("polygon((359 0,1 1,1 -1,359 0))", 4, 4, + 0.00060931217091786914, 24621363089.253811); + + test_geometry_sph_geo + < + bg::model::polygon, + bg::model::polygon + >("polygon((1 1, 1 4, 3 4, 3 3, 4 3, 4 4, 5 4, 5 1, 1 1))", + 9, 5, 0.003652987070377825, 147615606532.65408); + + test_empty_input>(); + test_empty_input>(); + test_empty_input>(); + + test_empty_input>(); + test_empty_input>(); + test_empty_input>(); +} + +int test_main(int, char* []) +{ + test_all(); + + return 0; +} diff --git a/test/algorithms/convex_hull/test_convex_hull.hpp b/test/algorithms/convex_hull/test_convex_hull.hpp index f0668ba05..2c1266134 100644 --- a/test/algorithms/convex_hull/test_convex_hull.hpp +++ b/test/algorithms/convex_hull/test_convex_hull.hpp @@ -146,7 +146,7 @@ void test_convex_hull(Geometry const& geometry, } -template +template void test_geometry_order(std::string const& wkt, std::size_t size_original, std::size_t size_hull_closed, double expected_area, double expected_perimeter = -1.0) @@ -158,33 +158,47 @@ void test_geometry_order(std::string const& wkt, Closed > hull_type; - typedef boost::geometry::strategies::convex_hull::cartesian<> strategy_type; - Geometry geometry; bg::read_wkt(wkt, geometry); boost::variant v(geometry); - test_convex_hull(geometry, size_original, + test_convex_hull(geometry, size_original, size_hull_closed, expected_area, expected_perimeter, !Clockwise); - test_convex_hull(v, size_original, + test_convex_hull(v, size_original, size_hull_closed, expected_area, expected_perimeter, !Clockwise); } -template +template void test_geometry(std::string const& wkt, - std::size_t size_original, std::size_t size_hull_closed, - double expected_area, double expected_perimeter = -1.0) + std::size_t size_original, std::size_t size_hull_closed, + double expected_area, double expected_perimeter = -1.0) { - test_geometry_order(wkt, size_original, + test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, + test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, + test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, + test_geometry_order(wkt, size_original, size_hull_closed, expected_area, expected_perimeter); } +template +void test_geometry_sph_geo(std::string const& wkt, + std::size_t size_original, + std::size_t size_hull_closed, + double spherical_expected_area, + double geographic_expected_area) +{ + typedef boost::geometry::strategies::convex_hull::spherical<> SphericalStrategy; + test_geometry(wkt, size_original, + size_hull_closed, spherical_expected_area); + + typedef boost::geometry::strategies::convex_hull::geographic<> GeoStrategy; + test_geometry(wkt, size_original, + size_hull_closed, geographic_expected_area); +} + template void test_empty_input() { From 69b743f1776b6dc58a4035af483e325e06821baf Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Thu, 24 Sep 2020 17:07:35 +0300 Subject: [PATCH 11/55] [tests] Add tests for robust cartesian convex hulls --- test/algorithms/convex_hull/Jamfile | 1 + .../convex_hull/convex_hull_robust.cpp | 123 ++++++++++++++++++ .../convex_hull/test_convex_hull.hpp | 120 +++++++++++------ 3 files changed, 201 insertions(+), 43 deletions(-) create mode 100644 test/algorithms/convex_hull/convex_hull_robust.cpp diff --git a/test/algorithms/convex_hull/Jamfile b/test/algorithms/convex_hull/Jamfile index e13d9a1b2..5bc795811 100644 --- a/test/algorithms/convex_hull/Jamfile +++ b/test/algorithms/convex_hull/Jamfile @@ -12,5 +12,6 @@ test-suite boost-geometry-algorithms-convex_hull : [ run convex_hull.cpp : : : : algorithms_convex_hull ] [ run convex_hull_multi.cpp : : : : algorithms_convex_hull_multi ] + [ run convex_hull_robust.cpp : : : : algorithms_convex_hull_robust ] [ run convex_hull_sph_geo.cpp : : : : algorithms_convex_hull_sph_geo ] ; diff --git a/test/algorithms/convex_hull/convex_hull_robust.cpp b/test/algorithms/convex_hull/convex_hull_robust.cpp new file mode 100644 index 000000000..47be14cfc --- /dev/null +++ b/test/algorithms/convex_hull/convex_hull_robust.cpp @@ -0,0 +1,123 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2020 Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fisikopoulos, 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) + +#include +#include + +#include "test_convex_hull.hpp" + +#include +#include + +#include + +#include + +#include + +struct robust_cartesian : boost::geometry::strategies::detail::cartesian_base +{ + template + static auto side(Geometry const&) + { + return boost::geometry::strategy::side::side_robust<>(); + } +}; + +struct precise_cartesian : boost::geometry::strategies::detail::cartesian_base +{ + template + static auto area(Geometry const&) + { + return boost::geometry::strategy::area::precise_cartesian<>(); + } +}; + +template +void test_all() +{ + typedef bg::model::d2::point_xy P; + typedef bg::model::d2::point_xy Pmp; + typedef boost::geometry::strategies::convex_hull::cartesian<> + non_robust_cartesian; + + // from sample polygon, with concavity + auto polygon_wkt0 = "polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,\ + 3.4 2.0, 4.1 3.0, 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))"; + test_geometry, robust_cartesian>( + polygon_wkt0, 12, 8, 5.245); + test_geometry, non_robust_cartesian>( + polygon_wkt0, 12, 8, 5.245); + test_geometry, non_robust_cartesian>( + polygon_wkt0, 12, 8, 5.245); + + // some colinear cases are ok with non robust predicate + auto polygon_wkt1 = "polygon((0.50000000000001621 0.50000000000001243,\ + 7.3000000000000173 7.3000000000000167,\ + 24.00000000000005 24.000000000000053,\ + 24.000000000000068 24.000000000000071,\ + 0 1,8 4,25 26,26 25,19 11))"; + test_geometry, robust_cartesian >( + polygon_wkt1, 9, 7, 137.25); + test_geometry, non_robust_cartesian >( + polygon_wkt1, 9, 7, 137.25); + test_geometry, non_robust_cartesian >( + polygon_wkt1, 9, 7, 137.25); + + // slightly non-convex result but areas equal + auto polygon_wkt2 = "polygon((27.643564356435643 -21.881188118811881,\ + 83.366336633663366 15.544554455445542,\ + 4.0 4.0,\ + 73.415841584158414 8.8613861386138595,\ + 27.643564356435643 -21.881188118811881))"; + test_geometry, robust_cartesian >( + polygon_wkt2, 5, 4, 1163.5247524752476, -1, true); + test_geometry, non_robust_cartesian >( + polygon_wkt2, 5, 5, 1163.5247524752476); + test_geometry, non_robust_cartesian >( + polygon_wkt2, 5, 4, 1163.5247524752476); + + // wrong orientation / sign in area + // here non_robust_cartesian computes wrong result with mp arithmetic + // correct results double checked with CGAL 5.1 + auto polygon_wkt3 = "polygon((200.0 49.200000000000003,\ + 100.0 49.600000000000001,\ + -233.33333333333334 50.93333333333333,\ + 166.66666666666669 49.333333333333336,\ + 200.0 49.200000000000003))"; + test_geometry, robust_cartesian, precise_cartesian >( + polygon_wkt3, 5, 4, 1.4210854715202004e-14, -1, true); + test_geometry, non_robust_cartesian, precise_cartesian >( + polygon_wkt3, 5, 4, -1.4210854715202004e-14); + test_geometry, non_robust_cartesian >( + polygon_wkt3, 5, 5, 1.69333333333333265e-13, -1, true); + + // missing one point could lead in arbitrary large errors in area + auto polygon_wkt4 = "polygon((0.10000000000000001 0.10000000000000001,\ + 0.20000000000000001 0.20000000000000004,\ + 0.79999999999999993 0.80000000000000004,\ + 1.267650600228229e30 1.2676506002282291e30,\ + 0.10000000000000001 0.10000000000000001))"; + test_geometry, robust_cartesian, precise_cartesian>( + polygon_wkt4, 5, 5, -0.315, -1, true); + test_geometry, non_robust_cartesian, precise_cartesian>( + polygon_wkt4, 5, 4, 0, -1, true); + test_geometry, non_robust_cartesian>( + polygon_wkt4, 5, 5, 3.472078301e+13, -1, true); +} + + +int test_main(int, char* []) +{ + using boost::multiprecision::cpp_dec_float_50; + test_all(); + + return 0; +} diff --git a/test/algorithms/convex_hull/test_convex_hull.hpp b/test/algorithms/convex_hull/test_convex_hull.hpp index 2c1266134..11ab0d004 100644 --- a/test/algorithms/convex_hull/test_convex_hull.hpp +++ b/test/algorithms/convex_hull/test_convex_hull.hpp @@ -27,17 +27,18 @@ #include #include +#include #include #include -template +template void check_convex_hull(Geometry const& geometry, Hull const& hull, std::size_t /*size_original*/, std::size_t size_hull, double expected_area, double expected_perimeter, - bool reverse) + bool reverse, AreaStrategy area_strategy) { std::size_t n = bg::num_points(hull); @@ -53,7 +54,8 @@ void check_convex_hull(Geometry const& geometry, Hull const& hull, // We omit this check as it is not important for the hull algorithm // BOOST_CHECK(bg::num_points(geometry) == size_original); - typename bg::default_area_result::type ah = bg::area(hull); + auto ah = bg::area(hull, area_strategy); + if (reverse) { ah = -ah; @@ -63,8 +65,7 @@ void check_convex_hull(Geometry const& geometry, Hull const& hull, if ( expected_perimeter >= 0 ) { - typename bg::default_length_result::type - ph = bg::perimeter(hull); + auto ph = bg::perimeter(hull); BOOST_CHECK_CLOSE(ph, expected_perimeter, 0.001); } @@ -95,11 +96,11 @@ inline bg::closure_selector get_closure(boost::variant +template void test_convex_hull(Geometry const& geometry, std::size_t size_original, std::size_t size_hull_closed, double expected_area, double expected_perimeter, - bool reverse) + bool reverse, bool use_only_strategy = false) { bool const is_original_closed = resolve_variant::get_closure(geometry) != bg::open; static bool const is_hull_closed = bg::closure::value != bg::open; @@ -113,43 +114,55 @@ void test_convex_hull(Geometry const& geometry, Hull hull; - // Test version with output iterator - bg::detail::convex_hull::convex_hull_insert(geometry, - std::back_inserter(hull.outer())); - check_convex_hull(geometry, hull, size_original, size_hull_from_orig, - expected_area, expected_perimeter, reverse); + if (!use_only_strategy) + { + // Test version with output iterator + bg::detail::convex_hull::convex_hull_insert(geometry, + std::back_inserter(hull.outer())); + check_convex_hull(geometry, hull, size_original, size_hull_from_orig, + expected_area, expected_perimeter, reverse, + AreaStrategy()); - // Test version with ring as output - bg::clear(hull); - bg::convex_hull(geometry, hull.outer()); - check_convex_hull(geometry, hull, size_original, size_hull, expected_area, - expected_perimeter, false); - - // Test version with polygon as output - bg::clear(hull); - bg::convex_hull(geometry, hull); - check_convex_hull(geometry, hull, size_original, size_hull, expected_area, - expected_perimeter, false); + // Test version with ring as output + bg::clear(hull); + bg::convex_hull(geometry, hull.outer()); + check_convex_hull(geometry, hull, size_original, size_hull, expected_area, + expected_perimeter, false, AreaStrategy()); + // Test version with polygon as output + bg::clear(hull); + bg::convex_hull(geometry, hull); + check_convex_hull(geometry, hull, size_original, size_hull, expected_area, + expected_perimeter, false, AreaStrategy()); + } // Test version with strategy bg::clear(hull); bg::convex_hull(geometry, hull.outer(), Strategy()); check_convex_hull(geometry, hull, size_original, size_hull, expected_area, - expected_perimeter, false); + expected_perimeter, false, AreaStrategy()); // Test version with output iterator and strategy bg::clear(hull); bg::detail::convex_hull::convex_hull_insert(geometry, std::back_inserter(hull.outer()), Strategy()); check_convex_hull(geometry, hull, size_original, size_hull_from_orig, - expected_area, expected_perimeter, reverse); + expected_area, expected_perimeter, reverse, AreaStrategy()); + } -template +template +< + typename Geometry, + typename Strategy, + typename AreaStrategy, + bool Clockwise, + bool Closed +> void test_geometry_order(std::string const& wkt, - std::size_t size_original, std::size_t size_hull_closed, - double expected_area, double expected_perimeter = -1.0) + std::size_t size_original, std::size_t size_hull_closed, + double expected_area, double expected_perimeter = -1.0, + bool use_only_strategy = false) { typedef bg::model::polygon < @@ -160,27 +173,48 @@ void test_geometry_order(std::string const& wkt, Geometry geometry; bg::read_wkt(wkt, geometry); - boost::variant v(geometry); - test_convex_hull(geometry, size_original, - size_hull_closed, expected_area, expected_perimeter, !Clockwise); - test_convex_hull(v, size_original, - size_hull_closed, expected_area, expected_perimeter, !Clockwise); + + test_convex_hull(geometry, size_original, + size_hull_closed, expected_area, expected_perimeter, !Clockwise, + use_only_strategy); + + boost::variant v(geometry); + test_convex_hull(v, size_original, + size_hull_closed, expected_area, expected_perimeter, !Clockwise, + use_only_strategy); } -template +template +< + typename Geometry, + typename Strategy, + typename AreaStrategy = typename bg::strategies::area::services::default_strategy + < + Geometry + >::type +> void test_geometry(std::string const& wkt, std::size_t size_original, std::size_t size_hull_closed, - double expected_area, double expected_perimeter = -1.0) + double expected_area, double expected_perimeter = -1.0, + bool use_only_strategy = false) { - test_geometry_order(wkt, size_original, - size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, - size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, - size_hull_closed, expected_area, expected_perimeter); - test_geometry_order(wkt, size_original, - size_hull_closed, expected_area, expected_perimeter); + test_geometry_order( + wkt, size_original, + size_hull_closed, expected_area, expected_perimeter, use_only_strategy + ); + test_geometry_order( + wkt, size_original, + size_hull_closed, expected_area, expected_perimeter, use_only_strategy + ); + test_geometry_order( + wkt, size_original, + size_hull_closed, expected_area, expected_perimeter, use_only_strategy + ); + test_geometry_order( + wkt, size_original, + size_hull_closed, expected_area, expected_perimeter, use_only_strategy + ); } template From 3f81bad3f25fc16cde01e826c4bc4c93e91975e1 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Fri, 25 Sep 2020 17:14:00 +0300 Subject: [PATCH 12/55] [strategy] Move side_robust and in_circle_robust strategies from extensions to strategy/cartesian --- extensions/test/triangulation/side_robust.cpp | 2 +- .../strategies => strategy}/cartesian/in_circle_robust.hpp | 6 +++--- .../strategies => strategy}/cartesian/side_robust.hpp | 6 +++--- test/algorithms/convex_hull/convex_hull_robust.cpp | 3 +-- 4 files changed, 8 insertions(+), 9 deletions(-) rename include/boost/geometry/{extensions/triangulation/strategies => strategy}/cartesian/in_circle_robust.hpp (90%) rename include/boost/geometry/{extensions/triangulation/strategies => strategy}/cartesian/side_robust.hpp (92%) diff --git a/extensions/test/triangulation/side_robust.cpp b/extensions/test/triangulation/side_robust.cpp index 64f978751..45bd06a98 100644 --- a/extensions/test/triangulation/side_robust.cpp +++ b/extensions/test/triangulation/side_robust.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include template void test_all() diff --git a/include/boost/geometry/extensions/triangulation/strategies/cartesian/in_circle_robust.hpp b/include/boost/geometry/strategy/cartesian/in_circle_robust.hpp similarity index 90% rename from include/boost/geometry/extensions/triangulation/strategies/cartesian/in_circle_robust.hpp rename to include/boost/geometry/strategy/cartesian/in_circle_robust.hpp index 63f70c50d..cf7be86f8 100644 --- a/include/boost/geometry/extensions/triangulation/strategies/cartesian/in_circle_robust.hpp +++ b/include/boost/geometry/strategy/cartesian/in_circle_robust.hpp @@ -9,8 +9,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_IN_CIRCLE_ROBUST_HPP -#define BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_IN_CIRCLE_ROBUST_HPP +#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_IN_CIRCLE_ROBUST_HPP +#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_IN_CIRCLE_ROBUST_HPP #include @@ -61,4 +61,4 @@ public: }} // namespace boost::geometry::strategy -#endif // BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_IN_CIRCLE_ROBUST_HPP +#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_IN_CIRCLE_ROBUST_HPP diff --git a/include/boost/geometry/extensions/triangulation/strategies/cartesian/side_robust.hpp b/include/boost/geometry/strategy/cartesian/side_robust.hpp similarity index 92% rename from include/boost/geometry/extensions/triangulation/strategies/cartesian/side_robust.hpp rename to include/boost/geometry/strategy/cartesian/side_robust.hpp index ca478048f..4ee4a1726 100644 --- a/include/boost/geometry/extensions/triangulation/strategies/cartesian/side_robust.hpp +++ b/include/boost/geometry/strategy/cartesian/side_robust.hpp @@ -9,8 +9,8 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_SIDE_ROBUST_HPP -#define BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_SIDE_ROBUST_HPP +#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP +#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP #include #include @@ -92,4 +92,4 @@ public: }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_SIDE_ROBUST_HPP +#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP diff --git a/test/algorithms/convex_hull/convex_hull_robust.cpp b/test/algorithms/convex_hull/convex_hull_robust.cpp index 47be14cfc..43f6072e6 100644 --- a/test/algorithms/convex_hull/convex_hull_robust.cpp +++ b/test/algorithms/convex_hull/convex_hull_robust.cpp @@ -16,8 +16,7 @@ #include #include -#include - +#include #include #include From 0df77e40c9a26eac59cc568bd8acce063505e695 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Wed, 30 Sep 2020 18:42:37 +0300 Subject: [PATCH 13/55] [test] Robustness tests --- .../strategies/convex_hull/cartesian.hpp | 4 +- .../strategy/cartesian/side_non_robust.hpp | 76 +++++++ .../convex_hull/convex_hull_robust.cpp | 67 +++--- .../convex_hull/test_convex_hull.hpp | 200 +++++++++++++----- 4 files changed, 249 insertions(+), 98 deletions(-) create mode 100644 include/boost/geometry/strategy/cartesian/side_non_robust.hpp diff --git a/include/boost/geometry/strategies/convex_hull/cartesian.hpp b/include/boost/geometry/strategies/convex_hull/cartesian.hpp index cc5c30c31..66e17735b 100644 --- a/include/boost/geometry/strategies/convex_hull/cartesian.hpp +++ b/include/boost/geometry/strategies/convex_hull/cartesian.hpp @@ -13,7 +13,7 @@ #include #include - +#include namespace boost { namespace geometry { @@ -28,7 +28,7 @@ public: template static auto side(Geometry const&) { - return strategy::side::side_by_triangle(); + return strategy::side::side_robust(); } }; diff --git a/include/boost/geometry/strategy/cartesian/side_non_robust.hpp b/include/boost/geometry/strategy/cartesian/side_non_robust.hpp new file mode 100644 index 000000000..2ef109cc1 --- /dev/null +++ b/include/boost/geometry/strategy/cartesian/side_non_robust.hpp @@ -0,0 +1,76 @@ +// Boost.Geometry + +// Copyright (c) 2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP +#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP + +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace side +{ + +/*! +\brief Adaptive precision predicate to check at which side of a segment a point lies: + left of segment (>0), right of segment (< 0), on segment (0). +\ingroup strategies +\tparam CalculationType \tparam_calculation +\details This predicate determines at which side of a segment a point lies +*/ +template +< + typename CalculationType = void +> +struct side_non_robust +{ +public: + //! \brief Computes double the signed area of the CCW triangle p1, p2, p + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + template + < + typename P1, + typename P2, + typename P + > + static inline int apply(P1 const& p1, P2 const& p2, P const& p) + { + typedef typename select_calculation_type_alt + < + CalculationType, + P1, + P2, + P + >::type coordinate_type; + typedef typename select_most_precise + < + coordinate_type, + double + >::type promoted_type; + + auto detleft = (promoted_type(get<0>(p1)) - promoted_type(get<0>(p))) + * (promoted_type(get<1>(p2)) - promoted_type(get<1>(p))); + auto detright = (promoted_type(get<1>(p1)) - promoted_type(get<1>(p))) + * (promoted_type(get<0>(p2)) - promoted_type(get<0>(p))); + return detleft > detright ? 1 : (detleft < detright ? -1 : 0 ); + + } +#endif + +}; + +}} // namespace strategy::side + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP diff --git a/test/algorithms/convex_hull/convex_hull_robust.cpp b/test/algorithms/convex_hull/convex_hull_robust.cpp index 43f6072e6..9ee6e55f4 100644 --- a/test/algorithms/convex_hull/convex_hull_robust.cpp +++ b/test/algorithms/convex_hull/convex_hull_robust.cpp @@ -16,45 +16,24 @@ #include #include -#include -#include - #include -struct robust_cartesian : boost::geometry::strategies::detail::cartesian_base -{ - template - static auto side(Geometry const&) - { - return boost::geometry::strategy::side::side_robust<>(); - } -}; - -struct precise_cartesian : boost::geometry::strategies::detail::cartesian_base -{ - template - static auto area(Geometry const&) - { - return boost::geometry::strategy::area::precise_cartesian<>(); - } -}; - template void test_all() { typedef bg::model::d2::point_xy P; typedef bg::model::d2::point_xy Pmp; - typedef boost::geometry::strategies::convex_hull::cartesian<> - non_robust_cartesian; // from sample polygon, with concavity auto polygon_wkt0 = "polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,\ 3.4 2.0, 4.1 3.0, 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))"; test_geometry, robust_cartesian>( polygon_wkt0, 12, 8, 5.245); - test_geometry, non_robust_cartesian>( + test_geometry, non_robust_cartesian_sbt>( polygon_wkt0, 12, 8, 5.245); - test_geometry, non_robust_cartesian>( + test_geometry, non_robust_cartesian_fast>( + polygon_wkt0, 12, 8, 5.245); + test_geometry, non_robust_cartesian_sbt>( polygon_wkt0, 12, 8, 5.245); // some colinear cases are ok with non robust predicate @@ -65,9 +44,11 @@ void test_all() 0 1,8 4,25 26,26 25,19 11))"; test_geometry, robust_cartesian >( polygon_wkt1, 9, 7, 137.25); - test_geometry, non_robust_cartesian >( + test_geometry, non_robust_cartesian_sbt >( polygon_wkt1, 9, 7, 137.25); - test_geometry, non_robust_cartesian >( + test_geometry, non_robust_cartesian_fast >( + polygon_wkt1, 9, 7, 137.25); + test_geometry, non_robust_cartesian_sbt >( polygon_wkt1, 9, 7, 137.25); // slightly non-convex result but areas equal @@ -77,14 +58,16 @@ void test_all() 73.415841584158414 8.8613861386138595,\ 27.643564356435643 -21.881188118811881))"; test_geometry, robust_cartesian >( - polygon_wkt2, 5, 4, 1163.5247524752476, -1, true); - test_geometry, non_robust_cartesian >( + polygon_wkt2, 5, 4, 1163.5247524752476); + test_geometry, non_robust_cartesian_sbt >( polygon_wkt2, 5, 5, 1163.5247524752476); - test_geometry, non_robust_cartesian >( + test_geometry, non_robust_cartesian_fast >( + polygon_wkt2, 5, 4, 1163.5247524752476); + test_geometry, non_robust_cartesian_sbt >( polygon_wkt2, 5, 4, 1163.5247524752476); // wrong orientation / sign in area - // here non_robust_cartesian computes wrong result with mp arithmetic + // here non_robust_cartesian_sbt computes wrong result with mp arithmetic // correct results double checked with CGAL 5.1 auto polygon_wkt3 = "polygon((200.0 49.200000000000003,\ 100.0 49.600000000000001,\ @@ -92,11 +75,13 @@ void test_all() 166.66666666666669 49.333333333333336,\ 200.0 49.200000000000003))"; test_geometry, robust_cartesian, precise_cartesian >( - polygon_wkt3, 5, 4, 1.4210854715202004e-14, -1, true); - test_geometry, non_robust_cartesian, precise_cartesian >( + polygon_wkt3, 5, 4, 1.4210854715202004e-14); + test_geometry, non_robust_cartesian_sbt, precise_cartesian >( polygon_wkt3, 5, 4, -1.4210854715202004e-14); - test_geometry, non_robust_cartesian >( - polygon_wkt3, 5, 5, 1.69333333333333265e-13, -1, true); + test_geometry, non_robust_cartesian_fast, precise_cartesian >( + polygon_wkt3, 5, 4, 1.4210854715202004e-14); + test_geometry, non_robust_cartesian_sbt >( + polygon_wkt3, 5, 5, 1.69333333333333265e-13); // missing one point could lead in arbitrary large errors in area auto polygon_wkt4 = "polygon((0.10000000000000001 0.10000000000000001,\ @@ -105,11 +90,13 @@ void test_all() 1.267650600228229e30 1.2676506002282291e30,\ 0.10000000000000001 0.10000000000000001))"; test_geometry, robust_cartesian, precise_cartesian>( - polygon_wkt4, 5, 5, -0.315, -1, true); - test_geometry, non_robust_cartesian, precise_cartesian>( - polygon_wkt4, 5, 4, 0, -1, true); - test_geometry, non_robust_cartesian>( - polygon_wkt4, 5, 5, 3.472078301e+13, -1, true); + polygon_wkt4, 5, 5, -0.315); + test_geometry, non_robust_cartesian_sbt, precise_cartesian>( + polygon_wkt4, 5, 4, 0); + test_geometry, non_robust_cartesian_fast, precise_cartesian>( + polygon_wkt4, 5, 4, -0.015); + test_geometry, non_robust_cartesian_sbt>( + polygon_wkt4, 5, 5, 3.472078301e+13); } diff --git a/test/algorithms/convex_hull/test_convex_hull.hpp b/test/algorithms/convex_hull/test_convex_hull.hpp index 11ab0d004..22e8d51df 100644 --- a/test/algorithms/convex_hull/test_convex_hull.hpp +++ b/test/algorithms/convex_hull/test_convex_hull.hpp @@ -29,11 +29,52 @@ #include #include +#include +#include +#include + #include #include +struct robust_cartesian : boost::geometry::strategies::detail::cartesian_base +{ + template + static auto side(Geometry const&) + { + return boost::geometry::strategy::side::side_robust<>(); + } +}; + +struct non_robust_cartesian_fast : boost::geometry::strategies::detail::cartesian_base +{ + template + static auto side(Geometry const&) + { + return boost::geometry::strategy::side::side_non_robust<>(); + } +}; + +struct non_robust_cartesian_sbt : boost::geometry::strategies::detail::cartesian_base +{ + template + static auto side(Geometry const&) + { + return boost::geometry::strategy::side::side_by_triangle<>(); + } +}; + +struct precise_cartesian : boost::geometry::strategies::detail::cartesian_base +{ + template + static auto area(Geometry const&) + { + return boost::geometry::strategy::area::precise_cartesian<>(); + } +}; + + template void check_convex_hull(Geometry const& geometry, Hull const& hull, std::size_t /*size_original*/, std::size_t size_hull, @@ -96,26 +137,80 @@ inline bg::closure_selector get_closure(boost::variant -void test_convex_hull(Geometry const& geometry, - std::size_t size_original, std::size_t size_hull_closed, - double expected_area, double expected_perimeter, - bool reverse, bool use_only_strategy = false) + +template +< + typename Hull, + typename Strategy, + typename AreaStrategy +> +struct test_convex_hull { - bool const is_original_closed = resolve_variant::get_closure(geometry) != bg::open; - static bool const is_hull_closed = bg::closure::value != bg::open; - - // convex_hull_insert() uses the original Geometry as a source of the info - // about the order and closure - std::size_t const size_hull_from_orig = is_original_closed ? - size_hull_closed : size_hull_closed - 1; - std::size_t const size_hull = is_hull_closed ? size_hull_closed : - size_hull_closed - 1; - - Hull hull; - - if (!use_only_strategy) + template + static void apply(Geometry const& geometry, + std::size_t size_original, + std::size_t size_hull_closed, + double expected_area, + double expected_perimeter, + bool reverse) { + bool const is_original_closed = resolve_variant::get_closure(geometry) != bg::open; + static bool const is_hull_closed = bg::closure::value != bg::open; + + // convex_hull_insert() uses the original Geometry as a source of the info + // about the order and closure + std::size_t const size_hull_from_orig = is_original_closed ? + size_hull_closed : size_hull_closed - 1; + std::size_t const size_hull = is_hull_closed ? size_hull_closed : + size_hull_closed - 1; + + Hull hull; + + // Test version with strategy + bg::clear(hull); + bg::convex_hull(geometry, hull.outer(), Strategy()); + check_convex_hull(geometry, hull, size_original, size_hull, + expected_area, expected_perimeter, false, AreaStrategy()); + + // Test version with output iterator and strategy + bg::clear(hull); + bg::detail::convex_hull::convex_hull_insert( + geometry, + std::back_inserter(hull.outer()), Strategy()); + check_convex_hull(geometry, hull, size_original, size_hull_from_orig, + expected_area, expected_perimeter, reverse, AreaStrategy()); + + } +}; + + +template +< + typename Hull, + typename AreaStrategy +> +struct test_convex_hull +{ + template + static void apply(Geometry const& geometry, + std::size_t size_original, + std::size_t size_hull_closed, + double expected_area, + double expected_perimeter, + bool reverse) + { + bool const is_original_closed = resolve_variant::get_closure(geometry) != bg::open; + static bool const is_hull_closed = bg::closure::value != bg::open; + + // convex_hull_insert() uses the original Geometry as a source of the info + // about the order and closure + std::size_t const size_hull_from_orig = is_original_closed ? + size_hull_closed : size_hull_closed - 1; + std::size_t const size_hull = is_hull_closed ? size_hull_closed : + size_hull_closed - 1; + + Hull hull; + // Test version with output iterator bg::detail::convex_hull::convex_hull_insert(geometry, std::back_inserter(hull.outer())); @@ -134,21 +229,22 @@ void test_convex_hull(Geometry const& geometry, bg::convex_hull(geometry, hull); check_convex_hull(geometry, hull, size_original, size_hull, expected_area, expected_perimeter, false, AreaStrategy()); + + // Test version with strategy + bg::clear(hull); + bg::convex_hull(geometry, hull.outer(), robust_cartesian()); + check_convex_hull(geometry, hull, size_original, size_hull, expected_area, + expected_perimeter, false, AreaStrategy()); + + // Test version with output iterator and strategy + bg::clear(hull); + bg::detail::convex_hull::convex_hull_insert(geometry, + std::back_inserter(hull.outer()), robust_cartesian()); + check_convex_hull(geometry, hull, size_original, size_hull_from_orig, + expected_area, expected_perimeter, reverse, AreaStrategy()); + } - // Test version with strategy - bg::clear(hull); - bg::convex_hull(geometry, hull.outer(), Strategy()); - check_convex_hull(geometry, hull, size_original, size_hull, expected_area, - expected_perimeter, false, AreaStrategy()); - - // Test version with output iterator and strategy - bg::clear(hull); - bg::detail::convex_hull::convex_hull_insert(geometry, - std::back_inserter(hull.outer()), Strategy()); - check_convex_hull(geometry, hull, size_original, size_hull_from_orig, - expected_area, expected_perimeter, reverse, AreaStrategy()); - -} +}; template @@ -160,9 +256,10 @@ template bool Closed > void test_geometry_order(std::string const& wkt, - std::size_t size_original, std::size_t size_hull_closed, - double expected_area, double expected_perimeter = -1.0, - bool use_only_strategy = false) + std::size_t size_original, + std::size_t size_hull_closed, + double expected_area, + double expected_perimeter = -1.0) { typedef bg::model::polygon < @@ -175,14 +272,12 @@ void test_geometry_order(std::string const& wkt, bg::read_wkt(wkt, geometry); - test_convex_hull(geometry, size_original, - size_hull_closed, expected_area, expected_perimeter, !Clockwise, - use_only_strategy); + test_convex_hull::apply(geometry, size_original, + size_hull_closed, expected_area, expected_perimeter, !Clockwise); boost::variant v(geometry); - test_convex_hull(v, size_original, - size_hull_closed, expected_area, expected_perimeter, !Clockwise, - use_only_strategy); + test_convex_hull::apply(v, size_original, + size_hull_closed, expected_area, expected_perimeter, !Clockwise); } template @@ -195,26 +290,19 @@ template >::type > void test_geometry(std::string const& wkt, - std::size_t size_original, std::size_t size_hull_closed, - double expected_area, double expected_perimeter = -1.0, - bool use_only_strategy = false) + std::size_t size_original, + std::size_t size_hull_closed, + double expected_area, + double expected_perimeter = -1.0) { test_geometry_order( - wkt, size_original, - size_hull_closed, expected_area, expected_perimeter, use_only_strategy - ); + wkt, size_original, size_hull_closed, expected_area, expected_perimeter); test_geometry_order( - wkt, size_original, - size_hull_closed, expected_area, expected_perimeter, use_only_strategy - ); + wkt, size_original, size_hull_closed, expected_area, expected_perimeter); test_geometry_order( - wkt, size_original, - size_hull_closed, expected_area, expected_perimeter, use_only_strategy - ); + wkt, size_original, size_hull_closed, expected_area, expected_perimeter); test_geometry_order( - wkt, size_original, - size_hull_closed, expected_area, expected_perimeter, use_only_strategy - ); + wkt, size_original, size_hull_closed, expected_area, expected_perimeter); } template From c79b9a60b7e4b076495cb48858da724e1d12f11c Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Thu, 8 Oct 2020 17:48:48 +0300 Subject: [PATCH 14/55] [strategies] Remove Geometry parameter from side in convex_hull strategies --- .../algorithms/detail/convex_hull/graham_andrew.hpp | 2 +- .../boost/geometry/strategies/convex_hull/cartesian.hpp | 3 +-- .../boost/geometry/strategies/convex_hull/geographic.hpp | 3 +-- .../boost/geometry/strategies/convex_hull/spherical.hpp | 3 +-- test/algorithms/convex_hull/test_convex_hull.hpp | 9 +++------ 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp b/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp index 58cd7a763..b264665c8 100644 --- a/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp +++ b/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp @@ -215,7 +215,7 @@ public: container_type lower_points, upper_points; - auto side_strategy = strategy.side(geometry); + auto side_strategy = strategy.side(); // Bounding left/right points // Second pass, now that extremes are found, assign all points diff --git a/include/boost/geometry/strategies/convex_hull/cartesian.hpp b/include/boost/geometry/strategies/convex_hull/cartesian.hpp index 66e17735b..4f4dc2778 100644 --- a/include/boost/geometry/strategies/convex_hull/cartesian.hpp +++ b/include/boost/geometry/strategies/convex_hull/cartesian.hpp @@ -25,8 +25,7 @@ template class cartesian : strategies::detail::cartesian_base { public: - template - static auto side(Geometry const&) + static auto side() { return strategy::side::side_robust(); } diff --git a/include/boost/geometry/strategies/convex_hull/geographic.hpp b/include/boost/geometry/strategies/convex_hull/geographic.hpp index 665cd7864..82580a2bb 100644 --- a/include/boost/geometry/strategies/convex_hull/geographic.hpp +++ b/include/boost/geometry/strategies/convex_hull/geographic.hpp @@ -41,8 +41,7 @@ public: : base_t(spheroid) {} - template - static auto side(Geometry const&) + static auto side() { return strategy::side::geographic < diff --git a/include/boost/geometry/strategies/convex_hull/spherical.hpp b/include/boost/geometry/strategies/convex_hull/spherical.hpp index acbee9c1b..db93a9f85 100644 --- a/include/boost/geometry/strategies/convex_hull/spherical.hpp +++ b/include/boost/geometry/strategies/convex_hull/spherical.hpp @@ -30,8 +30,7 @@ template class spherical : strategies::detail::spherical_base { public: - template - static auto side(Geometry const&) + static auto side() { return strategy::side::spherical_side_formula(); } diff --git a/test/algorithms/convex_hull/test_convex_hull.hpp b/test/algorithms/convex_hull/test_convex_hull.hpp index 22e8d51df..b7912075b 100644 --- a/test/algorithms/convex_hull/test_convex_hull.hpp +++ b/test/algorithms/convex_hull/test_convex_hull.hpp @@ -40,8 +40,7 @@ struct robust_cartesian : boost::geometry::strategies::detail::cartesian_base { - template - static auto side(Geometry const&) + static auto side() { return boost::geometry::strategy::side::side_robust<>(); } @@ -49,8 +48,7 @@ struct robust_cartesian : boost::geometry::strategies::detail::cartesian_base struct non_robust_cartesian_fast : boost::geometry::strategies::detail::cartesian_base { - template - static auto side(Geometry const&) + static auto side() { return boost::geometry::strategy::side::side_non_robust<>(); } @@ -58,8 +56,7 @@ struct non_robust_cartesian_fast : boost::geometry::strategies::detail::cartesia struct non_robust_cartesian_sbt : boost::geometry::strategies::detail::cartesian_base { - template - static auto side(Geometry const&) + static auto side() { return boost::geometry::strategy::side::side_by_triangle<>(); } From 8c4f1589c2bca3c9f456ec283d54addc4507db06 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Tue, 13 Oct 2020 11:45:21 +0300 Subject: [PATCH 15/55] [strategy] Fix convex hull strategies --- .../algorithms/detail/convex_hull/graham_andrew.hpp | 2 +- .../geometry/strategies/convex_hull/geographic.hpp | 4 ++-- .../geometry/strategies/convex_hull/spherical.hpp | 8 ++------ .../boost/geometry/strategies/geographic/side.hpp | 12 +++++++----- .../geometry/strategy/cartesian/precise_area.hpp | 6 +++--- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp b/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp index b264665c8..aab92053a 100644 --- a/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp +++ b/include/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp @@ -215,7 +215,7 @@ public: container_type lower_points, upper_points; - auto side_strategy = strategy.side(); + auto const side_strategy = strategy.side(); // Bounding left/right points // Second pass, now that extremes are found, assign all points diff --git a/include/boost/geometry/strategies/convex_hull/geographic.hpp b/include/boost/geometry/strategies/convex_hull/geographic.hpp index 82580a2bb..751ef1dd0 100644 --- a/include/boost/geometry/strategies/convex_hull/geographic.hpp +++ b/include/boost/geometry/strategies/convex_hull/geographic.hpp @@ -41,14 +41,14 @@ public: : base_t(spheroid) {} - static auto side() + auto side() const { return strategy::side::geographic < FormulaPolicy, Spheroid, CalculationType - >(); + >(base_t::m_spheroid); } }; diff --git a/include/boost/geometry/strategies/convex_hull/spherical.hpp b/include/boost/geometry/strategies/convex_hull/spherical.hpp index db93a9f85..cfbdb978b 100644 --- a/include/boost/geometry/strategies/convex_hull/spherical.hpp +++ b/include/boost/geometry/strategies/convex_hull/spherical.hpp @@ -22,12 +22,8 @@ namespace boost { namespace geometry namespace strategies { namespace convex_hull { -template -< - typename RadiusTypeOrSphere = double, - typename CalculationType = void -> -class spherical : strategies::detail::spherical_base +template +class spherical : strategies::detail::spherical_base { public: static auto side() diff --git a/include/boost/geometry/strategies/geographic/side.hpp b/include/boost/geometry/strategies/geographic/side.hpp index 67080d725..6f2de5277 100644 --- a/include/boost/geometry/strategies/geographic/side.hpp +++ b/include/boost/geometry/strategies/geographic/side.hpp @@ -110,6 +110,13 @@ public: template inline int apply(P1 const& p1, P2 const& p2, P const& p) const { + if (geometry::equals(p, p1, equals_point_point_strategy_type()) + || geometry::equals(p, p2, equals_point_point_strategy_type()) + || geometry::equals(p1, p2, equals_point_point_strategy_type())) + { + return 0; + } + typedef typename promote_floating_point < typename select_calculation_type_alt @@ -122,11 +129,6 @@ public: typedef typename FormulaPolicy::template inverse inverse_formula; - if (geometry::equals(p, p1) || geometry::equals(p, p2)) - { - return 0; - } - calc_t a1p = azimuth(p1, p, m_model); calc_t a12 = azimuth(p1, p2, m_model); diff --git a/include/boost/geometry/strategy/cartesian/precise_area.hpp b/include/boost/geometry/strategy/cartesian/precise_area.hpp index b0a3ba852..2771205ef 100644 --- a/include/boost/geometry/strategy/cartesian/precise_area.hpp +++ b/include/boost/geometry/strategy/cartesian/precise_area.hpp @@ -7,8 +7,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_AREA_ACCURATE_HPP -#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_AREA_ACCURATE_HPP +#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP +#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP #include @@ -115,4 +115,4 @@ public : }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_ACCURATE_HPP +#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP From eaf904f1e22665712a0947b4372116d327bad15a Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Fri, 16 Oct 2020 11:11:40 +0300 Subject: [PATCH 16/55] [strategies] Fix side_by_cross_track strategy issue --- .../spherical/side_by_cross_track.hpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp index 99e6aad1d..0f078443f 100644 --- a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp @@ -50,6 +50,15 @@ public : template static inline int apply(P1 const& p1, P2 const& p2, P const& p) { + typedef strategy::within::spherical_point_point + equals_point_point_strategy_type; + if (geometry::equals(p, p1, equals_point_point_strategy_type()) + || geometry::equals(p, p2, equals_point_point_strategy_type()) + || geometry::equals(p1, p2, equals_point_point_strategy_type())) + { + return 0; + } + typedef typename promote_floating_point < typename select_calculation_type_alt @@ -71,19 +80,9 @@ public : calc_t crs_AD = geometry::formula::spherical_azimuth (lon1, lat1, lon, lat).azimuth; - if (crs_AD == 0) - { - return 0; - } - calc_t crs_AB = geometry::formula::spherical_azimuth (lon1, lat1, lon2, lat2).azimuth; - if (crs_AB == 0) - { - return 0; - } - calc_t XTD = asin(sin(d1) * sin(crs_AD - crs_AB)); return math::equals(XTD, 0) ? 0 : XTD < 0 ? 1 : -1; From 9c1905d1a57d18edee135855b0340ebb446ff166 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Fri, 16 Oct 2020 11:30:16 +0300 Subject: [PATCH 17/55] [test] Calculate convex hull with a non-default spherical side strategy --- test/algorithms/convex_hull/convex_hull_sph_geo.cpp | 8 ++++++++ test/algorithms/convex_hull/test_convex_hull.hpp | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/test/algorithms/convex_hull/convex_hull_sph_geo.cpp b/test/algorithms/convex_hull/convex_hull_sph_geo.cpp index 33dfef803..277c3ae8c 100644 --- a/test/algorithms/convex_hull/convex_hull_sph_geo.cpp +++ b/test/algorithms/convex_hull/convex_hull_sph_geo.cpp @@ -52,6 +52,14 @@ void test_all() >("polygon((1 1, 1 4, 3 4, 3 3, 4 3, 4 4, 5 4, 5 1, 1 1))", 9, 5, 0.003652987070377825, 147615606532.65408); + // calculate convex hull with a non-default spherical side strategy + test_geometry + < + bg::model::polygon, + sphrerical_side_by_cross_track<> + >("polygon((359 0,1 1,1 -1,359 0))", 4, 4, + 0.00060931217091786914); + test_empty_input>(); test_empty_input>(); test_empty_input>(); diff --git a/test/algorithms/convex_hull/test_convex_hull.hpp b/test/algorithms/convex_hull/test_convex_hull.hpp index b7912075b..df1b959b0 100644 --- a/test/algorithms/convex_hull/test_convex_hull.hpp +++ b/test/algorithms/convex_hull/test_convex_hull.hpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -62,6 +63,15 @@ struct non_robust_cartesian_sbt : boost::geometry::strategies::detail::cartesian } }; +template +struct sphrerical_side_by_cross_track : boost::geometry::strategies::detail::spherical_base +{ + static auto side() + { + return boost::geometry::strategy::side::side_by_cross_track<>(); + } +}; + struct precise_cartesian : boost::geometry::strategies::detail::cartesian_base { template @@ -318,6 +328,7 @@ void test_geometry_sph_geo(std::string const& wkt, size_hull_closed, geographic_expected_area); } + template void test_empty_input() { From 6b74f7c8a344495384cc5ac4f74bb7a307b7c1d1 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 18 Sep 2020 19:08:48 +0200 Subject: [PATCH 18/55] Support umbrella strategies in relops, setops, index, buffer and more. Also is_simple, is_valid and extensions like dissolve and nsphere relops. Add umbrella strategies: - relate: used in setops, relops, buffer, is_xxx, dissolve, etc. - index: used in rtree - io: used in wkt read/write and extensions/shapefile Replace `point_box_by_side` agnostic strategy with CS-specific strategies. Fix passing of strategies (no defaults when user-defined strategy is passed) in places like buffer and distance. Alter tests accordingly. --- include/boost/geometry/algorithms/buffer.hpp | 13 +- include/boost/geometry/algorithms/crosses.hpp | 53 ++- .../detail/buffer/buffer_inserter.hpp | 16 +- .../detail/buffer/buffer_policies.hpp | 54 ++- .../buffer/buffered_piece_collection.hpp | 151 ++---- .../detail/buffer/get_piece_turns.hpp | 12 +- .../algorithms/detail/buffer/piece_border.hpp | 52 +- .../buffer/turn_in_original_visitor.hpp | 58 ++- .../detail/closest_feature/range_to_range.hpp | 10 +- .../detail/covered_by/implementation.hpp | 10 +- .../detail/covered_by/interface.hpp | 54 ++- .../detail/disjoint/areal_areal.hpp | 13 +- .../algorithms/detail/disjoint/box_box.hpp | 28 +- .../algorithms/detail/disjoint/interface.hpp | 45 +- .../detail/disjoint/linear_areal.hpp | 12 +- .../detail/disjoint/linear_linear.hpp | 4 +- .../detail/disjoint/linear_segment_or_box.hpp | 6 +- .../detail/disjoint/multipoint_geometry.hpp | 182 ++++--- .../algorithms/detail/disjoint/point_box.hpp | 32 +- .../detail/disjoint/point_point.hpp | 33 +- .../detail/disjoint/segment_box.hpp | 2 +- .../detail/distance/point_to_geometry.hpp | 37 +- .../detail/distance/segment_to_box.hpp | 23 +- .../detail/equals/implementation.hpp | 37 +- .../algorithms/detail/equals/interface.hpp | 47 +- .../algorithms/detail/equals/point_point.hpp | 27 +- .../detail/has_self_intersections.hpp | 21 - .../detail/intersection/areal_areal.hpp | 14 +- .../detail/intersection/interface.hpp | 73 +-- .../detail/intersects/implementation.hpp | 8 +- .../algorithms/detail/is_simple/areal.hpp | 103 ++-- .../algorithms/detail/is_simple/interface.hpp | 37 +- .../algorithms/detail/is_simple/linear.hpp | 9 +- .../detail/is_simple/multipoint.hpp | 8 +- .../detail/is_valid/has_duplicates.hpp | 9 +- .../algorithms/detail/is_valid/has_spikes.hpp | 75 +-- .../detail/is_valid/has_valid_self_turns.hpp | 2 +- .../algorithms/detail/is_valid/interface.hpp | 46 +- .../algorithms/detail/is_valid/linear.hpp | 14 +- .../detail/is_valid/multipolygon.hpp | 19 +- .../algorithms/detail/is_valid/polygon.hpp | 63 +-- .../algorithms/detail/is_valid/ring.hpp | 55 +-- .../algorithms/detail/is_valid/segment.hpp | 7 +- .../num_distinct_consecutive_points.hpp | 22 +- .../algorithms/detail/overlaps/interface.hpp | 90 +++- .../algorithms/detail/overlay/add_rings.hpp | 19 +- .../detail/overlay/append_no_duplicates.hpp | 4 +- .../overlay/append_no_dups_or_spikes.hpp | 39 +- .../detail/overlay/assign_parents.hpp | 52 +- .../detail/overlay/copy_segments.hpp | 14 +- .../overlay/enrich_intersection_points.hpp | 4 +- .../algorithms/detail/overlay/follow.hpp | 37 +- .../overlay/get_intersection_points.hpp | 2 +- .../detail/overlay/get_turn_info.hpp | 6 +- .../overlay/get_turn_info_for_endpoint.hpp | 29 +- .../detail/overlay/get_turn_info_helpers.hpp | 83 ++-- .../detail/overlay/get_turn_info_la.hpp | 51 +- .../detail/overlay/get_turn_info_ll.hpp | 23 +- .../algorithms/detail/overlay/get_turns.hpp | 99 ++-- .../detail/overlay/handle_self_turns.hpp | 58 +-- .../detail/overlay/intersection_insert.hpp | 10 +- .../detail/overlay/linear_linear.hpp | 10 +- .../algorithms/detail/overlay/overlay.hpp | 33 +- .../detail/overlay/pointlike_areal.hpp | 75 +-- .../detail/overlay/pointlike_linear.hpp | 58 +-- .../detail/overlay/range_in_geometry.hpp | 15 +- .../detail/overlay/ring_properties.hpp | 4 +- .../detail/overlay/select_rings.hpp | 38 +- .../detail/overlay/self_turn_points.hpp | 43 +- .../detail/overlay/traversal_ring_creator.hpp | 45 +- .../algorithms/detail/relate/areal_areal.hpp | 45 +- .../detail/relate/boundary_checker.hpp | 100 ++-- .../detail/relate/follow_helpers.hpp | 4 +- .../algorithms/detail/relate/interface.hpp | 38 +- .../algorithms/detail/relate/linear_areal.hpp | 92 ++-- .../detail/relate/linear_linear.hpp | 47 +- .../detail/relate/multi_point_geometry.hpp | 198 ++++---- .../detail/relate/point_geometry.hpp | 13 +- .../detail/relate/topology_check.hpp | 73 +-- .../algorithms/detail/relate/turns.hpp | 31 +- .../algorithms/detail/relation/interface.hpp | 5 +- .../detail/sections/section_box_policies.hpp | 29 +- .../detail/sections/sectionalize.hpp | 160 ++----- .../detail/touches/implementation.hpp | 30 +- .../algorithms/detail/touches/interface.hpp | 44 +- .../detail/within/implementation.hpp | 6 +- .../algorithms/detail/within/interface.hpp | 58 ++- .../algorithms/detail/within/multi_point.hpp | 29 +- .../detail/within/point_in_geometry.hpp | 109 ++--- .../boost/geometry/algorithms/difference.hpp | 63 ++- .../geometry/algorithms/sym_difference.hpp | 64 ++- include/boost/geometry/algorithms/union.hpp | 67 ++- .../extensions/algorithms/dissolve.hpp | 114 +++-- .../extensions/gis/io/shapefile/read.hpp | 12 +- .../nsphere/algorithms/covered_by.hpp | 15 +- .../extensions/nsphere/algorithms/within.hpp | 36 +- .../nsphere/strategies/relate/cartesian.hpp | 127 +++++ .../index/detail/algorithms/bounds.hpp | 28 +- .../algorithms/intersection_content.hpp | 9 +- .../geometry/index/detail/bounded_view.hpp | 22 +- .../index/detail/distance_predicates.hpp | 142 +----- .../geometry/index/detail/predicates.hpp | 4 +- .../index/detail/rtree/rstar/insert.hpp | 25 +- include/boost/geometry/index/equal_to.hpp | 16 +- include/boost/geometry/io/wkt/read.hpp | 8 +- include/boost/geometry/io/wkt/write.hpp | 8 +- .../robustness/get_rescale_policy.hpp | 221 ++------- .../policies/robustness/segment_ratio.hpp | 52 +- .../agnostic/point_in_box_by_side.hpp | 202 ++++++-- .../boost/geometry/strategies/cartesian.hpp | 3 + .../strategies/cartesian/box_in_box.hpp | 44 +- .../geometry/strategies/cartesian/index.hpp | 198 -------- .../strategies/cartesian/intersection.hpp | 13 +- .../geometry/strategies/cartesian/io.hpp | 74 --- .../strategies/cartesian/side_by_triangle.hpp | 3 +- .../strategies/concepts/within_concept.hpp | 78 ++- include/boost/geometry/strategies/detail.hpp | 8 +- .../boost/geometry/strategies/disjoint.hpp | 3 +- .../boost/geometry/strategies/geographic.hpp | 3 + .../geographic/disjoint_segment_box.hpp | 5 + .../geographic/distance_segment_box.hpp | 3 +- .../geometry/strategies/geographic/index.hpp | 216 --------- .../strategies/geographic/intersection.hpp | 10 +- .../geometry/strategies/geographic/io.hpp | 96 ---- include/boost/geometry/strategies/index.hpp | 67 --- .../geometry/strategies/index/cartesian.hpp | 147 ++++++ .../geometry/strategies/index/geographic.hpp | 279 +++++++++++ .../geometry/strategies/index/services.hpp | 50 ++ .../geometry/strategies/index/spherical.hpp | 161 +++++++ .../geometry/strategies/io/cartesian.hpp | 77 +++ .../geometry/strategies/io/geographic.hpp | 99 ++++ .../strategies/{io.hpp => io/services.hpp} | 19 +- .../geometry/strategies/io/spherical.hpp | 89 ++++ include/boost/geometry/strategies/relate.hpp | 168 +------ .../geometry/strategies/relate/cartesian.hpp | 448 ++++++++++++++++++ .../geometry/strategies/relate/geographic.hpp | 419 ++++++++++++++++ .../geometry/strategies/relate/services.hpp | 57 +++ .../geometry/strategies/relate/spherical.hpp | 404 ++++++++++++++++ .../boost/geometry/strategies/spherical.hpp | 3 + .../spherical/distance_segment_box.hpp | 1 + .../geometry/strategies/spherical/index.hpp | 199 -------- .../strategies/spherical/intersection.hpp | 3 +- .../geometry/strategies/spherical/io.hpp | 80 ---- .../spherical/point_in_poly_winding.hpp | 36 +- .../boost/geometry/strategies/strategies.hpp | 5 +- include/boost/geometry/strategy/relate.hpp | 175 +++++++ test/algorithms/buffer/buffer_multi_point.cpp | 12 +- .../algorithms/buffer/buffer_piece_border.cpp | 7 +- test/algorithms/buffer/test_buffer.hpp | 45 +- test/algorithms/buffer/test_buffer_geo.hpp | 16 +- test/algorithms/buffer/test_buffer_svg.hpp | 8 +- .../detail/sections/sectionalize.cpp | 11 +- test/algorithms/overlay/get_turn_info.cpp | 11 +- test/algorithms/overlay/get_turns.cpp | 4 +- .../overlay/get_turns_linear_linear_geo.cpp | 2 +- test/algorithms/overlay/overlay.cpp | 8 +- test/algorithms/overlay/select_rings.cpp | 8 +- .../overlay/self_intersection_points.cpp | 18 +- test/algorithms/overlay/sort_by_side.cpp | 10 +- .../algorithms/overlay/sort_by_side_basic.cpp | 12 +- test/algorithms/overlay/test_get_turns.hpp | 8 +- .../set_operations/check_turn_less.hpp | 6 +- .../difference/difference_tupled.cpp | 1 - .../intersection/intersection_tupled.cpp | 1 - .../sym_difference/sym_difference_tupled.cpp | 1 - .../test_get_turns_ll_invariance.hpp | 29 +- .../set_operations/union/union_tupled.cpp | 1 - test/algorithms/within/within.cpp | 12 +- test/algorithms/within/within_sph_geo.cpp | 17 +- test/cs_undefined/index.cpp | 60 +-- test/iterators/segment_iterator.cpp | 5 + test/strategies/point_in_box.cpp | 26 +- test/strategies/segment_intersection.cpp | 12 +- test/strategies/test_within.hpp | 8 +- test/strategies/winding.cpp | 8 +- 175 files changed, 5303 insertions(+), 3690 deletions(-) create mode 100644 include/boost/geometry/extensions/nsphere/strategies/relate/cartesian.hpp delete mode 100644 include/boost/geometry/strategies/cartesian/index.hpp delete mode 100644 include/boost/geometry/strategies/cartesian/io.hpp delete mode 100644 include/boost/geometry/strategies/geographic/index.hpp delete mode 100644 include/boost/geometry/strategies/geographic/io.hpp delete mode 100644 include/boost/geometry/strategies/index.hpp create mode 100644 include/boost/geometry/strategies/index/cartesian.hpp create mode 100644 include/boost/geometry/strategies/index/geographic.hpp create mode 100644 include/boost/geometry/strategies/index/services.hpp create mode 100644 include/boost/geometry/strategies/index/spherical.hpp create mode 100644 include/boost/geometry/strategies/io/cartesian.hpp create mode 100644 include/boost/geometry/strategies/io/geographic.hpp rename include/boost/geometry/strategies/{io.hpp => io/services.hpp} (59%) create mode 100644 include/boost/geometry/strategies/io/spherical.hpp create mode 100644 include/boost/geometry/strategies/relate/cartesian.hpp create mode 100644 include/boost/geometry/strategies/relate/geographic.hpp create mode 100644 include/boost/geometry/strategies/relate/services.hpp create mode 100644 include/boost/geometry/strategies/relate/spherical.hpp delete mode 100644 include/boost/geometry/strategies/spherical/index.hpp delete mode 100644 include/boost/geometry/strategies/spherical/io.hpp create mode 100644 include/boost/geometry/strategy/relate.hpp diff --git a/include/boost/geometry/algorithms/buffer.hpp b/include/boost/geometry/algorithms/buffer.hpp index 3bf6d2fa5..74523f11c 100644 --- a/include/boost/geometry/algorithms/buffer.hpp +++ b/include/boost/geometry/algorithms/buffer.hpp @@ -242,22 +242,23 @@ inline void buffer(GeometryIn const& geometry_in, geometry::envelope(geometry_in, box); geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy)); - typename strategy::intersection::services::default_strategy + typename strategies::relate::services::default_strategy < - typename cs_tag::type - >::type intersection_strategy; + GeometryIn, GeometryIn + >::type strategy; rescale_policy_type rescale_policy = boost::geometry::get_rescale_policy( - box, intersection_strategy); + box, strategy); - detail::buffer::buffer_inserter(geometry_in, range::back_inserter(geometry_out), + detail::buffer::buffer_inserter(geometry_in, + range::back_inserter(geometry_out), distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, - intersection_strategy, + strategy, rescale_policy); } diff --git a/include/boost/geometry/algorithms/crosses.hpp b/include/boost/geometry/algorithms/crosses.hpp index 6dcbdbe9d..c3656216a 100644 --- a/include/boost/geometry/algorithms/crosses.hpp +++ b/include/boost/geometry/algorithms/crosses.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2014 Samuel Debionne, Grenoble, France. -// This file was modified by Oracle on 2014, 2017. -// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -31,6 +31,8 @@ #include #include #include +#include +#include namespace boost { namespace geometry @@ -65,9 +67,14 @@ struct crosses namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct crosses { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) @@ -75,21 +82,50 @@ struct crosses concepts::check(); concepts::check(); - return dispatch::crosses::apply(geometry1, geometry2, strategy); + return dispatch::crosses + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); } +}; +template +struct crosses +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + //using strategies::crosses::services::strategy_converter; + using strategies::relate::services::strategy_converter; + return crosses + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct crosses +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::relate::services::default_strategy + //typedef typename strategies::crosses::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; - return apply(geometry1, geometry2, strategy_type()); + return crosses + < + strategy_type + >::apply(geometry1, geometry2, strategy_type()); } }; @@ -106,7 +142,10 @@ namespace resolve_variant Geometry2 const& geometry2, Strategy const& strategy) { - return resolve_strategy::crosses::apply(geometry1, geometry2, strategy); + return resolve_strategy::crosses + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index 685fdba66..86318d76e 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -921,7 +921,7 @@ template typename JoinStrategy, typename EndStrategy, typename PointStrategy, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy, typename VisitPiecesPolicy > @@ -931,7 +931,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator JoinStrategy const& join_strategy, EndStrategy const& end_strategy, PointStrategy const& point_strategy, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, VisitPiecesPolicy& visit_pieces_policy ) @@ -941,11 +941,11 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator typedef detail::buffer::buffered_piece_collection < typename geometry::ring_type::type, - IntersectionStrategy, + Strategy, DistanceStrategy, RobustPolicy > collection_type; - collection_type collection(intersection_strategy, distance_strategy, robust_policy); + collection_type collection(strategy, distance_strategy, robust_policy); collection_type const& const_collection = collection; bool const areal = util::is_areal::value; @@ -962,7 +962,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator >::apply(geometry_input, collection, distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, - robust_policy, intersection_strategy.get_side_strategy()); + robust_policy, strategy.side()); // pass strategy? collection.get_turns(); if (BOOST_GEOMETRY_CONDITION(areal)) @@ -1029,7 +1029,7 @@ template typename JoinStrategy, typename EndStrategy, typename PointStrategy, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy > inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out, @@ -1038,14 +1038,14 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator JoinStrategy const& join_strategy, EndStrategy const& end_strategy, PointStrategy const& point_strategy, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy) { detail::buffer::visit_pieces_default_policy visitor; buffer_inserter(geometry_input, out, distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, - intersection_strategy, robust_policy, visitor); + strategy, robust_policy, visitor); } #endif // DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp index 7f865ecc0..05d5c6fda 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp @@ -193,30 +193,37 @@ struct buffer_less } }; +template struct piece_get_box { + explicit piece_get_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Piece const& piece) + inline void apply(Box& total, Piece const& piece) const { assert_coordinate_type_equal(total, piece.m_piece_border.m_envelope); - typedef typename strategy::expand::services::default_strategy - < - box_tag, typename cs_tag::type - >::type expand_strategy_type; if (piece.m_piece_border.m_has_envelope) { geometry::expand(total, piece.m_piece_border.m_envelope, - expand_strategy_type()); + m_strategy); } } + + Strategy const& m_strategy; }; -template +template struct piece_overlaps_box { + explicit piece_overlaps_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Piece const& piece) + inline bool apply(Box const& box, Piece const& piece) const { assert_coordinate_type_equal(box, piece.m_piece_border.m_envelope); @@ -235,34 +242,45 @@ struct piece_overlaps_box } return ! geometry::detail::disjoint::disjoint_box_box(box, piece.m_piece_border.m_envelope, - DisjointBoxBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; +template struct turn_get_box { + explicit turn_get_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Turn const& turn) + inline void apply(Box& total, Turn const& turn) const { - typedef typename strategy::expand::services::default_strategy - < - point_tag, typename cs_tag::type - >::type expand_strategy_type; assert_coordinate_type_equal(total, turn.point); - geometry::expand(total, turn.point, expand_strategy_type()); + geometry::expand(total, turn.point, m_strategy); } + + Strategy const& m_strategy; }; -template +template struct turn_overlaps_box { + explicit turn_overlaps_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Turn const& turn) + inline bool apply(Box const& box, Turn const& turn) const { assert_coordinate_type_equal(turn.point, box); return ! geometry::detail::disjoint::disjoint_point_box(turn.point, box, - DisjointPointBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; struct enriched_map_buffer_include_policy diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index 3995f78da..a7f600e43 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -117,7 +117,7 @@ namespace detail { namespace buffer template < typename Ring, - typename IntersectionStrategy, + typename Strategy, typename DistanceStrategy, typename RobustPolicy > @@ -131,27 +131,6 @@ struct buffered_piece_collection typedef geometry::model::box box_type; - typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; - typedef typename IntersectionStrategy::envelope_strategy_type envelope_strategy_type; - typedef typename IntersectionStrategy::expand_strategy_type expand_strategy_type; - - typedef typename IntersectionStrategy::template area_strategy - < - point_type - >::type area_strategy_type; - - typedef typename area_strategy_type::template result_type - < - point_type - >::type area_result_type; - - typedef typename IntersectionStrategy::template point_in_geometry_strategy - < - point_type, - clockwise_ring_type - >::type point_in_geometry_strategy_type; - - typedef buffer_turn_info < point_type, @@ -232,23 +211,23 @@ struct buffered_piece_collection {} inline original_ring(clockwise_ring_type const& ring, - bool is_interior, bool has_interiors, - envelope_strategy_type const& envelope_strategy, - expand_strategy_type const& expand_strategy) + bool is_interior, bool has_interiors, + Strategy const& strategy) : m_ring(ring) , m_is_interior(is_interior) , m_has_interiors(has_interiors) { - geometry::envelope(m_ring, m_box, envelope_strategy); + geometry::envelope(m_ring, m_box, strategy); // create monotonic sections in x-dimension // The dimension is critical because the direction is later used // in the optimization for within checks using winding strategy // and this strategy is scanning in x direction. typedef std::integer_sequence dimensions; - geometry::sectionalize(m_ring, - detail::no_rescale_policy(), m_sections, - envelope_strategy, expand_strategy); + geometry::sectionalize + < + false, dimensions + >(m_ring, detail::no_rescale_policy(), m_sections, strategy); } clockwise_ring_type m_ring; @@ -295,31 +274,18 @@ struct buffered_piece_collection cluster_type m_clusters; - IntersectionStrategy m_intersection_strategy; + Strategy m_strategy; DistanceStrategy m_distance_strategy; - side_strategy_type m_side_strategy; - area_strategy_type m_area_strategy; - envelope_strategy_type m_envelope_strategy; - expand_strategy_type m_expand_strategy; - point_in_geometry_strategy_type m_point_in_geometry_strategy; - RobustPolicy const& m_robust_policy; - buffered_piece_collection(IntersectionStrategy const& intersection_strategy, + buffered_piece_collection(Strategy const& strategy, DistanceStrategy const& distance_strategy, RobustPolicy const& robust_policy) : m_first_piece_index(-1) , m_deflate(false) , m_has_deflated(false) - , m_intersection_strategy(intersection_strategy) + , m_strategy(strategy) , m_distance_strategy(distance_strategy) - , m_side_strategy(intersection_strategy.get_side_strategy()) - , m_area_strategy(intersection_strategy - .template get_area_strategy()) - , m_envelope_strategy(intersection_strategy.get_envelope_strategy()) - , m_expand_strategy(intersection_strategy.get_expand_strategy()) - , m_point_in_geometry_strategy(intersection_strategy - .template get_point_in_geometry_strategy()) , m_robust_policy(robust_policy) {} @@ -393,8 +359,7 @@ struct buffered_piece_collection it != boost::end(m_linear_end_points); ++it) { - if (detail::equals::equals_point_point(turn.point, *it, - m_intersection_strategy.get_equals_point_point_strategy())) + if (detail::equals::equals_point_point(turn.point, *it, m_strategy)) { turn.is_linear_end_point = true; } @@ -468,20 +433,11 @@ struct buffered_piece_collection // Check if a turn is inside any of the originals inline void check_turn_in_original() { - typedef turn_in_original_overlaps_box - < - typename IntersectionStrategy::disjoint_point_box_strategy_type - > turn_in_original_overlaps_box_type; - typedef original_overlaps_box - < - typename IntersectionStrategy::disjoint_box_box_strategy_type - > original_overlaps_box_type; - turn_in_original_visitor < turn_vector_type, - point_in_geometry_strategy_type - > visitor(m_turns, m_point_in_geometry_strategy); + Strategy + > visitor(m_turns, m_strategy); geometry::partition < @@ -489,8 +445,10 @@ struct buffered_piece_collection include_turn_policy, detail::partition::include_all_policy >::apply(m_turns, original_rings, visitor, - turn_get_box(), turn_in_original_overlaps_box_type(), - original_get_box(), original_overlaps_box_type()); + turn_get_box(m_strategy), + turn_in_original_overlaps_box(m_strategy), + original_get_box(m_strategy), + original_overlaps_box(m_strategy)); bool const deflate = m_distance_strategy.negative(); @@ -560,10 +518,11 @@ struct buffered_piece_collection } // Calculate envelopes for piece borders - border.get_properties_of_border(pc.type == geometry::strategy::buffer::buffered_point, pc.m_center); + border.get_properties_of_border(pc.type == geometry::strategy::buffer::buffered_point, + pc.m_center, m_strategy); if (! pc.is_flat_end && ! pc.is_flat_start) { - border.get_properties_of_offsetted_ring_part(m_side_strategy); + border.get_properties_of_offsetted_ring_part(m_strategy); } } } @@ -580,28 +539,19 @@ struct buffered_piece_collection piece_vector_type, buffered_ring_collection >, turn_vector_type, - IntersectionStrategy, + Strategy, RobustPolicy > visitor(m_pieces, offsetted_rings, m_turns, - m_intersection_strategy, m_robust_policy); + m_strategy, m_robust_policy); - typedef detail::section::get_section_box - < - typename IntersectionStrategy::expand_box_strategy_type - > get_section_box_type; - typedef detail::section::overlaps_section_box - < - typename IntersectionStrategy::disjoint_box_box_strategy_type - > overlaps_section_box_type; + detail::sectionalize::enlarge_sections(monotonic_sections, m_strategy); - detail::sectionalize::enlarge_sections(monotonic_sections, - m_envelope_strategy); geometry::partition < robust_box_type >::apply(monotonic_sections, visitor, - get_section_box_type(), - overlaps_section_box_type()); + detail::section::get_section_box(m_strategy), + detail::section::overlaps_section_box(m_strategy)); } update_turn_administration(); @@ -614,21 +564,14 @@ struct buffered_piece_collection turn_vector_type, piece_vector_type, DistanceStrategy > visitor(m_turns, m_pieces, m_distance_strategy); - typedef turn_overlaps_box - < - typename IntersectionStrategy::disjoint_point_box_strategy_type - > turn_overlaps_box_type; - typedef piece_overlaps_box - < - typename IntersectionStrategy::disjoint_box_box_strategy_type - > piece_overlaps_box_type; - geometry::partition < box_type >::apply(m_turns, m_pieces, visitor, - turn_get_box(), turn_overlaps_box_type(), - piece_get_box(), piece_overlaps_box_type()); + turn_get_box(m_strategy), + turn_overlaps_box(m_strategy), + piece_get_box(m_strategy), + piece_overlaps_box(m_strategy)); } } @@ -771,7 +714,7 @@ struct buffered_piece_collection original_rings.back() = original_ring(clockwise_ring, is_interior, has_interiors, - m_envelope_strategy, m_expand_strategy); + m_strategy); } } @@ -870,6 +813,7 @@ struct buffered_piece_collection boost::begin(ring) + pc.first_seg_id.segment_index, boost::begin(ring) + pc.beyond_last_segment_index, m_robust_policy, + m_strategy, ring_id, 10); } @@ -1042,7 +986,7 @@ struct buffered_piece_collection enrich_intersection_points(m_turns, m_clusters, offsetted_rings, offsetted_rings, m_robust_policy, - m_intersection_strategy); + m_strategy); } // Discards all rings which do have not-OK intersection points only. @@ -1067,8 +1011,6 @@ struct buffered_piece_collection inline bool point_coveredby_original(point_type const& point) { - typedef typename IntersectionStrategy::disjoint_point_box_strategy_type d_pb_strategy_type; - signed_size_type count_in_original = 0; // Check of the robust point of this outputted ring is in @@ -1087,14 +1029,14 @@ struct buffered_piece_collection } if (detail::disjoint::disjoint_point_box(point, original.m_box, - d_pb_strategy_type())) + m_strategy)) { continue; } int const geometry_code - = detail::within::point_in_geometry(point, - original.m_ring, m_point_in_geometry_strategy); + = detail::within::point_in_geometry(point, original.m_ring, + m_strategy); if (geometry_code == -1) { @@ -1133,7 +1075,7 @@ struct buffered_piece_collection buffered_ring& ring = *it; if (! ring.has_intersections() && boost::size(ring) > 0u - && geometry::area(ring, m_area_strategy) < 0) + && geometry::area(ring, m_strategy) < 0) { if (! point_coveredby_original(geometry::range::front(ring))) { @@ -1173,7 +1115,7 @@ struct buffered_piece_collection traversed_rings.clear(); buffer_overlay_visitor visitor; traverser::apply(offsetted_rings, offsetted_rings, - m_intersection_strategy, m_robust_policy, + m_strategy, m_robust_policy, m_turns, traversed_rings, turn_info_per_ring, m_clusters, visitor); @@ -1202,7 +1144,14 @@ struct buffered_piece_collection template inline OutputIterator assign(OutputIterator out) const { - typedef detail::overlay::ring_properties properties; + typedef typename geometry::area_result + < + buffered_ring, Strategy + >::type area_result_type; + typedef detail::overlay::ring_properties + < + point_type, area_result_type + > properties; std::map selected; @@ -1218,7 +1167,7 @@ struct buffered_piece_collection if (! it->has_intersections() && ! it->is_untouched_outside_original) { - properties p = properties(*it, m_area_strategy); + properties p = properties(*it, m_strategy); if (p.valid) { ring_identifier id(0, index, -1); @@ -1234,7 +1183,7 @@ struct buffered_piece_collection it != boost::end(traversed_rings); ++it, ++index) { - properties p = properties(*it, m_area_strategy); + properties p = properties(*it, m_strategy); if (p.valid) { ring_identifier id(2, index, -1); @@ -1243,9 +1192,9 @@ struct buffered_piece_collection } detail::overlay::assign_parents(offsetted_rings, traversed_rings, - selected, m_intersection_strategy); + selected, m_strategy); return detail::overlay::add_rings(selected, offsetted_rings, traversed_rings, out, - m_area_strategy); + m_strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp index d736db57b..2e75a6479 100644 --- a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp @@ -117,7 +117,7 @@ template typename Pieces, typename Rings, typename Turns, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy > class piece_turn_visitor @@ -125,7 +125,7 @@ class piece_turn_visitor Pieces const& m_pieces; Rings const& m_rings; Turns& m_turns; - IntersectionStrategy const& m_intersection_strategy; + Strategy const& m_strategy; RobustPolicy const& m_robust_policy; template @@ -271,7 +271,7 @@ class piece_turn_visitor turn_policy::apply(unique_sub_range1, unique_sub_range2, the_model, - m_intersection_strategy, + m_strategy, m_robust_policy, std::back_inserter(m_turns)); } @@ -283,12 +283,12 @@ public: piece_turn_visitor(Pieces const& pieces, Rings const& ring_collection, Turns& turns, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy) : m_pieces(pieces) , m_rings(ring_collection) , m_turns(turns) - , m_intersection_strategy(intersection_strategy) + , m_strategy(strategy) , m_robust_policy(robust_policy) {} @@ -307,7 +307,7 @@ public: || is_on_same_convex_ring(piece1, piece2) || detail::disjoint::disjoint_box_box(section1.bounding_box, section2.bounding_box, - m_intersection_strategy.get_disjoint_box_box_strategy()) ) + m_strategy) ) { return true; } diff --git a/include/boost/geometry/algorithms/detail/buffer/piece_border.hpp b/include/boost/geometry/algorithms/detail/buffer/piece_border.hpp index 026808edf..ecd03d9c8 100644 --- a/include/boost/geometry/algorithms/detail/buffer/piece_border.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/piece_border.hpp @@ -167,9 +167,11 @@ struct piece_border return result; } - void get_properties_of_border(bool is_point_buffer, Point const& center) + template + void get_properties_of_border(bool is_point_buffer, Point const& center, + Strategy const& strategy) { - m_has_envelope = calculate_envelope(m_envelope); + m_has_envelope = calculate_envelope(m_envelope, strategy); if (m_has_envelope) { // Take roundings into account, enlarge box @@ -182,8 +184,8 @@ struct piece_border } } - template - void get_properties_of_offsetted_ring_part(SideStrategy const& strategy) + template + void get_properties_of_offsetted_ring_part(Strategy const& strategy) { if (! ring_or_original_empty()) { @@ -209,16 +211,16 @@ struct piece_border m_originals[m_original_size++] = point; } - template - bool calculate_envelope(Box& envelope) const + template + bool calculate_envelope(Box& envelope, Strategy const& strategy) const { geometry::assign_inverse(envelope); if (ring_or_original_empty()) { return false; } - expand_envelope(envelope, m_ring->begin() + m_begin, m_ring->begin() + m_end); - expand_envelope(envelope, m_originals.begin(), m_originals.begin() + m_original_size); + expand_envelope(envelope, m_ring->begin() + m_begin, m_ring->begin() + m_end, strategy); + expand_envelope(envelope, m_originals.begin(), m_originals.begin() + m_original_size, strategy); return true; } @@ -333,8 +335,8 @@ private : return true; } - template - bool step(TurnPoint const& point, Point const& p1, Point const& p2, Strategy const & strategy, + template + bool step(TurnPoint const& point, Point const& p1, Point const& p2, TiRStrategy const & strategy, geometry::strategy::buffer::place_on_ring_type place_on_ring, State& state) const { // A step between original/offsetted ring is always convex @@ -357,22 +359,17 @@ private : return strategy.apply(point, p1, p2, dm, place_on_ring, state); } - template - void expand_envelope(Box& envelope, It begin, It end) const + template + void expand_envelope(Box& envelope, It begin, It end, Strategy const& strategy) const { - typedef typename strategy::expand::services::default_strategy - < - point_tag, typename cs_tag::type - >::type expand_strategy_type; - for (It it = begin; it != end; ++it) { - geometry::expand(envelope, *it, expand_strategy_type()); + geometry::expand(envelope, *it, strategy); } } - template - bool is_convex(SideStrategy const& strategy) const + template + bool is_convex(Strategy const& strategy) const { if (ring_or_original_empty()) { @@ -416,8 +413,8 @@ private : return result; } - template - bool is_convex(Point& previous, Point& current, It begin, It end, SideStrategy const& strategy) const + template + bool is_convex(Point& previous, Point& current, It begin, It end, Strategy const& strategy) const { for (It it = begin; it != end; ++it) { @@ -429,19 +426,16 @@ private : return true; } - template - bool is_convex(Point& previous, Point& current, Point const& next, SideStrategy const& strategy) const + template + bool is_convex(Point& previous, Point& current, Point const& next, Strategy const& strategy) const { - typename SideStrategy::equals_point_point_strategy_type const - eq_pp_strategy = strategy.get_equals_point_point_strategy(); - - int const side = strategy.apply(previous, current, next); + int const side = strategy.side().apply(previous, current, next); if (side == 1) { // Next is on the left side of clockwise ring: piece is not convex return false; } - if (! equals::equals_point_point(current, next, eq_pp_strategy)) + if (! equals::equals_point_point(current, next, strategy)) { previous = current; current = next; diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp index d51220dac..b1930dc0c 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2016, 2018. -// Modifications copyright (c) 2016-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2020. +// Modifications copyright (c) 2016-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -31,31 +31,40 @@ namespace boost { namespace geometry namespace detail { namespace buffer { + +template struct original_get_box { + explicit original_get_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Original const& original) + inline void apply(Box& total, Original const& original) const { assert_coordinate_type_equal(total, original.m_box); - typedef typename strategy::expand::services::default_strategy - < - box_tag, typename cs_tag::type - >::type expand_strategy_type; - - geometry::expand(total, original.m_box, expand_strategy_type()); + geometry::expand(total, original.m_box, m_strategy); } + + Strategy const& m_strategy; }; -template +template struct original_overlaps_box { + explicit original_overlaps_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Original const& original) + inline bool apply(Box const& box, Original const& original) const { assert_coordinate_type_equal(box, original.m_box); return ! detail::disjoint::disjoint_box_box(box, original.m_box, - DisjointBoxBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; struct include_turn_policy @@ -67,11 +76,15 @@ struct include_turn_policy } }; -template +template struct turn_in_original_overlaps_box { + explicit turn_in_original_overlaps_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Turn const& turn) + inline bool apply(Box const& box, Turn const& turn) const { if (! turn.is_turn_traversable || turn.within_original) { @@ -80,8 +93,10 @@ struct turn_in_original_overlaps_box } return ! geometry::detail::disjoint::disjoint_point_box( - turn.point, box, DisjointPointBoxStrategy()); + turn.point, box, m_strategy); } + + Strategy const& m_strategy; }; //! Check if specified is in range of specified iterators @@ -210,13 +225,13 @@ inline int point_in_original(Point const& point, Original const& original, } -template +template class turn_in_original_visitor { public: - turn_in_original_visitor(Turns& turns, PointInGeometryStrategy const& strategy) + turn_in_original_visitor(Turns& turns, Strategy const& strategy) : m_mutable_turns(turns) - , m_point_in_geometry_strategy(strategy) + , m_strategy(strategy) {} template @@ -234,13 +249,14 @@ public: return true; } - if (geometry::disjoint(turn.point, original.m_box)) + if (geometry::disjoint(turn.point, original.m_box, m_strategy)) { // Skip all disjoint return true; } - int const code = point_in_original(turn.point, original, m_point_in_geometry_strategy); + int const code = point_in_original(turn.point, original, + m_strategy.relate(turn.point, original.m_ring)); if (code == -1) { @@ -277,7 +293,7 @@ public: private : Turns& m_mutable_turns; - PointInGeometryStrategy const& m_point_in_geometry_strategy; + Strategy const& m_strategy; }; diff --git a/include/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp b/include/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp index a3e99bec7..1cf9ddc8a 100644 --- a/include/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp +++ b/include/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp @@ -54,13 +54,11 @@ private: QueryRangeIterator& qit_min, Distance& dist_min) { - typedef strategy::index::services::from_strategy - < - Strategy - > index_strategy_from; + using strategies::index::services::strategy_converter; typedef index::parameters < - index::linear<8>, typename index_strategy_from::type + index::linear<8>, + decltype(strategy_converter::get(strategy)) > index_parameters_type; typedef index::rtree rtree_type; @@ -73,7 +71,7 @@ private: // create -- packing algorithm rtree_type rt(rtree_first, rtree_last, index_parameters_type(index::linear<8>(), - index_strategy_from::get(strategy))); + strategy_converter::get(strategy))); RTreeValueType t_v; bool first = true; diff --git a/include/boost/geometry/algorithms/detail/covered_by/implementation.hpp b/include/boost/geometry/algorithms/detail/covered_by/implementation.hpp index b180a3d5a..80cdd539f 100644 --- a/include/boost/geometry/algorithms/detail/covered_by/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/covered_by/implementation.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013, 2014, 2017, 2019. -// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -66,8 +66,7 @@ struct covered_by template static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) { - ::boost::ignore_unused(strategy); - return strategy.apply(point, box); + return strategy.covered_by(point, box).apply(point, box); } }; @@ -78,8 +77,7 @@ struct covered_by static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { assert_dimension_equal(); - ::boost::ignore_unused(strategy); - return strategy.apply(box1, box2); + return strategy.covered_by(box1, box2).apply(box1, box2); } }; diff --git a/include/boost/geometry/algorithms/detail/covered_by/interface.hpp b/include/boost/geometry/algorithms/detail/covered_by/interface.hpp index 4749ed168..3d7804adb 100644 --- a/include/boost/geometry/algorithms/detail/covered_by/interface.hpp +++ b/include/boost/geometry/algorithms/detail/covered_by/interface.hpp @@ -4,9 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013, 2014, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. - +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -30,6 +29,8 @@ #include #include #include +#include +#include namespace boost { namespace geometry @@ -56,9 +57,14 @@ struct covered_by namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct covered_by { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) @@ -68,23 +74,51 @@ struct covered_by concepts::check(); assert_dimension_equal(); - return dispatch::covered_by::apply(geometry1, - geometry2, - strategy); + return dispatch::covered_by + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); } +}; +template +struct covered_by +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + //using strategies::covered_by::services::strategy_converter; + using strategies::relate::services::strategy_converter; + + return covered_by + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct covered_by +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::covered_by::services::default_strategy + //typedef typename strategies::covered_by::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; - return covered_by::apply(geometry1, geometry2, strategy_type()); + return covered_by + < + strategy_type + >::apply(geometry1, geometry2, strategy_type()); } }; @@ -101,7 +135,7 @@ struct covered_by Geometry2 const& geometry2, Strategy const& strategy) { - return resolve_strategy::covered_by + return resolve_strategy::covered_by ::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp b/include/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp index b8c778856..934f90c87 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp @@ -60,13 +60,9 @@ inline bool rings_containing(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { - // TODO: This will be removed when IntersectionStrategy is replaced with - // UmbrellaStrategy - auto const pgs = strategy.template get_point_in_geometry_strategy(); - return geometry::detail::any_range_of(geometry2, [&](auto const& range) { - return point_on_border_covered_by(range, geometry1, pgs); + return point_on_border_covered_by(range, geometry1, strategy); }); } @@ -116,11 +112,9 @@ struct areal_box Box const& box, Strategy const& strategy) { - // TODO: This will be removed when UmbrellaStrategy is supported - auto const ds = strategy.get_disjoint_segment_box_strategy(); if (! geometry::all_segments_of(areal, [&](auto const& s) { - return disjoint_segment_box::apply(s, box, ds); + return disjoint_segment_box::apply(s, box, strategy); }) ) { return false; @@ -129,8 +123,7 @@ struct areal_box // If there is no intersection of any segment and box, // the box might be located inside areal geometry - if ( point_on_border_covered_by(box, areal, - strategy.template get_point_in_geometry_strategy()) ) + if ( point_on_border_covered_by(box, areal, strategy) ) { return false; } diff --git a/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp index 67f063321..8092ae4f8 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2018. -// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -43,8 +43,23 @@ namespace detail { namespace disjoint \note Is used from other algorithms, declared separately to avoid circular references */ -template -inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const&) +template +< + typename Box1, typename Box2, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const& strategy) +{ + typedef decltype(strategy.disjoint(box1, box2)) strategy_type; + return strategy_type::apply(box1, box2); +} + +template +< + typename Box1, typename Box2, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const& ) { return Strategy::apply(box1, box2); } @@ -63,9 +78,10 @@ template struct disjoint { template - static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&) + static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { - return Strategy::apply(box1, box2); + typedef decltype(strategy.disjoint(box1, box2)) strategy_type; + return strategy_type::apply(box1, box2); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/interface.hpp b/include/boost/geometry/algorithms/detail/disjoint/interface.hpp index fc4aecbb0..0af19dced 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/interface.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/interface.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -32,7 +32,10 @@ #include +#include +#include #include +#include namespace boost { namespace geometry @@ -41,9 +44,14 @@ namespace boost { namespace geometry namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct disjoint { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) @@ -53,13 +61,37 @@ struct disjoint Geometry1, Geometry2 >::apply(geometry1, geometry2, strategy); } +}; +template +struct disjoint +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + //using strategies::disjoint::services::strategy_converter; + using strategies::relate::services::strategy_converter; + + return dispatch::disjoint + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct disjoint +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::disjoint::services::default_strategy + //typedef typename strategies::disjoint::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; @@ -88,7 +120,10 @@ struct disjoint Geometry2 const >(); - return resolve_strategy::disjoint::apply(geometry1, geometry2, strategy); + return resolve_strategy::disjoint + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp b/include/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp index a56f56e62..d5045189a 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp @@ -74,7 +74,7 @@ struct disjoint_no_intersections_policy point1_type p; geometry::point_on_border(p, g1); - return !geometry::covered_by(p, g2, strategy); + return ! geometry::covered_by(p, g2, strategy); } }; @@ -120,9 +120,7 @@ struct disjoint_linear_areal return false; } - return NoIntersectionsPolicy - ::apply(g1, g2, - strategy.template get_point_in_geometry_strategy()); + return NoIntersectionsPolicy::apply(g1, g2, strategy); } }; @@ -195,8 +193,7 @@ public: typename point_type::type p; detail::assign_point_from_index<0>(segment, p); - return !geometry::covered_by(p, polygon, - strategy.template get_point_in_geometry_strategy()); + return ! geometry::covered_by(p, polygon, strategy); } }; @@ -235,8 +232,7 @@ struct disjoint_segment_areal typename point_type::type p; detail::assign_point_from_index<0>(segment, p); - return !geometry::covered_by(p, ring, - strategy.template get_point_in_geometry_strategy()); + return ! geometry::covered_by(p, ring, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp index 08a714b36..fb667cb1e 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp @@ -65,8 +65,8 @@ struct disjoint_segment detail::segment_as_subrange sub_range1(segment1); detail::segment_as_subrange sub_range2(segment2); - intersection_return_type is = strategy.apply(sub_range1, sub_range2, - intersection_policy()); + intersection_return_type is = strategy.relate().apply(sub_range1, sub_range2, + intersection_policy()); return is.count == 0; } diff --git a/include/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp index 0f0036117..1999f10f3 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp @@ -58,8 +58,7 @@ struct disjoint_point_segment_or_box return dispatch::disjoint < Point, Segment - >::apply(point, segment, - strategy.template get_point_in_geometry_strategy()); + >::apply(point, segment, strategy); } }; @@ -72,8 +71,7 @@ struct disjoint_point_segment_or_box return dispatch::disjoint < Point, Box - >::apply(point, box, - strategy.get_disjoint_point_box_strategy()); + >::apply(point, box, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp index 54eaae86a..9e3a57a29 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp @@ -125,72 +125,78 @@ template class multipoint_linear { private: - template + template struct expand_box_point { + explicit expand_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Point const& point) + void apply(Box& total, Point const& point) const { - geometry::expand(total, point, ExpandPointBoxStrategy()); + geometry::expand(total, point, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct expand_box_segment { - explicit expand_box_segment(EnvelopeStrategy const& strategy) + explicit expand_box_segment(Strategy const& strategy) : m_strategy(strategy) {} template - inline void apply(Box& total, Segment const& segment) const + void apply(Box& total, Segment const& segment) const { geometry::expand(total, geometry::return_envelope(segment, m_strategy), - // TEMP - envelope umbrella strategy also contains - // expand strategies - strategies::envelope::services::strategy_converter - < - EnvelopeStrategy - >::get(m_strategy)); + m_strategy); } - EnvelopeStrategy const& m_strategy; + Strategy const& m_strategy; }; - template + template struct overlaps_box_point { + explicit overlaps_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Point const& point) + bool apply(Box const& box, Point const& point) const { - // The default strategy is enough in this case return ! detail::disjoint::disjoint_point_box(point, box, - DisjointPointBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_segment { - explicit overlaps_box_segment(DisjointStrategy const& strategy) + explicit overlaps_box_segment(Strategy const& strategy) : m_strategy(strategy) {} template - inline bool apply(Box const& box, Segment const& segment) const + bool apply(Box const& box, Segment const& segment) const { return ! dispatch::disjoint::apply(segment, box, m_strategy); } - DisjointStrategy const& m_strategy; + Strategy const& m_strategy; }; - template + template class item_visitor_type { public: - item_visitor_type(PtSegStrategy const& strategy) + item_visitor_type(Strategy const& strategy) : m_intersection_found(false) , m_strategy(strategy) {} @@ -211,7 +217,7 @@ private: private: bool m_intersection_found; - PtSegStrategy const& m_strategy; + Strategy const& m_strategy; }; // structs for partition -- end @@ -245,11 +251,6 @@ public: { item_visitor_type visitor(strategy); - typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type; - typedef typename Strategy::envelope_strategy_type envelope_strategy_type; - typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type; - typedef typename Strategy::disjoint_point_box_strategy_type disjoint_pb_strategy_type; - // TODO: disjoint Segment/Box may be called in partition multiple times // possibly for non-cartesian segments which could be slow. We should consider // passing a range of bounding boxes of segments after calculating them once. @@ -259,16 +260,17 @@ public: < geometry::model::box::type> >::apply(multipoint, segment_range(linear), visitor, - expand_box_point(), - overlaps_box_point(), - expand_box_segment(strategy.get_envelope_strategy()), - overlaps_box_segment(strategy.get_disjoint_strategy())); + expand_box_point(strategy), + overlaps_box_point(strategy), + expand_box_segment(strategy), + overlaps_box_segment(strategy)); return ! visitor.intersection_found(); } template - static inline bool apply(Linear const& linear, MultiPoint const& multipoint, Strategy const& strategy) + static inline bool apply(Linear const& linear, MultiPoint const& multipoint, + Strategy const& strategy) { return apply(multipoint, linear, strategy); } @@ -284,21 +286,19 @@ public: SingleGeometry const& single_geometry, Strategy const& strategy) { - typedef typename Strategy::disjoint_point_box_strategy_type d_pb_strategy_type; - typedef typename point_type::type point1_type; typedef typename point_type::type point2_type; typedef model::box box2_type; box2_type box2; - geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy()); + geometry::envelope(single_geometry, box2, strategy); geometry::detail::expand_by_epsilon(box2); typedef typename boost::range_const_iterator::type iterator; for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) { // The default strategy is enough for Point/Box - if (! detail::disjoint::disjoint_point_box(*it, box2, d_pb_strategy_type()) + if (! detail::disjoint::disjoint_point_box(*it, box2, strategy) && ! dispatch::disjoint::apply(*it, single_geometry, strategy)) { return false; @@ -309,7 +309,8 @@ public: } template - static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point, Strategy const& strategy) + static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point, + Strategy const& strategy) { return apply(multi_point, single_geometry, strategy); } @@ -320,56 +321,77 @@ template class multi_point_multi_geometry { private: - template + template struct expand_box_point { + explicit expand_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Point const& point) + void apply(Box& total, Point const& point) const { - geometry::expand(total, point, ExpandPointStrategy()); + geometry::expand(total, point, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct expand_box_box_pair { + explicit expand_box_box_pair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - inline void apply(Box& total, BoxPair const& box_pair) const + void apply(Box& total, BoxPair const& box_pair) const { - geometry::expand(total, box_pair.first, ExpandBoxStrategy()); + geometry::expand(total, box_pair.first, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_point { + explicit overlaps_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Point const& point) + bool apply(Box const& box, Point const& point) const { - // The default strategy is enough for Point/Box - return ! detail::disjoint::disjoint_point_box(point, box, - DisjointPointBoxStrategy()); + return ! detail::disjoint::disjoint_point_box(point, box, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_box_pair { + explicit overlaps_box_box_pair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - inline bool apply(Box const& box, BoxPair const& box_pair) const + bool apply(Box const& box, BoxPair const& box_pair) const { - // The default strategy is enough for Box/Box return ! detail::disjoint::disjoint_box_box(box_pair.first, box, - DisjointBoxBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; - template + template class item_visitor_type { public: item_visitor_type(MultiGeometry const& multi_geometry, - PtSegStrategy const& strategy) + Strategy const& strategy) : m_intersection_found(false) , m_multi_geometry(multi_geometry) , m_strategy(strategy) @@ -378,14 +400,15 @@ private: template inline bool apply(Point const& point, BoxPair const& box_pair) { - typedef typename PtSegStrategy::disjoint_point_box_strategy_type d_pb_strategy_type; - typedef typename boost::range_value::type single_type; // The default strategy is enough for Point/Box if (! m_intersection_found - && ! detail::disjoint::disjoint_point_box(point, box_pair.first, d_pb_strategy_type()) - && ! dispatch::disjoint::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy)) + && ! detail::disjoint::disjoint_point_box(point, box_pair.first, m_strategy) + && ! dispatch::disjoint + < + Point, single_type + >::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy)) { m_intersection_found = true; return false; @@ -398,7 +421,7 @@ private: private: bool m_intersection_found; MultiGeometry const& m_multi_geometry; - PtSegStrategy const& m_strategy; + Strategy const& m_strategy; }; // structs for partition -- end @@ -411,53 +434,26 @@ public: typedef model::box box1_type; typedef model::box box2_type; typedef std::pair box_pair_type; - - typename Strategy::envelope_strategy_type const - envelope_strategy = strategy.get_envelope_strategy(); std::size_t count2 = boost::size(multi_geometry); std::vector boxes(count2); for (std::size_t i = 0 ; i < count2 ; ++i) { - geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy); + geometry::envelope(range::at(multi_geometry, i), boxes[i].first, strategy); geometry::detail::expand_by_epsilon(boxes[i].first); boxes[i].second = i; } item_visitor_type visitor(multi_geometry, strategy); - typedef expand_box_point - < - typename Strategy::expand_point_strategy_type - > expand_box_point_type; - typedef overlaps_box_point - < - typename Strategy::disjoint_point_box_strategy_type - > overlaps_box_point_type; - typedef expand_box_box_pair - < - // TEMP - envelope umbrella strategy also contains - // expand strategies - decltype(strategies::envelope::services::strategy_converter - < - typename Strategy::envelope_strategy_type - >::get(strategy.get_envelope_strategy()) - .expand(std::declval(), - std::declval())) - > expand_box_box_pair_type; - typedef overlaps_box_box_pair - < - typename Strategy::disjoint_box_box_strategy_type - > overlaps_box_box_pair_type; - geometry::partition < box1_type >::apply(multi_point, boxes, visitor, - expand_box_point_type(), - overlaps_box_point_type(), - expand_box_box_pair_type(), - overlaps_box_box_pair_type()); + expand_box_point(strategy), + overlaps_box_point(strategy), + expand_box_box_pair(strategy), + overlaps_box_box_pair(strategy)); return ! visitor.intersection_found(); } diff --git a/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp index b4c402646..99cdda9ed 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2013-2018. -// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -41,8 +41,26 @@ namespace detail { namespace disjoint /*! \brief Internal utility function to detect if point/box are disjoint */ -template -inline bool disjoint_point_box(Point const& point, Box const& box, Strategy const& ) +template +< + typename Point, typename Box, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool disjoint_point_box(Point const& point, Box const& box, + Strategy const& strategy) +{ + typedef decltype(strategy.covered_by(point, box)) strategy_type; + // ! covered_by(point, box) + return ! strategy_type::apply(point, box); +} + +template +< + typename Point, typename Box, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool disjoint_point_box(Point const& point, Box const& box, + Strategy const& ) { // ! covered_by(point, box) return ! Strategy::apply(point, box); @@ -62,10 +80,12 @@ template struct disjoint { template - static inline bool apply(Point const& point, Box const& box, Strategy const& ) + static inline bool apply(Point const& point, Box const& box, + Strategy const& strategy) { + typedef decltype(strategy.covered_by(point, box)) strategy_type; // ! covered_by(point, box) - return ! Strategy::apply(point, box); + return ! strategy_type::apply(point, box); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp b/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp index f91712934..af28ecaff 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. -// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -22,11 +22,14 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP #include +#include #include #include +#include + // For backward compatibility #include #include @@ -46,10 +49,28 @@ namespace detail { namespace disjoint \brief Internal utility function to detect of points are disjoint \note To avoid circular references */ -template +template +< + typename Point1, typename Point2, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2, + Strategy const& strategy) +{ + typedef decltype(strategy.relate(point1, point2)) strategy_type; + // ! within(point1, point2) + return ! strategy_type::apply(point1, point2); +} + +template +< + typename Point1, typename Point2, typename Strategy, + std::enable_if_t::value, int> = 0 +> inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2, Strategy const& ) { + // ! within(point1, point2) return ! Strategy::apply(point1, point2); } @@ -68,9 +89,11 @@ struct disjoint { template static inline bool apply(Point1 const& point1, Point2 const& point2, - Strategy const& ) + Strategy const& strategy) { - return ! Strategy::apply(point1, point2); + typedef decltype(strategy.relate(point1, point2)) strategy_type; + // ! within(point1, point2) + return ! strategy_type::apply(point1, point2); } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp index ae89d1d6b..575e55bda 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp @@ -247,7 +247,7 @@ struct disjoint_segment_box Box const& box, Strategy const& strategy) { - return strategy.apply(segment, box); + return strategy.disjoint(segment, box).apply(segment, box); } }; diff --git a/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp b/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp index 6874fe2d7..1ca1ae1d7 100644 --- a/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp @@ -41,6 +41,7 @@ #include #include +#include #include @@ -164,8 +165,12 @@ struct point_to_ring Strategy const& strategy) { // TODO: pass strategy - if (within::within_point_geometry(point, ring, - strategy.get_point_in_geometry_strategy())) + auto const s = strategies::relate::services::strategy_converter + < + decltype(strategy.get_point_in_geometry_strategy()) + >::get(strategy.get_point_in_geometry_strategy()); + + if (within::within_point_geometry(point, ring, s)) { return return_type(0); } @@ -207,11 +212,15 @@ private: InteriorRingIterator last, Strategy const& strategy) { + // TEMP: pass strategy + auto const s = strategies::relate::services::strategy_converter + < + decltype(strategy.get_point_in_geometry_strategy()) + >::get(strategy.get_point_in_geometry_strategy()); + for (InteriorRingIterator it = first; it != last; ++it) { - // TODO: pass strategy - if (within::within_point_geometry(point, *it, - strategy.get_point_in_geometry_strategy())) + if (within::within_point_geometry(point, *it, s)) { // the point is inside a polygon hole, so its distance // to the polygon its distance to the polygon's @@ -240,9 +249,13 @@ public: Polygon const& polygon, Strategy const& strategy) { - // TODO: pass strategy - if (! within::covered_by_point_geometry(point, exterior_ring(polygon), - strategy.get_point_in_geometry_strategy())) + // TEMP: pass strategy + auto const s = strategies::relate::services::strategy_converter + < + decltype(strategy.get_point_in_geometry_strategy()) + >::get(strategy.get_point_in_geometry_strategy()); + + if (! within::covered_by_point_geometry(point, exterior_ring(polygon), s)) { // the point is outside the exterior ring, so its distance // to the polygon is its distance to the polygon's exterior ring @@ -340,8 +353,12 @@ struct point_to_multigeometry Strategy const& strategy) { // TODO: pass strategy - if (within::covered_by_point_geometry(point, multipolygon, - strategy.get_point_in_geometry_strategy())) + auto const s = strategies::relate::services::strategy_converter + < + decltype(strategy.get_point_in_geometry_strategy()) + >::get(strategy.get_point_in_geometry_strategy()); + + if (within::covered_by_point_geometry(point, multipolygon, s)) { return 0; } diff --git a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp index 1f381970d..0bf37569b 100644 --- a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp +++ b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp @@ -58,17 +58,20 @@ namespace detail { namespace distance { -// TODO: Take strategy -template -inline bool intersects_segment_box(Segment const& segment, Box const& box) +template +inline bool intersects_segment_box(Segment const& segment, Box const& box, + Strategy const& strategy) { - typedef typename strategy::disjoint::services::default_strategy + // TODO: pass strategy + auto const s = strategies::relate::services::strategy_converter < - Segment, Box - >::type strategy_type; + // This is the only strategy defined in distance segment/box + // strategies that carries the information about the spheroid + // so use it for now. + decltype(strategy.get_side_strategy()) + >::get(strategy.get_side_strategy()); - return ! detail::disjoint::disjoint_segment_box::apply(segment, box, - strategy_type()); + return ! detail::disjoint::disjoint_segment_box::apply(segment, box, s); } @@ -114,7 +117,7 @@ public: Strategy const& strategy, bool check_intersection = true) { - if (check_intersection && intersects_segment_box(segment, box)) + if (check_intersection && intersects_segment_box(segment, box, strategy)) { return 0; } @@ -229,7 +232,7 @@ public: Strategy const& strategy, bool check_intersection = true) { - if (check_intersection && intersects_segment_box(segment, box)) + if (check_intersection && intersects_segment_box(segment, box, strategy)) { return 0; } diff --git a/include/boost/geometry/algorithms/detail/equals/implementation.hpp b/include/boost/geometry/algorithms/detail/equals/implementation.hpp index cb422cbc3..f51923474 100644 --- a/include/boost/geometry/algorithms/detail/equals/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/equals/implementation.hpp @@ -64,9 +64,11 @@ template struct point_point { template - static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& ) + static inline bool apply(Point1 const& point1, Point2 const& point2, + Strategy const& strategy) { - return Strategy::apply(point1, point2); + typedef decltype(strategy.relate(point1, point2)) strategy_type; + return strategy_type::apply(point1, point2); } }; @@ -107,25 +109,22 @@ struct segment_segment static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& strategy) { - typename Strategy::point_in_point_strategy_type const& - pt_pt_strategy = strategy.get_point_in_point_strategy(); - return equals::equals_point_point( indexed_point_view(segment1), indexed_point_view(segment2), - pt_pt_strategy) + strategy) ? equals::equals_point_point( indexed_point_view(segment1), indexed_point_view(segment2), - pt_pt_strategy) + strategy) : ( equals::equals_point_point( indexed_point_view(segment1), indexed_point_view(segment2), - pt_pt_strategy) + strategy) && equals::equals_point_point( indexed_point_view(segment1), indexed_point_view(segment2), - pt_pt_strategy) + strategy) ); } }; @@ -138,15 +137,13 @@ struct area_check Geometry2 const& geometry2, Strategy const& strategy) { - return geometry::math::equals( - geometry::area(geometry1, - strategy.template get_area_strategy()), - geometry::area(geometry2, - strategy.template get_area_strategy())); + return geometry::math::equals(geometry::area(geometry1, strategy), + geometry::area(geometry2, strategy)); } }; +/* struct length_check { template @@ -154,16 +151,14 @@ struct length_check Geometry2 const& geometry2, Strategy const& strategy) { - return geometry::math::equals( - geometry::length(geometry1, - strategy.template get_distance_strategy()), - geometry::length(geometry2, - strategy.template get_distance_strategy())); + return geometry::math::equals(geometry::length(geometry1, strategy), + geometry::length(geometry2, strategy)); } }; +*/ -template +template struct collected_vector { typedef typename geometry::select_most_precise @@ -179,7 +174,7 @@ struct collected_vector < calculation_type, Geometry1, - typename IntersectionStrategy::side_strategy_type + decltype(std::declval().side()) > type; }; diff --git a/include/boost/geometry/algorithms/detail/equals/interface.hpp b/include/boost/geometry/algorithms/detail/equals/interface.hpp index 1e4918836..93d8674e5 100644 --- a/include/boost/geometry/algorithms/detail/equals/interface.hpp +++ b/include/boost/geometry/algorithms/detail/equals/interface.hpp @@ -5,9 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014, 2015, 2016, 2017, 2019. -// Modifications copyright (c) 2014-2019 Oracle and/or its affiliates. - +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -30,13 +29,16 @@ #include #include +#include +#include #include #include #include -#include +#include +#include namespace boost { namespace geometry @@ -94,9 +96,14 @@ struct equals::value +> struct equals { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) @@ -106,13 +113,37 @@ struct equals Geometry1, Geometry2 >::apply(geometry1, geometry2, strategy); } +}; +template +struct equals +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + //using strategies::equals::services::strategy_converter; + using strategies::relate::services::strategy_converter; + + return dispatch::equals + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct equals +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::relate::services::default_strategy + //typedef typename strategies::within::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 @@ -145,7 +176,9 @@ struct equals >(); return resolve_strategy::equals - ::apply(geometry1, geometry2, strategy); + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/equals/point_point.hpp b/include/boost/geometry/algorithms/detail/equals/point_point.hpp index 06a784284..26eaff95c 100644 --- a/include/boost/geometry/algorithms/detail/equals/point_point.hpp +++ b/include/boost/geometry/algorithms/detail/equals/point_point.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2013-2018. -// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -22,6 +22,11 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP +#include + +#include + + namespace boost { namespace geometry { @@ -33,7 +38,23 @@ namespace detail { namespace equals \brief Internal utility function to detect of points are disjoint \note To avoid circular references */ -template +template +< + typename Point1, typename Point2, typename Strategy, + std::enable_if_t::value, int> = 0 +> +inline bool equals_point_point(Point1 const& point1, Point2 const& point2, + Strategy const& strategy) +{ + typedef decltype(strategy.relate(point1, point2)) strategy_type; + return strategy_type::apply(point1, point2); +} + +template +< + typename Point1, typename Point2, typename Strategy, + std::enable_if_t::value, int> = 0 +> inline bool equals_point_point(Point1 const& point1, Point2 const& point2, Strategy const& ) { diff --git a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp index 5dac1c3ff..805ab6754 100644 --- a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp +++ b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp @@ -136,27 +136,6 @@ inline bool has_self_intersections(Geometry const& geometry, return false; } -// For backward compatibility -template -inline bool has_self_intersections(Geometry const& geometry, - bool throw_on_self_intersection = true) -{ - typedef typename geometry::point_type::type point_type; - typedef typename geometry::rescale_policy_type::type - rescale_policy_type; - - typename strategy::intersection::services::default_strategy - < - typename cs_tag::type - >::type strategy; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry, strategy); - - return has_self_intersections(geometry, strategy, robust_policy, - throw_on_self_intersection); -} - }} // namespace detail::overlay #endif // DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp b/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp index 994c3c7da..bda208ea7 100644 --- a/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp +++ b/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp @@ -109,10 +109,10 @@ struct intersection_areal_areal_ < areal::index, TupledOut >::type areal_out_type; - typedef typename geometry::tuples::element - < - pointlike::index, TupledOut - >::type pointlike_out_type; + //typedef typename geometry::tuples::element + // < + // pointlike::index, TupledOut + // >::type pointlike_out_type; // NOTE: The same robust_policy is used in each call of // intersection_insert. Is that correct? @@ -157,11 +157,7 @@ struct intersection_areal_areal_ areal_out_boundary, robust_policy, pointlike::get(geometry_out), - strategy.template get_point_in_geometry_strategy - < - pointlike_out_type, - areal_out_boundary_type - >()); + strategy); } return; diff --git a/include/boost/geometry/algorithms/detail/intersection/interface.hpp b/include/boost/geometry/algorithms/detail/intersection/interface.hpp index e3258eb93..fcd7e959e 100644 --- a/include/boost/geometry/algorithms/detail/intersection/interface.hpp +++ b/include/boost/geometry/algorithms/detail/intersection/interface.hpp @@ -2,9 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014, 2017, 2019. -// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates. - +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -23,6 +22,8 @@ #include #include #include +#include +#include #include @@ -108,14 +109,18 @@ struct intersection namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct intersection { template < typename Geometry1, typename Geometry2, - typename GeometryOut, - typename Strategy + typename GeometryOut > static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, @@ -140,7 +145,34 @@ struct intersection >::apply(geometry1, geometry2, robust_policy, geometry_out, strategy); } +}; +template +struct intersection +{ + template + < + typename Geometry1, + typename Geometry2, + typename GeometryOut + > + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + GeometryOut & geometry_out, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + return intersection + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, geometry_out, + strategy_converter::get(strategy)); + } +}; + +template <> +struct intersection +{ template < typename Geometry1, @@ -152,28 +184,15 @@ struct intersection GeometryOut & geometry_out, default_strategy) { - typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2, - typename geometry::cs_tag::type - >::type rescale_policy_type; - - typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 - >::type strategy; + >::type strategy_type; - rescale_policy_type robust_policy - = geometry::get_rescale_policy( - geometry1, geometry2, strategy); - - return dispatch::intersection + return intersection < - Geometry1, - Geometry2 - >::apply(geometry1, geometry2, robust_policy, geometry_out, - strategy); + strategy_type + >::apply(geometry1, geometry2, geometry_out, strategy_type()); } }; @@ -195,10 +214,10 @@ struct intersection concepts::check(); concepts::check(); - return resolve_strategy::intersection::apply(geometry1, - geometry2, - geometry_out, - strategy); + return resolve_strategy::intersection + < + Strategy + >::apply(geometry1, geometry2, geometry_out, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/intersects/implementation.hpp b/include/boost/geometry/algorithms/detail/intersects/implementation.hpp index cbb442ce4..76493f9d4 100644 --- a/include/boost/geometry/algorithms/detail/intersects/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/intersects/implementation.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2014 Bruno Lalande, Paris, France. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013-2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -30,7 +30,7 @@ #include #include -#include +#include namespace boost { namespace geometry @@ -48,7 +48,7 @@ struct self_intersects concepts::check(); typedef typename geometry::point_type::type point_type; - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry, Geometry >::type strategy_type; diff --git a/include/boost/geometry/algorithms/detail/is_simple/areal.hpp b/include/boost/geometry/algorithms/detail/is_simple/areal.hpp index 9f75b6903..6496591c8 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/areal.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/areal.hpp @@ -22,7 +22,6 @@ #include #include -#include #include #include @@ -38,54 +37,34 @@ namespace detail { namespace is_simple { -template -struct is_simple_ring +template +inline bool is_simple_ring(Ring const& ring, Strategy const& strategy) { - static inline bool apply(Ring const& ring) - { - simplicity_failure_policy policy; - return ! boost::empty(ring) - && ! detail::is_valid::has_duplicates - < - Ring, geometry::closure::value, CSTag - >::apply(ring, policy); - } -}; + simplicity_failure_policy policy; + return ! boost::empty(ring) + && ! detail::is_valid::has_duplicates + < + Ring, geometry::closure::value + >::apply(ring, policy, strategy); +} - -template -class is_simple_polygon +template +inline bool are_simple_interior_rings(InteriorRings const& interior_rings, + Strategy const& strategy) { -private: - template - static inline - bool are_simple_interior_rings(InteriorRings const& interior_rings) - { - return - detail::check_iterator_range - < - is_simple_ring - < - typename boost::range_value::type, - CSTag - > - >::apply(boost::begin(interior_rings), - boost::end(interior_rings)); - } + auto const end = boost::end(interior_rings); + return std::find_if(boost::begin(interior_rings), end, + [&](auto const& r) { return ! is_simple_ring(r, strategy); }) + == end; // non-simple ring not found + // allow empty ring +} -public: - static inline bool apply(Polygon const& polygon) - { - return - is_simple_ring - < - typename ring_type::type, - CSTag - >::apply(exterior_ring(polygon)) - && - are_simple_interior_rings(geometry::interior_rings(polygon)); - } -}; +template +inline bool is_simple_polygon(Polygon const& polygon, Strategy const& strategy) +{ + return is_simple_ring(geometry::exterior_ring(polygon), strategy) + && are_simple_interior_rings(geometry::interior_rings(polygon), strategy); +} }} // namespace detail::is_simple @@ -107,13 +86,9 @@ template struct is_simple { template - static inline bool apply(Ring const& ring, Strategy const&) + static inline bool apply(Ring const& ring, Strategy const& strategy) { - return detail::is_simple::is_simple_ring - < - Ring, - typename Strategy::cs_tag - >::apply(ring); + return detail::is_simple::is_simple_ring(ring, strategy); } }; @@ -125,13 +100,9 @@ template struct is_simple { template - static inline bool apply(Polygon const& polygon, Strategy const&) + static inline bool apply(Polygon const& polygon, Strategy const& strategy) { - return detail::is_simple::is_simple_polygon - < - Polygon, - typename Strategy::cs_tag - >::apply(polygon); + return detail::is_simple::is_simple_polygon(polygon, strategy); } }; @@ -144,18 +115,14 @@ template struct is_simple { template - static inline bool apply(MultiPolygon const& multipolygon, Strategy const&) + static inline bool apply(MultiPolygon const& multipolygon, Strategy const& strategy) { - return - detail::check_iterator_range - < - detail::is_simple::is_simple_polygon - < - typename boost::range_value::type, - typename Strategy::cs_tag - >, - true // allow empty multi-polygon - >::apply(boost::begin(multipolygon), boost::end(multipolygon)); + auto const end = boost::end(multipolygon); + return std::find_if(boost::begin(multipolygon), end, + [&](auto const& po) { + return ! detail::is_simple::is_simple_polygon(po, strategy); + }) == end; // non-simple polygon not found + // allow empty multi-polygon } }; diff --git a/include/boost/geometry/algorithms/detail/is_simple/interface.hpp b/include/boost/geometry/algorithms/detail/is_simple/interface.hpp index af0127dc7..7703b9ec6 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/interface.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/interface.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -20,7 +20,8 @@ #include #include #include -#include +#include +#include namespace boost { namespace geometry @@ -29,23 +30,47 @@ namespace boost { namespace geometry namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct is_simple { - template + template static inline bool apply(Geometry const& geometry, Strategy const& strategy) { return dispatch::is_simple::apply(geometry, strategy); } +}; +template +struct is_simple +{ + template + static inline bool apply(Geometry const& geometry, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + return dispatch::is_simple + < + Geometry + >::apply(geometry, strategy_converter::get(strategy)); + } +}; + +template <> +struct is_simple +{ template static inline bool apply(Geometry const& geometry, default_strategy) { // NOTE: Currently the strategy is only used for Linear geometries - typedef typename strategy::intersection::services::default_strategy + typedef typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry, Geometry >::type strategy_type; return dispatch::is_simple::apply(geometry, strategy_type()); @@ -65,7 +90,7 @@ struct is_simple { concepts::check(); - return resolve_strategy::is_simple::apply(geometry, strategy); + return resolve_strategy::is_simple::apply(geometry, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp index bb1c5a51b..1ae040975 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp @@ -221,8 +221,7 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg typedef is_acceptable_turn < - Linear, - typename Strategy::equals_point_point_strategy_type + Linear, Strategy > is_acceptable_turn_type; is_acceptable_turn_type predicate(linear); @@ -259,12 +258,12 @@ struct is_simple_linestring return ! boost::empty(linestring) && ! detail::is_valid::has_duplicates < - Linestring, closed, typename Strategy::cs_tag - >::apply(linestring, policy) + Linestring, closed + >::apply(linestring, policy, strategy) && ! detail::is_valid::has_spikes < Linestring, closed - >::apply(linestring, policy, strategy.get_side_strategy()); + >::apply(linestring, policy, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp b/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp index 3ef7778b8..536a9e5ed 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp @@ -42,7 +42,7 @@ template struct is_simple_multipoint { template - static inline bool apply(MultiPoint const& multipoint, Strategy const&) + static inline bool apply(MultiPoint const& multipoint, Strategy const& strategy) { typedef typename Strategy::cs_tag cs_tag; typedef geometry::less @@ -61,10 +61,10 @@ struct is_simple_multipoint std::sort(boost::begin(mp), boost::end(mp), less_type()); simplicity_failure_policy policy; - return !detail::is_valid::has_duplicates + return ! detail::is_valid::has_duplicates < - MultiPoint, closed, cs_tag - >::apply(mp, policy); + MultiPoint, closed + >::apply(mp, policy, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp index ca0a7c48b..36391baf8 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp @@ -33,11 +33,12 @@ namespace boost { namespace geometry namespace detail { namespace is_valid { -template +template struct has_duplicates { - template - static inline bool apply(Range const& range, VisitPolicy& visitor) + template + static inline bool apply(Range const& range, VisitPolicy& visitor, + Strategy const& ) { boost::ignore_unused(visitor); @@ -58,7 +59,7 @@ struct has_duplicates < typename boost::range_value::type, -1, - CSTag + typename Strategy::cs_tag > equal; const_iterator it = boost::const_begin(view); diff --git a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp index 18f5626b5..574d4bdfc 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -45,64 +45,27 @@ namespace boost { namespace geometry namespace detail { namespace is_valid { -template -struct equal_to -{ - Point const& m_point; - - equal_to(Point const& point) - : m_point(point) - {} - - template - inline bool operator()(OtherPoint const& other) const - { - return geometry::detail::equals::equals_point_point(m_point, other, Strategy()); - } -}; - -template -struct not_equal_to -{ - Point const& m_point; - - not_equal_to(Point const& point) - : m_point(point) - {} - - template - inline bool operator()(OtherPoint const& other) const - { - return ! geometry::detail::equals::equals_point_point(other, m_point, Strategy()); - } -}; - - template struct has_spikes { - template + template static inline Iterator find_different_from_first(Iterator first, Iterator last, - SideStrategy const& ) + Strategy const& strategy) { - typedef not_equal_to - < - typename point_type::type, - typename SideStrategy::equals_point_point_strategy_type - > not_equal; - - BOOST_GEOMETRY_ASSERT(first != last); - - Iterator second = first; - ++second; - return std::find_if(second, last, not_equal(*first)); + if (first == last) + return last; + auto const& front = *first; + ++first; + return std::find_if(first, last, [&](auto const& pt) { + return ! equals::equals_point_point(pt, front, strategy); + }); } - template + template static inline bool apply_at_closure(View const& view, VisitPolicy& visitor, - SideStrategy const& strategy, + Strategy const& strategy, bool is_linear) { boost::ignore_unused(visitor); @@ -119,10 +82,9 @@ struct has_spikes iterator next = find_different_from_first(cur, boost::end(view), strategy); - if (detail::is_spike_or_equal(*next, *cur, *prev, strategy)) + if (detail::is_spike_or_equal(*next, *cur, *prev, strategy.side())) { - return - ! visitor.template apply(is_linear, *cur); + return ! visitor.template apply(is_linear, *cur); } else { @@ -131,9 +93,9 @@ struct has_spikes } - template + template static inline bool apply(Range const& range, VisitPolicy& visitor, - SideStrategy const& strategy) + Strategy const& strategy) { boost::ignore_unused(visitor); @@ -169,7 +131,7 @@ struct has_spikes // in is_spike_or_equal, but this order calls the side // strategy in the way to correctly detect the spikes, // also in geographic cases going over the pole - if (detail::is_spike_or_equal(*next, *cur, *prev, strategy)) + if (detail::is_spike_or_equal(*next, *cur, *prev, strategy.side())) { return ! visitor.template apply(is_linestring, *cur); @@ -179,9 +141,8 @@ struct has_spikes next = find_different_from_first(cur, boost::end(view), strategy); } - if (geometry::detail::equals:: - equals_point_point(range::front(view), range::back(view), - strategy.get_equals_point_point_strategy())) + if (equals::equals_point_point(range::front(view), range::back(view), + strategy)) { return apply_at_closure(view, visitor, strategy, is_linestring); } diff --git a/include/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp index 348dba904..6c33961b3 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp @@ -41,7 +41,7 @@ namespace detail { namespace is_valid template < typename Geometry, - typename CSTag + typename CSTag // TODO: remove > class has_valid_self_turns { diff --git a/include/boost/geometry/algorithms/detail/is_valid/interface.hpp b/include/boost/geometry/algorithms/detail/is_valid/interface.hpp index e7f5c5783..4f8d1f543 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/interface.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/interface.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2014-2018, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -25,7 +25,8 @@ #include #include #include -#include +#include +#include namespace boost { namespace geometry @@ -34,9 +35,14 @@ namespace boost { namespace geometry namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct is_valid { - template + template static inline bool apply(Geometry const& geometry, VisitPolicy& visitor, Strategy const& strategy) @@ -44,18 +50,41 @@ struct is_valid return dispatch::is_valid::apply(geometry, visitor, strategy); } +}; + +template +struct is_valid +{ + template + static inline bool apply(Geometry const& geometry, + VisitPolicy& visitor, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + return dispatch::is_valid + < + Geometry + >::apply(geometry, visitor, + strategy_converter::get(strategy)); + } +}; + +template <> +struct is_valid +{ template static inline bool apply(Geometry const& geometry, VisitPolicy& visitor, default_strategy) { // NOTE: Currently the strategy is only used for Areal geometries - typedef typename strategy::intersection::services::default_strategy + typedef typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry, Geometry >::type strategy_type; - return dispatch::is_valid::apply(geometry, visitor, strategy_type()); + return dispatch::is_valid::apply(geometry, visitor, + strategy_type()); } }; @@ -74,7 +103,10 @@ struct is_valid { concepts::check(); - return resolve_strategy::is_valid::apply(geometry, visitor, strategy); + return resolve_strategy::is_valid + < + Strategy + >::apply(geometry, visitor, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/is_valid/linear.hpp b/include/boost/geometry/algorithms/detail/is_valid/linear.hpp index b2905732c..7176cc469 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/linear.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/linear.hpp @@ -64,15 +64,8 @@ struct is_valid_linestring std::size_t num_distinct = detail::num_distinct_consecutive_points < - Linestring, - 3u, - true, - not_equal_to - < - typename point_type::type, - typename Strategy::equals_point_point_strategy_type - > - >::apply(linestring); + Linestring, 3u, true + >::apply(linestring, strategy); if (num_distinct < 2u) { @@ -93,8 +86,7 @@ struct is_valid_linestring return ! has_spikes < Linestring, closed - >::apply(linestring, visitor, - strategy.get_side_strategy()); + >::apply(linestring, visitor, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp index d0b4264c7..0b3b4c4a7 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp @@ -118,14 +118,6 @@ private: } } - // prepare strategies - typedef typename Strategy::envelope_strategy_type envelope_strategy_type; - envelope_strategy_type const envelope_strategy - = strategy.get_envelope_strategy(); - typedef typename Strategy::disjoint_box_box_strategy_type disjoint_box_box_strategy_type; - disjoint_box_box_strategy_type const disjoint_strategy - = strategy.get_disjoint_box_box_strategy(); - // call partition to check if polygons are disjoint from each other typename base::template item_visitor_type item_visitor(strategy); @@ -133,15 +125,8 @@ private: < geometry::model::box::type> >::apply(polygon_iterators, item_visitor, - typename base::template expand_box - < - envelope_strategy_type - >(envelope_strategy), - typename base::template overlaps_box - < - envelope_strategy_type, - disjoint_box_box_strategy_type - >(envelope_strategy, disjoint_strategy)); + typename base::template expand_box(strategy), + typename base::template overlaps_box(strategy)); if (item_visitor.items_overlap) { diff --git a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp index ea27b23d2..72ae593f8 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -185,10 +185,10 @@ protected: }; // structs for partition -- start - template + template struct expand_box { - explicit expand_box(EnvelopeStrategy const& strategy) + explicit expand_box(Strategy const& strategy) : m_strategy(strategy) {} @@ -197,46 +197,38 @@ protected: { geometry::expand(total, item.get_envelope(m_strategy), - // TEMP - envelope umbrella strategy also contains - // expand strategies - strategies::envelope::services::strategy_converter - < - EnvelopeStrategy - >::get(m_strategy)); + m_strategy); } - EnvelopeStrategy const& m_strategy; + Strategy const& m_strategy; }; - template + template struct overlaps_box { - explicit overlaps_box(EnvelopeStrategy const& envelope_strategy, - DisjointBoxBoxStrategy const& disjoint_strategy) - : m_envelope_strategy(envelope_strategy) - , m_disjoint_strategy(disjoint_strategy) + explicit overlaps_box(Strategy const& strategy) + : m_strategy(strategy) {} template inline bool apply(Box const& box, partition_item const& item) const { - return ! geometry::disjoint(item.get_envelope(m_envelope_strategy), + return ! geometry::disjoint(item.get_envelope(m_strategy), box, - m_disjoint_strategy); + m_strategy); } - EnvelopeStrategy const& m_envelope_strategy; - DisjointBoxBoxStrategy const& m_disjoint_strategy; + Strategy const& m_strategy; }; - template + template struct item_visitor_type { bool items_overlap; - WithinStrategy const& m_strategy; + Strategy const& m_strategy; - explicit item_visitor_type(WithinStrategy const& strategy) + explicit item_visitor_type(Strategy const& strategy) : items_overlap(false) , m_strategy(strategy) {} @@ -299,14 +291,6 @@ protected: } } - // prepare strategy - typedef typename std::iterator_traits::value_type inter_ring_type; - typename Strategy::template point_in_geometry_strategy - < - inter_ring_type, ExteriorRing - >::type const in_exterior_strategy - = strategy.template get_point_in_geometry_strategy(); - signed_size_type ring_index = 0; for (RingIterator it = rings_first; it != rings_beyond; ++it, ++ring_index) @@ -314,7 +298,7 @@ protected: // do not examine interior rings that have turns with the // exterior ring if (ring_indices.find(ring_index) == ring_indices.end() - && ! geometry::covered_by(range::front(*it), exterior_ring, in_exterior_strategy)) + && ! geometry::covered_by(range::front(*it), exterior_ring, strategy)) { return visitor.template apply(); } @@ -342,14 +326,6 @@ protected: } } - // prepare strategies - typedef typename Strategy::envelope_strategy_type envelope_strategy_type; - envelope_strategy_type const envelope_strategy - = strategy.get_envelope_strategy(); - typedef typename Strategy::disjoint_box_box_strategy_type disjoint_box_box_strategy_type; - disjoint_box_box_strategy_type const disjoint_strategy - = strategy.get_disjoint_box_box_strategy(); - // call partition to check if interior rings are disjoint from // each other item_visitor_type item_visitor(strategy); @@ -358,15 +334,8 @@ protected: < box_type >::apply(ring_iterators, item_visitor, - expand_box - < - envelope_strategy_type - >(envelope_strategy), - overlaps_box - < - envelope_strategy_type, - disjoint_box_box_strategy_type - >(envelope_strategy, disjoint_strategy)); + expand_box(strategy), + overlaps_box(strategy)); if (item_visitor.items_overlap) { diff --git a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp index 9238780cf..bfa79fb54 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp @@ -92,21 +92,7 @@ struct is_topologically_closed }; - -template -struct ring_area_predicate -{ - typedef std::greater type; -}; - -template -struct ring_area_predicate -{ - typedef std::less type; -}; - - - +// TODO: use calculate_point_order here template struct is_properly_oriented { @@ -122,25 +108,15 @@ struct is_properly_oriented geometry::closure::value > ring_area_type; - typedef typename Strategy::template area_strategy + std::conditional_t < - Ring - >::type::template result_type::type area_result_type; - - typename ring_area_predicate - < - area_result_type, IsInteriorRing - >::type predicate; + IsInteriorRing, std::less<>, std::greater<> + > predicate; // Check area - area_result_type const zero = 0; - area_result_type const area - = ring_area_type::apply(ring, - // TEMP - in the future (umbrella) strategy will be passed here - geometry::strategies::area::services::strategy_converter - < - decltype(strategy.template get_area_strategy()) - >::get(strategy.template get_area_strategy())); + auto const area = ring_area_type::apply(ring, strategy); + decltype(area) const zero = 0; + if (predicate(area, zero)) { return visitor.template apply(); @@ -166,8 +142,6 @@ struct is_valid_ring static inline bool apply(Ring const& ring, VisitPolicy& visitor, Strategy const& strategy) { - typedef typename Strategy::cs_tag cs_tag; - // return invalid if any of the following condition holds: // (a) the ring's point coordinates are not invalid (e.g., NaN) // (b) the ring's size is below the minimal one @@ -199,13 +173,8 @@ struct is_valid_ring view_type const view(ring); if (detail::num_distinct_consecutive_points < - view_type, 4u, true, - not_equal_to - < - typename point_type::type, - typename Strategy::equals_point_point_strategy_type - > - >::apply(view) + view_type, 4u, true + >::apply(view, strategy) < 4u) { return @@ -213,9 +182,9 @@ struct is_valid_ring } return - is_topologically_closed::apply(ring, visitor, strategy.get_equals_point_point_strategy()) - && ! has_duplicates::apply(ring, visitor) - && ! has_spikes::apply(ring, visitor, strategy.get_side_strategy()) + is_topologically_closed::apply(ring, visitor, strategy) + && ! has_duplicates::apply(ring, visitor, strategy) + && ! has_spikes::apply(ring, visitor, strategy) && (! CheckSelfIntersections || has_valid_self_turns::apply(ring, visitor, strategy)) && is_properly_oriented::apply(ring, visitor, strategy); diff --git a/include/boost/geometry/algorithms/detail/is_valid/segment.hpp b/include/boost/geometry/algorithms/detail/is_valid/segment.hpp index 244a6ff3b..b1d27dafd 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/segment.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/segment.hpp @@ -45,10 +45,8 @@ template struct is_valid { template - static inline bool apply(Segment const& segment, VisitPolicy& visitor, Strategy const&) + static inline bool apply(Segment const& segment, VisitPolicy& visitor, Strategy const& strategy) { - typedef typename Strategy::equals_point_point_strategy_type eq_pp_strategy_type; - boost::ignore_unused(visitor); typename point_type::type p[2]; @@ -62,8 +60,7 @@ struct is_valid { return false; } - else if (! geometry::detail::equals::equals_point_point( - p[0], p[1], eq_pp_strategy_type())) + else if (! detail::equals::equals_point_point(p[0], p[1], strategy)) { return visitor.template apply(); } diff --git a/include/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp b/include/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp index ca5ac20b8..5acc531d3 100644 --- a/include/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp +++ b/include/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp @@ -41,12 +41,12 @@ template < typename Range, std::size_t MaximumNumber, - bool AllowDuplicates /* true */, - typename NotEqualTo + bool AllowDuplicates /* true */ > struct num_distinct_consecutive_points { - static inline std::size_t apply(Range const& range) + template + static inline std::size_t apply(Range const& range, Strategy const& strategy) { typedef typename boost::range_iterator::type iterator; @@ -58,26 +58,28 @@ struct num_distinct_consecutive_points } iterator current = boost::begin(range); + iterator const end = boost::end(range); std::size_t counter(0); do { ++counter; - iterator next = std::find_if(current, - boost::end(range), - NotEqualTo(*current)); + iterator next = std::find_if(current, end, [&](auto const& pt) { + return ! equals::equals_point_point(pt, *current, strategy); + }); current = next; } - while ( current != boost::end(range) && counter <= MaximumNumber ); + while ( current != end && counter <= MaximumNumber ); return counter; } }; -template -struct num_distinct_consecutive_points +template +struct num_distinct_consecutive_points { - static inline std::size_t apply(Range const& range) + template + static inline std::size_t apply(Range const& range, Strategy const&) { std::size_t const size = boost::size(range); return (size < MaximumNumber) ? size : MaximumNumber; diff --git a/include/boost/geometry/algorithms/detail/overlaps/interface.hpp b/include/boost/geometry/algorithms/detail/overlaps/interface.hpp index 088b51fe2..527ec1600 100644 --- a/include/boost/geometry/algorithms/detail/overlaps/interface.hpp +++ b/include/boost/geometry/algorithms/detail/overlaps/interface.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2014, 2015, 2017. -// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -28,7 +28,9 @@ #include -#include +#include +#include +#include namespace boost { namespace geometry @@ -60,6 +62,70 @@ struct overlaps #endif // DOXYGEN_NO_DISPATCH +namespace resolve_strategy +{ + +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> +struct overlaps +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return dispatch::overlaps + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); + } +}; + +template +struct overlaps +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + //using strategies::overlaps::services::strategy_converter; + using strategies::relate::services::strategy_converter; + return dispatch::overlaps + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct overlaps +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + default_strategy) + { + //typedef typename strategies::overlaps::services::default_strategy + typedef typename strategies::relate::services::default_strategy + < + Geometry1, Geometry2 + >::type strategy_type; + + return dispatch::overlaps + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy_type()); + } +}; + +} // namespace resolve_strategy + + /*! \brief \brief_check2{overlap} \ingroup overlaps @@ -82,10 +148,9 @@ inline bool overlaps(Geometry1 const& geometry1, concepts::check(); concepts::check(); - return dispatch::overlaps + return resolve_strategy::overlaps < - Geometry1, - Geometry2 + Strategy >::apply(geometry1, geometry2, strategy); } @@ -111,17 +176,10 @@ inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2) concepts::check(); concepts::check(); - typedef typename strategy::relate::services::default_strategy - < - Geometry1, - Geometry2 - >::type strategy_type; - - return dispatch::overlaps + return resolve_strategy::overlaps < - Geometry1, - Geometry2 - >::apply(geometry1, geometry2, strategy_type()); + default_strategy + >::apply(geometry1, geometry2, default_strategy()); } }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp index 3f33bb45a..45f2e7f12 100644 --- a/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp @@ -87,22 +87,17 @@ template typename Geometry2, typename RingCollection, typename OutputIterator, - typename AreaStrategy + typename Strategy > inline OutputIterator add_rings(SelectionMap const& map, Geometry1 const& geometry1, Geometry2 const& geometry2, RingCollection const& collection, OutputIterator out, - AreaStrategy const& area_strategy, + Strategy const& strategy, add_rings_error_handling error_handling = add_rings_ignore_unordered) { typedef typename SelectionMap::const_iterator iterator; - typedef typename AreaStrategy::template result_type - < - GeometryOut - >::type area_type; - area_type const zero = 0; std::size_t const min_num_points = core_detail::closure::minimum_ring_size < geometry::closure @@ -146,7 +141,9 @@ inline OutputIterator add_rings(SelectionMap const& map, // everything is figured out yet (sum of positive/negative rings) if (geometry::num_points(result) >= min_num_points) { - area_type const area = geometry::area(result, area_strategy); + typedef typename geometry::area_result::type area_type; + area_type const area = geometry::area(result, strategy); + area_type const zero = 0; // Ignore if area is 0 if (! math::equals(area, zero)) { @@ -174,16 +171,16 @@ template typename Geometry, typename RingCollection, typename OutputIterator, - typename AreaStrategy + typename Strategy > inline OutputIterator add_rings(SelectionMap const& map, Geometry const& geometry, RingCollection const& collection, OutputIterator out, - AreaStrategy const& area_strategy) + Strategy const& strategy) { Geometry empty; - return add_rings(map, geometry, empty, collection, out, area_strategy); + return add_rings(map, geometry, empty, collection, out, strategy); } diff --git a/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp b/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp index c96d721b7..f833fe618 100644 --- a/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp @@ -40,9 +40,9 @@ inline void append_with_duplicates(Range& range, Point const& point) geometry::append(range, point); } -template +template inline void append_no_duplicates(Range& range, Point const& point, - EqPPStrategy const& strategy) + Strategy const& strategy) { if ( boost::empty(range) || ! geometry::detail::equals::equals_point_point(geometry::range::back(range), diff --git a/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp b/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp index 9466e4122..f304600c0 100644 --- a/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp @@ -41,11 +41,11 @@ namespace detail { namespace overlay { // TODO: move this / rename this -template +template inline bool points_equal_or_close(Point1 const& point1, - Point2 const& point2, - EqualsStrategy const& strategy, - RobustPolicy const& robust_policy) + Point2 const& point2, + Strategy const& strategy, + RobustPolicy const& robust_policy) { if (detail::equals::equals_point_point(point1, point2, strategy)) { @@ -79,10 +79,10 @@ inline bool points_equal_or_close(Point1 const& point1, } -template +template inline void append_no_dups_or_spikes(Range& range, Point const& point, - SideStrategy const& strategy, - RobustPolicy const& robust_policy) + Strategy const& strategy, + RobustPolicy const& robust_policy) { #ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION std::cout << " add: (" @@ -93,8 +93,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point, // for geometries >= 3 points. // So we have to check the first potential duplicate differently if ( boost::size(range) == 1 - && points_equal_or_close(*(boost::begin(range)), point, - strategy.get_equals_point_point_strategy(), + && points_equal_or_close(*(boost::begin(range)), point, strategy, robust_policy) ) { return; @@ -111,7 +110,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point, && point_is_spike_or_equal(point, *(boost::end(range) - 3), *(boost::end(range) - 2), - strategy, + strategy.side(), // TODO: Pass strategy? robust_policy)) { // Use the Concept/traits, so resize and append again @@ -120,10 +119,10 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point, } } -template +template inline void append_no_collinear(Range& range, Point const& point, - SideStrategy const& strategy, - RobustPolicy const& robust_policy) + Strategy const& strategy, + RobustPolicy const& robust_policy) { // Stricter version, not allowing any point in a linear row // (spike, continuation or same point) @@ -133,7 +132,7 @@ inline void append_no_collinear(Range& range, Point const& point, // So we have to check the first potential duplicate differently if ( boost::size(range) == 1 && points_equal_or_close(*(boost::begin(range)), point, - strategy.get_equals_point_point_strategy(), + strategy, robust_policy) ) { return; @@ -150,7 +149,7 @@ inline void append_no_collinear(Range& range, Point const& point, && point_is_collinear(point, *(boost::end(range) - 3), *(boost::end(range) - 2), - strategy, + strategy.side(), // TODO: Pass strategy? robust_policy)) { // Use the Concept/traits, so resize and append again @@ -159,10 +158,10 @@ inline void append_no_collinear(Range& range, Point const& point, } } -template +template inline void clean_closing_dups_and_spikes(Range& range, - SideStrategy const& strategy, - RobustPolicy const& robust_policy) + Strategy const& strategy, + RobustPolicy const& robust_policy) { std::size_t const minsize = core_detail::closure::minimum_ring_size @@ -195,7 +194,9 @@ inline void clean_closing_dups_and_spikes(Range& range, // Check if closing point is a spike (this is so if the second point is // considered as collinear w.r.t. the last segment) - if (point_is_collinear(*second, *ultimate, *first, strategy, robust_policy)) + if (point_is_collinear(*second, *ultimate, *first, + strategy.side(), // TODO: Pass strategy? + robust_policy)) { range::erase(range, first); if (BOOST_GEOMETRY_CONDITION(closed)) diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index ac43d9c07..a4cfac4dc 100644 --- a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -127,27 +127,39 @@ struct ring_info_helper }; -template +template struct ring_info_helper_get_box { + ring_info_helper_get_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, InputItem const& item) + inline void apply(Box& total, InputItem const& item) const { assert_coordinate_type_equal(total, item.envelope); - geometry::expand(total, item.envelope, BoxExpandStrategy()); + geometry::expand(total, item.envelope, m_strategy); } + + Strategy const& m_strategy; }; -template +template struct ring_info_helper_overlaps_box { + ring_info_helper_overlaps_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, InputItem const& item) + inline bool apply(Box const& box, InputItem const& item) const { assert_coordinate_type_equal(box, item.envelope); return ! geometry::detail::disjoint::disjoint_box_box( - box, item.envelope, DisjointBoxBoxStrategy()); + box, item.envelope, m_strategy); } + + Strategy const& m_strategy; }; // Segments intersection Strategy @@ -196,8 +208,7 @@ struct assign_visitor { ring_info_type& inner_in_map = m_ring_map[inner.id]; - if (geometry::covered_by(inner_in_map.point, outer.envelope, - typename Strategy::disjoint_point_box_strategy_type()) + if (geometry::covered_by(inner_in_map.point, outer.envelope, m_strategy) && within_selected_input(inner_in_map, inner.id, outer.id, m_geometry1, m_geometry2, m_collection, m_strategy) @@ -244,10 +255,10 @@ inline void assign_parents(Geometry1 const& geometry1, typedef typename RingMap::mapped_type ring_info_type; typedef typename ring_info_type::point_type point_type; typedef model::box box_type; - typedef typename Strategy::template area_strategy + typedef typename geometry::area_result < - point_type - >::type::template result_type::type area_result_type; + point_type, Strategy // TODO: point_type is technically incorrect + >::type area_result_type; typedef typename RingMap::iterator map_iterator_type; @@ -273,15 +284,15 @@ inline void assign_parents(Geometry1 const& geometry1, { case 0 : geometry::envelope(get_ring::apply(it->first, geometry1), - item.envelope, strategy.get_envelope_strategy()); + item.envelope, strategy); break; case 1 : geometry::envelope(get_ring::apply(it->first, geometry2), - item.envelope, strategy.get_envelope_strategy()); + item.envelope, strategy); break; case 2 : geometry::envelope(get_ring::apply(it->first, collection), - item.envelope, strategy.get_envelope_strategy()); + item.envelope, strategy); break; } @@ -336,19 +347,12 @@ inline void assign_parents(Geometry1 const& geometry1, Strategy > visitor(geometry1, geometry2, collection, ring_map, strategy, check_for_orientation); - typedef ring_info_helper_get_box - < - typename Strategy::expand_box_strategy_type - > expand_box_type; - typedef ring_info_helper_overlaps_box - < - typename Strategy::disjoint_box_box_strategy_type - > overlaps_box_type; - geometry::partition < box_type - >::apply(vector, visitor, expand_box_type(), overlaps_box_type()); + >::apply(vector, visitor, + ring_info_helper_get_box(strategy), + ring_info_helper_overlaps_box(strategy)); } if (check_for_orientation) diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp index f6833da2c..d084e5984 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp @@ -61,14 +61,14 @@ struct copy_segments_ring < typename Ring, typename SegmentIdentifier, - typename SideStrategy, + typename Strategy, typename RobustPolicy, typename RangeOut > static inline void apply(Ring const& ring, SegmentIdentifier const& seg_id, signed_size_type to_index, - SideStrategy const& strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, RangeOut& current_output) { @@ -125,10 +125,10 @@ class copy_segments_linestring { private: // remove spikes - template + template static inline void append_to_output(RangeOut& current_output, Point const& point, - SideStrategy const& strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, std::true_type const&) { @@ -138,14 +138,14 @@ private: } // keep spikes - template + template static inline void append_to_output(RangeOut& current_output, Point const& point, - SideStrategy const& strategy, + Strategy const& strategy, RobustPolicy const&, std::false_type const&) { - detail::overlay::append_no_duplicates(current_output, point, strategy.get_equals_point_point_strategy()); + detail::overlay::append_no_duplicates(current_output, point, strategy); } public: diff --git a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp index 3661e434b..163dc64d9 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -524,7 +524,7 @@ inline void enrich_intersection_points(Turns& turns, detail::overlay::enrich_sort( mit->second, turns, geometry1, geometry2, - robust_policy, strategy.get_side_strategy()); + robust_policy, strategy.side()); // TODO: pass strategy } for (typename mapped_vector_type::iterator mit @@ -554,7 +554,7 @@ inline void enrich_intersection_points(Turns& turns, Reverse2, OverlayType >(clusters, turns, target_operation, - geometry1, geometry2, strategy.get_side_strategy()); + geometry1, geometry2, strategy.side()); // TODO: pass strategy detail::overlay::cleanup_clusters(turns, clusters); } diff --git a/include/boost/geometry/algorithms/detail/overlay/follow.hpp b/include/boost/geometry/algorithms/detail/overlay/follow.hpp index 88512479c..afcd2bd82 100644 --- a/include/boost/geometry/algorithms/detail/overlay/follow.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/follow.hpp @@ -62,11 +62,11 @@ template typename Operation, typename LineString, typename Polygon, - typename PtInPolyStrategy + typename Strategy > inline bool last_covered_by(Turn const& /*turn*/, Operation const& op, LineString const& linestring, Polygon const& polygon, - PtInPolyStrategy const& strategy) + Strategy const& strategy) { return geometry::covered_by(range::at(linestring, op.seg_id.segment_index), polygon, strategy); } @@ -78,12 +78,12 @@ template typename Operation, typename LineString, typename Polygon, - typename PtInPolyStrategy + typename Strategy > inline bool is_leaving(Turn const& turn, Operation const& op, bool entered, bool first, LineString const& linestring, Polygon const& polygon, - PtInPolyStrategy const& strategy) + Strategy const& strategy) { if (op.operation == operation_union) { @@ -104,12 +104,12 @@ template typename Operation, typename LineString, typename Polygon, - typename PtInPolyStrategy + typename Strategy > inline bool is_staying_inside(Turn const& turn, Operation const& op, bool entered, bool first, LineString const& linestring, Polygon const& polygon, - PtInPolyStrategy const& strategy) + Strategy const& strategy) { if (turn.method == method_crosses) { @@ -132,11 +132,11 @@ template typename Operation, typename Linestring, typename Polygon, - typename PtInPolyStrategy + typename Strategy > inline bool was_entered(Turn const& turn, Operation const& op, bool first, Linestring const& linestring, Polygon const& polygon, - PtInPolyStrategy const& strategy) + Strategy const& strategy) { if (first && (turn.method == method_collinear || turn.method == method_equal)) { @@ -234,7 +234,7 @@ struct action_selector { // On enter, append the intersection point and remember starting point // TODO: we don't check on spikes for linestrings (?). Consider this. - detail::overlay::append_no_duplicates(current_piece, point, strategy.get_equals_point_point_strategy()); + detail::overlay::append_no_duplicates(current_piece, point, strategy); segment_id = operation.seg_id; } @@ -263,7 +263,7 @@ struct action_selector < false, RemoveSpikes >::apply(linestring, segment_id, index, strategy, robust_policy, current_piece); - detail::overlay::append_no_duplicates(current_piece, point, strategy.get_equals_point_point_strategy()); + detail::overlay::append_no_duplicates(current_piece, point, strategy); if (::boost::size(current_piece) > 1) { *out++ = current_piece; @@ -431,14 +431,6 @@ public : typedef following::action_selector action; - typedef typename Strategy::cs_tag cs_tag; - - typename Strategy::template point_in_geometry_strategy - < - LineString, Polygon - >::type const pt_in_poly_strategy - = strategy.template get_point_in_geometry_strategy(); - // Sort intersection points on segments-along-linestring, and distance // (like in enrich is done for poly/poly) // sort turns by Linear seg_id, then by fraction, then @@ -446,7 +438,8 @@ public : // for different ring id: c, i, u, x typedef relate::turns::less < - 0, relate::turns::less_op_linear_areal_single<0>, cs_tag + 0, relate::turns::less_op_linear_areal_single<0>, + typename Strategy::cs_tag > turn_less; std::sort(boost::begin(turns), boost::end(turns), turn_less()); @@ -460,13 +453,13 @@ public : { turn_operation_iterator_type iit = boost::begin(it->operations); - if (following::was_entered(*it, *iit, first, linestring, polygon, pt_in_poly_strategy)) + if (following::was_entered(*it, *iit, first, linestring, polygon, strategy)) { debug_traverse(*it, *iit, "-> Was entered"); entered = true; } - if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy)) + if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon, strategy)) { debug_traverse(*it, *iit, "-> Staying inside"); @@ -482,7 +475,7 @@ public : strategy, robust_policy, linear::get(out)); } - else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy)) + else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, strategy)) { debug_traverse(*it, *iit, "-> Leaving"); diff --git a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp index e7b60c2c0..f0e3dbced 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp @@ -73,7 +73,7 @@ struct get_turn_without_info > policy_type; typename policy_type::return_type const result - = strategy.apply(range_p, range_q, policy_type()); + = strategy.relate().apply(range_p, range_q, policy_type()); for (std::size_t i = 0; i < result.count; i++) { diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 248649d8c..90cb8fbe5 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2015, 2017, 2018, 2019. -// Modifications copyright (c) 2015-2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2020. +// Modifications copyright (c) 2015-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -1289,7 +1289,7 @@ struct get_turn_info else { handler::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), - inters.get_swapped_sides(), umbrella_strategy); + inters.swapped_sides(), umbrella_strategy); *out++ = tp; } } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index c17fcb863..2b56d7dd5 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -111,12 +111,16 @@ namespace detail { namespace overlay { class linear_intersections { public: - template + template + < + typename Point1, typename Point2, typename IntersectionResult, + typename Strategy + > linear_intersections(Point1 const& pi, Point2 const& qi, IntersectionResult const& result, bool is_p_last, bool is_q_last, - EqPPStrategy const& strategy) + Strategy const& strategy) { int arrival_a = result.direction.arrival[0]; int arrival_b = result.direction.arrival[1]; @@ -237,7 +241,7 @@ struct get_turn_info_for_endpoint typename TurnInfo, typename IntersectionInfo, typename OutputIterator, - typename EqPPStrategy + typename Strategy > static inline bool apply(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, @@ -245,7 +249,7 @@ struct get_turn_info_for_endpoint IntersectionInfo const& inters, method_type /*method*/, OutputIterator out, - EqPPStrategy const& strategy) + Strategy const& strategy) { std::size_t ip_count = inters.i_info().count; // no intersection points @@ -398,8 +402,7 @@ struct get_turn_info_for_endpoint { boost::ignore_unused(ip_index, tp_model); - typename IntersectionInfo::side_strategy_type const& sides - = inters.get_side_strategy(); + auto const strategy = inters.strategy(); if ( !first2 && !last2 ) { @@ -409,8 +412,8 @@ struct get_turn_info_for_endpoint // may this give false positives for INTs? typename IntersectionResult::point_type const& inters_pt = inters.i_info().intersections[ip_index]; - BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); - BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt, strategy)); + BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt, strategy)); #endif if ( ip_i2 ) { @@ -421,6 +424,7 @@ struct get_turn_info_for_endpoint } else if ( ip_j2 ) { + auto const sides = strategy.side(); int const side_pj_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(1)); int const side_pj_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(1)); int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2)); @@ -460,8 +464,8 @@ struct get_turn_info_for_endpoint // may this give false positives for INTs? typename IntersectionResult::point_type const& inters_pt = inters.i_info().intersections[ip_index]; - BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); - BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt, strategy)); + BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt, strategy)); #endif if ( ip_i2 ) { @@ -472,6 +476,7 @@ struct get_turn_info_for_endpoint } else if ( ip_j2 ) { + auto const sides = strategy.side(); int const side_pi_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(0)); int const side_pi_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(0)); int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2)); diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp index 76e0f0258..b82528fa4 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp @@ -44,20 +44,20 @@ struct turn_operation_linear template < - typename TurnPointCSTag, typename UniqueSubRange1, typename UniqueSubRange2, - typename SideStrategy + typename Strategy > struct side_calculator { typedef typename UniqueSubRange1::point_type point1_type; typedef typename UniqueSubRange2::point_type point2_type; + typedef decltype(std::declval().side()) side_strategy_type; inline side_calculator(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, - SideStrategy const& side_strategy) - : m_side_strategy(side_strategy) + Strategy const& strategy) + : m_side_strategy(strategy.side()) , m_range_p(range_p) , m_range_q(range_q) {} @@ -84,9 +84,8 @@ struct side_calculator inline point2_type const& get_qj() const { return m_range_q.at(1); } inline point2_type const& get_qk() const { return m_range_q.at(2); } - // Used side-strategy, owned by the calculator, - // created from .get_side_strategy() - SideStrategy m_side_strategy; + // Used side-strategy, owned by the calculator + side_strategy_type m_side_strategy; // Used ranges - owned by get_turns or (for robust points) by intersection_info_base UniqueSubRange1 const& m_range_p; @@ -259,16 +258,14 @@ public: typedef robust_subrange_adapter robust_subrange1; typedef robust_subrange_adapter robust_subrange2; - typedef typename cs_tag::type cs_tag; - - typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; - typedef side_calculator side_calculator_type; + typedef side_calculator + < + robust_subrange1, robust_subrange2, UmbrellaStrategy + > side_calculator_type; typedef side_calculator < - cs_tag, robust_subrange2, robust_subrange1, - side_strategy_type + robust_subrange2, robust_subrange1, UmbrellaStrategy > robust_swapped_side_calculator_type; intersection_info_base(UniqueSubRange1 const& range_p, @@ -280,9 +277,9 @@ public: , m_robust_calc(range_p, range_q, robust_policy) , m_robust_range_p(range_p, m_robust_calc.m_rpi, m_robust_calc.m_rpj, robust_policy) , m_robust_range_q(range_q, m_robust_calc.m_rqi, m_robust_calc.m_rqj, robust_policy) - , m_side_calc(m_robust_range_p, m_robust_range_q, - umbrella_strategy.get_side_strategy()) - , m_result(umbrella_strategy.apply(range_p, range_q, + , m_side_calc(m_robust_range_p, m_robust_range_q, umbrella_strategy) + , m_swapped_side_calc(m_robust_range_q, m_robust_range_p, umbrella_strategy) + , m_result(umbrella_strategy.relate().apply(range_p, range_q, intersection_policy_type(), m_robust_range_p, m_robust_range_q)) {} @@ -299,13 +296,9 @@ public: inline robust_point2_type const& rqk() const { return m_robust_calc.get_rqk(); } inline side_calculator_type const& sides() const { return m_side_calc; } - - robust_swapped_side_calculator_type get_swapped_sides() const + inline robust_swapped_side_calculator_type const& swapped_sides() const { - robust_swapped_side_calculator_type result( - m_robust_range_q, m_robust_range_p, - m_side_calc.m_side_strategy); - return result; + return m_swapped_side_calc; } private : @@ -319,6 +312,7 @@ private : robust_subrange1 m_robust_range_p; robust_subrange2 m_robust_range_q; side_calculator_type m_side_calc; + robust_swapped_side_calculator_type m_swapped_side_calc; protected : result_type m_result; @@ -347,15 +341,14 @@ public: typedef typename UniqueSubRange1::point_type point1_type; typedef typename UniqueSubRange2::point_type point2_type; - typedef typename UmbrellaStrategy::cs_tag cs_tag; - - typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; - typedef side_calculator side_calculator_type; + typedef side_calculator + < + UniqueSubRange1, UniqueSubRange2, UmbrellaStrategy + > side_calculator_type; typedef side_calculator < - cs_tag, UniqueSubRange2, UniqueSubRange1, - side_strategy_type + UniqueSubRange2, UniqueSubRange1, UmbrellaStrategy > swapped_side_calculator_type; intersection_info_base(UniqueSubRange1 const& range_p, @@ -364,9 +357,10 @@ public: no_rescale_policy const& ) : m_range_p(range_p) , m_range_q(range_q) - , m_side_calc(range_p, range_q, - umbrella_strategy.get_side_strategy()) - , m_result(umbrella_strategy.apply(range_p, range_q, intersection_policy_type())) + , m_side_calc(range_p, range_q, umbrella_strategy) + , m_swapped_side_calc(range_q, range_p, umbrella_strategy) + , m_result(umbrella_strategy.relate() + .apply(range_p, range_q, intersection_policy_type())) {} inline bool p_is_last_segment() const { return m_range_p.is_last_segment(); } @@ -381,13 +375,9 @@ public: inline point2_type const& rqk() const { return m_side_calc.get_qk(); } inline side_calculator_type const& sides() const { return m_side_calc; } - - swapped_side_calculator_type get_swapped_sides() const + inline swapped_side_calculator_type const& swapped_sides() const { - swapped_side_calculator_type result( - m_range_q, m_range_p, - m_side_calc.m_side_strategy); - return result; + return m_swapped_side_calc; } private : @@ -397,6 +387,7 @@ private : // Owned by this class side_calculator_type m_side_calc; + swapped_side_calculator_type m_swapped_side_calc; protected : result_type m_result; @@ -422,8 +413,6 @@ public: typedef typename UniqueSubRange1::point_type point1_type; typedef typename UniqueSubRange2::point_type point2_type; - typedef UmbrellaStrategy intersection_strategy_type; - typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; typedef typename UmbrellaStrategy::cs_tag cs_tag; typedef typename base::side_calculator_type side_calculator_type; @@ -437,7 +426,7 @@ public: UmbrellaStrategy const& umbrella_strategy, RobustPolicy const& robust_policy) : base(range_p, range_q, umbrella_strategy, robust_policy) - , m_intersection_strategy(umbrella_strategy) + , m_umbrella_strategy(umbrella_strategy) , m_robust_policy(robust_policy) {} @@ -445,11 +434,6 @@ public: inline i_info_type const& i_info() const { return base::m_result.intersection_points; } inline d_info_type const& d_info() const { return base::m_result.direction; } - inline side_strategy_type get_side_strategy() const - { - return m_intersection_strategy.get_side_strategy(); - } - // TODO: it's more like is_spike_ip_p inline bool is_spike_p() const { @@ -524,6 +508,11 @@ public: return false; } + UmbrellaStrategy const& strategy() const + { + return m_umbrella_strategy; + } + private: template bool is_ip_j() const @@ -548,7 +537,7 @@ private: } } - UmbrellaStrategy const& m_intersection_strategy; + UmbrellaStrategy const& m_umbrella_strategy; RobustPolicy const& m_robust_policy; }; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index 5b5273392..20aaa6a43 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -79,7 +79,7 @@ struct get_turn_info_linear_areal case 's' : // starts from the middle get_turn_info_for_endpoint(range_p, range_q, tp_model, inters, method_none, out, - umbrella_strategy.get_point_in_point_strategy()); + umbrella_strategy); break; case 'd' : // disjoint: never do anything @@ -89,7 +89,7 @@ struct get_turn_info_linear_areal { if ( get_turn_info_for_endpoint(range_p, range_q, tp_model, inters, method_touch_interior, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -109,7 +109,7 @@ struct get_turn_info_linear_areal // Swap p/q handler::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), - inters.get_swapped_sides(), umbrella_strategy); + inters.swapped_sides(), umbrella_strategy); } if ( tp.operations[1].operation == operation_blocked ) @@ -124,7 +124,7 @@ struct get_turn_info_linear_areal // this function assumes that 'u' must be set for a spike calculate_spike_operation(tp.operations[0].operation, inters, - umbrella_strategy.get_point_in_point_strategy()); + umbrella_strategy); *out++ = tp; } @@ -144,7 +144,7 @@ struct get_turn_info_linear_areal // Both touch (both arrive there) if ( get_turn_info_for_endpoint(range_p, range_q, tp_model, inters, method_touch, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -218,7 +218,7 @@ struct get_turn_info_linear_areal bool ignore_spike = calculate_spike_operation(tp.operations[0].operation, inters, - umbrella_strategy.get_point_in_point_strategy()); + umbrella_strategy); if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) || ignore_spike @@ -234,7 +234,7 @@ struct get_turn_info_linear_areal { if ( get_turn_info_for_endpoint(range_p, range_q, tp_model, inters, method_equal, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -279,7 +279,7 @@ struct get_turn_info_linear_areal if ( get_turn_info_for_endpoint( range_p, range_q, tp_model, inters, method_collinear, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -359,13 +359,13 @@ struct get_turn_info_linear_areal if ( range_p.is_first_segment() && equals::equals_point_point(range_p.at(0), tp.point, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { tp.operations[0].position = position_front; } else if ( range_p.is_last_segment() && equals::equals_point_point(range_p.at(1), tp.point, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { tp.operations[0].position = position_back; } @@ -392,10 +392,10 @@ struct get_turn_info_linear_areal template + typename Strategy> static inline bool calculate_spike_operation(Operation & op, IntersectionInfo const& inters, - EqPPStrategy const& strategy) + Strategy const& strategy) { bool is_p_spike = ( op == operation_union || op == operation_intersection ) && inters.is_spike_p(); @@ -415,7 +415,7 @@ struct get_turn_info_linear_areal // spike on the edge point // if it's already known that the spike is going out this musn't be checked if ( ! going_out - && detail::equals::equals_point_point(inters.rpj(), inters.rqj(), strategy) ) + && equals::equals_point_point(inters.rpj(), inters.rqj(), strategy) ) { int const pk_q2 = inters.sides().pk_wrt_q2(); going_in = pk_q1 < 0 && pk_q2 < 0; // Pk on the right of both @@ -427,7 +427,7 @@ struct get_turn_info_linear_areal // spike on the edge point // if it's already known that the spike is going in this musn't be checked if ( ! going_in - && detail::equals::equals_point_point(inters.rpj(), inters.rqj(), strategy) ) + && equals::equals_point_point(inters.rpj(), inters.rqj(), strategy) ) { int const pk_q2 = inters.sides().pk_wrt_q2(); going_in = pk_q1 < 0 || pk_q2 < 0; // Pk on the right of one of them @@ -679,7 +679,7 @@ struct get_turn_info_linear_areal typename TurnInfo, typename IntersectionInfo, typename OutputIterator, - typename EqPPStrategy> + typename Strategy> static inline bool get_turn_info_for_endpoint( UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, @@ -687,7 +687,7 @@ struct get_turn_info_linear_areal IntersectionInfo const& inters, method_type /*method*/, OutputIterator out, - EqPPStrategy const& strategy) + Strategy const& strategy) { namespace ov = overlay; typedef ov::get_turn_info_for_endpoint get_info_e; @@ -705,9 +705,6 @@ struct get_turn_info_linear_areal return false; } - typename IntersectionInfo::side_strategy_type const& sides - = inters.get_side_strategy(); - linear_intersections intersections(range_p.at(0), range_q.at(0), inters.result(), @@ -738,6 +735,8 @@ struct get_turn_info_linear_areal } else { + auto const sides = strategy.side(); + // pi is the intersection point at qj or in the middle of q1 // so consider segments // 1. pi at qj: qi-qj-pj and qi-qj-qk @@ -807,6 +806,8 @@ struct get_turn_info_linear_areal } else //if ( result.template get<0>().count == 1 ) { + auto const sides = strategy.side(); + // pj is the intersection point at qj or in the middle of q1 // so consider segments // 1. pj at qj: qi-qj-pi and qi-qj-qk @@ -863,14 +864,6 @@ struct get_turn_info_linear_areal // don't ignore anything for now return false; } - - template - static inline bool equals_point_point(Point1 const& point1, Point2 const& point2, - IntersectionStrategy const& strategy) - { - return detail::equals::equals_point_point(point1, point2, - strategy.get_point_in_point_strategy()); - } }; }} // namespace detail::overlay diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index 0ea937a1e..ccb5e668a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -75,7 +75,7 @@ struct get_turn_info_linear_linear get_turn_info_for_endpoint ::apply(range_p, range_q, tp_model, inters, method_none, out, - umbrella_strategy.get_point_in_point_strategy()); + umbrella_strategy); break; case 'd' : // disjoint: never do anything @@ -86,7 +86,7 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(range_p, range_q, tp_model, inters, method_touch_interior, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -110,7 +110,7 @@ struct get_turn_info_linear_linear // Swap p/q policy::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), - inters.get_swapped_sides(), + inters.swapped_sides(), umbrella_strategy); } @@ -146,7 +146,7 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(range_p, range_q, tp_model, inters, method_touch, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -278,7 +278,7 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(range_p, range_q, tp_model, inters, method_equal, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -333,7 +333,7 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(range_p, range_q, tp_model, inters, method_collinear, out, - umbrella_strategy.get_point_in_point_strategy()) ) + umbrella_strategy) ) { // do nothing } @@ -416,29 +416,26 @@ struct get_turn_info_linear_linear // degenerate points if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) ) { - typedef typename UmbrellaStrategy::point_in_point_strategy_type - equals_strategy_type; - only_convert::apply(tp, inters.i_info()); // if any, only one of those should be true if ( range_p.is_first_segment() - && equals::equals_point_point(range_p.at(0), tp.point, equals_strategy_type()) ) + && equals::equals_point_point(range_p.at(0), tp.point, umbrella_strategy) ) { tp.operations[0].position = position_front; } else if ( range_p.is_last_segment() - && equals::equals_point_point(range_p.at(1), tp.point, equals_strategy_type()) ) + && equals::equals_point_point(range_p.at(1), tp.point, umbrella_strategy) ) { tp.operations[0].position = position_back; } else if ( range_q.is_first_segment() - && equals::equals_point_point(range_q.at(0), tp.point, equals_strategy_type()) ) + && equals::equals_point_point(range_q.at(0), tp.point, umbrella_strategy) ) { tp.operations[1].position = position_front; } else if ( range_q.is_last_segment() - && equals::equals_point_point(range_q.at(1), tp.point, equals_strategy_type()) ) + && equals::equals_point_point(range_q.at(1), tp.point, umbrella_strategy) ) { tp.operations[1].position = position_back; } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index b8f95f4bf..d2e2734f7 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -108,7 +108,7 @@ template typename Section, typename Point, typename CircularIterator, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy > struct unique_sub_range_from_section @@ -118,16 +118,17 @@ struct unique_sub_range_from_section unique_sub_range_from_section(Section const& section, signed_size_type index, CircularIterator circular_iterator, Point const& previous, Point const& current, + Strategy const& strategy, RobustPolicy const& robust_policy) - : m_section(section) - , m_index(index) - , m_previous_point(previous) - , m_current_point(current) - , m_circular_iterator(circular_iterator) - , m_point_retrieved(false) - , m_robust_policy(robust_policy) - { - } + : m_section(section) + , m_index(index) + , m_previous_point(previous) + , m_current_point(current) + , m_circular_iterator(circular_iterator) + , m_point_retrieved(false) + , m_strategy(strategy) + , m_robust_policy(robust_policy) + {} inline bool is_first_segment() const { @@ -170,7 +171,6 @@ private : inline void advance_to_non_duplicate_next(Point const& current, CircularIterator& circular_iterator) const { - typedef typename IntersectionStrategy::point_in_point_strategy_type disjoint_strategy_type; typedef typename robust_point_type::type robust_point_type; robust_point_type current_robust_point; robust_point_type next_robust_point; @@ -187,11 +187,8 @@ private : // So advance to the "non duplicate next" // (the check is defensive, to avoid endless loops) std::size_t check = 0; - while(! detail::disjoint::disjoint_point_point - ( - current_robust_point, next_robust_point, - disjoint_strategy_type() - ) + while(! detail::disjoint::disjoint_point_point( + current_robust_point, next_robust_point, m_strategy) && check++ < m_section.range_count) { circular_iterator++; @@ -206,6 +203,7 @@ private : mutable CircularIterator m_circular_iterator; mutable Point m_point; mutable bool m_point_retrieved; + Strategy m_strategy; RobustPolicy m_robust_policy; }; @@ -276,12 +274,12 @@ class get_turns_in_sections public : // Returns true if terminated, false if interrupted - template + template static inline bool apply( int source_id1, Geometry1 const& geometry1, Section1 const& sec1, int source_id2, Geometry2 const& geometry2, Section2 const& sec2, bool skip_larger, bool skip_adjacent, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) @@ -337,11 +335,11 @@ public : unique_sub_range_from_section < areal1, Section1, point1_type, circular1_iterator, - IntersectionStrategy, RobustPolicy + Strategy, RobustPolicy > unique_sub_range1(sec1, index1, circular1_iterator(begin_range_1, end_range_1, next1, true), *prev1, *it1, - robust_policy); + strategy, robust_policy); signed_size_type index2 = sec2.begin_index; signed_size_type ndi2 = sec2.non_duplicate_index; @@ -390,11 +388,11 @@ public : unique_sub_range_from_section < areal2, Section2, point2_type, circular2_iterator, - IntersectionStrategy, RobustPolicy + Strategy, RobustPolicy > unique_sub_range2(sec2, index2, circular2_iterator(begin_range_2, end_range_2, next2), *prev2, *it2, - robust_policy); + strategy, robust_policy); typedef typename boost::range_value::type turn_info; @@ -409,7 +407,7 @@ public : std::size_t const size_before = boost::size(turns); TurnPolicy::apply(unique_sub_range1, unique_sub_range2, - ti, intersection_strategy, robust_policy, + ti, strategy, robust_policy, std::back_inserter(turns)); if (InterruptPolicy::enabled) @@ -464,7 +462,7 @@ template typename Geometry1, typename Geometry2, bool Reverse1, bool Reverse2, typename TurnPolicy, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy @@ -475,20 +473,20 @@ struct section_visitor Geometry1 const& m_geometry1; int m_source_id2; Geometry2 const& m_geometry2; - IntersectionStrategy const& m_intersection_strategy; + Strategy const& m_strategy; RobustPolicy const& m_rescale_policy; Turns& m_turns; InterruptPolicy& m_interrupt_policy; section_visitor(int id1, Geometry1 const& g1, int id2, Geometry2 const& g2, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& ip) : m_source_id1(id1), m_geometry1(g1) , m_source_id2(id2), m_geometry2(g2) - , m_intersection_strategy(intersection_strategy) + , m_strategy(strategy) , m_rescale_policy(robust_policy) , m_turns(turns) , m_interrupt_policy(ip) @@ -499,7 +497,7 @@ struct section_visitor { if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box, - m_intersection_strategy.get_disjoint_box_box_strategy())) + m_strategy) ) { // false if interrupted return get_turns_in_sections @@ -512,7 +510,7 @@ struct section_visitor >::apply(m_source_id1, m_geometry1, sec1, m_source_id2, m_geometry2, sec2, false, false, - m_intersection_strategy, + m_strategy, m_rescale_policy, m_turns, m_interrupt_policy); } @@ -531,11 +529,11 @@ class get_turns_generic { public: - template + template static inline void apply( int source_id1, Geometry1 const& geometry1, int source_id2, Geometry2 const& geometry2, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) @@ -556,15 +554,10 @@ public: sections_type sec1, sec2; typedef std::integer_sequence dimensions; - typename IntersectionStrategy::envelope_strategy_type const - envelope_strategy = intersection_strategy.get_envelope_strategy(); - typename IntersectionStrategy::expand_strategy_type const - expand_strategy = intersection_strategy.get_expand_strategy(); - geometry::sectionalize(geometry1, robust_policy, - sec1, envelope_strategy, expand_strategy, 0); + sec1, strategy, 0); geometry::sectionalize(geometry2, robust_policy, - sec2, envelope_strategy, expand_strategy, 1); + sec2, strategy, 1); // ... and then partition them, intersecting overlapping sections in visitor method section_visitor @@ -572,27 +565,17 @@ public: Geometry1, Geometry2, Reverse1, Reverse2, TurnPolicy, - IntersectionStrategy, RobustPolicy, + Strategy, RobustPolicy, Turns, InterruptPolicy > visitor(source_id1, geometry1, source_id2, geometry2, - intersection_strategy, robust_policy, - turns, interrupt_policy); - - typedef detail::section::get_section_box - < - typename IntersectionStrategy::expand_box_strategy_type - > get_section_box_type; - typedef detail::section::overlaps_section_box - < - typename IntersectionStrategy::disjoint_box_box_strategy_type - > overlaps_section_box_type; + strategy, robust_policy, turns, interrupt_policy); geometry::partition < box_type >::apply(sec1, sec2, visitor, - get_section_box_type(), - overlaps_section_box_type()); + detail::section::get_section_box(strategy), + detail::section::overlaps_section_box(strategy)); } }; @@ -1094,10 +1077,10 @@ template > struct get_turns_reversed { - template + template static inline void apply(int source_id1, Geometry1 const& g1, int source_id2, Geometry2 const& g2, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) @@ -1109,7 +1092,7 @@ struct get_turns_reversed Reverse2, Reverse1, TurnPolicy >::apply(source_id2, g2, source_id1, g1, - intersection_strategy, robust_policy, + strategy, robust_policy, turns, interrupt_policy); } }; @@ -1140,14 +1123,14 @@ template typename AssignPolicy, typename Geometry1, typename Geometry2, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy > inline void get_turns(Geometry1 const& geometry1, Geometry2 const& geometry2, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) @@ -1178,7 +1161,7 @@ inline void get_turns(Geometry1 const& geometry1, > >::apply(0, geometry1, 1, geometry2, - intersection_strategy, + strategy, robust_policy, turns, interrupt_policy); } diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp index 5323c699b..aec43548d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp @@ -32,48 +32,6 @@ namespace boost { namespace geometry namespace detail { namespace overlay { - -template -< - typename Point, typename Geometry, - typename Tag2 = typename geometry::tag::type -> -struct check_within_strategy -{ - template - static inline typename Strategy::template point_in_geometry_strategy::type - within(Strategy const& strategy) - { - return strategy.template get_point_in_geometry_strategy(); - } - - template - static inline typename Strategy::template point_in_geometry_strategy::type - covered_by(Strategy const& strategy) - { - return strategy.template get_point_in_geometry_strategy(); - } -}; - -template -struct check_within_strategy -{ - template - static inline typename Strategy::within_point_box_strategy_type - within(Strategy const& ) - { - return typename Strategy::within_point_box_strategy_type(); - } - - template - static inline typename Strategy::covered_by_point_box_strategy_type - covered_by(Strategy const&) - { - return typename Strategy::covered_by_point_box_strategy_type(); - } -}; - - template struct check_within { @@ -86,14 +44,10 @@ struct check_within bool apply(Turn const& turn, Geometry0 const& geometry0, Geometry1 const& geometry1, UmbrellaStrategy const& strategy) { - typedef typename Turn::point_type point_type; - // Operations 0 and 1 have the same source index in self-turns return turn.operations[0].seg_id.source_index == 0 - ? geometry::within(turn.point, geometry1, - check_within_strategy::within(strategy)) - : geometry::within(turn.point, geometry0, - check_within_strategy::within(strategy)); + ? geometry::within(turn.point, geometry1, strategy) + : geometry::within(turn.point, geometry0, strategy); } }; @@ -110,15 +64,11 @@ struct check_within bool apply(Turn const& turn, Geometry0 const& geometry0, Geometry1 const& geometry1, UmbrellaStrategy const& strategy) { - typedef typename Turn::point_type point_type; - // difference = intersection(a, reverse(b)) // therefore we should reverse the meaning of within for geometry1 return turn.operations[0].seg_id.source_index == 0 - ? ! geometry::covered_by(turn.point, geometry1, - check_within_strategy::covered_by(strategy)) - : geometry::within(turn.point, geometry0, - check_within_strategy::within(strategy)); + ? ! geometry::covered_by(turn.point, geometry1, strategy) + : geometry::within(turn.point, geometry0, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 564d063f9..153fb1cf4 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -49,6 +49,10 @@ #include #include +#include +#include +#include + #include #include @@ -100,7 +104,7 @@ struct intersection_segment_segment_point detail::segment_as_subrange sub_range2(segment2); intersection_return_type - is = strategy.apply(sub_range1, sub_range2, policy_type()); + is = strategy.relate().apply(sub_range1, sub_range2, policy_type()); for (std::size_t i = 0; i < is.count; i++) { @@ -1535,9 +1539,9 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1, concepts::check(); concepts::check(); - typedef typename strategy::intersection::services::default_strategy + typedef typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry1, Geometry2 >::type strategy_type; return intersection_insert(geometry1, geometry2, out, diff --git a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp index 25090a58a..557a2a6fd 100644 --- a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp @@ -146,13 +146,13 @@ protected: typename Turns, typename LinearGeometry1, typename LinearGeometry2, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy > static inline void compute_turns(Turns& turns, LinearGeometry1 const& linear1, LinearGeometry2 const& linear2, - IntersectionStrategy const& strategy, + Strategy const& strategy, RobustPolicy const& robust_policy) { turns.clear(); @@ -181,14 +181,14 @@ protected: typename LinearGeometry1, typename LinearGeometry2, typename OutputIterator, - typename IntersectionStrategy + typename Strategy > static inline OutputIterator sort_and_follow_turns(Turns& turns, LinearGeometry1 const& linear1, LinearGeometry2 const& linear2, OutputIterator oit, - IntersectionStrategy const& strategy) + Strategy const& strategy) { // remove turns that have no added value turns::filter_continue_turns @@ -216,7 +216,7 @@ protected: FollowIsolatedPoints, !EnableFilterContinueTurns || OverlayType == overlay_intersection >::apply(linear1, linear2, boost::begin(turns), boost::end(turns), - oit, strategy.get_side_strategy()); + oit, strategy); } public: diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index a3d294701..10034a155 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -197,20 +197,13 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1, Geometry2 const& geometry2, OutputIterator out, Strategy const& strategy) { - typedef std::deque - < - typename geometry::ring_type::type - > ring_container_type; - - typedef typename geometry::point_type::type point_type1; + typedef typename geometry::ring_type::type ring_type; + typedef std::deque ring_container_type; typedef ring_properties < - point_type1, - typename Strategy::template area_strategy - < - point_type1 - >::type::template result_type::type + typename geometry::point_type::type, + typename geometry::area_result::type > properties; // Silence warning C4127: conditional expression is constant @@ -239,8 +232,7 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1, select_rings(geometry1, geometry2, empty, all_of_one_of_them, strategy); ring_container_type rings; assign_parents(geometry1, geometry2, rings, all_of_one_of_them, strategy); - return add_rings(all_of_one_of_them, geometry1, geometry2, rings, out, - strategy.template get_area_strategy()); + return add_rings(all_of_one_of_them, geometry1, geometry2, rings, out, strategy); } @@ -285,10 +277,8 @@ struct overlay > turn_info; typedef std::deque turn_container_type; - typedef std::deque - < - typename geometry::ring_type::type - > ring_container_type; + typedef typename geometry::ring_type::type ring_type; + typedef std::deque ring_container_type; // Define the clusters, mapping cluster_id -> turns typedef std::map @@ -365,12 +355,10 @@ std::cout << "traverse" << std::endl; get_ring_turn_info(turn_info_per_ring, turns, clusters); - typedef typename Strategy::template area_strategy::type area_strategy_type; - typedef ring_properties < point_type, - typename area_strategy_type::template result_type::type + typename geometry::area_result::type > properties; // Select all rings which are NOT touched by any intersection point @@ -379,7 +367,6 @@ std::cout << "traverse" << std::endl; selected_ring_properties, strategy); // Add rings created during traversal - area_strategy_type const area_strategy = strategy.template get_area_strategy(); { ring_identifier id(2, 0, -1); for (typename boost::range_iterator::type @@ -387,7 +374,7 @@ std::cout << "traverse" << std::endl; it != boost::end(rings); ++it) { - selected_ring_properties[id] = properties(*it, area_strategy); + selected_ring_properties[id] = properties(*it, strategy); selected_ring_properties[id].reversed = ReverseOut; id.multi_index++; } @@ -404,7 +391,7 @@ std::cout << "traverse" << std::endl; // The result may be too big, so the area is negative. In this case either // it can be returned or an exception can be thrown. return add_rings(selected_ring_properties, geometry1, geometry2, rings, out, - area_strategy, + strategy, OverlayType == overlay_union ? #if defined(BOOST_GEOMETRY_UNION_THROW_INVALID_OUTPUT_EXCEPTION) add_rings_throw_if_reversed diff --git a/include/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp b/include/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp index f1da6aba6..8b62b0752 100644 --- a/include/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp @@ -63,44 +63,68 @@ template class multipoint_multipolygon_point { private: - template + template struct expand_box_point { + explicit expand_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Point const& point) + inline void apply(Box& total, Point const& point) const { - geometry::expand(total, point, ExpandPointStrategy()); + geometry::expand(total, point, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct expand_box_boxpair { + explicit expand_box_boxpair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box1& total, std::pair const& box_pair) + inline void apply(Box1& total, std::pair const& box_pair) const { - geometry::expand(total, box_pair.first, ExpandBoxStrategy()); + geometry::expand(total, box_pair.first, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_point { + explicit overlaps_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Point const& point) + inline bool apply(Box const& box, Point const& point) const { - return ! geometry::disjoint(point, box, DisjointPointBoxStrategy()); + return ! geometry::disjoint(point, box, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_boxpair { + explicit overlaps_box_boxpair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box1 const& box, std::pair const& box_pair) + inline bool apply(Box1 const& box, std::pair const& box_pair) const { - return ! geometry::disjoint(box, box_pair.first, DisjointBoxBoxStrategy()); + return ! geometry::disjoint(box, box_pair.first, m_strategy); } + + Strategy const& m_strategy; }; template @@ -137,10 +161,10 @@ private: Strategy const& m_strategy; }; - template + template static inline void fill_box_pairs(Iterator first, Iterator last, std::vector > & box_pairs, - EnvelopeStrategy const& strategy) + Strategy const& strategy) { SizeT index = 0; for (; first != last; ++first, ++index) @@ -172,29 +196,16 @@ private: fill_box_pairs(boost::begin(multipolygon), boost::end(multipolygon), - box_pairs, - strategy.get_envelope_strategy()); - - // TEMP - envelope umbrella strategy also contains - // expand strategies - using expand_box_strategy_type = decltype( - strategies::envelope::services::strategy_converter - < - typename Strategy::envelope_strategy_type - >::get(strategy.get_envelope_strategy()) - .expand(std::declval(), std::declval())); - typedef typename Strategy::disjoint_box_box_strategy_type disjoint_box_box_strategy_type; - typedef typename Strategy::disjoint_point_box_strategy_type disjoint_point_box_strategy_type; - typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type; + box_pairs, strategy); geometry::partition < box_type >::apply(multipoint, box_pairs, item_visitor, - expand_box_point(), - overlaps_box_point(), - expand_box_boxpair(), - overlaps_box_boxpair()); + expand_box_point(strategy), + overlaps_box_point(strategy), + expand_box_boxpair(strategy), + overlaps_box_boxpair(strategy)); return oit; } diff --git a/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp index a05ee0b73..bbf62b363 100644 --- a/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp @@ -127,20 +127,26 @@ class multipoint_linear_point { private: // structs for partition -- start - template + template struct expand_box_point { + expand_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Point const& point) + inline void apply(Box& total, Point const& point) const { - geometry::expand(total, point, ExpandPointStrategy()); + geometry::expand(total, point, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct expand_box_segment { - explicit expand_box_segment(EnvelopeStrategy const& strategy) + explicit expand_box_segment(Strategy const& strategy) : m_strategy(strategy) {} @@ -149,31 +155,32 @@ private: { geometry::expand(total, geometry::return_envelope(segment, m_strategy), - // TEMP - envelope umbrella strategy also contains - // expand strategies - strategies::envelope::services::strategy_converter - < - EnvelopeStrategy - >::get(m_strategy)); + m_strategy); } - EnvelopeStrategy const& m_strategy; + Strategy const& m_strategy; }; - template + template struct overlaps_box_point { + explicit overlaps_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Point const& point) + inline bool apply(Box const& box, Point const& point) const { - return ! geometry::disjoint(point, box, DisjointPointBoxStrategy()); + return ! geometry::disjoint(point, box, m_strategy); } + + Strategy const& m_strategy; }; - template + template struct overlaps_box_segment { - explicit overlaps_box_segment(DisjointStrategy const& strategy) + explicit overlaps_box_segment(Strategy const& strategy) : m_strategy(strategy) {} @@ -183,7 +190,7 @@ private: return ! geometry::disjoint(segment, box, m_strategy); } - DisjointStrategy const& m_strategy; + Strategy const& m_strategy; }; template @@ -218,7 +225,7 @@ private: typedef geometry::segment_iterator const_iterator; typedef const_iterator iterator; - segment_range(Linear const& linear) + explicit segment_range(Linear const& linear) : m_linear(linear) {} @@ -244,11 +251,6 @@ private: { item_visitor_type item_visitor(oit, strategy); - typedef typename Strategy::envelope_strategy_type envelope_strategy_type; - typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type; - typedef typename Strategy::disjoint_point_box_strategy_type disjoint_point_box_strategy_type; - typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type; - // TODO: disjoint Segment/Box may be called in partition multiple times // possibly for non-cartesian segments which could be slow. We should consider // passing a range of bounding boxes of segments after calculating them once. @@ -261,10 +263,10 @@ private: typename boost::range_value::type > >::apply(multipoint, segment_range(linear), item_visitor, - expand_box_point(), - overlaps_box_point(), - expand_box_segment(strategy.get_envelope_strategy()), - overlaps_box_segment(strategy.get_disjoint_strategy())); + expand_box_point(strategy), + overlaps_box_point(strategy), + expand_box_segment(strategy), + overlaps_box_segment(strategy)); return oit; } diff --git a/include/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp b/include/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp index 09a397e0b..6f49f5168 100644 --- a/include/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp @@ -98,9 +98,9 @@ struct point_in_geometry_helper { template static inline int apply(Point const& point, Box const& box, - Strategy const&) + Strategy const& strategy) { - return geometry::covered_by(point, box) ? 1 : -1; + return geometry::covered_by(point, box, strategy) ? 1 : -1; } }; @@ -126,15 +126,9 @@ static inline int range_in_geometry(Geometry1 const& geometry1, ++it; } - typename Strategy::template point_in_geometry_strategy - < - Geometry1, Geometry2 - >::type const in_strategy - = strategy.template get_point_in_geometry_strategy(); - for ( ; it != end; ++it) { - result = point_in_geometry_helper::apply(*it, geometry2, in_strategy); + result = point_in_geometry_helper::apply(*it, geometry2, strategy); if (result != 0) { return result; @@ -153,8 +147,7 @@ inline int range_in_geometry(Point1 const& first_point1, Strategy const& strategy) { // check a point on border of geometry1 first - int result = point_in_geometry_helper::apply(first_point1, geometry2, - strategy.template get_point_in_geometry_strategy()); + int result = point_in_geometry_helper::apply(first_point1, geometry2, strategy); if (result == 0) { // if a point is on boundary of geometry2 diff --git a/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp index 7dbc5d5fa..c5341832b 100644 --- a/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp @@ -56,8 +56,8 @@ struct ring_properties , parent_area(-1) {} - template - inline ring_properties(RingOrBox const& ring_or_box, AreaStrategy const& strategy) + template + inline ring_properties(RingOrBox const& ring_or_box, Strategy const& strategy) : reversed(false) , discarded(false) , parent_area(-1) diff --git a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp index d0fc67231..5b4af8513 100644 --- a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp @@ -62,18 +62,18 @@ namespace dispatch template struct select_rings { - template + template static inline void apply(Box const& box, Geometry const& , ring_identifier const& id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy); } - template + template static inline void apply(Box const& box, ring_identifier const& id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy); } @@ -82,10 +82,10 @@ namespace dispatch template struct select_rings { - template + template static inline void apply(Ring const& ring, Geometry const& , ring_identifier const& id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { if (boost::size(ring) > 0) { @@ -93,10 +93,10 @@ namespace dispatch } } - template + template static inline void apply(Ring const& ring, ring_identifier const& id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { if (boost::size(ring) > 0) { @@ -109,10 +109,10 @@ namespace dispatch template struct select_rings { - template + template static inline void apply(Polygon const& polygon, Geometry const& geometry, ring_identifier id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { typedef typename geometry::ring_type::type ring_type; typedef select_rings per_ring; @@ -129,10 +129,10 @@ namespace dispatch } } - template + template static inline void apply(Polygon const& polygon, ring_identifier id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { typedef typename geometry::ring_type::type ring_type; typedef select_rings per_ring; @@ -153,10 +153,10 @@ namespace dispatch template struct select_rings { - template + template static inline void apply(Multi const& multi, Geometry const& geometry, ring_identifier id, RingPropertyMap& ring_properties, - AreaStrategy const& strategy) + Strategy const& strategy) { typedef typename boost::range_iterator < @@ -321,16 +321,14 @@ inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2, { typedef typename geometry::tag::type tag1; typedef typename geometry::tag::type tag2; - typedef typename geometry::point_type::type point1_type; - typedef typename geometry::point_type::type point2_type; - + RingPropertyMap all_ring_properties; dispatch::select_rings::apply(geometry1, geometry2, ring_identifier(0, -1, -1), all_ring_properties, - strategy.template get_area_strategy()); + strategy); dispatch::select_rings::apply(geometry2, geometry1, ring_identifier(1, -1, -1), all_ring_properties, - strategy.template get_area_strategy()); + strategy); update_ring_selection(geometry1, geometry2, turn_info_per_ring, all_ring_properties, selected_ring_properties, @@ -356,7 +354,7 @@ inline void select_rings(Geometry const& geometry, RingPropertyMap all_ring_properties; dispatch::select_rings::apply(geometry, ring_identifier(0, -1, -1), all_ring_properties, - strategy.template get_area_strategy()); + strategy); update_ring_selection(geometry, geometry, turn_info_per_ring, all_ring_properties, selected_ring_properties, diff --git a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp index 740756666..0845390a9 100644 --- a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp @@ -63,14 +63,14 @@ template typename Geometry, typename Turns, typename TurnPolicy, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy, typename InterruptPolicy > struct self_section_visitor { Geometry const& m_geometry; - IntersectionStrategy const& m_intersection_strategy; + Strategy const& m_strategy; RobustPolicy const& m_rescale_policy; Turns& m_turns; InterruptPolicy& m_interrupt_policy; @@ -78,14 +78,14 @@ struct self_section_visitor bool m_skip_adjacent; inline self_section_visitor(Geometry const& g, - IntersectionStrategy const& is, + Strategy const& s, RobustPolicy const& rp, Turns& turns, InterruptPolicy& ip, int source_index, bool skip_adjacent) : m_geometry(g) - , m_intersection_strategy(is) + , m_strategy(s) , m_rescale_policy(rp) , m_turns(turns) , m_interrupt_policy(ip) @@ -98,7 +98,7 @@ struct self_section_visitor { if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box, - m_intersection_strategy.get_disjoint_box_box_strategy()) + m_strategy) && ! sec1.duplicate && ! sec2.duplicate) { @@ -112,7 +112,7 @@ struct self_section_visitor >::apply(m_source_index, m_geometry, sec1, m_source_index, m_geometry, sec2, false, m_skip_adjacent, - m_intersection_strategy, + m_strategy, m_rescale_policy, m_turns, m_interrupt_policy); } @@ -127,10 +127,10 @@ struct self_section_visitor template struct get_turns { - template + template static inline bool apply( Geometry const& geometry, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy, @@ -152,32 +152,23 @@ struct get_turns typedef std::integer_sequence dimensions; sections_type sec; - geometry::sectionalize(geometry, robust_policy, sec, - intersection_strategy.get_envelope_strategy(), - intersection_strategy.get_expand_strategy()); + geometry::sectionalize(geometry, robust_policy, + sec, strategy); self_section_visitor < Reverse, Geometry, - Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy - > visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy, source_index, skip_adjacent); - - typedef detail::section::get_section_box - < - typename IntersectionStrategy::expand_box_strategy_type - > get_section_box_type; - typedef detail::section::overlaps_section_box - < - typename IntersectionStrategy::disjoint_box_box_strategy_type - > overlaps_section_box_type; + Turns, TurnPolicy, Strategy, RobustPolicy, InterruptPolicy + > visitor(geometry, strategy, robust_policy, turns, interrupt_policy, + source_index, skip_adjacent); // false if interrupted geometry::partition < box_type >::apply(sec, visitor, - get_section_box_type(), - overlaps_section_box_type()); + detail::section::get_section_box(strategy), + detail::section::overlaps_section_box(strategy)); return ! interrupt_policy.has_intersections; } @@ -340,13 +331,13 @@ template < typename AssignPolicy, typename Geometry, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy > inline void self_turns(Geometry const& geometry, - IntersectionStrategy const& strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy, diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp index e180c47bf..fd3513ff2 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp @@ -44,7 +44,7 @@ template typename Turns, typename TurnInfoMap, typename Clusters, - typename IntersectionStrategy, + typename Strategy, typename RobustPolicy, typename Visitor, typename Backtrack @@ -55,7 +55,8 @@ struct traversal_ring_creator < Reverse1, Reverse2, OverlayType, Geometry1, Geometry2, Turns, Clusters, - RobustPolicy, typename IntersectionStrategy::side_strategy_type, + RobustPolicy, + decltype(std::declval().side()), Visitor > traversal_type; @@ -68,17 +69,16 @@ struct traversal_ring_creator inline traversal_ring_creator(Geometry1 const& geometry1, Geometry2 const& geometry2, Turns& turns, TurnInfoMap& turn_info_map, Clusters const& clusters, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, Visitor& visitor) : m_trav(geometry1, geometry2, turns, clusters, - robust_policy, intersection_strategy.get_side_strategy(), - visitor) + robust_policy, strategy.side(), visitor) , m_geometry1(geometry1) , m_geometry2(geometry2) , m_turns(turns) , m_turn_info_map(turn_info_map) , m_clusters(clusters) - , m_intersection_strategy(intersection_strategy) + , m_strategy(strategy) , m_robust_policy(robust_policy) , m_visitor(visitor) { @@ -113,15 +113,13 @@ struct traversal_ring_creator { geometry::copy_segments(m_geometry1, previous_op.seg_id, to_vertex_index, - m_intersection_strategy.get_side_strategy(), - m_robust_policy, current_ring); + m_strategy, m_robust_policy, current_ring); } else { geometry::copy_segments(m_geometry2, previous_op.seg_id, to_vertex_index, - m_intersection_strategy.get_side_strategy(), - m_robust_policy, current_ring); + m_strategy, m_robust_policy, current_ring); } } @@ -164,8 +162,7 @@ struct traversal_ring_creator turn_type& current_turn = m_turns[turn_index]; turn_operation_type& op = current_turn.operations[op_index]; detail::overlay::append_no_collinear(current_ring, current_turn.point, - m_intersection_strategy.get_side_strategy(), - m_robust_policy); + m_strategy, m_robust_policy); // Register the visit m_trav.set_visited(current_turn, op); @@ -182,8 +179,7 @@ struct traversal_ring_creator turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index]; detail::overlay::append_no_collinear(ring, start_turn.point, - m_intersection_strategy.get_side_strategy(), - m_robust_policy); + m_strategy, m_robust_policy); signed_size_type current_turn_index = start_turn_index; int current_op_index = start_op_index; @@ -286,9 +282,7 @@ struct traversal_ring_creator if (geometry::num_points(ring) >= min_num_points) { - clean_closing_dups_and_spikes(ring, - m_intersection_strategy.get_side_strategy(), - m_robust_policy); + clean_closing_dups_and_spikes(ring, m_strategy, m_robust_policy); rings.push_back(ring); m_trav.finalize_visit_info(m_turn_info_map); @@ -297,14 +291,13 @@ struct traversal_ring_creator } else { - Backtrack::apply( - finalized_ring_size, - rings, ring, m_turns, start_turn, - m_turns[turn_index].operations[op_index], - traverse_error, - m_geometry1, m_geometry2, - m_intersection_strategy, m_robust_policy, - state, m_visitor); + Backtrack::apply(finalized_ring_size, + rings, ring, m_turns, start_turn, + m_turns[turn_index].operations[op_index], + traverse_error, + m_geometry1, m_geometry2, + m_strategy, m_robust_policy, + state, m_visitor); } } @@ -413,7 +406,7 @@ private: Turns& m_turns; TurnInfoMap& m_turn_info_map; // contains turn-info information per ring Clusters const& m_clusters; - IntersectionStrategy const& m_intersection_strategy; + Strategy const& m_strategy; RobustPolicy const& m_robust_policy; Visitor& m_visitor; }; diff --git a/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp index 18be9a255..99df598da 100644 --- a/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp @@ -209,10 +209,10 @@ struct areal_areal typedef typename geometry::point_type::type point1_type; typedef typename geometry::point_type::type point2_type; - template + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result, - IntersectionStrategy const& intersection_strategy) + Strategy const& strategy) { // TODO: If Areal geometry may have infinite size, change the following line: @@ -226,38 +226,25 @@ struct areal_areal typedef typename turns::get_turns < Geometry1, Geometry2 - >::template turn_info_type::type turn_type; + >::template turn_info_type::type turn_type; std::vector turns; interrupt_policy_areal_areal interrupt_policy(geometry1, geometry2, result); - turns::get_turns::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); + turns::get_turns::apply(turns, geometry1, geometry2, interrupt_policy, strategy); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; - typedef typename IntersectionStrategy::cs_tag cs_tag; + typedef typename Strategy::cs_tag cs_tag; - typedef typename IntersectionStrategy::template point_in_geometry_strategy - < - Geometry1, Geometry2 - >::type point_in_areal_strategy12_type; - point_in_areal_strategy12_type point_in_areal_strategy12 - = intersection_strategy.template get_point_in_geometry_strategy(); - typedef typename IntersectionStrategy::template point_in_geometry_strategy - < - Geometry2, Geometry1 - >::type point_in_areal_strategy21_type; - point_in_areal_strategy21_type point_in_areal_strategy21 - = intersection_strategy.template get_point_in_geometry_strategy(); - - no_turns_aa_pred - pred1(geometry2, result, point_in_areal_strategy12); + no_turns_aa_pred + pred1(geometry2, result, strategy); for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; - no_turns_aa_pred - pred2(geometry1, result, point_in_areal_strategy21); + no_turns_aa_pred + pred2(geometry1, result, strategy); for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; @@ -282,8 +269,7 @@ struct areal_areal { // analyse sorted turns turns_analyser analyser; - analyse_each_turn(result, analyser, turns.begin(), turns.end(), - point_in_areal_strategy12.get_equals_point_point_strategy()); + analyse_each_turn(result, analyser, turns.begin(), turns.end(), strategy); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; @@ -297,8 +283,8 @@ struct areal_areal { // analyse rings for which turns were not generated // or only i/i or u/u was generated - uncertain_rings_analyser<0, Result, Geometry1, Geometry2, point_in_areal_strategy12_type> - rings_analyser(result, geometry1, geometry2, point_in_areal_strategy12); + uncertain_rings_analyser<0, Result, Geometry1, Geometry2, Strategy> + rings_analyser(result, geometry1, geometry2, strategy); analyse_uncertain_rings<0>::apply(rings_analyser, turns.begin(), turns.end()); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) @@ -323,8 +309,7 @@ struct areal_areal { // analyse sorted turns turns_analyser analyser; - analyse_each_turn(result, analyser, turns.begin(), turns.end(), - point_in_areal_strategy21.get_equals_point_point_strategy()); + analyse_each_turn(result, analyser, turns.begin(), turns.end(), strategy); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; @@ -338,8 +323,8 @@ struct areal_areal { // analyse rings for which turns were not generated // or only i/i or u/u was generated - uncertain_rings_analyser<1, Result, Geometry2, Geometry1, point_in_areal_strategy21_type> - rings_analyser(result, geometry2, geometry1, point_in_areal_strategy21); + uncertain_rings_analyser<1, Result, Geometry2, Geometry1, Strategy> + rings_analyser(result, geometry2, geometry1, strategy); analyse_uncertain_rings<1>::apply(rings_analyser, turns.begin(), turns.end()); //if ( result.interrupt ) diff --git a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp index 89101ff93..487c706e9 100644 --- a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp +++ b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2018 Oracle and/or its affiliates. +// Copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -30,27 +30,29 @@ namespace detail { namespace relate { enum boundary_query { boundary_front, boundary_back, boundary_any }; -template ::type> +template +< + typename Geometry, + typename Strategy, + typename Tag = typename geometry::tag::type +> class boundary_checker {}; -template -class boundary_checker +template +class boundary_checker { typedef typename point_type::type point_type; public: - typedef WithinStrategy equals_strategy_type; - - boundary_checker(Geometry const& g) - : has_boundary( boost::size(g) >= 2 - && !detail::equals::equals_point_point(range::front(g), - range::back(g), - equals_strategy_type()) ) + boundary_checker(Geometry const& g, Strategy const& s) + : m_has_boundary( boost::size(g) >= 2 + && ! detail::equals::equals_point_point(range::front(g), + range::back(g), + s) ) #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER - , geometry(g) + , m_geometry(g) #endif + , m_strategy(s) {} template @@ -60,30 +62,34 @@ public: #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER // may give false positives for INT BOOST_GEOMETRY_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any) - && detail::equals::equals_point_point(pt, range::front(geometry), WithinStrategy()) + && detail::equals::equals_point_point(pt, range::front(m_geometry), m_strategy) || (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any) - && detail::equals::equals_point_point(pt, range::back(geometry), WithinStrategy()) ); + && detail::equals::equals_point_point(pt, range::back(m_geometry), m_strategy) ); #endif - return has_boundary; + return m_has_boundary; + } + + Strategy const& strategy() const + { + return m_strategy; } private: - bool has_boundary; + bool m_has_boundary; #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER - Geometry const& geometry; + Geometry const& m_geometry; #endif + Strategy const& m_strategy; }; -template -class boundary_checker +template +class boundary_checker { typedef typename point_type::type point_type; public: - typedef WithinStrategy equals_strategy_type; - - boundary_checker(Geometry const& g) - : is_filled(false), geometry(g) + boundary_checker(Geometry const& g, Strategy const& s) + : m_is_filled(false), m_geometry(g), m_strategy(s) {} // First call O(NlogN) @@ -91,22 +97,22 @@ public: template bool is_endpoint_boundary(point_type const& pt) const { - typedef geometry::less less_type; + typedef geometry::less less_type; typedef typename boost::range_size::type size_type; - size_type multi_count = boost::size(geometry); + size_type multi_count = boost::size(m_geometry); if ( multi_count < 1 ) return false; - if ( ! is_filled ) + if ( ! m_is_filled ) { //boundary_points.clear(); - boundary_points.reserve(multi_count * 2); + m_boundary_points.reserve(multi_count * 2); typedef typename boost::range_iterator::type multi_iterator; - for ( multi_iterator it = boost::begin(geometry) ; - it != boost::end(geometry) ; ++ it ) + for ( multi_iterator it = boost::begin(m_geometry) ; + it != boost::end(m_geometry) ; ++ it ) { typename boost::range_reference::type ls = *it; @@ -126,33 +132,33 @@ public: point_reference back_pt = range::back(ls); // linear ring or point - no boundary - if (! equals::equals_point_point(front_pt, back_pt, equals_strategy_type())) + if (! equals::equals_point_point(front_pt, back_pt, m_strategy)) { // do not add points containing NaN coordinates // because they cannot be reasonably compared, e.g. with MSVC // an assertion failure is reported in std::equal_range() if (! geometry::has_nan_coordinate(front_pt)) { - boundary_points.push_back(front_pt); + m_boundary_points.push_back(front_pt); } if (! geometry::has_nan_coordinate(back_pt)) { - boundary_points.push_back(back_pt); + m_boundary_points.push_back(back_pt); } } } - std::sort(boundary_points.begin(), - boundary_points.end(), + std::sort(m_boundary_points.begin(), + m_boundary_points.end(), less_type()); - is_filled = true; + m_is_filled = true; } std::size_t equal_points_count = boost::size( - std::equal_range(boundary_points.begin(), - boundary_points.end(), + std::equal_range(m_boundary_points.begin(), + m_boundary_points.end(), pt, less_type()) ); @@ -160,12 +166,18 @@ public: return equal_points_count % 2 != 0;// && equal_points_count > 0; // the number is odd and > 0 } -private: - mutable bool is_filled; - // TODO: store references/pointers instead of points? - mutable std::vector boundary_points; + Strategy const& strategy() const + { + return m_strategy; + } - Geometry const& geometry; +private: + mutable bool m_is_filled; + // TODO: store references/pointers instead of points? + mutable std::vector m_boundary_points; + + Geometry const& m_geometry; + Strategy const& m_strategy; }; }} // namespace detail::relate diff --git a/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp b/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp index 139664cc7..d584e81e5 100644 --- a/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp +++ b/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp @@ -341,9 +341,9 @@ private: std::vector m_other_entry_points; // TODO: use map here or sorted vector? }; -template +template inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn, - EqPPStrategy const& strategy) + Strategy const& strategy) { segment_identifier const& prev_seg_id = prev_turn.operations[OpId].seg_id; segment_identifier const& curr_seg_id = curr_turn.operations[OpId].seg_id; diff --git a/include/boost/geometry/algorithms/detail/relate/interface.hpp b/include/boost/geometry/algorithms/detail/relate/interface.hpp index 1c06d65d5..801ad21db 100644 --- a/include/boost/geometry/algorithms/detail/relate/interface.hpp +++ b/include/boost/geometry/algorithms/detail/relate/interface.hpp @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include #include @@ -161,9 +162,15 @@ struct result_handler_type::value +> struct relate { - template + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, ResultHandler & handler, @@ -175,14 +182,37 @@ struct relate Geometry2 >::apply(geometry1, geometry2, handler, strategy); } +}; +template +struct relate +{ + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + ResultHandler & handler, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + dispatch::relate + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, handler, + strategy_converter::get(strategy)); + } +}; + +template <> +struct relate +{ template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, ResultHandler & handler, default_strategy) { - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 @@ -220,7 +250,7 @@ struct relate Mask >::type handler(mask); - resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy); + resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy); return handler.result(); } diff --git a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp index 031564898..28823433a 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -229,10 +229,10 @@ struct linear_areal > {}; - template + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result, - IntersectionStrategy const& intersection_strategy) + Strategy const& strategy) { // TODO: If Areal geometry may have infinite size, change the following line: @@ -243,38 +243,34 @@ struct linear_areal return; // get and analyse turns - typedef typename turn_info_type::type turn_type; + typedef typename turn_info_type::type turn_type; std::vector turns; interrupt_policy_linear_areal interrupt_policy(geometry2, result); - turns::get_turns::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); + turns::get_turns::apply(turns, geometry1, geometry2, interrupt_policy, strategy); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; - typedef typename IntersectionStrategy::template point_in_geometry_strategy::type within_strategy_type; - within_strategy_type const within_strategy = intersection_strategy.template get_point_in_geometry_strategy(); - - typedef typename IntersectionStrategy::cs_tag cs_tag; - typedef typename within_strategy_type::equals_point_point_strategy_type eq_pp_strategy_type; + typedef typename Strategy::cs_tag cs_tag; typedef boundary_checker < Geometry1, - eq_pp_strategy_type + Strategy > boundary_checker1_type; - boundary_checker1_type boundary_checker1(geometry1); + boundary_checker1_type boundary_checker1(geometry1, strategy); no_turns_la_linestring_pred < Geometry2, Result, - within_strategy_type, + Strategy, boundary_checker1_type, TransposeResult > pred1(geometry2, result, - within_strategy, + strategy, boundary_checker1); for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) @@ -302,7 +298,7 @@ struct linear_areal turns.begin(), turns.end(), geometry1, geometry2, boundary_checker1, - intersection_strategy.get_side_strategy()); + strategy); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; @@ -395,14 +391,12 @@ struct linear_areal typedef turns::less<1, turns::less_op_areal_linear<1>, cs_tag> less; std::sort(it, next, less()); - eq_pp_strategy_type const eq_pp_strategy = within_strategy.get_equals_point_point_strategy(); - // analyse areal_boundary_analyser analyser; for ( turn_iterator rit = it ; rit != next ; ++rit ) { // if the analyser requests, break the search - if ( !analyser.apply(it, rit, next, eq_pp_strategy) ) + if ( !analyser.apply(it, rit, next, strategy) ) break; } @@ -626,18 +620,20 @@ struct linear_areal static const std::size_t other_op_id = 1; template struct la_side_calculator { + typedef decltype(std::declval().side()) side_strategy_type; + inline la_side_calculator(Pi const& pi, Pj const& pj, Pk const& pk, - Qi const& qi, Qj const& qj, Qk const& qk, - SideStrategy const& side_strategy) + Qi const& qi, Qj const& qj, Qk const& qk, + Strategy const& strategy) : m_pi(pi), m_pj(pj), m_pk(pk) , m_qi(qi), m_qj(qj), m_qk(qk) - , m_side_strategy(side_strategy) + , m_side_strategy(strategy.side()) {} inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); } @@ -652,7 +648,7 @@ struct linear_areal Qj const& m_qj; Qk const& m_qk; - SideStrategy m_side_strategy; + side_strategy_type m_side_strategy; }; @@ -672,12 +668,12 @@ struct linear_areal typename Geometry, typename OtherGeometry, typename BoundaryChecker, - typename SideStrategy> + typename Strategy> void apply(Result & res, TurnIt it, Geometry const& geometry, OtherGeometry const& other_geometry, BoundaryChecker const& boundary_checker, - SideStrategy const& side_strategy) + Strategy const& strategy) { overlay::operation_type op = it->operations[op_id].operation; @@ -706,7 +702,7 @@ struct linear_areal // real exit point - may be multiple // we know that we entered and now we exit if ( ! turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it, - side_strategy.get_equals_point_point_strategy()) ) + strategy) ) { m_exit_watcher.reset_detected_exit(); @@ -749,7 +745,7 @@ struct linear_areal if ( ( op == overlay::operation_intersection || op == overlay::operation_continue ) && turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it, - side_strategy.get_equals_point_point_strategy()) ) + strategy) ) { fake_enter_detected = true; } @@ -770,7 +766,7 @@ struct linear_areal || seg_id.multi_index != m_previous_turn_ptr->operations[op_id].seg_id.multi_index ) ) // or the next single-geometry || ( m_previous_operation == overlay::operation_union && ! turn_on_the_same_ip(*m_previous_turn_ptr, *it, - side_strategy.get_equals_point_point_strategy()) ) + strategy) ) ) { update(res); @@ -803,7 +799,7 @@ struct linear_areal // real interior overlap if ( ! turn_on_the_same_ip(*m_previous_turn_ptr, *it, - side_strategy.get_equals_point_point_strategy()) ) + strategy) ) { update(res); m_interior_detected = false; @@ -919,7 +915,7 @@ struct linear_areal && calculate_from_inside(geometry, other_geometry, *it, - side_strategy); + strategy); if ( from_inside ) update(res); @@ -1020,7 +1016,7 @@ struct linear_areal && calculate_from_inside(geometry, other_geometry, *it, - side_strategy); + strategy); if ( first_from_inside ) { update(res); @@ -1208,11 +1204,11 @@ struct linear_areal // check if the passed turn's segment of Linear geometry arrived // from the inside or the outside of the Areal geometry - template + template static inline bool calculate_from_inside(Geometry1 const& geometry1, Geometry2 const& geometry2, Turn const& turn, - SideStrategy const& side_strategy) + Strategy const& strategy) { typedef typename cs_tag::type cs_tag; @@ -1242,7 +1238,7 @@ struct linear_areal point2_type const& qj = range::at(range2, q_seg_ij + 1); point1_type qi_conv; geometry::convert(qi, qi_conv); - bool const is_ip_qj = equals::equals_point_point(turn.point, qj, side_strategy.get_equals_point_point_strategy()); + bool const is_ip_qj = equals::equals_point_point(turn.point, qj, strategy); // TODO: test this! // BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi)); // BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi)); @@ -1257,11 +1253,11 @@ struct linear_areal range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2), range::pos(range2, q_seg_jk), boost::end(range2), - side_strategy.get_equals_point_point_strategy()); + strategy); // Will this sequence of points be always correct? - la_side_calculator - side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, side_strategy); + la_side_calculator + side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, strategy); return calculate_from_inside_sides(side_calc); } @@ -1270,16 +1266,16 @@ struct linear_areal point2_type new_qj; geometry::convert(turn.point, new_qj); - la_side_calculator - side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, side_strategy); + la_side_calculator + side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, strategy); return calculate_from_inside_sides(side_calc); } } - template + template static inline It find_next_non_duplicated(It first, It current, It last, - EqPPStrategy const& strategy) + Strategy const& strategy) { BOOST_GEOMETRY_ASSERT( current != last ); @@ -1340,14 +1336,14 @@ struct linear_areal typename Geometry, typename OtherGeometry, typename BoundaryChecker, - typename SideStrategy> + typename Strategy> static inline void analyse_each_turn(Result & res, Analyser & analyser, TurnIt first, TurnIt last, Geometry const& geometry, OtherGeometry const& other_geometry, BoundaryChecker const& boundary_checker, - SideStrategy const& side_strategy) + Strategy const& strategy) { if ( first == last ) return; @@ -1357,7 +1353,7 @@ struct linear_areal analyser.apply(res, it, geometry, other_geometry, boundary_checker, - side_strategy); + strategy); if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) ) return; @@ -1437,9 +1433,9 @@ struct linear_areal , m_previous_turn_ptr(NULL) {} - template + template bool apply(TurnIt /*first*/, TurnIt it, TurnIt last, - EqPPStrategy const& strategy) + Strategy const& strategy) { overlay::operation_type op = it->operations[1].operation; @@ -1493,12 +1489,12 @@ struct areal_linear static const bool interruption_enabled = linear_areal_type::interruption_enabled; - template + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result, - IntersectionStrategy const& intersection_strategy) + Strategy const& strategy) { - linear_areal_type::apply(geometry2, geometry1, result, intersection_strategy); + linear_areal_type::apply(geometry2, geometry1, result, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp index ec8fe428d..fa46db245 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -42,8 +42,6 @@ namespace detail { namespace relate { template class disjoint_linestring_pred { - typedef typename BoundaryChecker::equals_strategy_type equals_strategy_type; - public: disjoint_linestring_pred(Result & res, BoundaryChecker const& boundary_checker) @@ -83,7 +81,7 @@ public: if ( count == 2 && equals::equals_point_point(range::front(linestring), range::back(linestring), - equals_strategy_type()) ) + m_boundary_checker.strategy()) ) { update(m_result); } @@ -122,12 +120,12 @@ struct linear_linear typedef typename geometry::point_type::type point1_type; typedef typename geometry::point_type::type point2_type; - template + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result, - IntersectionStrategy const& intersection_strategy) + Strategy const& strategy) { - typedef typename IntersectionStrategy::cs_tag cs_tag; + typedef typename Strategy::cs_tag cs_tag; // The result should be FFFFFFFFF relate::set::value>(result);// FFFFFFFFd, d in [1,9] or T @@ -138,7 +136,7 @@ struct linear_linear typedef typename turns::get_turns < Geometry1, Geometry2 - >::template turn_info_type::type turn_type; + >::template turn_info_type::type turn_type; std::vector turns; interrupt_policy_linear_linear interrupt_policy(result); @@ -148,28 +146,20 @@ struct linear_linear Geometry1, Geometry2, detail::get_turns::get_turn_info_type > - >::apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); + >::apply(turns, geometry1, geometry2, interrupt_policy, strategy); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; - typedef boundary_checker - < - Geometry1, - typename IntersectionStrategy::point_in_point_strategy_type - > boundary_checker1_type; - boundary_checker1_type boundary_checker1(geometry1); + typedef boundary_checker boundary_checker1_type; + boundary_checker1_type boundary_checker1(geometry1, strategy); disjoint_linestring_pred pred1(result, boundary_checker1); for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; - typedef boundary_checker - < - Geometry2, - typename IntersectionStrategy::point_in_point_strategy_type - > boundary_checker2_type; - boundary_checker2_type boundary_checker2(geometry2); + typedef boundary_checker boundary_checker2_type; + boundary_checker2_type boundary_checker2(geometry2, strategy); disjoint_linestring_pred pred2(result, boundary_checker2); for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) @@ -292,8 +282,6 @@ struct linear_linear BoundaryChecker const& boundary_checker, OtherBoundaryChecker const& other_boundary_checker) { - typedef typename BoundaryChecker::equals_strategy_type equals_strategy_type; - overlay::operation_type const op = it->operations[op_id].operation; segment_identifier const& seg_id = it->operations[op_id].seg_id; @@ -345,7 +333,7 @@ struct linear_linear // we know that we entered and now we exit if ( ! turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it, - equals_strategy_type()) ) + boundary_checker.strategy()) ) { m_exit_watcher.reset_detected_exit(); @@ -368,7 +356,7 @@ struct linear_linear if ( op == overlay::operation_intersection && turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it, - equals_strategy_type()) ) + boundary_checker.strategy()) ) { fake_enter_detected = true; } @@ -668,14 +656,9 @@ struct linear_linear Geometry const& geometry, OtherGeometry const& other_geometry, BoundaryChecker const& boundary_checker, - OtherBoundaryChecker const& /*other_boundary_checker*/, + OtherBoundaryChecker const& other_boundary_checker, bool first_in_range) { - typedef typename BoundaryChecker::equals_strategy_type - equals_strategy1_type; - typedef typename OtherBoundaryChecker::equals_strategy_type - equals_strategy2_type; - typename detail::single_geometry_return_type::type ls1_ref = detail::single_geometry(geometry, turn.operations[op_id].seg_id); typename detail::single_geometry_return_type::type @@ -745,11 +728,11 @@ struct linear_linear bool const is_point1 = boost::size(ls1_ref) == 2 && equals::equals_point_point(range::front(ls1_ref), range::back(ls1_ref), - equals_strategy1_type()); + boundary_checker.strategy()); bool const is_point2 = boost::size(ls2_ref) == 2 && equals::equals_point_point(range::front(ls2_ref), range::back(ls2_ref), - equals_strategy2_type()); + other_boundary_checker.strategy()); // if the second one is degenerated if ( !is_point1 && is_point2 ) diff --git a/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp b/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp index 12b4ff642..7da7f2be5 100644 --- a/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp @@ -50,21 +50,20 @@ namespace detail { namespace relate template < typename Geometry, - typename EqPPStrategy, typename Tag = typename tag::type > struct multi_point_geometry_eb { - template + template static inline bool apply(MultiPoint const& , - detail::relate::topology_check const& ) + detail::relate::topology_check const& ) { return true; } }; -template -struct multi_point_geometry_eb +template +struct multi_point_geometry_eb { template struct boundary_visitor @@ -74,26 +73,30 @@ struct multi_point_geometry_eb , m_boundary_found(false) {} - template + template struct find_pred { - find_pred(Point const& point) + find_pred(Point const& point, Strategy const& strategy) : m_point(point) + , m_strategy(strategy) {} template bool operator()(Pt const& pt) const { - return detail::equals::equals_point_point(pt, m_point, EqPPStrategy()); + return detail::equals::equals_point_point(pt, m_point, m_strategy); } Point const& m_point; + Strategy const& m_strategy; }; - template - bool apply(Point const& boundary_point) + template + bool apply(Point const& boundary_point, Strategy const& strategy) { - if (std::find_if(m_points.begin(), m_points.end(), find_pred(boundary_point)) == m_points.end()) + if ( std::find_if(m_points.begin(), m_points.end(), + find_pred(boundary_point, strategy)) + == m_points.end() ) { m_boundary_found = true; return false; @@ -108,9 +111,9 @@ struct multi_point_geometry_eb bool m_boundary_found; }; - template + template static inline bool apply(MultiPoint const& multi_point, - detail::relate::topology_check const& tc) + detail::relate::topology_check const& tc) { boundary_visitor visitor(multi_point); tc.for_each_boundary_point(visitor); @@ -118,12 +121,9 @@ struct multi_point_geometry_eb } }; -template -struct multi_point_geometry_eb +template +struct multi_point_geometry_eb { - // TODO: CS-specific less compare strategy derived from EqPPStrategy - typedef geometry::less less_type; - template struct boundary_visitor { @@ -132,10 +132,13 @@ struct multi_point_geometry_eb , m_boundary_found(false) {} - template - bool apply(Point const& boundary_point) + template + bool apply(Point const& boundary_point, Strategy const&) { - if (! std::binary_search(m_points.begin(), m_points.end(), boundary_point, less_type())) + typedef geometry::less less_type; + + if (! std::binary_search(m_points.begin(), m_points.end(), + boundary_point, less_type()) ) { m_boundary_found = true; return false; @@ -150,13 +153,15 @@ struct multi_point_geometry_eb bool m_boundary_found; }; - template + template static inline bool apply(MultiPoint const& multi_point, - detail::relate::topology_check const& tc) + detail::relate::topology_check const& tc) { typedef typename boost::range_value::type point_type; typedef std::vector points_type; - points_type points(boost::begin(multi_point), boost::end(multi_point)); + typedef geometry::less less_type; + + points_type points(boost::begin(multi_point), boost::end(multi_point)); std::sort(points.begin(), points.end(), less_type()); boundary_visitor visitor(points); @@ -179,11 +184,9 @@ struct multi_point_single_geometry { typedef typename point_type::type point2_type; typedef model::box box2_type; - typedef typename Strategy::equals_point_point_strategy_type eq_pp_strategy_type; - typedef typename Strategy::disjoint_point_box_strategy_type d_pb_strategy_type; box2_type box2; - geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy()); + geometry::envelope(single_geometry, box2, strategy); geometry::detail::expand_by_epsilon(box2); typedef typename boost::range_const_iterator::type iterator; @@ -197,7 +200,7 @@ struct multi_point_single_geometry } // The default strategy is enough for Point/Box - if (detail::disjoint::disjoint_point_box(*it, box2, d_pb_strategy_type())) + if (detail::disjoint::disjoint_point_box(*it, box2, strategy)) { relate::set(result); } @@ -225,14 +228,12 @@ struct multi_point_single_geometry } } - typedef detail::relate::topology_check - < - SingleGeometry, eq_pp_strategy_type - > tc_t; + typedef detail::relate::topology_check tc_t; + if ( relate::may_update(result) || relate::may_update(result) ) { - tc_t tc(single_geometry); + tc_t tc(single_geometry, strategy); if ( relate::may_update(result) && tc.has_interior() ) @@ -245,10 +246,7 @@ struct multi_point_single_geometry if ( relate::may_update(result) && tc.has_boundary() ) { - if (multi_point_geometry_eb - < - SingleGeometry, eq_pp_strategy_type - >::apply(multi_point, tc)) + if (multi_point_geometry_eb::apply(multi_point, tc)) { relate::set(result); } @@ -266,62 +264,88 @@ struct multi_point_single_geometry template class multi_point_multi_geometry_ii_ib { - template + template struct expand_box_point { + expand_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Point const& point) + inline void apply(Box& total, Point const& point) const { - geometry::expand(total, point, ExpandPointStrategy()); + geometry::expand(total, point, m_strategy); } + + private: + Strategy const& m_strategy; }; - template + template struct expand_box_box_pair { + expand_box_box_pair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, BoxPair const& box_pair) + inline void apply(Box& total, BoxPair const& box_pair) const { - geometry::expand(total, box_pair.first, ExpandBoxStrategy()); + geometry::expand(total, box_pair.first, m_strategy); } + + private: + Strategy const& m_strategy; }; - template + template struct overlaps_box_point { + overlaps_box_point(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Point const& point) + inline bool apply(Box const& box, Point const& point) const { // The default strategy is enough for Point/Box return ! detail::disjoint::disjoint_point_box(point, box, - DisjointPointBoxStrategy()); + m_strategy); } + + private: + Strategy const& m_strategy; }; - template + template struct overlaps_box_box_pair { + overlaps_box_box_pair(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, BoxPair const& box_pair) + inline bool apply(Box const& box, BoxPair const& box_pair) const { // The default strategy is enough for Box/Box return ! detail::disjoint::disjoint_box_box(box_pair.first, box, - DisjointBoxBoxStrategy()); + m_strategy); } + + private: + Strategy const& m_strategy; }; - template + template class item_visitor_type { - typedef typename PtSegStrategy::equals_point_point_strategy_type pp_strategy_type; - typedef typename PtSegStrategy::disjoint_point_box_strategy_type d_pp_strategy_type; - typedef detail::relate::topology_check topology_check_type; + typedef detail::relate::topology_check topology_check_type; public: item_visitor_type(MultiGeometry const& multi_geometry, topology_check_type const& tc, Result & result, - PtSegStrategy const& strategy) + Strategy const& strategy) : m_multi_geometry(multi_geometry) , m_tc(tc) , m_result(result) @@ -332,7 +356,7 @@ class multi_point_multi_geometry_ii_ib inline bool apply(Point const& point, BoxPair const& box_pair) { // The default strategy is enough for Point/Box - if (! detail::disjoint::disjoint_point_box(point, box_pair.first, d_pp_strategy_type())) + if (! detail::disjoint::disjoint_point_box(point, box_pair.first, m_strategy) ) { typename boost::range_value::type const& single = range::at(m_multi_geometry, box_pair.second); @@ -371,7 +395,7 @@ class multi_point_multi_geometry_ii_ib MultiGeometry const& m_multi_geometry; topology_check_type const& m_tc; Result & m_result; - PtSegStrategy const& m_strategy; + Strategy const& m_strategy; }; public: @@ -387,46 +411,21 @@ public: std::vector const& boxes, detail::relate::topology_check < - MultiGeometry, - typename Strategy::equals_point_point_strategy_type + MultiGeometry, Strategy > const& tc, Result & result, Strategy const& strategy) { item_visitor_type visitor(multi_geometry, tc, result, strategy); - typedef expand_box_point - < - typename Strategy::expand_point_strategy_type - > expand_box_point_type; - typedef overlaps_box_point - < - typename Strategy::disjoint_point_box_strategy_type - > overlaps_box_point_type; - typedef expand_box_box_pair - < - // TEMP - envelope umbrella strategy also contains - // expand strategies - decltype(strategies::envelope::services::strategy_converter - < - typename Strategy::envelope_strategy_type - >::get(strategy.get_envelope_strategy()) - .expand(std::declval(), - std::declval())) - > expand_box_box_pair_type; - typedef overlaps_box_box_pair - < - typename Strategy::disjoint_box_box_strategy_type - > overlaps_box_box_pair_type; - geometry::partition < box1_type >::apply(multi_point, boxes, visitor, - expand_box_point_type(), - overlaps_box_point_type(), - expand_box_box_pair_type(), - overlaps_box_box_pair_type()); + expand_box_point(strategy), + overlaps_box_point(strategy), + expand_box_box_pair(strategy), + overlaps_box_box_pair(strategy)); } }; @@ -451,23 +450,18 @@ struct multi_point_multi_geometry_ii_ib_ie std::vector const& boxes, detail::relate::topology_check < - MultiGeometry, - typename Strategy::equals_point_point_strategy_type + MultiGeometry, Strategy > const& tc, Result & result, Strategy const& strategy) { - typedef strategy::index::services::from_strategy - < - Strategy - > index_strategy_from; typedef index::parameters < - index::rstar<4>, typename index_strategy_from::type + index::rstar<4>, Strategy > index_parameters_type; index::rtree rtree(boxes.begin(), boxes.end(), - index_parameters_type(index::rstar<4>(), index_strategy_from::get(strategy))); + index_parameters_type(index::rstar<4>(), strategy)); typedef typename boost::range_const_iterator::type iterator; for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) @@ -537,22 +531,17 @@ struct multi_point_multi_geometry typedef model::box box2_type; typedef std::pair box_pair_type; - typedef typename Strategy::equals_point_point_strategy_type eq_pp_strategy_type; - - typename Strategy::envelope_strategy_type const - envelope_strategy = strategy.get_envelope_strategy(); - std::size_t count2 = boost::size(multi_geometry); std::vector boxes(count2); for (std::size_t i = 0 ; i < count2 ; ++i) { - geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy); + geometry::envelope(range::at(multi_geometry, i), boxes[i].first, strategy); geometry::detail::expand_by_epsilon(boxes[i].first); boxes[i].second = i; } - typedef detail::relate::topology_check tc_t; - tc_t tc(multi_geometry); + typedef detail::relate::topology_check tc_t; + tc_t tc(multi_geometry, strategy); if ( relate::may_update(result) || relate::may_update(result) @@ -590,10 +579,7 @@ struct multi_point_multi_geometry if ( relate::may_update(result) && tc.has_boundary() ) { - if (multi_point_geometry_eb - < - MultiGeometry, eq_pp_strategy_type - >::apply(multi_point, tc)) + if (multi_point_geometry_eb::apply(multi_point, tc)) { relate::set(result); } diff --git a/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp index 7b1726abe..501c5f3dd 100644 --- a/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -60,11 +60,8 @@ struct point_geometry if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; - typedef detail::relate::topology_check - < - Geometry, - typename Strategy::equals_point_point_strategy_type - > tc_t; + typedef detail::relate::topology_check tc_t; + if ( relate::may_update(result) || relate::may_update(result) ) { @@ -79,7 +76,7 @@ struct point_geometry else { // check if there is a boundary in Geometry - tc_t tc(geometry); + tc_t tc(geometry, strategy); if ( tc.has_interior() ) relate::set(result); if ( tc.has_boundary() ) diff --git a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp index ab42504ec..459c81614 100644 --- a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp +++ b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2018, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -28,15 +28,18 @@ namespace detail { namespace relate { // TODO: change the name for e.g. something with the word "exterior" -template ::type> +template +< + typename Geometry, + typename Strategy, + typename Tag = typename geometry::tag::type +> struct topology_check : not_implemented {}; -//template -//struct topology_check +//template +//struct topology_check //{ // static const char interior = '0'; // static const char boundary = 'F'; @@ -49,14 +52,15 @@ struct topology_check // topology_check(Point const&, IgnoreBoundaryPoint const&) {} //}; -template -struct topology_check +template +struct topology_check { static const char interior = '1'; static const char boundary = '0'; - topology_check(Linestring const& ls) + topology_check(Linestring const& ls, Strategy const& strategy) : m_ls(ls) + , m_strategy(strategy) , m_is_initialized(false) {} @@ -87,8 +91,8 @@ struct topology_check init(); if (m_has_boundary) { - if (visitor.apply(range::front(m_ls))) - visitor.apply(range::back(m_ls)); + if (visitor.apply(range::front(m_ls), m_strategy)) + visitor.apply(range::back(m_ls), m_strategy); } } @@ -104,26 +108,29 @@ private: m_has_boundary = count > 1 && ! detail::equals::equals_point_point(range::front(m_ls), range::back(m_ls), - EqPPStrategy()); + m_strategy); m_is_initialized = true; } Linestring const& m_ls; + Strategy const& m_strategy; + mutable bool m_is_initialized; mutable bool m_has_interior; mutable bool m_has_boundary; }; -template -struct topology_check +template +struct topology_check { static const char interior = '1'; static const char boundary = '0'; - topology_check(MultiLinestring const& mls) + topology_check(MultiLinestring const& mls, Strategy const& strategy) : m_mls(mls) + , m_strategy(strategy) , m_is_initialized(false) {} @@ -163,7 +170,7 @@ struct topology_check } private: - typedef geometry::less less_type; + typedef geometry::less less_type; void init() const { @@ -198,7 +205,7 @@ private: point_reference back_pt = range::back(ls); // don't store boundaries of linear rings, this doesn't change anything - if (! equals::equals_point_point(front_pt, back_pt, EqPPStrategy())) + if (! equals::equals_point_point(front_pt, back_pt, m_strategy)) { // do not add points containing NaN coordinates // because they cannot be reasonably compared, e.g. with MSVC @@ -236,7 +243,7 @@ private: } template - static inline bool find_odd_count(It first, It last) + inline bool find_odd_count(It first, It last) const { interrupting_visitor visitor; for_each_boundary_point(first, last, visitor); @@ -248,7 +255,7 @@ private: bool found; interrupting_visitor() : found(false) {} template - bool apply(Point const&) + bool apply(Point const&, Strategy const&) { found = true; return false; @@ -256,7 +263,7 @@ private: }; template - static void for_each_boundary_point(It first, It last, Visitor& visitor) + void for_each_boundary_point(It first, It last, Visitor& visitor) const { if ( first == last ) return; @@ -267,12 +274,12 @@ private: for ( ; first != last ; ++first, ++prev ) { // the end of the equal points subrange - if ( ! equals::equals_point_point(*first, *prev, EqPPStrategy()) ) + if ( ! equals::equals_point_point(*first, *prev, m_strategy) ) { // odd count -> boundary if ( count % 2 != 0 ) { - if (! visitor.apply(*prev)) + if (! visitor.apply(*prev, m_strategy)) { return; } @@ -289,12 +296,14 @@ private: // odd count -> boundary if ( count % 2 != 0 ) { - visitor.apply(*prev); + visitor.apply(*prev, m_strategy); } } private: MultiLinestring const& m_mls; + Strategy const& m_strategy; + mutable bool m_is_initialized; mutable bool m_has_interior; @@ -313,25 +322,25 @@ struct topology_check_areal static bool has_boundary() { return true; } }; -template -struct topology_check +template +struct topology_check : topology_check_areal { - topology_check(Ring const&) {} + topology_check(Ring const&, Strategy const&) {} }; -template -struct topology_check +template +struct topology_check : topology_check_areal { - topology_check(Polygon const&) {} + topology_check(Polygon const&, Strategy const&) {} }; -template -struct topology_check +template +struct topology_check : topology_check_areal { - topology_check(MultiPolygon const&) {} + topology_check(MultiPolygon const&, Strategy const&) {} template static bool check_boundary_point(Point const& ) { return true; } diff --git a/include/boost/geometry/algorithms/detail/relate/turns.hpp b/include/boost/geometry/algorithms/detail/relate/turns.hpp index 7a5012896..7d8288730 100644 --- a/include/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/include/boost/geometry/algorithms/detail/relate/turns.hpp @@ -84,43 +84,28 @@ struct get_turns > type; }; - template - static inline void apply(Turns & turns, - Geometry1 const& geometry1, - Geometry2 const& geometry2) - { - detail::get_turns::no_interrupt_policy interrupt_policy; - - typename strategy::intersection::services::default_strategy - < - typename cs_tag::type - >::type intersection_strategy; - - apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy); - } - - template + template static inline void apply(Turns & turns, Geometry1 const& geometry1, Geometry2 const& geometry2, InterruptPolicy & interrupt_policy, - IntersectionStrategy const& intersection_strategy) + Strategy const& strategy) { - typedef typename robust_policy_type::type robust_policy_t; + typedef typename robust_policy_type::type robust_policy_t; robust_policy_t robust_policy = geometry::get_rescale_policy( - geometry1, geometry2, intersection_strategy); + geometry1, geometry2, strategy); - apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy, robust_policy); + apply(turns, geometry1, geometry2, interrupt_policy, strategy, robust_policy); } - template + template static inline void apply(Turns & turns, Geometry1 const& geometry1, Geometry2 const& geometry2, InterruptPolicy & interrupt_policy, - IntersectionStrategy const& intersection_strategy, + Strategy const& strategy, RobustPolicy const& robust_policy) { static const bool reverse1 = detail::overlay::do_reverse @@ -143,7 +128,7 @@ struct get_turns reverse2, GetTurnPolicy >::apply(0, geometry1, 1, geometry2, - intersection_strategy, robust_policy, + strategy, robust_policy, turns, interrupt_policy); } }; diff --git a/include/boost/geometry/algorithms/detail/relation/interface.hpp b/include/boost/geometry/algorithms/detail/relation/interface.hpp index 6e555116d..e9d940c3e 100644 --- a/include/boost/geometry/algorithms/detail/relation/interface.hpp +++ b/include/boost/geometry/algorithms/detail/relation/interface.hpp @@ -57,7 +57,10 @@ struct relation Matrix >::type handler; - resolve_strategy::relate::apply(geometry1, geometry2, handler, strategy); + resolve_strategy::relate + < + Strategy + >::apply(geometry1, geometry2, handler, strategy); return handler.result(); } diff --git a/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp b/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp index 5727ee817..2caaea096 100644 --- a/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp +++ b/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2018-2020. +// Modifications copyright (c) 2018-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -26,28 +26,39 @@ namespace boost { namespace geometry namespace detail { namespace section { -template +template struct get_section_box { + get_section_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline void apply(Box& total, Section const& section) + inline void apply(Box& total, Section const& section) const { assert_coordinate_type_equal(total, section.bounding_box); - geometry::expand(total, section.bounding_box, - ExpandBoxStrategy()); + geometry::expand(total, section.bounding_box, m_strategy); } + + Strategy const& m_strategy; }; -template +template struct overlaps_section_box { + overlaps_section_box(Strategy const& strategy) + : m_strategy(strategy) + {} + template - static inline bool apply(Box const& box, Section const& section) + inline bool apply(Box const& box, Section const& section) const { assert_coordinate_type_equal(box, section.bounding_box); return ! detail::disjoint::disjoint_box_box(box, section.bounding_box, - DisjointBoxBoxStrategy()); + m_strategy); } + + Strategy const& m_strategy; }; diff --git a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp index 6478eedb1..b670030c4 100644 --- a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -336,9 +337,9 @@ struct assign_loop template struct box_first_in_section { - template + template static inline void apply(Box & box, Point const& prev, Point const& curr, - EnvelopeStrategy const& strategy) + Strategy const& strategy) { geometry::model::referring_segment seg(prev, curr); geometry::envelope(seg, box, strategy); @@ -348,12 +349,12 @@ struct box_first_in_section template <> struct box_first_in_section { - template + template static inline void apply(Box & box, Point const& prev, Point const& curr, - ExpandStrategy const& ) + Strategy const& strategy) { - geometry::envelope(prev, box); - geometry::expand(box, curr); + geometry::envelope(prev, box, strategy); + geometry::expand(box, curr, strategy); } }; @@ -374,9 +375,9 @@ struct box_next_in_section { template static inline void apply(Box & box, Point const& , Point const& curr, - Strategy const& ) + Strategy const& strategy) { - geometry::expand(box, curr); + geometry::expand(box, curr, strategy); } }; @@ -391,50 +392,17 @@ struct sectionalize_part static const std::size_t dimension_count = util::sequence_size::value; - template - < - typename Iterator, - typename RobustPolicy, - typename Sections - > - static inline void apply(Sections& sections, - Iterator begin, Iterator end, - RobustPolicy const& robust_policy, - ring_identifier ring_id, - std::size_t max_count) - { - typedef typename strategy::envelope::services::default_strategy - < - segment_tag, - typename cs_tag::type - >::type envelope_strategy_type; - - typedef typename strategy::expand::services::default_strategy - < - segment_tag, - typename cs_tag::type - >::type expand_strategy_type; - - apply(sections, begin, end, - robust_policy, - envelope_strategy_type(), - expand_strategy_type(), - ring_id, max_count); - } - template < typename Iterator, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy, - typename ExpandStrategy + typename Strategy > static inline void apply(Sections& sections, Iterator begin, Iterator end, RobustPolicy const& robust_policy, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, ring_identifier ring_id, std::size_t max_count) { @@ -448,10 +416,10 @@ struct sectionalize_part ); typedef typename geometry::robust_point_type - < - Point, - RobustPolicy - >::type robust_point_type; + < + Point, + RobustPolicy + >::type robust_point_type; std::size_t const count = std::distance(begin, end); if (count == 0) @@ -552,14 +520,14 @@ struct sectionalize_part // In cartesian this is envelope of previous point expanded with current point // in non-cartesian this is envelope of a segment box_first_in_section::type> - ::apply(section.bounding_box, previous_robust_point, current_robust_point, envelope_strategy); + ::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy); } else { // In cartesian this is expand with current point // in non-cartesian this is expand with a segment box_next_in_section::type> - ::apply(section.bounding_box, previous_robust_point, current_robust_point, expand_strategy); + ::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy); } section.end_index = index + 1; @@ -605,23 +573,21 @@ struct sectionalize_range typename Range, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy, - typename ExpandStrategy + typename Strategy > static inline void apply(Range const& range, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, ring_identifier ring_id, std::size_t max_count) { typedef typename closeable_view::type cview_type; typedef typename reversible_view - < - cview_type const, - Reverse ? iterate_reverse : iterate_forward - >::type view_type; + < + cview_type const, + Reverse ? iterate_reverse : iterate_forward + >::type view_type; cview_type cview(range); view_type view(cview); @@ -641,7 +607,7 @@ struct sectionalize_range sectionalize_part::apply(sections, boost::begin(view), boost::end(view), - robust_policy, envelope_strategy, expand_strategy, + robust_policy, strategy, ring_id, max_count); } }; @@ -658,27 +624,24 @@ struct sectionalize_polygon typename Polygon, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy, - typename ExpandStrategy + typename Strategy > static inline void apply(Polygon const& poly, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, ring_identifier ring_id, std::size_t max_count) { typedef typename point_type::type point_type; typedef sectionalize_range - < - closure::value, Reverse, - point_type, DimensionVector - > per_range; + < + closure::value, Reverse, point_type, DimensionVector + > per_range; ring_id.ring_index = -1; per_range::apply(exterior_ring(poly), robust_policy, sections, - envelope_strategy, expand_strategy, ring_id, max_count); + strategy, ring_id, max_count); ring_id.ring_index++; typename interior_return_type::type @@ -687,7 +650,7 @@ struct sectionalize_polygon it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index) { per_range::apply(*it, robust_policy, sections, - envelope_strategy, expand_strategy, ring_id, max_count); + strategy, ring_id, max_count); } } }; @@ -700,14 +663,12 @@ struct sectionalize_box typename Box, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy, - typename ExpandStrategy + typename Strategy > static inline void apply(Box const& box, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, ring_identifier const& ring_id, std::size_t max_count) { typedef typename point_type::type point_type; @@ -735,13 +696,10 @@ struct sectionalize_box // NOTE: Use cartesian envelope strategy in all coordinate systems // because edges of a box are not geodesic segments sectionalize_range - < - closed, false, - point_type, - DimensionVector - >::apply(points, robust_policy, sections, - envelope_strategy, expand_strategy, - ring_id, max_count); + < + closed, false, point_type, DimensionVector + >::apply(points, robust_policy, sections, + strategy, ring_id, max_count); } }; @@ -753,14 +711,12 @@ struct sectionalize_multi typename MultiGeometry, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy, - typename ExpandStrategy + typename Strategy > static inline void apply(MultiGeometry const& multi, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, ring_identifier ring_id, std::size_t max_count) { @@ -771,7 +727,7 @@ struct sectionalize_multi ++it, ++ring_id.multi_index) { Policy::apply(*it, robust_policy, sections, - envelope_strategy, expand_strategy, + strategy, ring_id, max_count); } } @@ -983,7 +939,7 @@ struct sectionalize inline void sectionalize(Geometry const& geometry, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& envelope_strategy, - ExpandStrategy const& expand_strategy, + Strategy const& strategy, int source_index = 0, std::size_t max_count = 10) { - BOOST_STATIC_ASSERT((! std::is_fundamental::value)); - concepts::check(); typedef typename boost::range_value::type section_type; @@ -1044,10 +996,10 @@ inline void sectionalize(Geometry const& geometry, Reverse, DimensionVector >::apply(geometry, robust_policy, sections, - envelope_strategy, expand_strategy, + strategy, ring_id, max_count); - detail::sectionalize::enlarge_sections(sections, envelope_strategy); + detail::sectionalize::enlarge_sections(sections, strategy); } @@ -1065,29 +1017,17 @@ inline void sectionalize(Geometry const& geometry, int source_index = 0, std::size_t max_count = 10) { - typedef typename strategy::envelope::services::default_strategy + typedef typename strategies::envelope::services::default_strategy < - typename tag::type, - typename cs_tag::type - >::type envelope_strategy_type; - - typedef typename strategy::expand::services::default_strategy - < - std::conditional_t - < - std::is_same::type, box_tag>::value, - box_tag, - segment_tag - >, - typename cs_tag::type - >::type expand_strategy_type; + Geometry, + model::box::type> + >::type strategy_type; boost::geometry::sectionalize < Reverse, DimensionVector >(geometry, robust_policy, sections, - envelope_strategy_type(), - expand_strategy_type(), + strategy_type(), source_index, max_count); } diff --git a/include/boost/geometry/algorithms/detail/touches/implementation.hpp b/include/boost/geometry/algorithms/detail/touches/implementation.hpp index 8755de66d..fd492ab14 100644 --- a/include/boost/geometry/algorithms/detail/touches/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/touches/implementation.hpp @@ -211,29 +211,24 @@ inline bool point_on_border_within(Geometry1 const& geometry1, && geometry::within(pt, geometry2, strategy); } -template +template inline bool rings_containing(FirstGeometry const& geometry1, SecondGeometry const& geometry2, - IntersectionStrategy const& strategy) + Strategy const& strategy) { - // TODO: This will be removed when IntersectionStrategy is replaced with - // UmbrellaStrategy - auto const point_in_ring_strategy - = strategy.template get_point_in_geometry_strategy(); - return geometry::detail::any_range_of(geometry2, [&](auto const& range) { - return point_on_border_within(range, geometry1, point_in_ring_strategy); + return point_on_border_within(range, geometry1, strategy); }); } template struct areal_areal { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - IntersectionStrategy const& strategy) + Strategy const& strategy) { typedef typename geometry::point_type::type point_type; typedef detail::overlay::turn_info turn_info; @@ -410,7 +405,7 @@ struct self_touches { concepts::check(); - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry, Geometry >::type strategy_type; @@ -418,18 +413,19 @@ struct self_touches typedef detail::overlay::turn_info turn_info; typedef detail::overlay::get_turn_info - < - detail::overlay::assign_null_policy - > policy_type; + < + detail::overlay::assign_null_policy + > policy_type; std::deque turns; detail::touches::areal_interrupt_policy policy; strategy_type strategy; // TODO: skip_adjacent should be set to false detail::self_get_turn_points::get_turns - < - false, policy_type - >::apply(geometry, strategy, detail::no_rescale_policy(), turns, policy, 0, true); + < + false, policy_type + >::apply(geometry, strategy, detail::no_rescale_policy(), + turns, policy, 0, true); return policy.result(); } diff --git a/include/boost/geometry/algorithms/detail/touches/interface.hpp b/include/boost/geometry/algorithms/detail/touches/interface.hpp index 9f41b3608..4000d79c6 100644 --- a/include/boost/geometry/algorithms/detail/touches/interface.hpp +++ b/include/boost/geometry/algorithms/detail/touches/interface.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2015, 2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -35,7 +35,8 @@ #include #include -#include +#include +#include namespace boost { namespace geometry @@ -84,9 +85,14 @@ struct touches namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct touches { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) @@ -96,13 +102,36 @@ struct touches Geometry1, Geometry2 >::apply(geometry1, geometry2, strategy); } +}; +template +struct touches +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + //using strategies::touches::services::strategy_converter; + using strategies::relate::services::strategy_converter; + + return dispatch::touches + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct touches +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 @@ -129,7 +158,10 @@ struct touches concepts::check(); concepts::check(); - return resolve_strategy::touches::apply(geometry1, geometry2, strategy); + return resolve_strategy::touches + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/within/implementation.hpp b/include/boost/geometry/algorithms/detail/within/implementation.hpp index 9a88e41a5..a402c015a 100644 --- a/include/boost/geometry/algorithms/detail/within/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/within/implementation.hpp @@ -88,8 +88,7 @@ struct within template static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) { - boost::ignore_unused(strategy); - return strategy.apply(point, box); + return strategy.within(point, box).apply(point, box); } }; @@ -100,8 +99,7 @@ struct within static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) { assert_dimension_equal(); - boost::ignore_unused(strategy); - return strategy.apply(box1, box2); + return strategy.within(box1, box2).apply(box1, box2); } }; diff --git a/include/boost/geometry/algorithms/detail/within/interface.hpp b/include/boost/geometry/algorithms/detail/within/interface.hpp index 048cc01f7..362f1dc38 100644 --- a/include/boost/geometry/algorithms/detail/within/interface.hpp +++ b/include/boost/geometry/algorithms/detail/within/interface.hpp @@ -4,9 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013, 2014, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. - +// This file was modified by Oracle on 2013-2020. +// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -34,7 +33,8 @@ #include #include #include -#include +#include +#include namespace boost { namespace geometry @@ -63,30 +63,65 @@ struct within namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct within { - template + template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { concepts::within::check(); - return dispatch::within::apply(geometry1, geometry2, strategy); + return dispatch::within + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); } +}; +template +struct within +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + //using strategies::within::services::strategy_converter; + using strategies::relate::services::strategy_converter; + + return within + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, + strategy_converter::get(strategy)); + } +}; + +template <> +struct within +{ template static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, default_strategy) { - typedef typename strategy::within::services::default_strategy + //typedef typename strategies::within::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; - return apply(geometry1, geometry2, strategy_type()); + return within + < + strategy_type + >::apply(geometry1, geometry2, strategy_type()); } }; @@ -108,9 +143,10 @@ struct within concepts::check(); assert_dimension_equal(); - return resolve_strategy::within::apply(geometry1, - geometry2, - strategy); + return resolve_strategy::within + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/within/multi_point.hpp b/include/boost/geometry/algorithms/detail/within/multi_point.hpp index 319a782f3..349ef0302 100644 --- a/include/boost/geometry/algorithms/detail/within/multi_point.hpp +++ b/include/boost/geometry/algorithms/detail/within/multi_point.hpp @@ -1,7 +1,6 @@ // Boost.Geometry // Copyright (c) 2017-2020, Oracle and/or its affiliates. - // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -54,10 +53,12 @@ struct multi_point_point Point const& point, Strategy const& strategy) { + auto const s = strategy.relate(multi_point, point); + typedef typename boost::range_const_iterator::type iterator; for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) { - if (! strategy.apply(*it, point)) + if (! s.apply(*it, point)) { return false; } @@ -126,11 +127,9 @@ struct multi_point_single_geometry // Create envelope of geometry box2_type box; - geometry::envelope(linear_or_areal, box, strategy.get_envelope_strategy()); + geometry::envelope(linear_or_areal, box, strategy); geometry::detail::expand_by_epsilon(box); - typedef typename Strategy::disjoint_point_box_strategy_type point_in_box_type; - // Test each Point with envelope and then geometry if needed // If in the exterior, break bool result = false; @@ -138,8 +137,10 @@ struct multi_point_single_geometry typedef typename boost::range_const_iterator::type iterator; for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) { - int in_val = 0; + typedef decltype(strategy.covered_by(*it, box)) point_in_box_type; + int in_val = 0; + // exterior of box and of geometry if (! point_in_box_type::apply(*it, box) || (in_val = point_in_geometry(*it, linear_or_areal, strategy)) < 0) @@ -173,9 +174,6 @@ struct multi_point_multi_geometry typedef model::box box2_type; static const bool is_linear = util::is_linear::value; - typename Strategy::envelope_strategy_type const - envelope_strategy = strategy.get_envelope_strategy(); - // TODO: box pairs could be constructed on the fly, inside the rtree // Prepare range of envelopes and ids @@ -185,23 +183,16 @@ struct multi_point_multi_geometry box_pair_vector boxes(count2); for (std::size_t i = 0 ; i < count2 ; ++i) { - geometry::envelope(linear_or_areal, boxes[i].first, envelope_strategy); + geometry::envelope(linear_or_areal, boxes[i].first, strategy); geometry::detail::expand_by_epsilon(boxes[i].first); boxes[i].second = i; } // Create R-tree - typedef strategy::index::services::from_strategy - < - Strategy - > index_strategy_from; - typedef index::parameters - < - index::rstar<4>, typename index_strategy_from::type - > index_parameters_type; + typedef index::parameters, Strategy> index_parameters_type; index::rtree rtree(boxes.begin(), boxes.end(), - index_parameters_type(index::rstar<4>(), index_strategy_from::get(strategy))); + index_parameters_type(index::rstar<4>(), strategy)); // For each point find overlapping envelopes and test corresponding single geometries // If a point is in the exterior break diff --git a/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp index b8d69f6e2..3ef02ca90 100644 --- a/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp @@ -7,7 +7,6 @@ // This file was modified by Oracle on 2013-2020. // Modifications copyright (c) 2013-2020, Oracle and/or its affiliates. - // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -34,8 +33,6 @@ #include #include -#include -#include #include #include @@ -45,32 +42,13 @@ namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace within { -template -inline bool equals_point_point(Point1 const& p1, Point2 const& p2, Strategy const& strategy) -{ - return equals::equals_point_point(p1, p2, strategy.get_equals_point_point_strategy()); -} - -// TODO: is this needed? -inline int check_result_type(int result) -{ - return result; -} - -template -inline T check_result_type(T result) -{ - BOOST_GEOMETRY_ASSERT(false); - return result; -} template inline int point_in_range(Point const& point, Range const& range, Strategy const& strategy) { - boost::ignore_unused(strategy); + typename Strategy::state_type state; typedef typename boost::range_iterator::type iterator_type; - typename Strategy::state_type state; iterator_type it = boost::begin(range); iterator_type end = boost::end(range); @@ -82,18 +60,7 @@ int point_in_range(Point const& point, Range const& range, Strategy const& strat } } - return check_result_type(strategy.result(state)); -} - -template -inline int point_in_range(Point const& point, Range const& range) -{ - typedef typename strategy::point_in_geometry::services::default_strategy - < - Point, Geometry - >::type strategy_type; - - return point_in_range(point, range, strategy_type()); + return strategy.result(state); } }} // namespace detail::within @@ -117,8 +84,8 @@ struct point_in_geometry template static inline int apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy) { - boost::ignore_unused(strategy); - return strategy.apply(point1, point2) ? 1 : -1; + typedef decltype(strategy.relate(point1, point2)) strategy_type; + return strategy_type::apply(point1, point2) ? 1 : -1; } }; @@ -128,24 +95,23 @@ struct point_in_geometry template static inline int apply(Point const& point, Segment const& segment, Strategy const& strategy) { - boost::ignore_unused(strategy); - typedef typename geometry::point_type::type point_type; point_type p0, p1; // TODO: don't copy points detail::assign_point_from_index<0>(segment, p0); detail::assign_point_from_index<1>(segment, p1); - typename Strategy::state_type state; - strategy.apply(point, p0, p1, state); - int r = detail::within::check_result_type(strategy.result(state)); + auto const s = strategy.relate(point, segment); + typename decltype(s)::state_type state; + s.apply(point, p0, p1, state); + int r = s.result(state); if ( r != 0 ) return -1; // exterior // if the point is equal to the one of the terminal points - if ( detail::within::equals_point_point(point, p0, strategy) - || detail::within::equals_point_point(point, p1, strategy) ) + if ( detail::equals::equals_point_point(point, p0, strategy) + || detail::equals::equals_point_point(point, p1, strategy) ) return 0; // boundary else return 1; // interior @@ -162,24 +128,37 @@ struct point_in_geometry std::size_t count = boost::size(linestring); if ( count > 1 ) { - if ( detail::within::point_in_range(point, linestring, strategy) != 0 ) + if ( detail::within::point_in_range(point, linestring, + strategy.relate(point, linestring)) != 0 ) + { return -1; // exterior + } + + typedef typename boost::range_value::type point_type; + point_type const& front = range::front(linestring); + point_type const& back = range::back(linestring); // if the linestring doesn't have a boundary - if (detail::within::equals_point_point(range::front(linestring), range::back(linestring), strategy)) + if ( detail::equals::equals_point_point(front, back, strategy) ) + { return 1; // interior + } // else if the point is equal to the one of the terminal points - else if (detail::within::equals_point_point(point, range::front(linestring), strategy) - || detail::within::equals_point_point(point, range::back(linestring), strategy)) + else if ( detail::equals::equals_point_point(point, front, strategy) + || detail::equals::equals_point_point(point, back, strategy) ) + { return 0; // boundary + } else + { return 1; // interior + } } // TODO: for now degenerated linestrings are ignored // throw an exception here? /*else if ( count == 1 ) { - if ( detail::equals::equals_point_point(point, range::front(linestring)) ) + if ( detail::equals::equals_point_point(point, front, strategy) ) return 1; }*/ @@ -202,7 +181,8 @@ struct point_in_geometry } detail::normalized_view view(ring); - return detail::within::point_in_range(point, view, strategy); + return detail::within::point_in_range(point, view, + strategy.relate(point, ring)); } }; @@ -309,12 +289,12 @@ struct point_in_geometry point_type const& back = range::back(*it); // is closed_ring - no boundary - if ( detail::within::equals_point_point(front, back, strategy) ) + if ( detail::equals::equals_point_point(front, back, strategy) ) continue; // is point on boundary - if ( detail::within::equals_point_point(point, front, strategy) - || detail::within::equals_point_point(point, back, strategy) ) + if ( detail::equals::equals_point_point(point, front, strategy) + || detail::equals::equals_point_point(point, back, strategy) ) { ++boundaries; } @@ -371,41 +351,18 @@ inline int point_in_geometry(Point const& point, Geometry const& geometry, Strat return detail_dispatch::within::point_in_geometry::apply(point, geometry, strategy); } -template -inline int point_in_geometry(Point const& point, Geometry const& geometry) -{ - typedef typename strategy::point_in_geometry::services::default_strategy - < - Point, Geometry - >::type strategy_type; - - return point_in_geometry(point, geometry, strategy_type()); -} - template inline bool within_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy) { return point_in_geometry(point, geometry, strategy) > 0; } -template -inline bool within_point_geometry(Point const& point, Geometry const& geometry) -{ - return point_in_geometry(point, geometry) > 0; -} - template inline bool covered_by_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy) { return point_in_geometry(point, geometry, strategy) >= 0; } -template -inline bool covered_by_point_geometry(Point const& point, Geometry const& geometry) -{ - return point_in_geometry(point, geometry) >= 0; -} - }} // namespace detail::within #endif // DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/algorithms/difference.hpp b/include/boost/geometry/algorithms/difference.hpp index be96eea5c..addd51f63 100644 --- a/include/boost/geometry/algorithms/difference.hpp +++ b/include/boost/geometry/algorithms/difference.hpp @@ -2,7 +2,7 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2019, 2020. +// This file was modified by Oracle on 2017-2020. // Modifications copyright (c) 2017-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include @@ -253,7 +255,7 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, Geometry2 const& geometry2, OutputIterator out) { - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 @@ -270,15 +272,14 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct difference { - template - < - typename Geometry1, - typename Geometry2, - typename Collection, - typename Strategy - > + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, @@ -294,25 +295,46 @@ struct difference geometry::detail::output_geometry_back_inserter(output_collection), strategy); } +}; - template - < - typename Geometry1, - typename Geometry2, - typename Collection - > +template +struct difference +{ + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection & output_collection, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + + difference + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, output_collection, + strategy_converter::get(strategy)); + } +}; + +template <> +struct difference +{ + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, default_strategy) { - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; - apply(geometry1, geometry2, output_collection, strategy_type()); + difference + < + strategy_type + >::apply(geometry1, geometry2, output_collection, strategy_type()); } }; @@ -331,9 +353,10 @@ struct difference Collection& output_collection, Strategy const& strategy) { - resolve_strategy::difference::apply(geometry1, geometry2, - output_collection, - strategy); + resolve_strategy::difference + < + Strategy + >::apply(geometry1, geometry2, output_collection, strategy); } }; diff --git a/include/boost/geometry/algorithms/sym_difference.hpp b/include/boost/geometry/algorithms/sym_difference.hpp index 4d8550bcb..3d33431f9 100644 --- a/include/boost/geometry/algorithms/sym_difference.hpp +++ b/include/boost/geometry/algorithms/sym_difference.hpp @@ -2,7 +2,7 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2015, 2017, 2019, 2020. +// This file was modified by Oracle on 2015-2020. // Modifications copyright (c) 2015-2020 Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include @@ -497,9 +498,9 @@ template inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, Geometry2 const& geometry2, OutputIterator out) { - typedef typename strategy::intersection::services::default_strategy + typedef typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry1, Geometry2 >::type strategy_type; return sym_difference_insert(geometry1, geometry2, out, strategy_type()); @@ -511,15 +512,14 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct sym_difference { - template - < - typename Geometry1, - typename Geometry2, - typename Collection, - typename Strategy - > + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, @@ -535,13 +535,31 @@ struct sym_difference geometry::detail::output_geometry_back_inserter(output_collection), strategy); } +}; - template - < - typename Geometry1, - typename Geometry2, - typename Collection - > +template +struct sym_difference +{ + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection & output_collection, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + + sym_difference + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, output_collection, + strategy_converter::get(strategy)); + } +}; + +template <> +struct sym_difference +{ + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, @@ -552,7 +570,10 @@ struct sym_difference Geometry1, Geometry2 >::type strategy_type; - apply(geometry1, geometry2, output_collection, strategy_type()); + sym_difference + < + strategy_type + >::apply(geometry1, geometry2, output_collection, strategy_type()); } }; @@ -571,9 +592,10 @@ struct sym_difference Collection& output_collection, Strategy const& strategy) { - resolve_strategy::sym_difference::apply(geometry1, geometry2, - output_collection, - strategy); + resolve_strategy::sym_difference + < + Strategy + >::apply(geometry1, geometry2, output_collection, strategy); } }; diff --git a/include/boost/geometry/algorithms/union.hpp b/include/boost/geometry/algorithms/union.hpp index 535e8b147..7f507a329 100644 --- a/include/boost/geometry/algorithms/union.hpp +++ b/include/boost/geometry/algorithms/union.hpp @@ -18,13 +18,15 @@ #include +#include +#include #include #include #include -#include -#include #include #include +#include +#include #include #include @@ -349,9 +351,9 @@ inline OutputIterator union_insert(Geometry1 const& geometry1, concepts::check(); geometry::detail::output_geometry_concept_check::apply(); - typename strategy::intersection::services::default_strategy + typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry1, Geometry2 >::type strategy; typedef typename geometry::rescale_overlay_policy_type @@ -377,15 +379,14 @@ inline OutputIterator union_insert(Geometry1 const& geometry1, namespace resolve_strategy { +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> struct union_ { - template - < - typename Geometry1, - typename Geometry2, - typename Collection, - typename Strategy - > + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, @@ -414,25 +415,46 @@ struct union_ geometry::detail::output_geometry_back_inserter(output_collection), strategy); } +}; - template - < - typename Geometry1, - typename Geometry2, - typename Collection - > +template +struct union_ +{ + template + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Collection & output_collection, + Strategy const& strategy) + { + using strategies::relate::services::strategy_converter; + + union_ + < + decltype(strategy_converter::get(strategy)) + >::apply(geometry1, geometry2, output_collection, + strategy_converter::get(strategy)); + } +}; + +template <> +struct union_ +{ + template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection & output_collection, default_strategy) { - typedef typename strategy::relate::services::default_strategy + typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; - apply(geometry1, geometry2, output_collection, strategy_type()); + union_ + < + strategy_type + >::apply(geometry1, geometry2, output_collection, strategy_type()); } }; @@ -462,9 +484,10 @@ struct union_ >::type >::apply(); - resolve_strategy::union_::apply(geometry1, geometry2, - output_collection, - strategy); + resolve_strategy::union_ + < + Strategy + >::apply(geometry1, geometry2, output_collection, strategy); } }; diff --git a/include/boost/geometry/extensions/algorithms/dissolve.hpp b/include/boost/geometry/extensions/algorithms/dissolve.hpp index 7bed2425b..6948301b3 100644 --- a/include/boost/geometry/extensions/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/algorithms/dissolve.hpp @@ -418,6 +418,72 @@ struct dissolve #endif // DOXYGEN_NO_DISPATCH +namespace resolve_strategy +{ + +template +< + typename GeometryOut, + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> +struct dissolve +{ + template + < + typename Geometry, typename RescalePolicy, typename OutputIterator, + typename Strategy, typename Visitor + > + static inline OutputIterator apply(Geometry const& geometry, + RescalePolicy const& rescale_policy, + OutputIterator out, + Strategy const& strategy, + Visitor& visitor) + { + dispatch::dissolve + < + Geometry, + GeometryOut, + detail::overlay::do_reverse + < + geometry::point_order::value + >::value + >::apply(geometry, rescale_policy, out, strategy, visitor); + } +}; + +template +struct dissolve +{ + template + < + typename Geometry, typename RescalePolicy, typename OutputIterator, + typename Strategy, typename Visitor + > + static inline OutputIterator apply(Geometry const& geometry, + RescalePolicy const& rescale_policy, + OutputIterator out, + Strategy const& strategy, + Visitor& visitor) + { + using strategies::relate::services::strategy_converter; + + dispatch::dissolve + < + Geometry, + GeometryOut, + detail::overlay::do_reverse + < + geometry::point_order::value + >::value + >::apply(geometry, rescale_policy, out, + strategy_converter::get(strategy), + visitor); + } +}; + +} // namespace resolve_strategy + /*! \brief Removes self intersections from a geometry @@ -449,9 +515,10 @@ inline OutputIterator dissolve_inserter(Geometry const& geometry, concepts::check(); typedef typename geometry::rescale_policy_type - < - typename geometry::point_type::type - >::type rescale_policy_type; + < + typename geometry::point_type::type, + typename Strategy::cs_tag + >::type rescale_policy_type; rescale_policy_type robust_policy = geometry::get_rescale_policy( @@ -459,15 +526,10 @@ inline OutputIterator dissolve_inserter(Geometry const& geometry, detail::overlay::overlay_null_visitor visitor; - return dispatch::dissolve - < - Geometry, - GeometryOut, - detail::overlay::do_reverse + return resolve_strategy::dissolve < - geometry::point_order::value - >::value - >::apply(geometry, robust_policy, out, strategy, visitor); + GeometryOut, Strategy + >::apply(geometry, robust_policy, out, strategy, visitor); } /*! @@ -492,9 +554,9 @@ template inline OutputIterator dissolve_inserter(Geometry const& geometry, OutputIterator out) { - typedef typename strategy::intersection::services::default_strategy + typedef typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry, Geometry >::type strategy_type; return dissolve_inserter(geometry, out, strategy_type()); @@ -517,9 +579,10 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection, concepts::check(); typedef typename geometry::rescale_policy_type - < - typename geometry::point_type::type - >::type rescale_policy_type; + < + typename geometry::point_type::type, + typename Strategy::cs_tag + >::type rescale_policy_type; rescale_policy_type robust_policy = geometry::get_rescale_policy( @@ -527,17 +590,12 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection, detail::overlay::overlay_null_visitor visitor; - dispatch::dissolve - < - Geometry, - geometry_out, - detail::overlay::do_reverse + return resolve_strategy::dissolve < - geometry::point_order::value - >::value - >::apply(geometry, robust_policy, - std::back_inserter(output_collection), - strategy, visitor); + geometry_out, Strategy + >::apply(geometry, robust_policy, + std::back_inserter(output_collection), + strategy, visitor); } template @@ -547,9 +605,9 @@ template > inline void dissolve(Geometry const& geometry, Collection& output_collection) { - typedef typename strategy::intersection::services::default_strategy + typedef typename strategies::relate::services::default_strategy < - typename cs_tag::type + Geometry, Geometry >::type strategy_type; dissolve(geometry, output_collection, strategy_type()); diff --git a/include/boost/geometry/extensions/gis/io/shapefile/read.hpp b/include/boost/geometry/extensions/gis/io/shapefile/read.hpp index 40f8c8cb5..62c2dbf35 100644 --- a/include/boost/geometry/extensions/gis/io/shapefile/read.hpp +++ b/include/boost/geometry/extensions/gis/io/shapefile/read.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2019, Oracle and/or its affiliates. +// Copyright (c) 2019-2020, 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. @@ -32,9 +32,9 @@ #include // TEMP - only here for convenience, for now -#include -#include -#include +#include +#include +#include namespace boost { namespace geometry @@ -924,9 +924,9 @@ template inline void read_shapefile(IStream &is, RangeOfGeometries & range_of_geometries) { typedef typename boost::range_value::type geometry_type; - typedef typename strategy::io::services::default_strategy + typedef typename strategies::io::services::default_strategy < - typename cs_tag::type + geometry_type >::type strategy_type; geometry::concepts::check(); diff --git a/include/boost/geometry/extensions/nsphere/algorithms/covered_by.hpp b/include/boost/geometry/extensions/nsphere/algorithms/covered_by.hpp index 932924b32..c219ef8b3 100644 --- a/include/boost/geometry/extensions/nsphere/algorithms/covered_by.hpp +++ b/include/boost/geometry/extensions/nsphere/algorithms/covered_by.hpp @@ -5,6 +5,10 @@ // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 Oracle and/or its affiliates. +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -19,8 +23,7 @@ #include -#include -#include +#include namespace boost { namespace geometry @@ -37,8 +40,8 @@ struct covered_by static inline bool apply(NSphere const& nsphere, Box const& box, Strategy const& strategy) { assert_dimension_equal(); - boost::ignore_unused(strategy); - return strategy.apply(nsphere, box); + + return strategy.covered_by(nsphere, box).apply(nsphere, box); } }; @@ -49,8 +52,8 @@ struct covered_by static inline bool apply(Point const& point, NSphere const& nsphere, Strategy const& strategy) { assert_dimension_equal(); - boost::ignore_unused(strategy); - return strategy.apply(point, nsphere); + + return strategy.covered_by(point, nsphere).apply(point, nsphere); } }; diff --git a/include/boost/geometry/extensions/nsphere/algorithms/within.hpp b/include/boost/geometry/extensions/nsphere/algorithms/within.hpp index df6ddd358..207bc6289 100644 --- a/include/boost/geometry/extensions/nsphere/algorithms/within.hpp +++ b/include/boost/geometry/extensions/nsphere/algorithms/within.hpp @@ -5,6 +5,10 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2019 Adam Wulkiewicz, Lodz, Poland. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 Oracle and/or its affiliates. +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -29,6 +33,8 @@ #include #include +#include + namespace boost { namespace geometry { @@ -43,22 +49,24 @@ namespace detail { namespace within // on the boudary template -inline bool box_in_circle(B const& b, C const& c, S const& s) +inline bool box_in_circle(B const& b, C const& c, S const& strategy) { typedef typename point_type::type point_type; // Currently only implemented for 2d geometries assert_dimension(); assert_dimension(); - ::boost::ignore_unused(s); - - // Box: all four points must lie within circle + // Box: all four points must lie within circle + point_type const p0 = geometry::make(get(b), get(b)); + point_type const p1 = geometry::make(get(b), get(b)); + point_type const p2 = geometry::make(get(b), get(b)); + point_type const p3 = geometry::make(get(b), get(b)); + + auto const s = strategy.within(p0, c); + // Check points lower-left and upper-right, then lower-right and upper-left - return s.apply(geometry::make(get(b), get(b)), c) - && s.apply(geometry::make(get(b), get(b)), c) - && s.apply(geometry::make(get(b), get(b)), c) - && s.apply(geometry::make(get(b), get(b)), c); + return s.apply(p0, c) && s.apply(p1, c) && s.apply(p2, c) && s.apply(p3, c); } // Generic "range-in-circle", true if all points within circle @@ -70,7 +78,10 @@ inline bool range_in_circle(R const& range, C const& c, S const& s) for (typename boost::range_iterator::type it = boost::begin(range); it != boost::end(range); ++it) { - if (! s.apply(*it, c)) + auto const& p = *it; + + // TODO: This is not fully correct since some of the points can lie on the boundary + if (! s.within(p, c).apply(p, c)) { return false; } @@ -117,8 +128,7 @@ struct within template static inline bool apply(P const& p, Circle const& c, Strategy const& strategy) { - ::boost::ignore_unused(strategy); - return strategy.apply(p, c); + return strategy.within(p, c).apply(p, c); } }; @@ -181,8 +191,8 @@ struct within static inline bool apply(NSphere const& nsphere, Box const& box, Strategy const& strategy) { assert_dimension_equal(); - boost::ignore_unused(strategy); - return strategy.apply(nsphere, box); + + return strategy.within(nsphere, box).apply(nsphere, box); } }; diff --git a/include/boost/geometry/extensions/nsphere/strategies/relate/cartesian.hpp b/include/boost/geometry/extensions/nsphere/strategies/relate/cartesian.hpp new file mode 100644 index 000000000..37c55b07f --- /dev/null +++ b/include/boost/geometry/extensions/nsphere/strategies/relate/cartesian.hpp @@ -0,0 +1,127 @@ +// Boost.Geometry + +// Copyright (c) 2020, 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_EXTENSIONS_NSPHERE_STRATEGIES_RELATE_CARTESIAN_HPP +#define BOOST_GEOMETRY_EXTENSIONS_NSPHERE_STRATEGIES_RELATE_CARTESIAN_HPP + + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace relate +{ + +template +class cartesian_for_nsphere + : public strategies::relate::cartesian +{ +public: + + // covered_by + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && std::is_same::type>::value + > * = nullptr) + { + return strategy::within::point_in_nsphere + < + Geometry1, Geometry2, + strategy::within::point_nsphere_covered_by_comparable_distance + >(); + } + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + std::is_same::type>::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::nsphere_in_box + < + Geometry1, Geometry2, + strategy::within::nsphere_covered_by_range + >(); + } + + // within + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && std::is_same::type>::value + > * = nullptr) + { + return strategy::within::point_in_nsphere + < + Geometry1, Geometry2, + strategy::within::point_nsphere_within_comparable_distance + >(); + } + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + std::is_same::type>::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::nsphere_in_box + < + Geometry1, Geometry2, + strategy::within::nsphere_within_range + >(); + } +}; + + +namespace services +{ + +template +struct default_strategy, Geometry2, cartesian_tag, cartesian_tag> +{ + using type = strategies::relate::cartesian_for_nsphere<>; +}; + +template +struct default_strategy, cartesian_tag, cartesian_tag> +{ + using type = strategies::relate::cartesian_for_nsphere<>; +}; + +template +struct default_strategy, model::nsphere, cartesian_tag, cartesian_tag> +{ + using type = strategies::relate::cartesian_for_nsphere<>; +}; + + +} // namespace services + +}} // namespace strategies::relate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_EXTENSIONS_NSPHERE_STRATEGIES_RELATE_CARTESIAN_HPP diff --git a/include/boost/geometry/index/detail/algorithms/bounds.hpp b/include/boost/geometry/index/detail/algorithms/bounds.hpp index 2a0fa9ced..1828a2467 100644 --- a/include/boost/geometry/index/detail/algorithms/bounds.hpp +++ b/include/boost/geometry/index/detail/algorithms/bounds.hpp @@ -4,8 +4,8 @@ // // Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland. // -// This file was modified by Oracle on 2019. -// Modifications copyright (c) 2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2019-2020. +// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // // Use, modification and distribution is subject to the Boost Software License, @@ -80,9 +80,9 @@ struct expand } template - static inline void apply(Bounds & b, Geometry const& g, Strategy const& ) + static inline void apply(Bounds & b, Geometry const& g, Strategy const& s) { - geometry::expand(b, g, typename Strategy::expand_point_strategy_type()); + geometry::expand(b, g, s); } }; @@ -95,9 +95,9 @@ struct expand } template - static inline void apply(Bounds & b, Geometry const& g, Strategy const& ) + static inline void apply(Bounds & b, Geometry const& g, Strategy const& s) { - geometry::expand(b, g, typename Strategy::expand_box_strategy_type()); + geometry::expand(b, g, s); } }; @@ -112,8 +112,9 @@ struct expand template static inline void apply(Bounds & b, Geometry const& g, Strategy const& s) { - index::detail::bounded_view v(g, s); - geometry::expand(b, v, typename Strategy::expand_box_strategy_type()); + geometry::expand(b, geometry::return_envelope(g, s), s); + // requires additional strategy + //geometry::expand(b, g, s); } }; @@ -154,9 +155,9 @@ struct covered_by_bounds } template - static inline bool apply(Geometry const& g, Bounds & b, Strategy const&) + static inline bool apply(Geometry const& g, Bounds & b, Strategy const& s) { - return geometry::covered_by(g, b, typename Strategy::covered_by_point_box_strategy_type()); + return geometry::covered_by(g, b, s); } }; @@ -169,9 +170,9 @@ struct covered_by_bounds } template - static inline bool apply(Geometry const& g, Bounds & b, Strategy const&) + static inline bool apply(Geometry const& g, Bounds & b, Strategy const& s) { - return geometry::covered_by(g, b, typename Strategy::covered_by_box_box_strategy_type()); + return geometry::covered_by(g, b, s); } }; @@ -194,8 +195,7 @@ struct covered_by_bounds typedef geometry::model::box bounds_type; typedef index::detail::bounded_view view_type; - return geometry::covered_by(view_type(g, strategy), b, - typename Strategy::covered_by_box_box_strategy_type()); + return geometry::covered_by(view_type(g, strategy), b, strategy); } }; diff --git a/include/boost/geometry/index/detail/algorithms/intersection_content.hpp b/include/boost/geometry/index/detail/algorithms/intersection_content.hpp index 2fee7b13d..880540bc0 100644 --- a/include/boost/geometry/index/detail/algorithms/intersection_content.hpp +++ b/include/boost/geometry/index/detail/algorithms/intersection_content.hpp @@ -4,8 +4,8 @@ // // Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland. // -// This file was modified by Oracle on 2019. -// Modifications copyright (c) 2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2019-2020. +// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // // Use, modification and distribution is subject to the Boost Software License, @@ -24,10 +24,9 @@ namespace boost { namespace geometry { namespace index { namespace detail { // Util to distinguish between default and non-default index strategy template -inline bool disjoint_box_box(Box const& box1, Box const& box2, Strategy const&) +inline bool disjoint_box_box(Box const& box1, Box const& box2, Strategy const& s) { - return geometry::detail::disjoint::disjoint_box_box(box1, box2, - typename Strategy::disjoint_box_box_strategy_type()); + return geometry::detail::disjoint::disjoint_box_box(box1, box2, s); } template diff --git a/include/boost/geometry/index/detail/bounded_view.hpp b/include/boost/geometry/index/detail/bounded_view.hpp index 7df1fc6ca..6b4d91a64 100644 --- a/include/boost/geometry/index/detail/bounded_view.hpp +++ b/include/boost/geometry/index/detail/bounded_view.hpp @@ -19,7 +19,8 @@ #include #include -#include +#include +#include namespace boost { namespace geometry { @@ -94,24 +95,11 @@ private: template struct bounded_view_base { - template - inline void envelope(Segment const& segment, S const& strategy) - { - geometry::envelope(segment, m_box, - strategy.get_envelope_segment_strategy()); - } - - inline void envelope(Segment const& segment, default_strategy const& ) - { - geometry::envelope(segment, m_box); - } - -public: typedef typename geometry::coordinate_type::type coordinate_type; bounded_view_base(Segment const& segment, Strategy const& strategy) { - envelope(segment, strategy); + geometry::envelope(segment, m_box, strategy); } template @@ -215,10 +203,10 @@ struct bounded_view::type + typename strategies::index::services::default_strategy::type > { - typedef typename strategy::index::services::default_strategy + typedef typename strategies::index::services::default_strategy < Geometry >::type strategy_type; diff --git a/include/boost/geometry/index/detail/distance_predicates.hpp b/include/boost/geometry/index/detail/distance_predicates.hpp index aba951847..9ad44d18d 100644 --- a/include/boost/geometry/index/detail/distance_predicates.hpp +++ b/include/boost/geometry/index/detail/distance_predicates.hpp @@ -100,135 +100,41 @@ struct relation< to_furthest > // ------------------------------------------------------------------ // -template -< - typename G1, typename G2, typename Strategy, - typename Tag1 = typename geometry::tag::type, - typename Tag2 = typename geometry::tag::type -> -struct comparable_distance_call_base -{ - typedef typename geometry::default_comparable_distance_result - < - G1, G2 - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const&) - { - return geometry::comparable_distance(g1, g2); - } -}; - -template -< - typename G1, typename G2, typename Strategy -> -struct comparable_distance_call_base -{ - typedef typename geometry::comparable_distance_result - < - G1, G2, - typename Strategy::comparable_distance_point_point_strategy_type - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) - { - return geometry::comparable_distance(g1, g2, - s.get_comparable_distance_point_point_strategy()); - } -}; - -template -< - typename G1, typename G2, typename Strategy -> -struct comparable_distance_call_base -{ - typedef typename geometry::comparable_distance_result - < - G1, G2, - typename Strategy::comparable_distance_point_box_strategy_type - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) - { - return geometry::comparable_distance(g1, g2, - s.get_comparable_distance_point_box_strategy()); - } -}; - -template -< - typename G1, typename G2, typename Strategy -> -struct comparable_distance_call_base -{ - typedef typename geometry::comparable_distance_result - < - G1, G2, - typename Strategy::comparable_distance_point_segment_strategy_type - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) - { - return geometry::comparable_distance(g1, g2, - s.get_comparable_distance_point_segment_strategy()); - } -}; - -template -< - typename G1, typename G2, typename Strategy -> -struct comparable_distance_call_base -{ - typedef typename geometry::comparable_distance_result - < - G1, G2, - typename Strategy::comparable_distance_segment_box_strategy_type - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) - { - return geometry::comparable_distance(g1, g2, - s.get_comparable_distance_segment_box_strategy()); - } -}; - -template -< - typename G1, typename G2, typename Strategy -> -struct comparable_distance_call_base -{ - typedef typename geometry::comparable_distance_result - < - G1, G2, - typename Strategy::comparable_distance_point_segment_strategy_type - >::type result_type; - - static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) - { - return geometry::comparable_distance(g1, g2, - s.get_comparable_distance_point_segment_strategy()); - } -}; - template < typename G1, typename G2, typename Strategy > struct comparable_distance_call - : comparable_distance_call_base -{}; +{ + typedef typename geometry::comparable_distance_result + < + G1, G2, + decltype(std::declval().comparable_distance(std::declval(), + std::declval())) + >::type result_type; + + static inline result_type apply(G1 const& g1, G2 const& g2, Strategy const& s) + { + return geometry::comparable_distance(g1, g2, s.comparable_distance(g1, g2)); + } +}; template < typename G1, typename G2 > struct comparable_distance_call - : comparable_distance_call_base -{}; +{ + typedef typename geometry::default_comparable_distance_result + < + G1, G2 + >::type result_type; + + static inline result_type apply(G1 const& g1, G2 const& g2, default_strategy const&) + { + return geometry::comparable_distance(g1, g2); + } +}; // ------------------------------------------------------------------ // // calculate_distance diff --git a/include/boost/geometry/index/detail/predicates.hpp b/include/boost/geometry/index/detail/predicates.hpp index 1318c1cf0..08bc18e15 100644 --- a/include/boost/geometry/index/detail/predicates.hpp +++ b/include/boost/geometry/index/detail/predicates.hpp @@ -225,9 +225,9 @@ struct spatial_predicate_intersects } template - static inline bool apply(G1 const& g1, G2 const& g2, S const& ) + static inline bool apply(G1 const& g1, G2 const& g2, S const& s) { - return geometry::intersects(g1, g2, typename S::covered_by_point_box_strategy_type()); + return geometry::intersects(g1, g2, s); } }; diff --git a/include/boost/geometry/index/detail/rtree/rstar/insert.hpp b/include/boost/geometry/index/detail/rtree/rstar/insert.hpp index 3f35bcad6..87ef987b8 100644 --- a/include/boost/geometry/index/detail/rtree/rstar/insert.hpp +++ b/include/boost/geometry/index/detail/rtree/rstar/insert.hpp @@ -29,32 +29,32 @@ namespace rstar { // Utility to distinguish between default and non-default index strategy template -struct comparable_distance_point_point +struct comparable_distance { - typedef typename Strategy::comparable_distance_point_point_strategy_type strategy_type; typedef typename geometry::comparable_distance_result < - Point1, Point2, strategy_type + Point1, Point2, + decltype(std::declval().comparable_distance( + std::declval(), std::declval())) >::type result_type; - static inline strategy_type get_strategy(Strategy const& strategy) + static inline result_type call(Point1 const& p1, Point2 const& p2, Strategy const& s) { - return strategy.get_comparable_distance_point_point_strategy(); + return geometry::comparable_distance(p1, p2, s.comparable_distance(p1, p2)); } }; template -struct comparable_distance_point_point +struct comparable_distance { - typedef default_strategy strategy_type; typedef typename geometry::default_comparable_distance_result < Point1, Point2 >::type result_type; - static inline strategy_type get_strategy(default_strategy const& ) + static inline result_type call(Point1 const& p1, Point2 const& p2, default_strategy const& ) { - return strategy_type(); + return geometry::comparable_distance(p1, p2); } }; @@ -88,7 +88,7 @@ public: typedef typename geometry::point_type::type point_type; typedef typename index::detail::strategy_type::type strategy_type; // TODO: awulkiew - change second point_type to the point type of the Indexable? - typedef rstar::comparable_distance_point_point + typedef rstar::comparable_distance < point_type, point_type, strategy_type > comparable_distance_pp; @@ -117,8 +117,7 @@ public: // If constructor is used instead of resize() MS implementation leaks here sorted_elements.reserve(elements_count); // MAY THROW, STRONG (V, E: alloc, copy) - typename comparable_distance_pp::strategy_type - cdist_strategy = comparable_distance_pp::get_strategy(index::detail::get_strategy(parameters)); + auto const& strategy = index::detail::get_strategy(parameters); for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it ) @@ -126,7 +125,7 @@ public: point_type element_center; geometry::centroid( rtree::element_indexable(*it, translator), element_center); sorted_elements.push_back(std::make_pair( - geometry::comparable_distance(node_center, element_center, cdist_strategy), + comparable_distance_pp::call(node_center, element_center, strategy), *it)); // MAY THROW (V, E: copy) } diff --git a/include/boost/geometry/index/equal_to.hpp b/include/boost/geometry/index/equal_to.hpp index f457f5184..3ce2e1e4c 100644 --- a/include/boost/geometry/index/equal_to.hpp +++ b/include/boost/geometry/index/equal_to.hpp @@ -2,8 +2,8 @@ // // Copyright (c) 2011-2016 Adam Wulkiewicz, Lodz, Poland. // -// This file was modified by Oracle on 2019. -// Modifications copyright (c) 2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2019-2020. +// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // // Use, modification and distribution is subject to the Boost Software License, @@ -39,9 +39,9 @@ struct equals } template - inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const&) + inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const& s) { - return geometry::equals(g1, g2, typename Strategy::within_point_point_strategy_type()); + return geometry::equals(g1, g2, s); } }; @@ -54,11 +54,9 @@ struct equals } template - inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const&) + inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const& s) { - // NOTE: there is no strategy for equals(box, box) so pass dummy variable - // TODO: there should be a strategy even if it is the same for all CSes in case undefined_cs was used - return geometry::equals(g1, g2, 0); + return geometry::equals(g1, g2, s); } }; @@ -73,7 +71,7 @@ struct equals template inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const& s) { - return geometry::equals(g1, g2, s.get_relate_segment_segment_strategy()); + return geometry::equals(g1, g2, s); } }; diff --git a/include/boost/geometry/io/wkt/read.hpp b/include/boost/geometry/io/wkt/read.hpp index 7d73adf73..d75a44fd1 100644 --- a/include/boost/geometry/io/wkt/read.hpp +++ b/include/boost/geometry/io/wkt/read.hpp @@ -53,6 +53,10 @@ #include +#include +#include +#include + #include #include @@ -303,9 +307,9 @@ private: static inline bool disjoint(point_type const& p1, point_type const& p2) { // TODO: pass strategy - typedef typename strategy::disjoint::services::default_strategy + typedef typename strategies::io::services::default_strategy < - point_type, point_type + point_type >::type strategy_type; return detail::disjoint::disjoint_point_point(p1, p2, strategy_type()); diff --git a/include/boost/geometry/io/wkt/write.hpp b/include/boost/geometry/io/wkt/write.hpp index 6bd584b22..6b1ca59a0 100644 --- a/include/boost/geometry/io/wkt/write.hpp +++ b/include/boost/geometry/io/wkt/write.hpp @@ -48,6 +48,10 @@ #include +#include +#include +#include + #include #include @@ -184,9 +188,9 @@ private: static inline bool disjoint(point_type const& p1, point_type const& p2) { // TODO: pass strategy - typedef typename strategy::disjoint::services::default_strategy + typedef typename strategies::io::services::default_strategy < - point_type, point_type + point_type >::type strategy_type; return detail::disjoint::disjoint_point_point(p1, p2, strategy_type()); diff --git a/include/boost/geometry/policies/robustness/get_rescale_policy.hpp b/include/boost/geometry/policies/robustness/get_rescale_policy.hpp index 64ddb6924..66f949fe4 100644 --- a/include/boost/geometry/policies/robustness/get_rescale_policy.hpp +++ b/include/boost/geometry/policies/robustness/get_rescale_policy.hpp @@ -20,6 +20,7 @@ #include +#include #include #include @@ -96,13 +97,13 @@ inline void scale_box_to_integer_range(Box const& box, template < typename Point, typename RobustPoint, typename Geometry, - typename Factor, typename EnvelopeStrategy + typename Factor, typename Strategy > static inline void init_rescale_policy(Geometry const& geometry, Point& min_point, RobustPoint& min_robust_point, Factor& factor, - EnvelopeStrategy const& strategy) + Strategy const& strategy) { if (geometry::is_empty(geometry)) { @@ -123,15 +124,15 @@ static inline void init_rescale_policy(Geometry const& geometry, template < typename Point, typename RobustPoint, typename Geometry1, typename Geometry2, - typename Factor, typename EnvelopeStrategy1, typename EnvelopeStrategy2 + typename Factor, typename Strategy1, typename Strategy2 > static inline void init_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2, Point& min_point, RobustPoint& min_robust_point, Factor& factor, - EnvelopeStrategy1 const& strategy1, - EnvelopeStrategy2 const& strategy2) + Strategy1 const& strategy1, + Strategy2 const& strategy2) { // Get bounding boxes (when at least one of the geometries is not empty) bool const is_empty1 = geometry::is_empty(geometry1); @@ -161,13 +162,7 @@ static inline void init_rescale_policy(Geometry1 const& geometry1, < model::box >(geometry2, strategy2); - geometry::expand(env, env2, - // TEMP - envelope umbrella strategy also contains - // expand strategies - strategies::envelope::services::strategy_converter - < - EnvelopeStrategy1 - >::get(strategy1)); + geometry::expand(env, env2, strategy1); } scale_box_to_integer_range(env, min_point, min_robust_point, factor); @@ -205,9 +200,9 @@ struct rescale_policy_type template struct get_rescale_policy { - template + template static inline Policy apply(Geometry const& geometry, - EnvelopeStrategy const& strategy) + Strategy const& strategy) { typedef typename point_type::type point_type; typedef typename geometry::coordinate_type::type coordinate_type; @@ -228,10 +223,10 @@ struct get_rescale_policy return Policy(min_point, min_robust_point, factor); } - template + template static inline Policy apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - EnvelopeStrategy1 const& strategy1, - EnvelopeStrategy2 const& strategy2) + Strategy1 const& strategy1, + Strategy2 const& strategy2) { typedef typename point_type::type point_type; typedef typename geometry::coordinate_type::type coordinate_type; @@ -354,177 +349,63 @@ struct rescale_overlay_policy_type::type, - typename CSTag = typename Strategy::cs_tag -> -struct get_envelope_strategy -{ - typedef typename Strategy::envelope_strategy_type type; - - static inline type apply(Strategy const& strategy) - { - return strategy.get_envelope_strategy(); - } -}; - -template -struct get_envelope_strategy -{ - typedef typename Strategy::envelope_box_strategy_type type; - - static inline type apply(Strategy const& ) - { - return type(); - } -}; - -// NOTE: within::xxx_point_point shouldn't have a getter for envelope strategy -// so dispatch by CStag. In the future strategies should probably be redesigned. -template -struct get_envelope_strategy -{ - typedef strategy::envelope::cartesian_point type; - - static inline type apply(Strategy const& ) - { - return type(); - } -}; -template -struct get_envelope_strategy -{ - typedef strategy::envelope::spherical_point type; - - static inline type apply(Strategy const& ) - { - return type(); - } -}; - -template -struct get_envelope_strategy -{ - typedef strategy::envelope::cartesian_point type; - - static inline type apply(Strategy const& ) - { - return type(); - } -}; -template -struct get_envelope_strategy -{ - typedef strategy::envelope::spherical_point type; - - static inline type apply(Strategy const& ) - { - return type(); - } -}; - - -// utility for backward-compatibility either treating the argument as geometry -// or envelope strategy for get_rescale_policy -template -< - typename Geometry2OrStrategy, - typename Tag = typename geometry::tag::type -> -struct get_rescale_policy_geometry_or_strategy -{ - template - static inline Policy apply(Geometry const& geometry, Geometry2OrStrategy const& geometry2) - { - typename geometry::strategy::envelope::services::default_strategy - < - typename geometry::tag::type, - typename geometry::cs_tag::type - >::type strategy1; - typename geometry::strategy::envelope::services::default_strategy - < - typename geometry::tag::type, - typename geometry::cs_tag::type - >::type strategy2; - - return detail::get_rescale_policy::get_rescale_policy - < - Policy - >::apply(geometry, geometry2, strategy1, strategy2); - } -}; - -template -struct get_rescale_policy_geometry_or_strategy -{ - template - static inline Policy apply(Geometry const& geometry, Strategy const& strategy) - { - return detail::get_rescale_policy::get_rescale_policy - < - Policy - >::apply(geometry, - get_envelope_strategy - < - Geometry, Strategy - >::apply(strategy)); - } -}; - - -}} // namespace detail::get_rescale_policy -#endif // DOXYGEN_NO_DETAIL - - template inline Policy get_rescale_policy(Geometry const& geometry) { - typename geometry::strategy::envelope::services::default_strategy + typename geometry::strategies::envelope::services::default_strategy < - typename geometry::tag::type, - typename geometry::cs_tag::type + Geometry, + model::box::type> >::type strategy; return detail::get_rescale_policy::get_rescale_policy::apply(geometry, strategy); } -template -inline Policy get_rescale_policy(Geometry const& geometry, Geometry2OrStrategy const& geometry2_or_strategy) +template +< + typename Policy, typename Geometry, typename Strategy, + std::enable_if_t::type>::value, int> = 0 +> +inline Policy get_rescale_policy(Geometry const& geometry, Strategy const& strategy) { - // if the second argument is a geometry use default strategy - // otherwise assume it's envelope strategy for the first argument - return detail::get_rescale_policy::get_rescale_policy_geometry_or_strategy + return detail::get_rescale_policy::get_rescale_policy < - Geometry2OrStrategy - > ::template apply(geometry, geometry2_or_strategy); + Policy + >::apply(geometry, strategy); } -template +template +< + typename Policy, typename Geometry1, typename Geometry2, + std::enable_if_t::type>::value, int> = 0 +> +inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2) +{ + typename geometry::strategies::envelope::services::default_strategy + < + Geometry1, + model::box::type> + >::type strategy1; + typename geometry::strategies::envelope::services::default_strategy + < + Geometry2, + model::box::type> + >::type strategy2; + + return detail::get_rescale_policy::get_rescale_policy + < + Policy + >::apply(geometry1, geometry2, strategy1, strategy2); +} + +template inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2, - IntersectionStrategy const& strategy) + Strategy const& strategy) { return detail::get_rescale_policy::get_rescale_policy < Policy - >::apply(geometry1, geometry2, - detail::get_rescale_policy::get_envelope_strategy - < - Geometry1, IntersectionStrategy - >::apply(strategy), - detail::get_rescale_policy::get_envelope_strategy - < - Geometry2, IntersectionStrategy - >::apply(strategy)); + >::apply(geometry1, geometry2, strategy, strategy); } diff --git a/include/boost/geometry/policies/robustness/segment_ratio.hpp b/include/boost/geometry/policies/robustness/segment_ratio.hpp index c9e012e90..9f36047e2 100644 --- a/include/boost/geometry/policies/robustness/segment_ratio.hpp +++ b/include/boost/geometry/policies/robustness/segment_ratio.hpp @@ -118,19 +118,63 @@ public : , m_approximation(0) {} - inline segment_ratio(const Type& nominator, const Type& denominator) - : m_numerator(nominator) + inline segment_ratio(const Type& numerator, const Type& denominator) + : m_numerator(numerator) , m_denominator(denominator) { initialize(); } + segment_ratio(segment_ratio const&) = default; + segment_ratio& operator=(segment_ratio const&) = default; + segment_ratio(segment_ratio&&) = default; + segment_ratio& operator=(segment_ratio&&) = default; + + // These are needed because in intersection strategies ratios are assigned + // in fractions and if a user passes CalculationType then ratio Type in + // turns is taken from geometry coordinate_type and the one used in + // a strategy uses Type selected using CalculationType. + // See: detail::overlay::intersection_info_base + // and policies::relate::segments_intersection_points + // in particular segments_collinear() where ratios are assigned. + template friend class segment_ratio; + template + segment_ratio(segment_ratio const& r) + : m_numerator(r.m_numerator) + , m_denominator(r.m_denominator) + { + initialize(); + } + template + segment_ratio& operator=(segment_ratio const& r) + { + m_numerator = r.m_numerator; + m_denominator = r.m_denominator; + initialize(); + return *this; + } + template + segment_ratio(segment_ratio && r) + : m_numerator(std::move(r.m_numerator)) + , m_denominator(std::move(r.m_denominator)) + { + initialize(); + } + template + segment_ratio& operator=(segment_ratio && r) + { + m_numerator = std::move(r.m_numerator); + m_denominator = std::move(r.m_denominator); + initialize(); + return *this; + } + inline Type const& numerator() const { return m_numerator; } inline Type const& denominator() const { return m_denominator; } - inline void assign(const Type& nominator, const Type& denominator) + inline void assign(const Type& numerator, const Type& denominator) { - m_numerator = nominator; + m_numerator = numerator; m_denominator = denominator; initialize(); } diff --git a/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp b/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp index f87656dbc..5ea58736e 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2018-2020. +// Modifications copyright (c) 2018-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -24,8 +24,10 @@ #include #include #include -#include #include +#include +#include +#include namespace boost { namespace geometry { namespace strategy @@ -34,6 +36,10 @@ namespace boost { namespace geometry { namespace strategy namespace within { +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + struct decide_within { static inline bool apply(int side, bool& result) @@ -65,45 +71,181 @@ struct decide_covered_by // This strategy is not suitable for boxes in non-cartesian CSes having edges // longer than 180deg because e.g. the SSF formula picks the side of the closer // longitude, so for long edges the side is the opposite. -template -struct point_in_box_by_side +// Actually it is not suitable for shorter edges either because the edges of +// boxes are defined by meridians and parallels, not great circles or geodesics. +template +inline bool point_in_box_by_side(Point const& point, Box const& box, + Strategy const& strategy) +{ + boost::ignore_unused(strategy); + + // Create (counterclockwise) array of points, the fifth one closes it + // Every point should be on the LEFT side (=1), or ON the border (=0), + // So >= 1 or >= 0 + boost::array::type, 5> bp; + geometry::detail::assign_box_corners_oriented(box, bp); + bp[4] = bp[0]; + + bool result = true; + for (int i = 1; i < 5; i++) + { + int const side = strategy.apply(point, bp[i - 1], bp[i]); + if (! Decide::apply(side, result)) + { + return result; + } + } + + return result; +} + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +// There should probably be another category of geometry different than box, +// e.g. rectangle or convex_ring. This strategy should probably be an +// algorithm calling side strategy. + +template +struct cartesian_point_box_by_side { template static inline bool apply(Point const& point, Box const& box) { - typedef typename strategy::side::services::default_strategy + return within::detail::point_in_box_by_side < - typename cs_tag::type - >::type side_strategy_type; - - // Create (counterclockwise) array of points, the fifth one closes it - // Every point should be on the LEFT side (=1), or ON the border (=0), - // So >= 1 or >= 0 - boost::array::type, 5> bp; - geometry::detail::assign_box_corners_oriented(box, bp); - bp[4] = bp[0]; - - bool result = true; - side_strategy_type strategy; - boost::ignore_unused(strategy); - - for (int i = 1; i < 5; i++) - { - int const side = strategy.apply(point, bp[i - 1], bp[i]); - if (! Decide::apply(side, result)) - { - return result; - } - } - - return result; + within::detail::decide_within + >(point, box, + strategy::side::side_by_triangle()); } }; +template +struct spherical_point_box_by_side +{ + template + static inline bool apply(Point const& point, Box const& box) + { + return within::detail::point_in_box_by_side + < + within::detail::decide_within + >(point, box, + strategy::side::spherical_side_formula()); + } +}; + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +struct geographic_point_box_by_side +{ + geographic_point_box_by_side() = default; + + explicit geographic_point_box_by_side(Spheroid const& spheroid) + : m_side(spheroid) + {} + + template + bool apply(Point const& point, Box const& box) const + { + return within::detail::point_in_box_by_side + < + within::detail::decide_within + >(point, box, m_side); + } + + Spheroid const& model() const + { + return m_side.model(); + } + +private: + strategy::side::geographic + < + FormulaPolicy, Spheroid, CalculationType + > m_side; +}; + } // namespace within +namespace covered_by +{ + + +template +struct cartesian_point_box_by_side +{ + template + static bool apply(Point const& point, Box const& box) + { + return within::detail::point_in_box_by_side + < + within::detail::decide_covered_by + >(point, box, + strategy::side::side_by_triangle()); + } +}; + +template +struct spherical_point_box_by_side +{ + template + static bool apply(Point const& point, Box const& box) + { + return within::detail::point_in_box_by_side + < + within::detail::decide_covered_by + >(point, box, + strategy::side::spherical_side_formula()); + } +}; + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +struct geographic_point_box_by_side +{ + geographic_point_box_by_side() = default; + + explicit geographic_point_box_by_side(Spheroid const& spheroid) + : m_side(spheroid) + {} + + template + bool apply(Point const& point, Box const& box) const + { + return within::detail::point_in_box_by_side + < + within::detail::decide_covered_by + >(point, box, m_side); + } + + Spheroid const& model() const + { + return m_side.model(); + } + +private: + strategy::side::geographic + < + FormulaPolicy, Spheroid, CalculationType + > m_side; +}; + + +} + + }}} // namespace boost::geometry::strategy diff --git a/include/boost/geometry/strategies/cartesian.hpp b/include/boost/geometry/strategies/cartesian.hpp index a49cfe6a3..9ba28fb2c 100644 --- a/include/boost/geometry/strategies/cartesian.hpp +++ b/include/boost/geometry/strategies/cartesian.hpp @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include namespace boost { namespace geometry diff --git a/include/boost/geometry/strategies/cartesian/box_in_box.hpp b/include/boost/geometry/strategies/cartesian/box_in_box.hpp index fef054cdb..a0cb6d9d1 100644 --- a/include/boost/geometry/strategies/cartesian/box_in_box.hpp +++ b/include/boost/geometry/strategies/cartesian/box_in_box.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2015, 2016, 2017, 2019. -// Modifications copyright (c) 2016-2019, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2020. +// Modifications copyright (c) 2016-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -186,11 +186,6 @@ struct relate_box_box_loop }; -} // namespace detail -#endif // DOXYGEN_NO_DETAIL - - -// for backward compatibility template struct box_within_range : within::detail::box_within_coord @@ -226,31 +221,8 @@ struct box_covered_by_range {}; -// for backward compatibility -template -< - typename B1, - typename B2, - template class SubStrategy = box_within_range -> -struct box_in_box -{ - template - static inline bool apply(Box1 const& box1, Box2 const& box2) - { - typedef typename tag_cast - < - typename geometry::cs_tag::type, - spherical_tag - >::type cs_tag; - - return within::detail::relate_box_box_loop - < - SubStrategy, cs_tag, - 0, dimension::type::value - >::apply(box1, box2); - } -}; +} // namespace detail +#endif // DOXYGEN_NO_DETAIL struct cartesian_box_box @@ -260,7 +232,7 @@ struct cartesian_box_box { return within::detail::relate_box_box_loop < - box_within_range, + within::detail::box_within_range, cartesian_tag, 0, dimension::type::value >::apply(box1, box2); @@ -274,7 +246,7 @@ struct spherical_box_box { return within::detail::relate_box_box_loop < - box_within_range, + within::detail::box_within_range, spherical_tag, 0, dimension::type::value >::apply(box1, box2); @@ -296,7 +268,7 @@ struct cartesian_box_box { return within::detail::relate_box_box_loop < - strategy::within::box_covered_by_range, + within::detail::box_covered_by_range, cartesian_tag, 0, dimension::type::value >::apply(box1, box2); @@ -310,7 +282,7 @@ struct spherical_box_box { return within::detail::relate_box_box_loop < - strategy::within::box_covered_by_range, + within::detail::box_covered_by_range, spherical_tag, 0, dimension::type::value >::apply(box1, box2); diff --git a/include/boost/geometry/strategies/cartesian/index.hpp b/include/boost/geometry/strategies/cartesian/index.hpp deleted file mode 100644 index f4a16be5a..000000000 --- a/include/boost/geometry/strategies/cartesian/index.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// Boost.Geometry Index -// -// R-tree strategies -// -// Copyright (c) 2019-2020, Oracle and/or its affiliates. -// 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_STRATEGIES_CARTESIAN_INDEX_HPP -#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INDEX_HPP - - -#include -#include -#include -#include -#include -#include - -#include -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -namespace boost { namespace geometry { namespace strategy { namespace index -{ - -template -< - typename CalculationType = void -> -struct cartesian -{ - typedef cartesian_tag cs_tag; - - typedef geometry::strategy::envelope::cartesian_point envelope_point_strategy_type; - typedef geometry::strategy::envelope::cartesian_box envelope_box_strategy_type; - typedef geometry::strategy::envelope::cartesian_segment - < - CalculationType - > envelope_segment_strategy_type; - - static inline envelope_segment_strategy_type get_envelope_segment_strategy() - { - return envelope_segment_strategy_type(); - } - - typedef geometry::strategy::expand::cartesian_point expand_point_strategy_type; - typedef geometry::strategy::expand::cartesian_box expand_box_strategy_type; - typedef geometry::strategy::expand::cartesian_segment expand_segment_strategy_type; - - static inline expand_segment_strategy_type get_expand_segment_strategy() - { - return expand_segment_strategy_type(); - } - - typedef geometry::strategy::covered_by::cartesian_point_box covered_by_point_box_strategy_type; - typedef geometry::strategy::covered_by::cartesian_box_box covered_by_box_box_strategy_type; - typedef geometry::strategy::within::cartesian_point_point within_point_point_strategy_type; - /* - typedef geometry::strategy::within::cartesian_point_box within_point_box_strategy_type; - typedef geometry::strategy::within::cartesian_box_box within_box_box_strategy_type; - typedef geometry::strategy::within::cartesian_winding - < - void, void, CalculationType - > within_point_segment_strategy_type; - - static inline within_point_segment_strategy_type get_within_point_segment_strategy() - { - return within_point_segment_strategy_type(); - } - */ - - // used in equals(Seg, Seg) but only to get_point_in_point_strategy() - typedef geometry::strategy::intersection::cartesian_segments - < - CalculationType - > relate_segment_segment_strategy_type; - - static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy() - { - return relate_segment_segment_strategy_type(); - } - - // used in intersection_content - typedef geometry::strategy::disjoint::cartesian_box_box disjoint_box_box_strategy_type; - - typedef geometry::strategy::distance::comparable::pythagoras - < - CalculationType - > comparable_distance_point_point_strategy_type; - - static inline comparable_distance_point_point_strategy_type get_comparable_distance_point_point_strategy() - { - return comparable_distance_point_point_strategy_type(); - } - - typedef geometry::strategy::distance::comparable::pythagoras_point_box - < - CalculationType - > comparable_distance_point_box_strategy_type; - - static inline comparable_distance_point_box_strategy_type get_comparable_distance_point_box_strategy() - { - return comparable_distance_point_box_strategy_type(); - } - - // TODO: comparable version should be possible - typedef geometry::strategy::distance::projected_point - < - CalculationType, - geometry::strategy::distance::pythagoras - > comparable_distance_point_segment_strategy_type; - - static inline comparable_distance_point_segment_strategy_type get_comparable_distance_point_segment_strategy() - { - return comparable_distance_point_segment_strategy_type(); - } - - typedef geometry::strategy::distance::cartesian_segment_box - < - CalculationType, - geometry::strategy::distance::pythagoras - > comparable_distance_segment_box_strategy_type; - - static inline comparable_distance_segment_box_strategy_type get_comparable_distance_segment_box_strategy() - { - return comparable_distance_segment_box_strategy_type(); - } -}; - - -namespace services -{ - -template -struct default_strategy -{ - typedef cartesian<> type; -}; - - -// within and relate (MPt, Mls/MPoly) -template -struct from_strategy > -{ - typedef strategy::index::cartesian type; - - static inline type get(within::cartesian_winding const&) - { - return type(); - } -}; - -// distance (MPt, MPt) -template -struct from_strategy > -{ - typedef strategy::index::cartesian type; - - static inline type get(distance::comparable::pythagoras const&) - { - return type(); - } -}; - -// distance (MPt, Linear/Areal) -template -struct from_strategy > -{ - typedef strategy::index::cartesian type; - - static inline type get(distance::projected_point const&) - { - return type(); - } -}; - - -} // namespace services - - -}}}} // namespace boost::geometry::strategy::index - -#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INDEX_HPP diff --git a/include/boost/geometry/strategies/cartesian/intersection.hpp b/include/boost/geometry/strategies/cartesian/intersection.hpp index 81efbbc47..f0b471036 100644 --- a/include/boost/geometry/strategies/cartesian/intersection.hpp +++ b/include/boost/geometry/strategies/cartesian/intersection.hpp @@ -436,13 +436,12 @@ struct cartesian_segments point2_type const& q1 = range_q.at(0); point2_type const& q2 = range_q.at(1); - using geometry::detail::equals::equals_point_point; - bool const p_is_point = equals_point_point(p1, p2, point_in_point_strategy_type()); - bool const q_is_point = equals_point_point(q1, q2, point_in_point_strategy_type()); + bool const p_is_point = equals_point_point(p1, p2); + bool const q_is_point = equals_point_point(q1, q2); if (p_is_point && q_is_point) { - return equals_point_point(p1, q2, point_in_point_strategy_type()) + return equals_point_point(p1, q2) ? Policy::degenerate(p, true) : Policy::disjoint() ; @@ -772,6 +771,12 @@ private: : ca1 < cb2 ? 4 : 2 ); } + + template + static inline bool equals_point_point(Point1 const& point1, Point2 const& point2) + { + return strategy::within::cartesian_point_point::apply(point1, point2); + } }; diff --git a/include/boost/geometry/strategies/cartesian/io.hpp b/include/boost/geometry/strategies/cartesian/io.hpp deleted file mode 100644 index d8fda2961..000000000 --- a/include/boost/geometry/strategies/cartesian/io.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// Boost.Geometry - -// Copyright (c) 2019, 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_EXTENSIONS_STRATEGIES_CARTESIAN_IO_HPP -#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_CARTESIAN_IO_HPP - - -#include - -#include -#include - - -namespace boost { namespace geometry -{ - -namespace strategy { namespace io -{ - -template -struct cartesian -{ - typedef strategy::point_order::cartesian point_order_strategy_type; - - static inline point_order_strategy_type get_point_order_strategy() - { - return point_order_strategy_type(); - } - - template - struct point_in_geometry_strategy - { - typedef strategy::within::cartesian_winding - < - typename point_type::type, - typename point_type::type, - CalculationType - > type; - }; - - template - static inline typename point_in_geometry_strategy::type - get_point_in_geometry_strategy() - { - typedef typename point_in_geometry_strategy - < - Geometry1, Geometry2 - >::type strategy_type; - return strategy_type(); - } -}; - -namespace services -{ - -template <> -struct default_strategy -{ - typedef cartesian<> type; -}; - -} // namespace services - -}} // namespace strategy::io - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_CARTESIAN_IO_HPP diff --git a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp index 62eceaadf..e53eac893 100644 --- a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp +++ b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp @@ -269,8 +269,7 @@ private: template static inline bool equals_point_point(P1 const& p1, P2 const& p2) { - typedef equals_point_point_strategy_type strategy_t; - return geometry::detail::equals::equals_point_point(p1, p2, strategy_t()); + return strategy::within::cartesian_point_point::apply(p1, p2); } }; diff --git a/include/boost/geometry/strategies/concepts/within_concept.hpp b/include/boost/geometry/strategies/concepts/within_concept.hpp index 4616fb981..8775613ec 100644 --- a/include/boost/geometry/strategies/concepts/within_concept.hpp +++ b/include/boost/geometry/strategies/concepts/within_concept.hpp @@ -33,6 +33,8 @@ #include #include +#include + #include @@ -40,6 +42,48 @@ namespace boost { namespace geometry { namespace concepts { +namespace detail +{ + + +template +< + typename Point, typename Geometry, typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> +struct relate_strategy_dispatch +{ + using type = decltype(std::declval().relate( + std::declval(), std::declval())); +}; + +template +struct relate_strategy_dispatch +{ + using type = Strategy; +}; + +template +< + typename Point, typename Geometry, typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> +struct within_strategy_dispatch +{ + using type = decltype(std::declval().within( + std::declval(), std::declval())); +}; + +template +struct within_strategy_dispatch +{ + using type = Strategy; +}; + + +} // namespace detail + + /*! \brief Checks strategy for within (point-in-polygon) \ingroup within @@ -51,8 +95,14 @@ class WithinStrategyPolygonal typedef typename geometry::point_type::type point_of_segment; + // 0) + typedef typename concepts::detail::relate_strategy_dispatch + < + Point, Polygonal, Strategy + >::type strategy_type; + // 1) must define state_type - typedef typename Strategy::state_type state_type; + typedef typename strategy_type::state_type state_type; struct checker { @@ -101,7 +151,7 @@ class WithinStrategyPolygonal // CHECK: calling method apply and result - Strategy const* str = 0; + strategy_type const* str = 0; state_type* st = 0; point_type const* p = 0; segment_point_type const* sp = 0; @@ -117,8 +167,8 @@ class WithinStrategyPolygonal public : BOOST_CONCEPT_USAGE(WithinStrategyPolygonal) { - checker::apply(&Strategy::template apply, - &Strategy::result); + checker::apply(&strategy_type::template apply, + &strategy_type::result); } #endif }; @@ -128,6 +178,12 @@ class WithinStrategyPointBox { #ifndef DOXYGEN_NO_CONCEPT_MEMBERS + // 0) + typedef typename concepts::detail::within_strategy_dispatch + < + Point, Box, Strategy + >::type strategy_type; + struct checker { template @@ -167,7 +223,7 @@ class WithinStrategyPointBox // CHECK: calling method apply - Strategy const* str = 0; + strategy_type const* str = 0; point_type const* p = 0; box_type const* bx = 0; @@ -181,7 +237,7 @@ class WithinStrategyPointBox public : BOOST_CONCEPT_USAGE(WithinStrategyPointBox) { - checker::apply(&Strategy::template apply); + checker::apply(&strategy_type::template apply); } #endif }; @@ -191,6 +247,12 @@ class WithinStrategyBoxBox { #ifndef DOXYGEN_NO_CONCEPT_MEMBERS + // 0) + typedef typename concepts::detail::within_strategy_dispatch + < + Box1, Box2, Strategy + >::type strategy_type; + struct checker { template @@ -230,7 +292,7 @@ class WithinStrategyBoxBox // CHECK: calling method apply - Strategy const* str = 0; + strategy_type const* str = 0; box_type1 const* b1 = 0; box_type2 const* b2 = 0; @@ -244,7 +306,7 @@ class WithinStrategyBoxBox public : BOOST_CONCEPT_USAGE(WithinStrategyBoxBox) { - checker::apply(&Strategy::template apply); + checker::apply(&strategy_type::template apply); } #endif }; diff --git a/include/boost/geometry/strategies/detail.hpp b/include/boost/geometry/strategies/detail.hpp index 410423d46..360b7ccfb 100644 --- a/include/boost/geometry/strategies/detail.hpp +++ b/include/boost/geometry/strategies/detail.hpp @@ -44,7 +44,7 @@ struct is_umbrella_strategy struct cartesian_base : umbrella_strategy { - typedef cartesian_tag tag; + typedef cartesian_tag cs_tag; }; template @@ -60,7 +60,7 @@ protected: >::type radius_type; public: - typedef spherical_tag tag; + typedef spherical_tag cs_tag; spherical_base() : m_radius(1.0) @@ -87,7 +87,7 @@ template <> class spherical_base : umbrella_strategy { public: - typedef spherical_tag tag; + typedef spherical_tag cs_tag; srs::sphere model() const { @@ -99,7 +99,7 @@ template class geographic_base : umbrella_strategy { public: - typedef geographic_tag tag; + typedef geographic_tag cs_tag; geographic_base() : m_spheroid() diff --git a/include/boost/geometry/strategies/disjoint.hpp b/include/boost/geometry/strategies/disjoint.hpp index c5413a86d..9a52f5bc2 100644 --- a/include/boost/geometry/strategies/disjoint.hpp +++ b/include/boost/geometry/strategies/disjoint.hpp @@ -18,7 +18,8 @@ #include #include -#include + +#include namespace boost { namespace geometry { namespace strategy { namespace disjoint diff --git a/include/boost/geometry/strategies/geographic.hpp b/include/boost/geometry/strategies/geographic.hpp index c3bc2a4da..92dc66f1b 100644 --- a/include/boost/geometry/strategies/geographic.hpp +++ b/include/boost/geometry/strategies/geographic.hpp @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include namespace boost { namespace geometry diff --git a/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp b/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp index c4b843072..2e06049aa 100644 --- a/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp +++ b/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp @@ -93,6 +93,11 @@ public: strategy::disjoint::spherical_box_box()); } + Spheroid const& model() const + { + return m_spheroid; + } + private: Spheroid m_spheroid; }; diff --git a/include/boost/geometry/strategies/geographic/distance_segment_box.hpp b/include/boost/geometry/strategies/geographic/distance_segment_box.hpp index 99b181fa2..491d4da2b 100644 --- a/include/boost/geometry/strategies/geographic/distance_segment_box.hpp +++ b/include/boost/geometry/strategies/geographic/distance_segment_box.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2018-2019 Oracle and/or its affiliates. +// Copyright (c) 2018-2020 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/geometry/strategies/geographic/index.hpp b/include/boost/geometry/strategies/geographic/index.hpp deleted file mode 100644 index 216de31ff..000000000 --- a/include/boost/geometry/strategies/geographic/index.hpp +++ /dev/null @@ -1,216 +0,0 @@ -// Boost.Geometry Index -// -// R-tree strategies -// -// Copyright (c) 2019, Oracle and/or its affiliates. -// 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_STRATEGIES_GEOGRAPHIC_INDEX_HPP -#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INDEX_HPP - -#include -#include - -#include -#include // backward compatibility -#include -#include -#include -#include // backward compatibility -#include // backward compatibility -#include -#include - -#include - - -namespace boost { namespace geometry { namespace strategy { namespace index -{ - -template -< - typename FormulaPolicy = strategy::andoyer, - typename Spheroid = geometry::srs::spheroid, - typename CalculationType = void -> -struct geographic - : spherical -{ - typedef geographic_tag cs_tag; - - typedef geometry::strategy::envelope::geographic_segment - < - FormulaPolicy, Spheroid, CalculationType - > envelope_segment_strategy_type; - - inline envelope_segment_strategy_type get_envelope_segment_strategy() const - { - return envelope_segment_strategy_type(m_spheroid); - } - - typedef geometry::strategy::expand::geographic_segment - < - FormulaPolicy, Spheroid, CalculationType - > expand_segment_strategy_type; - - inline expand_segment_strategy_type get_expand_segment_strategy() const - { - return expand_segment_strategy_type(m_spheroid); - } - - // used in equals(Seg, Seg) but only to get_point_in_point_strategy() - typedef geometry::strategy::intersection::geographic_segments - < - FormulaPolicy, - // If index::geographic formula is derived from intersection::geographic_segments - // formula with different Order this may cause an inconsistency - strategy::default_order::value, - Spheroid, - CalculationType - > relate_segment_segment_strategy_type; - - inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy() const - { - return relate_segment_segment_strategy_type(m_spheroid); - } - - typedef geometry::strategy::distance::geographic - < - FormulaPolicy, Spheroid, CalculationType - > comparable_distance_point_point_strategy_type; - - inline comparable_distance_point_point_strategy_type get_comparable_distance_point_point_strategy() const - { - return comparable_distance_point_point_strategy_type(m_spheroid); - } - - typedef geometry::strategy::distance::geographic_cross_track_point_box - < - FormulaPolicy, Spheroid, CalculationType - > comparable_distance_point_box_strategy_type; - - inline comparable_distance_point_box_strategy_type get_comparable_distance_point_box_strategy() const - { - return comparable_distance_point_box_strategy_type(m_spheroid); - } - - typedef geometry::strategy::distance::geographic_cross_track - < - FormulaPolicy, Spheroid, CalculationType - > comparable_distance_point_segment_strategy_type; - - inline comparable_distance_point_segment_strategy_type get_comparable_distance_point_segment_strategy() const - { - return comparable_distance_point_segment_strategy_type(m_spheroid); - } - - typedef geometry::strategy::distance::geographic_segment_box - < - FormulaPolicy, Spheroid, CalculationType - > comparable_distance_segment_box_strategy_type; - - inline comparable_distance_segment_box_strategy_type get_comparable_distance_segment_box_strategy() const - { - return comparable_distance_segment_box_strategy_type(m_spheroid); - } - - geographic() - : m_spheroid() - {} - - explicit geographic(Spheroid const& spheroid) - : m_spheroid(spheroid) - {} - -public: - Spheroid m_spheroid; -}; - - -namespace services -{ - -template -struct default_strategy -{ - typedef geographic<> type; -}; - - -// within and relate (MPt, Mls/MPoly) -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(within::geographic_winding const& strategy) - { - return type(strategy.model()); - } -}; - -// distance (MPt, MPt) -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(distance::geographic const& strategy) - { - return type(strategy.model()); - } -}; -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(distance::andoyer const& strategy) - { - return type(strategy.model()); - } -}; -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(distance::thomas const& strategy) - { - return type(strategy.model()); - } -}; -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(distance::vincenty const& strategy) - { - return type(strategy.model()); - } -}; - -// distance (MPt, Linear/Areal) -template -struct from_strategy > -{ - typedef strategy::index::geographic type; - - static inline type get(distance::geographic_cross_track const& strategy) - { - return type(strategy.model()); - } -}; - - -} // namespace services - - -}}}} // namespace boost::geometry::strategy::index - -#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INDEX_HPP diff --git a/include/boost/geometry/strategies/geographic/intersection.hpp b/include/boost/geometry/strategies/geographic/intersection.hpp index 56edb8ea0..f157d7542 100644 --- a/include/boost/geometry/strategies/geographic/intersection.hpp +++ b/include/boost/geometry/strategies/geographic/intersection.hpp @@ -72,7 +72,7 @@ namespace strategy { namespace intersection template < typename FormulaPolicy = strategy::andoyer, - unsigned int Order = strategy::default_order::value, + std::size_t Order = strategy::default_order::value, typename Spheroid = srs::spheroid, typename CalculationType = void > @@ -247,6 +247,11 @@ struct geographic_segments : m_spheroid(spheroid) {} + Spheroid model() const + { + return m_spheroid; + } + // Relate segments a and b template < @@ -992,8 +997,7 @@ private: template static inline bool equals_point_point(Point1 const& point1, Point2 const& point2) { - return detail::equals::equals_point_point(point1, point2, - point_in_point_strategy_type()); + return strategy::within::spherical_point_point::apply(point1, point2); } private: diff --git a/include/boost/geometry/strategies/geographic/io.hpp b/include/boost/geometry/strategies/geographic/io.hpp deleted file mode 100644 index c4898ea0c..000000000 --- a/include/boost/geometry/strategies/geographic/io.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// Boost.Geometry - -// Copyright (c) 2019, 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_EXTENSIONS_STRATEGIES_GEOGRAPHIC_IO_HPP -#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_GEOGRAPHIC_IO_HPP - - -#include - -#include -#include - - -namespace boost { namespace geometry -{ - -namespace strategy { namespace io -{ - -template - < - typename FormulaPolicy = strategy::andoyer, - typename Spheroid = srs::spheroid, - typename CalculationType = void - > -struct geographic -{ - typedef strategy::point_order::geographic - < - FormulaPolicy, - Spheroid, - CalculationType - > point_order_strategy_type; - - point_order_strategy_type get_point_order_strategy() const - { - return point_order_strategy_type(m_spheroid); - } - - template - struct point_in_geometry_strategy - { - typedef strategy::within::geographic_winding - < - typename point_type::type, - typename point_type::type, - FormulaPolicy, - Spheroid, - CalculationType - > type; - }; - - template - typename point_in_geometry_strategy::type - get_point_in_geometry_strategy() const - { - typedef typename point_in_geometry_strategy - < - Geometry1, Geometry2 - >::type strategy_type; - return strategy_type(m_spheroid); - } - - geographic() - {} - - geographic(Spheroid const& spheroid) - : m_spheroid(spheroid) - {} - -private: - Spheroid m_spheroid; -}; - -namespace services -{ - -template <> -struct default_strategy -{ - typedef geographic<> type; -}; - -} // namespace services - -}} // namespace strategy::io - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_GEOGRAPHIC_IO_HPP diff --git a/include/boost/geometry/strategies/index.hpp b/include/boost/geometry/strategies/index.hpp deleted file mode 100644 index 3f8fddd8d..000000000 --- a/include/boost/geometry/strategies/index.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// Boost.Geometry Index -// -// R-tree strategies -// -// Copyright (c) 2019-2020, Oracle and/or its affiliates. -// 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_STRATEGIES_INDEX_HPP -#define BOOST_GEOMETRY_STRATEGIES_INDEX_HPP - - -#include -#include -#include - - -namespace boost { namespace geometry { namespace strategy { namespace index -{ - -namespace services -{ - -template -< - typename Geometry, - typename CSTag = typename geometry::cs_tag::type -> -struct default_strategy -{ - /*BOOST_GEOMETRY_STATIC_ASSERT_FALSE( - "Not implemented for this type.", - Geometry);*/ - - typedef geometry::default_strategy type; -}; - - -// TEMP -// Utility to get index strategy from other strategy -// In the final version this utility will probably replaced with some other mechanism -// The issue is cross-dependencies between strategies -template -struct from_strategy -{ - /*BOOST_GEOMETRY_STATIC_ASSERT_FALSE( - "Not implemented for this type.", - Strategy);*/ - - typedef geometry::default_strategy type; - - static inline type get(Strategy const&) - { - return type(); - } -}; - - -} // namespace services - - -}}}} // namespace boost::geometry::strategy::index - -#endif // BOOST_GEOMETRY_STRATEGIES_INDEX_HPP diff --git a/include/boost/geometry/strategies/index/cartesian.hpp b/include/boost/geometry/strategies/index/cartesian.hpp new file mode 100644 index 000000000..52352e2de --- /dev/null +++ b/include/boost/geometry/strategies/index/cartesian.hpp @@ -0,0 +1,147 @@ +// Boost.Geometry + +// Copyright (c) 2020, 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_INDEX_CARTESIAN_HPP +#define BOOST_GEOMETRY_STRATEGIES_INDEX_CARTESIAN_HPP + + +// TODO: move to strategy directory +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry { namespace strategies { namespace index +{ + +template +class cartesian + : public relate::cartesian +{ +public: + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + //return geometry::strategy::distance::comparable::pythagoras(); + return geometry::strategy::distance::pythagoras(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_segment::value) + || (util::is_segment::value + && util::is_pointlike::value) + > * = nullptr) + { + return geometry::strategy::distance::projected_point + < + CalculationType, + //geometry::strategy::distance::comparable::pythagoras + geometry::strategy::distance::pythagoras + >(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_box::value) + || (util::is_box::value + && util::is_pointlike::value) + > * = nullptr) + { + //return geometry::strategy::distance::comparable::pythagoras_point_box(); + return geometry::strategy::distance::pythagoras_point_box(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_segment::value + && util::is_box::value) + || (util::is_box::value + && util::is_segment::value) + > * = nullptr) + { + return geometry::strategy::distance::cartesian_segment_box + < + CalculationType, + //geometry::strategy::distance::comparable::pythagoras + geometry::strategy::distance::pythagoras + >(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_segment::value + > * = nullptr) + { + return strategy::distance::projected_point + < + CalculationType, + //strategy::distance::comparable::pythagoras + strategy::distance::pythagoras + >(); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::index::cartesian<>; +}; + + +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::projected_point const& ) + { + return strategies::index::cartesian(); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::comparable::pythagoras const&) + { + return strategies::index::cartesian(); + } +}; + + +} // namespace services + + +}}}} // namespace boost::geometry::strategy::index + +#endif // BOOST_GEOMETRY_STRATEGIES_INDEX_CARTESIAN_HPP diff --git a/include/boost/geometry/strategies/index/geographic.hpp b/include/boost/geometry/strategies/index/geographic.hpp new file mode 100644 index 000000000..75f9f5ecf --- /dev/null +++ b/include/boost/geometry/strategies/index/geographic.hpp @@ -0,0 +1,279 @@ +// Boost.Geometry + +// Copyright (c) 2020, 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_INDEX_GEOGRAPHIC_HPP +#define BOOST_GEOMETRY_STRATEGIES_INDEX_GEOGRAPHIC_HPP + + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry { namespace strategies { namespace index +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + // TODO: Is SeriesOrder argument needed here? + std::size_t SeriesOrder = strategy::default_order::value, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +class geographic + : public relate::geographic +{ + typedef relate::geographic base_t; + +public: + geographic() + : base_t() + {} + + explicit geographic(Spheroid const& spheroid) + : base_t(spheroid) + {} + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) const + { + return geometry::strategy::distance::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_segment::value) + || (util::is_segment::value + && util::is_pointlike::value) + > * = nullptr) const + { + return geometry::strategy::distance::geographic_cross_track + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_box::value) + || (util::is_box::value + && util::is_pointlike::value) + > * = nullptr) const + { + return geometry::strategy::distance::geographic_cross_track_point_box + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_segment::value + && util::is_box::value) + || (util::is_box::value + && util::is_segment::value) + > * = nullptr) const + { + return geometry::strategy::distance::geographic_segment_box + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_segment::value + > * = nullptr) const + { + return geometry::strategy::distance::geographic_cross_track + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::index::geographic<>; +}; + +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::geographic_cross_track const& strategy) + { + return strategies::index::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(strategy.model()); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + typedef strategies::index::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + > base_strategy; + + struct altered_strategy : base_strategy + { + explicit altered_strategy(Spheroid const& spheroid) + : base_strategy(spheroid) + {} + + // It seems that this declaration is needed because comparable_distance + // is not static function. + using base_strategy::comparable_distance; + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_segment::value) + || (util::is_segment::value + && util::is_pointlike::value) + > * = nullptr) const + { + return geometry::strategy::distance::detail::geographic_cross_track + < + FormulaPolicy, Spheroid, CalculationType, Bisection, EnableClosestPoint + >(base_strategy::m_spheroid); + } + + template + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_segment::value + > * = nullptr) const + { + return geometry::strategy::distance::detail::geographic_cross_track + < + FormulaPolicy, Spheroid, CalculationType, Bisection, EnableClosestPoint + >(base_strategy::m_spheroid); + } + }; + + static auto get(strategy::distance::detail::geographic_cross_track const& strategy) + { + return altered_strategy(strategy.model()); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::geographic const& strategy) + { + return strategies::index::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(strategy.model()); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::andoyer const& strategy) + { + return strategies::index::geographic + < + strategy::andoyer, + strategy::default_order::value, + Spheroid, + CalculationType + >(strategy.model()); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::thomas const& strategy) + { + return strategies::index::geographic + < + strategy::thomas, + strategy::default_order::value, + Spheroid, + CalculationType + >(strategy.model()); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::vincenty const& strategy) + { + return strategies::index::geographic + < + strategy::vincenty, + strategy::default_order::value, + Spheroid, + CalculationType + >(strategy.model()); + } +}; + +} // namespace services + + +}}}} // namespace boost::geometry::strategy::index + +#endif // BOOST_GEOMETRY_STRATEGIES_INDEX_GEOGRAPHIC_HPP diff --git a/include/boost/geometry/strategies/index/services.hpp b/include/boost/geometry/strategies/index/services.hpp new file mode 100644 index 000000000..f256a3ac3 --- /dev/null +++ b/include/boost/geometry/strategies/index/services.hpp @@ -0,0 +1,50 @@ +// Boost.Geometry + +// Copyright (c) 2020, 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_INDEX_SERVICES_HPP +#define BOOST_GEOMETRY_STRATEGIES_INDEX_SERVICES_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace index { namespace services +{ + +template +< + typename Geometry, + typename CSTag = typename geometry::cs_tag::type +> +struct default_strategy +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this coordinate system.", + Geometry, CSTag); +}; + +template +struct strategy_converter +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this Strategy.", + Strategy); +}; + + +}}} // namespace strategy::index::services + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_INDEX_SERVICES_HPP diff --git a/include/boost/geometry/strategies/index/spherical.hpp b/include/boost/geometry/strategies/index/spherical.hpp new file mode 100644 index 000000000..938d9cf3a --- /dev/null +++ b/include/boost/geometry/strategies/index/spherical.hpp @@ -0,0 +1,161 @@ +// Boost.Geometry + +// Copyright (c) 2020, 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_INDEX_SPHERICAL_HPP +#define BOOST_GEOMETRY_STRATEGIES_INDEX_SPHERICAL_HPP + + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace index +{ + +template +class spherical + : public relate::spherical +{ +public: + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + //return geometry::strategy::distance::comparable::haversine(); + return geometry::strategy::distance::haversine(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_segment::value) + || (util::is_segment::value + && util::is_pointlike::value) + > * = nullptr) + { + //return geometry::strategy::distance::comparable::cross_track + return geometry::strategy::distance::cross_track + < + CalculationType, + //geometry::strategy::distance::comparable::haversine + geometry::strategy::distance::haversine + >(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_box::value) + || (util::is_box::value + && util::is_pointlike::value) + > * = nullptr) + { + //return geometry::strategy::distance::comparable::cross_track_point_box + return geometry::strategy::distance::cross_track_point_box + < + CalculationType, + //geometry::strategy::distance::comparable::haversine + geometry::strategy::distance::haversine + >(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_segment::value + && util::is_box::value) + || (util::is_box::value + && util::is_segment::value) + > * = nullptr) + { + return geometry::strategy::distance::spherical_segment_box + < + CalculationType, + //geometry::strategy::distance::comparable::haversine + geometry::strategy::distance::haversine + >(); + } + + template + static auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_segment::value + > * = nullptr) + { + return strategy::distance::projected_point + < + CalculationType, + //strategy::distance::comparable::pythagoras + strategy::distance::pythagoras + >(); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::index::spherical<>; +}; + +template +struct default_strategy +{ + using type = strategies::index::spherical<>; +}; + +template +struct default_strategy +{ + using type = strategies::index::spherical<>; +}; + +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::comparable::cross_track const& ) + { + return strategies::index::spherical(); + } +}; +// TEMP - needed in distance until umbrella strategies are supported +template +struct strategy_converter> +{ + static auto get(strategy::distance::comparable::haversine const&) + { + return strategies::index::spherical(); + } +}; + +} // namespace services + + +}}}} // namespace boost::geometry::strategy::index + +#endif // BOOST_GEOMETRY_STRATEGIES_INDEX_SPHERICAL_HPP diff --git a/include/boost/geometry/strategies/io/cartesian.hpp b/include/boost/geometry/strategies/io/cartesian.hpp new file mode 100644 index 000000000..cd726a425 --- /dev/null +++ b/include/boost/geometry/strategies/io/cartesian.hpp @@ -0,0 +1,77 @@ +// Boost.Geometry + +// Copyright (c) 2019-2020, 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_IO_CARTESIAN_HPP +#define BOOST_GEOMETRY_STRATEGIES_IO_CARTESIAN_HPP + + +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace io +{ + +template +class cartesian + : public strategies::detail::cartesian_base +{ +public: + static auto point_order() + { + return strategy::point_order::cartesian(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::cartesian_point_point(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::cartesian_winding(); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + typedef cartesian<> type; +}; + +} // namespace services + +}} // namespace strategies::io + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_IO_CARTESIAN_HPP diff --git a/include/boost/geometry/strategies/io/geographic.hpp b/include/boost/geometry/strategies/io/geographic.hpp new file mode 100644 index 000000000..ed17c9d4a --- /dev/null +++ b/include/boost/geometry/strategies/io/geographic.hpp @@ -0,0 +1,99 @@ +// Boost.Geometry + +// Copyright (c) 2019-2020, 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_IO_GEOGRAPHIC_HPP +#define BOOST_GEOMETRY_STRATEGIES_IO_GEOGRAPHIC_HPP + + +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace io +{ + +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() + : base_t() + {} + + explicit geographic(Spheroid const& spheroid) + : base_t(spheroid) + {} + + auto point_order() const + { + return strategy::point_order::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::spherical_point_point(); + } + + template + auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) const + { + return strategy::within::geographic_winding + < + void, void, + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + typedef geographic<> type; +}; + +} // namespace services + +}} // namespace strategies::io + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_IO_GEOGRAPHIC_HPP diff --git a/include/boost/geometry/strategies/io.hpp b/include/boost/geometry/strategies/io/services.hpp similarity index 59% rename from include/boost/geometry/strategies/io.hpp rename to include/boost/geometry/strategies/io/services.hpp index c4f956e91..2577f06aa 100644 --- a/include/boost/geometry/strategies/io.hpp +++ b/include/boost/geometry/strategies/io/services.hpp @@ -7,34 +7,39 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_IO_HPP -#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_IO_HPP +#ifndef BOOST_GEOMETRY_STRATEGIES_IO_SERVICES_HPP +#define BOOST_GEOMETRY_STRATEGIES_IO_SERVICES_HPP +#include #include namespace boost { namespace geometry { -namespace strategy { namespace io +namespace strategies { namespace io { namespace services { -template +template +< + typename Geometry, + typename CSTag = typename geometry::cs_tag::type +> struct default_strategy { BOOST_GEOMETRY_STATIC_ASSERT_FALSE( "Not implemented for this coordinate system.", - CSTag); + Geometry, CSTag); }; } // namespace services -}} // namespace strategy::io +}} // namespace strategies::io }} // namespace boost::geometry -#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_IO_HPP +#endif // BOOST_GEOMETRY_STRATEGIES_IO_SERVICES_HPP diff --git a/include/boost/geometry/strategies/io/spherical.hpp b/include/boost/geometry/strategies/io/spherical.hpp new file mode 100644 index 000000000..c74515a99 --- /dev/null +++ b/include/boost/geometry/strategies/io/spherical.hpp @@ -0,0 +1,89 @@ +// Boost.Geometry + +// Copyright (c) 2019-2020, 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_IO_SPHERICAL_HPP +#define BOOST_GEOMETRY_STRATEGIES_IO_SPHERICAL_HPP + + +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace io +{ + +template +class spherical + : public strategies::detail::spherical_base +{ +public: + static auto point_order() + { + return strategy::point_order::spherical(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::spherical_point_point(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::spherical_winding(); + } +}; + +namespace services +{ + +template +struct default_strategy +{ + typedef spherical<> type; +}; + +template +struct default_strategy +{ + typedef spherical<> type; +}; + +template +struct default_strategy +{ + typedef spherical<> type; +}; + +} // namespace services + +}} // namespace strategies::io + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_IO_SPHERICAL_HPP diff --git a/include/boost/geometry/strategies/relate.hpp b/include/boost/geometry/strategies/relate.hpp index 481fb38a1..7d388eb51 100644 --- a/include/boost/geometry/strategies/relate.hpp +++ b/include/boost/geometry/strategies/relate.hpp @@ -1,175 +1,21 @@ // Boost.Geometry -// Copyright (c) 2017-2020, Oracle and/or its affiliates. +// Copyright (c) 2020, Oracle and/or its affiliates. + // 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) +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html #ifndef BOOST_GEOMETRY_STRATEGIES_RELATE_HPP #define BOOST_GEOMETRY_STRATEGIES_RELATE_HPP -#include - -#include -#include -#include -#include - -#include -#include -#include +#include +BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.") -namespace boost { namespace geometry -{ - -namespace strategy -{ - -namespace point_in_geometry -{ - -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS -namespace services -{ - -template -< - typename Point, - typename Geometry, - typename Tag1 = typename tag::type, - typename Tag2 = typename tag::type -> -struct default_strategy - : strategy::within::services::default_strategy - < - Point, - Geometry - > -{ - typedef typename default_strategy::type within_strategy_type; - - typedef typename strategy::covered_by::services::default_strategy - < - Point, - Geometry - >::type covered_by_strategy_type; - - static const bool same_strategies = std::is_same::value; - BOOST_GEOMETRY_STATIC_ASSERT(same_strategies, - "Default within and covered_by strategies not compatible.", - within_strategy_type, covered_by_strategy_type); -}; - -template -struct default_strategy - : strategy::within::services::default_strategy -{}; - -template -struct default_strategy - : strategy::within::services::default_strategy -{}; - - -} // namespace services -#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS - - -} // namespace point_in_geometry - -namespace relate -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail -{ - -template -struct default_intersection_strategy - : strategy::intersection::services::default_strategy - < - typename cs_tag::type - > -{}; - -template -struct default_point_in_geometry_strategy - : point_in_geometry::services::default_strategy - < - typename point_type::type, - Geometry - > -{}; - -} // namespace detail -#endif // DOXYGEN_NO_DETAIL - -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS -namespace services -{ - -template -< - typename Geometry1, - typename Geometry2, - int TopDim1 = geometry::topological_dimension::value, - int TopDim2 = geometry::topological_dimension::value -> -struct default_strategy -{ - BOOST_GEOMETRY_STATIC_ASSERT_FALSE( - "Not implemented for these types.", - Geometry1, Geometry2); -}; - -template -struct default_strategy - : detail::default_point_in_geometry_strategy -{}; - -template -struct default_strategy - : detail::default_point_in_geometry_strategy -{}; - -template -struct default_strategy - : detail::default_point_in_geometry_strategy -{}; - -template -struct default_strategy - : detail::default_intersection_strategy -{}; - -template -struct default_strategy - : detail::default_intersection_strategy -{}; - -template -struct default_strategy - : detail::default_intersection_strategy -{}; - -template -struct default_strategy - : detail::default_intersection_strategy -{}; - -} // namespace services -#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS - -} // namespace relate - -} // namespace strategy - - -}} // namespace boost::geometry +#include #endif // BOOST_GEOMETRY_STRATEGIES_RELATE_HPP diff --git a/include/boost/geometry/strategies/relate/cartesian.hpp b/include/boost/geometry/strategies/relate/cartesian.hpp new file mode 100644 index 000000000..ca2763736 --- /dev/null +++ b/include/boost/geometry/strategies/relate/cartesian.hpp @@ -0,0 +1,448 @@ +// Boost.Geometry + +// Copyright (c) 2020, 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_RELATE_CARTESIAN_HPP +#define BOOST_GEOMETRY_STRATEGIES_RELATE_CARTESIAN_HPP + + +// TEMP - move to strategy +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace relate +{ + +template +class cartesian + : public strategies::detail::cartesian_base +{ +public: + //area + + template + static auto area(Geometry const&) + { + return strategy::area::cartesian(); + } + + // covered_by + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::cartesian_point_box(); + } + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::cartesian_box_box(); + } + + // disjoint + + template + static auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::disjoint::cartesian_box_box(); + } + + template + static auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_box::value + > * = nullptr) + { + // NOTE: Inconsistent name. + return strategy::disjoint::segment_box(); + } + + // envelope + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_point_t * = nullptr) + { + return strategy::envelope::cartesian_point(); + } + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_multi_point_t * = nullptr) + { + return strategy::envelope::cartesian_multipoint(); + } + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_box_t * = nullptr) + { + return strategy::envelope::cartesian_box(); + } + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_segment_t * = nullptr) + { + return strategy::envelope::cartesian_segment(); + } + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_polysegmental_t * = nullptr) + { + return strategy::envelope::cartesian(); + } + + // expand + + template + static auto expand(Box const&, Geometry const&, + typename util::enable_if_point_t * = nullptr) + { + return strategy::expand::cartesian_point(); + } + + template + static auto expand(Box const&, Geometry const&, + typename util::enable_if_box_t * = nullptr) + { + return strategy::expand::cartesian_box(); + } + + template + static auto expand(Box const&, Geometry const&, + typename util::enable_if_segment_t * = nullptr) + { + return strategy::expand::cartesian_segment(); + } + + // relate + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::cartesian_point_point(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::cartesian_winding(); + } + + // The problem is that this strategy is often used with non-geometry ranges. + // So dispatching only by geometry categories is impossible. + // In the past it was taking two segments, now it takes 3-point sub-ranges. + // So dispatching by segments is impossible. + // It could be dispatched by (linear || polygonal || non-geometry point range). + // For now implement as 0-parameter, special case relate. + + //template + static auto relate(/*Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + ( util::is_linear::value + || util::is_polygonal::value ) + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr*/) + { + return strategy::intersection::cartesian_segments(); + } + + // side + + static auto side() + { + return strategy::side::side_by_triangle(); + } + + // within + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::cartesian_point_box(); + } + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::cartesian_box_box(); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::relate::cartesian<>; +}; + + +template <> +struct strategy_converter +{ + static auto get(strategy::within::cartesian_point_point const& ) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::within::cartesian_point_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::covered_by::cartesian_point_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::covered_by::cartesian_box_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::disjoint::cartesian_box_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::disjoint::segment_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::within::cartesian_box_box const&) + { + return strategies::relate::cartesian<>(); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::within::cartesian_winding const& ) + { + return strategies::relate::cartesian(); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::intersection::cartesian_segments const& ) + { + return strategies::relate::cartesian(); + } +}; + +template +struct strategy_converter> +{ + struct altered_strategy + : strategies::relate::cartesian + { + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::cartesian_point_box_by_side(); + } + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::cartesian_point_box_by_side(); + } + }; + + static auto get(strategy::covered_by::cartesian_point_box_by_side const&) + { + return altered_strategy(); + } + + static auto get(strategy::within::cartesian_point_box_by_side const&) + { + return altered_strategy(); + } +}; + +template +struct strategy_converter> + : strategy_converter> +{}; + +template +struct strategy_converter> +{ + struct altered_strategy + : strategies::relate::cartesian + { + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::franklin(); + } + }; + + static auto get(strategy::within::franklin const&) + { + return altered_strategy(); + } +}; + +template +struct strategy_converter> +{ + struct altered_strategy + : strategies::relate::cartesian + { + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::crossings_multiply(); + } + }; + + static auto get(strategy::within::crossings_multiply const&) + { + return altered_strategy(); + } +}; + +// TEMP used in distance segment/box +template +struct strategy_converter> +{ + static auto get(strategy::side::side_by_triangle const&) + { + return strategies::relate::cartesian(); + } +}; + + +} // namespace services + +}} // namespace strategies::relate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_RELATE_CARTESIAN_HPP diff --git a/include/boost/geometry/strategies/relate/geographic.hpp b/include/boost/geometry/strategies/relate/geographic.hpp new file mode 100644 index 000000000..d01a43099 --- /dev/null +++ b/include/boost/geometry/strategies/relate/geographic.hpp @@ -0,0 +1,419 @@ +// Boost.Geometry + +// Copyright (c) 2020, 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_RELATE_GEOGRAPHIC_HPP +#define BOOST_GEOMETRY_STRATEGIES_RELATE_GEOGRAPHIC_HPP + + +// TEMP +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace relate +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + // TODO: Is SeriesOrder argument needed here? + std::size_t SeriesOrder = strategy::default_order::value, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +class geographic + : public strategies::detail::geographic_base +{ + using base_t = strategies::detail::geographic_base; + +public: + geographic() + : base_t() + {} + + explicit geographic(Spheroid const& spheroid) + : base_t(spheroid) + {} + + // area + + template + auto area(Geometry const&) const + { + return strategy::area::geographic + < + FormulaPolicy, SeriesOrder, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + // covered_by + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::spherical_point_box(); + } + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::spherical_box_box(); + } + + // disjoint + + template + static auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::disjoint::spherical_box_box(); + } + + template + auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_box::value + > * = nullptr) const + { + // NOTE: Inconsistent name + // The only disjoint(Seg, Box) strategy that takes CalculationType. + return strategy::disjoint::segment_box_geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + // envelope + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_point_t * = nullptr) + { + return strategy::envelope::spherical_point(); + } + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_multi_point_t * = nullptr) + { + return strategy::envelope::spherical_multipoint(); + } + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_box_t * = nullptr) + { + return strategy::envelope::spherical_box(); + } + + template + auto envelope(Geometry const&, Box const&, + typename util::enable_if_segment_t * = nullptr) const + { + return strategy::envelope::geographic_segment + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + template + auto envelope(Geometry const&, Box const&, + typename util::enable_if_polysegmental_t * = nullptr) const + { + return strategy::envelope::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + // expand + + template + static auto expand(Box const&, Geometry const&, + typename util::enable_if_point_t * = nullptr) + { + return strategy::expand::spherical_point(); + } + + template + static auto expand(Box const&, Geometry const&, + typename util::enable_if_box_t * = nullptr) + { + return strategy::expand::spherical_box(); + } + + template + auto expand(Box const&, Geometry const&, + typename util::enable_if_segment_t * = nullptr) const + { + return strategy::expand::geographic_segment + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + // relate + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::spherical_point_point(); + } + + template + auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) const + { + return strategy::within::geographic_winding + < + void, void, FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + //template + auto relate(/*Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + ( util::is_linear::value + || util::is_polygonal::value ) + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr*/) const + { + return strategy::intersection::geographic_segments + < + FormulaPolicy, SeriesOrder, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + // side + + auto side() const + { + return strategy::side::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + + // within + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::spherical_point_box(); + } + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::spherical_box_box(); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::relate::geographic<>; +}; + + +template +struct strategy_converter> +{ + static auto get(strategy::disjoint::segment_box_geographic const& s) + { + return strategies::relate::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(s.model()); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::within::geographic_winding const& s) + { + return strategies::relate::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(s.model()); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::intersection::geographic_segments const& s) + { + return strategies::relate::geographic + < + FormulaPolicy, SeriesOrder, Spheroid, CalculationType + >(s.model()); + } +}; + +template +struct strategy_converter> +{ + struct altered_strategy + : strategies::relate::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + > + { + altered_strategy(Spheroid const& spheroid) + : strategies::relate::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(spheroid) + {} + + template + auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) const + { + return strategy::covered_by::geographic_point_box_by_side + < + FormulaPolicy, Spheroid, CalculationType + >(this->model()); + } + + template + auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) const + { + return strategy::within::geographic_point_box_by_side + < + FormulaPolicy, Spheroid, CalculationType + >(this->model()); + } + }; + + static auto get(strategy::covered_by::geographic_point_box_by_side const& s) + { + return altered_strategy(s.model()); + } + + static auto get(strategy::within::geographic_point_box_by_side const& s) + { + return altered_strategy(s.model()); + } +}; + +template +struct strategy_converter> + : strategy_converter> +{}; + +// TEMP used in distance segment/box +template +struct strategy_converter> +{ + static auto get(strategy::side::geographic const& s) + { + return strategies::relate::geographic + < + FormulaPolicy, + strategy::default_order::value, + Spheroid, + CalculationType + >(s.model()); + } +}; + + +} // namespace services + +}} // namespace strategies::relate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_RELATE_GEOGRAPHIC_HPP diff --git a/include/boost/geometry/strategies/relate/services.hpp b/include/boost/geometry/strategies/relate/services.hpp new file mode 100644 index 000000000..cf9f7c97d --- /dev/null +++ b/include/boost/geometry/strategies/relate/services.hpp @@ -0,0 +1,57 @@ +// Boost.Geometry + +// Copyright (c) 2020, 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_RELATE_SERVICES_HPP +#define BOOST_GEOMETRY_STRATEGIES_RELATE_SERVICES_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + + +namespace strategies { namespace relate { + +namespace services +{ + +template +< + typename Geometry1, + typename Geometry2, + typename CSTag1 = typename geometry::cs_tag::type, + typename CSTag2 = typename geometry::cs_tag::type +> +struct default_strategy +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this Geometry's coordinate system.", + Geometry1, Geometry2, CSTag1, CSTag2); +}; + +template +struct strategy_converter +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this Strategy.", + Strategy); +}; + + +} // namespace services + +}} // namespace strategies::relate + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_RELATE_SERVICES_HPP diff --git a/include/boost/geometry/strategies/relate/spherical.hpp b/include/boost/geometry/strategies/relate/spherical.hpp new file mode 100644 index 000000000..b6f3252e2 --- /dev/null +++ b/include/boost/geometry/strategies/relate/spherical.hpp @@ -0,0 +1,404 @@ +// Boost.Geometry + +// Copyright (c) 2020, 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_RELATE_SPHERICAL_HPP +#define BOOST_GEOMETRY_STRATEGIES_RELATE_SPHERICAL_HPP + + +// TEMP - move to strategy +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace relate +{ + + +template +class spherical + : public strategies::detail::spherical_base +{ + using base_t = strategies::detail::spherical_base; + +public: + // area + + template + auto area(Geometry const&) const + { + return strategy::area::spherical(1.0); + } + + // covered_by + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::spherical_point_box(); + } + + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::spherical_box_box(); + } + + // disjoint + + template + static auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::disjoint::spherical_box_box(); + } + + template + static auto disjoint(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_box::value + > * = nullptr) + { + // NOTE: Inconsistent name. + return strategy::disjoint::segment_box_spherical(); + } + + // envelope + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_point_t * = nullptr) + { + return strategy::envelope::spherical_point(); + } + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_multi_point_t * = nullptr) + { + return strategy::envelope::spherical_multipoint(); + } + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_box_t * = nullptr) + { + return strategy::envelope::spherical_box(); + } + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_segment_t * = nullptr) + { + return strategy::envelope::spherical_segment(); + } + + template + static auto envelope(Geometry const&, Box const&, + typename util::enable_if_polysegmental_t * = nullptr) + { + return strategy::envelope::spherical(); + } + + // expand + + template + static auto expand(Box const&, Geometry const&, + typename util::enable_if_point_t * = nullptr) + { + return strategy::expand::spherical_point(); + } + + template + static auto expand(Box const&, Geometry const&, + typename util::enable_if_box_t * = nullptr) + { + return strategy::expand::spherical_box(); + } + + template + static auto expand(Box const&, Geometry const&, + typename util::enable_if_segment_t * = nullptr) + { + return strategy::expand::spherical_segment(); + } + + // relate + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) + { + return strategy::within::spherical_point_point(); + } + + template + static auto relate(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr) + { + return strategy::within::spherical_winding(); + } + + //template + static auto relate(/*Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + ( util::is_linear::value + || util::is_polygonal::value ) + && ( util::is_linear::value + || util::is_polygonal::value ) + > * = nullptr*/) + { + return strategy::intersection::spherical_segments(); + } + + // side + + static auto side() + { + return strategy::side::spherical_side_formula(); + } + + // within + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::spherical_point_box(); + } + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_box::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::spherical_box_box(); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::relate::spherical<>; +}; + +template +struct default_strategy +{ + using type = strategies::relate::spherical<>; +}; + +template +struct default_strategy +{ + using type = strategies::relate::spherical<>; +}; + + +template <> +struct strategy_converter +{ + static auto get(strategy::within::spherical_point_point const& ) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::within::spherical_point_box const&) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::covered_by::spherical_point_box const&) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::covered_by::spherical_box_box const&) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::disjoint::spherical_box_box const&) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::disjoint::segment_box_spherical const&) + { + return strategies::relate::spherical<>(); + } +}; + +template <> +struct strategy_converter +{ + static auto get(strategy::within::spherical_box_box const&) + { + return strategies::relate::spherical<>(); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::within::spherical_winding const& ) + { + return strategies::relate::spherical(); + } +}; + +template +struct strategy_converter> +{ + static auto get(strategy::intersection::spherical_segments const& ) + { + return strategies::relate::spherical(); + } +}; + +template +struct strategy_converter> +{ + struct altered_strategy + : strategies::relate::spherical + { + template + static auto covered_by(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::covered_by::spherical_point_box_by_side(); + } + + template + static auto within(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_box::value + > * = nullptr) + { + return strategy::within::spherical_point_box_by_side(); + } + }; + + static auto get(strategy::covered_by::spherical_point_box_by_side const&) + { + return altered_strategy(); + } + + static auto get(strategy::within::spherical_point_box_by_side const&) + { + return altered_strategy(); + } +}; + +template +struct strategy_converter> + : strategy_converter> +{}; + +// TEMP used in distance segment/box +template +struct strategy_converter> +{ + static auto get(strategy::side::spherical_side_formula const& ) + { + return strategies::relate::spherical(); + } +}; + + +} // namespace services + +}} // namespace strategies::relate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_RELATE_SPHERICAL_HPP diff --git a/include/boost/geometry/strategies/spherical.hpp b/include/boost/geometry/strategies/spherical.hpp index 30501a4e2..3f40189fc 100644 --- a/include/boost/geometry/strategies/spherical.hpp +++ b/include/boost/geometry/strategies/spherical.hpp @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include namespace boost { namespace geometry diff --git a/include/boost/geometry/strategies/spherical/distance_segment_box.hpp b/include/boost/geometry/strategies/spherical/distance_segment_box.hpp index c8bd5c34e..0e9414122 100644 --- a/include/boost/geometry/strategies/spherical/distance_segment_box.hpp +++ b/include/boost/geometry/strategies/spherical/distance_segment_box.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include // spherical #include diff --git a/include/boost/geometry/strategies/spherical/index.hpp b/include/boost/geometry/strategies/spherical/index.hpp deleted file mode 100644 index 909f1ed8d..000000000 --- a/include/boost/geometry/strategies/spherical/index.hpp +++ /dev/null @@ -1,199 +0,0 @@ -// Boost.Geometry Index -// -// R-tree strategies -// -// Copyright (c) 2019-2020, Oracle and/or its affiliates. -// 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_STRATEGIES_SPHERICAL_INDEX_HPP -#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_INDEX_HPP - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - - -namespace boost { namespace geometry { namespace strategy { namespace index -{ - -template -< - typename CalculationType = void -> -struct spherical -{ - typedef spherical_tag cs_tag; - - typedef geometry::strategy::envelope::spherical_point envelope_point_strategy_type; - typedef geometry::strategy::envelope::spherical_box envelope_box_strategy_type; - typedef geometry::strategy::envelope::spherical_segment - < - CalculationType - > envelope_segment_strategy_type; - - static inline envelope_segment_strategy_type get_envelope_segment_strategy() - { - return envelope_segment_strategy_type(); - } - - typedef geometry::strategy::expand::spherical_point expand_point_strategy_type; - typedef geometry::strategy::expand::spherical_box expand_box_strategy_type; - typedef geometry::strategy::expand::spherical_segment - < - CalculationType - > expand_segment_strategy_type; - - static inline expand_segment_strategy_type get_expand_segment_strategy() - { - return expand_segment_strategy_type(); - } - - typedef geometry::strategy::covered_by::spherical_point_box covered_by_point_box_strategy_type; - typedef geometry::strategy::covered_by::spherical_box_box covered_by_box_box_strategy_type; - typedef geometry::strategy::within::spherical_point_point within_point_point_strategy_type; - //typedef geometry::strategy::within::spherical_point_box within_point_box_strategy_type; - //typedef geometry::strategy::within::spherical_box_box within_box_box_strategy_type; - - // used in equals(Seg, Seg) but only to get_point_in_point_strategy() - typedef geometry::strategy::intersection::spherical_segments - < - CalculationType - > relate_segment_segment_strategy_type; - - static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy() - { - return relate_segment_segment_strategy_type(); - } - - // used in intersection_content - typedef geometry::strategy::disjoint::spherical_box_box disjoint_box_box_strategy_type; - - typedef geometry::strategy::distance::comparable::haversine - < - double, - CalculationType - > comparable_distance_point_point_strategy_type; - - static inline comparable_distance_point_point_strategy_type get_comparable_distance_point_point_strategy() - { - return comparable_distance_point_point_strategy_type(); - } - - // TODO: Comparable version should be possible - typedef geometry::strategy::distance::cross_track_point_box - < - CalculationType, - geometry::strategy::distance::haversine - > comparable_distance_point_box_strategy_type; - - static inline comparable_distance_point_box_strategy_type get_comparable_distance_point_box_strategy() - { - return comparable_distance_point_box_strategy_type(); - } - - // TODO: Radius is not needed in comparable strategy - typedef geometry::strategy::distance::comparable::cross_track - < - CalculationType, - geometry::strategy::distance::comparable::haversine - > comparable_distance_point_segment_strategy_type; - - static inline comparable_distance_point_segment_strategy_type get_comparable_distance_point_segment_strategy() - { - return comparable_distance_point_segment_strategy_type(); - } - - // comparable? - typedef geometry::strategy::distance::spherical_segment_box - < - CalculationType, - geometry::strategy::distance::haversine - > comparable_distance_segment_box_strategy_type; - - static inline comparable_distance_segment_box_strategy_type get_comparable_distance_segment_box_strategy() - { - return comparable_distance_segment_box_strategy_type(); - } -}; - - -namespace services -{ - -template -struct default_strategy -{ - typedef spherical<> type; -}; - -template -struct default_strategy -{ - typedef spherical<> type; -}; - -template -struct default_strategy -{ - typedef spherical<> type; -}; - - -template -struct from_strategy > -{ - typedef strategy::index::spherical type; - - static inline type get(within::spherical_winding const&) - { - return type(); - } -}; - -// distance (MPt, MPt) -template -struct from_strategy > -{ - typedef strategy::index::spherical type; - - static inline type get(distance::comparable::haversine const&) - { - return type(); - } -}; - -// distance (MPt, Linear/Areal) -template -struct from_strategy > -{ - typedef strategy::index::spherical type; - - static inline type get(distance::comparable::cross_track const&) - { - return type(); - } -}; - - -} // namespace services - - -}}}} // namespace boost::geometry::strategy::index - -#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_INDEX_HPP diff --git a/include/boost/geometry/strategies/spherical/intersection.hpp b/include/boost/geometry/strategies/spherical/intersection.hpp index b02c9980d..c78c8a69e 100644 --- a/include/boost/geometry/strategies/spherical/intersection.hpp +++ b/include/boost/geometry/strategies/spherical/intersection.hpp @@ -886,8 +886,7 @@ private: template static inline bool equals_point_point(Point1 const& point1, Point2 const& point2) { - return detail::equals::equals_point_point(point1, point2, - point_in_point_strategy_type()); + return strategy::within::spherical_point_point::apply(point1, point2); } }; diff --git a/include/boost/geometry/strategies/spherical/io.hpp b/include/boost/geometry/strategies/spherical/io.hpp deleted file mode 100644 index d5ff5c36b..000000000 --- a/include/boost/geometry/strategies/spherical/io.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Boost.Geometry - -// Copyright (c) 2019, 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_EXTENSIONS_STRATEGIES_SPHERICAL_IO_HPP -#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_SPHERICAL_IO_HPP - - -#include - -#include -#include - - -namespace boost { namespace geometry -{ - -namespace strategy { namespace io -{ - -template -struct spherical -{ - typedef strategy::point_order::spherical point_order_strategy_type; - - static inline point_order_strategy_type get_point_order_strategy() - { - return point_order_strategy_type(); - } - - template - struct point_in_geometry_strategy - { - typedef strategy::within::spherical_winding - < - typename point_type::type, - typename point_type::type, - CalculationType - > type; - }; - - template - static inline typename point_in_geometry_strategy::type - get_point_in_geometry_strategy() - { - typedef typename point_in_geometry_strategy - < - Geometry1, Geometry2 - >::type strategy_type; - return strategy_type(); - } -}; - -namespace services -{ - -template <> -struct default_strategy -{ - typedef spherical<> type; -}; - -template <> -struct default_strategy -{ - typedef spherical<> type; -}; - -} // namespace services - -}} // namespace strategy::io - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_SPHERICAL_IO_HPP diff --git a/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp b/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp index 1b0216a76..b94a97ca5 100644 --- a/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp @@ -557,27 +557,13 @@ namespace services template struct default_strategy { - typedef within::detail::spherical_winding_base - < - typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type, - void - > type; + typedef within::spherical_winding<> type; }; template struct default_strategy { - typedef within::detail::spherical_winding_base - < - typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type, - void - > type; + typedef within::spherical_winding<> type; }; } // namespace services @@ -595,27 +581,13 @@ namespace strategy { namespace covered_by { namespace services template struct default_strategy { - typedef within::detail::spherical_winding_base - < - typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type, - void - > type; + typedef within::spherical_winding<> type; }; template struct default_strategy { - typedef within::detail::spherical_winding_base - < - typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type, - void - > type; + typedef within::spherical_winding<> type; }; }}} // namespace strategy::covered_by::services diff --git a/include/boost/geometry/strategies/strategies.hpp b/include/boost/geometry/strategies/strategies.hpp index f02b9adbe..f4398b195 100644 --- a/include/boost/geometry/strategies/strategies.hpp +++ b/include/boost/geometry/strategies/strategies.hpp @@ -35,7 +35,6 @@ #include #include #include // for backward compatibility -#include #include #include #include @@ -61,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -80,7 +78,6 @@ #include #include #include -#include #include #include #include @@ -100,7 +97,6 @@ #include #include //#include -#include #include //#include #include @@ -129,6 +125,7 @@ #include #include #include +#include #include #include diff --git a/include/boost/geometry/strategy/relate.hpp b/include/boost/geometry/strategy/relate.hpp new file mode 100644 index 000000000..6f9967082 --- /dev/null +++ b/include/boost/geometry/strategy/relate.hpp @@ -0,0 +1,175 @@ +// Boost.Geometry + +// Copyright (c) 2017-2020, Oracle and/or its affiliates. +// 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_STRATEGY_RELATE_HPP +#define BOOST_GEOMETRY_STRATEGY_RELATE_HPP + + +#include + +#include +#include +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategy +{ + +namespace point_in_geometry +{ + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template +< + typename Point, + typename Geometry, + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type +> +struct default_strategy + : strategy::within::services::default_strategy + < + Point, + Geometry + > +{ + typedef typename default_strategy::type within_strategy_type; + + typedef typename strategy::covered_by::services::default_strategy + < + Point, + Geometry + >::type covered_by_strategy_type; + + static const bool same_strategies = std::is_same::value; + BOOST_GEOMETRY_STATIC_ASSERT(same_strategies, + "Default within and covered_by strategies not compatible.", + within_strategy_type, covered_by_strategy_type); +}; + +template +struct default_strategy + : strategy::within::services::default_strategy +{}; + +template +struct default_strategy + : strategy::within::services::default_strategy +{}; + + +} // namespace services +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +} // namespace point_in_geometry + +namespace relate +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct default_intersection_strategy + : strategy::intersection::services::default_strategy + < + typename cs_tag::type + > +{}; + +template +struct default_point_in_geometry_strategy + : point_in_geometry::services::default_strategy + < + typename point_type::type, + Geometry + > +{}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template +< + typename Geometry1, + typename Geometry2, + int TopDim1 = geometry::topological_dimension::value, + int TopDim2 = geometry::topological_dimension::value +> +struct default_strategy +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for these types.", + Geometry1, Geometry2); +}; + +template +struct default_strategy + : detail::default_point_in_geometry_strategy +{}; + +template +struct default_strategy + : detail::default_point_in_geometry_strategy +{}; + +template +struct default_strategy + : detail::default_point_in_geometry_strategy +{}; + +template +struct default_strategy + : detail::default_intersection_strategy +{}; + +template +struct default_strategy + : detail::default_intersection_strategy +{}; + +template +struct default_strategy + : detail::default_intersection_strategy +{}; + +template +struct default_strategy + : detail::default_intersection_strategy +{}; + +} // namespace services +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +} // namespace relate + +} // namespace strategy + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGY_RELATE_HPP diff --git a/test/algorithms/buffer/buffer_multi_point.cpp b/test/algorithms/buffer/buffer_multi_point.cpp index d2dc1b39b..4b6839405 100644 --- a/test/algorithms/buffer/buffer_multi_point.cpp +++ b/test/algorithms/buffer/buffer_multi_point.cpp @@ -3,6 +3,10 @@ // Copyright (c) 2012-2019 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 Oracle and/or its affiliates. +// 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) @@ -80,10 +84,10 @@ void test_all() 115057490003226.125, ut_settings(1.0)); { - typename bg::strategy::area::services::default_strategy + typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag

::type - >::type area_strategy; + multi_point_type, multi_point_type + >::type strategy; multi_point_type g; bg::read_wkt(mysql_report_3, g); @@ -94,7 +98,7 @@ void test_all() distance_strategy(1), side_strategy, bg::strategy::buffer::point_circle(36), - area_strategy, + strategy, 1, 0, 3.12566719800474635, ut_settings(1.0)); } } diff --git a/test/algorithms/buffer/buffer_piece_border.cpp b/test/algorithms/buffer/buffer_piece_border.cpp index fd0e8f72d..9626d2bf9 100644 --- a/test/algorithms/buffer/buffer_piece_border.cpp +++ b/test/algorithms/buffer/buffer_piece_border.cpp @@ -103,10 +103,11 @@ Border setup_piece_border(Ring& ring, Ring& original, typedef typename bg::point_type::type point_type; - border.get_properties_of_border(false, point_type()); + bg::strategies::relate::cartesian<> strategy; - bg::strategy::side::side_by_triangle<> side_strategy; - border.get_properties_of_offsetted_ring_part(side_strategy); + border.get_properties_of_border(false, point_type(), strategy); + + border.get_properties_of_offsetted_ring_part(strategy); return border; } diff --git a/test/algorithms/buffer/test_buffer.hpp b/test/algorithms/buffer/test_buffer.hpp index 3f1581635..1042b3e03 100644 --- a/test/algorithms/buffer/test_buffer.hpp +++ b/test/algorithms/buffer/test_buffer.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2010-2019 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2016-2017. -// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2020. +// Modifications copyright (c) 2016-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -137,7 +137,7 @@ template typename DistanceStrategy, typename SideStrategy, typename PointStrategy, - typename AreaStrategy, + typename Strategy, typename Geometry > void test_buffer(std::string const& caseid, @@ -148,7 +148,7 @@ void test_buffer(std::string const& caseid, DistanceStrategy const& distance_strategy, SideStrategy const& side_strategy, PointStrategy const& point_strategy, - AreaStrategy const& area_strategy, + Strategy const& strategy, int expected_count, int expected_holes_count, expectation_limits const& expected_area, @@ -177,7 +177,7 @@ void test_buffer(std::string const& caseid, } else { - bg::envelope(geometry, envelope); + bg::envelope(geometry, envelope, strategy); } std::string join_name = JoinTestProperties::name(); @@ -233,20 +233,12 @@ void test_buffer(std::string const& caseid, typedef typename bg::point_type::type point_type; typedef typename bg::rescale_policy_type::type rescale_policy_type; - typedef typename bg::strategy::intersection::services::default_strategy - < - typename bg::cs_tag::type - >::type strategy_type; - typedef typename strategy_type::envelope_strategy_type envelope_strategy_type; - + // Enlarge the box to get a proper rescale policy bg::buffer(envelope, envelope, distance_strategy.max_distance(join_strategy, end_strategy)); - strategy_type strategy; rescale_policy_type rescale_policy - = bg::get_rescale_policy(envelope); - - envelope_strategy_type envelope_strategy; + = bg::get_rescale_policy(envelope, strategy); buffered.clear(); bg::detail::buffer::buffer_inserter(geometry, @@ -285,7 +277,7 @@ void test_buffer(std::string const& caseid, bg::model::box envelope_output; bg::assign_values(envelope_output, 0, 0, 1, 1); - bg::envelope(buffered, envelope_output, envelope_strategy); + bg::envelope(buffered, envelope_output, strategy); // std::cout << caseid << std::endl; // std::cout << "INPUT: " << bg::wkt(geometry) << std::endl; @@ -318,8 +310,7 @@ void test_buffer(std::string const& caseid, if (settings.test_area) { - typename bg::default_area_result::type area - = bg::area(buffered, area_strategy); + auto const area = bg::area(buffered, strategy); BOOST_CHECK_MESSAGE(expected_area.contains(area, settings.tolerance, settings.use_ln_area), "difference: " << caseid << std::setprecision(20) << " #area expected: " << expected_area @@ -376,14 +367,14 @@ void test_buffer(std::string const& caseid, bg::model::multi_polygon::type - >::type area_strategy; + Geometry, Geometry + >::type strategy; test_buffer(caseid, buffered, geometry, join_strategy, end_strategy, distance_strategy, side_strategy, point_strategy, - area_strategy, + strategy, -1, -1, expected_area, settings); } @@ -432,17 +423,17 @@ void test_one(std::string const& caseid, std::string const& wkt, bg::math::equals(distance_right, same_distance) ? distance_left : distance_right); - typename bg::strategy::area::services::default_strategy + typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type - >::type area_strategy; + Geometry, Geometry + >::type strategy; bg::model::multi_polygon buffered; test_buffer (caseid, buffered, g, join_strategy, end_strategy, distance_strategy, side_strategy, circle_strategy, - area_strategy, + strategy, expected_count, expected_holes_count, expected_area, settings); @@ -463,7 +454,7 @@ void test_one(std::string const& caseid, std::string const& wkt, (caseid + "_sym", buffered, g, join_strategy, end_strategy, sym_distance_strategy, side_strategy, circle_strategy, - area_strategy, + strategy, expected_count, expected_holes_count, expected_area, settings); diff --git a/test/algorithms/buffer/test_buffer_geo.hpp b/test/algorithms/buffer/test_buffer_geo.hpp index efeeee1e2..c7342716f 100644 --- a/test/algorithms/buffer/test_buffer_geo.hpp +++ b/test/algorithms/buffer/test_buffer_geo.hpp @@ -3,6 +3,10 @@ // Copyright (c) 2018-2019 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 Oracle and/or its affiliates. +// 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) @@ -44,11 +48,11 @@ void test_one_geo(std::string const& caseid, // Use Thomas strategy to calculate geographic area, because it is // the most precise (unless scale of buffer is only around 1 meter) - bg::strategy::area::geographic - < - bg::strategy::thomas, 5, - bg::srs::spheroid, long double - > area_strategy; + bg::strategies::relate::geographic + < + bg::strategy::thomas, 5, + bg::srs::spheroid, long double + > strategy; bg::model::multi_polygon buffer; @@ -56,7 +60,7 @@ void test_one_geo(std::string const& caseid, (caseid, buffer, input_geometry, join_strategy, end_strategy, distance_strategy, side_strategy, circle_strategy, - area_strategy, + strategy, expected_count, expected_holes_count, expected_area, settings); } diff --git a/test/algorithms/buffer/test_buffer_svg.hpp b/test/algorithms/buffer/test_buffer_svg.hpp index 2c7db78ce..9d0fb9f85 100644 --- a/test/algorithms/buffer/test_buffer_svg.hpp +++ b/test/algorithms/buffer/test_buffer_svg.hpp @@ -2,6 +2,11 @@ // Unit Test Helper // Copyright (c) 2010-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 Oracle and/or its affiliates. +// 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) @@ -207,7 +212,8 @@ private : } #endif - bg::model::ring const& corner = piece.m_piece_border.get_full_ring(); + // NOTE: ring is returned by copy here + auto const& corner = piece.m_piece_border.get_full_ring(); if (m_zoom && do_pieces) { diff --git a/test/algorithms/detail/sections/sectionalize.cpp b/test/algorithms/detail/sections/sectionalize.cpp index 48047f667..ce448a1fd 100644 --- a/test/algorithms/detail/sections/sectionalize.cpp +++ b/test/algorithms/detail/sections/sectionalize.cpp @@ -61,18 +61,23 @@ void test_sectionalize_part() sections_type sections; section_type section; - Geometry geometry; geometry.push_back(bg::make(1, 1)); bg::detail::no_rescale_policy rescale_policy; + typename bg::strategies::relate::services::default_strategy + < + Geometry, Geometry + >::type strategy; bg::ring_identifier ring_id; - sectionalize_part::apply(sections, geometry.begin(), geometry.end(), rescale_policy, ring_id, 10); + sectionalize_part::apply(sections, geometry.begin(), geometry.end(), + rescale_policy, strategy, ring_id, 10); // There should not yet be anything generated, because it is only ONE point geometry.push_back(bg::make(2, 2)); - sectionalize_part::apply(sections, geometry.begin(), geometry.end(), rescale_policy, ring_id, 10); + sectionalize_part::apply(sections, geometry.begin(), geometry.end(), + rescale_policy, strategy, ring_id, 10); } diff --git a/test/algorithms/overlay/get_turn_info.cpp b/test/algorithms/overlay/get_turn_info.cpp index 3835f6f47..a70093de4 100644 --- a/test/algorithms/overlay/get_turn_info.cpp +++ b/test/algorithms/overlay/get_turn_info.cpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017. -// Modifications copyright (c) 2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -25,6 +25,9 @@ #include #include +// TEMP +#include + #if defined(TEST_WITH_SVG) # include #endif @@ -74,9 +77,9 @@ void test_with_point(std::string const& caseid, P qj = bg::make

(qj_x, qj_y); P qk = bg::make

(qk_x, qk_y); - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag

::type + P, P >::type strategy_type; typedef typename bg::detail::no_rescale_policy rescale_policy_type; diff --git a/test/algorithms/overlay/get_turns.cpp b/test/algorithms/overlay/get_turns.cpp index 1b8d279b9..5db074ab3 100644 --- a/test/algorithms/overlay/get_turns.cpp +++ b/test/algorithms/overlay/get_turns.cpp @@ -64,9 +64,9 @@ struct test_get_turns { typedef typename bg::point_type::type point_type; - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + G1, G2 >::type strategy_type; typedef typename bg::rescale_policy_type::type diff --git a/test/algorithms/overlay/get_turns_linear_linear_geo.cpp b/test/algorithms/overlay/get_turns_linear_linear_geo.cpp index 4b3a22d47..de0d82b7f 100644 --- a/test/algorithms/overlay/get_turns_linear_linear_geo.cpp +++ b/test/algorithms/overlay/get_turns_linear_linear_geo.cpp @@ -21,7 +21,7 @@ void test_radian() typedef bg::model::multi_linestring mls; bg::srs::spheroid sph_wgs84(6378137.0, 6356752.3142451793); - boost::geometry::strategy::intersection::geographic_segments<> wgs84(sph_wgs84); + boost::geometry::strategies::relate::geographic<> wgs84(sph_wgs84); test_geometry( "LINESTRING(0 0, -3.14159265358979 0)", diff --git a/test/algorithms/overlay/overlay.cpp b/test/algorithms/overlay/overlay.cpp index f89bfabff..5d3c04b21 100644 --- a/test/algorithms/overlay/overlay.cpp +++ b/test/algorithms/overlay/overlay.cpp @@ -3,8 +3,8 @@ // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017. -// Modifications copyright (c) 2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -407,9 +407,9 @@ void test_overlay(std::string const& caseid, OverlayType > overlay; - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry, Geometry >::type strategy_type; strategy_type strategy; diff --git a/test/algorithms/overlay/select_rings.cpp b/test/algorithms/overlay/select_rings.cpp index af43328f5..89f43732f 100644 --- a/test/algorithms/overlay/select_rings.cpp +++ b/test/algorithms/overlay/select_rings.cpp @@ -2,8 +2,8 @@ // // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // -// This file was modified by Oracle on 2017. -// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // // Use, modification and distribution is subject to the Boost Software License, @@ -57,9 +57,9 @@ void test_geometry(std::string const& wkt1, std::string const& wkt2, map_type selected; std::map empty; - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry1, Geometry2 >::type strategy_type; bg::detail::overlay::select_rings(geometry1, geometry2, empty, selected, strategy_type()); diff --git a/test/algorithms/overlay/self_intersection_points.cpp b/test/algorithms/overlay/self_intersection_points.cpp index 2d7a42039..16b8ed24f 100644 --- a/test/algorithms/overlay/self_intersection_points.cpp +++ b/test/algorithms/overlay/self_intersection_points.cpp @@ -5,8 +5,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2017. -// Modifications copyright (c) 2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -55,9 +55,9 @@ static void test_self_intersection_points(std::string const& case_id, { typedef typename bg::point_type::type point_type; //typedef typename bg::rescale_policy_type::type rescale_policy_type; - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry, Geometry >::type strategy_type; typedef bg::detail::no_rescale_policy rescale_policy_type; typedef bg::detail::overlay::turn_info turn_info; @@ -91,6 +91,12 @@ static void test_self_intersection_points(std::string const& case_id, BOOST_CHECK_EQUAL(expected_count, n); + typedef typename bg::rescale_policy_type::type + default_rescale_policy_type; + + default_rescale_policy_type default_robust_policy + = bg::get_rescale_policy(geometry, strategy); + if (expected_count > 0) { BOOST_CHECK_EQUAL(bg::intersects(geometry), true); @@ -99,7 +105,7 @@ static void test_self_intersection_points(std::string const& case_id, { try { - boost::geometry::detail::overlay::has_self_intersections(geometry); + bg::detail::overlay::has_self_intersections(geometry, strategy, default_robust_policy); BOOST_CHECK_MESSAGE(false, "Case " << case_id << " there are no self-intersections detected!"); } catch(...) @@ -113,7 +119,7 @@ static void test_self_intersection_points(std::string const& case_id, { try { - boost::geometry::detail::overlay::has_self_intersections(geometry); + bg::detail::overlay::has_self_intersections(geometry, strategy, default_robust_policy); } catch(...) { diff --git a/test/algorithms/overlay/sort_by_side.cpp b/test/algorithms/overlay/sort_by_side.cpp index 1e0f42258..92e613cbd 100644 --- a/test/algorithms/overlay/sort_by_side.cpp +++ b/test/algorithms/overlay/sort_by_side.cpp @@ -4,8 +4,8 @@ // Copyright (c) 2016 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2017, 2019. -// Modifications copyright (c) 2017, 2019, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -165,7 +165,7 @@ std::vector apply_overlay( // Gather cluster properties, with test option return ::gather_cluster_properties( clusters, turns, bg::detail::overlay::operation_from_overlay::value, - geometry1, geometry2, strategy.get_side_strategy()); + geometry1, geometry2, strategy.side()); } @@ -197,9 +197,9 @@ void test_sort_by_side(std::string const& case_id, rescale_policy_type robust_policy = bg::get_rescale_policy(g1, g2); - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry, Geometry >::type strategy_type; strategy_type strategy; diff --git a/test/algorithms/overlay/sort_by_side_basic.cpp b/test/algorithms/overlay/sort_by_side_basic.cpp index f37bd38c6..9d2b01370 100644 --- a/test/algorithms/overlay/sort_by_side_basic.cpp +++ b/test/algorithms/overlay/sort_by_side_basic.cpp @@ -4,8 +4,8 @@ // Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2017. -// Modifications copyright (c) 2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2020. +// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -90,14 +90,14 @@ std::vector apply_get_turns(std::string const& case_id, // Define sorter, sorting counter-clockwise such that polygons are on the // right side - typedef typename Strategy::side_strategy_type side_strategy; + typedef decltype(strategy.side()) side_strategy; typedef bg::detail::overlay::sort_by_side::side_sorter < false, false, overlay_union, point_type, side_strategy, std::less > sbs_type; - sbs_type sbs(strategy.get_side_strategy()); + sbs_type sbs(strategy.side()); std::cout << "Case: " << case_id << std::endl; @@ -256,9 +256,9 @@ void test_basic(std::string const& case_id, rescale_policy_type robust_policy = bg::get_rescale_policy(g1, g2); - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + multi_polygon, multi_polygon >::type strategy_type; strategy_type strategy; diff --git a/test/algorithms/overlay/test_get_turns.hpp b/test/algorithms/overlay/test_get_turns.hpp index f761a996d..1a4afc6b5 100644 --- a/test/algorithms/overlay/test_get_turns.hpp +++ b/test/algorithms/overlay/test_get_turns.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2014, 2016, 2017, 2018. -// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2016-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -259,9 +259,9 @@ void check_geometry_range(Geometry1 const& g1, std::string const& wkt2, Expected const& expected) { - typename bg::strategy::intersection::services::default_strategy + typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry1, Geometry2 >::type strategy; check_geometry_range(g1, g2, wkt1, wkt2, expected, strategy); diff --git a/test/algorithms/set_operations/check_turn_less.hpp b/test/algorithms/set_operations/check_turn_less.hpp index 0e9984d4a..deb619d3c 100644 --- a/test/algorithms/set_operations/check_turn_less.hpp +++ b/test/algorithms/set_operations/check_turn_less.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2015, 2019, Oracle and/or its affiliates. +// Copyright (c) 2015-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -73,9 +73,9 @@ struct check_turn_less static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2) { - typedef typename bg::strategy::intersection::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < - typename bg::cs_tag::type + Geometry1, Geometry2 >::type strategy_type; typedef bg::detail::no_rescale_policy robust_policy_type; diff --git a/test/algorithms/set_operations/difference/difference_tupled.cpp b/test/algorithms/set_operations/difference/difference_tupled.cpp index 7b3d9e65d..30ecd2d50 100644 --- a/test/algorithms/set_operations/difference/difference_tupled.cpp +++ b/test/algorithms/set_operations/difference/difference_tupled.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/test/algorithms/set_operations/intersection/intersection_tupled.cpp b/test/algorithms/set_operations/intersection/intersection_tupled.cpp index 3501fcaf5..5957355b3 100644 --- a/test/algorithms/set_operations/intersection/intersection_tupled.cpp +++ b/test/algorithms/set_operations/intersection/intersection_tupled.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/test/algorithms/set_operations/sym_difference/sym_difference_tupled.cpp b/test/algorithms/set_operations/sym_difference/sym_difference_tupled.cpp index 0bfa98bcd..0985ed410 100644 --- a/test/algorithms/set_operations/sym_difference/sym_difference_tupled.cpp +++ b/test/algorithms/set_operations/sym_difference/sym_difference_tupled.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp index 22b01cab2..b3685843f 100644 --- a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp +++ b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, 2019, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -65,11 +65,13 @@ private: < typename Turns, typename LinearGeometry1, - typename LinearGeometry2 + typename LinearGeometry2, + typename Strategy > static inline void compute_turns(Turns& turns, LinearGeometry1 const& linear1, - LinearGeometry2 const& linear2) + LinearGeometry2 const& linear2, + Strategy const& strategy) { turns.clear(); bg_detail::relate::turns::get_turns @@ -77,12 +79,14 @@ private: LinearGeometry1, LinearGeometry2, bg_detail::get_turns::get_turn_info_type - < - LinearGeometry1, - LinearGeometry2, - assign_policy - > - >::apply(turns, linear1, linear2); + < + LinearGeometry1, + LinearGeometry2, + assign_policy + > + >::apply(turns, linear1, linear2, + bg_detail::get_turns::no_interrupt_policy(), + strategy); } @@ -92,7 +96,7 @@ public: static inline void apply(Linear1 const& lineargeometry1, Linear2 const& lineargeometry2) { - typedef typename bg::strategy::relate::services::default_strategy + typedef typename bg::strategies::relate::services::default_strategy < Linear1, Linear2 >::type strategy_type; @@ -123,8 +127,9 @@ public: boost::geometry::reverse(linear2_reverse); turns_container turns_all, rturns_all; - compute_turns(turns_all, linear1, linear2); - compute_turns(rturns_all, linear1, linear2_reverse); + strategy_type strategy; + compute_turns(turns_all, linear1, linear2, strategy); + compute_turns(rturns_all, linear1, linear2_reverse, strategy); turns_container turns_wo_cont(turns_all); turns_container rturns_wo_cont(rturns_all); diff --git a/test/algorithms/set_operations/union/union_tupled.cpp b/test/algorithms/set_operations/union/union_tupled.cpp index 494fe1677..72e8acd7e 100644 --- a/test/algorithms/set_operations/union/union_tupled.cpp +++ b/test/algorithms/set_operations/union/union_tupled.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/test/algorithms/within/within.cpp b/test/algorithms/within/within.cpp index 9cd98628e..cd5591754 100644 --- a/test/algorithms/within/within.cpp +++ b/test/algorithms/within/within.cpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014, 2015, 2016, 2018. -// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -112,16 +112,12 @@ void test_strategy() bg::strategy::within::cartesian_point_box()); BOOST_CHECK_EQUAL(r, true); - r = bg::within(b, b, - bg::strategy::within::box_in_box()); - BOOST_CHECK_EQUAL(r, true); - r = bg::within(b0, b0, - bg::strategy::within::box_in_box()); + bg::strategy::within::cartesian_box_box()); BOOST_CHECK_EQUAL(r, false); r = bg::within(p, b, - bg::strategy::within::point_in_box_by_side<>()); + bg::strategy::within::cartesian_point_box_by_side<>()); BOOST_CHECK_EQUAL(r, true); } diff --git a/test/algorithms/within/within_sph_geo.cpp b/test/algorithms/within/within_sph_geo.cpp index 128f24dda..56d49334f 100644 --- a/test/algorithms/within/within_sph_geo.cpp +++ b/test/algorithms/within/within_sph_geo.cpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2016-2018 Oracle and/or its affiliates. +// Copyright (c) 2016-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -19,7 +19,12 @@ void test_point_box_by_side() // Test spherical boxes // See also http://www.gcmap.com/mapui?P=1E45N-19E45N-19E55N-1E55N-1E45N,10E55.1N,10E45.1N typedef bg::model::box box_t; - bg::strategy::within::point_in_box_by_side<> by_side; + std::conditional_t + < + std::is_same::type, bg::geographic_tag>::value, + bg::strategy::within::geographic_point_box_by_side<>, + bg::strategy::within::spherical_point_box_by_side<> + > by_side; box_t box; bg::read_wkt("POLYGON((1 45,19 55))", box); BOOST_CHECK_EQUAL(bg::within(Point(10, 55.1), box, by_side), true); @@ -32,6 +37,14 @@ void test_point_box_by_side() BOOST_CHECK_EQUAL(bg::within(Point(10, 45.3), box, by_side), false); BOOST_CHECK_EQUAL(bg::within(Point(10, 45.4), box, by_side), true); + bg::strategy::within::spherical_point_box s; + BOOST_CHECK_EQUAL(bg::within(Point(10, 44.9), box, s), false); + BOOST_CHECK_EQUAL(bg::within(Point(10, 45.0), box, s), false); + BOOST_CHECK_EQUAL(bg::within(Point(10, 45.1), box, s), true); + BOOST_CHECK_EQUAL(bg::within(Point(10, 49.9), box, s), true); + BOOST_CHECK_EQUAL(bg::within(Point(10, 55.0), box, s), false); + BOOST_CHECK_EQUAL(bg::within(Point(10, 55.1), box, s), false); + // By default Box is not a polygon in spherical CS, edges are defined by small circles BOOST_CHECK_EQUAL(bg::within(Point(10, 45.1), box), true); BOOST_CHECK_EQUAL(bg::within(Point(10, 54.9), box), true); diff --git a/test/cs_undefined/index.cpp b/test/cs_undefined/index.cpp index 008187044..5908aa248 100644 --- a/test/cs_undefined/index.cpp +++ b/test/cs_undefined/index.cpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2019, Oracle and/or its affiliates. +// Copyright (c) 2019-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -18,6 +18,10 @@ #include +#include +#include +#include + #include namespace bgi = boost::geometry::index; @@ -67,35 +71,35 @@ int test_main(int, char*[]) { geom g; - rtree_test(g.pt, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::cartesian<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::cartesian<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::cartesian<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::cartesian<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::spherical<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::spherical<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::spherical<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::spherical<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.pt, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.b, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::geographic<> >()); - rtree_test(g.s, bgi::parameters, bg::strategy::index::geographic<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.pt, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.b, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::geographic<> >()); + rtree_test(g.s, bgi::parameters, bg::strategies::index::geographic<> >()); return 0; } diff --git a/test/iterators/segment_iterator.cpp b/test/iterators/segment_iterator.cpp index f867a524d..fdfe90ef5 100644 --- a/test/iterators/segment_iterator.cpp +++ b/test/iterators/segment_iterator.cpp @@ -47,6 +47,11 @@ #include +// TEMP +#include +#include +#include + #include #include diff --git a/test/strategies/point_in_box.cpp b/test/strategies/point_in_box.cpp index 8ab354cd8..f246923c9 100644 --- a/test/strategies/point_in_box.cpp +++ b/test/strategies/point_in_box.cpp @@ -3,8 +3,8 @@ // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014. -// Modifications copyright (c) 2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -21,7 +21,7 @@ void test_box_of(std::string const& wkt_point, std::string const& wkt_box, bool expected_within, bool expected_covered_by) { typedef bg::model::box box_type; - + Point point; box_type box; bg::read_wkt(wkt_point, point); @@ -32,22 +32,26 @@ void test_box_of(std::string const& wkt_point, std::string const& wkt_box, BOOST_CHECK_EQUAL(detected_within, expected_within); BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); - // Also test with the non-default agnostic side version - namespace wi = bg::strategy::within; - wi::point_in_box_by_side<> within_strategy; - wi::point_in_box_by_side covered_by_strategy; + // Also test with the non-default side version + bg::strategy::within::cartesian_point_box_by_side<> within_strategy; + bg::strategy::covered_by::cartesian_point_box_by_side<> covered_by_strategy; detected_within = bg::within(point, box, within_strategy); detected_covered_by = bg::covered_by(point, box, covered_by_strategy); BOOST_CHECK_EQUAL(detected_within, expected_within); BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); + // BREAKING CHANGE: + // Internally the strategies are converted to umbrella strategy + // and then the umbrella strategy is used to get correct strategy + // for corresponding algorithm. + // PREVIOUSLY: // We might exchange strategies between within/covered by. // So the lines below might seem confusing, but are as intended - detected_within = bg::covered_by(point, box, within_strategy); - detected_covered_by = bg::within(point, box, covered_by_strategy); - BOOST_CHECK_EQUAL(detected_within, expected_within); - BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); + //detected_within = bg::covered_by(point, box, within_strategy); + //detected_covered_by = bg::within(point, box, covered_by_strategy); + //BOOST_CHECK_EQUAL(detected_within, expected_within); + //BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by); // Finally we call the strategies directly detected_within = within_strategy.apply(point, box); diff --git a/test/strategies/segment_intersection.cpp b/test/strategies/segment_intersection.cpp index c0230aabf..ebda67ef7 100644 --- a/test/strategies/segment_intersection.cpp +++ b/test/strategies/segment_intersection.cpp @@ -24,12 +24,6 @@ #include #include - -#include -#include - -#include - #include #include @@ -37,6 +31,12 @@ #include #include +#include + +#include +#include + + BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian); diff --git a/test/strategies/test_within.hpp b/test/strategies/test_within.hpp index ae9b06dde..f4280beb0 100644 --- a/test/strategies/test_within.hpp +++ b/test/strategies/test_within.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014, 2019. -// Modifications copyright (c) 2014, 2019 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -31,6 +31,10 @@ #include #include +// TEMP +#include +#include +#include #include #include diff --git a/test/strategies/winding.cpp b/test/strategies/winding.cpp index ba4ec1b75..fb10d461c 100644 --- a/test/strategies/winding.cpp +++ b/test/strategies/winding.cpp @@ -3,8 +3,8 @@ // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014, 2016. -// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2020. +// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -24,7 +24,7 @@ void test_cartesian() std::string const triangle = "POLYGON((0 0,0 4,6 0,0 0))"; std::string const with_hole = "POLYGON((0 0,0 3,3 3,3 0,0 0),(1 1,2 1,2 2,1 2,1 1))"; - bg::strategy::within::winding s; + bg::strategy::within::cartesian_winding<> s; test_geometry("b1", "POINT(1 1)", box, s, true); @@ -78,7 +78,7 @@ void test_spherical() typedef bg::model::point > point; typedef bg::model::polygon polygon; - bg::strategy::within::winding s; + bg::strategy::within::spherical_winding<> s; // Ticket #9354 From 1186dedeb8bbff7cd6d1c1362676a02ca4608e8a Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 22 Oct 2020 03:33:09 +0200 Subject: [PATCH 19/55] [strategies] Add ctors, store substrategy and propagate radius in distance segment/box strategy. --- .../spherical/distance_segment_box.hpp | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/include/boost/geometry/strategies/spherical/distance_segment_box.hpp b/include/boost/geometry/strategies/spherical/distance_segment_box.hpp index 0e9414122..0e5af0f6f 100644 --- a/include/boost/geometry/strategies/spherical/distance_segment_box.hpp +++ b/include/boost/geometry/strategies/spherical/distance_segment_box.hpp @@ -224,9 +224,9 @@ struct spherical_segment_box typedef Strategy type; }; - inline typename distance_pp_strategy::type get_distance_pp_strategy() const + inline Strategy get_distance_pp_strategy() const { - return typename distance_pp_strategy::type(); + return m_strategy; } // point-segment strategy getters struct distance_ps_strategy @@ -236,7 +236,7 @@ struct spherical_segment_box inline typename distance_ps_strategy::type get_distance_ps_strategy() const { - return typename distance_ps_strategy::type(); + return typename distance_ps_strategy::type(m_strategy.radius()); } struct distance_pb_strategy @@ -246,7 +246,7 @@ struct spherical_segment_box inline typename distance_pb_strategy::type get_distance_pb_strategy() const { - return typename distance_pb_strategy::type(); + return typename distance_pb_strategy::type(m_strategy.radius()); } // TODO: why is the Radius not propagated above? @@ -265,6 +265,19 @@ struct spherical_segment_box return equals_point_point_strategy_type(); } + // constructors + + inline spherical_segment_box() + {} + + explicit inline spherical_segment_box(typename Strategy::radius_type const& r) + : m_strategy(r) + {} + + inline spherical_segment_box(Strategy const& s) + : m_strategy(s) + {} + // methods template Date: Thu, 22 Oct 2020 03:35:45 +0200 Subject: [PATCH 20/55] [strategies] Add getters in global umbrella strategies and simplify implementation. --- .../geometry/strategies/area/geographic.hpp | 3 +- .../geometry/strategies/area/spherical.hpp | 3 +- .../boost/geometry/strategies/cartesian.hpp | 73 +-------- include/boost/geometry/strategies/detail.hpp | 23 ++- .../strategies/envelope/cartesian.hpp | 30 +--- .../strategies/envelope/geographic.hpp | 31 +--- .../strategies/envelope/spherical.hpp | 50 ++---- .../geometry/strategies/expand/cartesian.hpp | 3 +- .../geometry/strategies/expand/geographic.hpp | 3 +- .../geometry/strategies/expand/spherical.hpp | 27 +++- .../boost/geometry/strategies/geographic.hpp | 82 +--------- .../geometry/strategies/index/cartesian.hpp | 1 - .../geometry/strategies/index/geographic.hpp | 2 +- .../geometry/strategies/index/spherical.hpp | 148 +++++++++++------- .../geometry/strategies/relate/cartesian.hpp | 70 +-------- .../geometry/strategies/relate/geographic.hpp | 83 +--------- .../geometry/strategies/relate/spherical.hpp | 98 +++--------- .../boost/geometry/strategies/spherical.hpp | 84 ++-------- 18 files changed, 220 insertions(+), 594 deletions(-) diff --git a/include/boost/geometry/strategies/area/geographic.hpp b/include/boost/geometry/strategies/area/geographic.hpp index 4c04da7be..5f9e1dab7 100644 --- a/include/boost/geometry/strategies/area/geographic.hpp +++ b/include/boost/geometry/strategies/area/geographic.hpp @@ -30,7 +30,8 @@ template typename Spheroid = srs::spheroid, typename CalculationType = void > -class geographic : strategies::detail::geographic_base +class geographic + : public strategies::detail::geographic_base { using base_t = strategies::detail::geographic_base; diff --git a/include/boost/geometry/strategies/area/spherical.hpp b/include/boost/geometry/strategies/area/spherical.hpp index 2486abb7d..8194aeb00 100644 --- a/include/boost/geometry/strategies/area/spherical.hpp +++ b/include/boost/geometry/strategies/area/spherical.hpp @@ -28,7 +28,8 @@ template typename RadiusTypeOrSphere = double, typename CalculationType = void > -class spherical : strategies::detail::spherical_base +class spherical + : public strategies::detail::spherical_base { using base_t = strategies::detail::spherical_base; diff --git a/include/boost/geometry/strategies/cartesian.hpp b/include/boost/geometry/strategies/cartesian.hpp index 9ba28fb2c..102a1ecfd 100644 --- a/include/boost/geometry/strategies/cartesian.hpp +++ b/include/boost/geometry/strategies/cartesian.hpp @@ -28,74 +28,17 @@ namespace strategies template -struct cartesian : strategies::detail::cartesian_base +class cartesian + // derived from the umbrella strategy defining the most strategies + : public strategies::index::cartesian { - // area +public: - template - static auto area(Geometry const&) + // point_order + + static auto point_order() { - return strategy::area::cartesian(); - } - - // envelope - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::envelope::cartesian_point(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_multi_point_t * = nullptr) - { - return strategy::envelope::cartesian_multipoint(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::envelope::cartesian_box(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::envelope::cartesian_segment(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_polysegmental_t * = nullptr) - { - return strategy::envelope::cartesian(); - } - - // expand - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::cartesian_point(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::cartesian_box(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::expand::cartesian_segment(); + return strategy::point_order::cartesian(); } }; diff --git a/include/boost/geometry/strategies/detail.hpp b/include/boost/geometry/strategies/detail.hpp index 360b7ccfb..cdb4581b9 100644 --- a/include/boost/geometry/strategies/detail.hpp +++ b/include/boost/geometry/strategies/detail.hpp @@ -47,10 +47,7 @@ struct cartesian_base : umbrella_strategy typedef cartesian_tag cs_tag; }; -template -< - typename RadiusTypeOrSphere -> +template class spherical_base : umbrella_strategy { protected: @@ -80,18 +77,32 @@ public: } protected: + radius_type const& radius() const + { + return m_radius; + } + radius_type m_radius; }; template <> class spherical_base : umbrella_strategy { +protected: + typedef double radius_type; + public: typedef spherical_tag cs_tag; - srs::sphere model() const + srs::sphere model() const { - return srs::sphere(1.0); + return srs::sphere(1.0); + } + +protected: + radius_type radius() const + { + return 1.0; } }; diff --git a/include/boost/geometry/strategies/envelope/cartesian.hpp b/include/boost/geometry/strategies/envelope/cartesian.hpp index 2fee1ece0..3bce5dbc3 100644 --- a/include/boost/geometry/strategies/envelope/cartesian.hpp +++ b/include/boost/geometry/strategies/envelope/cartesian.hpp @@ -19,12 +19,9 @@ #include #include -#include // TEMP -#include -#include // TEMP - #include #include +#include namespace boost { namespace geometry @@ -34,7 +31,8 @@ namespace strategies { namespace envelope { template -struct cartesian : strategies::detail::cartesian_base +struct cartesian + : strategies::expand::cartesian { template static auto envelope(Geometry const&, Box const&, @@ -70,28 +68,6 @@ struct cartesian : strategies::detail::cartesian_base { return strategy::envelope::cartesian(); } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::cartesian_point(); - } - - // TEMP - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::cartesian_box(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::expand::cartesian_segment(); - } }; diff --git a/include/boost/geometry/strategies/envelope/geographic.hpp b/include/boost/geometry/strategies/envelope/geographic.hpp index 236ac6e15..26e1eea70 100644 --- a/include/boost/geometry/strategies/envelope/geographic.hpp +++ b/include/boost/geometry/strategies/envelope/geographic.hpp @@ -19,6 +19,7 @@ #include // TEMP #include +#include namespace boost { namespace geometry @@ -33,9 +34,10 @@ template typename Spheroid = srs::spheroid, typename CalculationType = void > -class geographic : strategies::detail::geographic_base +class geographic + : public strategies::expand::geographic { - using base_t = strategies::detail::geographic_base; + using base_t = strategies::expand::geographic; public: geographic() @@ -86,31 +88,6 @@ public: FormulaPolicy, Spheroid, CalculationType >(base_t::m_spheroid); } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::spherical_point(); - } - - // TEMP - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::spherical_box(); - } - - template - auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) const - { - return strategy::expand::geographic_segment - < - FormulaPolicy, Spheroid, CalculationType - >(base_t::m_spheroid); - } }; diff --git a/include/boost/geometry/strategies/envelope/spherical.hpp b/include/boost/geometry/strategies/envelope/spherical.hpp index 5d2f5cfea..f9e2f1352 100644 --- a/include/boost/geometry/strategies/envelope/spherical.hpp +++ b/include/boost/geometry/strategies/envelope/spherical.hpp @@ -19,12 +19,9 @@ #include #include -#include // TEMP -#include -#include // TEMP - #include #include +#include namespace boost { namespace geometry @@ -33,15 +30,14 @@ namespace boost { namespace geometry namespace strategies { namespace envelope { -template -< - typename CalculationType = void -> -class spherical : strategies::detail::spherical_base +#ifndef DOXYGEN_NO_DETAIL +namespace detail { - using base_t = strategies::detail::spherical_base; -public: +template +struct spherical + : strategies::expand::detail::spherical +{ template static auto envelope(Geometry const&, Box const&, typename util::enable_if_point_t * = nullptr) @@ -76,31 +72,19 @@ public: { return strategy::envelope::spherical(); } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::spherical_point(); - } - - // TEMP - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::spherical_box(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::expand::spherical_segment(); - } }; +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +template +class spherical + : public strategies::envelope::detail::spherical +{}; + + namespace services { diff --git a/include/boost/geometry/strategies/expand/cartesian.hpp b/include/boost/geometry/strategies/expand/cartesian.hpp index 3f73edf07..0c830e7a3 100644 --- a/include/boost/geometry/strategies/expand/cartesian.hpp +++ b/include/boost/geometry/strategies/expand/cartesian.hpp @@ -30,7 +30,8 @@ namespace strategies { namespace expand template -struct cartesian : strategies::detail::cartesian_base +struct cartesian + : strategies::detail::cartesian_base { template static auto expand(Box const&, Geometry const&, diff --git a/include/boost/geometry/strategies/expand/geographic.hpp b/include/boost/geometry/strategies/expand/geographic.hpp index f07c63622..0812979cd 100644 --- a/include/boost/geometry/strategies/expand/geographic.hpp +++ b/include/boost/geometry/strategies/expand/geographic.hpp @@ -31,7 +31,8 @@ template typename Spheroid = srs::spheroid, typename CalculationType = void > -class geographic : strategies::detail::geographic_base +class geographic + : public strategies::detail::geographic_base { using base_t = strategies::detail::geographic_base; diff --git a/include/boost/geometry/strategies/expand/spherical.hpp b/include/boost/geometry/strategies/expand/spherical.hpp index c81417f23..363a9691f 100644 --- a/include/boost/geometry/strategies/expand/spherical.hpp +++ b/include/boost/geometry/strategies/expand/spherical.hpp @@ -28,15 +28,16 @@ namespace boost { namespace geometry namespace strategies { namespace expand { -template -< - typename CalculationType = void -> -class spherical : strategies::detail::spherical_base -{ - using base_t = strategies::detail::spherical_base; -public: +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + + +template +struct spherical + : strategies::detail::spherical_base +{ template static auto expand(Box const&, Geometry const&, typename util::enable_if_point_t * = nullptr) @@ -60,6 +61,16 @@ public: }; +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +template +class spherical + : public strategies::expand::detail::spherical +{}; + + namespace services { diff --git a/include/boost/geometry/strategies/geographic.hpp b/include/boost/geometry/strategies/geographic.hpp index 92dc66f1b..2c59fccb4 100644 --- a/include/boost/geometry/strategies/geographic.hpp +++ b/include/boost/geometry/strategies/geographic.hpp @@ -34,9 +34,11 @@ template typename Spheroid = srs::spheroid, typename CalculationType = void > -class geographic : strategies::detail::geographic_base +class geographic + // derived from the umbrella strategy defining the most strategies + : public index::geographic { - using base_t = strategies::detail::geographic_base; + using base_t = index::geographic; public: geographic() @@ -47,81 +49,9 @@ public: : base_t(spheroid) {} - // area - - template - auto area(Geometry const&) const + auto point_order() const { - return strategy::area::geographic - < - FormulaPolicy, SeriesOrder, Spheroid, CalculationType - >(base_t::m_spheroid); - } - - // envelope - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::envelope::spherical_point(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_multi_point_t * = nullptr) - { - return strategy::envelope::spherical_multipoint(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::envelope::spherical_box(); - } - - template - auto envelope(Geometry const&, Box const&, - typename util::enable_if_segment_t * = nullptr) const - { - return strategy::envelope::geographic_segment - < - FormulaPolicy, Spheroid, CalculationType - >(base_t::m_spheroid); - } - - template - auto envelope(Geometry const&, Box const&, - typename util::enable_if_polysegmental_t * = nullptr) const - { - return strategy::envelope::geographic - < - FormulaPolicy, Spheroid, CalculationType - >(base_t::m_spheroid); - } - - // expand - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::spherical_point(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::spherical_box(); - } - - template - auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) const - { - return strategy::expand::geographic_segment + return strategy::point_order::geographic < FormulaPolicy, Spheroid, CalculationType >(base_t::m_spheroid); diff --git a/include/boost/geometry/strategies/index/cartesian.hpp b/include/boost/geometry/strategies/index/cartesian.hpp index 52352e2de..fe5d018e2 100644 --- a/include/boost/geometry/strategies/index/cartesian.hpp +++ b/include/boost/geometry/strategies/index/cartesian.hpp @@ -17,7 +17,6 @@ #include #include - #include diff --git a/include/boost/geometry/strategies/index/geographic.hpp b/include/boost/geometry/strategies/index/geographic.hpp index 75f9f5ecf..8723eaf12 100644 --- a/include/boost/geometry/strategies/index/geographic.hpp +++ b/include/boost/geometry/strategies/index/geographic.hpp @@ -12,9 +12,9 @@ #include - #include +// TEMP - move to strategy #include #include #include diff --git a/include/boost/geometry/strategies/index/spherical.hpp b/include/boost/geometry/strategies/index/spherical.hpp index 938d9cf3a..5ffd6ea24 100644 --- a/include/boost/geometry/strategies/index/spherical.hpp +++ b/include/boost/geometry/strategies/index/spherical.hpp @@ -11,8 +11,13 @@ #define BOOST_GEOMETRY_STRATEGIES_INDEX_SPHERICAL_HPP -#include +// TEMP - move to strategy +#include +#include +#include +#include +#include #include @@ -22,97 +27,130 @@ namespace boost { namespace geometry namespace strategies { namespace index { -template -class spherical - : public relate::spherical +#ifndef DOXYGEN_NO_DETAIL +namespace detail { + +template +class spherical + : public strategies::relate::detail::spherical +{ + using base_t = strategies::relate::detail::spherical; + public: template - static auto comparable_distance(Geometry1 const&, Geometry2 const&, - std::enable_if_t - < - util::is_pointlike::value - && util::is_pointlike::value - > * = nullptr) + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_pointlike::value + && util::is_pointlike::value + > * = nullptr) const { - //return geometry::strategy::distance::comparable::haversine(); - return geometry::strategy::distance::haversine(); + //return geometry::strategy::distance::comparable::haversine + return geometry::strategy::distance::haversine + < + typename base_t::radius_type, CalculationType + >(base_t::radius()); } template - static auto comparable_distance(Geometry1 const&, Geometry2 const&, - std::enable_if_t - < - (util::is_pointlike::value - && util::is_segment::value) - || (util::is_segment::value - && util::is_pointlike::value) - > * = nullptr) + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_segment::value) + || (util::is_segment::value + && util::is_pointlike::value) + > * = nullptr) const { //return geometry::strategy::distance::comparable::cross_track return geometry::strategy::distance::cross_track < CalculationType, - //geometry::strategy::distance::comparable::haversine - geometry::strategy::distance::haversine - >(); + //geometry::strategy::distance::comparable::haversine + geometry::strategy::distance::haversine + < + typename base_t::radius_type, CalculationType + > + >(base_t::radius()); } template - static auto comparable_distance(Geometry1 const&, Geometry2 const&, - std::enable_if_t - < - (util::is_pointlike::value - && util::is_box::value) - || (util::is_box::value - && util::is_pointlike::value) - > * = nullptr) + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_pointlike::value + && util::is_box::value) + || (util::is_box::value + && util::is_pointlike::value) + > * = nullptr) const { //return geometry::strategy::distance::comparable::cross_track_point_box return geometry::strategy::distance::cross_track_point_box < CalculationType, - //geometry::strategy::distance::comparable::haversine - geometry::strategy::distance::haversine - >(); + //geometry::strategy::distance::comparable::haversine + geometry::strategy::distance::haversine + < + typename base_t::radius_type, CalculationType + > + >(base_t::radius()); } template - static auto comparable_distance(Geometry1 const&, Geometry2 const&, - std::enable_if_t - < - (util::is_segment::value - && util::is_box::value) - || (util::is_box::value - && util::is_segment::value) - > * = nullptr) + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + (util::is_segment::value + && util::is_box::value) + || (util::is_box::value + && util::is_segment::value) + > * = nullptr) const { return geometry::strategy::distance::spherical_segment_box < CalculationType, - //geometry::strategy::distance::comparable::haversine - geometry::strategy::distance::haversine - >(); + //geometry::strategy::distance::comparable::haversine + geometry::strategy::distance::haversine + < + typename base_t::radius_type, CalculationType + > + // TODO: + >(/*base_t::radius()*/); } template - static auto comparable_distance(Geometry1 const&, Geometry2 const&, - std::enable_if_t - < - util::is_segment::value - && util::is_segment::value - > * = nullptr) + auto comparable_distance(Geometry1 const&, Geometry2 const&, + std::enable_if_t + < + util::is_segment::value + && util::is_segment::value + > * = nullptr) const { - return strategy::distance::projected_point + //return geometry::strategy::distance::comparable::cross_track + return geometry::strategy::distance::cross_track < CalculationType, - //strategy::distance::comparable::pythagoras - strategy::distance::pythagoras - >(); + //geometry::strategy::distance::comparable::haversine + geometry::strategy::distance::haversine + < + typename base_t::radius_type, CalculationType + > + >(base_t::radius()); } }; +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +template +class spherical + : public strategies::index::detail::spherical +{}; + + namespace services { diff --git a/include/boost/geometry/strategies/relate/cartesian.hpp b/include/boost/geometry/strategies/relate/cartesian.hpp index ca2763736..16c6853a3 100644 --- a/include/boost/geometry/strategies/relate/cartesian.hpp +++ b/include/boost/geometry/strategies/relate/cartesian.hpp @@ -21,17 +21,11 @@ #include #include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include #include @@ -44,7 +38,7 @@ namespace strategies { namespace relate template class cartesian - : public strategies::detail::cartesian_base + : public strategies::envelope::cartesian { public: //area @@ -104,66 +98,6 @@ public: return strategy::disjoint::segment_box(); } - // envelope - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::envelope::cartesian_point(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_multi_point_t * = nullptr) - { - return strategy::envelope::cartesian_multipoint(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::envelope::cartesian_box(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::envelope::cartesian_segment(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_polysegmental_t * = nullptr) - { - return strategy::envelope::cartesian(); - } - - // expand - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::cartesian_point(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::cartesian_box(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::expand::cartesian_segment(); - } - // relate template diff --git a/include/boost/geometry/strategies/relate/geographic.hpp b/include/boost/geometry/strategies/relate/geographic.hpp index d01a43099..4c9f81d1e 100644 --- a/include/boost/geometry/strategies/relate/geographic.hpp +++ b/include/boost/geometry/strategies/relate/geographic.hpp @@ -11,24 +11,18 @@ #define BOOST_GEOMETRY_STRATEGIES_RELATE_GEOGRAPHIC_HPP -// TEMP +// TEMP - move to strategy #include #include #include #include #include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include #include @@ -48,9 +42,9 @@ template typename CalculationType = void > class geographic - : public strategies::detail::geographic_base + : public strategies::envelope::geographic { - using base_t = strategies::detail::geographic_base; + using base_t = strategies::envelope::geographic; public: geographic() @@ -125,75 +119,6 @@ public: >(base_t::m_spheroid); } - // envelope - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::envelope::spherical_point(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_multi_point_t * = nullptr) - { - return strategy::envelope::spherical_multipoint(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::envelope::spherical_box(); - } - - template - auto envelope(Geometry const&, Box const&, - typename util::enable_if_segment_t * = nullptr) const - { - return strategy::envelope::geographic_segment - < - FormulaPolicy, Spheroid, CalculationType - >(base_t::m_spheroid); - } - - template - auto envelope(Geometry const&, Box const&, - typename util::enable_if_polysegmental_t * = nullptr) const - { - return strategy::envelope::geographic - < - FormulaPolicy, Spheroid, CalculationType - >(base_t::m_spheroid); - } - - // expand - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::spherical_point(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::spherical_box(); - } - - template - auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) const - { - return strategy::expand::geographic_segment - < - FormulaPolicy, Spheroid, CalculationType - >(base_t::m_spheroid); - } - // relate template diff --git a/include/boost/geometry/strategies/relate/spherical.hpp b/include/boost/geometry/strategies/relate/spherical.hpp index b6f3252e2..265de7a61 100644 --- a/include/boost/geometry/strategies/relate/spherical.hpp +++ b/include/boost/geometry/strategies/relate/spherical.hpp @@ -19,17 +19,11 @@ #include #include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include #include @@ -40,20 +34,28 @@ namespace boost { namespace geometry namespace strategies { namespace relate { - -template -class spherical - : public strategies::detail::spherical_base +#ifndef DOXYGEN_NO_DETAIL +namespace detail { - using base_t = strategies::detail::spherical_base; + +template +class spherical + : public strategies::envelope::detail::spherical +{ + using base_t = strategies::envelope::detail::spherical; public: + // area template auto area(Geometry const&) const { - return strategy::area::spherical(1.0); + return strategy::area::spherical + < + typename base_t::radius_type, + CalculationType + >(base_t::radius()); } // covered_by @@ -105,66 +107,6 @@ public: return strategy::disjoint::segment_box_spherical(); } - // envelope - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::envelope::spherical_point(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_multi_point_t * = nullptr) - { - return strategy::envelope::spherical_multipoint(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::envelope::spherical_box(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::envelope::spherical_segment(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_polysegmental_t * = nullptr) - { - return strategy::envelope::spherical(); - } - - // expand - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::spherical_point(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::spherical_box(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::expand::spherical_segment(); - } - // relate template @@ -236,6 +178,16 @@ public: }; +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +template +class spherical + : public strategies::relate::detail::spherical +{}; + + namespace services { diff --git a/include/boost/geometry/strategies/spherical.hpp b/include/boost/geometry/strategies/spherical.hpp index 3f40189fc..a110f9f85 100644 --- a/include/boost/geometry/strategies/spherical.hpp +++ b/include/boost/geometry/strategies/spherical.hpp @@ -32,89 +32,31 @@ template typename RadiusTypeOrSphere = double, typename CalculationType = void > -class spherical : strategies::detail::spherical_base +class spherical + // derived from the umbrella strategy defining the most strategies + : public strategies::index::detail::spherical { - using base_t = strategies::detail::spherical_base; + using base_t = strategies::index::detail::spherical; public: - spherical() - : base_t() - {} + spherical() = default; template explicit spherical(RadiusOrSphere const& radius_or_sphere) - : base_t(radius_or_sphere) - {} - - // area - - template - auto area(Geometry const&) const + //: base_t(radius_or_sphere) { - return strategy::area::spherical + // TODO: pass into the constructor + base_t::m_radius = strategy_detail::get_radius < - typename base_t::radius_type, CalculationType - >(base_t::m_radius); + RadiusOrSphere + >::apply(radius_or_sphere); } - // envelope + // point_order - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_point_t * = nullptr) + static auto point_order() { - return strategy::envelope::spherical_point(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_multi_point_t * = nullptr) - { - return strategy::envelope::spherical_multipoint(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::envelope::spherical_box(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::envelope::spherical_segment(); - } - - template - static auto envelope(Geometry const&, Box const&, - typename util::enable_if_polysegmental_t * = nullptr) - { - return strategy::envelope::spherical(); - } - - // expand - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_point_t * = nullptr) - { - return strategy::expand::spherical_point(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_box_t * = nullptr) - { - return strategy::expand::spherical_box(); - } - - template - static auto expand(Box const&, Geometry const&, - typename util::enable_if_segment_t * = nullptr) - { - return strategy::expand::spherical_segment(); + return strategy::point_order::spherical(); } }; From b0e3c6723a1afe0015aad1557567a47d66f0c9c6 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Mon, 26 Oct 2020 15:18:59 +0200 Subject: [PATCH 21/55] [strategies] [convex_hull] Inherit base class in public mode --- include/boost/geometry/strategies/convex_hull/cartesian.hpp | 2 +- include/boost/geometry/strategies/convex_hull/geographic.hpp | 2 +- include/boost/geometry/strategies/convex_hull/spherical.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/geometry/strategies/convex_hull/cartesian.hpp b/include/boost/geometry/strategies/convex_hull/cartesian.hpp index 4f4dc2778..1bef4e389 100644 --- a/include/boost/geometry/strategies/convex_hull/cartesian.hpp +++ b/include/boost/geometry/strategies/convex_hull/cartesian.hpp @@ -22,7 +22,7 @@ namespace strategies { namespace convex_hull { template -class cartesian : strategies::detail::cartesian_base +class cartesian : public strategies::detail::cartesian_base { public: static auto side() diff --git a/include/boost/geometry/strategies/convex_hull/geographic.hpp b/include/boost/geometry/strategies/convex_hull/geographic.hpp index 751ef1dd0..f80e1c29d 100644 --- a/include/boost/geometry/strategies/convex_hull/geographic.hpp +++ b/include/boost/geometry/strategies/convex_hull/geographic.hpp @@ -28,7 +28,7 @@ template typename Spheroid = srs::spheroid, typename CalculationType = void > -class geographic : strategies::detail::geographic_base +class geographic : public strategies::detail::geographic_base { using base_t = strategies::detail::geographic_base; diff --git a/include/boost/geometry/strategies/convex_hull/spherical.hpp b/include/boost/geometry/strategies/convex_hull/spherical.hpp index cfbdb978b..0eec8ee82 100644 --- a/include/boost/geometry/strategies/convex_hull/spherical.hpp +++ b/include/boost/geometry/strategies/convex_hull/spherical.hpp @@ -23,7 +23,7 @@ namespace strategies { namespace convex_hull { template -class spherical : strategies::detail::spherical_base +class spherical : public strategies::detail::spherical_base { public: static auto side() From 470e9e1bcec4ed99851769188e339c2987bdd4b9 Mon Sep 17 00:00:00 2001 From: Vissarion Fisikopoulos Date: Fri, 6 Nov 2020 12:08:08 +0200 Subject: [PATCH 22/55] [tests] Add tests regarding accuracy in cartesian area computations --- test/algorithms/area/area.cpp | 65 ++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/test/algorithms/area/area.cpp b/test/algorithms/area/area.cpp index 14e11680a..367cb4292 100644 --- a/test/algorithms/area/area.cpp +++ b/test/algorithms/area/area.cpp @@ -27,14 +27,15 @@ #include #include +#include + #include #include //#define BOOST_GEOMETRY_TEST_DEBUG +#include #include -#include - template void test_polygon() { @@ -186,23 +187,59 @@ struct precise_cartesian : bg::strategies::detail::cartesian_base } }; -void test_inaccurate_cases() +void test_accurate_sum_strategy() { typedef bg::model::point point_type; + typedef bg::model::point + < + boost::multiprecision::cpp_dec_float_50, + 2, + bg::cs::cartesian + > mp_point_type; - bg::model::polygon poly; + auto const poly0_string = "POLYGON((0 0,0 1,1 0,0 0))"; - bg::read_wkt("POLYGON((0.10000000000000001 0.10000000000000001,\ - 0.20000000000000001 0.20000000000000004,\ - 0.79999999999999993 0.80000000000000004,\ - 1.267650600228229e30 1.2676506002282291e30,\ - 0.10000000000000001 0.10000000000000001))", poly); + bg::model::polygon poly0; + bg::read_wkt(poly0_string, poly0); - double inaccurate = bg::area(poly); - double accurate = bg::area(poly, precise_cartesian()); + BOOST_CHECK_CLOSE(bg::area(poly0), 0.5, 0.0001); + BOOST_CHECK_CLOSE(bg::area(poly0, precise_cartesian()), 0.5, 0.0001); - BOOST_CHECK_CLOSE(inaccurate, 0, 0.0001); - BOOST_CHECK_CLOSE(accurate, -0.315, 0.0001); + bg::model::polygon mp_poly0; + bg::read_wkt(poly0_string, mp_poly0); + + BOOST_CHECK_CLOSE(bg::area(mp_poly0), 0.5, 0.0001); + + auto const poly1_string = "POLYGON((0.10000000000000001 0.10000000000000001,\ + 0.20000000000000001 0.20000000000000004,\ + 0.79999999999999993 0.80000000000000004,\ + 1.267650600228229e30 1.2676506002282291e30,\ + 0.10000000000000001 0.10000000000000001))"; + + bg::model::polygon poly1; + bg::read_wkt(poly1_string, poly1); + + BOOST_CHECK_CLOSE(bg::area(poly1), 0, 0.0001); + BOOST_CHECK_CLOSE(bg::area(poly1, precise_cartesian()), -0.315, 0.0001); + + bg::model::polygon mp_poly1; + bg::read_wkt(poly1_string, mp_poly1); + + BOOST_CHECK_CLOSE(bg::area(mp_poly1), 34720783012552.6, 0.0001); + + auto const poly2_string = "POLYGON((1.267650600228229e30 1.2676506002282291e30,\ + 0.8 0.8,0.2 0.2,0.1 0.1,1.267650600228229e30 1.2676506002282291e30))"; + + bg::model::polygon poly2; + bg::read_wkt(poly2_string, poly2); + + BOOST_CHECK_CLOSE(bg::area(poly2), 0, 0.0001); + BOOST_CHECK_CLOSE(bg::area(poly2, precise_cartesian()), 0.315, 0.0001); + + bg::model::polygon mp_poly2; + bg::read_wkt(poly2_string, mp_poly2); + + BOOST_CHECK_CLOSE(bg::area(mp_poly2), 35000000000000, 0.0001); } void test_variant() @@ -266,6 +303,8 @@ int test_main(int, char* []) test_variant(); + test_accurate_sum_strategy(); + // test_empty_input >(); return 0; From e84295005a27897f3446f85903b402114eddc0ee Mon Sep 17 00:00:00 2001 From: Vissarion Fisikopoulos Date: Fri, 6 Nov 2020 12:18:00 +0200 Subject: [PATCH 23/55] [strategies] Use auto and const in some places in cartesian area strategies --- include/boost/geometry/strategies/area/cartesian.hpp | 2 +- include/boost/geometry/strategy/cartesian/area.hpp | 3 +-- .../boost/geometry/strategy/cartesian/precise_area.hpp | 9 ++++----- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/boost/geometry/strategies/area/cartesian.hpp b/include/boost/geometry/strategies/area/cartesian.hpp index bd156c226..7dc0034c7 100644 --- a/include/boost/geometry/strategies/area/cartesian.hpp +++ b/include/boost/geometry/strategies/area/cartesian.hpp @@ -47,7 +47,7 @@ struct default_strategy template struct strategy_converter > { - static auto get(strategy::area::cartesian const& strategy) + static auto get(strategy::area::cartesian const&) { return strategies::area::cartesian(); } diff --git a/include/boost/geometry/strategy/cartesian/area.hpp b/include/boost/geometry/strategy/cartesian/area.hpp index 130df4651..a3fd514e7 100644 --- a/include/boost/geometry/strategy/cartesian/area.hpp +++ b/include/boost/geometry/strategy/cartesian/area.hpp @@ -114,8 +114,7 @@ public : } template - static inline typename result_type::type - result(state& st) + static inline auto result(state& st) { return st.area(); } diff --git a/include/boost/geometry/strategy/cartesian/precise_area.hpp b/include/boost/geometry/strategy/cartesian/precise_area.hpp index b0a3ba852..6c080af32 100644 --- a/include/boost/geometry/strategy/cartesian/precise_area.hpp +++ b/include/boost/geometry/strategy/cartesian/precise_area.hpp @@ -89,18 +89,17 @@ public : { typedef typename state::return_type return_type; - auto det = (return_type(get<0>(p1)) + return_type(get<0>(p2))) - * (return_type(get<1>(p1)) - return_type(get<1>(p2))); + auto const det = (return_type(get<0>(p1)) + return_type(get<0>(p2))) + * (return_type(get<1>(p1)) - return_type(get<1>(p2))); - auto res = boost::geometry::detail::precise_math::two_sum(st.sum1, det); + auto const res = boost::geometry::detail::precise_math::two_sum(st.sum1, det); st.sum1 = res[0]; st.sum2 += res[1]; } template - static inline typename result_type::type - result(state& st) + static inline auto result(state& st) { return st.area(); } From 4c6f569d2dedc5e6714a510d538b922273226dda Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 26 Nov 2020 04:59:40 +0100 Subject: [PATCH 24/55] [test] Include only necessary headers of Boost.Range. --- test/algorithms/distance/distance_brute_force.hpp | 7 +++++-- .../algorithms/distance/distance_geo_linear_box.cpp | 4 ++-- test/algorithms/distance/distance_se_geo_ar_ar.cpp | 4 ++-- test/algorithms/distance/distance_se_geo_l_ar.cpp | 4 ++-- test/algorithms/distance/distance_se_geo_l_l.cpp | 4 ++-- test/algorithms/distance/distance_se_geo_pl_ar.cpp | 4 ++-- test/algorithms/distance/distance_se_pl_pl.cpp | 4 +--- test/algorithms/set_operations/check_turn_less.hpp | 6 ++++-- .../set_operations/difference/test_difference.hpp | 5 +++-- .../difference/test_difference_linear_linear.hpp | 4 +++- .../intersection_areal_areal_linear.cpp | 9 ++++----- .../intersection/test_intersection.hpp | 5 +++-- .../test_intersection_linear_linear.hpp | 3 ++- .../test_sym_difference_linear_linear.hpp | 4 +++- .../set_operations/test_get_turns_ll_invariance.hpp | 6 +++++- .../set_operations/test_set_ops_linear_linear.hpp | 13 +++++++++---- .../set_operations/test_set_ops_pointlike.hpp | 3 +++ test/algorithms/set_operations/union/test_union.hpp | 7 +++++-- .../union/test_union_linear_linear.hpp | 4 +++- test/algorithms/test_is_valid.hpp | 7 +++++-- test/geometries/initialization.cpp | 6 +++++- test/test_geometries/all_custom_linestring.hpp | 8 +++++--- test/test_geometries/all_custom_polygon.hpp | 7 ++++--- test/test_geometries/all_custom_ring.hpp | 7 ++++--- test/test_geometries/wrapped_boost_array.hpp | 6 +++++- 25 files changed, 91 insertions(+), 50 deletions(-) diff --git a/test/algorithms/distance/distance_brute_force.hpp b/test/algorithms/distance/distance_brute_force.hpp index 82d0015b8..1e5b8b998 100644 --- a/test/algorithms/distance/distance_brute_force.hpp +++ b/test/algorithms/distance/distance_brute_force.hpp @@ -1,10 +1,11 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2014, 2018 Oracle and/or its affiliates. +// Copyright (c) 2014-2020 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, 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 @@ -16,7 +17,9 @@ #include #include -#include +#include +#include +#include #include #include diff --git a/test/algorithms/distance/distance_geo_linear_box.cpp b/test/algorithms/distance/distance_geo_linear_box.cpp index 4b6aacf30..0d22b5eb4 100644 --- a/test/algorithms/distance/distance_geo_linear_box.cpp +++ b/test/algorithms/distance/distance_geo_linear_box.cpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2017, 2018 Oracle and/or its affiliates. +// Copyright (c) 2017-2020 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 @@ -14,7 +15,6 @@ #define BOOST_TEST_MODULE test_distance_geographic_linear_areal #endif -#include #include #include diff --git a/test/algorithms/distance/distance_se_geo_ar_ar.cpp b/test/algorithms/distance/distance_se_geo_ar_ar.cpp index 4e25d7eac..d00517ddc 100644 --- a/test/algorithms/distance/distance_se_geo_ar_ar.cpp +++ b/test/algorithms/distance/distance_se_geo_ar_ar.cpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2017, 2018 Oracle and/or its affiliates. +// Copyright (c) 2017-2020 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 @@ -12,7 +13,6 @@ #define BOOST_TEST_MODULE test_distance_geographic_areal_areal #endif -#include #include #include diff --git a/test/algorithms/distance/distance_se_geo_l_ar.cpp b/test/algorithms/distance/distance_se_geo_l_ar.cpp index ae332a0da..a3263ea71 100644 --- a/test/algorithms/distance/distance_se_geo_l_ar.cpp +++ b/test/algorithms/distance/distance_se_geo_l_ar.cpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2017, 2018 Oracle and/or its affiliates. +// Copyright (c) 2017-2020 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 @@ -14,7 +15,6 @@ #define BOOST_TEST_MODULE test_distance_geographic_linear_areal #endif -#include #include #include diff --git a/test/algorithms/distance/distance_se_geo_l_l.cpp b/test/algorithms/distance/distance_se_geo_l_l.cpp index f287f5264..9ab18ebd5 100644 --- a/test/algorithms/distance/distance_se_geo_l_l.cpp +++ b/test/algorithms/distance/distance_se_geo_l_l.cpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2018 Oracle and/or its affiliates. +// Copyright (c) 2018-2020 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 @@ -14,7 +15,6 @@ #define BOOST_TEST_MODULE test_distance_geographic_linear_linear #endif -#include #include #include diff --git a/test/algorithms/distance/distance_se_geo_pl_ar.cpp b/test/algorithms/distance/distance_se_geo_pl_ar.cpp index 3a9d5f277..e51b4b7cf 100644 --- a/test/algorithms/distance/distance_se_geo_pl_ar.cpp +++ b/test/algorithms/distance/distance_se_geo_pl_ar.cpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2017-2018, Oracle and/or its affiliates. +// Copyright (c) 2017-2020, 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 @@ -14,7 +15,6 @@ #define BOOST_TEST_MODULE test_distance_geographic_pointlike_areal #endif -#include #include #include diff --git a/test/algorithms/distance/distance_se_pl_pl.cpp b/test/algorithms/distance/distance_se_pl_pl.cpp index 56c0a6e46..f06bd9a2e 100644 --- a/test/algorithms/distance/distance_se_pl_pl.cpp +++ b/test/algorithms/distance/distance_se_pl_pl.cpp @@ -1,7 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2014-2018, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -16,8 +16,6 @@ #define BOOST_TEST_MODULE test_distance_spherical_equatorial_pointlike_pointlike #endif -#include - #include #include diff --git a/test/algorithms/set_operations/check_turn_less.hpp b/test/algorithms/set_operations/check_turn_less.hpp index 147342a22..88f25ce23 100644 --- a/test/algorithms/set_operations/check_turn_less.hpp +++ b/test/algorithms/set_operations/check_turn_less.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2015, 2019, Oracle and/or its affiliates. +// Copyright (c) 2015-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -11,7 +11,9 @@ #ifndef BOOST_GEOMETRY_TEST_CHECK_TURN_LESS_HPP #define BOOST_GEOMETRY_TEST_CHECK_TURN_LESS_HPP -#include +#include +#include +#include #include "test_set_ops_linear_linear.hpp" diff --git a/test/algorithms/set_operations/difference/test_difference.hpp b/test/algorithms/set_operations/difference/test_difference.hpp index fdbd7d797..3c9ce08a5 100644 --- a/test/algorithms/set_operations/difference/test_difference.hpp +++ b/test/algorithms/set_operations/difference/test_difference.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2016, 2017, 2019. -// Modifications copyright (c) 2016-2019, Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2020. +// Modifications copyright (c) 2016-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -28,6 +28,7 @@ #include #include +#include #include #include diff --git a/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp b/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp index 14f6b039a..36e5459d7 100644 --- a/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp +++ b/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -13,6 +13,8 @@ #include +#include + #include #include "../test_set_ops_linear_linear.hpp" #include "../check_turn_less.hpp" diff --git a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp index c83c794c0..9a648f996 100644 --- a/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp +++ b/test/algorithms/set_operations/intersection/intersection_areal_areal_linear.cpp @@ -1,13 +1,14 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit test -// Copyright (c) 2015, Oracle and/or its affiliates. +// Copyright (c) 2015-2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, 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 -// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle - #ifndef BOOST_TEST_MODULE #define BOOST_TEST_MODULE test_intersection_linear_linear_areal #endif @@ -19,8 +20,6 @@ #include -#include - #include #include #include diff --git a/test/algorithms/set_operations/intersection/test_intersection.hpp b/test/algorithms/set_operations/intersection/test_intersection.hpp index 49c8aa4b0..12071d1b6 100644 --- a/test/algorithms/set_operations/intersection/test_intersection.hpp +++ b/test/algorithms/set_operations/intersection/test_intersection.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2016, 2017. -// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2020. +// Modifications copyright (c) 2016-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -18,6 +18,7 @@ #include #include +#include #include #include diff --git a/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp b/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp index f916b023c..0b47c4f75 100644 --- a/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp +++ b/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -13,6 +13,7 @@ #include +#include #include #include diff --git a/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp b/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp index 843345247..c850df8df 100644 --- a/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp +++ b/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -13,6 +13,8 @@ #include +#include + #include #include "../test_set_ops_linear_linear.hpp" #include diff --git a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp index 3fdc3a575..73253c3ac 100644 --- a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp +++ b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, 2019, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -13,6 +13,10 @@ #include +#include +#include +#include + #include #include diff --git a/test/algorithms/set_operations/test_set_ops_linear_linear.hpp b/test/algorithms/set_operations/test_set_ops_linear_linear.hpp index a8749b42b..d9bf57c2c 100644 --- a/test/algorithms/set_operations/test_set_ops_linear_linear.hpp +++ b/test/algorithms/set_operations/test_set_ops_linear_linear.hpp @@ -1,12 +1,13 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, 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 -// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle - #ifndef BOOST_GEOMETRY_TEST_SET_OPS_LINEAR_LINEAR_HPP #define BOOST_GEOMETRY_TEST_SET_OPS_LINEAR_LINEAR_HPP @@ -17,7 +18,11 @@ #include #include -#include +#include +#include +#include +#include +#include #include #include diff --git a/test/algorithms/set_operations/test_set_ops_pointlike.hpp b/test/algorithms/set_operations/test_set_ops_pointlike.hpp index 6908aa552..1cbe5de84 100644 --- a/test/algorithms/set_operations/test_set_ops_pointlike.hpp +++ b/test/algorithms/set_operations/test_set_ops_pointlike.hpp @@ -22,6 +22,9 @@ namespace bg = ::boost::geometry; #include #include #include +#include +#include +#include #include #include diff --git a/test/algorithms/set_operations/union/test_union.hpp b/test/algorithms/set_operations/union/test_union.hpp index 5d762e2b5..e17012265 100644 --- a/test/algorithms/set_operations/union/test_union.hpp +++ b/test/algorithms/set_operations/union/test_union.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2015, 2016, 2017. -// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2020. +// Modifications copyright (c) 2015-2020 Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include diff --git a/test/algorithms/set_operations/union/test_union_linear_linear.hpp b/test/algorithms/set_operations/union/test_union_linear_linear.hpp index e4357b603..8f09dc1c5 100644 --- a/test/algorithms/set_operations/union/test_union_linear_linear.hpp +++ b/test/algorithms/set_operations/union/test_union_linear_linear.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -13,6 +13,8 @@ #include +#include + #include #include "../test_set_ops_linear_linear.hpp" #include diff --git a/test/algorithms/test_is_valid.hpp b/test/algorithms/test_is_valid.hpp index df0be5b81..0b5f2aed5 100644 --- a/test/algorithms/test_is_valid.hpp +++ b/test/algorithms/test_is_valid.hpp @@ -1,7 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2020, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -17,7 +17,10 @@ #include #include -#include +#include +#include +#include +#include #include #include diff --git a/test/geometries/initialization.cpp b/test/geometries/initialization.cpp index 23dd11f52..c71ae302b 100644 --- a/test/geometries/initialization.cpp +++ b/test/geometries/initialization.cpp @@ -3,6 +3,10 @@ // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 Oracle and/or its affiliates. +// 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) @@ -10,7 +14,7 @@ #include #include -#include +#include #include #include diff --git a/test/test_geometries/all_custom_linestring.hpp b/test/test_geometries/all_custom_linestring.hpp index 133fb29a2..a2a3c4a12 100644 --- a/test/test_geometries/all_custom_linestring.hpp +++ b/test/test_geometries/all_custom_linestring.hpp @@ -2,6 +2,11 @@ // Unit Test // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 Oracle and/or its affiliates. +// 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) @@ -11,9 +16,6 @@ #include -#include - - #include #include #include diff --git a/test/test_geometries/all_custom_polygon.hpp b/test/test_geometries/all_custom_polygon.hpp index 1ce9286eb..7e385f971 100644 --- a/test/test_geometries/all_custom_polygon.hpp +++ b/test/test_geometries/all_custom_polygon.hpp @@ -3,6 +3,10 @@ // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 Oracle and/or its affiliates. +// 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) @@ -12,9 +16,6 @@ #include -#include - - #include #include #include diff --git a/test/test_geometries/all_custom_ring.hpp b/test/test_geometries/all_custom_ring.hpp index aa1d37cfe..e49acea9b 100644 --- a/test/test_geometries/all_custom_ring.hpp +++ b/test/test_geometries/all_custom_ring.hpp @@ -3,6 +3,10 @@ // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 Oracle and/or its affiliates. +// 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) @@ -12,9 +16,6 @@ #include -#include - - #include #include #include diff --git a/test/test_geometries/wrapped_boost_array.hpp b/test/test_geometries/wrapped_boost_array.hpp index 8f4d8e39b..9dc723589 100644 --- a/test/test_geometries/wrapped_boost_array.hpp +++ b/test/test_geometries/wrapped_boost_array.hpp @@ -3,6 +3,10 @@ // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2020. +// Modifications copyright (c) 2020 Oracle and/or its affiliates. +// 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) @@ -14,7 +18,7 @@ #include #include -#include +#include #include #include From 77838a899547b9f3714ea296106ef4ca83bd6be3 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 2 Dec 2020 10:35:39 +0100 Subject: [PATCH 25/55] [copy_segment_point] change implementation to allow also negative offsets, including unit test --- .../detail/overlay/copy_segment_point.hpp | 26 +++--- .../detail/overlay/segment_identifier.hpp | 2 +- test/algorithms/overlay/Jamfile | 1 + .../algorithms/overlay/copy_segment_point.cpp | 88 +++++++++++++++++++ 4 files changed, 102 insertions(+), 15 deletions(-) create mode 100644 test/algorithms/overlay/copy_segment_point.cpp diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp index 0e36cf004..49901a8b8 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -48,7 +47,7 @@ template ::type iterator; - geometry::ever_circling_iterator it(boost::begin(view), boost::end(view), - boost::begin(view) + seg_id.segment_index, true); + std::size_t const segment_count = boost::size(view) - 1; - for (signed_size_type i = 0; i < offset; ++i, ++it) - { - } + while (offset < 0) { offset += segment_count; } + + signed_size_type const target = (seg_id.segment_index + offset) % segment_count; + + geometry::convert(*(boost::begin(view) + target), point); - geometry::convert(*it, point); return true; } }; @@ -84,7 +82,7 @@ template inline bool copy_segment_point(Geometry const& geometry, - SegmentIdentifier const& seg_id, int offset, + SegmentIdentifier const& seg_id, signed_size_type offset, PointOut& point_out) { concepts::check(); @@ -316,7 +314,7 @@ template typename PointOut > inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geometry2, - SegmentIdentifier const& seg_id, int offset, + SegmentIdentifier const& seg_id, signed_size_type offset, PointOut& point_out) { concepts::check(); diff --git a/include/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp b/include/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp index b2d6d7f34..4d6c9fc02 100644 --- a/include/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp @@ -27,11 +27,11 @@ namespace boost { namespace geometry { - // Internal struct to uniquely identify a segment // on a linestring,ring // or polygon (needs ring_index) // or multi-geometry (needs multi_index) +// It is always used for clockwise indication (even if the original is anticlockwise) struct segment_identifier { inline segment_identifier() diff --git a/test/algorithms/overlay/Jamfile b/test/algorithms/overlay/Jamfile index be413b335..b9575595c 100644 --- a/test/algorithms/overlay/Jamfile +++ b/test/algorithms/overlay/Jamfile @@ -16,6 +16,7 @@ test-suite boost-geometry-algorithms-overlay : [ run assemble.cpp : : : : algorithms_assemble ] + [ run copy_segment_point.cpp : : : : algorithms_copy_segment_point ] [ run get_turn_info.cpp : : : : algorithms_get_turn_info ] [ run get_turns.cpp : : : : algorithms_get_turns ] [ run get_turns_areal_areal.cpp : : : : algorithms_get_turns_areal_areal ] diff --git a/test/algorithms/overlay/copy_segment_point.cpp b/test/algorithms/overlay/copy_segment_point.cpp new file mode 100644 index 000000000..101908906 --- /dev/null +++ b/test/algorithms/overlay/copy_segment_point.cpp @@ -0,0 +1,88 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2020 Barend Gehrels, Amsterdam, the Netherlands. + +// 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) + +#include + +#include + +#include +#include +#include +#include + +template +void test_basic(std::string const& case_id, int line, + std::string const& wkt, bg::segment_identifier const& id, + int offset, std::size_t expected_index) +{ + using point_type = bg::model::point; + using polygon_type = bg::model::polygon; + + polygon_type polygon; + bg::read_wkt(wkt, polygon); + + // Check the result + auto const& ring = bg::exterior_ring(polygon); + + point_type point; + bg::copy_segment_point(polygon, id, offset, point); + + // Sanity check + bool const expectation_in_range = expected_index < ring.size(); + BOOST_CHECK_MESSAGE(expectation_in_range, "Expectation out of range " << expected_index); + if (! expectation_in_range) + { + return; + } + + point_type const expected_point = ring[expected_index]; + + bool const equal = ! bg::disjoint(point, expected_point); + + BOOST_CHECK_MESSAGE(equal, "copy_segment_point: " << case_id + << " line " << line << " at index " << expected_index + << " not as expected: " + << bg::wkt(point) << " vs " << bg::wkt(expected_point)); +} + +template +void test_all(std::string const& case_id, std::string const& wkt) +{ + // Check zero offset, all segment ids + test_basic(case_id, __LINE__, wkt, {0, 0, -1, 0}, 0, 0); + test_basic(case_id, __LINE__, wkt, {0, 0, -1, 1}, 0, 1); + test_basic(case_id, __LINE__, wkt, {0, 0, -1, 2}, 0, 2); + test_basic(case_id, __LINE__, wkt, {0, 0, -1, 3}, 0, 3); + + // Check positive offsets, it should endlessly loop around, regardless of direction or closure + bg::segment_identifier const start{0, 0, -1, 0}; + test_basic(case_id, __LINE__, wkt, start, 1, 1); + test_basic(case_id, __LINE__, wkt, start, 2, 2); + test_basic(case_id, __LINE__, wkt, start, 3, 3); + test_basic(case_id, __LINE__, wkt, start, 4, 0); + test_basic(case_id, __LINE__, wkt, start, 5, 1); + test_basic(case_id, __LINE__, wkt, start, 6, 2); + test_basic(case_id, __LINE__, wkt, start, 7, 3); + + // Check negative offsets + test_basic(case_id, __LINE__, wkt, start, -1, 3); + test_basic(case_id, __LINE__, wkt, start, -2, 2); + test_basic(case_id, __LINE__, wkt, start, -3, 1); + test_basic(case_id, __LINE__, wkt, start, -4, 0); + test_basic(case_id, __LINE__, wkt, start, -5, 3); + test_basic(case_id, __LINE__, wkt, start, -6, 2); + test_basic(case_id, __LINE__, wkt, start, -7, 1); +} + +int test_main(int, char* []) +{ + test_all("closed", "POLYGON((0 2,1 2,1 1,0 1,0 2))"); + test_all("open", "POLYGON((0 2,1 2,1 1,0 1))"); + return 0; +} From abaa211d3ad890ab245cbd8d571ed3a777512944 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 2 Dec 2020 14:19:50 +0100 Subject: [PATCH 26/55] [sort_by_side] fix cases where the cluster point is approached by segments, but the last point before is colocated with the turn itself This fixes 50% of the errors currently found by recursive_polygons_buffer (when rescaling is turned off) --- .../detail/overlay/copy_segment_point.hpp | 1 - .../algorithms/detail/overlay/get_ring.hpp | 5 +- .../detail/overlay/handle_colocations.hpp | 2 +- .../detail/overlay/sort_by_side.hpp | 98 ++++++++++++++----- .../algorithms/detail/overlay/traversal.hpp | 6 +- .../buffer/buffer_multi_polygon.cpp | 12 +-- test/algorithms/buffer/test_buffer_svg.hpp | 2 +- test/algorithms/overlay/sort_by_side.cpp | 2 +- .../algorithms/overlay/sort_by_side_basic.cpp | 2 +- .../set_operations/difference/difference.cpp | 2 +- .../difference/difference_multi.cpp | 2 +- .../intersection/intersection_multi.cpp | 2 +- .../set_operations/union/union_multi.cpp | 2 +- 13 files changed, 90 insertions(+), 48 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp index 49901a8b8..10d12085b 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -397,7 +397,6 @@ inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geo } - }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp b/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp index 1cf5b1e9d..4931633b1 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp @@ -119,13 +119,12 @@ struct get_ring template -inline std::size_t segment_count_on_ring(Geometry const& geometry, - segment_identifier const& seg_id) +inline std::size_t segment_count_on_ring(Geometry const& geometry, segment_identifier const& seg_id) { typedef typename geometry::tag::type tag; ring_identifier const rid(0, seg_id.multi_index, seg_id.ring_index); // A closed polygon, a triangle of 4 points, including starting point, - // contains 3 segments. So handle as if closed and subtract one. + // contains 3 segments. So handle as if it is closed, and subtract one. return geometry::num_points(detail::overlay::get_ring::apply(rid, geometry), true) - 1; } diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp index 960e37032..8d6887d95 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp @@ -831,7 +831,7 @@ inline bool fill_sbs(Sbs& sbs, Point& turn_point, } for (int i = 0; i < 2; i++) { - sbs.add(turn.operations[i], turn_index, i, geometry1, geometry2, first); + sbs.add(turn, turn.operations[i], turn_index, i, geometry1, geometry2, first); first = false; } } diff --git a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp index 484a439e0..9b0726deb 100644 --- a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp @@ -66,6 +66,8 @@ struct ranked_point , seg_id(si) {} + using point_type = Point; + Point point; rank_type rank; signed_size_type zone; // index of closed zone, in uu turn there would be 2 zones @@ -252,12 +254,14 @@ public : , m_strategy(strategy) {} + template void add_segment_from(signed_size_type turn_index, int op_index, Point const& point_from, - operation_type op, segment_identifier const& si, + Operation const& op, bool is_origin) { - m_ranked_points.push_back(rp(point_from, turn_index, op_index, dir_from, op, si)); + m_ranked_points.push_back(rp(point_from, turn_index, op_index, + dir_from, op.operation, op.seg_id)); if (is_origin) { m_origin = point_from; @@ -265,24 +269,46 @@ public : } } + template void add_segment_to(signed_size_type turn_index, int op_index, Point const& point_to, - operation_type op, segment_identifier const& si) + Operation const& op) { - m_ranked_points.push_back(rp(point_to, turn_index, op_index, dir_to, op, si)); + m_ranked_points.push_back(rp(point_to, turn_index, op_index, + dir_to, op.operation, op.seg_id)); } + template void add_segment(signed_size_type turn_index, int op_index, Point const& point_from, Point const& point_to, - operation_type op, segment_identifier const& si, - bool is_origin) + Operation const& op, bool is_origin) { - add_segment_from(turn_index, op_index, point_from, op, si, is_origin); - add_segment_to(turn_index, op_index, point_to, op, si); + add_segment_from(turn_index, op_index, point_from, op, is_origin); + add_segment_to(turn_index, op_index, point_to, op); + } + + template + static inline bool approximately_equals(Point1 const& a, Point2 const& b, + T const& limit) + { + // Including distance would introduce cyclic dependencies. + // This simple code works and is efficient for all coordinate systems. + return std::abs(geometry::get<0>(a) - geometry::get<0>(b)) <= limit + && std::abs(geometry::get<1>(a) - geometry::get<1>(b)) <= limit; } template - Point add(Operation const& op, signed_size_type turn_index, int op_index, + static Point walk_back(Operation const& op, int offset, + Geometry1 const& geometry1, + Geometry2 const& geometry2) + { + Point point; + geometry::copy_segment_point(geometry1, geometry2, op.seg_id, offset, point); + return point; + } + + template + Point add(Turn const& turn, Operation const& op, signed_size_type turn_index, int op_index, Geometry1 const& geometry1, Geometry2 const& geometry2, bool is_origin) @@ -291,20 +317,34 @@ public : geometry::copy_segment_points(geometry1, geometry2, op.seg_id, point1, point2, point3); Point const& point_to = op.fraction.is_one() ? point3 : point2; - add_segment(turn_index, op_index, point1, point_to, op.operation, op.seg_id, is_origin); + + int offset = 0; + + // If the point is in the neighbourhood (the limit itself is not important), + // then take a point (or more) further back. + // The limit of offset avoids theoretical infinite loops. In practice it currently + // walks max 1 point back in all cases. + while (approximately_equals(point1, turn.point, 1.0e-6) && offset > -10) + { + point1 = walk_back(op, --offset, geometry1, geometry2); + } + + add_segment(turn_index, op_index, point1, point_to, op, is_origin); + return point1; } - template - void add(Operation const& op, signed_size_type turn_index, int op_index, + template + void add(Turn const& turn, + Operation const& op, signed_size_type turn_index, int op_index, segment_identifier const& departure_seg_id, Geometry1 const& geometry1, Geometry2 const& geometry2, - bool check_origin) + bool is_departure) { - Point const point1 = add(op, turn_index, op_index, geometry1, geometry2, false); + Point potential_origin = add(turn, op, turn_index, op_index, geometry1, geometry2, false); - if (check_origin) + if (is_departure) { bool const is_origin = op.seg_id.source_index == departure_seg_id.source_index @@ -317,7 +357,7 @@ public : if (m_origin_count == 0 || segment_distance < m_origin_segment_distance) { - m_origin = point1; + m_origin = potential_origin; m_origin_segment_distance = segment_distance; } m_origin_count++; @@ -325,25 +365,33 @@ public : } } + template + static signed_size_type segment_count_on_ring(Operation const& op, + Geometry1 const& geometry1, + Geometry2 const& geometry2) + { + // Take wrap into account + // Suppose point_count=10 (10 points, 9 segments), dep.seg_id=7, op.seg_id=2, + // then distance=9-7+2=4, being segments 7,8,0,1 + return op.seg_id.source_index == 0 + ? detail::overlay::segment_count_on_ring(geometry1, op.seg_id) + : detail::overlay::segment_count_on_ring(geometry2, op.seg_id); + } + template static signed_size_type calculate_segment_distance(Operation const& op, segment_identifier const& departure_seg_id, Geometry1 const& geometry1, Geometry2 const& geometry2) { + BOOST_ASSERT(op.seg_id.source_index == departure_seg_id.source_index); + signed_size_type result = op.seg_id.segment_index - departure_seg_id.segment_index; if (op.seg_id.segment_index >= departure_seg_id.segment_index) { // dep.seg_id=5, op.seg_id=7, distance=2, being segments 5,6 - return op.seg_id.segment_index - departure_seg_id.segment_index; + return result; } - // Take wrap into account - // Suppose point_count=10 (10 points, 9 segments), dep.seg_id=7, op.seg_id=2, - // then distance=9-7+2=4, being segments 7,8,0,1 - std::size_t const segment_count - = op.seg_id.source_index == 0 - ? segment_count_on_ring(geometry1, op.seg_id) - : segment_count_on_ring(geometry2, op.seg_id); - return segment_count - departure_seg_id.segment_index + op.seg_id.segment_index; + return segment_count_on_ring(op, geometry1, geometry2) + result; } void apply(Point const& turn_point) diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp index a6f8b2a9f..f436639cb 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp @@ -748,7 +748,8 @@ public : for (int i = 0; i < 2; i++) { - sbs.add(cluster_turn.operations[i], + sbs.add(cluster_turn, + cluster_turn.operations[i], cluster_turn_index, i, previous_seg_id, m_geometry1, m_geometry2, departure_turn); @@ -823,7 +824,8 @@ public : // Add this turn to the sort-by-side sorter for (int i = 0; i < 2; i++) { - sbs.add(current_turn.operations[i], + sbs.add(current_turn, + current_turn.operations[i], turn_index, i, previous_seg_id, m_geometry1, m_geometry2, true); diff --git a/test/algorithms/buffer/buffer_multi_polygon.cpp b/test/algorithms/buffer/buffer_multi_polygon.cpp index 032b992f2..f8dbac476 100644 --- a/test/algorithms/buffer/buffer_multi_polygon.cpp +++ b/test/algorithms/buffer/buffer_multi_polygon.cpp @@ -558,23 +558,17 @@ void test_all() test_one("nores_mt_6", nores_mt_6, join_round32, end_flat, 16.9018, 1.0); test_one("nores_et_1", nores_et_1, join_round32, end_flat, 18.9866, 1.0); - -#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("nores_et_2", nores_et_2, join_round32, end_flat, 23.8389, 1.0); test_one("nores_et_3", nores_et_3, join_round32, end_flat, 26.9030, 1.0); -#endif - test_one("nores_et_4", nores_et_4, join_round32, end_flat, 19.9626, 1.0); test_one("nores_et_5", nores_et_5, join_round32, end_flat, 19.9615, 1.0); + test_one("nores_et_6", nores_et_6, join_round32, end_flat, 96.1795, 1.0); + test_one("nores_et_7", nores_et_7, join_round32, end_flat, 105.9577, 1.0); test_one("nores_wn_1", nores_wn_1, join_round32, end_flat, 23.7659, 1.0); test_one("nores_wn_2", nores_wn_2, join_round32, end_flat, 18.2669, 1.0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) - test_one("nores_et_6", nores_et_6, join_round32, end_flat, 96.1795, 1.0); - test_one("nores_et_7", nores_et_7, join_round32, end_flat, 105.9577, 1.0); test_one("nores_wt_1", nores_wt_1, join_round32, end_flat, 80.1609, 1.0); -#endif test_one("neighbouring_small", neighbouring, @@ -619,7 +613,7 @@ int test_main(int, char* []) #endif #if defined(BOOST_GEOMETRY_TEST_FAILURES) - BoostGeometryWriteExpectedFailures(1, 8, 2, 7); + BoostGeometryWriteExpectedFailures(1, 1, 2, 3); #endif return 0; diff --git a/test/algorithms/buffer/test_buffer_svg.hpp b/test/algorithms/buffer/test_buffer_svg.hpp index 2c7db78ce..6f59fe647 100644 --- a/test/algorithms/buffer/test_buffer_svg.hpp +++ b/test/algorithms/buffer/test_buffer_svg.hpp @@ -207,7 +207,7 @@ private : } #endif - bg::model::ring const& corner = piece.m_piece_border.get_full_ring(); + auto const& corner = piece.m_piece_border.get_full_ring(); if (m_zoom && do_pieces) { diff --git a/test/algorithms/overlay/sort_by_side.cpp b/test/algorithms/overlay/sort_by_side.cpp index 1e0f42258..bcd6b3bae 100644 --- a/test/algorithms/overlay/sort_by_side.cpp +++ b/test/algorithms/overlay/sort_by_side.cpp @@ -101,7 +101,7 @@ std::vector gather_cluster_properties( for (int i = 0; i < 2; i++) { turn_operation_type const& op = turn.operations[i]; - sbs.add(op, turn_index, i, geometry1, geometry2, first); + sbs.add(turn, op, turn_index, i, geometry1, geometry2, first); first = false; } } diff --git a/test/algorithms/overlay/sort_by_side_basic.cpp b/test/algorithms/overlay/sort_by_side_basic.cpp index f37bd38c6..e014e7dff 100644 --- a/test/algorithms/overlay/sort_by_side_basic.cpp +++ b/test/algorithms/overlay/sort_by_side_basic.cpp @@ -120,7 +120,7 @@ std::vector apply_get_turns(std::string const& case_id, has_origin = true; } - sbs.add(turn.operations[i], turn_index, i, + sbs.add(turn, turn.operations[i], turn_index, i, geometry1, geometry2, is_origin); } diff --git a/test/algorithms/set_operations/difference/difference.cpp b/test/algorithms/set_operations/difference/difference.cpp index 6d3d49999..ef6b2e140 100644 --- a/test/algorithms/set_operations/difference/difference.cpp +++ b/test/algorithms/set_operations/difference/difference.cpp @@ -624,7 +624,7 @@ int test_main(int, char* []) #if defined(BOOST_GEOMETRY_TEST_FAILURES) // Not yet fully tested for float and long double. // The difference algorithm can generate (additional) slivers - BoostGeometryWriteExpectedFailures(10, 11, 24, 15); + BoostGeometryWriteExpectedFailures(10, 11, 24, 16); #endif return 0; diff --git a/test/algorithms/set_operations/difference/difference_multi.cpp b/test/algorithms/set_operations/difference/difference_multi.cpp index 2203f071f..91e143dff 100644 --- a/test/algorithms/set_operations/difference/difference_multi.cpp +++ b/test/algorithms/set_operations/difference/difference_multi.cpp @@ -524,7 +524,7 @@ int test_main(int, char* []) #if defined(BOOST_GEOMETRY_TEST_FAILURES) // Not yet fully tested for float. // The difference algorithm can generate (additional) slivers - BoostGeometryWriteExpectedFailures(22, 13, 19, 7); + BoostGeometryWriteExpectedFailures(22, 9, 20, 7); #endif return 0; diff --git a/test/algorithms/set_operations/intersection/intersection_multi.cpp b/test/algorithms/set_operations/intersection/intersection_multi.cpp index 585232273..043512267 100644 --- a/test/algorithms/set_operations/intersection/intersection_multi.cpp +++ b/test/algorithms/set_operations/intersection/intersection_multi.cpp @@ -499,7 +499,7 @@ int test_main(int, char* []) #endif #if defined(BOOST_GEOMETRY_TEST_FAILURES) - BoostGeometryWriteExpectedFailures(9, 3, 2, 1); + BoostGeometryWriteExpectedFailures(9, 1, 2, 1); #endif return 0; diff --git a/test/algorithms/set_operations/union/union_multi.cpp b/test/algorithms/set_operations/union/union_multi.cpp index 53c70844b..6d7d7fbc6 100644 --- a/test/algorithms/set_operations/union/union_multi.cpp +++ b/test/algorithms/set_operations/union/union_multi.cpp @@ -489,7 +489,7 @@ int test_main(int, char* []) #endif #if defined(BOOST_GEOMETRY_TEST_FAILURES) - BoostGeometryWriteExpectedFailures(9, 2, 1, 0); + BoostGeometryWriteExpectedFailures(9, 0, 1, 0); #endif return 0; From 324249bb2dd2f348f2dab95359b25db81da7cf4f Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 9 Dec 2020 12:03:17 +0100 Subject: [PATCH 27/55] [copy_segment_point] change offset with modulo, add to box, update unit test --- .../detail/overlay/copy_segment_point.hpp | 36 ++++--- .../algorithms/overlay/copy_segment_point.cpp | 100 +++++++++++++----- test/count_set.hpp | 4 - 3 files changed, 92 insertions(+), 48 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp index 10d12085b..e9b9a2f04 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -42,6 +42,16 @@ namespace boost { namespace geometry namespace detail { namespace copy_segments { +inline signed_size_type circular_offset(signed_size_type segment_count, signed_size_type index, + signed_size_type offset) +{ + signed_size_type result = (index + offset) % segment_count; + if (result < 0) + { + result += segment_count; + } + return result; +} template struct copy_segment_point_range @@ -66,12 +76,11 @@ struct copy_segment_point_range rview_type view(cview); std::size_t const segment_count = boost::size(view) - 1; + signed_size_type const target = circular_offset(segment_count, seg_id.segment_index, offset); - while (offset < 0) { offset += segment_count; } - - signed_size_type const target = (seg_id.segment_index + offset) % segment_count; - - geometry::convert(*(boost::begin(view) + target), point); + BOOST_GEOMETRY_ASSERT(target >= 0); + BOOST_GEOMETRY_ASSERT(target < boost::size(view)); + geometry::convert(range::at(view, target), point); return true; } @@ -111,15 +120,14 @@ struct copy_segment_point_box SegmentIdentifier const& seg_id, signed_size_type offset, PointOut& point) { - signed_size_type index = seg_id.segment_index; - for (int i = 0; i < offset; i++) - { - index++; - } - boost::array::type, 4> bp; assign_box_corners_oriented(box, bp); - point = bp[index % 4]; + + signed_size_type const target = circular_offset(4, seg_id.segment_index, offset); + BOOST_GEOMETRY_ASSERT(target >= 0); + BOOST_GEOMETRY_ASSERT(target < bp.size()); + + point = bp[target]; return true; } }; @@ -138,7 +146,6 @@ struct copy_segment_point_multi SegmentIdentifier const& seg_id, signed_size_type offset, PointOut& point) { - BOOST_GEOMETRY_ASSERT ( seg_id.multi_index >= 0 @@ -276,9 +283,6 @@ struct copy_segment_point #endif // DOXYGEN_NO_DISPATCH - - - /*! \brief Helper function, copies a point from a segment \ingroup overlay diff --git a/test/algorithms/overlay/copy_segment_point.cpp b/test/algorithms/overlay/copy_segment_point.cpp index 101908906..33c3f9536 100644 --- a/test/algorithms/overlay/copy_segment_point.cpp +++ b/test/algorithms/overlay/copy_segment_point.cpp @@ -16,22 +16,21 @@ #include #include -template -void test_basic(std::string const& case_id, int line, +template +void test_basic(GetRing get_ring, std::string const& case_id, int line, std::string const& wkt, bg::segment_identifier const& id, int offset, std::size_t expected_index) { - using point_type = bg::model::point; - using polygon_type = bg::model::polygon; + using point_type = typename bg::point_type::type; - polygon_type polygon; - bg::read_wkt(wkt, polygon); + Geometry geometry; + bg::read_wkt(wkt, geometry); // Check the result - auto const& ring = bg::exterior_ring(polygon); + auto ring = get_ring(geometry); point_type point; - bg::copy_segment_point(polygon, id, offset, point); + bg::copy_segment_point(geometry, id, offset, point); // Sanity check bool const expectation_in_range = expected_index < ring.size(); @@ -51,38 +50,83 @@ void test_basic(std::string const& case_id, int line, << bg::wkt(point) << " vs " << bg::wkt(expected_point)); } -template -void test_all(std::string const& case_id, std::string const& wkt) +template +void test_geometry(std::string const& case_id, std::string const& wkt, GetRing get_ring) { // Check zero offset, all segment ids - test_basic(case_id, __LINE__, wkt, {0, 0, -1, 0}, 0, 0); - test_basic(case_id, __LINE__, wkt, {0, 0, -1, 1}, 0, 1); - test_basic(case_id, __LINE__, wkt, {0, 0, -1, 2}, 0, 2); - test_basic(case_id, __LINE__, wkt, {0, 0, -1, 3}, 0, 3); + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 0}, 0, 0); + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 1}, 0, 1); + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 2}, 0, 2); + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 3}, 0, 3); // Check positive offsets, it should endlessly loop around, regardless of direction or closure bg::segment_identifier const start{0, 0, -1, 0}; - test_basic(case_id, __LINE__, wkt, start, 1, 1); - test_basic(case_id, __LINE__, wkt, start, 2, 2); - test_basic(case_id, __LINE__, wkt, start, 3, 3); - test_basic(case_id, __LINE__, wkt, start, 4, 0); - test_basic(case_id, __LINE__, wkt, start, 5, 1); - test_basic(case_id, __LINE__, wkt, start, 6, 2); - test_basic(case_id, __LINE__, wkt, start, 7, 3); + test_basic(get_ring, case_id, __LINE__, wkt, start, 1, 1); + test_basic(get_ring, case_id, __LINE__, wkt, start, 2, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, 3, 3); + test_basic(get_ring, case_id, __LINE__, wkt, start, 4, 0); + test_basic(get_ring, case_id, __LINE__, wkt, start, 5, 1); + test_basic(get_ring, case_id, __LINE__, wkt, start, 6, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, 7, 3); // Check negative offsets - test_basic(case_id, __LINE__, wkt, start, -1, 3); - test_basic(case_id, __LINE__, wkt, start, -2, 2); - test_basic(case_id, __LINE__, wkt, start, -3, 1); - test_basic(case_id, __LINE__, wkt, start, -4, 0); - test_basic(case_id, __LINE__, wkt, start, -5, 3); - test_basic(case_id, __LINE__, wkt, start, -6, 2); - test_basic(case_id, __LINE__, wkt, start, -7, 1); + test_basic(get_ring, case_id, __LINE__, wkt, start, -1, 3); + test_basic(get_ring, case_id, __LINE__, wkt, start, -2, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, -3, 1); + test_basic(get_ring, case_id, __LINE__, wkt, start, -4, 0); + test_basic(get_ring, case_id, __LINE__, wkt, start, -5, 3); + test_basic(get_ring, case_id, __LINE__, wkt, start, -6, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, -7, 1); +} + +template +void test_all(std::string const& case_id, std::string const& wkt) +{ + using point_type = bg::model::point; + using polygon_type = bg::model::polygon; + + test_geometry(case_id, wkt, [](polygon_type const& polygon) + { + return bg::exterior_ring(polygon); + }); +} + +template +void test_box(std::string const& case_id, std::string const& wkt) +{ + using point_type = bg::model::point; + using box_type = bg::model::box; + + test_geometry(case_id, wkt, [](box_type const& box) + { + boost::array ring; + bg::detail::assign_box_corners_oriented(box, ring); + return ring; + }); + +} + +void test_circular_offset() +{ + BOOST_CHECK_EQUAL(3, bg::detail::copy_segments::circular_offset(4, 0, -1)); + BOOST_CHECK_EQUAL(2, bg::detail::copy_segments::circular_offset(4, 0, -2)); + BOOST_CHECK_EQUAL(1, bg::detail::copy_segments::circular_offset(4, 0, -3)); + + BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 1)); + BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 11)); + BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 21)); + + BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -1)); + BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -11)); + BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -21)); } int test_main(int, char* []) { + test_circular_offset(); + test_all("closed", "POLYGON((0 2,1 2,1 1,0 1,0 2))"); test_all("open", "POLYGON((0 2,1 2,1 1,0 1))"); + test_box("box", "BOX(0 0,5 5)"); return 0; } diff --git a/test/count_set.hpp b/test/count_set.hpp index 751649171..3d69b5ca4 100644 --- a/test/count_set.hpp +++ b/test/count_set.hpp @@ -29,10 +29,6 @@ struct count_set { m_values.insert(static_cast(value)); } - else - { - std::cout << "EMPTY" << std::endl; - } } count_set(std::size_t value1, std::size_t value2) From 4e8ff8113114b037d5e382af2df4958cac0e918a Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 9 Dec 2020 13:52:52 +0100 Subject: [PATCH 28/55] [sort_by_side] add epsilon to approximately_equals --- .../detail/overlay/sort_by_side.hpp | 28 +++++++++++++++---- .../set_operations/union/union_multi.cpp | 2 +- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp index 9b0726deb..948b03db5 100644 --- a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp @@ -25,6 +25,9 @@ #include #include +#include +#include +#include namespace boost { namespace geometry { @@ -287,14 +290,29 @@ public : add_segment_to(turn_index, op_index, point_to, op); } + // Returns true if two points are approximately equal, tuned by a giga-epsilon constant + // (if constant is 1.0, for type double, the boundary is about 1.0e-7) template static inline bool approximately_equals(Point1 const& a, Point2 const& b, - T const& limit) + T const& limit_giga_epsilon) { // Including distance would introduce cyclic dependencies. - // This simple code works and is efficient for all coordinate systems. - return std::abs(geometry::get<0>(a) - geometry::get<0>(b)) <= limit - && std::abs(geometry::get<1>(a) - geometry::get<1>(b)) <= limit; + using coor_t = typename select_coordinate_type::type; + using calc_t = typename geometry::select_most_precise ::type; + constexpr calc_t machine_giga_epsilon = 1.0e9 * std::numeric_limits::epsilon(); + + calc_t const& a0 = geometry::get<0>(a); + calc_t const& b0 = geometry::get<0>(b); + calc_t const& a1 = geometry::get<1>(a); + calc_t const& b1 = geometry::get<1>(b); + calc_t const one = 1.0; + calc_t const c = math::detail::greatest(a0, b0, a1, b1, one); + + // The maximum limit is avoid, for floating point, large limits like 400 + // (which are be calculated using eps) + constexpr calc_t maxlimit = 1.0e-3; + auto const limit = (std::min)(maxlimit, limit_giga_epsilon * machine_giga_epsilon * c); + return std::abs(a0 - b0) <= limit && std::abs(a1 - b1) <= limit; } template @@ -324,7 +342,7 @@ public : // then take a point (or more) further back. // The limit of offset avoids theoretical infinite loops. In practice it currently // walks max 1 point back in all cases. - while (approximately_equals(point1, turn.point, 1.0e-6) && offset > -10) + while (approximately_equals(point1, turn.point, 1.0) && offset > -10) { point1 = walk_back(op, --offset, geometry1, geometry2); } diff --git a/test/algorithms/set_operations/union/union_multi.cpp b/test/algorithms/set_operations/union/union_multi.cpp index 6d7d7fbc6..bcc0185a5 100644 --- a/test/algorithms/set_operations/union/union_multi.cpp +++ b/test/algorithms/set_operations/union/union_multi.cpp @@ -489,7 +489,7 @@ int test_main(int, char* []) #endif #if defined(BOOST_GEOMETRY_TEST_FAILURES) - BoostGeometryWriteExpectedFailures(9, 0, 1, 0); + BoostGeometryWriteExpectedFailures(9, 0, 3, 0); #endif return 0; From 59e0840d750cbcc7fd1f563ab6fa5fd7a3914ebc Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 16 Dec 2020 14:29:15 +0100 Subject: [PATCH 29/55] [sort_by_side] walk forward for point_to (similarly to walking backwards for point_from) --- .../detail/overlay/sort_by_side.hpp | 25 ++++++++++++------- .../buffer/buffer_multi_polygon.cpp | 4 ++- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp index 948b03db5..316f53a02 100644 --- a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp @@ -316,7 +316,7 @@ public : } template - static Point walk_back(Operation const& op, int offset, + static Point walk_over_ring(Operation const& op, int offset, Geometry1 const& geometry1, Geometry2 const& geometry2) { @@ -331,25 +331,32 @@ public : Geometry2 const& geometry2, bool is_origin) { - Point point1, point2, point3; + Point point_from, point2, point3; geometry::copy_segment_points(geometry1, geometry2, - op.seg_id, point1, point2, point3); - Point const& point_to = op.fraction.is_one() ? point3 : point2; + op.seg_id, point_from, point2, point3); + Point point_to = op.fraction.is_one() ? point3 : point2; - int offset = 0; // If the point is in the neighbourhood (the limit itself is not important), // then take a point (or more) further back. // The limit of offset avoids theoretical infinite loops. In practice it currently // walks max 1 point back in all cases. - while (approximately_equals(point1, turn.point, 1.0) && offset > -10) + int offset = 0; + while (approximately_equals(point_from, turn.point, 1.0) && offset > -10) { - point1 = walk_back(op, --offset, geometry1, geometry2); + point_from = walk_over_ring(op, --offset, geometry1, geometry2); } - add_segment(turn_index, op_index, point1, point_to, op, is_origin); + // Similarly for the point to, walk forward + offset = 0; + while (approximately_equals(point_to, turn.point, 1.0) && offset < 10) + { + point_to = walk_over_ring(op, ++offset, geometry1, geometry2); + } - return point1; + add_segment(turn_index, op_index, point_from, point_to, op, is_origin); + + return point_from; } template diff --git a/test/algorithms/buffer/buffer_multi_polygon.cpp b/test/algorithms/buffer/buffer_multi_polygon.cpp index f8dbac476..f5421ec44 100644 --- a/test/algorithms/buffer/buffer_multi_polygon.cpp +++ b/test/algorithms/buffer/buffer_multi_polygon.cpp @@ -346,7 +346,8 @@ static std::string const nores_wn_2 // Other cases with wrong turn information static std::string const nores_wt_1 = "MULTIPOLYGON(((0 4,0 5,1 4,0 4)),((9 3,9 4,10 4,9 3)),((9 7,10 8,10 7,9 7)),((6 7,7 8,7 7,6 7)),((0 7,0 8,1 8,0 7)),((3 6,4 6,4 5,3 4,3 6)),((3 7,2 6,2 7,3 7)),((3 7,3 8,4 8,4 7,3 7)),((3 3,4 4,4 3,3 3)),((3 3,3 2,2 2,2 3,3 3)),((2 6,2 5,1 5,1 6,2 6)),((6 4,6 3,5 3,5 4,6 4)),((6 4,7 5,7 4,6 4)),((5 1,4 0,4 1,5 1)),((5 1,5 2,6 2,6 1,5 1)))"; - +static std::string const nores_wt_2 + = "MULTIPOLYGON(((1 1,2 2,2 1,1 1)),((0 2,0 3,1 3,0 2)),((4 3,5 4,5 3,4 3)),((4 3,3 3,4 4,4 3)))"; static std::string const neighbouring = "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)),((10 10,10 20,20 20,20 10,10 10)))"; @@ -569,6 +570,7 @@ void test_all() test_one("nores_wn_2", nores_wn_2, join_round32, end_flat, 18.2669, 1.0); test_one("nores_wt_1", nores_wt_1, join_round32, end_flat, 80.1609, 1.0); + test_one("nores_wt_2", nores_wt_2, join_round32, end_flat, 22.1102, 1.0); test_one("neighbouring_small", neighbouring, From cb9c71037ca9a9178a9a3595af33705e0f462970 Mon Sep 17 00:00:00 2001 From: Edward Diener Date: Sun, 20 Dec 2020 05:15:29 -0500 Subject: [PATCH 30/55] Add "cxxstd" json field. The "cxxstd" json field is being added to each Boost library's meta json information for libraries whose minumum C++ standard compilation level is C++11 on up. The value of this field matches one of the values for 'cxxstd' in Boost.Build. The purpose of doing this is to provide information for the Boost website documentation for each library which will specify the minimum C++ standard compilation that an end-user must employ in order to use the particular library. This will aid end-users who want to know if they can successfully use a Boost library based on their C++ compiler's compilation level, without having to search the library's documentation to find this out. (#783) --- meta/libraries.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/meta/libraries.json b/meta/libraries.json index a6648fc39..1ad723ca6 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -20,6 +20,7 @@ "The Boost.Geometry library provides geometric algorithms, primitives and spatial index.", "category": [ "Algorithms", "Data", "Math" - ] + ], + "cxxstd": "14" } ] From 4034ac88b214da0eab8943172eff0f1200b0a6cc Mon Sep 17 00:00:00 2001 From: Vissarion Fisikopoulos Date: Mon, 21 Dec 2020 15:11:17 +0200 Subject: [PATCH 31/55] [strategies] [test] Fix spherical cross track and convex hull tests --- .../geometry/strategies/spherical/side_by_cross_track.hpp | 4 ++++ test/algorithms/Jamfile | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp index 0f078443f..6cbc5cedc 100644 --- a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp @@ -15,12 +15,16 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP +#include + #include #include #include #include +#include + #include #include #include diff --git a/test/algorithms/Jamfile b/test/algorithms/Jamfile index 787a56fc5..3846cdb12 100644 --- a/test/algorithms/Jamfile +++ b/test/algorithms/Jamfile @@ -25,8 +25,6 @@ test-suite boost-geometry-algorithms [ run comparable_distance.cpp : : : : algorithms_comparable_distance ] [ run convert.cpp : : : : algorithms_convert ] [ run convert_multi.cpp : : : : algorithms_convert_multi ] - [ run convex_hull.cpp : : : : algorithms_convex_hull ] - [ run convex_hull_multi.cpp : : : : algorithms_convex_hull_multi ] [ run correct.cpp : : : : algorithms_correct ] [ run correct_multi.cpp : : : : algorithms_correct_multi ] [ run correct_closure.cpp : : : : algorithms_correct_closure ] From f6153724c0aaad62ad4cb9b02055cb82b3898b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20=C5=81oskot?= Date: Wed, 23 Dec 2020 10:30:04 +0100 Subject: [PATCH 32/55] Catch up examples with addition of robustness policy and others (#787) The example/c03_custom_linestring_example.cpp requires change from PR #786 These changes make all examples compile again. Fixes #784 --- example/05_b_overlay_linestring_polygon_example.cpp | 5 +++-- example/c05_custom_point_pointer_example.cpp | 3 ++- example/c08_custom_non_std_example.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/example/05_b_overlay_linestring_polygon_example.cpp b/example/05_b_overlay_linestring_polygon_example.cpp index 38349decb..f37165f3e 100644 --- a/example/05_b_overlay_linestring_polygon_example.cpp +++ b/example/05_b_overlay_linestring_polygon_example.cpp @@ -67,12 +67,13 @@ int main(void) #endif // Calculate intersection points (turn points) - typedef bg::segment_ratio_type::type segment_ratio; + typedef bg::detail::segment_ratio_type::type segment_ratio; typedef bg::detail::overlay::turn_info turn_info; std::vector turns; bg::detail::get_turns::no_interrupt_policy policy; bg::detail::no_rescale_policy rescale_policy; - bg::get_turns(ls, p, rescale_policy, turns, policy); + bg::strategy::intersection::services::default_strategy::type>::type intersection_strategy; + bg::get_turns(ls, p, intersection_strategy, rescale_policy, turns, policy); std::cout << "Intersection of linestring/polygon" << std::endl; BOOST_FOREACH(turn_info const& turn, turns) diff --git a/example/c05_custom_point_pointer_example.cpp b/example/c05_custom_point_pointer_example.cpp index d8059fe04..a1d9dbef0 100644 --- a/example/c05_custom_point_pointer_example.cpp +++ b/example/c05_custom_point_pointer_example.cpp @@ -102,10 +102,11 @@ int main() // This works because outputs to a normal struct point, no point* typedef boost::geometry::model::linestring linestring_2d; + boost::geometry::detail::no_rescale_policy rescale_policy; std::vector clipped; boost::geometry::strategy::intersection::liang_barsky strategy; boost::geometry::detail::intersection::clip_range_with_box(cb, - myline, std::back_inserter(clipped), strategy); + myline, rescale_policy, std::back_inserter(clipped), strategy); std::cout << boost::geometry::length(clipped.front()) << std::endl; diff --git a/example/c08_custom_non_std_example.cpp b/example/c08_custom_non_std_example.cpp index 0a545a3de..12bb76840 100644 --- a/example/c08_custom_non_std_example.cpp +++ b/example/c08_custom_non_std_example.cpp @@ -281,7 +281,7 @@ int main() // Create (as an example) a regular polygon const int n = 5; - const double d = (360 / n) * boost::geometry::math::d2r; + const double d = (360 / n) * boost::geometry::math::d2r(); double a = 0; for (int i = 0; i < n + 1; i++, a += d) { From b54a0589bdb6c48423ff4cab34f1ab2c48d8cb6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20=C5=81oskot?= Date: Wed, 23 Dec 2020 10:35:09 +0100 Subject: [PATCH 33/55] Catch up with dms_parser change from function call operator to apply (#786) The change was applied in PR #394 --- include/boost/geometry/extensions/algorithms/parse.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/extensions/algorithms/parse.hpp b/include/boost/geometry/extensions/algorithms/parse.hpp index d9354435d..836e1ab25 100644 --- a/include/boost/geometry/extensions/algorithms/parse.hpp +++ b/include/boost/geometry/extensions/algorithms/parse.hpp @@ -58,8 +58,8 @@ struct parsing typedef typename coordinate_type::type coord_t; typedef boost::geometry::projections::detail::dms_result dms_result_t; - dms_result_t r1 = strategy(c1.c_str()); - dms_result_t r2 = strategy(c2.c_str()); + dms_result_t r1 = strategy.apply(c1.c_str()); + dms_result_t r2 = strategy.apply(c2.c_str()); if (0 == r1.axis()) set<0>(point, r1.angle()); From 84d3a8d9ceb49489e8c230b92843326f5907417b Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 30 Dec 2020 11:46:02 +0100 Subject: [PATCH 34/55] [get_turn_info] handle collinear as equal if both segments arrive at intersection point --- .../detail/overlay/get_turn_info.hpp | 98 +++++++++++++------ 1 file changed, 70 insertions(+), 28 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index e90910c9b..8146c8fa0 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -186,7 +186,8 @@ struct base_turn_handler { ti.method = method; - // For touch/touch interior always take the intersection point 0 (there is only one). + // For touch/touch interior always take the intersection point 0 + // (usually there is only one - but if collinear is handled as touch, both could be taken). static int const index = 0; geometry::convert(info.intersections[index], ti.point); @@ -965,8 +966,57 @@ template > struct collinear : public base_turn_handler { + template + < + typename IntersectionInfo, + typename UniqueSubRange1, + typename UniqueSubRange2, + typename DirInfo + > + static bool handle_as_equal(IntersectionInfo const& info, + UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, + DirInfo const& dir_info) + { +#if defined(BOOST_GEOMETRY_USE_RESCALING) + return false; +#endif + int const arrival_p = dir_info.arrival[0]; + int const arrival_q = dir_info.arrival[1]; + if (arrival_p * arrival_q != -1 || info.count != 2) + { + // Code below assumes that either p or q arrives in the other segment + return false; + } + + auto const location = distance_measure(info.intersections[1], + arrival_p == 1 ? range_q.at(1) : range_p.at(1)); + decltype(location) const zero = 0; + return math::equals(location, zero); + } + /* - arrival P pk//p1 qk//q1 product* case result + Either P arrives within Q (arrival_p == -1) or Q arrives within P. + + Typical situation: + ^q2 + / + ^q1 + / ____ ip[1] + //|p1 } this section of p/q is colllinear + q0// | } ____ ip[0] + / | + / v + p0 p2 + + P arrives (at p1) in segment Q (between q0 and q1). + Therefore arrival_p == 1 + P (p2) goes to the right (-1). Follow P for intersection, or follow Q for union. + Therefore if (arrival_p==1) and side_p==-1, result = iu + + Complete table: + + arrival P pk//p1 qk//q1 product case result 1 1 1 CLL1 ui -1 1 -1 CLL2 iu 1 1 1 CLR1 ui @@ -980,7 +1030,9 @@ struct collinear : public base_turn_handler 1 0 0 CC1 cc -1 0 0 CC2 cc - *product = arrival * (pk//p1 or qk//q1) + Resulting in the rule: + The arrival-info multiplied by the relevant side delivers the result. + product = arrival * (pk//p1 or qk//q1) Stated otherwise: - if P arrives: look at turn P @@ -989,13 +1041,6 @@ struct collinear : public base_turn_handler - if P arrives and P turns right: intersection for P - if Q arrives and Q turns left: union for Q (=intersection for P) - if Q arrives and Q turns right: intersection for Q (=union for P) - - ROBUSTNESS: p and q are collinear, so you would expect - that side qk//p1 == pk//q1. But that is not always the case - in near-epsilon ranges. Then decision logic is different. - If p arrives, q is further, so the angle qk//p1 is (normally) - more precise than pk//p1 - */ template < @@ -1016,9 +1061,9 @@ struct collinear : public base_turn_handler // Copy the intersection point in TO direction assign_point(ti, method_collinear, info, non_opposite_to_index(info)); - int const arrival = dir_info.arrival[0]; + int const arrival_p = dir_info.arrival[0]; // Should not be 0, this is checked before - BOOST_GEOMETRY_ASSERT(arrival != 0); + BOOST_GEOMETRY_ASSERT(arrival_p != 0); bool const has_pk = ! range_p.is_last_segment(); bool const has_qk = ! range_q.is_last_segment(); @@ -1026,19 +1071,15 @@ struct collinear : public base_turn_handler int const side_q = has_qk ? side.qk_wrt_q1() : 0; // If p arrives, use p, else use q - int const side_p_or_q = arrival == 1 + int const side_p_or_q = arrival_p == 1 ? side_p : side_q ; - // See comments above, - // resulting in a strange sort of mathematic rule here: - // The arrival-info multiplied by the relevant side - // delivers a consistent result. + // Calculate product according to comments above. + int const product = arrival_p * side_p_or_q; - int const product = arrival * side_p_or_q; - - if(product == 0) + if (product == 0) { both(ti, operation_continue); } @@ -1186,11 +1227,11 @@ public: { TurnInfo tp = tp_model; - int const p_arrival = info.d_info().arrival[0]; - int const q_arrival = info.d_info().arrival[1]; + int const arrival_p = info.d_info().arrival[0]; + int const arrival_q = info.d_info().arrival[1]; // If P arrives within Q, there is a turn dependent on P - if ( p_arrival == 1 + if ( arrival_p == 1 && ! range_p.is_last_segment() && set_tp<0>(side.pk_wrt_p1(), tp, info.i_info()) ) { @@ -1200,7 +1241,7 @@ public: } // If Q arrives within P, there is a turn dependent on Q - if ( q_arrival == 1 + if ( arrival_q == 1 && ! range_q.is_last_segment() && set_tp<1>(side.qk_wrt_q1(), tp, info.i_info()) ) { @@ -1212,8 +1253,8 @@ public: if (AssignPolicy::include_opposite) { // Handle cases not yet handled above - if ((q_arrival == -1 && p_arrival == 0) - || (p_arrival == -1 && q_arrival == 0)) + if ((arrival_q == -1 && arrival_p == 0) + || (arrival_p == -1 && arrival_q == 0)) { for (unsigned int i = 0; i < 2; i++) { @@ -1420,9 +1461,10 @@ struct get_turn_info // Collinear if ( ! inters.d_info().opposite ) { - - if ( inters.d_info().arrival[0] == 0 ) + if (inters.d_info().arrival[0] == 0 + || collinear::handle_as_equal(inters.i_info(), range_p, range_q, inters.d_info())) { + // Both segments arrive at the second intersection point handle_as_equal = true; } else From 24dc47e23fbdde7951a0e1cf86608d7efd2b5d69 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 13 Jan 2021 01:23:52 +0100 Subject: [PATCH 35/55] [algorithms] Add new algorithm: azimuth(). --- include/boost/geometry/algorithms/azimuth.hpp | 189 ++++++++++++++++++ .../geometry/algorithms/detail/azimuth.hpp | 152 -------------- .../geometry/algorithms/detail/course.hpp | 40 ---- include/boost/geometry/geometry.hpp | 5 +- include/boost/geometry/strategies/azimuth.hpp | 4 +- .../geometry/strategies/azimuth/cartesian.hpp | 63 ++++++ .../strategies/azimuth/geographic.hpp | 81 ++++++++ .../geometry/strategies/azimuth/services.hpp | 56 ++++++ .../geometry/strategies/azimuth/spherical.hpp | 67 +++++++ .../boost/geometry/strategies/cartesian.hpp | 10 +- .../geometry/strategies/cartesian/azimuth.hpp | 67 ++++++- .../boost/geometry/strategies/geographic.hpp | 11 + .../strategies/geographic/azimuth.hpp | 57 +++--- .../boost/geometry/strategies/spherical.hpp | 10 +- .../geometry/strategies/spherical/azimuth.hpp | 77 ++++--- 15 files changed, 614 insertions(+), 275 deletions(-) create mode 100644 include/boost/geometry/algorithms/azimuth.hpp delete mode 100644 include/boost/geometry/algorithms/detail/azimuth.hpp delete mode 100644 include/boost/geometry/algorithms/detail/course.hpp create mode 100644 include/boost/geometry/strategies/azimuth/cartesian.hpp create mode 100644 include/boost/geometry/strategies/azimuth/geographic.hpp create mode 100644 include/boost/geometry/strategies/azimuth/services.hpp create mode 100644 include/boost/geometry/strategies/azimuth/spherical.hpp diff --git a/include/boost/geometry/algorithms/azimuth.hpp b/include/boost/geometry/algorithms/azimuth.hpp new file mode 100644 index 000000000..8403871db --- /dev/null +++ b/include/boost/geometry/algorithms/azimuth.hpp @@ -0,0 +1,189 @@ +// Boost.Geometry + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-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 + +// 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_AZIMUTH_HPP +#define BOOST_GEOMETRY_ALGORITHMS_AZIMUTH_HPP + + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Geometry1, typename Geometry2, + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type +> +struct azimuth : not_implemented +{}; + +template +struct azimuth +{ + template + static auto apply(Point1 const& p1, Point2 const& p2, Strategy const& strategy) + { + typedef typename decltype(strategy.azimuth())::template result_type + < + typename coordinate_type::type, + typename coordinate_type::type + >::type calc_t; + + calc_t result = 0; + calc_t x1 = geometry::get_as_radian<0>(p1); + calc_t y1 = geometry::get_as_radian<1>(p1); + calc_t x2 = geometry::get_as_radian<0>(p2); + calc_t y2 = geometry::get_as_radian<1>(p2); + + strategy.azimuth().apply(x1, y1, x2, y2, result); + + // NOTE: It is not clear which units we should use for the result. + // For now radians are always returned but a user could expect + // e.g. something like this: + /* + bool const both_degree = std::is_same + < + typename detail::cs_angular_units::type, + geometry::degree + >::value + && std::is_same + < + typename detail::cs_angular_units::type, + geometry::degree + >::value; + if (both_degree) + { + result *= math::r2d(); + } + */ + + return result; + } +}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_strategy +{ + +template +< + typename Strategy, + bool IsUmbrella = strategies::detail::is_umbrella_strategy::value +> +struct azimuth +{ + template + static auto apply(P1 const& p1, P2 const& p2, Strategy const& strategy) + { + return dispatch::azimuth::apply(p1, p2, strategy); + } +}; + +template +struct azimuth +{ + template + static auto apply(P1 const& p1, P2 const& p2, Strategy const& strategy) + { + using strategies::azimuth::services::strategy_converter; + return dispatch::azimuth + < + P1, P2 + >::apply(p1, p2, strategy_converter::get(strategy)); + } +}; + +template <> +struct azimuth +{ + template + static auto apply(P1 const& p1, P2 const& p2, default_strategy) + { + typedef typename strategies::azimuth::services::default_strategy + < + P1, P2 + >::type strategy_type; + + return dispatch::azimuth::apply(p1, p2, strategy_type()); + } +}; + + +} // namespace resolve_strategy + + +namespace resolve_variant +{ +} // namespace resolve_variant + + +template +inline auto azimuth(Point1 const& point1, Point2 const& point2) +{ + concepts::check(); + concepts::check(); + + return resolve_strategy::azimuth + < + default_strategy + >::apply(point1, point2, default_strategy()); +} + + +template +inline auto azimuth(Point1 const& point1, Point2 const& point2, Strategy const& strategy) +{ + concepts::check(); + concepts::check(); + + return resolve_strategy::azimuth::apply(point1, point2, strategy); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_AZIMUTH_HPP diff --git a/include/boost/geometry/algorithms/detail/azimuth.hpp b/include/boost/geometry/algorithms/detail/azimuth.hpp deleted file mode 100644 index 21007778b..000000000 --- a/include/boost/geometry/algorithms/detail/azimuth.hpp +++ /dev/null @@ -1,152 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. - -// This file was modified by Oracle on 2014, 2016, 2017. -// Modifications copyright (c) 2014-2017, 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_DETAIL_AZIMUTH_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP - - -#include - -#include -#include -#include -#include - -#include -#include - -#include - -#include - - -namespace boost { namespace geometry -{ - -// An azimuth is an angle between a vector/segment from origin to a point of -// interest and a reference vector. Typically north-based azimuth is used. -// North direction is used as a reference, angle is measured clockwise -// (North - 0deg, East - 90deg). For consistency in 2d cartesian CS -// the reference vector is Y axis, angle is measured clockwise. -// http://en.wikipedia.org/wiki/Azimuth - -#ifndef DOXYGEN_NO_DISPATCH -namespace detail_dispatch -{ - -template -struct azimuth - : not_implemented -{}; - -template -struct azimuth -{ - template - static inline ReturnType apply(P1 const& p1, P2 const& p2, Spheroid const& spheroid) - { - return geometry::formula::vincenty_inverse().apply - ( get_as_radian<0>(p1), get_as_radian<1>(p1), - get_as_radian<0>(p2), get_as_radian<1>(p2), - spheroid ).azimuth; - } - - template - static inline ReturnType apply(P1 const& p1, P2 const& p2) - { - return apply(p1, p2, srs::spheroid()); - } -}; - -template -struct azimuth -{ - template - static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/) - { - return geometry::formula::spherical_azimuth - ( get_as_radian<0>(p1), get_as_radian<1>(p1), - get_as_radian<0>(p2), get_as_radian<1>(p2)).azimuth; - } - - template - static inline ReturnType apply(P1 const& p1, P2 const& p2) - { - return apply(p1, p2, 0); // dummy model - } -}; - -template -struct azimuth - : azimuth -{}; - -template -struct azimuth -{ - template - static inline ReturnType apply(P1 const& p1, P2 const& p2, Plane const& /*unused*/) - { - ReturnType x = get<0>(p2) - get<0>(p1); - ReturnType y = get<1>(p2) - get<1>(p1); - - // NOTE: azimuth 0 is at Y axis, increasing right - // as in spherical/geographic where 0 is at North axis - return atan2(x, y); - } - - template - static inline ReturnType apply(P1 const& p1, P2 const& p2) - { - return apply(p1, p2, 0); // dummy model - } -}; - -} // detail_dispatch -#endif // DOXYGEN_NO_DISPATCH - -#ifndef DOXYGEN_NO_DETAIL -namespace detail -{ - -/// Calculate azimuth between two points. -/// The result is in radians. -template -inline ReturnType azimuth(Point1 const& p1, Point2 const& p2) -{ - return detail_dispatch::azimuth - < - ReturnType, - typename geometry::cs_tag::type - >::apply(p1, p2); -} - -/// Calculate azimuth between two points. -/// The result is in radians. -template -inline ReturnType azimuth(Point1 const& p1, Point2 const& p2, Model const& model) -{ - return detail_dispatch::azimuth - < - ReturnType, - typename geometry::cs_tag::type - >::apply(p1, p2, model); -} - -} // namespace detail -#endif // DOXYGEN_NO_DETAIL - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP diff --git a/include/boost/geometry/algorithms/detail/course.hpp b/include/boost/geometry/algorithms/detail/course.hpp deleted file mode 100644 index 37424941b..000000000 --- a/include/boost/geometry/algorithms/detail/course.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. - -// This file was modified by Oracle on 2014. -// Modifications copyright (c) 2014, Oracle and/or its affiliates. - -// 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_DETAIL_COURSE_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP - -#include - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail -{ - -/// Calculate course (bearing) between two points. -/// -/// NOTE: left for convenience and temporary backward compatibility -template -inline ReturnType course(Point1 const& p1, Point2 const& p2) -{ - return azimuth(p1, p2); -} - -} // namespace detail -#endif // DOXYGEN_NO_DETAIL - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP diff --git a/include/boost/geometry/geometry.hpp b/include/boost/geometry/geometry.hpp index 24b12fab7..9aff956c9 100644 --- a/include/boost/geometry/geometry.hpp +++ b/include/boost/geometry/geometry.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2014-2020. -// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -60,6 +60,7 @@ BOOST_PRAGMA_MESSAGE("CAUTION: Define BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNI #include #include #include +#include #include #include #include diff --git a/include/boost/geometry/strategies/azimuth.hpp b/include/boost/geometry/strategies/azimuth.hpp index 1573ad22a..7d1e105d9 100644 --- a/include/boost/geometry/strategies/azimuth.hpp +++ b/include/boost/geometry/strategies/azimuth.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2016-2020 Oracle and/or its affiliates. +// Copyright (c) 2016-2021 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -26,7 +26,7 @@ namespace strategy { namespace azimuth { namespace services \tparam CSTag tag of coordinate system \tparam CalculationType \tparam_calculation */ -template +template struct default_strategy { BOOST_GEOMETRY_STATIC_ASSERT_FALSE( diff --git a/include/boost/geometry/strategies/azimuth/cartesian.hpp b/include/boost/geometry/strategies/azimuth/cartesian.hpp new file mode 100644 index 000000000..ac6136f89 --- /dev/null +++ b/include/boost/geometry/strategies/azimuth/cartesian.hpp @@ -0,0 +1,63 @@ +// 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_AZIMUTH_CARTESIAN_HPP +#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_CARTESIAN_HPP + + +// TODO: move this file to boost/geometry/strategy +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace azimuth +{ + +template +struct cartesian : strategies::detail::cartesian_base +{ + static auto azimuth() + { + return strategy::azimuth::cartesian(); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::azimuth::cartesian<>; +}; + + +template +struct strategy_converter > +{ + static auto get(strategy::azimuth::cartesian const&) + { + return strategies::azimuth::cartesian(); + } +}; + + +} // namespace services + +}} // namespace strategies::azimuth + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_CARTESIAN_HPP diff --git a/include/boost/geometry/strategies/azimuth/geographic.hpp b/include/boost/geometry/strategies/azimuth/geographic.hpp new file mode 100644 index 000000000..a4fac5e60 --- /dev/null +++ b/include/boost/geometry/strategies/azimuth/geographic.hpp @@ -0,0 +1,81 @@ +// 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_AZIMUTH_GEOGRAPHIC_HPP +#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_GEOGRAPHIC_HPP + + +// TODO: move this file to boost/geometry/strategy +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace azimuth +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +class geographic : strategies::detail::geographic_base +{ + using base_t = strategies::detail::geographic_base; + +public: + geographic() + : base_t() + {} + + explicit geographic(Spheroid const& spheroid) + : base_t(spheroid) + {} + + auto azimuth() const + { + return strategy::azimuth::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + using type = strategies::azimuth::geographic<>; +}; + + +template +struct strategy_converter > +{ + static auto get(strategy::azimuth::geographic const& strategy) + { + return strategies::azimuth::geographic(strategy.model()); + } +}; + +} // namespace services + +}} // namespace strategies::azimuth + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_GEOGRAPHIC_HPP diff --git a/include/boost/geometry/strategies/azimuth/services.hpp b/include/boost/geometry/strategies/azimuth/services.hpp new file mode 100644 index 000000000..11980e5a4 --- /dev/null +++ b/include/boost/geometry/strategies/azimuth/services.hpp @@ -0,0 +1,56 @@ +// 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_AZIMUTH_SERVICES_HPP +#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SERVICES_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + + +namespace strategies { namespace azimuth { + +namespace services +{ + +template +< + typename Point1, typename Point2, + typename CSTag1 = typename geometry::cs_tag::type, + typename CSTag2 = typename geometry::cs_tag::type +> +struct default_strategy +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for these Points' coordinate systems.", + Point1, Point2, CSTag1, CSTag2); +}; + +template +struct strategy_converter +{ + BOOST_GEOMETRY_STATIC_ASSERT_FALSE( + "Not implemented for this Strategy.", + Strategy); +}; + + +} // namespace services + +}} // namespace strategies::azimuth + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SERVICES_HPP diff --git a/include/boost/geometry/strategies/azimuth/spherical.hpp b/include/boost/geometry/strategies/azimuth/spherical.hpp new file mode 100644 index 000000000..a87cf927b --- /dev/null +++ b/include/boost/geometry/strategies/azimuth/spherical.hpp @@ -0,0 +1,67 @@ +// 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_AZIMUTH_SPHERICAL_HPP +#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SPHERICAL_HPP + + +// TODO: move this file to boost/geometry/strategy +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategies { namespace azimuth +{ + +template +class spherical : strategies::detail::spherical_base +{ + using base_t = strategies::detail::spherical_base; + +public: + + static auto azimuth() + { + return strategy::azimuth::spherical(); + } +}; + + +namespace services +{ + + +template +struct default_strategy +{ + using type = strategies::azimuth::spherical<>; +}; + +template +struct strategy_converter > +{ + static auto get(strategy::azimuth::spherical const&) + { + return strategies::azimuth::spherical(); + } +}; + + +} // namespace services + +}} // namespace strategies::azimuth + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SPHERICAL_HPP diff --git a/include/boost/geometry/strategies/cartesian.hpp b/include/boost/geometry/strategies/cartesian.hpp index 324424d43..33b77f698 100644 --- a/include/boost/geometry/strategies/cartesian.hpp +++ b/include/boost/geometry/strategies/cartesian.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright (c) 2020-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -36,6 +37,13 @@ struct cartesian : strategies::detail::cartesian_base return strategy::area::cartesian(); } + // azimuth + + static auto azimuth() + { + return strategy::azimuth::cartesian(); + } + // envelope template diff --git a/include/boost/geometry/strategies/cartesian/azimuth.hpp b/include/boost/geometry/strategies/cartesian/azimuth.hpp index 2ff16e945..74a9ea12b 100644 --- a/include/boost/geometry/strategies/cartesian/azimuth.hpp +++ b/include/boost/geometry/strategies/cartesian/azimuth.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2016-2018 Oracle and/or its affiliates. +// Copyright (c) 2016-2021 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -11,32 +11,81 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP +#include + #include #include +#include +#include + namespace boost { namespace geometry { namespace strategy { namespace azimuth { -template -< - typename CalculationType = void -> +template class cartesian -{}; +{ +public: + template + struct result_type + : geometry::select_most_precise + < + // NOTE: this promotes any integer type to double + typename geometry::promote_floating_point::type, + typename geometry::promote_floating_point::type, + CalculationType + > + {}; + + template + static inline void apply(T1 const& x1, T1 const& y1, + T2 const& x2, T2 const& y2, + Result& a1, Result& a2) + { + compute(x1, y1, x2, y2, a1, a2); + } + template + static inline void apply(T1 const& x1, T1 const& y1, + T2 const& x2, T2 const& y2, + Result& a1) + { + compute(x1, y1, x2, y2, a1, a1); + } + template + static inline void apply_reverse(T1 const& x1, T1 const& y1, + T2 const& x2, T2 const& y2, + Result& a2) + { + compute(x1, y1, x2, y2, a2, a2); + } + +private: + template + static inline void compute(T1 const& x1, T1 const& y1, + T2 const& x2, T2 const& y2, + Result& a1, Result& a2) + { + typedef typename result_type::type calc_t; + + // NOTE: azimuth 0 is at Y axis, increasing right + // as in spherical/geographic where 0 is at North axis + a1 = a2 = atan2(calc_t(x2) - calc_t(x1), calc_t(y2) - calc_t(y1)); + } +}; #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS namespace services { -template -struct default_strategy +template <> +struct default_strategy { - typedef strategy::azimuth::cartesian type; + typedef strategy::azimuth::cartesian<> type; }; } diff --git a/include/boost/geometry/strategies/geographic.hpp b/include/boost/geometry/strategies/geographic.hpp index 9cbaa714b..68c6e9bf2 100644 --- a/include/boost/geometry/strategies/geographic.hpp +++ b/include/boost/geometry/strategies/geographic.hpp @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -56,6 +57,16 @@ public: >(base_t::m_spheroid); } + // azimuth + + auto azimuth() const + { + return strategy::azimuth::geographic + < + FormulaPolicy, Spheroid, CalculationType + >(base_t::m_spheroid); + } + // envelope template diff --git a/include/boost/geometry/strategies/geographic/azimuth.hpp b/include/boost/geometry/strategies/geographic/azimuth.hpp index ca280313d..9e6914d92 100644 --- a/include/boost/geometry/strategies/geographic/azimuth.hpp +++ b/include/boost/geometry/strategies/geographic/azimuth.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2016-2020 Oracle and/or its affiliates. +// Copyright (c) 2016-2021 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -19,6 +19,8 @@ #include #include +#include + namespace boost { namespace geometry { @@ -34,7 +36,14 @@ template > class geographic { -public : +public: + template + struct result_type + : geometry::select_most_precise + < + T1, T2, CalculationType + > + {}; typedef Spheroid model_type; @@ -51,28 +60,28 @@ public : return m_spheroid; } - template - inline void apply(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1, T& a2) const + template + inline void apply(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1, Result& a2) const { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2); } - template - inline void apply(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1) const + template + inline void apply(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1) const { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a1); } - template - inline void apply_reverse(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a2) const + template + inline void apply_reverse(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a2) const { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, @@ -85,16 +94,13 @@ private : < bool EnableAzimuth, bool EnableReverseAzimuth, - typename T + typename T1, typename T2, typename Result > - inline void compute(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1, T& a2) const + inline void compute(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1, Result& a2) const { - typedef std::conditional_t - < - std::is_void::value, T, CalculationType - > calc_t; + typedef typename result_type::type calc_t; typedef typename FormulaPolicy::template inverse < @@ -127,14 +133,13 @@ private : namespace services { -template -struct default_strategy +template <> +struct default_strategy { typedef strategy::azimuth::geographic < strategy::andoyer, - srs::spheroid, - CalculationType + srs::spheroid > type; }; diff --git a/include/boost/geometry/strategies/spherical.hpp b/include/boost/geometry/strategies/spherical.hpp index 07bfc5235..fe060d455 100644 --- a/include/boost/geometry/strategies/spherical.hpp +++ b/include/boost/geometry/strategies/spherical.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright (c) 2020-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -55,6 +56,13 @@ public: >(base_t::m_radius); } + // azimuth + + static auto azimuth() + { + return strategy::azimuth::spherical(); + } + // envelope template diff --git a/include/boost/geometry/strategies/spherical/azimuth.hpp b/include/boost/geometry/strategies/spherical/azimuth.hpp index 32339057b..6fcb15ac9 100644 --- a/include/boost/geometry/strategies/spherical/azimuth.hpp +++ b/include/boost/geometry/strategies/spherical/azimuth.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2016-2020 Oracle and/or its affiliates. +// Copyright (c) 2016-2021 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -14,9 +14,12 @@ #include -#include #include +#include + +#include + namespace boost { namespace geometry { @@ -24,61 +27,58 @@ namespace boost { namespace geometry namespace strategy { namespace azimuth { -template -< - typename CalculationType = void -> +template class spherical { -public : +public: + template + struct result_type + : geometry::select_most_precise + < + T1, T2, CalculationType + > + {}; - inline spherical() - {} - - template - inline void apply(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1, T& a2) const + template + static inline void apply(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1, Result& a2) { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2); } - template - inline void apply(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1) const + template + static inline void apply(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1) { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a1); } - template - inline void apply_reverse(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a2) const + template + static inline void apply_reverse(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a2) { compute(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a2, a2); } -private : - +private: template < bool EnableAzimuth, bool EnableReverseAzimuth, - typename T + typename T1, typename T2, typename Result > - inline void compute(T const& lon1_rad, T const& lat1_rad, - T const& lon2_rad, T const& lat2_rad, - T& a1, T& a2) const + static inline void compute(T1 const& lon1_rad, T1 const& lat1_rad, + T2 const& lon2_rad, T2 const& lat2_rad, + Result& a1, Result& a2) { - typedef std::conditional_t - < - std::is_void::value, T, CalculationType - > calc_t; + typedef typename result_type::type calc_t; geometry::formula::result_spherical result = geometry::formula::spherical_azimuth @@ -104,19 +104,12 @@ private : namespace services { -template -struct default_strategy +template <> +struct default_strategy { - typedef strategy::azimuth::spherical type; + typedef strategy::azimuth::spherical<> type; }; -/* -template -struct default_strategy -{ - typedef strategy::azimuth::spherical type; -}; -*/ } #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS From 627e9d93b50bb60318f0bc87af58b0da37d0939d Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 13 Jan 2021 01:24:50 +0100 Subject: [PATCH 36/55] [test] Add test for newly added azimuth() algorithm. --- test/algorithms/Jamfile | 5 +-- test/algorithms/azimuth.cpp | 62 +++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 test/algorithms/azimuth.cpp diff --git a/test/algorithms/Jamfile b/test/algorithms/Jamfile index 3846cdb12..db2d1ce67 100644 --- a/test/algorithms/Jamfile +++ b/test/algorithms/Jamfile @@ -5,8 +5,8 @@ # Copyright (c) 2009-2015 Mateusz Loskot, London, UK. # Copyright (c) 2018 Adam Wulkiewicz, Lodz, Poland. # -# This file was modified by Oracle on 2014, 2015, 2016, 2017. -# Modifications copyright (c) 2014-2017, Oracle and/or its affiliates. +# This file was modified by Oracle on 2014-2021. +# Modifications copyright (c) 2014-2021, Oracle and/or its affiliates. # # Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle # Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -20,6 +20,7 @@ test-suite boost-geometry-algorithms : [ run append.cpp : : : : algorithms_append ] [ run assign.cpp : : : : algorithms_assign ] + [ run azimuth.cpp : : : : algorithms_azimuth ] [ run centroid.cpp : : : : algorithms_centroid ] [ run centroid_multi.cpp : : : : algorithms_centroid_multi ] [ run comparable_distance.cpp : : : : algorithms_comparable_distance ] diff --git a/test/algorithms/azimuth.cpp b/test/algorithms/azimuth.cpp new file mode 100644 index 000000000..98db9e255 --- /dev/null +++ b/test/algorithms/azimuth.cpp @@ -0,0 +1,62 @@ +// Boost.Geometry +// Unit Test + +// 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 + + +#include + +#include + +#include + +template +void test_one(P const& p1, P const& p2, double expected) +{ + double const result = bg::azimuth(p1, p2) * bg::math::r2d(); + BOOST_CHECK_CLOSE(result, expected, 0.0001); +} + +template +void test_car() +{ + test_one(P(0, 0), P(0, 0), 0); + test_one(P(0, 0), P(1, 1), 45); + test_one(P(0, 0), P(100, 1), 89.427061302316517); + test_one(P(0, 0), P(-1, 1), -45); + test_one(P(0, 0), P(-100, 1), -89.427061302316517); +} + +template +void test_sph() +{ + test_one(P(0, 0), P(0, 0), 0); + test_one(P(0, 0), P(1, 1), 44.995636455344851); + test_one(P(0, 0), P(100, 1), 88.984576593576293); + test_one(P(0, 0), P(-1, 1), -44.995636455344851); + test_one(P(0, 0), P(-100, 1), -88.984576593576293); +} + +template +void test_geo() +{ + test_one(P(0, 0), P(0, 0), 0); + test_one(P(0, 0), P(1, 1), 45.187718848049521); + test_one(P(0, 0), P(100, 1), 88.986933066023497); + test_one(P(0, 0), P(-1, 1), -45.187718848049521); + test_one(P(0, 0), P(-100, 1), -88.986933066023497); +} + +int test_main(int, char* []) +{ + test_car< bg::model::point >(); + test_sph< bg::model::point > >(); + test_geo< bg::model::point > >(); + + return 0; +} From 58429fb557960378c3299dde5c4a351b113d34b9 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 30 Dec 2020 14:20:43 +0100 Subject: [PATCH 37/55] [get_turn_info] minor clean up of typedefs and includes --- .../detail/overlay/get_turn_info.hpp | 80 +++++-------------- 1 file changed, 18 insertions(+), 62 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 8146c8fa0..e6fb7cd78 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -15,7 +15,6 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP - #include #include @@ -28,9 +27,6 @@ #include #include -#include - -#include #include // Silence warning C4127: conditional expression is constant @@ -131,15 +127,7 @@ struct base_turn_handler return 0; } - typedef typename select_coordinate_type - < - typename UniqueSubRange1::point_type, - typename UniqueSubRange2::point_type - >::type coordinate_type; - - typedef detail::distance_measure dm_type; - - dm_type const dm = get_distance_measure(range_p.at(range_index), range_p.at(range_index + 1), range_q.at(point_index)); + auto const dm = get_distance_measure(range_p.at(range_index), range_p.at(range_index + 1), range_q.at(point_index)); return dm.measure == 0 ? 0 : dm.measure > 0 ? 1 : -1; } @@ -226,9 +214,8 @@ struct base_turn_handler { // TODO: use comparable distance for point-point instead - but that // causes currently cycling include problems - typedef typename geometry::coordinate_type::type ctype; - ctype const dx = get<0>(a) - get<0>(b); - ctype const dy = get<1>(a) - get<1>(b); + auto const dx = get<0>(a) - get<0>(b); + auto const dy = get<1>(a) - get<1>(b); return dx * dx + dy * dy; } @@ -260,19 +247,10 @@ struct base_turn_handler // pk/q2 is considered as collinear, but there might be // a tiny measurable difference. If so, use that. // Calculate pk // qj-qk - typedef detail::distance_measure - < - typename select_coordinate_type - < - typename UniqueSubRange1::point_type, - typename UniqueSubRange2::point_type - >::type - > dm_type; - - const bool p_closer = + bool const p_closer = ti.operations[IndexP].remaining_distance < ti.operations[IndexQ].remaining_distance; - dm_type const dm + auto const dm = p_closer ? get_distance_measure(range_q.at(index_q - 1), range_q.at(index_q), range_p.at(index_p)) @@ -283,8 +261,7 @@ struct base_turn_handler { // Not truely collinear, distinguish for union/intersection // If p goes left (positive), take that for a union - - bool p_left = p_closer ? dm.is_positive() : dm.is_negative(); + bool const p_left = p_closer ? dm.is_positive() : dm.is_negative(); ti.operations[IndexP].operation = p_left ? operation_union : operation_intersection; @@ -348,14 +325,9 @@ struct touch_interior : public base_turn_handler // Therefore handle it as a normal touch (two segments arrive at the // intersection point). It currently checks for zero, but even a // distance a little bit larger would do. - typedef typename geometry::coordinate_type - < - typename UniqueSubRange::point_type - >::type coor_t; - - coor_t const location = distance_measure(info.intersections[0], non_touching_range.at(1)); - coor_t const zero = 0; - bool const result = math::equals(location, zero); + auto const dm = distance_measure(info.intersections[0], non_touching_range.at(1)); + decltype(dm) const zero = 0; + bool const result = math::equals(dm, zero); return result; } @@ -541,16 +513,8 @@ struct touch : public base_turn_handler // >----->P qj is LEFT of P1 and pi is LEFT of Q2 // (the other way round is also possible) - typedef typename select_coordinate_type - < - typename UniqueSubRange1::point_type, - typename UniqueSubRange2::point_type - >::type coordinate_type; - - typedef detail::distance_measure dm_type; - - dm_type const dm_qj_p1 = get_distance_measure(range_p.at(0), range_p.at(1), range_q.at(1)); - dm_type const dm_pi_q2 = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(0)); + auto const dm_qj_p1 = get_distance_measure(range_p.at(0), range_p.at(1), range_q.at(1)); + auto const dm_pi_q2 = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(0)); if (dm_qj_p1.measure > 0 && dm_pi_q2.measure > 0) { @@ -565,8 +529,8 @@ struct touch : public base_turn_handler return true; } - dm_type const dm_pj_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(1)); - dm_type const dm_qi_p2 = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(0)); + auto const dm_pj_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(1)); + auto const dm_qi_p2 = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(0)); if (dm_pj_q1.measure > 0 && dm_qi_p2.measure > 0) { @@ -814,17 +778,9 @@ struct equal : public base_turn_handler // They turn to the same side, or continue both collinearly // Without rescaling, to check for union/intersection, // try to check side values (without any thresholds) - typedef typename select_coordinate_type - < - typename UniqueSubRange1::point_type, - typename UniqueSubRange2::point_type - >::type coordinate_type; - - typedef detail::distance_measure dm_type; - - dm_type const dm_pk_q2 + auto const dm_pk_q2 = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(2)); - dm_type const dm_qk_p2 + auto const dm_qk_p2 = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(2)); if (dm_qk_p2.measure != dm_pk_q2.measure) @@ -989,10 +945,10 @@ struct collinear : public base_turn_handler return false; } - auto const location = distance_measure(info.intersections[1], + auto const dm = distance_measure(info.intersections[1], arrival_p == 1 ? range_q.at(1) : range_p.at(1)); - decltype(location) const zero = 0; - return math::equals(location, zero); + decltype(dm) const zero = 0; + return math::equals(dm, zero); } /* From d006d1e4ac98007de44462ede2cac48646259be2 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 13 Jan 2021 09:33:37 +0100 Subject: [PATCH 38/55] [test] add testcases from recursive_polygons_buffer partly solved by handling collinear as equal --- .../buffer/buffer_multi_polygon.cpp | 51 ++++++++++++++++++- .../set_operations/difference/difference.cpp | 2 +- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/test/algorithms/buffer/buffer_multi_polygon.cpp b/test/algorithms/buffer/buffer_multi_polygon.cpp index f5421ec44..94535088b 100644 --- a/test/algorithms/buffer/buffer_multi_polygon.cpp +++ b/test/algorithms/buffer/buffer_multi_polygon.cpp @@ -349,6 +349,34 @@ static std::string const nores_wt_1 static std::string const nores_wt_2 = "MULTIPOLYGON(((1 1,2 2,2 1,1 1)),((0 2,0 3,1 3,0 2)),((4 3,5 4,5 3,4 3)),((4 3,3 3,4 4,4 3)))"; +static std::string const nores_b8e6 + = "MULTIPOLYGON(((4 4,5 5,5 4,4 4)),((4 2,5 2,5 1,3 1,4 2)),((3 1,4 0,3 0,3 1)))"; +static std::string const nores_2881 + = "MULTIPOLYGON(((2 5,2 6,3 5,2 5)),((1 7,0 7,0 8,1 8,1 7)),((1 7,1 6,0 6,1 7)))"; +static std::string const nores_3af0 + = "MULTIPOLYGON(((1 8,0 8,0 9,1 9,1 8)),((1 8,1 7,0 7,1 8)),((2 4,3 5,3 4,2 4)),((2 6,2 7,3 6,2 6)))"; +static std::string const nores_6061 + = "MULTIPOLYGON(((2 8,2 9,3 8,2 8)),((4 3,4 4,5 4,4 3)),((7 2,7 3,8 2,7 2)),((5 3,6 4,6 3,5 3)),((2 6,3 7,3 6,2 6)),((2 3,3 2,3 1,2 1,2 3)),((2 3,3 4,3 3,2 3)))"; + +static std::string const nores_1ea1 + = "MULTIPOLYGON(((2 0,2 1,3 0,2 0)),((7 5,6 4,5 3,5 4,5 5,7 5)),((2 3,1 3,1 4,2 3)),((2 3,2 4,3 3,2 3)))"; +static std::string const nores_804e + = "MULTIPOLYGON(((4 8,4 9,5 8,4 8)),((3 9,3 10,4 10,3 9)),((0 7,0 8,1 7,0 7)),((4 6,3 6,3 7,4 6)),((4 6,4 7,5 7,4 6)))"; +static std::string const nores_37f6 + = "MULTIPOLYGON(((4 1,5 2,5 1,4 1)),((1 0,1 1,2 1,2 0,1 0)),((0 3,0 4,1 4,1 3,0 3)),((2 2,2 3,3 2,2 2)))"; + +static std::string const nores_495d + = "MULTIPOLYGON(((2 0,2 1,3 0,2 0)),((2 3,3 4,3 3,2 3)),((5 1,5 2,6 2,5 1)),((4 3,4 2,3 2,4 3)))"; + +// rescaled +static std::string const res_ebc4 + = "MULTIPOLYGON(((3 9,3 10,4 9,3 9)),((9 5,9 6,10 6,10 5,9 5)),((8 8,8 9,9 9,8 8)),((4 8,3 7,3 8,4 8)),((4 8,5 9,6 9,6 8,4 8)),((4 5,3 4,3 5,4 5)),((4 5,5 6,5 5,4 5)))"; +static std::string const res_8618 + = "MULTIPOLYGON(((6 2,7 3,7 2,6 2)),((4 3,5 4,5 3,4 3)),((3 0,3 1,4 0,3 0)),((8 7,8 8,9 8,8 7)),((0 7,0 8,1 8,1 7,0 7)),((2 2,1 2,1 3,1 4,2 4,2 2)),((2 2,2 1,1 1,2 2)))"; +static std::string const res_3b4d + = "MULTIPOLYGON(((8 0,9 1,9 0,8 0)),((3 4,2 4,2 5,2 6,3 6,3 4)),((3 4,4 3,3 3,3 4)),((3 8,3 9,4 9,3 8)),((0 5,0 6,1 6,0 5)),((7 3,8 4,8 3,7 3)),((5 5,6 6,6 5,5 5)))"; + + static std::string const neighbouring = "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)),((10 10,10 20,20 20,20 10,10 10)))"; @@ -483,7 +511,6 @@ void test_all() test_one("rt_p3", rt_p3, join_miter, end_flat, 22.3995, 1.0); test_one("rt_p4", rt_p4, join_miter, end_flat, 33.0563, 1.0); test_one("rt_p5", rt_p5, join_miter, end_flat, 17.0, 1.0); - test_one("rt_p6", rt_p6, join_miter, end_flat, 18.4853, 1.0); test_one("rt_p7", rt_p7, join_miter, end_flat, 26.2279, 1.0); test_one("rt_p8", rt_p8, join_miter, end_flat, 29.0563, 1.0); @@ -571,6 +598,26 @@ void test_all() test_one("nores_wt_1", nores_wt_1, join_round32, end_flat, 80.1609, 1.0); test_one("nores_wt_2", nores_wt_2, join_round32, end_flat, 22.1102, 1.0); + test_one("nores_b8e6", nores_b8e6, join_round32, end_flat, 19.8528, 1.0); + + test_one("nores_2881", nores_2881, join_round32, end_flat, 16.5517, 1.0); + test_one("nores_6061", nores_6061, join_round32, end_flat, 39.7371, 1.0); + test_one("nores_37f6", nores_37f6, join_round32, end_flat, 26.5339, 1.0); + +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) + // Cases not yet solved without rescaling (out of 241) + test_one("nores_1ea1", nores_1ea1, join_round32, end_flat, 28.9755, 1.0); + test_one("nores_804e", nores_804e, join_round32, end_flat, 26.4503, 1.0); + test_one("nores_3af0", nores_3af0, join_round32, end_flat, 22.1008, 1.0); + test_one("nores_495d", nores_495d, join_round32, end_flat, 23.4376, 1.0); +#endif + +#if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) + // Erroneous cases with rescaling (out of 8) + test_one("res_ebc4", res_ebc4, join_round32, end_flat, 43.8877, 1.0); + test_one("res_8618", res_8618, join_round32, end_flat, 48.1085, 1.0); + test_one("res_3b4d", res_3b4d, join_round32, end_flat, 48.4739, 1.0); +#endif test_one("neighbouring_small", neighbouring, @@ -615,7 +662,7 @@ int test_main(int, char* []) #endif #if defined(BOOST_GEOMETRY_TEST_FAILURES) - BoostGeometryWriteExpectedFailures(1, 1, 2, 3); + BoostGeometryWriteExpectedFailures(4, 6, 3, 8); #endif return 0; diff --git a/test/algorithms/set_operations/difference/difference.cpp b/test/algorithms/set_operations/difference/difference.cpp index ef6b2e140..6d3d49999 100644 --- a/test/algorithms/set_operations/difference/difference.cpp +++ b/test/algorithms/set_operations/difference/difference.cpp @@ -624,7 +624,7 @@ int test_main(int, char* []) #if defined(BOOST_GEOMETRY_TEST_FAILURES) // Not yet fully tested for float and long double. // The difference algorithm can generate (additional) slivers - BoostGeometryWriteExpectedFailures(10, 11, 24, 16); + BoostGeometryWriteExpectedFailures(10, 11, 24, 15); #endif return 0; From c267547e2e9c3f40b163d0e53ba0d7aca411772b Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 20 Jan 2021 02:34:16 +0100 Subject: [PATCH 39/55] [doc] Add documentation for azimuth() algorithm. --- doc/doxy/doxygen_input/groups/groups.hpp | 5 +- doc/imports.qbk | 4 +- doc/make_qbk.py | 4 +- doc/quickref.xml | 4 ++ doc/reference.qbk | 8 +++- doc/reference/algorithms/azimuth.qbk | 22 +++++++++ doc/src/examples/algorithms/azimuth.cpp | 42 +++++++++++++++++ .../examples/algorithms/azimuth_strategy.cpp | 46 +++++++++++++++++++ include/boost/geometry/algorithms/azimuth.hpp | 37 +++++++++++++++ 9 files changed, 165 insertions(+), 7 deletions(-) create mode 100644 doc/reference/algorithms/azimuth.qbk create mode 100644 doc/src/examples/algorithms/azimuth.cpp create mode 100644 doc/src/examples/algorithms/azimuth_strategy.cpp diff --git a/doc/doxy/doxygen_input/groups/groups.hpp b/doc/doxy/doxygen_input/groups/groups.hpp index 1caf7cf63..d2659b561 100644 --- a/doc/doxy/doxygen_input/groups/groups.hpp +++ b/doc/doxy/doxygen_input/groups/groups.hpp @@ -2,8 +2,8 @@ // // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2018-2021. +// Modifications 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,7 @@ \defgroup area area: calculate area of a Geometry \defgroup arithmetic arithmetic: arithmetic operations on points \defgroup assign assign: assign values to geometries +\defgroup azimuth azimuth: calculate azimuth of a segment defined by a pair of points \defgroup buffer buffer: calculate buffer of a geometry \defgroup centroid centroid: calculate centroid (center of gravity) of a geometry \defgroup clear clear: clear geometries diff --git a/doc/imports.qbk b/doc/imports.qbk index a184f1513..a5fdacf08 100644 --- a/doc/imports.qbk +++ b/doc/imports.qbk @@ -5,7 +5,7 @@ Copyright (c) 2009-2012 Mateusz Loskot, London, UK. Copyright (c) 2009-2012 Bruno Lalande, Paris, France. - 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 @@ -24,6 +24,8 @@ [import src/examples/algorithms/assign_3d_point.cpp] [import src/examples/algorithms/assign_inverse.cpp] [import src/examples/algorithms/assign_points.cpp] +[import src/examples/algorithms/azimuth.cpp] +[import src/examples/algorithms/azimuth_strategy.cpp] [import src/examples/algorithms/buffer_with_strategies.cpp] [import src/examples/algorithms/clear.cpp] [import src/examples/algorithms/centroid.cpp] diff --git a/doc/make_qbk.py b/doc/make_qbk.py index 8a5cb6100..f4d7881e3 100755 --- a/doc/make_qbk.py +++ b/doc/make_qbk.py @@ -6,7 +6,7 @@ # Copyright (c) 2009-2012 Mateusz Loskot (mateusz@loskot.net), London, UK # Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland # -# 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 # Use, modification and distribution is subject to the Boost Software License, @@ -96,7 +96,7 @@ def cs_to_quickbook(section): call_doxygen() algorithms = ["append", "assign", "make", "clear" - , "area", "buffer", "centroid", "convert", "correct", "covered_by" + , "area", "azimuth", "buffer", "centroid", "convert", "correct", "covered_by" , "convex_hull", "crosses", "densify", "difference" , "discrete_frechet_distance", "discrete_hausdorff_distance", "disjoint" , "distance", "envelope", "equals", "expand", "for_each", "is_empty" diff --git a/doc/quickref.xml b/doc/quickref.xml index bad6b5097..092a7f2ae 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -364,6 +364,10 @@ coordinate values) + Azimuth + + azimuth + Buffer buffer diff --git a/doc/reference.qbk b/doc/reference.qbk index aa0be56c0..a9270a5fb 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -6,8 +6,8 @@ Copyright (c) 2009-2017 Bruno Lalande, Paris, France. Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland. - This file was modified by Oracle on 2014, 2017, 2018. - Modifications copyright (c) 2014-2018, Oracle and/or its affiliates. + This file was modified by Oracle on 2014-2021. + Modifications copyright (c) 2014-2021, Oracle and/or its affiliates. Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -80,6 +80,10 @@ [include generated/append.qbk] +[section:azimuth azimuth] +[include generated/azimuth.qbk] +[endsect] + [section:buffer buffer] [include generated/buffer.qbk] [endsect] diff --git a/doc/reference/algorithms/azimuth.qbk b/doc/reference/algorithms/azimuth.qbk new file mode 100644 index 000000000..5b2606661 --- /dev/null +++ b/doc/reference/algorithms/azimuth.qbk @@ -0,0 +1,22 @@ +[/============================================================================ + Boost.Geometry + + Copyright (c) 2021, Oracle and/or its affiliates. + 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) +=============================================================================/] + +[def __this_function__ azimuth] + +[heading_conformance_no_ogc __this_function__] +[note PostGIS contains an algorithm ST_Azimuth with the same functionality. + See the [@https://postgis.net/docs/ST_Azimuth.html PostGIS documentation]. +] + +[heading Behavior] +The algorithm calculates the azimuth of a segment defined by a pair of points. + +[note The result is in radians.] diff --git a/doc/src/examples/algorithms/azimuth.cpp b/doc/src/examples/algorithms/azimuth.cpp new file mode 100644 index 000000000..0f799920a --- /dev/null +++ b/doc/src/examples/algorithms/azimuth.cpp @@ -0,0 +1,42 @@ +// Boost.Geometry +// QuickBook Example + +// Copyright (c) 2021, Oracle and/or its affiliates +// 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) + +//[azimuth +//` Shows how to calculate azimuth + +#include + +#include +#include + +int main() +{ + typedef boost::geometry::model::d2::point_xy point_type; + + point_type p1(0, 0); + point_type p2(1, 1); + + auto azimuth = boost::geometry::azimuth(p1, p2); + + std::cout << "azimuth: " << azimuth << std::endl; + + return 0; +} + +//] + +//[azimuth_output +/*` +Output: +[pre +azimuth: 0.785398 +] +*/ +//] diff --git a/doc/src/examples/algorithms/azimuth_strategy.cpp b/doc/src/examples/algorithms/azimuth_strategy.cpp new file mode 100644 index 000000000..2a8ef5178 --- /dev/null +++ b/doc/src/examples/algorithms/azimuth_strategy.cpp @@ -0,0 +1,46 @@ +// Boost.Geometry +// QuickBook Example + +// Copyright (c) 2021, Oracle and/or its affiliates +// 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) + +//[azimuth_strategy +//` Shows how to calculate azimuth in geographic coordinate system + +#include + +#include +#include + +int main() +{ + namespace bg = boost::geometry; + typedef bg::model::point > point_type; + + point_type p1(0, 0); + point_type p2(1, 1); + + bg::srs::spheroid spheroid(6378137.0, 6356752.3142451793); + bg::strategies::azimuth::geographic<> strategy(spheroid); + + auto azimuth = boost::geometry::azimuth(p1, p2, strategy); + + std::cout << "azimuth: " << azimuth << std::endl; + + return 0; +} + +//] + +//[azimuth_strategy_output +/*` +Output: +[pre +azimuth: 0.788674 +] +*/ +//] diff --git a/include/boost/geometry/algorithms/azimuth.hpp b/include/boost/geometry/algorithms/azimuth.hpp index 8403871db..b7ad8ef3d 100644 --- a/include/boost/geometry/algorithms/azimuth.hpp +++ b/include/boost/geometry/algorithms/azimuth.hpp @@ -160,6 +160,23 @@ namespace resolve_variant } // namespace resolve_variant +/*! +\brief Calculate azimuth of a segment defined by a pair of points. +\ingroup azimuth +\tparam Point1 Type of the first point of a segment. +\tparam Point2 Type of the second point of a segment. +\param point1 First point of a segment. +\param point2 Second point of a segment. +\return Azimuth in radians. + +\qbk{[include reference/algorithms/azimuth.qbk]} + +\qbk{ +[heading Example] +[azimuth] +[azimuth_output] +} +*/ template inline auto azimuth(Point1 const& point1, Point2 const& point2) { @@ -173,6 +190,26 @@ inline auto azimuth(Point1 const& point1, Point2 const& point2) } +/*! +\brief Calculate azimuth of a segment defined by a pair of points. +\ingroup azimuth +\tparam Point1 Type of the first point of a segment. +\tparam Point2 Type of the second point of a segment. +\tparam Strategy Type of an umbrella strategy defining azimuth strategy. +\param point1 First point of a segment. +\param point2 Second point of a segment. +\param strategy Umbrella strategy defining azimuth strategy. +\return Azimuth in radians. + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/azimuth.qbk]} + +\qbk{ +[heading Example] +[azimuth_strategy] +[azimuth_strategy_output] +} +*/ template inline auto azimuth(Point1 const& point1, Point2 const& point2, Strategy const& strategy) { From bceae0187c820e101d316d69b61aa09d3d961344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20=C5=81oskot?= Date: Wed, 20 Jan 2021 23:23:34 +0100 Subject: [PATCH 40/55] Add missing #include --- include/boost/geometry/algorithms/detail/relate/result.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/geometry/algorithms/detail/relate/result.hpp b/include/boost/geometry/algorithms/detail/relate/result.hpp index 03bdb8384..c7a83665b 100644 --- a/include/boost/geometry/algorithms/detail/relate/result.hpp +++ b/include/boost/geometry/algorithms/detail/relate/result.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include From 602790a3f349ca8989460afe4f2d997f8c556954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20=C5=81oskot?= Date: Thu, 28 Jan 2021 22:58:12 +0100 Subject: [PATCH 41/55] Display in README.md we are a C++14 header-only library --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3470ac8c4..f8350de1a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ![Boost.Geometry](doc/other/logo/logo_bkg.png) -Boost.Geometry, part of collection of the [Boost C++ Libraries](http://github.com/boostorg), defines concepts, primitives and algorithms for solving geometry problems. +Boost.Geometry, part of collection of the [Boost C++ Libraries](http://github.com/boostorg), defines concepts, primitives and algorithms for solving geometry problems. Boost.Geometry is a C++14 header-only library. [![Licence](https://img.shields.io/badge/license-boost-4480cc.png)](http://www.boost.org/LICENSE_1_0.txt) [![Documentation](https://img.shields.io/badge/-documentation-4480cc.png)](http://boost.org/libs/geometry) From 9eb674d64f61c3ab057c8e5bfa236b6536c82408 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 31 Jan 2021 22:23:05 +0100 Subject: [PATCH 42/55] [strategies] Remove usage of equals() algorithm from side strategies. --- .../strategies/cartesian/side_by_triangle.hpp | 12 ++++----- .../geometry/strategies/geographic/side.hpp | 25 ++++++++----------- .../spherical/side_by_cross_track.hpp | 20 ++++++--------- 3 files changed, 25 insertions(+), 32 deletions(-) diff --git a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp index e53eac893..ea58e78e7 100644 --- a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp +++ b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015-2020. -// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2021. +// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -24,17 +24,17 @@ #include #include -#include -#include -#include +#include #include #include #include #include -#include +#include + +#include namespace boost { namespace geometry diff --git a/include/boost/geometry/strategies/geographic/side.hpp b/include/boost/geometry/strategies/geographic/side.hpp index 6f2de5277..901d4eba1 100644 --- a/include/boost/geometry/strategies/geographic/side.hpp +++ b/include/boost/geometry/strategies/geographic/side.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014-2020. -// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -23,20 +23,17 @@ #include -#include -#include -#include - -#include - -#include - +//#include #include #include #include #include -//#include +#include + +#include +#include +#include namespace boost { namespace geometry { @@ -110,9 +107,9 @@ public: template inline int apply(P1 const& p1, P2 const& p2, P const& p) const { - if (geometry::equals(p, p1, equals_point_point_strategy_type()) - || geometry::equals(p, p2, equals_point_point_strategy_type()) - || geometry::equals(p1, p2, equals_point_point_strategy_type())) + if (equals_point_point_strategy_type::apply(p, p1) + || equals_point_point_strategy_type::apply(p, p2) + || equals_point_point_strategy_type::apply(p1, p2)) { return 0; } diff --git a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp index 6cbc5cedc..b5cdb032b 100644 --- a/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/side_by_cross_track.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014-2017. -// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-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 @@ -15,24 +15,20 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP -#include - -#include #include +#include #include #include +//#include +#include #include #include #include #include -#include -//#include - - namespace boost { namespace geometry { @@ -56,9 +52,9 @@ public : { typedef strategy::within::spherical_point_point equals_point_point_strategy_type; - if (geometry::equals(p, p1, equals_point_point_strategy_type()) - || geometry::equals(p, p2, equals_point_point_strategy_type()) - || geometry::equals(p1, p2, equals_point_point_strategy_type())) + if (equals_point_point_strategy_type::apply(p, p1) + || equals_point_point_strategy_type::apply(p, p2) + || equals_point_point_strategy_type::apply(p1, p2)) { return 0; } From c7adc567b0381faeb153272dbf8e68936007e6e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20=C5=81oskot?= Date: Thu, 11 Feb 2021 23:37:09 +0100 Subject: [PATCH 43/55] Fix MSVC warning C4267: '=': conversion from 'size_t' to 'int' (#798) --- .../extensions/algorithms/detail/overlay/dissolver.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/geometry/extensions/algorithms/detail/overlay/dissolver.hpp b/include/boost/geometry/extensions/algorithms/detail/overlay/dissolver.hpp index 02aef91d0..86c430cc6 100644 --- a/include/boost/geometry/extensions/algorithms/detail/overlay/dissolver.hpp +++ b/include/boost/geometry/extensions/algorithms/detail/overlay/dissolver.hpp @@ -433,7 +433,7 @@ struct dissolver_generic // There are less then 16 elements, handle them quadraticly - int n = boost::size(output_collection); + std::size_t n = boost::size(output_collection); for(iterator_type it1 = boost::begin(index_vector); it1 != boost::end(index_vector); @@ -520,7 +520,7 @@ struct dissolver_generic boost::end(output_collection)), helper_vector, strategy, - n, 1); + static_cast(n), 1); return changed; } @@ -577,8 +577,8 @@ struct dissolver_generic std::vector unioned_collection; - int size = 0, previous_size = 0; - int n = 0; + std::size_t size = 0, previous_size = 0; + std::size_t n = 0; bool changed = false; while(divide_and_conquer<1> From 0cfe9ae1d24bd043e3d0746e27bbb60885013a79 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 12 Feb 2021 00:26:16 +0100 Subject: [PATCH 44/55] [ci] Add repositories for GH workflows with ubuntu-latest. --- .github/workflows/minimal-clang.yml | 7 +++++-- .github/workflows/minimal-gcc.yml | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/minimal-clang.yml b/.github/workflows/minimal-clang.yml index cceca7af6..b772f0b5b 100644 --- a/.github/workflows/minimal-clang.yml +++ b/.github/workflows/minimal-clang.yml @@ -92,8 +92,11 @@ jobs: - name: Install run: | - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 15CF4D18AF4F7421 - sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main" + # Required for compilers not available in ubuntu latest + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main" + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe" + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic main" + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic universe" sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt -q -y update sudo apt -q -y install clang-${{ matrix.version }} g++-multilib diff --git a/.github/workflows/minimal-gcc.yml b/.github/workflows/minimal-gcc.yml index 72e8288ab..f08521486 100644 --- a/.github/workflows/minimal-gcc.yml +++ b/.github/workflows/minimal-gcc.yml @@ -80,9 +80,11 @@ jobs: - name: Install run: | - # gcc-4.8 is not available in Bionic anymore + # Required for compilers not available in ubuntu latest sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main" sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe" + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic main" + sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ bionic universe" sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt -q -y update sudo apt -q -y install g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib From 4a444b0b775c5885a6809d25e1a9a2842a5766e8 Mon Sep 17 00:00:00 2001 From: Tristan Carel Date: Sat, 13 Feb 2021 19:13:44 +0100 Subject: [PATCH 45/55] Fix build in index serialization Fixes #807 --- include/boost/geometry/index/detail/serialization.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/boost/geometry/index/detail/serialization.hpp b/include/boost/geometry/index/detail/serialization.hpp index 14961d7f4..7397790ca 100644 --- a/include/boost/geometry/index/detail/serialization.hpp +++ b/include/boost/geometry/index/detail/serialization.hpp @@ -396,7 +396,7 @@ private: if ( current_level < leafs_level ) { - node_pointer n = rtree::create_node::apply(allocators); // MAY THROW (A) + node_pointer n = rtree::create_node::apply(allocators); // MAY THROW (A) subtree_destroyer auto_remover(n, allocators); internal_node & in = rtree::get(*n); @@ -419,7 +419,7 @@ private: { BOOST_GEOMETRY_INDEX_ASSERT(current_level == leafs_level, "unexpected value"); - node_pointer n = rtree::create_node::apply(allocators); // MAY THROW (A) + node_pointer n = rtree::create_node::apply(allocators); // MAY THROW (A) subtree_destroyer auto_remover(n, allocators); leaf & l = rtree::get(*n); @@ -546,10 +546,11 @@ void load(Archive & ar, boost::geometry::index::rtree & rt, unsig typedef typename view::options_type options_type; typedef typename view::box_type box_type; typedef typename view::allocators_type allocators_type; + typedef typename view::members_holder members_holder; typedef typename options_type::parameters_type parameters_type; typedef typename allocators_type::node_pointer node_pointer; - typedef detail::rtree::subtree_destroyer subtree_destroyer; + typedef detail::rtree::subtree_destroyer subtree_destroyer; view tree(rt); @@ -563,7 +564,7 @@ void load(Archive & ar, boost::geometry::index::rtree & rt, unsig if ( 0 < values_count ) { size_type loaded_values_count = 0; - n = detail::rtree::load + n = detail::rtree::load ::apply(ar, version, leafs_level, loaded_values_count, params, tree.members().translator(), tree.members().allocators()); // MAY THROW subtree_destroyer remover(n, tree.members().allocators()); From accec61743a3e9be288ac4b6e8318ee1b4aa8913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joni=20Kerkel=C3=A4?= Date: Mon, 15 Feb 2021 10:22:58 +0200 Subject: [PATCH 46/55] Add tests for extensions/algorithms/parse.hpp (#802) Closes #788 --- extensions/test/algorithms/Jamfile | 1 + extensions/test/algorithms/parse.cpp | 179 +++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 extensions/test/algorithms/parse.cpp diff --git a/extensions/test/algorithms/Jamfile b/extensions/test/algorithms/Jamfile index c52a0383b..1f77ed79c 100644 --- a/extensions/test/algorithms/Jamfile +++ b/extensions/test/algorithms/Jamfile @@ -14,6 +14,7 @@ test-suite boost-geometry-extensions-algorithms [ run distance_info.cpp ] [ run connect.cpp ] # [ run offset.cpp ] + [ run parse.cpp ] [ run midpoints.cpp ] # [ run selected.cpp ] ; diff --git a/extensions/test/algorithms/parse.cpp b/extensions/test/algorithms/parse.cpp new file mode 100644 index 000000000..84e0930a7 --- /dev/null +++ b/extensions/test/algorithms/parse.cpp @@ -0,0 +1,179 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// Unit Test + +// Copyright (c) 2021 Joni Kerkelä, Oulu, Finland. + +// 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) + +#include + +#include +#include +#include +#include +#include + +#include + + +using namespace boost::geometry; + +template +void test_parse(std::string const& coordinate_1, std::string const& coordinate_2, + double expected_result_coord_1, double expected_result_coord_2) +{ + auto geo_point_result = parse

(coordinate_1, coordinate_2); + BOOST_CHECK_CLOSE(((double)bg::get<0>(geo_point_result)), expected_result_coord_1, 1.0e-6); + BOOST_CHECK_CLOSE(((double)bg::get<1>(geo_point_result)), expected_result_coord_2, 1.0e-6); + + P p; + parse(p, coordinate_1, coordinate_2); + BOOST_CHECK_CLOSE(((double)bg::get<0>(p)), expected_result_coord_1, 1.0e-6); + BOOST_CHECK_CLOSE(((double)bg::get<1>(p)), expected_result_coord_2, 1.0e-6); +} + +template +void test_parse_with_parse_strategy(std::string const& coordinate_1, std::string const& coordinate_2, + double expected_result_coord_1, double expected_result_coord_2, S const& strategy) +{ + P p; + parse(p, coordinate_1, coordinate_2, strategy); + BOOST_CHECK_CLOSE(((double)bg::get<0>(p)), expected_result_coord_1, 1.0e-6); + BOOST_CHECK_CLOSE(((double)bg::get<1>(p)), expected_result_coord_2, 1.0e-6); +} + +template +void test_parse_with_point_and_parse_strategy(std::string const& coordinate_1, std::string const& coordinate_2, + double expected_result_coord_1, double expected_result_coord_2, T const& parser) +{ + test_parse_with_parse_strategy(coordinate_1, + coordinate_2, expected_result_coord_1, expected_result_coord_2, parser); +} + +template +void test_all_complex_dms_strategy() +{ + typedef typename coordinate_type

::type coord_t; + typedef typename projections::detail::dms_parser parser_t; + + // with minutes + double expected_dms_result1 = as_radian ? 5.166666666 * bg::math::d2r() : 5.166666666; + double expected_dms_result2 = as_radian ? -5.166666666 * bg::math::d2r() : -5.166666666; + test_parse_with_point_and_parse_strategy(std::string("5d10E"), std::string("5d10N"), + expected_dms_result1, expected_dms_result2, parser_t()); + + // with minutes and indicator + double expected_dms_result3 = as_radian ? (5.16666666 * bg::math::d2r()) : 5.16666666; + double expected_dms_result4 = as_radian ? -(5.16666666 * bg::math::d2r()) : -5.16666666; + test_parse_with_point_and_parse_strategy(std::string("5d10'E"), std::string("5d10'N"), + expected_dms_result3, expected_dms_result4, parser_t()); + + // with minutes/seconds + double expected_dms_result5 = as_radian ? (5.1680555555 * bg::math::d2r()) : 5.1680555555; + double expected_dms_result6 = as_radian ? -(5.16805555555 * bg::math::d2r()) : -5.16805555555; + test_parse_with_point_and_parse_strategy(std::string("5d10'05E"), std::string("5d10'05N"), + expected_dms_result5, expected_dms_result6, parser_t()); + + // with seconds only + double sec = 1 / 3600.0; + double expected_dms_result7 = as_radian ? ((5 + sec) * bg::math::d2r()) : (5 + sec); + double expected_dms_result8 = as_radian ? -((5 + sec) * bg::math::d2r()) : -(5 + sec); + test_parse_with_point_and_parse_strategy(std::string("5d1\"E"), std::string("5d1\"N"), + expected_dms_result7, expected_dms_result8, parser_t()); + + // with spaces and signs + test_parse_with_point_and_parse_strategy(std::string("5d 1\" E"), std::string("5d 1\" N"), + expected_dms_result7, expected_dms_result8, parser_t()); + + test_parse_with_point_and_parse_strategy(std::string("+5d 1\" E"), std::string("+5d 1\" N"), + expected_dms_result7, expected_dms_result8, parser_t()); + + test_parse_with_point_and_parse_strategy(std::string("-5d 1\" E"), std::string("-5d 1\" N"), + -expected_dms_result7, -expected_dms_result8, parser_t()); + + test_parse_with_point_and_parse_strategy(std::string("5d 10' 05 E"), std::string("5d 10' 05 N"), + expected_dms_result5, expected_dms_result6, parser_t()); + + // in radians + double expected_dms_result9 = as_radian ? 5.15 : (5.15 * bg::math::r2d()); + double expected_dms_result10 = as_radian ? -5.15 : -(5.15 * bg::math::r2d()); + test_parse_with_point_and_parse_strategy(std::string("5.15RE"), std::string("5.15RN"), + expected_dms_result9, expected_dms_result10, parser_t()); + + test_parse_with_point_and_parse_strategy(std::string("5.15R E"), std::string("5.15R N"), + expected_dms_result9, expected_dms_result10, parser_t()); +} + +template +void test_all_with_simple_dms_strategy() +{ + typedef typename coordinate_type

::type coord_t; + + double generic_expected_result1 = as_radian ? 2 * bg::math::d2r() : 2; + double generic_expected_result2 = as_radian ? -4 * bg::math::d2r() : -4; + + typedef typename projections::detail::dms_parser parser_t1; + test_parse_with_point_and_parse_strategy(std::string("2e"), std::string("4n"), + generic_expected_result1, generic_expected_result2, parser_t1()); + + test_parse_with_point_and_parse_strategy(std::string("2w"), std::string("4s"), + generic_expected_result2, generic_expected_result1, parser_t1()); + + test_parse_with_point_and_parse_strategy(std::string("2w"), std::string("4e"), + 2 * generic_expected_result1, generic_expected_result1, parser_t1()); + + test_parse_with_point_and_parse_strategy(std::string("2s"), std::string("4n"), + -(generic_expected_result1), generic_expected_result2, parser_t1()); + + test_parse_with_point_and_parse_strategy(std::string("4n"), std::string("2s"), + -(generic_expected_result1), generic_expected_result2, parser_t1()); + + typedef typename projections::detail::dms_parser parser_t2; + test_parse_with_point_and_parse_strategy(std::string("2o"), std::string("4z"), + generic_expected_result1, generic_expected_result2, parser_t2()); + + typedef typename projections::detail::dms_parser parser_t3; + test_parse_with_point_and_parse_strategy(std::string("4N"), std::string("2S"), + -(generic_expected_result1), generic_expected_result2, parser_t3()); + + test_parse_with_point_and_parse_strategy(std::string("4n"), std::string("2s"), + -(generic_expected_result1), generic_expected_result2, parser_t3()); +} + + +void test_all_without_strategy() +{ + test_parse > >(std::string("1E"), + std::string("2N"), 1 * bg::math::d2r(), 2 * bg::math::d2r()); + test_parse > >(std::string("1W"), + std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); + test_parse > >(std::string("1E"), + std::string("2N"), 1 * bg::math::d2r(), 2 * bg::math::d2r()); + test_parse > >(std::string("1W"), + std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); + test_parse > >(std::string("1W"), + std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); + test_parse > >(std::string("1W"), + std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); + test_parse >(std::string("1W"), + std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); + test_parse >(std::string("1W"), + std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); +} + +void test_all() +{ + test_all_without_strategy(); + test_all_with_simple_dms_strategy >, false>(); + test_all_with_simple_dms_strategy >, true>(); + test_all_complex_dms_strategy >, false>(); + test_all_complex_dms_strategy >, true>(); +} + +int test_main(int, char* []) +{ + test_all(); + return 0; +} From 3b0898389abd8dec839f6564c6ccf748f6b38c1f Mon Sep 17 00:00:00 2001 From: Ayush Gupta <55524855+ayushgupta138@users.noreply.github.com> Date: Mon, 15 Feb 2021 23:49:44 +0530 Subject: [PATCH 47/55] Update unit test for parse.hpp (#806) Initial implementation of the tests have been added in #802 These are further improvements to those tests. --- extensions/test/algorithms/parse.cpp | 114 ++++++++++++++++++--------- 1 file changed, 77 insertions(+), 37 deletions(-) diff --git a/extensions/test/algorithms/parse.cpp b/extensions/test/algorithms/parse.cpp index 84e0930a7..c1eae4f34 100644 --- a/extensions/test/algorithms/parse.cpp +++ b/extensions/test/algorithms/parse.cpp @@ -2,36 +2,38 @@ // Unit Test // Copyright (c) 2021 Joni Kerkelä, Oulu, Finland. +// Copyright (c) 2021 Ayush Gupta, Gujarat, India // 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) +#include #include #include #include #include #include -#include #include - using namespace boost::geometry; -template -void test_parse(std::string const& coordinate_1, std::string const& coordinate_2, - double expected_result_coord_1, double expected_result_coord_2) +template +void test_parse(std::string const& coordinate_1, + std::string const& coordinate_2, + T expected_result_coord_1, + T expected_result_coord_2) { - auto geo_point_result = parse

(coordinate_1, coordinate_2); - BOOST_CHECK_CLOSE(((double)bg::get<0>(geo_point_result)), expected_result_coord_1, 1.0e-6); - BOOST_CHECK_CLOSE(((double)bg::get<1>(geo_point_result)), expected_result_coord_2, 1.0e-6); + Geometry geometry; + geometry = parse(coordinate_1, coordinate_2); + BOOST_CHECK_CLOSE(((double)bg::get<0>(geometry)), expected_result_coord_1, 1.0e-4); + BOOST_CHECK_CLOSE(((double)bg::get<1>(geometry)), expected_result_coord_2, 1.0e-4); - P p; - parse(p, coordinate_1, coordinate_2); - BOOST_CHECK_CLOSE(((double)bg::get<0>(p)), expected_result_coord_1, 1.0e-6); - BOOST_CHECK_CLOSE(((double)bg::get<1>(p)), expected_result_coord_2, 1.0e-6); + parse(geometry, coordinate_1, coordinate_2); + BOOST_CHECK_CLOSE(((double)bg::get<0>(geometry)), expected_result_coord_1, 1.0e-4); + BOOST_CHECK_CLOSE(((double)bg::get<1>(geometry)), expected_result_coord_2, 1.0e-4); } template @@ -40,8 +42,8 @@ void test_parse_with_parse_strategy(std::string const& coordinate_1, std::string { P p; parse(p, coordinate_1, coordinate_2, strategy); - BOOST_CHECK_CLOSE(((double)bg::get<0>(p)), expected_result_coord_1, 1.0e-6); - BOOST_CHECK_CLOSE(((double)bg::get<1>(p)), expected_result_coord_2, 1.0e-6); + BOOST_CHECK_CLOSE(((double)bg::get<0>(p)), expected_result_coord_1, 1.0e-4); + BOOST_CHECK_CLOSE(((double)bg::get<1>(p)), expected_result_coord_2, 1.0e-4); } template @@ -56,7 +58,7 @@ template void test_all_complex_dms_strategy() { typedef typename coordinate_type

::type coord_t; - typedef typename projections::detail::dms_parser parser_t; + using parser_t = projections::detail::dms_parser; // with minutes double expected_dms_result1 = as_radian ? 5.166666666 * bg::math::d2r() : 5.166666666; @@ -104,17 +106,37 @@ void test_all_complex_dms_strategy() test_parse_with_point_and_parse_strategy(std::string("5.15R E"), std::string("5.15R N"), expected_dms_result9, expected_dms_result10, parser_t()); + + // test with random characters in strategy(for generality check) + using parser_t1 = bg::projections::detail::dms_parser; + + + test_parse_with_point_and_parse_strategy(std::string("45o 30m 30s A"), std::string("120o 30m 45s D"), + -2.1033408163, 0.7942705942, parser_t1()); + + test_parse_with_point_and_parse_strategy(std::string("1.75p c"), std::string("5o 40m 55s b"), + 0.0991686810, -1.7500000000, parser_t1()); + + // creating another strategy with returning value as degree + using parser_t2 = bg::projections::detail::dms_parser; // return value in degree and rest parameters as default value. + + + test_parse_with_point_and_parse_strategy(std::string("80d 45' 30\"S"), std::string("150d 30' 30\"E"), + 150.5083333333, -80.7583333333, parser_t2()); + test_parse_with_point_and_parse_strategy(std::string("15d 10' 20\"N"), std::string("2.75r W"), + -157.5633261332, 15.1722222222, parser_t2()); + } template void test_all_with_simple_dms_strategy() { - typedef typename coordinate_type

::type coord_t; + using coord_t = typename coordinate_type

::type; double generic_expected_result1 = as_radian ? 2 * bg::math::d2r() : 2; double generic_expected_result2 = as_radian ? -4 * bg::math::d2r() : -4; - typedef typename projections::detail::dms_parser parser_t1; + using parser_t1 = projections::detail::dms_parser; test_parse_with_point_and_parse_strategy(std::string("2e"), std::string("4n"), generic_expected_result1, generic_expected_result2, parser_t1()); @@ -130,42 +152,59 @@ void test_all_with_simple_dms_strategy() test_parse_with_point_and_parse_strategy(std::string("4n"), std::string("2s"), -(generic_expected_result1), generic_expected_result2, parser_t1()); - typedef typename projections::detail::dms_parser parser_t2; + using parser_t2 = projections::detail::dms_parser; test_parse_with_point_and_parse_strategy(std::string("2o"), std::string("4z"), generic_expected_result1, generic_expected_result2, parser_t2()); - typedef typename projections::detail::dms_parser parser_t3; + using parser_t3 = projections::detail::dms_parser; test_parse_with_point_and_parse_strategy(std::string("4N"), std::string("2S"), -(generic_expected_result1), generic_expected_result2, parser_t3()); test_parse_with_point_and_parse_strategy(std::string("4n"), std::string("2s"), -(generic_expected_result1), generic_expected_result2, parser_t3()); + } - +template void test_all_without_strategy() { - test_parse > >(std::string("1E"), - std::string("2N"), 1 * bg::math::d2r(), 2 * bg::math::d2r()); - test_parse > >(std::string("1W"), - std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); - test_parse > >(std::string("1E"), - std::string("2N"), 1 * bg::math::d2r(), 2 * bg::math::d2r()); - test_parse > >(std::string("1W"), - std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); - test_parse > >(std::string("1W"), - std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); - test_parse > >(std::string("1W"), - std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); - test_parse >(std::string("1W"), - std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); - test_parse >(std::string("1W"), - std::string("2S"), -1 * bg::math::d2r(), -2 * bg::math::d2r()); + using T = typename bg::coordinate_type::type; + T const d2r = math::d2r(); + + test_parse(std::string("1E"), std::string("2N"), 1 * d2r, 2 * d2r); + test_parse(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r); + test_parse(std::string("1E"), std::string("2N"), 1 * d2r, 2 * d2r); + test_parse(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r); + test_parse(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r); + test_parse(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r); + test_parse(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r); + test_parse(std::string("1W"), std::string("2S"), -1 * d2r, -2 * d2r); + + // tests for dms strings, values returned in radian(default strategy). + test_parse(std::string("45d 30' 30\" N"), std::string("120D 30'45\"W"), -2.1033408163, 0.7942705942); + test_parse(std::string("32D45' 57\"n"), std::string("170d 10' 25\"E"), 2.9700910868, 0.5718719189); + test_parse(std::string("5d38'40\"S"), std::string("168D 10' 20\"w"), -2.9351602461, -0.0985141822); + test_parse(std::string("72D 20'45\"s"), std::string("5d 40' 55\"e"), 0.0991686810, -1.2626735329); + + // test for radian and dms strings combined returning values in degree. + test_parse(std::string("2.5r N"), std::string("0.75r E"), 0.7500000000, 2.5000000000); + test_parse(std::string("1.25r S"), std::string("120D 30' 45\"w"), -2.1033408163, -1.2500000000); } +void test_without_strategy() +{ + test_all_without_strategy>>(); + test_all_without_strategy>>(); + test_all_without_strategy>>(); + test_all_without_strategy>>(); + test_all_without_strategy>>(); + test_all_without_strategy>>(); + test_all_without_strategy>(); + test_all_without_strategy>(); +} void test_all() { - test_all_without_strategy(); + test_without_strategy(); test_all_with_simple_dms_strategy >, false>(); test_all_with_simple_dms_strategy >, true>(); test_all_complex_dms_strategy >, false>(); @@ -177,3 +216,4 @@ int test_main(int, char* []) test_all(); return 0; } + From 920de2ca6accfc6aea8d8d72c5c044dc25db181a Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 16 Feb 2021 13:06:32 +0100 Subject: [PATCH 48/55] [algorithms] Remove unneeded comments, change names and indentation. --- include/boost/geometry/algorithms/buffer.hpp | 10 +++++----- .../detail/buffer/buffer_inserter.hpp | 20 +++++++++---------- .../buffer/buffered_piece_collection.hpp | 11 ++++------ .../detail/covered_by/interface.hpp | 6 ++---- .../algorithms/detail/disjoint/interface.hpp | 6 ++---- .../algorithms/detail/equals/interface.hpp | 6 ++---- .../detail/intersection/areal_areal.hpp | 6 +----- .../algorithms/detail/is_simple/areal.hpp | 8 +++++--- .../algorithms/detail/overlaps/interface.hpp | 6 ++---- .../algorithms/detail/overlay/get_turns.hpp | 8 ++++---- .../algorithms/detail/touches/interface.hpp | 5 ++--- .../algorithms/detail/within/interface.hpp | 6 ++---- 12 files changed, 41 insertions(+), 57 deletions(-) diff --git a/include/boost/geometry/algorithms/buffer.hpp b/include/boost/geometry/algorithms/buffer.hpp index 74523f11c..453b14873 100644 --- a/include/boost/geometry/algorithms/buffer.hpp +++ b/include/boost/geometry/algorithms/buffer.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2017-2020. -// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2021. +// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -245,11 +245,11 @@ inline void buffer(GeometryIn const& geometry_in, typename strategies::relate::services::default_strategy < GeometryIn, GeometryIn - >::type strategy; + >::type strategies; rescale_policy_type rescale_policy = boost::geometry::get_rescale_policy( - box, strategy); + box, strategies); detail::buffer::buffer_inserter(geometry_in, range::back_inserter(geometry_out), @@ -258,7 +258,7 @@ inline void buffer(GeometryIn const& geometry_in, join_strategy, end_strategy, point_strategy, - strategy, + strategies, rescale_policy); } diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index 86318d76e..aefa6e7a6 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017-2020. -// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2021. +// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -921,7 +921,7 @@ template typename JoinStrategy, typename EndStrategy, typename PointStrategy, - typename Strategy, + typename Strategies, typename RobustPolicy, typename VisitPiecesPolicy > @@ -931,7 +931,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator JoinStrategy const& join_strategy, EndStrategy const& end_strategy, PointStrategy const& point_strategy, - Strategy const& strategy, + Strategies const& strategies, RobustPolicy const& robust_policy, VisitPiecesPolicy& visit_pieces_policy ) @@ -941,11 +941,11 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator typedef detail::buffer::buffered_piece_collection < typename geometry::ring_type::type, - Strategy, + Strategies, DistanceStrategy, RobustPolicy > collection_type; - collection_type collection(strategy, distance_strategy, robust_policy); + collection_type collection(strategies, distance_strategy, robust_policy); collection_type const& const_collection = collection; bool const areal = util::is_areal::value; @@ -962,7 +962,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator >::apply(geometry_input, collection, distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, - robust_policy, strategy.side()); // pass strategy? + robust_policy, strategies.side()); // pass strategies? collection.get_turns(); if (BOOST_GEOMETRY_CONDITION(areal)) @@ -1029,7 +1029,7 @@ template typename JoinStrategy, typename EndStrategy, typename PointStrategy, - typename Strategy, + typename Strategies, typename RobustPolicy > inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out, @@ -1038,14 +1038,14 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator JoinStrategy const& join_strategy, EndStrategy const& end_strategy, PointStrategy const& point_strategy, - Strategy const& strategy, + Strategies const& strategies, RobustPolicy const& robust_policy) { detail::buffer::visit_pieces_default_policy visitor; buffer_inserter(geometry_input, out, distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, - strategy, robust_policy, visitor); + strategies, robust_policy, visitor); } #endif // DOXYGEN_NO_DETAIL diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index a7f600e43..6c852bd65 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2016-2020. -// Modifications copyright (c) 2016-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2021. +// Modifications copyright (c) 2016-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -1027,16 +1027,13 @@ struct buffered_piece_collection { continue; } - if (detail::disjoint::disjoint_point_box(point, - original.m_box, - m_strategy)) + if (detail::disjoint::disjoint_point_box(point, original.m_box,m_strategy)) { continue; } int const geometry_code - = detail::within::point_in_geometry(point, original.m_ring, - m_strategy); + = detail::within::point_in_geometry(point, original.m_ring, m_strategy); if (geometry_code == -1) { diff --git a/include/boost/geometry/algorithms/detail/covered_by/interface.hpp b/include/boost/geometry/algorithms/detail/covered_by/interface.hpp index 3d7804adb..d1b4db2a6 100644 --- a/include/boost/geometry/algorithms/detail/covered_by/interface.hpp +++ b/include/boost/geometry/algorithms/detail/covered_by/interface.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013-2020. -// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2021. +// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -89,7 +89,6 @@ struct covered_by Geometry2 const& geometry2, Strategy const& strategy) { - //using strategies::covered_by::services::strategy_converter; using strategies::relate::services::strategy_converter; return covered_by @@ -108,7 +107,6 @@ struct covered_by Geometry2 const& geometry2, default_strategy) { - //typedef typename strategies::covered_by::services::default_strategy typedef typename strategies::relate::services::default_strategy < Geometry1, diff --git a/include/boost/geometry/algorithms/detail/disjoint/interface.hpp b/include/boost/geometry/algorithms/detail/disjoint/interface.hpp index 0af19dced..b7df7345c 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/interface.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/interface.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2020. -// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2021. +// Modifications copyright (c) 2013-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -71,7 +71,6 @@ struct disjoint Geometry2 const& geometry2, Strategy const& strategy) { - //using strategies::disjoint::services::strategy_converter; using strategies::relate::services::strategy_converter; return dispatch::disjoint @@ -90,7 +89,6 @@ struct disjoint Geometry2 const& geometry2, default_strategy) { - //typedef typename strategies::disjoint::services::default_strategy typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 diff --git a/include/boost/geometry/algorithms/detail/equals/interface.hpp b/include/boost/geometry/algorithms/detail/equals/interface.hpp index 93d8674e5..bd31e8c2c 100644 --- a/include/boost/geometry/algorithms/detail/equals/interface.hpp +++ b/include/boost/geometry/algorithms/detail/equals/interface.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014-2020. -// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -123,7 +123,6 @@ struct equals Geometry2 const& geometry2, Strategy const& strategy) { - //using strategies::equals::services::strategy_converter; using strategies::relate::services::strategy_converter; return dispatch::equals @@ -142,7 +141,6 @@ struct equals Geometry2 const& geometry2, default_strategy) { - //typedef typename strategies::within::services::default_strategy typedef typename strategies::relate::services::default_strategy < Geometry1, diff --git a/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp b/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp index bda208ea7..9faa1df55 100644 --- a/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp +++ b/include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright (c) 2020-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. @@ -109,10 +109,6 @@ struct intersection_areal_areal_ < areal::index, TupledOut >::type areal_out_type; - //typedef typename geometry::tuples::element - // < - // pointlike::index, TupledOut - // >::type pointlike_out_type; // NOTE: The same robust_policy is used in each call of // intersection_insert. Is that correct? diff --git a/include/boost/geometry/algorithms/detail/is_simple/areal.hpp b/include/boost/geometry/algorithms/detail/is_simple/areal.hpp index 6496591c8..3c716331b 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/areal.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/areal.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2020, Oracle and/or its affiliates. +// Copyright (c) 2014-2021, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -54,8 +54,10 @@ inline bool are_simple_interior_rings(InteriorRings const& interior_rings, { auto const end = boost::end(interior_rings); return std::find_if(boost::begin(interior_rings), end, - [&](auto const& r) { return ! is_simple_ring(r, strategy); }) - == end; // non-simple ring not found + [&](auto const& r) + { + return ! is_simple_ring(r, strategy); + }) == end; // non-simple ring not found // allow empty ring } diff --git a/include/boost/geometry/algorithms/detail/overlaps/interface.hpp b/include/boost/geometry/algorithms/detail/overlaps/interface.hpp index 527ec1600..fbe0ffdae 100644 --- a/include/boost/geometry/algorithms/detail/overlaps/interface.hpp +++ b/include/boost/geometry/algorithms/detail/overlaps/interface.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2014-2020. -// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -92,7 +92,6 @@ struct overlaps Geometry2 const& geometry2, Strategy const& strategy) { - //using strategies::overlaps::services::strategy_converter; using strategies::relate::services::strategy_converter; return dispatch::overlaps < @@ -110,7 +109,6 @@ struct overlaps Geometry2 const& geometry2, default_strategy) { - //typedef typename strategies::overlaps::services::default_strategy typedef typename strategies::relate::services::default_strategy < Geometry1, Geometry2 diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index d2e2734f7..45db3d252 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014-2020. -// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2021. +// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -187,9 +187,9 @@ private : // So advance to the "non duplicate next" // (the check is defensive, to avoid endless loops) std::size_t check = 0; - while(! detail::disjoint::disjoint_point_point( + while (! detail::disjoint::disjoint_point_point( current_robust_point, next_robust_point, m_strategy) - && check++ < m_section.range_count) + && check++ < m_section.range_count) { circular_iterator++; geometry::recalculate(next_robust_point, *circular_iterator, m_robust_policy); diff --git a/include/boost/geometry/algorithms/detail/touches/interface.hpp b/include/boost/geometry/algorithms/detail/touches/interface.hpp index 4000d79c6..39d997463 100644 --- a/include/boost/geometry/algorithms/detail/touches/interface.hpp +++ b/include/boost/geometry/algorithms/detail/touches/interface.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2020. -// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2021. +// Modifications copyright (c) 2013-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -112,7 +112,6 @@ struct touches Geometry2 const& geometry2, Strategy const& strategy) { - //using strategies::touches::services::strategy_converter; using strategies::relate::services::strategy_converter; return dispatch::touches diff --git a/include/boost/geometry/algorithms/detail/within/interface.hpp b/include/boost/geometry/algorithms/detail/within/interface.hpp index 362f1dc38..1a10ca84d 100644 --- a/include/boost/geometry/algorithms/detail/within/interface.hpp +++ b/include/boost/geometry/algorithms/detail/within/interface.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013-2020. -// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2021. +// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -92,7 +92,6 @@ struct within Geometry2 const& geometry2, Strategy const& strategy) { - //using strategies::within::services::strategy_converter; using strategies::relate::services::strategy_converter; return within @@ -111,7 +110,6 @@ struct within Geometry2 const& geometry2, default_strategy) { - //typedef typename strategies::within::services::default_strategy typedef typename strategies::relate::services::default_strategy < Geometry1, From b1e5362d5968cfa00eee8d2e311288bd7358ce14 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 16 Feb 2021 14:24:10 +0100 Subject: [PATCH 49/55] [azimuth] Make variables const. --- include/boost/geometry/algorithms/azimuth.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/geometry/algorithms/azimuth.hpp b/include/boost/geometry/algorithms/azimuth.hpp index b7ad8ef3d..2e97eed2f 100644 --- a/include/boost/geometry/algorithms/azimuth.hpp +++ b/include/boost/geometry/algorithms/azimuth.hpp @@ -70,10 +70,10 @@ struct azimuth >::type calc_t; calc_t result = 0; - calc_t x1 = geometry::get_as_radian<0>(p1); - calc_t y1 = geometry::get_as_radian<1>(p1); - calc_t x2 = geometry::get_as_radian<0>(p2); - calc_t y2 = geometry::get_as_radian<1>(p2); + calc_t const x1 = geometry::get_as_radian<0>(p1); + calc_t const y1 = geometry::get_as_radian<1>(p1); + calc_t const x2 = geometry::get_as_radian<0>(p2); + calc_t const y2 = geometry::get_as_radian<1>(p2); strategy.azimuth().apply(x1, y1, x2, y2, result); From 1f16b72cd639858fade03e02918d46c718bcc818 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 16 Feb 2021 15:25:11 +0100 Subject: [PATCH 50/55] [strategies] Remove redundent comments. --- include/boost/geometry/strategies/cartesian.hpp | 6 +----- include/boost/geometry/strategies/geographic.hpp | 6 +----- include/boost/geometry/strategies/spherical.hpp | 4 ---- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/include/boost/geometry/strategies/cartesian.hpp b/include/boost/geometry/strategies/cartesian.hpp index 4d3c22e05..9b4559ad4 100644 --- a/include/boost/geometry/strategies/cartesian.hpp +++ b/include/boost/geometry/strategies/cartesian.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright (c) 2020-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -36,15 +36,11 @@ class cartesian { public: - // azimuth - static auto azimuth() { return strategy::azimuth::cartesian(); } - // point_order - static auto point_order() { return strategy::point_order::cartesian(); diff --git a/include/boost/geometry/strategies/geographic.hpp b/include/boost/geometry/strategies/geographic.hpp index 635109f2d..815f1e3f3 100644 --- a/include/boost/geometry/strategies/geographic.hpp +++ b/include/boost/geometry/strategies/geographic.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2020, Oracle and/or its affiliates. +// Copyright (c) 2020-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -51,8 +51,6 @@ public: : base_t(spheroid) {} - // azimuth - auto azimuth() const { return strategy::azimuth::geographic @@ -61,8 +59,6 @@ public: >(base_t::m_spheroid); } - // point_order - auto point_order() const { return strategy::point_order::geographic diff --git a/include/boost/geometry/strategies/spherical.hpp b/include/boost/geometry/strategies/spherical.hpp index c72e0deeb..07495e857 100644 --- a/include/boost/geometry/strategies/spherical.hpp +++ b/include/boost/geometry/strategies/spherical.hpp @@ -54,15 +54,11 @@ public: >::apply(radius_or_sphere); } - // azimuth - static auto azimuth() { return strategy::azimuth::spherical(); } - // point_order - static auto point_order() { return strategy::point_order::spherical(); From a941645547c98c0d2fdc7b831761cf2c9929d7da Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 16 Feb 2021 15:35:38 +0100 Subject: [PATCH 51/55] [test][azimuth] Add tests with non-default vincenty formula. --- test/algorithms/azimuth.cpp | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/test/algorithms/azimuth.cpp b/test/algorithms/azimuth.cpp index 98db9e255..541884771 100644 --- a/test/algorithms/azimuth.cpp +++ b/test/algorithms/azimuth.cpp @@ -15,10 +15,23 @@ #include -template -void test_one(P const& p1, P const& p2, double expected) + +template +auto call_azimuth(P const& p1, P const& p2, S const& s) { - double const result = bg::azimuth(p1, p2) * bg::math::r2d(); + return bg::azimuth(p1, p2, s); +} + +template +auto call_azimuth(P const& p1, P const& p2, bg::default_strategy const&) +{ + return bg::azimuth(p1, p2); +} + +template +void test_one(P const& p1, P const& p2, double expected, S const& s = S()) +{ + double const result = call_azimuth(p1, p2, s) * bg::math::r2d(); BOOST_CHECK_CLOSE(result, expected, 0.0001); } @@ -52,11 +65,24 @@ void test_geo() test_one(P(0, 0), P(-100, 1), -88.986933066023497); } +template +void test_geo_v() +{ + bg::strategies::azimuth::geographic s; + + test_one(P(0, 0), P(0, 0), 0, s); + test_one(P(0, 0), P(1, 1), 45.188040229339755, s); + test_one(P(0, 0), P(100, 1), 88.986914518230208, s); + test_one(P(0, 0), P(-1, 1), -45.188040229339755, s); + test_one(P(0, 0), P(-100, 1), -88.986914518230208, s); +} + int test_main(int, char* []) { test_car< bg::model::point >(); test_sph< bg::model::point > >(); test_geo< bg::model::point > >(); + test_geo_v< bg::model::point > >(); return 0; } From 2a048f7be420af57b6aa6fb924d45570891cb0ce Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 16 Feb 2021 16:15:12 +0100 Subject: [PATCH 52/55] [distance] Add missing include. --- .../geometry/algorithms/detail/distance/segment_to_box.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp index 0bf37569b..296df7ef6 100644 --- a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp +++ b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2020 Oracle and/or its affiliates. +// Copyright (c) 2014-2021 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -48,6 +48,9 @@ #include #include +// TEMP - remove when distance umbrella strategies are implemented +#include + namespace boost { namespace geometry { From 5c1fffb1ea35d422de65d942b119adcce2c9b639 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 16 Feb 2021 17:17:55 +0100 Subject: [PATCH 53/55] [overlay] Fix warnings: unused type and signed/unsigned comparison. --- .../detail/overlay/copy_segment_point.hpp | 19 ++++++++----------- .../detail/overlay/select_rings.hpp | 5 ++--- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp index e9b9a2f04..154b2bb7f 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2020. -// Modifications copyright (c) 2020, Oracle and/or its affiliates. +// This file was modified by Oracle on 2020-2021. +// Modifications copyright (c) 2020-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -77,9 +77,9 @@ struct copy_segment_point_range std::size_t const segment_count = boost::size(view) - 1; signed_size_type const target = circular_offset(segment_count, seg_id.segment_index, offset); + BOOST_GEOMETRY_ASSERT(target >= 0 + && std::size_t(target) < boost::size(view)); - BOOST_GEOMETRY_ASSERT(target >= 0); - BOOST_GEOMETRY_ASSERT(target < boost::size(view)); geometry::convert(range::at(view, target), point); return true; @@ -124,8 +124,8 @@ struct copy_segment_point_box assign_box_corners_oriented(box, bp); signed_size_type const target = circular_offset(4, seg_id.segment_index, offset); - BOOST_GEOMETRY_ASSERT(target >= 0); - BOOST_GEOMETRY_ASSERT(target < bp.size()); + BOOST_GEOMETRY_ASSERT(target >= 0 + && std::size_t(target) < bp.size()); point = bp[target]; return true; @@ -146,11 +146,8 @@ struct copy_segment_point_multi SegmentIdentifier const& seg_id, signed_size_type offset, PointOut& point) { - BOOST_GEOMETRY_ASSERT - ( - seg_id.multi_index >= 0 - && seg_id.multi_index < int(boost::size(multi)) - ); + BOOST_GEOMETRY_ASSERT(seg_id.multi_index >= 0 + && std::size_t(seg_id.multi_index) < boost::size(multi)); // Call the single-version return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, offset, point); diff --git a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp index 5b4af8513..1f4313336 100644 --- a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2017-2020. -// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017-2021. +// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -349,7 +349,6 @@ inline void select_rings(Geometry const& geometry, Strategy const& strategy) { typedef typename geometry::tag::type tag; - typedef typename geometry::point_type::type point_type; RingPropertyMap all_ring_properties; dispatch::select_rings::apply(geometry, From b786bd9dd98ce2e72ae9594af1fb2ce8619512e0 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 16 Feb 2021 17:44:12 +0100 Subject: [PATCH 54/55] [test][setops] Fix gcc error caused by incorrect passing of interrupt_policy into get_turns. --- .../set_operations/test_get_turns_ll_invariance.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp index face7df2b..77463a53d 100644 --- a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp +++ b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2020, Oracle and/or its affiliates. +// Copyright (c) 2014-2021, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -79,6 +79,7 @@ private: Strategy const& strategy) { turns.clear(); + bg_detail::get_turns::no_interrupt_policy interrupt_policy; bg_detail::relate::turns::get_turns < LinearGeometry1, @@ -90,7 +91,7 @@ private: assign_policy > >::apply(turns, linear1, linear2, - bg_detail::get_turns::no_interrupt_policy(), + interrupt_policy, strategy); } From 3802d235d1d04c8624202053c3a05349c47230c5 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 17 Feb 2021 17:01:21 +0100 Subject: [PATCH 55/55] [example][index] Fix serialization example. --- index/example/serialize.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index/example/serialize.cpp b/index/example/serialize.cpp index 11ce08bc0..bc50371d5 100644 --- a/index/example/serialize.cpp +++ b/index/example/serialize.cpp @@ -1,7 +1,7 @@ // Boost.Geometry Index // Additional tests -// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2021 Adam Wulkiewicz, Lodz, Poland. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -25,13 +25,13 @@ #include #include -template ::value> +template ::value> struct print_tuple { template static inline Os & apply(Os & os, T const& t) { - os << boost::get(t) << ", "; + os << std::get(t) << ", "; return print_tuple::apply(os, t); } }; @@ -51,7 +51,7 @@ int main() namespace bg = boost::geometry; namespace bgi = bg::index; - typedef boost::tuple S; + typedef std::tuple S; typedef bg::model::point P; typedef bg::model::box

B; @@ -81,7 +81,7 @@ int main() std::cout << "vector and tree created in: " << t.elapsed() << std::endl; print_tuple::apply(std::cout, bgi::detail::rtree::utilities::statistics(tree)) << std::endl; - std::cout << boost::get<0>(s) << std::endl; + std::cout << std::get<0>(s) << std::endl; BOOST_FOREACH(V const& v, tree | bgi::adaptors::queried(bgi::intersects(q))) std::cout << bg::wkt(v) << std::endl;