From e314795dbb0a0d1218dc4cbdf3449772ad5eeb2e Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 15 Mar 2019 17:28:48 +0100 Subject: [PATCH 01/68] [formulas] Add asserts for validity of azimuth passed to thomas_direct and differential_quantities. --- include/boost/geometry/formulas/differential_quantities.hpp | 4 ++++ include/boost/geometry/formulas/thomas_direct.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/include/boost/geometry/formulas/differential_quantities.hpp b/include/boost/geometry/formulas/differential_quantities.hpp index 6d4c22328..6e1658abe 100644 --- a/include/boost/geometry/formulas/differential_quantities.hpp +++ b/include/boost/geometry/formulas/differential_quantities.hpp @@ -11,6 +11,7 @@ #ifndef BOOST_GEOMETRY_FORMULAS_INVERSE_DIFFERENTIAL_QUANTITIES_HPP #define BOOST_GEOMETRY_FORMULAS_INVERSE_DIFFERENTIAL_QUANTITIES_HPP +#include #include #include @@ -73,6 +74,9 @@ public: CT const sig_12 = dlon / one_minus_f; if (BOOST_GEOMETRY_CONDITION(EnableReducedLength)) { + CT const pi = math::pi(); + BOOST_GEOMETRY_ASSERT(-pi <= azimuth && azimuth <= pi); + int azi_sign = math::sign(azimuth) >= 0 ? 1 : -1; // for antipodal CT m12 = azi_sign * sin(sig_12) * b; reduced_length = m12; diff --git a/include/boost/geometry/formulas/thomas_direct.hpp b/include/boost/geometry/formulas/thomas_direct.hpp index 7b61616af..2218ea995 100644 --- a/include/boost/geometry/formulas/thomas_direct.hpp +++ b/include/boost/geometry/formulas/thomas_direct.hpp @@ -15,6 +15,7 @@ #include +#include #include #include @@ -80,6 +81,8 @@ public: CT const pi = math::pi(); CT const pi_half = pi / c2; + BOOST_GEOMETRY_ASSERT(-pi <= azimuth12 && azimuth12 <= pi); + // keep azimuth small - experiments show low accuracy // if the azimuth is closer to (+-)180 deg. CT azi12_alt = azimuth12; From 7f703fd5a64de66969bb301c0394683f91782aee Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 15 Mar 2019 17:30:38 +0100 Subject: [PATCH 02/68] [strategies][buffer] Make sure geographic azimuth is in valid range in geographic_point_circle. --- .../geometry/strategies/geographic/buffer_point_circle.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/geometry/strategies/geographic/buffer_point_circle.hpp b/include/boost/geometry/strategies/geographic/buffer_point_circle.hpp index 7e7c8fe81..8e9662c5d 100644 --- a/include/boost/geometry/strategies/geographic/buffer_point_circle.hpp +++ b/include/boost/geometry/strategies/geographic/buffer_point_circle.hpp @@ -88,6 +88,7 @@ public : > direct_t; calculation_type const two_pi = geometry::math::two_pi(); + calculation_type const pi = geometry::math::pi(); calculation_type const diff = two_pi / calculation_type(m_count); // TODO: after calculation of some angles is corrected, @@ -96,6 +97,9 @@ public : for (std::size_t i = 0; i < m_count; i++, angle += diff) { + if (angle > pi) + angle -= two_pi; + typename direct_t::result_type dir_r = direct_t::apply(get_as_radian<0>(point), get_as_radian<1>(point), buffer_distance, angle, From bfe704419f91bab1370bcd4b369ff6a939c04133 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 27 Mar 2019 09:18:47 +0100 Subject: [PATCH 03/68] [overlay] add starting turns, and improvements in turn_info w.r.t. collinearity --- .../overlay/enrich_intersection_points.hpp | 13 +- .../detail/overlay/get_distance_measure.hpp | 188 +++++++++++++++ .../algorithms/detail/overlay/get_ring.hpp | 15 +- .../detail/overlay/get_turn_info.hpp | 227 ++++++++++++++++-- .../detail/overlay/handle_colocations.hpp | 114 ++++++++- .../detail/overlay/sort_by_side.hpp | 17 +- .../algorithms/detail/overlay/turn_info.hpp | 2 +- 7 files changed, 528 insertions(+), 48 deletions(-) create mode 100644 include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp 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 287a06b08..0fe2f02cf 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -53,9 +53,9 @@ namespace detail { namespace overlay { template -struct discarded_turn +struct discarded_indexed_turn { - discarded_turn(Turns const& turns) + discarded_indexed_turn(Turns const& turns) : m_turns(turns) {} @@ -272,7 +272,7 @@ inline void enrich_adapt(Operations& operations, Turns& turns) } // Remove discarded turns from operations to avoid having them as next turn - discarded_turn const predicate(turns); + discarded_indexed_turn const predicate(turns); operations.erase(std::remove_if(boost::begin(operations), boost::end(operations), predicate), boost::end(operations)); } @@ -426,6 +426,13 @@ inline void enrich_intersection_points(Turns& turns, std::vector > mapped_vector_type; + // As long as turn indexes are not used yet, turns might be erased from + // the vector + detail::overlay::erase_colocated_start_turns(turns, geometry1, geometry2); + + // From here on, turn indexes are used (in clusters, next_index, etc) + // and may only be flagged as discarded + bool has_cc = false; bool const has_colocations = detail::overlay::handle_colocations(turns, diff --git a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp new file mode 100644 index 000000000..2c622c753 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp @@ -0,0 +1,188 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2019 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) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP + +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct distance_measure +{ + T value; + + distance_measure() + : value(T()) + {} + + bool is_small() const { return true; } + bool is_zero() const { return true; } + bool is_positive() const { return false; } +}; + +template +struct distance_measure_floating +{ + T measure; + + distance_measure_floating() + : measure(T()) + {} + + // Returns true if the distance measure is small. + // This is an arbitrary boundary, to enable some behaviour + // (for example include or exclude turns), which are checked later + // with other conditions. + bool is_small() const { return std::fabs(measure) < 1.0e-3; } + + // Returns true if the distance measure is absolutely zero + bool is_zero() const { return measure == 0.0; } + + // Returns true if the distance measure is positive. Distance measure + // algorithm should return positive value if it is located on the left side. + bool is_positive() const { return measure > 0.0; } +}; + +template <> +struct distance_measure + : public distance_measure_floating {}; + +template <> +struct distance_measure + : public distance_measure_floating {}; + +template <> +struct distance_measure + : public distance_measure_floating {}; + +} // detail + + +namespace detail_dispatch +{ + +template +struct get_distance_measure + : not_implemented +{}; + +template +struct get_distance_measure +{ + typedef detail::distance_measure result_type; + + template + static result_type apply(SegmentPoint const& p1, SegmentPoint const& p2, + Point const& p) + { + typedef CalculationType ct; + + // Construct a line in general form (ax + by + c = 0), + // (will be replaced by a general_form structure in next PR) + ct const x1 = geometry::get<0>(p1); + ct const y1 = geometry::get<1>(p1); + ct const x2 = geometry::get<0>(p2); + ct const y2 = geometry::get<1>(p2); + ct const a = y1 - y2; + ct const b = x2 - x1; + ct const c = -a * x1 - b * y1; + + // Returns a distance measure + // https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_an_equation + // dividing by sqrt(a*a+b*b) is not necessary for this distance measure, + // it is not a real distance and purpose is to detect small differences + // in collinearity + result_type result; + result.measure = a * geometry::get<0>(p) + b * geometry::get<1>(p) + c; + + return result; + } +}; + +template +struct get_distance_measure +{ + typedef detail::distance_measure result_type; + + template + static result_type apply(SegmentPoint const& , SegmentPoint const& , + Point const& ) + { + // TODO, optional + result_type result; + return result; + } +}; + +template +struct get_distance_measure +{ + typedef detail::distance_measure result_type; + + template + static result_type apply(SegmentPoint const& , SegmentPoint const& , + Point const& ) + { + // TODO, optional + result_type result; + return result; + } +}; +template +struct get_distance_measure +{ + typedef detail::distance_measure result_type; + + template + static result_type apply(SegmentPoint const& , SegmentPoint const& , + Point const& ) + { + // TODO, optional + result_type result; + return result; + } +}; + + +} // namespace detail_dispatch + +namespace detail +{ + +// Returns a (often very tiny) value to indicate its side, and distance, +// 0 (absolutely 0, not even an epsilon) means collinear. Like side, +// a negative means that p is to the right of p1-p2. And a positive value +// means that p is to the left of p1-p2. +template +static distance_measure::type> +get_distance_measure(SegmentPoint const& p1, SegmentPoint const& p2, Point const& p) +{ + return detail_dispatch::get_distance_measure + < + typename select_coordinate_type::type, + typename geometry::cs_tag::type + >::apply(p1, p2, p); + +} + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_DISTANCE_MEASURE_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp b/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp index 460c30def..07e984b19 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include @@ -49,8 +51,6 @@ struct get_ring }; - - template<> struct get_ring { @@ -113,6 +113,17 @@ struct get_ring }; +template +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. + return geometry::num_points(detail::overlay::get_ring::apply(rid, geometry), true) - 1; +} + }} // namespace detail::overlay #endif // DOXYGEN_NO_DETAIL 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 6d92b1bd3..31c6563af 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -21,11 +21,12 @@ #include #include +#include #include #include +#include #include -#include #include @@ -142,6 +143,51 @@ struct base_turn_handler ctype const dy = get<1>(a) - get<1>(b); return dx * dx + dy * dy; } + + template + < + std::size_t IndexP, + std::size_t IndexQ, + typename UniqueSubRange1, + typename UniqueSubRange2, + typename TurnInfo + > + static inline void both_collinear(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, + std::size_t index_p, std::size_t index_q, + TurnInfo& ti) + { +#if ! defined(BOOST_GEOMETRY_USE_RESCALING) + ti.operations[IndexP].remaining_distance = distance_measure(ti.point, range_p.at(index_p)); + ti.operations[IndexQ].remaining_distance = distance_measure(ti.point, range_q.at(index_q)); + + // 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; + + dm_type const dm = get_distance_measure(range_q.at(index_q - 1), + range_q.at(index_q), range_p.at(index_p)); + + if (! dm.is_zero()) + { + // Not truely collinear, distinguish for union/intersection + // If p goes left (positive), take that for a union + ui_else_iu(dm.is_positive(), ti); + return; + } +#endif + + both(ti, operation_continue); + } + }; @@ -266,19 +312,8 @@ struct touch_interior : public base_turn_handler // Q intersects on interior of P and continues collinearly if (side_qk_q == side_qi_p) { - // Collinearly in the same direction - // (Q comes from left of P and turns left, - // OR Q comes from right of P and turns right) - // Omit second intersection point. - // Union: just continue - // Intersection: just continue - both(ti, operation_continue); - - // Calculate remaining distance. - // Q arrives at p, at point qj, so use qk for q - // and use pj for p - ti.operations[index_p].remaining_distance = distance_measure(ti.point, range_p.at(1)); - ti.operations[index_q].remaining_distance = distance_measure(ti.point, range_q.at(2)); + both_collinear(range_p, range_q, 1, 2, ti); + return; } else { @@ -369,13 +404,12 @@ struct touch : public base_turn_handler // (#BRL2) if (side_pk_q2 == 0 && ! block_q) { - both(ti, operation_continue); + both_collinear<0, 1>(range_p, range_q, 2, 2, ti); return; } int const side_pk_q1 = has_pk && has_qk ? side.pk_wrt_q1() : 0; - // Collinear opposite case -> block P // (#BRL4, #BLR8) if (side_pk_q1 == 0) @@ -538,7 +572,7 @@ struct equal : public base_turn_handler // oppositely if (side_pk_q2 == 0 && side_pk_p == side_qk_p) { - both(ti, operation_continue); + both_collinear<0, 1>(range_p, range_q, 2, 2, ti); return; } @@ -560,6 +594,130 @@ struct equal : public base_turn_handler }; +template +< + typename TurnInfo +> +struct start : public base_turn_handler +{ + template + < + typename UniqueSubRange1, + typename UniqueSubRange2, + typename IntersectionInfo, + typename DirInfo, + typename SidePolicy + > + static inline bool apply(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, + TurnInfo& ti, + IntersectionInfo const& info, + DirInfo const& dir_info, + SidePolicy const& side) + { +#if defined(BOOST_GEOMETRY_USE_RESCALING) + // If rescaled, it is not necessary to handle start turns + return false; +#endif + + if (dir_info.opposite) + { + // They should not be collinear + return false; + } + + int const side_pj_q1 = side.pj_wrt_q1(); + int const side_qj_p1 = side.qj_wrt_p1(); + + // Get side values at starting point + typedef detail::distance_measure + < + typename select_coordinate_type + < + typename UniqueSubRange1::point_type, + typename UniqueSubRange2::point_type + >::type + > dm_type; + + dm_type const dm_pi_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(0)); + dm_type const dm_qi_p1 = get_distance_measure(range_p.at(0), range_p.at(1), range_q.at(0)); + + if (dir_info.how_a == -1 && dir_info.how_b == -1) + { + // Both p and q leave + if (dm_pi_q1.is_zero() && dm_qi_p1.is_zero()) + { + // Exactly collinear, not necessary to handle it + return false; + } + + if (! (dm_pi_q1.is_small() && dm_qi_p1.is_small())) + { + // Not nearly collinear + return false; + } + + if (side_qj_p1 == 0) + { + // Collinear is not handled + return false; + } + + ui_else_iu(side_qj_p1 == -1, ti); + } + else if (dir_info.how_b == -1) + { + // p ---------------> + // | + // | q q leaves + // v + // + + if (dm_qi_p1.is_zero() || ! dm_qi_p1.is_small()) + { + // Exactly collinear + return false; + } + + if (side_qj_p1 == 0) + { + // Collinear is not handled + return false; + } + + ui_else_iu(side_qj_p1 == -1, ti); + } + else if (dir_info.how_a == -1) + { + if (dm_pi_q1.is_zero() || ! dm_pi_q1.is_small()) + { + // It starts exactly, not necessary to handle it + return false; + } + + // p leaves + if (side_pj_q1 == 0) + { + // Collinear is not handled + return false; + } + + ui_else_iu(side_pj_q1 == 1, ti); + } + else + { + // Not supported + return false; + } + + // Copy intersection point + assign_point(ti, method_start, info, 0); + return true; + } + +}; + + template < typename TurnInfo, @@ -978,18 +1136,13 @@ struct get_turn_info // Copy, to copy possibly extended fields TurnInfo tp = tp_model; + bool do_only_convert = false; + // Select method and apply switch(method) { - case 'a' : // collinear, "at" - case 'f' : // collinear, "from" - case 's' : // starts from the middle - if (AssignPolicy::include_no_turn - && inters.i_info().count > 0) - { - only_convert::apply(tp, inters.i_info()); - *out++ = tp; - } + case 'a' : // "angle" + do_only_convert = true; break; case 'd' : // disjoint: never do anything @@ -1030,6 +1183,20 @@ struct get_turn_info *out++ = tp; } break; + case 'f' : + case 's' : + { + // "from" or "start" without rescaling, it is in some cases necessary to handle + if (start::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides())) + { + *out++ = tp; + } + else + { + do_only_convert = true; + } + } + break; case 'e': { if ( ! inters.d_info().opposite ) @@ -1105,6 +1272,14 @@ struct get_turn_info break; } + if (do_only_convert + && AssignPolicy::include_no_turn + && inters.i_info().count > 0) + { + only_convert::apply(tp, inters.i_info()); + *out++ = tp; + } + return out; } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp index 6bb30fcce..1ba54ae6b 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp @@ -22,9 +22,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -82,6 +84,14 @@ struct turn_operation_index signed_size_type op_index; // only 0,1 }; +struct is_discarded +{ + template + inline bool operator()(Turn const& turn) const + { + return turn.discarded; + } +}; template struct less_by_fraction_and_type @@ -246,7 +256,7 @@ inline void handle_colocation_cluster(Turns& turns, turn_type& turn = turns[toi.turn_index]; turn_operation_type const& op = turn.operations[toi.op_index]; - BOOST_ASSERT(ref_op.seg_id == op.seg_id); + BOOST_GEOMETRY_ASSERT(ref_op.seg_id == op.seg_id); if (ref_op.fraction == op.fraction) { @@ -256,7 +266,7 @@ inline void handle_colocation_cluster(Turns& turns, { ref_id = add_turn_to_cluster(ref_turn, cluster_per_segment, cluster_id); } - BOOST_ASSERT(ref_id != -1); + BOOST_GEOMETRY_ASSERT(ref_id != -1); // ref_turn (both operations) are already added to cluster, // so also "op" is already added to cluster, @@ -504,6 +514,100 @@ inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters) } } +template +inline segment_identifier get_preceding_segment_id(segment_identifier const& id, + Geometry0 const& geometry0, Geometry1 const& geometry1) +{ + segment_identifier result = id; + + if (result.segment_index == 0) + { + // Assign to segment_count before decrement + result.segment_index + = id.source_index == 0 + ? segment_count_on_ring(geometry0, id) + : segment_count_on_ring(geometry1, id); + } + + result.segment_index--; + + return result; +} + +// Turns marked with method can be generated but are often duplicate, +// unless (by floating point precision) the preceding touching turn is just missed. +// This means that all (nearly) colocated with preceding touching turn +// can be deleted. This is done before colocation itself (because in colocated, +// they are only discarded, and that can give issues in traversal) +template +inline void erase_colocated_start_turns(Turns& turns, + Geometry0 const& geometry0, Geometry1 const& geometry1) +{ + typedef std::pair seg_id_pair; + typedef std::map map_type; + + typedef typename boost::range_value::type turn_type; + typedef typename boost::range_iterator::type turn_it; + typedef map_type::const_iterator map_it; + + // Collect starting turns into map + map_type preceding_segments; + std::size_t turn_index = 0; + for (turn_it it = boost::begin(turns); it != boost::end(turns); ++it, ++turn_index) + { + turn_type const& turn = *it; + if (turn.method == method_start) + { + // Insert identifiers for preceding segments of both operations. + // (For self turns geometry1 == geometry2) + seg_id_pair const pair( + get_preceding_segment_id(turn.operations[0].seg_id, geometry0, geometry1), + get_preceding_segment_id(turn.operations[1].seg_id, geometry0, geometry1)); + + // There should exist only one turn with such ids + BOOST_GEOMETRY_ASSERT(preceding_segments.find(pair) == preceding_segments.end()); + + preceding_segments[pair] = turn_index; + } + } + + if (preceding_segments.empty()) + { + return; + } + + // Find touching turns on preceding segment id combinations + bool has_discarded = false; + for (turn_it it = boost::begin(turns); it != boost::end(turns); ++it) + { + turn_type const& turn = *it; + if (turn.method == method_touch) + { + seg_id_pair const pair(turn.operations[0].seg_id, + turn.operations[1].seg_id); + + map_it mit = preceding_segments.find(pair); + + if (mit != preceding_segments.end()) + { + // The found touching turn precedes the found starting turn. + // (To be completely sure we could verify if turn.point is (nearly) equal) + // These turns are duplicate, discard the starting turn. + has_discarded = true; + turn_type& extra_turn = turns[mit->second]; + extra_turn.discarded = true; + } + } + } + + if (has_discarded) + { + turns.erase(std::remove_if(boost::begin(turns), boost::end(turns), + is_discarded()), + boost::end(turns)); + } +} + template < overlay_type OverlayType, @@ -537,11 +641,7 @@ inline void set_colocation(Turns& turns, Clusters const& clusters) for (set_iterator it = ids.begin(); it != ids.end(); ++it) { turn_type& turn = turns[*it]; - - if (both_target) - { - turn.has_colocated_both = true; - } + turn.has_colocated_both = true; } } } 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 74f438775..eae68403e 100644 --- a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -301,17 +300,17 @@ public : { 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; } // Take wrap into account - // Suppose ring_count=10 (10 points, 9 segments), dep.seg_id=7, op.seg_id=2, then distance=10-9+2 - // Generic function (is this used somewhere else too?) - ring_identifier const rid(op.seg_id.source_index, op.seg_id.multi_index, op.seg_id.ring_index); - signed_size_type const segment_count - (op.seg_id.source_index == 0 - ? geometry::num_points(detail::overlay::get_ring::type>::apply(rid, geometry1)) - : geometry::num_points(detail::overlay::get_ring::type>::apply(rid, geometry2))); - return ((segment_count - 1) - departure_seg_id.segment_index) + op.seg_id.segment_index; + // 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; } void apply(Point const& turn_point) diff --git a/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp index 545b5e902..e976bdb03 100644 --- a/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp @@ -33,6 +33,7 @@ enum method_type method_touch_interior, method_collinear, method_equal, + method_start, method_error }; @@ -92,7 +93,6 @@ struct turn_info bool touch_only; // True in case of method touch(interior) and lines do not cross signed_size_type cluster_id; // For multiple turns on same location, > 0. Else -1. 0 is unused. bool discarded; - bool has_colocated_both; // Colocated with a uu turn (for union) or ii (other) Container operations; From 68f87ebfcafa69655918c85deaaa7349c9216aab Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 3 Apr 2019 13:57:44 +0200 Subject: [PATCH 04/68] [traversal] avoid early finish when no points were included --- .../algorithms/detail/overlay/traversal.hpp | 23 +++++++++++-------- .../detail/overlay/traversal_ring_creator.hpp | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp index 3a7d82ce0..831d5e395 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp @@ -1128,22 +1128,25 @@ public : int previous_op_index, signed_size_type previous_turn_index, segment_identifier const& previous_seg_id, - bool is_start) + bool is_start, bool has_points) { turn_type const& current_turn = m_turns[turn_index]; if (BOOST_GEOMETRY_CONDITION(target_operation == operation_intersection)) { - bool const back_at_start_cluster - = current_turn.is_clustered() - && m_turns[start_turn_index].cluster_id == current_turn.cluster_id; - - if (turn_index == start_turn_index || back_at_start_cluster) + if (has_points) { - // Intersection can always be finished if returning - turn_index = start_turn_index; - op_index = start_op_index; - return true; + bool const back_at_start_cluster + = current_turn.is_clustered() + && m_turns[start_turn_index].cluster_id == current_turn.cluster_id; + + if (turn_index == start_turn_index || back_at_start_cluster) + { + // Intersection can always be finished if returning + turn_index = start_turn_index; + op_index = start_op_index; + return true; + } } if (! current_turn.is_clustered() 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 99b2834f1..2b182b872 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp @@ -142,7 +142,7 @@ struct traversal_ring_creator if (! m_trav.select_turn(start_turn_index, start_op_index, turn_index, op_index, previous_op_index, previous_turn_index, previous_seg_id, - is_start)) + is_start, current_ring.size() > 1)) { return is_start ? traverse_error_no_next_ip_at_start From de5187f39cbaf29f851b74d41d046e1672e34422 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 3 Apr 2019 13:58:40 +0200 Subject: [PATCH 05/68] [test] update testcases w.r.t. disabling rescaling, add two cases --- .../buffer/buffer_linestring_aimes.cpp | 2 ++ .../buffer/buffer_multi_linestring.cpp | 2 -- .../buffer/buffer_multi_polygon.cpp | 8 ++--- test/algorithms/buffer/buffer_polygon.cpp | 2 ++ test/algorithms/overlay/overlay_cases.hpp | 13 ++++++++ .../set_operations/difference/difference.cpp | 32 +++++++------------ .../difference/test_difference.hpp | 6 ++-- .../intersection/intersection.cpp | 30 +++++++++-------- .../intersection/intersection_multi.cpp | 21 ++++++++---- .../algorithms/set_operations/union/union.cpp | 31 ++++++++++++------ .../set_operations/union/union_multi.cpp | 3 +- 11 files changed, 90 insertions(+), 60 deletions(-) diff --git a/test/algorithms/buffer/buffer_linestring_aimes.cpp b/test/algorithms/buffer/buffer_linestring_aimes.cpp index 54b6381eb..6468a80dc 100644 --- a/test/algorithms/buffer/buffer_linestring_aimes.cpp +++ b/test/algorithms/buffer/buffer_linestring_aimes.cpp @@ -474,6 +474,8 @@ void test_aimes() int test_main(int, char* []) { +#if defined(BOOST_GEOMETRY_USE_RESCALING) test_aimes >(); +#endif return 0; } diff --git a/test/algorithms/buffer/buffer_multi_linestring.cpp b/test/algorithms/buffer/buffer_multi_linestring.cpp index 69703ba2f..078495127 100644 --- a/test/algorithms/buffer/buffer_multi_linestring.cpp +++ b/test/algorithms/buffer/buffer_multi_linestring.cpp @@ -141,7 +141,6 @@ void test_all() } { -#if defined(BOOST_GEOMETRY_USE_RESCALING) // Coordinates in one linestring vary so much that // length = geometry::math::sqrt(dx * dx + dy * dy); returns a value of inf for length // That geometry is skipped for the buffer @@ -156,7 +155,6 @@ void test_all() test_one("mysql_2015_04_10b", mysql_2015_04_10b, join_round32, end_round32, ut_settings::ignore_area(), 0.98, ut_settings::assertions_only()); -#endif // Two other cases with for length calculation test_one("mysql_2015_09_08a", diff --git a/test/algorithms/buffer/buffer_multi_polygon.cpp b/test/algorithms/buffer/buffer_multi_polygon.cpp index 346576095..af6f4a9a5 100644 --- a/test/algorithms/buffer/buffer_multi_polygon.cpp +++ b/test/algorithms/buffer/buffer_multi_polygon.cpp @@ -368,26 +368,24 @@ void test_all() test_one("rt_d", rt_d, join_round, end_flat, 18.8726, 0.3); test_one("rt_e", rt_e, join_round, end_flat, 14.1866, 0.3); +#if defined(BOOST_GEOMETRY_USE_RESCALING) test_one("rt_g1", rt_g1, join_round, end_flat, 24.719, 1.0); +#endif test_one("rt_g3", rt_g3, join_miter, end_flat, 16.5711, 1.0); test_one("rt_d", rt_d, join_miter, end_flat, 19.8823, 0.3); -#if defined(BOOST_GEOMETRY_USE_RESCALING) test_one("rt_e", rt_e, join_miter, end_flat, 15.1198, 0.3); test_one("rt_f", rt_f, join_miter, end_flat, 4.60853, 0.3); -#endif test_one("rt_g1", rt_g1, join_miter, end_flat, 30.3137, 1.0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) test_one("rt_g2", rt_g2, join_miter, end_flat, 18.5711, 1.0); -#endif test_one("rt_h", rt_h, join_round, end_flat, 47.6012, 1.0); test_one("rt_h", rt_h, join_miter, end_flat, 61.7058, 1.0); test_one("rt_i", rt_i, join_round, end_flat, 10.7528, 1.0); #if defined(BOOST_GEOMETRY_USE_RESCALING) test_one("rt_i", rt_i, join_miter, end_flat, 13.6569, 1.0); -#endif test_one("rt_j", rt_j, join_round, end_flat, 28.7309, 1.0); +#endif test_one("rt_j", rt_j, join_miter, end_flat, 35.1421, 1.0); test_one("rt_k", rt_k, join_round, end_flat, 42.0092, 1.0); test_one("rt_k", rt_k, join_miter, end_flat, 48.0563, 1.0); diff --git a/test/algorithms/buffer/buffer_polygon.cpp b/test/algorithms/buffer/buffer_polygon.cpp index f7d7eae63..0e5504a8b 100644 --- a/test/algorithms/buffer/buffer_polygon.cpp +++ b/test/algorithms/buffer/buffer_polygon.cpp @@ -374,7 +374,9 @@ void test_all() test_one("snake4", snake, join_miter, end_flat, 64.44, 0.4); test_one("snake5", snake, join_miter, end_flat, 72, 0.5); test_one("snake6", snake, join_miter, end_flat, 75.44, 0.6); +#if defined(BOOST_GEOMETRY_USE_RESCALING) test_one("snake16", snake, join_miter, end_flat, 114.24, 1.6); +#endif test_one("funnelgate2", funnelgate, join_miter, end_flat, 120.982, 2.0); test_one("funnelgate3", funnelgate, join_miter, end_flat, 13.0*13.0, 3.0); diff --git a/test/algorithms/overlay/overlay_cases.hpp b/test/algorithms/overlay/overlay_cases.hpp index 4cb151485..478d0558b 100644 --- a/test/algorithms/overlay/overlay_cases.hpp +++ b/test/algorithms/overlay/overlay_cases.hpp @@ -783,6 +783,19 @@ static std::string case_precision_13[2] = "POLYGON((1 1,9.99999999999999912e-06 1,9.99999999999999912e-06 3,1 3,1 1))" }; +static std::string case_precision_14[2] = +{ + "POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))", + "POLYGON((2 7,4 7,4.00000079999999958 3.00000020000000012,2 3,2 7))" +}; + +static std::string case_precision_15[2] = +{ + // Needs handling of side_value + "POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))", + "POLYGON((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,2 3,3.99999599999999988 3.00000499999999981,4 7,2 7))" +}; + // ticket_17 is keyholed, so has a hole formed by an deliberate intersection // This will fail the intersection/traversal process static std::string ticket_17[2] = { diff --git a/test/algorithms/set_operations/difference/difference.cpp b/test/algorithms/set_operations/difference/difference.cpp index 0afeaa1fd..43b071eeb 100644 --- a/test/algorithms/set_operations/difference/difference.cpp +++ b/test/algorithms/set_operations/difference/difference.cpp @@ -85,13 +85,11 @@ void test_all() 1, 5, 8.0, 1, 5, 8.0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) test_one("star_comb_15", star_comb_15[0], star_comb_15[1], 30, -1, 227.658275102812, 30, -1, 480.485775259312, sym_settings); -#endif test_one("new_hole", new_hole[0], new_hole[1], @@ -122,7 +120,6 @@ void test_all() 1, 5, 9.0, 1, 5, 9.0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) test_one("only_hole_intersections1", only_hole_intersections[0], only_hole_intersections[1], 2, 10, 1.9090909, @@ -134,7 +131,6 @@ void test_all() 3, 20, 30.9090909, 4, 16, 10.9090909, sym_settings); -#endif test_one("first_within_second", first_within_second[1], first_within_second[0], @@ -271,15 +267,14 @@ void test_all() 1, 61, 10.2717, 1, 61, 10.2717); -#if defined(BOOST_GEOMETRY_USE_RESCALING) if ( BOOST_GEOMETRY_CONDITION((boost::is_same::value)) ) { test_one("buffer_mp2", buffer_mp2[0], buffer_mp2[1], 1, 91, 12.09857, - 1, 155, 24.19714); + 1, 155, 24.19714, + BG_IF_RESCALED(2, 1), -1, 12.09857 + 24.19714); } -#endif /*** TODO: self-tangencies for difference test_one("wrapped_a", @@ -297,6 +292,7 @@ void test_all() ut_settings settings; settings.percentage = BG_IF_RESCALED(0.001, 0.1); settings.test_validity = BG_IF_RESCALED(true, false); + settings.sym_difference = BG_IF_RESCALED(true, false); // Isovist - the # output polygons differ per compiler/pointtype, (very) small // rings might be discarded. We check area only @@ -399,22 +395,21 @@ void test_all() 1, 5, 384.2295081964694, tolerance(0.01)); -#if defined(BOOST_GEOMETRY_USE_RESCALING) // 2011-07-02 / 2014-06-19 // Interesting FP-precision case. // sql server gives: 6.62295817619452E-05 // PostGIS gives: 0.0 (no output) // Boost.Geometry gave results depending on FP-type, and compiler, and operating system. - // Since rescaling to integer results are equal w.r.t. compiler/FP type, + // With rescaling results are equal w.r.t. compiler/FP type, // however, some long spikes are still generated in the resulting difference + // Without rescaling there is no output, like PostGIS test_one("ggl_list_20110627_phillip", ggl_list_20110627_phillip[0], ggl_list_20110627_phillip[1], - if_typed_tt(1, 1), -1, - if_typed_tt(0.0000000000001105367, 0.000125137888971949), + BG_IF_RESCALED(1, 0), -1, + BG_IF_RESCALED(if_typed_tt(0.0000000000001105367, 0.000125137888971949), 0), 1, -1, 3577.40960816756, tolerance(0.01) ); -#endif { // With rescaling, difference of output a-b and a sym b is invalid @@ -438,12 +433,10 @@ void test_all() 1, 10, 10.03103292, 0, 0, 0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) test_one("ticket_9081_15", ticket_9081_15[0], ticket_9081_15[1], - 2, 10, 0.0334529710902111, - 1, 4, 5.3469555172380723e-010); -#endif + 2, -1, 0.0334529710902111, + BG_IF_RESCALED(1, 0), -1, BG_IF_RESCALED(5.3469555172380723e-010, 0)); test_one("ticket_9081_314", ticket_9081_314[0], ticket_9081_314[1], @@ -463,12 +456,11 @@ void test_all() 1, 4, 0.029019232, sym_settings); -#if defined(BOOST_GEOMETRY_USE_RESCALING) test_one("ticket_10108_b", ticket_10108_b[0], ticket_10108_b[1], - 1, 5, 1081.68697, - 1, 5, 1342.65795); -#endif + 1, -1, 1081.68697, + 1, -1, 1342.65795, + BG_IF_RESCALED(2, 1), -1, 1081.68697 + 1342.65795); test_one("ticket_11725", ticket_11725[0], ticket_11725[1], diff --git a/test/algorithms/set_operations/difference/test_difference.hpp b/test/algorithms/set_operations/difference/test_difference.hpp index f534f1bf0..4230413bc 100644 --- a/test/algorithms/set_operations/difference/test_difference.hpp +++ b/test/algorithms/set_operations/difference/test_difference.hpp @@ -187,8 +187,6 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g return_string << bg::wkt(result); typename bg::default_area_result::type const area = bg::area(result); - std::size_t const n = expected_point_count >= 0 - ? bg::num_points(result) : 0; #if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST) #if ! defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) @@ -241,8 +239,10 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g #if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST) +#if defined(BOOST_GEOMETRY_USE_RESCALING) if (expected_point_count >= 0) { + std::size_t const n = bg::num_points(result); BOOST_CHECK_MESSAGE(bg::math::abs(int(n) - expected_point_count) < 3, "difference: " << caseid << " #points expected: " << expected_point_count @@ -250,6 +250,7 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g << " type: " << (type_for_assert_message()) ); } +#endif if (expected_count >= 0) { @@ -283,7 +284,6 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g } #endif - return return_string.str(); } diff --git a/test/algorithms/set_operations/intersection/intersection.cpp b/test/algorithms/set_operations/intersection/intersection.cpp index e70633113..dfad0dced 100644 --- a/test/algorithms/set_operations/intersection/intersection.cpp +++ b/test/algorithms/set_operations/intersection/intersection.cpp @@ -53,7 +53,7 @@ BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::vector) #define TEST_INTERSECTION_WITH(caseid, index1, index2, \ clips, points, area, settings) \ (test_one) \ - ( #caseid #index1 "_" #index2, caseid[index1], caseid[index2], \ + ( #caseid "_" #index1 "_" #index2, caseid[index1], caseid[index2], \ clips, points, area, settings) template @@ -190,8 +190,8 @@ void test_areal() test_one("geos_1", geos_1[0], geos_1[1], - 1, -1, 3461.0214843, // MSVC 14 reports 3461.025390625 - ut_settings(0.005, false)); + 1, -1, 3461.12321694, // MSVC 14 reports 3461.025390625 + ut_settings(0.01, false)); // Expectations: // In most cases: 0 (no intersection) @@ -253,13 +253,10 @@ void test_areal() TEST_INTERSECTION(ggl_list_20190307_matthieu_1, 2, -1, 0.035136); TEST_INTERSECTION(ggl_list_20190307_matthieu_2, 1, -1, 3.64285); -#if defined(BOOST_GEOMETRY_USE_RESCALING) test_one("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1], 1, 4, 0.00029437899183903937, ut_settings(0.01)); - test_one("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1], 1, 0, 2.914213562373); -#endif test_one("ticket_8254", ticket_8254[0], ticket_8254[1], 1, 4, 3.635930e-08, ut_settings(0.01)); @@ -283,13 +280,11 @@ void test_areal() ticket_10108_a[0], ticket_10108_a[1], 0, 0, 0.0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) // msvc 5.6023011e-5 // mingw 5.6022954e-5 test_one("ticket_10108_b", ticket_10108_b[0], ticket_10108_b[1], 0, 0, 5.6022983e-5, ut_settings(-1.0)); -#endif test_one("ticket_10747_a", ticket_10747_a[0], ticket_10747_a[1], @@ -303,16 +298,23 @@ void test_areal() test_one("ticket_10747_d", ticket_10747_d[0], ticket_10747_d[1], 1, 4, 703687777321.0); + + // Delivers very small triangle < 1.0e-13, or zero test_one("ticket_10747_e", ticket_10747_e[0], ticket_10747_e[1], - 1, 4, 7.0368748575710959e-15); + BG_IF_RESCALED(1, 0), -1, 1.0e-13, ut_settings(-1.0)); test_one("ticket_11576", ticket_11576[0], ticket_11576[1], 1, 0, 5.585617332907136e-07); - test_one("ticket_9563", ticket_9563[0], ticket_9563[1], - 1, 8, 129.90381); + { + // Not yet valid when rescaling is turned off + ut_settings settings; + settings.test_validity = BG_IF_RESCALED(true, false); + test_one("ticket_9563", ticket_9563[0], ticket_9563[1], + 1, 8, 129.90381, settings); + } #if ! defined(BOOST_GEOMETRY_USE_RESCALING) // With rescaling the output is empty @@ -354,6 +356,8 @@ void test_areal() 0, -1, 0.0); TEST_INTERSECTION(case_105, 1, 34, 76.0); + TEST_INTERSECTION(case_106, 2, -1, 3.5); + TEST_INTERSECTION(case_107, 3, -1, 3.0); TEST_INTERSECTION(case_precision_1, 0, 0, 0.0); TEST_INTERSECTION(case_precision_2, 0, 0, 0.0); @@ -386,8 +390,8 @@ void test_areal() TEST_INTERSECTION_WITH(case_precision_13, 1, 0, 1, -1, 2.0, settings); } - TEST_INTERSECTION(case_106, 2, -1, 3.5); - TEST_INTERSECTION(case_107, 3, -1, 3.0); + TEST_INTERSECTION(case_precision_14, 0, -1, 0.0); + TEST_INTERSECTION(case_precision_15, 1, -1, 14.0); test_one("mysql_21964049", mysql_21964049[0], mysql_21964049[1], diff --git a/test/algorithms/set_operations/intersection/intersection_multi.cpp b/test/algorithms/set_operations/intersection/intersection_multi.cpp index 63f96ba8f..f3e14fbed 100644 --- a/test/algorithms/set_operations/intersection/intersection_multi.cpp +++ b/test/algorithms/set_operations/intersection/intersection_multi.cpp @@ -135,14 +135,14 @@ void test_areal() case_107_multi[1], case_107_multi[2], 3, 13, 3.0); -#if defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) { - ut_settings ignore_validity; ignore_validity.test_validity = false; + ut_settings ignore_validity; - // One intersection is missing (by rescaling) + // Rescaling misses one intersection test_one("case_108_multi", case_108_multi[0], case_108_multi[1], - 5, 33, 7.5, + 7, -1, 7.5, ignore_validity); } #endif @@ -326,15 +326,23 @@ void test_areal() TEST_INTERSECTION(case_recursive_boxes_82, 5, -1, 8.5); TEST_INTERSECTION(case_recursive_boxes_83, 5, -1, 10.25); TEST_INTERSECTION(case_recursive_boxes_84, 1, -1, 0.5); +#if ! defined(BOOST_GEOMETRY_USE_RESCALING) TEST_INTERSECTION(case_recursive_boxes_85, 1, -1, 0.25); +#endif TEST_INTERSECTION(case_recursive_boxes_86, 0, -1, 0.0); TEST_INTERSECTION(case_recursive_boxes_87, 0, -1, 0.0); TEST_INTERSECTION(case_recursive_boxes_88, 4, -1, 3.5); +#if ! defined(BOOST_GEOMETRY_USE_RESCALING) TEST_INTERSECTION(case_precision_m1, 1, -1, 14.0); TEST_INTERSECTION(case_precision_m2, 2, -1, 15.25); TEST_INTERSECTION_REV(case_precision_m1, 1, -1, 14.0); TEST_INTERSECTION_REV(case_precision_m2, 2, -1, 15.25); +#else + // Validity: false positives (very small triangles looking like a line) + TEST_INTERSECTION_IGNORE(case_precision_m1, 1, -1, 14.0); + TEST_INTERSECTION_IGNORE(case_precision_m2, 2, -1, 15.25); +#endif test_one("ggl_list_20120915_h2_a", ggl_list_20120915_h2[0], ggl_list_20120915_h2[1], @@ -354,10 +362,11 @@ void test_areal() // Very small slice is generated. // qcc-arm reports 1.7791215549400884e-14 + // With rescaling, generates very small triangle test_one("ticket_11018", ticket_11018[0], ticket_11018[1], - 1, 4, BG_IF_RESCALED(1.7791170511070893e-14, 9.896437631745599e-09), - ut_settings(0.001) + BG_IF_RESCALED(1, 0), 0, + 1.0e-8, ut_settings(-1) ); TEST_INTERSECTION(ticket_12503, 2, 13, 17.375); diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index 0efbde3b6..7f1299c7e 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -268,6 +268,8 @@ void test_areal() TEST_UNION(case_precision_11, 1, 1, -1, 73.0); TEST_UNION(case_precision_12, 1, 0, -1, 14.0); TEST_UNION(case_precision_13, 1, 0, -1, 14.0); + TEST_UNION(case_precision_14, 1, 0, -1, 22.0); + TEST_UNION(case_precision_15, 1, 1, -1, 73.0); TEST_UNION_REV(case_precision_1, 1, 0, -1, 22.0); TEST_UNION_REV(case_precision_2, 1, 0, -1, 22.0); @@ -282,6 +284,8 @@ void test_areal() TEST_UNION_REV(case_precision_11, 1, 1, -1, 73.0); TEST_UNION_REV(case_precision_12, 1, 0, -1, 14.0); TEST_UNION_REV(case_precision_13, 1, 0, -1, 14.0); + TEST_UNION_REV(case_precision_14, 1, 0, -1, 22.0); + TEST_UNION_REV(case_precision_15, 1, 1, -1, 73.0); /* test_one(102, @@ -388,8 +392,12 @@ void test_areal() ticket_9081_15[0], ticket_9081_15[1], 1, 0, -1, 0.0403425433); - test_one("ticket_9563", ticket_9563[0], ticket_9563[1], - 1, 0, 13, 150.0); + { + ut_settings settings; + settings.test_validity = BG_IF_RESCALED(true, false); + test_one("ticket_9563", ticket_9563[0], ticket_9563[1], + 1, 0, 13, 150.0, settings); + } // Float result is OK but a bit larger test_one("ticket_9756", ticket_9756[0], ticket_9756[1], @@ -416,10 +424,13 @@ void test_areal() TEST_UNION(issue_566_a, 1, 0, -1, 214.3728); TEST_UNION(issue_566_b, 1, 0, -1, 214.3728); + TEST_UNION_REV(issue_566_a, 1, 0, -1, 214.3728); + TEST_UNION_REV(issue_566_b, 1, 0, -1, 214.3728); { ut_settings ignore_validity; ignore_validity.test_validity = false; + ignore_validity.percentage = 0.01; test_one("geos_1", geos_1[0], geos_1[1], 1, 0, -1, 3461.3203125, ignore_validity); @@ -431,16 +442,20 @@ void test_areal() test_one("geos_4", geos_4[0], geos_4[1], 1, 0, -1, 2304.4163115); - test_one("buffer_rt_a", buffer_rt_a[0], buffer_rt_a[1], - 1, 0, 265, 19.280667); - // Robustness issues, followed out buffer-robustness-tests, test them also reverse -#if defined(BOOST_GEOMETRY_USE_RESCALING) + { + // Area can vary depending on joining point of nearly parallel lines + ut_settings settings; + settings.percentage = 0.01; + test_one("buffer_rt_a", buffer_rt_a[0], buffer_rt_a[1], + 1, 0, -1, 19.28, settings); + test_one("buffer_rt_a_rev", buffer_rt_a[1], buffer_rt_a[0], + 1, 0, -1, 19.28, settings); + } test_one("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1], 1, 0, -1, 4.60853); test_one("buffer_rt_f_rev", buffer_rt_f[1], buffer_rt_f[0], 1, 0, -1, 4.60853); -#endif test_one("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1], 1, 0, -1, 16.571); test_one("buffer_rt_g_rev", buffer_rt_g[1], buffer_rt_g[0], @@ -476,12 +491,10 @@ void test_areal() 1, 0, -1, 18.5710); test_one("buffer_rt_q_rev", buffer_rt_q[1], buffer_rt_q[0], 1, 0, -1, 18.5710); -#if defined(BOOST_GEOMETRY_USE_RESCALING) test_one("buffer_rt_r", buffer_rt_r[0], buffer_rt_r[1], 1, 0, -1, 21.07612); test_one("buffer_rt_r_rev", buffer_rt_r[1], buffer_rt_r[0], 1, 0, -1, 21.07612); -#endif test_one("buffer_rt_t", buffer_rt_t[0], buffer_rt_t[1], 1, 0, -1, 15.6569); test_one("buffer_rt_t_rev", buffer_rt_t[1], buffer_rt_t[0], diff --git a/test/algorithms/set_operations/union/union_multi.cpp b/test/algorithms/set_operations/union/union_multi.cpp index cb897b400..4ff8fb1a5 100644 --- a/test/algorithms/set_operations/union/union_multi.cpp +++ b/test/algorithms/set_operations/union/union_multi.cpp @@ -403,10 +403,9 @@ void test_areal() test_one("ticket_11984", ticket_11984[0], ticket_11984[1], 1, 2, 134, 60071.08077); - test_one("ticket_12118", ticket_12118[0], ticket_12118[1], - 1, 1, 27, 2221.38713); + 1, -1, 27, 2221.38713); #if defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) || ! defined(BOOST_GEOMETRY_USE_RESCALING) // No output if rescaling is done From 25a4e6a2c7f23753f14f27380cbbc822d3b945cd Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 3 Apr 2019 15:51:00 +0200 Subject: [PATCH 06/68] [formulas][strategies] Fix potential warning. Add brackets. --- include/boost/geometry/formulas/differential_quantities.hpp | 3 +-- .../geometry/strategies/geographic/buffer_point_circle.hpp | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/formulas/differential_quantities.hpp b/include/boost/geometry/formulas/differential_quantities.hpp index 6e1658abe..789275f14 100644 --- a/include/boost/geometry/formulas/differential_quantities.hpp +++ b/include/boost/geometry/formulas/differential_quantities.hpp @@ -74,8 +74,7 @@ public: CT const sig_12 = dlon / one_minus_f; if (BOOST_GEOMETRY_CONDITION(EnableReducedLength)) { - CT const pi = math::pi(); - BOOST_GEOMETRY_ASSERT(-pi <= azimuth && azimuth <= pi); + BOOST_GEOMETRY_ASSERT((-math::pi() <= azimuth && azimuth <= math::pi())); int azi_sign = math::sign(azimuth) >= 0 ? 1 : -1; // for antipodal CT m12 = azi_sign * sin(sig_12) * b; diff --git a/include/boost/geometry/strategies/geographic/buffer_point_circle.hpp b/include/boost/geometry/strategies/geographic/buffer_point_circle.hpp index 8e9662c5d..51aacefa8 100644 --- a/include/boost/geometry/strategies/geographic/buffer_point_circle.hpp +++ b/include/boost/geometry/strategies/geographic/buffer_point_circle.hpp @@ -98,7 +98,9 @@ public : for (std::size_t i = 0; i < m_count; i++, angle += diff) { if (angle > pi) + { angle -= two_pi; + } typename direct_t::result_type dir_r = direct_t::apply(get_as_radian<0>(point), get_as_radian<1>(point), From ce4307bdfb7c3c784f09feb8240a05672f6bb2cb Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 17 Apr 2019 13:28:23 +0200 Subject: [PATCH 07/68] [get_turn_info] Review remark, get cs tag from umbrella strategy --- .../detail/overlay/get_distance_measure.hpp | 4 +- .../detail/overlay/get_turn_info.hpp | 79 +++++++++++-------- .../detail/overlay/get_turn_info_helpers.hpp | 40 +++++----- .../detail/overlay/get_turn_info_la.hpp | 48 +++++------ .../detail/overlay/get_turn_info_ll.hpp | 36 +++++---- .../strategies/cartesian/intersection.hpp | 2 + .../strategies/geographic/intersection.hpp | 2 + .../strategies/spherical/intersection.hpp | 2 + 8 files changed, 119 insertions(+), 94 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp index 2c622c753..0b14e88a8 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp @@ -168,14 +168,14 @@ namespace detail // 0 (absolutely 0, not even an epsilon) means collinear. Like side, // a negative means that p is to the right of p1-p2. And a positive value // means that p is to the left of p1-p2. -template +template static distance_measure::type> get_distance_measure(SegmentPoint const& p1, SegmentPoint const& p2, Point const& p) { return detail_dispatch::get_distance_measure < typename select_coordinate_type::type, - typename geometry::cs_tag::type + cs_tag >::apply(p1, p2, p); } 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 31c6563af..b7ec1813d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -150,10 +150,12 @@ struct base_turn_handler std::size_t IndexQ, typename UniqueSubRange1, typename UniqueSubRange2, + typename UmbrellaStrategy, typename TurnInfo > static inline void both_collinear(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, + UmbrellaStrategy const& umbrella_strategy, std::size_t index_p, std::size_t index_q, TurnInfo& ti) { @@ -167,20 +169,24 @@ struct base_turn_handler typedef detail::distance_measure < typename select_coordinate_type - < - typename UniqueSubRange1::point_type, - typename UniqueSubRange2::point_type + < + typename UniqueSubRange1::point_type, + typename UniqueSubRange2::point_type >::type > dm_type; - dm_type const dm = get_distance_measure(range_q.at(index_q - 1), + dm_type const dm = get_distance_measure(range_q.at(index_q - 1), range_q.at(index_q), range_p.at(index_p)); if (! dm.is_zero()) { // Not truely collinear, distinguish for union/intersection // If p goes left (positive), take that for a union - ui_else_iu(dm.is_positive(), ti); + + ti.operations[IndexP].operation = dm.is_positive() + ? operation_union : operation_intersection; + ti.operations[IndexQ].operation = dm.is_positive() + ? operation_intersection : operation_union; return; } #endif @@ -205,14 +211,16 @@ struct touch_interior : public base_turn_handler typename UniqueSubRange2, typename IntersectionInfo, typename DirInfo, - typename SidePolicy + typename SidePolicy, + typename UmbrellaStrategy > static inline void apply(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, TurnInfo& ti, IntersectionInfo const& intersection_info, DirInfo const& dir_info, - SidePolicy const& side) + SidePolicy const& side, + UmbrellaStrategy const& umbrella_strategy) { assign_point(ti, method_touch_interior, intersection_info, 0); @@ -312,7 +320,7 @@ struct touch_interior : public base_turn_handler // Q intersects on interior of P and continues collinearly if (side_qk_q == side_qi_p) { - both_collinear(range_p, range_q, 1, 2, ti); + both_collinear(range_p, range_q, umbrella_strategy, 1, 2, ti); return; } else @@ -361,14 +369,16 @@ struct touch : public base_turn_handler typename UniqueSubRange2, typename IntersectionInfo, typename DirInfo, - typename SidePolicy + typename SideCalculator, + typename UmbrellaStrategy > static inline void apply(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, TurnInfo& ti, IntersectionInfo const& intersection_info, DirInfo const& dir_info, - SidePolicy const& side) + SideCalculator const& side, + UmbrellaStrategy const& umbrella_strategy) { assign_point(ti, method_touch, intersection_info, 0); @@ -404,7 +414,7 @@ struct touch : public base_turn_handler // (#BRL2) if (side_pk_q2 == 0 && ! block_q) { - both_collinear<0, 1>(range_p, range_q, 2, 2, ti); + both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti); return; } @@ -547,14 +557,16 @@ struct equal : public base_turn_handler typename UniqueSubRange2, typename IntersectionInfo, typename DirInfo, - typename SidePolicy + typename SideCalculator, + typename UmbrellaStrategy > static inline void apply(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, TurnInfo& ti, IntersectionInfo const& info, DirInfo const& , - SidePolicy const& side) + SideCalculator const& side, + UmbrellaStrategy const& umbrella_strategy) { // Copy the intersection point in TO direction assign_point(ti, method_equal, info, non_opposite_to_index(info)); @@ -572,8 +584,7 @@ struct equal : public base_turn_handler // oppositely if (side_pk_q2 == 0 && side_pk_p == side_qk_p) { - both_collinear<0, 1>(range_p, range_q, 2, 2, ti); - + both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti); return; } @@ -606,14 +617,16 @@ struct start : public base_turn_handler typename UniqueSubRange2, typename IntersectionInfo, typename DirInfo, - typename SidePolicy + typename SideCalculator, + typename UmbrellaStrategy > static inline bool apply(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, TurnInfo& ti, IntersectionInfo const& info, DirInfo const& dir_info, - SidePolicy const& side) + SideCalculator const& side, + UmbrellaStrategy const& umbrella_strategy) { #if defined(BOOST_GEOMETRY_USE_RESCALING) // If rescaled, it is not necessary to handle start turns @@ -639,8 +652,9 @@ struct start : public base_turn_handler >::type > dm_type; - dm_type const dm_pi_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(0)); - dm_type const dm_qi_p1 = get_distance_measure(range_p.at(0), range_p.at(1), range_q.at(0)); + typedef typename UmbrellaStrategy::cs_tag cs_tag; + dm_type const dm_pi_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(0)); + dm_type const dm_qi_p1 = get_distance_measure(range_p.at(0), range_p.at(1), range_q.at(0)); if (dir_info.how_a == -1 && dir_info.how_b == -1) { @@ -1108,7 +1122,7 @@ struct get_turn_info typename UniqueSubRange1, typename UniqueSubRange2, typename TurnInfo, - typename IntersectionStrategy, + typename UmbrellaStrategy, typename RobustPolicy, typename OutputIterator > @@ -1116,7 +1130,7 @@ struct get_turn_info UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, TurnInfo const& tp_model, - IntersectionStrategy const& intersection_strategy, + UmbrellaStrategy const& umbrella_strategy, RobustPolicy const& robust_policy, OutputIterator out) { @@ -1124,12 +1138,11 @@ struct get_turn_info < UniqueSubRange1, UniqueSubRange2, typename TurnInfo::point_type, - IntersectionStrategy, + UmbrellaStrategy, RobustPolicy > inters_info; - inters_info inters(range_p, range_q, - intersection_strategy, robust_policy); + inters_info inters(range_p, range_q, umbrella_strategy, robust_policy); char const method = inters.d_info().how; @@ -1153,19 +1166,19 @@ struct get_turn_info typedef touch_interior < TurnInfo - > policy; + > handler; // If Q (1) arrives (1) if ( inters.d_info().arrival[1] == 1 ) { - policy::template apply<0>(range_p, range_q, tp, inters.i_info(), inters.d_info(), - inters.sides()); + handler::template apply<0>(range_p, range_q, tp, inters.i_info(), inters.d_info(), + inters.sides(), umbrella_strategy); } else { // Swap p/q - policy::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), - inters.get_swapped_sides()); + handler::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), + inters.get_swapped_sides(), umbrella_strategy); } *out++ = tp; } @@ -1179,7 +1192,7 @@ struct get_turn_info case 't' : { // Both touch (both arrive there) - touch::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides()); + touch::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy); *out++ = tp; } break; @@ -1187,7 +1200,7 @@ struct get_turn_info case 's' : { // "from" or "start" without rescaling, it is in some cases necessary to handle - if (start::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides())) + if (start::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy)) { *out++ = tp; } @@ -1203,7 +1216,7 @@ struct get_turn_info { // Both equal // or collinear-and-ending at intersection point - equal::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides()); + equal::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy); *out++ = tp; } else @@ -1226,7 +1239,7 @@ struct get_turn_info { // Collinear, but similar thus handled as equal equal::apply(range_p, range_q, tp, - inters.i_info(), inters.d_info(), inters.sides()); + inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy); // override assigned method tp.method = method_collinear; 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 087ca8060..4b0aa162f 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 @@ -217,7 +217,7 @@ private : template < typename UniqueSubRange1, typename UniqueSubRange2, - typename TurnPoint, typename IntersectionStrategy, typename RobustPolicy> + typename TurnPoint, typename UmbrellaStrategy, typename RobustPolicy> class intersection_info_base : private robust_points { @@ -232,7 +232,7 @@ public: typedef typename cs_tag::type cs_tag; - typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; + typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; typedef side_calculator side_calculator_type; @@ -244,7 +244,7 @@ public: intersection_info_base(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, - IntersectionStrategy const& intersection_strategy, + UmbrellaStrategy const& umbrella_strategy, RobustPolicy const& robust_policy) : base(range_p, range_q, robust_policy) , m_range_p(range_p) @@ -252,7 +252,7 @@ public: , m_robust_range_p(range_p, base::m_rpi, base::m_rpj, robust_policy) , m_robust_range_q(range_q, base::m_rqi, base::m_rqj, robust_policy) , m_side_calc(m_robust_range_p, m_robust_range_q, - intersection_strategy.get_side_strategy()) + umbrella_strategy.get_side_strategy()) {} inline typename UniqueSubRange1::point_type const& pi() const { return m_range_p.at(0); } @@ -289,10 +289,10 @@ private : template < typename UniqueSubRange1, typename UniqueSubRange2, - typename TurnPoint, typename IntersectionStrategy + typename TurnPoint, typename UmbrellaStrategy > class intersection_info_base + TurnPoint, UmbrellaStrategy, detail::no_rescale_policy> { public: typedef typename UniqueSubRange1::point_type point1_type; @@ -301,9 +301,9 @@ public: typedef typename UniqueSubRange1::point_type robust_point1_type; typedef typename UniqueSubRange2::point_type robust_point2_type; - typedef typename cs_tag::type cs_tag; + typedef typename UmbrellaStrategy::cs_tag cs_tag; - typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; + typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; typedef side_calculator side_calculator_type; typedef side_calculator @@ -314,12 +314,12 @@ public: intersection_info_base(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, - IntersectionStrategy const& intersection_strategy, + UmbrellaStrategy const& umbrella_strategy, no_rescale_policy const& /*robust_policy*/) : m_range_p(range_p) , m_range_q(range_q) , m_side_calc(range_p, range_q, - intersection_strategy.get_side_strategy()) + umbrella_strategy.get_side_strategy()) {} inline point1_type const& rpi() const { return m_side_calc.get_pi(); } @@ -354,15 +354,15 @@ template < typename UniqueSubRange1, typename UniqueSubRange2, typename TurnPoint, - typename IntersectionStrategy, + typename UmbrellaStrategy, typename RobustPolicy > class intersection_info : public intersection_info_base + TurnPoint, UmbrellaStrategy, RobustPolicy> { typedef intersection_info_base base; + TurnPoint, UmbrellaStrategy, RobustPolicy> base; public: typedef segment_intersection_points @@ -387,8 +387,8 @@ public: policies::relate::segments_direction > intersection_policy_type; - typedef IntersectionStrategy intersection_strategy_type; - typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; + typedef UmbrellaStrategy intersection_strategy_type; + typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; typedef model::referring_segment segment_type1; typedef model::referring_segment segment_type2; @@ -400,18 +400,18 @@ public: intersection_info(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, - IntersectionStrategy const& intersection_strategy, + UmbrellaStrategy const& umbrella_strategy, RobustPolicy const& robust_policy) : base(range_p, range_q, - intersection_strategy, robust_policy) - , m_result(intersection_strategy.apply( + umbrella_strategy, robust_policy) + , m_result(umbrella_strategy.apply( segment_type1(range_p.at(0), range_p.at(1)), segment_type2(range_q.at(0), range_q.at(1)), intersection_policy_type(), robust_policy, base::rpi(), base::rpj(), base::rqi(), base::rqj())) - , m_intersection_strategy(intersection_strategy) + , m_intersection_strategy(umbrella_strategy) , m_robust_policy(robust_policy) {} @@ -523,7 +523,7 @@ private: } result_type m_result; - IntersectionStrategy const& m_intersection_strategy; + UmbrellaStrategy const& m_intersection_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 f8272794b..5b5273392 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 @@ -44,7 +44,7 @@ struct get_turn_info_linear_areal typename UniqueSubRange1, typename UniqueSubRange2, typename TurnInfo, - typename IntersectionStrategy, + typename UmbrellaStrategy, typename RobustPolicy, typename OutputIterator > @@ -52,7 +52,7 @@ struct get_turn_info_linear_areal UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, TurnInfo const& tp_model, - IntersectionStrategy const& strategy, + UmbrellaStrategy const& umbrella_strategy, RobustPolicy const& robust_policy, OutputIterator out) { @@ -60,11 +60,11 @@ struct get_turn_info_linear_areal < UniqueSubRange1, UniqueSubRange2, typename TurnInfo::point_type, - IntersectionStrategy, + UmbrellaStrategy, RobustPolicy > inters_info; - inters_info inters(range_p, range_q, strategy, robust_policy); + inters_info inters(range_p, range_q, umbrella_strategy, robust_policy); char const method = inters.d_info().how; @@ -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, - strategy.get_point_in_point_strategy()); + umbrella_strategy.get_point_in_point_strategy()); break; case 'd' : // disjoint: never do anything @@ -89,30 +89,27 @@ struct get_turn_info_linear_areal { if ( get_turn_info_for_endpoint(range_p, range_q, tp_model, inters, method_touch_interior, out, - strategy.get_point_in_point_strategy()) ) + umbrella_strategy.get_point_in_point_strategy()) ) { // do nothing } else { - typedef touch_interior - < - TurnInfo - > policy; + typedef touch_interior handler; // If Q (1) arrives (1) if ( inters.d_info().arrival[1] == 1 ) { - policy::template apply<0>(range_p, range_q, tp, + handler::template apply<0>(range_p, range_q, tp, inters.i_info(), inters.d_info(), - inters.sides()); + inters.sides(), umbrella_strategy); } else { // Swap p/q - policy::template apply<1>(range_q, range_p, + handler::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), - inters.get_swapped_sides()); + inters.get_swapped_sides(), umbrella_strategy); } if ( tp.operations[1].operation == operation_blocked ) @@ -127,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, - strategy.get_point_in_point_strategy()); + umbrella_strategy.get_point_in_point_strategy()); *out++ = tp; } @@ -147,14 +144,15 @@ 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, - strategy.get_point_in_point_strategy()) ) + umbrella_strategy.get_point_in_point_strategy()) ) { // do nothing } else { touch::apply(range_p, range_q, tp, - inters.i_info(), inters.d_info(), inters.sides()); + inters.i_info(), inters.d_info(), inters.sides(), + umbrella_strategy); if ( tp.operations[1].operation == operation_blocked ) { @@ -220,7 +218,7 @@ struct get_turn_info_linear_areal bool ignore_spike = calculate_spike_operation(tp.operations[0].operation, inters, - strategy.get_point_in_point_strategy()); + umbrella_strategy.get_point_in_point_strategy()); if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) || ignore_spike @@ -236,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, - strategy.get_point_in_point_strategy()) ) + umbrella_strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -249,7 +247,8 @@ struct get_turn_info_linear_areal // Both equal // or collinear-and-ending at intersection point equal::apply(range_p, range_q, tp, - inters.i_info(), inters.d_info(), inters.sides()); + inters.i_info(), inters.d_info(), inters.sides(), + umbrella_strategy); turn_transformer_ec transformer(method_touch); transformer(tp); @@ -280,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, - strategy.get_point_in_point_strategy()) ) + umbrella_strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -297,7 +296,8 @@ struct get_turn_info_linear_areal { // Collinear, but similar thus handled as equal equal::apply(range_p, range_q, tp, - inters.i_info(), inters.d_info(), inters.sides()); + inters.i_info(), inters.d_info(), inters.sides(), + umbrella_strategy); method_replace = method_touch; version = append_equal; @@ -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, - strategy.get_point_in_point_strategy()) ) + umbrella_strategy.get_point_in_point_strategy()) ) { tp.operations[0].position = position_front; } else if ( range_p.is_last_segment() && equals::equals_point_point(range_p.at(1), tp.point, - strategy.get_point_in_point_strategy()) ) + umbrella_strategy.get_point_in_point_strategy()) ) { tp.operations[0].position = position_back; } 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 217f4a340..0ea937a1e 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 @@ -39,7 +39,7 @@ struct get_turn_info_linear_linear typename UniqueSubRange1, typename UniqueSubRange2, typename TurnInfo, - typename IntersectionStrategy, + typename UmbrellaStrategy, typename RobustPolicy, typename OutputIterator > @@ -47,7 +47,7 @@ struct get_turn_info_linear_linear UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, TurnInfo const& tp_model, - IntersectionStrategy const& strategy, + UmbrellaStrategy const& umbrella_strategy, RobustPolicy const& robust_policy, OutputIterator out) { @@ -55,11 +55,11 @@ struct get_turn_info_linear_linear < UniqueSubRange1, UniqueSubRange2, typename TurnInfo::point_type, - IntersectionStrategy, + UmbrellaStrategy, RobustPolicy > inters_info; - inters_info inters(range_p, range_q, strategy, robust_policy); + inters_info inters(range_p, range_q, umbrella_strategy, robust_policy); char const method = inters.d_info().how; @@ -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, - strategy.get_point_in_point_strategy()); + umbrella_strategy.get_point_in_point_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, - strategy.get_point_in_point_strategy()) ) + umbrella_strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -102,14 +102,16 @@ struct get_turn_info_linear_linear { policy::template apply<0>(range_p, range_q, tp, inters.i_info(), inters.d_info(), - inters.sides()); + inters.sides(), + umbrella_strategy); } else { // Swap p/q policy::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), - inters.get_swapped_sides()); + inters.get_swapped_sides(), + umbrella_strategy); } if ( tp.operations[0].operation == operation_blocked ) @@ -144,14 +146,16 @@ struct get_turn_info_linear_linear if ( get_turn_info_for_endpoint ::apply(range_p, range_q, tp_model, inters, method_touch, out, - strategy.get_point_in_point_strategy()) ) + umbrella_strategy.get_point_in_point_strategy()) ) { // do nothing } else { touch::apply(range_p, range_q, tp, - inters.i_info(), inters.d_info(), inters.sides()); + inters.i_info(), inters.d_info(), + inters.sides(), + umbrella_strategy); // workarounds for touch<> not taking spikes into account starts here // those was discovered empirically @@ -274,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, - strategy.get_point_in_point_strategy()) ) + umbrella_strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -288,7 +292,8 @@ struct get_turn_info_linear_linear // Both equal // or collinear-and-ending at intersection point equal::apply(range_p, range_q, tp, - inters.i_info(), inters.d_info(), inters.sides()); + inters.i_info(), inters.d_info(), inters.sides(), + umbrella_strategy); operation_type spike_op = ( tp.operations[0].operation != operation_continue @@ -328,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, - strategy.get_point_in_point_strategy()) ) + umbrella_strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -347,7 +352,8 @@ struct get_turn_info_linear_linear { // Collinear, but similar thus handled as equal equal::apply(range_p, range_q, tp, - inters.i_info(), inters.d_info(), inters.sides()); + inters.i_info(), inters.d_info(), inters.sides(), + umbrella_strategy); method_replace = method_touch; if ( tp.operations[0].operation != operation_continue @@ -410,7 +416,7 @@ struct get_turn_info_linear_linear // degenerate points if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) ) { - typedef typename IntersectionStrategy::point_in_point_strategy_type + typedef typename UmbrellaStrategy::point_in_point_strategy_type equals_strategy_type; only_convert::apply(tp, inters.i_info()); diff --git a/include/boost/geometry/strategies/cartesian/intersection.hpp b/include/boost/geometry/strategies/cartesian/intersection.hpp index fea98af1b..c47fd30e8 100644 --- a/include/boost/geometry/strategies/cartesian/intersection.hpp +++ b/include/boost/geometry/strategies/cartesian/intersection.hpp @@ -75,6 +75,8 @@ template > struct cartesian_segments { + typedef cartesian_tag cs_tag; + typedef side::side_by_triangle side_strategy_type; static inline side_strategy_type get_side_strategy() diff --git a/include/boost/geometry/strategies/geographic/intersection.hpp b/include/boost/geometry/strategies/geographic/intersection.hpp index 6f317bb31..0e5baf830 100644 --- a/include/boost/geometry/strategies/geographic/intersection.hpp +++ b/include/boost/geometry/strategies/geographic/intersection.hpp @@ -73,6 +73,8 @@ template > struct geographic_segments { + typedef geographic_tag cs_tag; + typedef side::geographic < FormulaPolicy, Spheroid, CalculationType diff --git a/include/boost/geometry/strategies/spherical/intersection.hpp b/include/boost/geometry/strategies/spherical/intersection.hpp index 9142009fe..0d483f24b 100644 --- a/include/boost/geometry/strategies/spherical/intersection.hpp +++ b/include/boost/geometry/strategies/spherical/intersection.hpp @@ -89,6 +89,8 @@ template > struct ecef_segments { + typedef spherical_tag cs_tag; + typedef side::spherical_side_formula side_strategy_type; static inline side_strategy_type get_side_strategy() From b84918fcde5cbdf94070ef5bcda3dd86a72a6585 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 17 Apr 2019 15:10:04 +0200 Subject: [PATCH 08/68] [test] add testcase for FP precision without rescaling --- test/algorithms/overlay/overlay_cases.hpp | 6 ++++++ test/algorithms/set_operations/union/union.cpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/test/algorithms/overlay/overlay_cases.hpp b/test/algorithms/overlay/overlay_cases.hpp index 478d0558b..196509222 100644 --- a/test/algorithms/overlay/overlay_cases.hpp +++ b/test/algorithms/overlay/overlay_cases.hpp @@ -796,6 +796,12 @@ static std::string case_precision_15[2] = "POLYGON((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,2 3,3.99999599999999988 3.00000499999999981,4 7,2 7))" }; +static std::string case_precision_16[2] = +{ + "POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))", + "POLYGON((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,2 3,4 2.99999940000000009,4 7,2 7))" +}; + // ticket_17 is keyholed, so has a hole formed by an deliberate intersection // This will fail the intersection/traversal process static std::string ticket_17[2] = { diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index 7f1299c7e..b3e413d39 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -270,6 +270,7 @@ void test_areal() TEST_UNION(case_precision_13, 1, 0, -1, 14.0); TEST_UNION(case_precision_14, 1, 0, -1, 22.0); TEST_UNION(case_precision_15, 1, 1, -1, 73.0); + TEST_UNION(case_precision_16, 1, 1, -1, 73.0); TEST_UNION_REV(case_precision_1, 1, 0, -1, 22.0); TEST_UNION_REV(case_precision_2, 1, 0, -1, 22.0); @@ -286,6 +287,7 @@ void test_areal() TEST_UNION_REV(case_precision_13, 1, 0, -1, 14.0); TEST_UNION_REV(case_precision_14, 1, 0, -1, 22.0); TEST_UNION_REV(case_precision_15, 1, 1, -1, 73.0); + TEST_UNION_REV(case_precision_16, 1, 1, -1, 73.0); /* test_one(102, From 88fde34c137b46d04f6297622ab13fc130677b2d Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Mon, 22 Apr 2019 16:14:20 +0300 Subject: [PATCH 09/68] [strategies] Create newton method function --- .../geographic/distance_cross_track.hpp | 177 ++++++++++-------- 1 file changed, 98 insertions(+), 79 deletions(-) diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 53942529b..089cb0357 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -82,6 +82,7 @@ template typename FormulaPolicy = strategy::andoyer, typename Spheroid = srs::spheroid, typename CalculationType = void, + bool Bisection = false, bool EnableClosestPoint = false > class geographic_cross_track @@ -205,6 +206,101 @@ private : return g4 - pi/2; } + template + static void newton_update(CT lon1, CT lat1, //p1 + CT lon2, CT lat2, //p2 + CT lon3, CT lat3, //query point p3 + Spheroid const& spheroid, + CT& s14, CT const& a12, + result_distance_point_segment& result) + { + typedef typename FormulaPolicy::template inverse + inverse_distance_azimuth_quantities_type; + typedef typename FormulaPolicy::template inverse + inverse_azimuth_type; + typedef typename FormulaPolicy::template direct + direct_distance_type; + + CT const half_pi = math::pi() / CT(2); + CT prev_distance; + geometry::formula::result_direct res14; + geometry::formula::result_inverse res34; + res34.distance = -1; + + int counter = 0; // robustness + CT g4; + CT delta_g4; + bool dist_improve = true; + + do{ + prev_distance = res34.distance; + + // Solve the direct problem to find p4 (GEO) + res14 = direct_distance_type::apply(lon1, lat1, s14, a12, spheroid); + + // Solve an inverse problem to find g4 + // g4 is the angle between segment (p1,p2) and segment (p3,p4) that meet on p4 (GEO) + + CT a4 = inverse_azimuth_type::apply(res14.lon2, res14.lat2, + lon2, lat2, spheroid).azimuth; + res34 = inverse_distance_azimuth_quantities_type::apply(res14.lon2, res14.lat2, + lon3, lat3, spheroid); + g4 = res34.azimuth - a4; + + CT M43 = res34.geodesic_scale; // cos(s14/earth_radius) is the spherical limit + CT m34 = res34.reduced_length; + CT der = (M43 / m34) * sin(g4); + + //normalize + delta_g4 = normalize(g4, der); + s14 = s14 - delta_g4 / der; + result.distance = res34.distance; + + dist_improve = prev_distance > res34.distance || prev_distance == -1; + if (!dist_improve) + { + result.distance = prev_distance; + } + + #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK + std::cout << "p4=" << res14.lon2 * math::r2d() << + "," << res14.lat2 * math::r2d() << std::endl; + std::cout << "a34=" << res34.azimuth * math::r2d() << std::endl; + std::cout << "a4=" << a4 * math::r2d() << std::endl; + std::cout << "g4(normalized)=" << g4 * math::r2d() << std::endl; + std::cout << "delta_g4=" << delta_g4 * math::r2d() << std::endl; + std::cout << "der=" << der << std::endl; + std::cout << "M43=" << M43 << std::endl; + std::cout << "spherical limit=" << cos(s14/earth_radius) << std::endl; + std::cout << "m34=" << m34 << std::endl; + std::cout << "new_s14=" << s14 << std::endl; + std::cout << std::setprecision(16) << "dist =" << res34.distance << std::endl; + std::cout << "---------end of step " << counter << std::endl<< std::endl; + if (g4 == half_pi) + { + std::cout << "Stop msg: g4 == half_pi" << std::endl; + } + if (!dist_improve) + { + std::cout << "Stop msg: res34.distance >= prev_distance" << std::endl; + } + if (delta_g4 == 0) + { + std::cout << "Stop msg: delta_g4 == 0" << std::endl; + } + if (counter == BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS) + { + std::cout << "Stop msg: counter" << std::endl; + } + #endif + + } while (g4 != half_pi + && dist_improve + && delta_g4 != 0 + && counter++ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS); + + } + template result_distance_point_segment static inline apply(CT lon1, CT lat1, //p1 @@ -212,14 +308,10 @@ private : CT lon3, CT lat3, //query point p3 Spheroid const& spheroid) { - typedef typename FormulaPolicy::template inverse - inverse_distance_azimuth_quantities_type; typedef typename FormulaPolicy::template inverse inverse_azimuth_type; typedef typename FormulaPolicy::template inverse inverse_azimuth_reverse_type; - typedef typename FormulaPolicy::template direct - direct_distance_type; CT const earth_radius = geometry::formula::mean_radius(spheroid); @@ -440,82 +532,9 @@ private : #endif // Update s14 (using Newton method) - CT prev_distance; - geometry::formula::result_direct res14; - geometry::formula::result_inverse res34; - res34.distance = -1; - int counter = 0; // robustness - CT g4; - CT delta_g4; - bool dist_improve = true; - - do{ - prev_distance = res34.distance; - - // Solve the direct problem to find p4 (GEO) - res14 = direct_distance_type::apply(lon1, lat1, s14, a12, spheroid); - - // Solve an inverse problem to find g4 - // g4 is the angle between segment (p1,p2) and segment (p3,p4) that meet on p4 (GEO) - - CT a4 = inverse_azimuth_type::apply(res14.lon2, res14.lat2, - lon2, lat2, spheroid).azimuth; - res34 = inverse_distance_azimuth_quantities_type::apply(res14.lon2, res14.lat2, - lon3, lat3, spheroid); - g4 = res34.azimuth - a4; - - CT M43 = res34.geodesic_scale; // cos(s14/earth_radius) is the spherical limit - CT m34 = res34.reduced_length; - CT der = (M43 / m34) * sin(g4); - - //normalize - delta_g4 = normalize(g4, der); - s14 = s14 - delta_g4 / der; - result.distance = res34.distance; - - dist_improve = prev_distance > res34.distance || prev_distance == -1; - if (!dist_improve) - { - result.distance = prev_distance; - } - -#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "p4=" << res14.lon2 * math::r2d() << - "," << res14.lat2 * math::r2d() << std::endl; - std::cout << "a34=" << res34.azimuth * math::r2d() << std::endl; - std::cout << "a4=" << a4 * math::r2d() << std::endl; - std::cout << "g4(normalized)=" << g4 * math::r2d() << std::endl; - std::cout << "delta_g4=" << delta_g4 * math::r2d() << std::endl; - std::cout << "der=" << der << std::endl; - std::cout << "M43=" << M43 << std::endl; - std::cout << "spherical limit=" << cos(s14/earth_radius) << std::endl; - std::cout << "m34=" << m34 << std::endl; - std::cout << "new_s14=" << s14 << std::endl; - std::cout << std::setprecision(16) << "dist =" << res34.distance << std::endl; - std::cout << "---------end of step " << counter << std::endl<< std::endl; - if (g4 == half_pi) - { - std::cout << "Stop msg: g4 == half_pi" << std::endl; - } - if (!dist_improve) - { - std::cout << "Stop msg: res34.distance >= prev_distance" << std::endl; - } - if (delta_g4 == 0) - { - std::cout << "Stop msg: delta_g4 == 0" << std::endl; - } - if (counter == BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS) - { - std::cout << "Stop msg: counter" << std::endl; - } -#endif - - } while (g4 != half_pi - && dist_improve - && delta_g4 != 0 - && counter++ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS); + newton_update(lon1, lat1, lon2, lat2, lon3, lat3, + spheroid, s14, a12, result); #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "distance=" << res34.distance << std::endl; From 0f41f9b29bebe6441114b23f066162b50a856f9c Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Tue, 23 Apr 2019 14:42:11 +0300 Subject: [PATCH 10/68] [strategies] Better start estimation for Newton method in goe distance pt-sgmt --- .../geographic/distance_cross_track.hpp | 81 ++++++++++--------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 089cb0357..e234903e7 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -44,6 +44,7 @@ #include #include +#include #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK #include @@ -271,7 +272,7 @@ private : std::cout << "delta_g4=" << delta_g4 * math::r2d() << std::endl; std::cout << "der=" << der << std::endl; std::cout << "M43=" << M43 << std::endl; - std::cout << "spherical limit=" << cos(s14/earth_radius) << std::endl; + //std::cout << "spherical limit=" << cos(s14/earth_radius) << std::endl; std::cout << "m34=" << m34 << std::endl; std::cout << "new_s14=" << s14 << std::endl; std::cout << std::setprecision(16) << "dist =" << res34.distance << std::endl; @@ -298,7 +299,39 @@ private : && dist_improve && delta_g4 != 0 && counter++ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS); +#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK + std::cout << "distance=" << res34.distance << std::endl; + std::cout << "s34(geo) =" + << inverse_distance_azimuth_quantities_type::apply(res14.lon2, res14.lat2, lon3, lat3, spheroid).distance + << ", p4=(" << res14.lon2 * math::r2d() << "," + << res14.lat2 * math::r2d() << ")" + << std::endl; + + CT s31 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon1, lat1, spheroid).distance; + CT s32 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon2, lat2, spheroid).distance; + + CT a4 = inverse_azimuth_type::apply(res14.lon2, res14.lat2, lon2, lat2, spheroid).azimuth; + geometry::formula::result_direct res4 = direct_distance_type::apply(res14.lon2, res14.lat2, .04, a4, spheroid); + CT p4_plus = inverse_distance_azimuth_quantities_type::apply(res4.lon2, res4.lat2, lon3, lat3, spheroid).distance; + + geometry::formula::result_direct res1 = direct_distance_type::apply(lon1, lat1, s14-.04, a12, spheroid); + CT p4_minus = inverse_distance_azimuth_quantities_type::apply(res1.lon2, res1.lat2, lon3, lat3, spheroid).distance; + + std::cout << "s31=" << s31 << "\ns32=" << s32 + << "\np4_plus=" << p4_plus << ", p4=(" << res4.lon2 * math::r2d() << "," << res4.lat2 * math::r2d() << ")" + << "\np4_minus=" << p4_minus << ", p4=(" << res1.lon2 * math::r2d() << "," << res1.lat2 * math::r2d() << ")" + << std::endl; + + if (res34.distance <= p4_plus && res34.distance <= p4_minus) + { + std::cout << "Closest point computed" << std::endl; + } + else + { + std::cout << "There is a closer point nearby" << std::endl; + } +#endif } template @@ -524,6 +557,15 @@ private : : cos_frac <= -1 ? pi * earth_radius : acos(cos_frac) * earth_radius; + CT a12_sph = geometry::formula::spherical_azimuth<>(lon1, lat1, lon2, lat2); + + geometry::formula::result_direct res + = geometry::formula::spherical_direct + (lon1, lat1, s14, a12_sph, srs::sphere(earth_radius)); + + s14 = geometry::strategy::distance::geographic + ::apply(lon1, lat1, res.lon2, res.lat2, spheroid); + #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "s34=" << s34 << std::endl; std::cout << "s13=" << s13 << std::endl; @@ -536,43 +578,6 @@ private : newton_update(lon1, lat1, lon2, lat2, lon3, lat3, spheroid, s14, a12, result); -#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "distance=" << res34.distance << std::endl; - - point p4(res14.lon2, res14.lat2); - CT s34_sph = str.apply(p4, p3); - - std::cout << "s34(sph) =" << s34_sph << std::endl; - std::cout << "s34(geo) =" - << inverse_distance_azimuth_quantities_type::apply(get<0>(p4), get<1>(p4), lon3, lat3, spheroid).distance - << ", p4=(" << get<0>(p4) * math::r2d() << "," - << get<1>(p4) * math::r2d() << ")" - << std::endl; - - CT s31 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon1, lat1, spheroid).distance; - CT s32 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon2, lat2, spheroid).distance; - - CT a4 = inverse_azimuth_type::apply(get<0>(p4), get<1>(p4), lon2, lat2, spheroid).azimuth; - geometry::formula::result_direct res4 = direct_distance_type::apply(get<0>(p4), get<1>(p4), .04, a4, spheroid); - CT p4_plus = inverse_distance_azimuth_quantities_type::apply(res4.lon2, res4.lat2, lon3, lat3, spheroid).distance; - - geometry::formula::result_direct res1 = direct_distance_type::apply(lon1, lat1, s14-.04, a12, spheroid); - CT p4_minus = inverse_distance_azimuth_quantities_type::apply(res1.lon2, res1.lat2, lon3, lat3, spheroid).distance; - - std::cout << "s31=" << s31 << "\ns32=" << s32 - << "\np4_plus=" << p4_plus << ", p4=(" << res4.lon2 * math::r2d() << "," << res4.lat2 * math::r2d() << ")" - << "\np4_minus=" << p4_minus << ", p4=(" << res1.lon2 * math::r2d() << "," << res1.lat2 * math::r2d() << ")" - << std::endl; - - if (res34.distance <= p4_plus && res34.distance <= p4_minus) - { - std::cout << "Closest point computed" << std::endl; - } - else - { - std::cout << "There is a closer point nearby" << std::endl; - } -#endif return result; } From 17831d71f8e10591519d0e2e2cf93e4382878372 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Tue, 23 Apr 2019 16:50:10 +0300 Subject: [PATCH 11/68] [strategies] Bisection method for geo distance pt-sgmt --- .../geographic/distance_cross_track.hpp | 141 ++++++++++++++++-- .../algorithms/distance/distance_geo_pl_l.cpp | 1 + .../distance/test_distance_geo_common.hpp | 3 + 3 files changed, 136 insertions(+), 9 deletions(-) diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index e234903e7..30a318296 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -207,6 +207,95 @@ private : return g4 - pi/2; } + template + static void bisection(CT lon1, CT lat1, //p1 + CT lon2, CT lat2, //p2 + CT lon3, CT lat3, //query point p3 + Spheroid const& spheroid, + CT& s14, CT const& a12, + result_distance_point_segment& result) + { + typedef typename FormulaPolicy::template direct + direct_distance_type; + typedef typename FormulaPolicy::template inverse + inverse_distance_type; + + geometry::formula::result_direct res14; + + int counter = 0; // robustness + bool dist_improve = true; + + CT pl_lon = lon1; + CT pl_lat = lat1; + CT pr_lon = lon2; + CT pr_lat = lat2; + + s14 = geometry::strategy::distance::geographic + ::apply(lon1, lat1, lon2, lat2, spheroid) / 2; + + do{ + // Solve the direct problem to find p4 (GEO) + res14 = direct_distance_type::apply(lon1, lat1, s14, a12, spheroid); + +#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK + std::cout << "dist(pl,p3)=" + << inverse_distance_type::apply(lon3, lat3, + pr_lon, pr_lat, + spheroid).distance + << std::endl; + std::cout << "dist(pr,p3)=" + << inverse_distance_type::apply(lon3, lat3, + pr_lon, pr_lat, + spheroid).distance + << std::endl; +#endif + if (inverse_distance_type::apply(lon3, lat3, pl_lon, pl_lat, spheroid).distance + < inverse_distance_type::apply(lon3, lat3, pr_lon, pr_lat, spheroid).distance) + { + s14 -= inverse_distance_type::apply(res14.lon2, res14.lat2, pl_lon, pl_lat, + spheroid).distance/2; + pr_lon = res14.lon2; + pr_lat = res14.lat2; + } + else + { + s14 += inverse_distance_type::apply(res14.lon2, res14.lat2, pr_lon, pr_lat, + spheroid).distance/2; + pl_lon = res14.lon2; + pl_lat = res14.lat2; + } + + CT new_distance = inverse_distance_type::apply(lon3, lat3, + res14.lon2, res14.lat2, + spheroid).distance; + + dist_improve = new_distance != result.distance; + +#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK + std::cout << "p4=" << res14.lon2 * math::r2d() << + "," << res14.lat2 * math::r2d() << std::endl; + std::cout << "pl=" << pl_lon * math::r2d() << "," << pl_lat * math::r2d()<< std::endl; + std::cout << "pr=" << pr_lon * math::r2d() << "," << pr_lat * math::r2d() << std::endl; + std::cout << "new_s14=" << s14 << std::endl; + std::cout << std::setprecision(16) << "result.distance =" << result.distance << std::endl; + std::cout << std::setprecision(16) << "new_distance =" << new_distance << std::endl; + std::cout << "---------end of step " << counter << std::endl<< std::endl; + if (!dist_improve) + { + std::cout << "Stop msg: res34.distance >= prev_distance" << std::endl; + } + if (counter == BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS) + { + std::cout << "Stop msg: counter" << std::endl; + } +#endif + + result.distance = new_distance; + + } while (dist_improve + && counter++ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS); + } + template static void newton_update(CT lon1, CT lat1, //p1 CT lon2, CT lat2, //p2 @@ -575,9 +664,16 @@ private : // Update s14 (using Newton method) - newton_update(lon1, lat1, lon2, lat2, lon3, lat3, + if (Bisection) + { + bisection(lon1, lat1, lon2, lat2, lon3, lat3, spheroid, s14, a12, result); - + } + else + { + newton_update(lon1, lat1, lon2, lat2, lon3, lat3, + spheroid, s14, a12, result); + } return result; } @@ -619,6 +715,18 @@ struct tag > typedef strategy_tag_distance_point_segment type; }; +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType, + bool Bisection +> +struct tag > +{ + typedef strategy_tag_distance_point_segment type; +}; + //return types template @@ -649,18 +757,32 @@ struct return_type::template return_type {}; +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType, + bool Bisection, + typename P, + typename PS +> +struct return_type, P, PS> + : geographic_cross_track::template return_type +{}; + //comparable types template < typename FormulaPolicy, typename Spheroid, - typename CalculationType + typename CalculationType, + bool Bisection > -struct comparable_type > +struct comparable_type > { typedef geographic_cross_track < - FormulaPolicy, Spheroid, CalculationType + FormulaPolicy, Spheroid, CalculationType, Bisection > type; }; @@ -668,13 +790,14 @@ template < typename FormulaPolicy, typename Spheroid, - typename CalculationType + typename CalculationType, + bool Bisection > -struct get_comparable > +struct get_comparable > { public : - static inline geographic_cross_track - apply(geographic_cross_track const& strategy) + static inline geographic_cross_track + apply(geographic_cross_track const& strategy) { return strategy; } diff --git a/test/algorithms/distance/distance_geo_pl_l.cpp b/test/algorithms/distance/distance_geo_pl_l.cpp index bab601dee..b9fd567ad 100644 --- a/test/algorithms/distance/distance_geo_pl_l.cpp +++ b/test/algorithms/distance/distance_geo_pl_l.cpp @@ -657,6 +657,7 @@ void test_all_pl_l(Strategy_pp pp_strategy, Strategy_ps ps_strategy, BOOST_AUTO_TEST_CASE( test_all_pointlike_linear ) { + test_all_pl_l(vincenty_pp(), vincenty_ps_bisection()); test_all_pl_l(vincenty_pp(), vincenty_ps()); test_all_pl_l(thomas_pp(), thomas_ps()); test_all_pl_l(andoyer_pp(), andoyer_ps()); diff --git a/test/algorithms/distance/test_distance_geo_common.hpp b/test/algorithms/distance/test_distance_geo_common.hpp index 09e9c1908..3c94e664a 100644 --- a/test/algorithms/distance/test_distance_geo_common.hpp +++ b/test/algorithms/distance/test_distance_geo_common.hpp @@ -71,6 +71,9 @@ typedef bg::strategy::distance::geographic_cross_track vincenty_ps; +typedef bg::strategy::distance::geographic_cross_track + vincenty_ps_bisection; + // Spherical strategy for point-box distance typedef bg::strategy::distance::cross_track_point_box<> spherical_pb; From 0ab8a04e916ae960eac258146aed834b578a07e6 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Wed, 24 Apr 2019 12:22:39 +0300 Subject: [PATCH 12/68] [test] Tests for distance pt-sgmt strategy --- test/strategies/Jamfile.v2 | 6 +- test/strategies/distance_cross_track.cpp | 125 +++++ .../strategies/distance_cross_track_cases.hpp | 491 ++++++++++++++++++ 3 files changed, 620 insertions(+), 2 deletions(-) create mode 100644 test/strategies/distance_cross_track.cpp create mode 100644 test/strategies/distance_cross_track_cases.hpp diff --git a/test/strategies/Jamfile.v2 b/test/strategies/Jamfile.v2 index 10d281b38..11f502d0f 100644 --- a/test/strategies/Jamfile.v2 +++ b/test/strategies/Jamfile.v2 @@ -4,9 +4,10 @@ # 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, 2016, 2017, 2018. -# Modifications copyright (c) 2014-2018, Oracle and/or its affiliates. +# This file was modified by Oracle on 2014-2019. +# Modifications copyright (c) 2014-2019, 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 # @@ -20,6 +21,7 @@ test-suite boost-geometry-strategies [ run cross_track.cpp : : : : strategies_cross_track ] [ run crossings_multiply.cpp : : : : strategies_crossings_multiply ] [ run distance_default_result.cpp : : : : strategies_distance_default_result ] + [ run distance_cross_track.cpp : : : : strategies_distance_cross_track ] [ run douglas_peucker.cpp : : : : strategies_douglas_peucker ] [ run envelope_segment.cpp : : : : strategies_envelope_segment ] [ run franklin.cpp : : : : strategies_franklin ] diff --git a/test/strategies/distance_cross_track.cpp b/test/strategies/distance_cross_track.cpp new file mode 100644 index 000000000..930ccc1ae --- /dev/null +++ b/test/strategies/distance_cross_track.cpp @@ -0,0 +1,125 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2019 Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, 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 "../formulas/test_formula.hpp" +#include "distance_cross_track_cases.hpp" + +#include +#include +#include + +struct error{ + double long_distance; + double short_distance; + double very_short_distance; + double very_very_short_distance; +}; + +void check_result(double const& result, double const& expected, + double const& reference, error const& reference_error, + bool check_reference_only) +{ + BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 0.0000001, + std::setprecision(20) << "result {" << result << "} different than expected {" << expected << "}."); + + double reference_error_value = result > 1000 ? reference_error.long_distance + : result > 100 ? reference_error.short_distance + : result > 20 ? reference_error.very_short_distance + : reference_error.very_very_short_distance; + + BOOST_GEOMETRY_CHECK_CLOSE(result, reference, reference_error_value, + std::setprecision(20) << "result {" << result << "} different than reference {" << reference << "}."); +} + +template +void test_all(expected_results const& results, bool check_reference_only) +{ + double const d2r = bg::math::d2r(); + double const r2d = bg::math::r2d(); + + double lon1r = results.p1.lon * d2r; + double lat1r = results.p1.lat * d2r; + double lon2r = results.p2.lon * d2r; + double lat2r = results.p2.lat * d2r; + double lon3r = results.p3.lon * d2r; + double lat3r = results.p3.lat * d2r; + + typedef bg::srs::spheroid Spheroid; + + // WGS84 + Spheroid spheroid(6378137.0, 6356752.3142451793); + + std::string output; + + error errors [] + { + {0.00000001, 0.00000001, 0.00000001, 0.000001}, //vincenty + {0.0002, 0.002, 0.01, 0.2}, //thomas + {0.002, 0.3, 15, 25}, //andoyer + {1, 6, 15, 200} //spherical + }; + + //vincenty + double distance = bg::strategy::distance::geographic_cross_track_bisection(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.vincenty_bisection, results.reference, errors[0], check_reference_only); + output += boost::lexical_cast(distance) + ",\n"; + + distance = bg::strategy::distance::geographic_cross_track(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.vincenty, results.reference, errors[0], check_reference_only); + output += boost::lexical_cast(distance) + ",\n"; + + //thomas + distance = bg::strategy::distance::geographic_cross_track_bisection(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.thomas_bisection, results.reference, errors[1], check_reference_only); + output += boost::lexical_cast(distance) + ",\n";; + + distance = bg::strategy::distance::geographic_cross_track(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.thomas, results.reference, errors[1], check_reference_only); + output += boost::lexical_cast(distance) + ",\n"; + + //andoyer + distance = bg::strategy::distance::geographic_cross_track_bisection(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.andoyer_bisection, results.reference, errors[2], check_reference_only); + output += boost::lexical_cast(distance) + ",\n"; + + distance = bg::strategy::distance::geographic_cross_track(spheroid) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.andoyer, results.reference, errors[2], check_reference_only); + output += boost::lexical_cast(distance) + ",\n"; + + //spherical + distance = bg::strategy::distance::cross_track<>(bg::formula::mean_radius(spheroid)) + .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); + check_result(distance, results.spherical, results.reference, errors[3], check_reference_only); + output += boost::lexical_cast(distance) + ",\n"; + std::cout << std::setprecision(20) << output << "\n"; + +} + +int test_main(int, char*[]) +{ + typedef bg::model::point > point; + + for (size_t i = 0; i < expected_size; ++i) + { + test_all(expected[i], false); + } + + return 0; +} diff --git a/test/strategies/distance_cross_track_cases.hpp b/test/strategies/distance_cross_track_cases.hpp new file mode 100644 index 000000000..4ddb0f3a9 --- /dev/null +++ b/test/strategies/distance_cross_track_cases.hpp @@ -0,0 +1,491 @@ +// Boost.Geometry +// Unit Test + +// Copyright (c) 2019 Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, 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_TEST_DISTANCE_CROSS_TRACK_CASES_HPP +#define BOOST_GEOMETRY_TEST_DISTANCE_CROSS_TRACK_CASES_HPP + +struct coordinates +{ + double lon; + double lat; +}; + +struct expected_results +{ + coordinates p1; //1st point of segment + coordinates p2; //2nd point of segment + coordinates p3; //point to compute distance from segment + double reference; // karney or vincenty + double vincenty_bisection; + double vincenty; + double thomas_bisection; + double thomas; + double andoyer_bisection; + double andoyer; + double spherical; +}; + +expected_results expected[] = +{ + { + { 0, 0 },{ 1, 1 },{ 0, 1 }, + 78442.119873761606868, + 78442.119873761606868, + 78442.119873761592316, + 78442.118218914125464, + 78442.118218840550981, + 78440.792929481409374, + 78440.792934224984492, + 78618.810427426869865 + } , { + { 0, 0 },{ 1, 1 },{ 1, 0 }, + 78453.98942845336569, + 78453.98942845336569, + 78453.98942845336569, + 78453.990728736869642, + 78453.990728682110785, + 78453.54172924211889, + 78453.541733992169611, + 78630.786885094828904 + } , { + { 10, 15 },{ 30, 15 },{ 15, 80 }, + 7204174.4886689241976, + 7204174.4886689241976, + 7204174.4886689241976, + 7204174.4785777237266, + 7204174.4785777227953, + 7204194.9162934627384, + 7204194.9162937803194, + 7205729.8545973757282 + } , { + { 10, 15 },{ 30, 15 },{ 15, 10 }, + 571412.78107940487098, + 571412.78107940487098, + 571412.78107940475456, + 571412.77996722259559, + 571412.77996722620446, + 571408.51759251800831, + 571408.51759251928888, + 574226.66911869682372 + } , { + { 10, 15 },{ 30, 15 },{ 5, 10 }, + 775316.40275838342495, + 775316.40275838342495, + 775316.40275838342495, + 775316.40098149504047, + 775316.40098149504047, + 775309.55307898123283, + 775309.55307898123283, + 776861.2271022957284 + } , { + { 10, 15 },{ 30, 15 },{ 35, 10 }, + 775316.40275838342495, + 775316.40275838342495, + 775316.40275838342495, + 775316.40098149504047, + 775316.40098149504047, + 775309.55307898123283, + 775309.55307898123283, + 776861.22710229584482 + } , { + { 2, 2 },{ 3, 2 },{ 3.5, 3 }, + 123770.82713049851009, + 123770.82713049851009, + 123770.82713049851009, + 123770.82682863833907, + 123770.82682863833907, + 123769.27773668900772, + 123769.27773668900772, + 124295.90554402528505 + } , { + { 2, 2 },{ 3, 2 },{ 1.5, 3 }, + 123770.82713049851009, + 123770.82713049851009, + 123770.82713049851009, + 123770.82682863833907, + 123770.82682863833907, + 123769.27773668900772, + 123769.27773668900772, + 124295.90554402528505 + } , { + { 2, 2 },{ 3, 2 },{ 2, 3 }, + 110576.41139532231318, + 110576.41139532231318, + 110576.41139532238594, + 110576.41139116862905, + 110576.41139118297724, + 110575.1780244907568, + 110575.17802451056195, + 111195.07457694716868 + } , { + { 2, 2 },{ 3, 2 },{ 3, 3 }, + 110576.41139532234229, + 110576.41139532234229, + 110576.41139532234229, + 110576.41139242639474, + 110576.41139243228827, + 110575.17802478378871, + 110575.17802474705968, + 111195.07457694721234 + } , { + { 2, 2 },{ 3, 2 },{ 3.5, 1 }, + 123784.75399867084343, + 123784.75399867084343, + 123784.75399867084343, + 123784.75369734384003, + 123784.75369734384003, + 123783.19294134904339, + 123783.19294134904339, + 124311.043335600305 + } , { + { 2, 2 },{ 3, 2 },{ 1.5, 1 }, + 123784.75399867084343, + 123784.75399867084343, + 123784.75399867084343, + 123784.75369734384003, + 123784.75369734384003, + 123783.19294134904339, + 123783.19294134904339, + 124311.043335600305 + } , { + { 2, 2 },{ 3, 2 },{ 2, 1 }, + 110575.06481432798319, + 110575.06481432798319, + 110575.06481432798319, + 110575.06688667042181, + 110575.06688667042181, + 110573.82008001199574, + 110573.82008001199574, + 111195.07973463158123 + } , { + { 2, 2 },{ 3, 2 },{ 3, 1 }, + 110575.06481432798319, + 110575.06481432798319, + 110575.06481432798319, + 110575.06688667042181, + 110575.06688667042181, + 110573.82008001199574, + 110573.82008001199574, + 111195.07973463158123 + } , { + { 2, -2 },{ 3, -2 },{ 3, -1 }, + 110575.06481432798319, + 110575.06481432798319, + 110575.06481432798319, + 110575.06688667042181, + 110575.06688667042181, + 110573.82008001199574, + 110573.82008001199574, + 111195.07973463158123 + } , { + { 220, 2 },{ 3, 2 },{ 3, 1 }, + 110575.06481432798319, + 110575.06481432798319, + 110575.06481432798319, + 110575.06688667042181, + 110575.06688667042181, + 110573.82008001199574, + 110573.82008001199574, + 111195.07973463158123 + } , //antimeridian + { + { 220, 2 },{ 3, 2 },{ 220, 1 }, + 110575.06481432798319, + 110575.06481432798319, + 110575.06481432798319, + 110575.06688667042181, + 110575.06688667042181, + 110573.82008001199574, + 110573.82008001199574, + 111195.07973463158123 + } , //meridian + { + { 2, 2 },{ 2, 4 },{ 2.5, 2 }, + 55626.064900081859, + 55626.064900081859, + 55626.064900081867, + 55626.06490013907, + 55626.064900107223, + 55626.065279513903, + 55626.065279463517, + 55563.670489238102 + } , { + { 2, 2 },{ 2, 4 },{ 2.5, 5 }, + 123722.15822285149, + 123722.15822285149, + 123722.15822285149, + 123722.15791917888, + 123722.15791917888, + 123720.64936755209, + 123720.64936755209, + 124243.00560435352 + } , { + { 2, 2 },{ 2, 4 },{ 2.5, 3 }, + 55583.973320908837, + 55583.973320908837, + 55583.97332090883, + 55583.973320941128, + 55583.973320900877, + 55583.97416950998, + 55583.974169663285, + 55521.343440931159 + } , { + { 0, 40 },{ 180, 80 },{ 0, 20 }, + 2217162.7761786841, + 2217162.7761786841, + 2217162.7761786841, + 2217162.7361901053, + 2217162.7361901053, + 2217171.9891410829, + 2217171.9891410829, + 2223901.5946926316 + } , { + { 0, 40 },{ 0, 80 },{ 0, 20 }, + 2217162.7761786841, + 2217162.7761786841, + 2217162.7761786841, + 2217162.7361901053, + 2217162.7361901053, + 2217171.9891410829, + 2217171.9891410829, + 2223901.5946926316 + } , { + { 0, 0 },{ 0, 90 },{ 0, 80 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + } , { + { 0, 0 },{ 0, 90 },{ 1, 80 }, + 19392.530629092114, + 19392.530629092114, + 19392.530629092107, + 19392.53062953979, + 19392.530629094777, + 19392.328788289116, + 19392.328788113067, + 19307.872231041671 + } , { + { 1, -1 }, { 1, 0 },{ 2, 0 }, + 111319.4907932264, + 111319.4907932264, + 111319.4907932264, + 111319.49079334327, + 111319.49079326246, + 111319.49079326226, + 111319.49079326246, + 111195.07973463158 + } , //equator + { + { 2, 0 },{ 3, 0 },{ 0, 0 }, + 222638.98158645280637, + 222638.98158645280637, + 222638.98158645280637, + 222638.98158654122381, + 222638.98158654122381, + 222638.98158654125291, + 222638.98158654125291, + 222390.15946926316246 + } , { + { 2, 0 },{ 3, 0 },{ 2.5, 3 }, + 331725.86989626317518, + 331725.86989626317518, + 331725.86989626317518, + 331725.87608870770782, + 331725.87608870770782, + 331722.14136137196328, + 331722.14136137196328, + 333585.2392038948019 + } , { + { 2, 0 },{ 3, 0 },{ 2, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + } , { + { 2, 0 },{ 3, 0 },{ 3, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + } , { + { 2, 0 },{ 3, 0 },{ 2.5, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + } , { + { 2, 0 },{ 3, 0 },{ 3.5, 3 }, + 336358.80734967370518, + 336358.80734967370518, + 336358.80734967370518, + 336358.80718013871228, + 336358.80718013871228, + 336354.9292840428534, + 336354.9292840428534, + 338182.45508443051949 + } , //segment pass by pole +/* those cases have expected very large reference errors for spherical + * { + { 0, 0 },{ 180, 0 },{ 0, 90 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 10007557.176116843 + } , { + { 0, 0 },{ 180, 0 },{ 80, 89 }, + 109996.81571864839, + 109996.81571864839, + 109996.81571864836, + 109996.81571864968, + 109996.81571858823, + 109995.58014976831, + 109995.58014972134, + 9896362.096382184, + }*/ // short distance to segment + { + { 0.5, 0 },{ 175.5, 0 },{ 90, 1e-3 }, + 110.57427582169922, + 110.57427582169922, + 110.57427582169922, + 110.57427792305019, + 110.57427792305019, + 110.57302444153535, + 110.57302444153535, + 111.19507973475258 + } , { + { 0.5, 0 },{ 175.5, 0 },{ 90, 1e-8 }, + 0.0011057427582158647, + 0.0011057427582158647, + 0.0011057427582158647, + 0.0011057427792293744, + 0.0011057427792293744, + 0.0011057302444142166, + 0.0011057302444142166, + 0.0011119503057618657 + } , { + { -16.42203, -7.52882 }, { 4.89998, -6.1556 },{ 3.32696, -6.29345 }, + 489.92809351881567, + 489.92809351881567, + 489.92809351901735, + 489.93476618419248, + 489.93477281079282, + 488.53486698285008, + 488.5348711891001, + 516.3066451728439 + } , { + { -16.42203, -7.52882 }, { 4.89998, -6.1556 },{ 3.32696, -6.2889 }, + 11.511229576046485, + 11.511229576046485, + 11.51122957617916, + 11.50474785537202, + 11.504394870933424, + 12.898977232559222, + 12.898968261046516, + 12.130727461169611 + } , { + { -16.42203, -7.52882 }, { 4.89998, -6.1556 },{ 3.32696, -6.28895 }, + 6.0009073659133909, + 6.0009073659133909, + 6.0009073659387502, + 5.9949823734311893, + 5.9941706378723278, + 7.3883629173067344, + 7.3889362323779535, + 17.671122161310702 + } +#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS + , { + { 0, 10 }, { 20, 10 }, { 18.00000000000003908, 10.054676080707787733 }, + 0.0011398027228318023, + 0.0011398027228318023, + 0.0060057460922939617, + 0, + 0, + 0, + 0.30055333992381872, + 39.88666722147299 + } , { + { 0, 10 }, { 20, 10 }, { 18, 10.054678231628329854 }, + 0.23669789852514209, + 0.23669789852514209, + 0.23669789883426567, + 0.25069019912476698, + 0.23204712322540744, + 0.26712030782599411, + 0.40206187237490559, + 40.125767043637062 + } , { + { 0, 10 }, { 20, 10 },{ 17.999999999999950262, 10.054676091041047314 }, + 2.7930744094407741e-06, + 2.7930744094407741e-06, + 0.0058967770186943418, + 0, + 0, + 0, + 0.30055160527904862, + 39.887815883329125 + } +#endif + , // large distance to segment + { + { 0.5, 0 }, { 175.5, 0 }, { 90, 90 }, + 10001965.729311479, + 10001965.729311479, + 10001965.729311479, + 10001965.729311479, + 10001965.729311479, + 10001958.678477952, + 10001958.678477952, + 10007557.108987356 + } , { + { 0.5, -89 }, { 175.5, -89 }, { 90, 90 }, + 19892237.59370932, + 19892237.59370932, + 19892237.59370932, + 19892237.570068691, + 19892237.570068691, + 19892224.746673118, + 19892224.746673118, + 19903919.272499084 + } , //acos issue solved + { + { 90, 0 }, { 0, 1.000005 }, {0, 90}, + 9891389.2448064201, + 9891389.2448064201, + 9891389.2448064163, + 9891370.4775929395, + 9891370.4775932431, + 9891383.4444574378, + 9891383.4444574378, + 9896361.5404068138 + } +}; + +size_t const expected_size = sizeof(expected) / sizeof(expected_results); + +#endif // BOOST_GEOMETRY_TEST_DISTANCE_CROSS_TRACK_CASES_HPP From 1ec4137c9be4b0bb068b9778743b9e24769679be Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Wed, 24 Apr 2019 15:40:29 +0300 Subject: [PATCH 13/68] [test] Minor change in distance pt-sgmt test case --- test/strategies/distance_cross_track_cases.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/strategies/distance_cross_track_cases.hpp b/test/strategies/distance_cross_track_cases.hpp index 4ddb0f3a9..b60588bbe 100644 --- a/test/strategies/distance_cross_track_cases.hpp +++ b/test/strategies/distance_cross_track_cases.hpp @@ -388,15 +388,15 @@ expected_results expected[] = 0.0011057302444142166, 0.0011119503057618657 } , { - { -16.42203, -7.52882 }, { 4.89998, -6.1556 },{ 3.32696, -6.29345 }, - 489.92809351881567, - 489.92809351881567, - 489.92809351901735, - 489.93476618419248, - 489.93477281079282, - 488.53486698285008, - 488.5348711891001, - 516.3066451728439 + { -16.42203, -7.52882 }, { 4.89998, -6.15568 },{ 3.32696, -6.29345 }, + 481.73908764883043, + 481.73908764883043, + 481.73908764873721, + 481.74578258317035, + 481.74576160418479, + 480.34603374821353, + 480.34602624448405, + 508.0731159303939, } , { { -16.42203, -7.52882 }, { 4.89998, -6.1556 },{ 3.32696, -6.2889 }, 11.511229576046485, From bdf759a1d1208a8e5cfabf66e9dc127a8a07fa2f Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Wed, 24 Apr 2019 16:43:28 +0300 Subject: [PATCH 14/68] [test] Distance pt-seg; added test case; fix initializers; remove redundant function parameters --- test/strategies/distance_cross_track.cpp | 33 +++++++++---------- .../strategies/distance_cross_track_cases.hpp | 23 +++++++++++-- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/test/strategies/distance_cross_track.cpp b/test/strategies/distance_cross_track.cpp index 930ccc1ae..c8f2b6839 100644 --- a/test/strategies/distance_cross_track.cpp +++ b/test/strategies/distance_cross_track.cpp @@ -16,7 +16,6 @@ #include "distance_cross_track_cases.hpp" #include -#include #include struct error{ @@ -27,13 +26,12 @@ struct error{ }; void check_result(double const& result, double const& expected, - double const& reference, error const& reference_error, - bool check_reference_only) + double const& reference, error const& reference_error) { BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 0.0000001, std::setprecision(20) << "result {" << result << "} different than expected {" << expected << "}."); - double reference_error_value = result > 1000 ? reference_error.long_distance + double reference_error_value = result > 2000 ? reference_error.long_distance : result > 100 ? reference_error.short_distance : result > 20 ? reference_error.very_short_distance : reference_error.very_very_short_distance; @@ -43,10 +41,9 @@ void check_result(double const& result, double const& expected, } template -void test_all(expected_results const& results, bool check_reference_only) +void test_all(expected_results const& results) { double const d2r = bg::math::d2r(); - double const r2d = bg::math::r2d(); double lon1r = results.p1.lon * d2r; double lat1r = results.p1.lat * d2r; @@ -66,47 +63,47 @@ void test_all(expected_results const& results, bool check_reference_only) { {0.00000001, 0.00000001, 0.00000001, 0.000001}, //vincenty {0.0002, 0.002, 0.01, 0.2}, //thomas - {0.002, 0.3, 15, 25}, //andoyer + {0.002, 0.4, 15, 25}, //andoyer {1, 6, 15, 200} //spherical }; //vincenty - double distance = bg::strategy::distance::geographic_cross_track_bisection(spheroid) + double distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); - check_result(distance, results.vincenty_bisection, results.reference, errors[0], check_reference_only); + check_result(distance, results.vincenty_bisection, results.reference, errors[0]); output += boost::lexical_cast(distance) + ",\n"; distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); - check_result(distance, results.vincenty, results.reference, errors[0], check_reference_only); + check_result(distance, results.vincenty, results.reference, errors[0]); output += boost::lexical_cast(distance) + ",\n"; //thomas - distance = bg::strategy::distance::geographic_cross_track_bisection(spheroid) + distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); - check_result(distance, results.thomas_bisection, results.reference, errors[1], check_reference_only); + check_result(distance, results.thomas_bisection, results.reference, errors[1]); output += boost::lexical_cast(distance) + ",\n";; distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); - check_result(distance, results.thomas, results.reference, errors[1], check_reference_only); + check_result(distance, results.thomas, results.reference, errors[1]); output += boost::lexical_cast(distance) + ",\n"; //andoyer - distance = bg::strategy::distance::geographic_cross_track_bisection(spheroid) + distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); - check_result(distance, results.andoyer_bisection, results.reference, errors[2], check_reference_only); + check_result(distance, results.andoyer_bisection, results.reference, errors[2]); output += boost::lexical_cast(distance) + ",\n"; distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); - check_result(distance, results.andoyer, results.reference, errors[2], check_reference_only); + check_result(distance, results.andoyer, results.reference, errors[2]); output += boost::lexical_cast(distance) + ",\n"; //spherical distance = bg::strategy::distance::cross_track<>(bg::formula::mean_radius(spheroid)) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); - check_result(distance, results.spherical, results.reference, errors[3], check_reference_only); + check_result(distance, results.spherical, results.reference, errors[3]); output += boost::lexical_cast(distance) + ",\n"; std::cout << std::setprecision(20) << output << "\n"; @@ -118,7 +115,7 @@ int test_main(int, char*[]) for (size_t i = 0; i < expected_size; ++i) { - test_all(expected[i], false); + test_all(expected[i]); } return 0; diff --git a/test/strategies/distance_cross_track_cases.hpp b/test/strategies/distance_cross_track_cases.hpp index b60588bbe..3716fc3f2 100644 --- a/test/strategies/distance_cross_track_cases.hpp +++ b/test/strategies/distance_cross_track_cases.hpp @@ -265,6 +265,7 @@ expected_results expected[] = 0, 0, 0, + 0, 0 } , { { 0, 0 },{ 0, 90 },{ 1, 80 }, @@ -315,6 +316,7 @@ expected_results expected[] = 0, 0, 0, + 0, 0 } , { { 2, 0 },{ 3, 0 },{ 3, 0 }, @@ -324,6 +326,7 @@ expected_results expected[] = 0, 0, 0, + 0, 0 } , { { 2, 0 },{ 3, 0 },{ 2.5, 0 }, @@ -333,6 +336,7 @@ expected_results expected[] = 0, 0, 0, + 0, 0 } , { { 2, 0 },{ 3, 0 },{ 3.5, 3 }, @@ -388,7 +392,8 @@ expected_results expected[] = 0.0011057302444142166, 0.0011119503057618657 } , { - { -16.42203, -7.52882 }, { 4.89998, -6.15568 },{ 3.32696, -6.29345 }, + // mysql Bug #29545865 + { -16.42203, -7.52882 },{ 4.89998, -6.15568 },{ 3.32696, -6.29345 }, 481.73908764883043, 481.73908764883043, 481.73908764873721, @@ -398,7 +403,7 @@ expected_results expected[] = 480.34602624448405, 508.0731159303939, } , { - { -16.42203, -7.52882 }, { 4.89998, -6.1556 },{ 3.32696, -6.2889 }, + { -16.42203, -7.52882 },{ 4.89998, -6.1556 },{ 3.32696, -6.2889 }, 11.511229576046485, 11.511229576046485, 11.51122957617916, @@ -408,7 +413,7 @@ expected_results expected[] = 12.898968261046516, 12.130727461169611 } , { - { -16.42203, -7.52882 }, { 4.89998, -6.1556 },{ 3.32696, -6.28895 }, + { -16.42203, -7.52882 },{ 4.89998, -6.1556 },{ 3.32696, -6.28895 }, 6.0009073659133909, 6.0009073659133909, 6.0009073659387502, @@ -417,6 +422,18 @@ expected_results expected[] = 7.3883629173067344, 7.3889362323779535, 17.671122161310702 + } , { + // mysql Bug #29545865 + //{ 8.65279, -2.71668 }, + { -7.13372, 8.35583 },{ -9.09998, -1.22625 },{ -7.35561, 7.2137 }, + 1671.2894143458557, + 1671.2894143458557, + 1671.2894143458786, + 1671.2962894596874, + 1671.296284713379, + 1677.2323385335374, + 1677.232338307874, + 1668.697566121507 } #ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS , { From 720a02cd37cf8612b29fbf75a637f88ed2975a83 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Wed, 24 Apr 2019 16:49:58 +0300 Subject: [PATCH 15/68] [strategies] Use constant references in distance_cross_track geographic strategy --- .../geographic/distance_cross_track.hpp | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 30a318296..09e60d005 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -122,7 +122,7 @@ public : // points on a meridian not crossing poles template - inline CT vertical_or_meridian(CT lat1, CT lat2) const + inline CT vertical_or_meridian(CT const& lat1, CT const& lat2) const { typedef typename formula::meridian_inverse < @@ -152,7 +152,7 @@ private : template result_distance_point_segment - static inline non_iterative_case(CT lon, CT lat, CT distance) + static inline non_iterative_case(CT const& lon, CT const& lat, CT const& distance) { result_distance_point_segment result; result.distance = distance; @@ -167,8 +167,8 @@ private : template result_distance_point_segment - static inline non_iterative_case(CT lon1, CT lat1, //p1 - CT lon2, CT lat2, //p2 + static inline non_iterative_case(CT const& lon1, CT const& lat1, //p1 + CT const& lon2, CT const& lat2, //p2 Spheroid const& spheroid) { CT distance = geometry::strategy::distance::geographic @@ -178,7 +178,7 @@ private : } template - CT static inline normalize(CT g4, CT& der) + CT static inline normalize(CT const& g4, CT& der) { CT const pi = math::pi(); if (g4 < -1.25*pi)//close to -270 @@ -208,9 +208,9 @@ private : } template - static void bisection(CT lon1, CT lat1, //p1 - CT lon2, CT lat2, //p2 - CT lon3, CT lat3, //query point p3 + static void bisection(CT const& lon1, CT const& lat1, //p1 + CT const& lon2, CT const& lat2, //p2 + CT const& lon3, CT const& lat3, //query point p3 Spheroid const& spheroid, CT& s14, CT const& a12, result_distance_point_segment& result) @@ -297,12 +297,12 @@ private : } template - static void newton_update(CT lon1, CT lat1, //p1 - CT lon2, CT lat2, //p2 - CT lon3, CT lat3, //query point p3 - Spheroid const& spheroid, - CT& s14, CT const& a12, - result_distance_point_segment& result) + static void newton(CT const& lon1, CT const& lat1, //p1 + CT const& lon2, CT const& lat2, //p2 + CT const& lon3, CT const& lat3, //query point p3 + Spheroid const& spheroid, + CT& s14, CT const& a12, + result_distance_point_segment& result) { typedef typename FormulaPolicy::template inverse inverse_distance_azimuth_quantities_type; @@ -425,9 +425,9 @@ private : template result_distance_point_segment - static inline apply(CT lon1, CT lat1, //p1 - CT lon2, CT lat2, //p2 - CT lon3, CT lat3, //query point p3 + static inline apply(CT const& lo1, CT const& la1, //p1 + CT const& lo2, CT const& la2, //p2 + CT const& lo3, CT const& la3, //query point p3 Spheroid const& spheroid) { typedef typename FormulaPolicy::template inverse @@ -446,12 +446,12 @@ private : CT const c0 = CT(0); // Convert to radians - lon1 = math::as_radian(lon1); - lat1 = math::as_radian(lat1); - lon2 = math::as_radian(lon2); - lat2 = math::as_radian(lat2); - lon3 = math::as_radian(lon3); - lat3 = math::as_radian(lat3); + CT lon1 = math::as_radian(lo1); + CT lat1 = math::as_radian(la1); + CT lon2 = math::as_radian(lo2); + CT lat2 = math::as_radian(la2); + CT lon3 = math::as_radian(lo3); + CT lat3 = math::as_radian(la3); if (lon1 > lon2) { @@ -671,7 +671,7 @@ private : } else { - newton_update(lon1, lat1, lon2, lat2, lon3, lat3, + newton(lon1, lat1, lon2, lat2, lon3, lat3, spheroid, s14, a12, result); } From f24542af2e00e6c72cdc628f7462d01417e5c0cf Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Wed, 24 Apr 2019 17:40:21 +0300 Subject: [PATCH 16/68] [test] Distance pt-seg; another test case for point on the othe side of segment --- .../strategies/geographic/distance_cross_track.hpp | 5 +++++ test/strategies/distance_cross_track_cases.hpp | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 09e60d005..47b9744b5 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -655,6 +655,11 @@ private : s14 = geometry::strategy::distance::geographic ::apply(lon1, lat1, res.lon2, res.lat2, spheroid); + std::cout << "spherical + geo= " + << geometry::strategy::distance::geographic + ::apply(lon3, lat3, res.lon2, res.lat2, spheroid) + << std::endl; + #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "s34=" << s34 << std::endl; std::cout << "s13=" << s13 << std::endl; diff --git a/test/strategies/distance_cross_track_cases.hpp b/test/strategies/distance_cross_track_cases.hpp index 3716fc3f2..01cf2a120 100644 --- a/test/strategies/distance_cross_track_cases.hpp +++ b/test/strategies/distance_cross_track_cases.hpp @@ -401,7 +401,17 @@ expected_results expected[] = 481.74576160418479, 480.34603374821353, 480.34602624448405, - 508.0731159303939, + 508.0731159303939 + } , { // same segment but the point is from the other side + { -16.42203, -7.52882 },{ 4.89998, -6.15568 },{ 3.3262, -6.28451}, + 510.48273138899611, + 510.48273138899611, + 510.48273138908797, + 510.47605556026537, + 510.47605888246693, + 511.86547773473234, + 511.86548088955459, + 489.55321195417821 } , { { -16.42203, -7.52882 },{ 4.89998, -6.1556 },{ 3.32696, -6.2889 }, 11.511229576046485, From 59a52077c77ab9dab4ffe727cd5b80775367e351 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Fri, 26 Apr 2019 17:16:12 +0200 Subject: [PATCH 17/68] [overlay] fix and review remarks --- .../detail/overlay/get_distance_measure.hpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp index 0b14e88a8..bf65af5fc 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp @@ -14,6 +14,8 @@ #include #include +#include + namespace boost { namespace geometry { @@ -24,10 +26,10 @@ namespace detail template struct distance_measure { - T value; + T measure; distance_measure() - : value(T()) + : measure(T()) {} bool is_small() const { return true; } @@ -48,7 +50,7 @@ struct distance_measure_floating // This is an arbitrary boundary, to enable some behaviour // (for example include or exclude turns), which are checked later // with other conditions. - bool is_small() const { return std::fabs(measure) < 1.0e-3; } + bool is_small() const { return std::abs(measure) < 1.0e-3; } // Returns true if the distance measure is absolutely zero bool is_zero() const { return measure == 0.0; } @@ -76,9 +78,12 @@ struct distance_measure namespace detail_dispatch { -template +// TODO: this is effectively a strategy, but for internal usage. +// It might be moved to the strategies folder. + +template struct get_distance_measure - : not_implemented + : not_implemented {}; template @@ -168,6 +173,7 @@ namespace detail // 0 (absolutely 0, not even an epsilon) means collinear. Like side, // a negative means that p is to the right of p1-p2. And a positive value // means that p is to the left of p1-p2. + template static distance_measure::type> get_distance_measure(SegmentPoint const& p1, SegmentPoint const& p2, Point const& p) From 6b4ef246c3b9e4f7535fe5d87dd5cd8536d5a0c2 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 1 May 2019 22:00:47 +0200 Subject: [PATCH 18/68] [overlay] apply review remarks --- .../detail/overlay/get_distance_measure.hpp | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp index bf65af5fc..ec3936511 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp @@ -134,34 +134,9 @@ struct get_distance_measure } }; -template -struct get_distance_measure -{ - typedef detail::distance_measure result_type; - - template - static result_type apply(SegmentPoint const& , SegmentPoint const& , - Point const& ) - { - // TODO, optional - result_type result; - return result; - } -}; template struct get_distance_measure -{ - typedef detail::distance_measure result_type; - - template - static result_type apply(SegmentPoint const& , SegmentPoint const& , - Point const& ) - { - // TODO, optional - result_type result; - return result; - } -}; + : get_distance_measure {}; } // namespace detail_dispatch From bde086d94481aca7b2c20f482f07e1615bb1a8e5 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 1 May 2019 15:44:45 +0200 Subject: [PATCH 19/68] [traverse] remove condition for self-turn --- include/boost/geometry/algorithms/detail/overlay/traversal.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp index 831d5e395..ee993e0d9 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp @@ -803,8 +803,7 @@ public : { continue; } - if (is_self_turn(cluster_turn) - || cluster_turn.both(target_operation)) + if (cluster_turn.both(target_operation)) { // Not (yet) supported, can be cluster of u/u turns return false; From bcb9f60becd1a4f7107decf1d92c35f13cd06acf Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 1 May 2019 15:45:15 +0200 Subject: [PATCH 20/68] [test] add testcases 17,18,19,20 --- test/algorithms/overlay/overlay_cases.hpp | 25 +++++++++++++++ .../intersection/intersection.cpp | 32 +++++++++++++------ .../algorithms/set_operations/union/union.cpp | 12 +++++++ 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/test/algorithms/overlay/overlay_cases.hpp b/test/algorithms/overlay/overlay_cases.hpp index 196509222..6e6e55959 100644 --- a/test/algorithms/overlay/overlay_cases.hpp +++ b/test/algorithms/overlay/overlay_cases.hpp @@ -802,6 +802,31 @@ static std::string case_precision_16[2] = "POLYGON((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,2 3,4 2.99999940000000009,4 7,2 7))" }; +static std::string case_precision_17[2] = +{ + "POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))", + "POLYGON((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,2 3,4 3.00000499999999999,4 7,2 7))" +}; + +static std::string case_precision_18[2] = +{ + "POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))", + "POLYGON((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,2.00000199999999984 3.00000400000000012,4 3,4 7,2 7))" +}; + +static std::string case_precision_19[2] = +{ + "POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))", + "POLYGON((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,1.99999199999999999 2.99999400000000005,4 3,4 7,2 7))" +}; + +static std::string case_precision_20[2] = +{ + "POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))", + "POLYGON((2 7,4 7,4 3,2.00000000000000044 3,2 7))" +}; + + // ticket_17 is keyholed, so has a hole formed by an deliberate intersection // This will fail the intersection/traversal process static std::string ticket_17[2] = { diff --git a/test/algorithms/set_operations/intersection/intersection.cpp b/test/algorithms/set_operations/intersection/intersection.cpp index dfad0dced..a8703b51f 100644 --- a/test/algorithms/set_operations/intersection/intersection.cpp +++ b/test/algorithms/set_operations/intersection/intersection.cpp @@ -371,6 +371,22 @@ void test_areal() TEST_INTERSECTION(case_precision_10, 1, -1, 14.0); TEST_INTERSECTION(case_precision_11, 1, -1, 14.0); + { + ut_settings settings(0.01); + TEST_INTERSECTION_WITH(case_precision_12, 0, 1, 1, -1, 2.0, settings); + TEST_INTERSECTION_WITH(case_precision_13, 0, 1, 1, -1, 2.0, settings); + TEST_INTERSECTION_WITH(case_precision_12, 1, 0, 1, -1, 2.0, settings); + TEST_INTERSECTION_WITH(case_precision_13, 1, 0, 1, -1, 2.0, settings); + } + + TEST_INTERSECTION(case_precision_14, 0, -1, 0.0); + TEST_INTERSECTION(case_precision_15, 1, -1, 14.0); + TEST_INTERSECTION(case_precision_16, 1, -1, 14.0); + TEST_INTERSECTION(case_precision_17, 1, -1, 14.0); + TEST_INTERSECTION(case_precision_18, 1, -1, 14.0); + TEST_INTERSECTION(case_precision_19, 1, -1, 14.0); + TEST_INTERSECTION(case_precision_20, 0, 0, 0.0); + TEST_INTERSECTION_REV(case_precision_1, 0, 0, 0.0); TEST_INTERSECTION_REV(case_precision_2, 0, 0, 0.0); TEST_INTERSECTION_REV(case_precision_3, 0, 0, 0.0); @@ -382,16 +398,14 @@ void test_areal() TEST_INTERSECTION_REV(case_precision_9, 1, -1, 14.0); TEST_INTERSECTION_REV(case_precision_10, 1, -1, 14.0); TEST_INTERSECTION_REV(case_precision_11, 1, -1, 14.0); - { - ut_settings settings(0.01); - TEST_INTERSECTION_WITH(case_precision_12, 0, 1, 1, -1, 2.0, settings); - TEST_INTERSECTION_WITH(case_precision_13, 0, 1, 1, -1, 2.0, settings); - TEST_INTERSECTION_WITH(case_precision_12, 1, 0, 1, -1, 2.0, settings); - TEST_INTERSECTION_WITH(case_precision_13, 1, 0, 1, -1, 2.0, settings); - } - TEST_INTERSECTION(case_precision_14, 0, -1, 0.0); - TEST_INTERSECTION(case_precision_15, 1, -1, 14.0); + TEST_INTERSECTION_REV(case_precision_14, 0, -1, 0.0); + TEST_INTERSECTION_REV(case_precision_15, 1, -1, 14.0); + TEST_INTERSECTION_REV(case_precision_16, 1, -1, 14.0); + TEST_INTERSECTION_REV(case_precision_17, 1, -1, 14.0); + TEST_INTERSECTION_REV(case_precision_18, 1, -1, 14.0); + TEST_INTERSECTION_REV(case_precision_19, 1, -1, 14.0); + TEST_INTERSECTION_REV(case_precision_20, 0, 0, 0.0); test_one("mysql_21964049", mysql_21964049[0], mysql_21964049[1], diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index b3e413d39..fa4428e5a 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -271,6 +271,12 @@ void test_areal() TEST_UNION(case_precision_14, 1, 0, -1, 22.0); TEST_UNION(case_precision_15, 1, 1, -1, 73.0); TEST_UNION(case_precision_16, 1, 1, -1, 73.0); + TEST_UNION(case_precision_17, 1, 1, -1, 73.0); + TEST_UNION(case_precision_18, 1, 1, -1, 73.0); + TEST_UNION(case_precision_19, 1, 1, -1, 73.0); +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) + TEST_UNION(case_precision_20, 1, 0, -1, 22.0); +#endif TEST_UNION_REV(case_precision_1, 1, 0, -1, 22.0); TEST_UNION_REV(case_precision_2, 1, 0, -1, 22.0); @@ -288,6 +294,12 @@ void test_areal() TEST_UNION_REV(case_precision_14, 1, 0, -1, 22.0); TEST_UNION_REV(case_precision_15, 1, 1, -1, 73.0); TEST_UNION_REV(case_precision_16, 1, 1, -1, 73.0); + TEST_UNION_REV(case_precision_17, 1, 1, -1, 73.0); + TEST_UNION_REV(case_precision_18, 1, 1, -1, 73.0); + TEST_UNION_REV(case_precision_19, 1, 1, -1, 73.0); +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) + TEST_UNION_REV(case_precision_20, 1, 0, -1, 22.0); +#endif /* test_one(102, From 229b42aee82f4f7823904b34d9a1ed2a98be47e0 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 15 May 2019 12:04:27 +0200 Subject: [PATCH 21/68] [TURNS] Disable start-turns, and take the closer point to measure distance, which makes that measurement more precise. --- .../overlay/enrich_intersection_points.hpp | 4 ++- .../detail/overlay/get_distance_measure.hpp | 6 +++- .../detail/overlay/get_turn_info.hpp | 28 +++++++++++++------ .../algorithms/set_operations/union/union.cpp | 6 +++- 4 files changed, 33 insertions(+), 11 deletions(-) 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 0fe2f02cf..6eb93b4b5 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -428,7 +428,9 @@ inline void enrich_intersection_points(Turns& turns, // As long as turn indexes are not used yet, turns might be erased from // the vector - detail::overlay::erase_colocated_start_turns(turns, geometry1, geometry2); + // For now start turns are disabled. + // TODO: remove code or fix inconsistencies within validity and relations + // detail::overlay::erase_colocated_start_turns(turns, geometry1, geometry2); // From here on, turn indexes are used (in clusters, next_index, etc) // and may only be flagged as discarded diff --git a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp index ec3936511..f879e850b 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp @@ -56,8 +56,12 @@ struct distance_measure_floating bool is_zero() const { return measure == 0.0; } // Returns true if the distance measure is positive. Distance measure - // algorithm should return positive value if it is located on the left side. + // algorithm returns positive value if it is located on the left side. bool is_positive() const { return measure > 0.0; } + + // Returns true if the distance measure is negative. Distance measure + // algorithm returns negative value if it is located on the right side. + bool is_negative() const { return measure < 0.0; } }; template <> 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 b7ec1813d..f726fc1a0 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -159,6 +159,10 @@ struct base_turn_handler std::size_t index_p, std::size_t index_q, TurnInfo& ti) { + BOOST_GEOMETRY_ASSERT(IndexP + IndexQ == 1); + BOOST_GEOMETRY_ASSERT(index_p > 0 && index_p <= 2); + BOOST_GEOMETRY_ASSERT(index_q > 0 && index_q <= 2); + #if ! defined(BOOST_GEOMETRY_USE_RESCALING) ti.operations[IndexP].remaining_distance = distance_measure(ti.point, range_p.at(index_p)); ti.operations[IndexQ].remaining_distance = distance_measure(ti.point, range_q.at(index_q)); @@ -175,17 +179,26 @@ struct base_turn_handler >::type > dm_type; - dm_type const dm = get_distance_measure(range_q.at(index_q - 1), - range_q.at(index_q), range_p.at(index_p)); + const bool p_closer = + ti.operations[IndexP].remaining_distance + < ti.operations[IndexQ].remaining_distance; + dm_type const dm + = p_closer + ? get_distance_measure(range_q.at(index_q - 1), + range_q.at(index_q), range_p.at(index_p)) + : get_distance_measure(range_p.at(index_p - 1), + range_p.at(index_p), range_q.at(index_q)); if (! dm.is_zero()) { // Not truely collinear, distinguish for union/intersection // If p goes left (positive), take that for a union - ti.operations[IndexP].operation = dm.is_positive() + bool p_left = p_closer ? dm.is_positive() : dm.is_negative(); + + ti.operations[IndexP].operation = p_left ? operation_union : operation_intersection; - ti.operations[IndexQ].operation = dm.is_positive() + ti.operations[IndexQ].operation = p_left ? operation_intersection : operation_union; return; } @@ -626,12 +639,11 @@ struct start : public base_turn_handler IntersectionInfo const& info, DirInfo const& dir_info, SideCalculator const& side, - UmbrellaStrategy const& umbrella_strategy) + UmbrellaStrategy const& ) { -#if defined(BOOST_GEOMETRY_USE_RESCALING) - // If rescaled, it is not necessary to handle start turns + // For now disabled. TODO: remove all code or fix inconsistencies + // within validity and relations return false; -#endif if (dir_info.opposite) { diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index fa4428e5a..add1e4552 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -466,15 +466,17 @@ void test_areal() test_one("buffer_rt_a_rev", buffer_rt_a[1], buffer_rt_a[0], 1, 0, -1, 19.28, settings); } +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) test_one("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1], 1, 0, -1, 4.60853); test_one("buffer_rt_f_rev", buffer_rt_f[1], buffer_rt_f[0], 1, 0, -1, 4.60853); +#endif test_one("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1], 1, 0, -1, 16.571); test_one("buffer_rt_g_rev", buffer_rt_g[1], buffer_rt_g[0], 1, 0, -1, 16.571); -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) test_one("buffer_rt_i", buffer_rt_i[0], buffer_rt_i[1], 1, 0, -1, 13.6569); #endif @@ -505,10 +507,12 @@ void test_areal() 1, 0, -1, 18.5710); test_one("buffer_rt_q_rev", buffer_rt_q[1], buffer_rt_q[0], 1, 0, -1, 18.5710); +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) test_one("buffer_rt_r", buffer_rt_r[0], buffer_rt_r[1], 1, 0, -1, 21.07612); test_one("buffer_rt_r_rev", buffer_rt_r[1], buffer_rt_r[0], 1, 0, -1, 21.07612); +#endif test_one("buffer_rt_t", buffer_rt_t[0], buffer_rt_t[1], 1, 0, -1, 15.6569); test_one("buffer_rt_t_rev", buffer_rt_t[1], buffer_rt_t[0], From becbecc0a4398ca71386ade67870cc33ca1f8bab Mon Sep 17 00:00:00 2001 From: Vissarion Fisikopoulos Date: Tue, 21 May 2019 14:24:10 +0300 Subject: [PATCH 22/68] [srs] [projections] Fix call to pj_qsfn in cea --- include/boost/geometry/srs/projections/proj/cea.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/geometry/srs/projections/proj/cea.hpp b/include/boost/geometry/srs/projections/proj/cea.hpp index 467330e56..14d7ea9a3 100644 --- a/include/boost/geometry/srs/projections/proj/cea.hpp +++ b/include/boost/geometry/srs/projections/proj/cea.hpp @@ -164,7 +164,7 @@ namespace projections par.e = sqrt(par.es); proj_parm.apa = pj_authset(par.es); - proj_parm.qp = pj_qsfn(1., par.e, par.one_es); + proj_parm.qp = pj_qsfn(T(1), par.e, par.one_es); } } From ea6dcda82c50966256c4fa31798d29aa812e2f0d Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Tue, 28 May 2019 16:37:59 +0300 Subject: [PATCH 23/68] [strategies] [test] Use correctly units in pt-seg distance geo strategy --- .../geographic/distance_cross_track.hpp | 28 ++++----- .../algorithms/distance/distance_geo_pl_l.cpp | 57 +++++++++++++++++++ 2 files changed, 71 insertions(+), 14 deletions(-) diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 47b9744b5..454080359 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -114,9 +114,9 @@ public : { typedef typename geometry::detail::cs_angular_units::type units_type; - return (apply(get<0>(sp1), get<1>(sp1), - get<0>(sp2), get<1>(sp2), - get<0>(p), get<1>(p), + return (apply(get_as_radian<0>(sp1), get_as_radian<1>(sp1), + get_as_radian<0>(sp2), get_as_radian<1>(sp2), + get_as_radian<0>(p), get_as_radian<1>(p), m_spheroid)).distance; } @@ -445,13 +445,12 @@ private : CT const half_pi = pi / CT(2); CT const c0 = CT(0); - // Convert to radians - CT lon1 = math::as_radian(lo1); - CT lat1 = math::as_radian(la1); - CT lon2 = math::as_radian(lo2); - CT lat2 = math::as_radian(la2); - CT lon3 = math::as_radian(lo3); - CT lat3 = math::as_radian(la3); + CT lon1 = lo1; + CT lat1 = la1; + CT lon2 = lo2; + CT lat2 = la2; + CT lon3 = lo3; + CT lat3 = la3; if (lon1 > lon2) { @@ -655,10 +654,11 @@ private : s14 = geometry::strategy::distance::geographic ::apply(lon1, lat1, res.lon2, res.lat2, spheroid); - std::cout << "spherical + geo= " - << geometry::strategy::distance::geographic - ::apply(lon3, lat3, res.lon2, res.lat2, spheroid) - << std::endl; + // this is used in postgis, at least in 2.5 + //std::cout << "spherical + geo= " + // << geometry::strategy::distance::geographic + // ::apply(lon3, lat3, res.lon2, res.lat2, spheroid) + // << std::endl; #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "s34=" << s34 << std::endl; diff --git a/test/algorithms/distance/distance_geo_pl_l.cpp b/test/algorithms/distance/distance_geo_pl_l.cpp index b9fd567ad..d8b3e282b 100644 --- a/test/algorithms/distance/distance_geo_pl_l.cpp +++ b/test/algorithms/distance/distance_geo_pl_l.cpp @@ -12,6 +12,8 @@ #define BOOST_TEST_MODULE test_distance_geographic_pointlike_linear #endif +#include + #include #include @@ -26,6 +28,9 @@ typedef bg::model::segment segment_type; typedef bg::model::linestring linestring_type; typedef bg::model::multi_linestring multi_linestring_type; +typedef bg::cs::geographic cs_type_rad; +typedef bg::model::point point_type_rad; +typedef bg::model::segment segment_type_rad; //=========================================================================== @@ -381,6 +386,54 @@ void test_distance_point_segment_no_thomas(Strategy_pp const& strategy_pp, strategy_ps, true, true); } +template +void test_distance_point_segment_rad_mix(Strategy_pp const& strategy_pp, + Strategy_ps const& strategy_ps) +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << std::endl; + std::cout << "point/segment distance tests" << std::endl; +#endif + typedef test_distance_of_geometries tester1; + typedef test_distance_of_geometries tester2; + typedef test_distance_of_geometries tester3; + typedef test_distance_of_geometries tester4; + + const double d2r = bg::math::d2r(); + + std::ostringstream s1; + s1 << 1*d2r; + std::ostringstream s2; + s2 << 2*d2r; + std::ostringstream s3; + s3 << 3*d2r; + + tester1::apply("p-s-mix1", + "POINT(3 1)", + "SEGMENT(2 2,3 2)", + //110575.06481432798,//1929.8861025802998, + pp_distance("POINT(3 2)", "POINT(3 1)", strategy_pp), + strategy_ps, true, true); + tester2::apply("p-s-mix2", + "POINT(" + s3.str() + " " + s1.str() + ")", + "SEGMENT(2 2,3 2)", + pp_distance("POINT(3 2)", "POINT(3 1)", strategy_pp), + strategy_ps, true, true); + tester3::apply("p-s-mix3", + "POINT(3 1)", + "SEGMENT(" + s2.str() + " " + s2.str() + "," + + s3.str() + " " + s2.str() + ")", + pp_distance("POINT(3 2)", "POINT(3 1)", strategy_pp), + strategy_ps, true, true); + tester4::apply("p-s-mix4", + "POINT(" + s3.str() + " " + s1.str() + ")", + "SEGMENT(" + s2.str() + " " + s2.str() + "," + + s3.str() + " " + s2.str() + ")", + pp_distance("POINT(3 2)", "POINT(3 1)", strategy_pp), + strategy_ps, true, true); +} + //=========================================================================== template @@ -669,4 +722,8 @@ BOOST_AUTO_TEST_CASE( test_all_pointlike_linear ) test_distance_point_segment_no_thomas(vincenty_pp(), vincenty_ps()); //test_distance_point_segment_no_thomas(thomas_pp(), thomas_ps()); test_distance_point_segment_no_thomas(andoyer_pp(), andoyer_ps()); + + test_distance_point_segment_rad_mix(vincenty_pp(), vincenty_ps()); + test_distance_point_segment_rad_mix(thomas_pp(), thomas_ps()); + test_distance_point_segment_rad_mix(andoyer_pp(), andoyer_ps()); } From 5cd6314aca8060acfa89a6d4486f5ded62018eca Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Wed, 29 May 2019 15:53:58 +0300 Subject: [PATCH 24/68] [tests] Minor fixes in distance pt-segment --- test/algorithms/distance/distance_geo_pl_l.cpp | 9 ++++----- test/algorithms/distance/test_distance_geo_common.hpp | 10 +++++----- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/test/algorithms/distance/distance_geo_pl_l.cpp b/test/algorithms/distance/distance_geo_pl_l.cpp index d8b3e282b..76e300e66 100644 --- a/test/algorithms/distance/distance_geo_pl_l.cpp +++ b/test/algorithms/distance/distance_geo_pl_l.cpp @@ -81,7 +81,7 @@ void test_distance_point_segment(Strategy_pp const& strategy_pp, tester::apply("p-s-02", "POINT(2.5 3)", "SEGMENT(2 0,3 0)", - pp_distance("POINT(2.5 3)", "POINT(2.49777 0)", strategy_pp), + pp_distance("POINT(2.5 3)", "POINT(2.5 0)", strategy_pp), strategy_ps, true, true); tester::apply("p-s-03", "POINT(2 0)", @@ -176,19 +176,19 @@ void test_distance_point_segment(Strategy_pp const& strategy_pp, tester::apply("p-s-down-1", "POINT(2 1)", "SEGMENT(2 2,3 2)", - pp_distance("POINT(2.0003 2)", "POINT(2 1)", strategy_pp), + pp_distance("POINT(2 2)", "POINT(2 1)", strategy_pp), strategy_ps, true, true); tester::apply("p-s-down-2", "POINT(3 1)", "SEGMENT(2 2,3 2)", - pp_distance("POINT(2.9997 2)", "POINT(3 1)", strategy_pp), + pp_distance("POINT(3 2)", "POINT(3 1)", strategy_pp), strategy_ps, true, true); tester::apply("p-s-south", "POINT(3 -1)", "SEGMENT(2 -2,3 -2)", - pp_distance("POINT(2.9997 -2)", "POINT(3 -1)", strategy_pp), + pp_distance("POINT(3 -2)", "POINT(3 -1)", strategy_pp), strategy_ps, true, true); tester::apply("p-s-antimeridian-1", @@ -412,7 +412,6 @@ void test_distance_point_segment_rad_mix(Strategy_pp const& strategy_pp, tester1::apply("p-s-mix1", "POINT(3 1)", "SEGMENT(2 2,3 2)", - //110575.06481432798,//1929.8861025802998, pp_distance("POINT(3 2)", "POINT(3 1)", strategy_pp), strategy_ps, true, true); tester2::apply("p-s-mix2", diff --git a/test/algorithms/distance/test_distance_geo_common.hpp b/test/algorithms/distance/test_distance_geo_common.hpp index 3c94e664a..252759cfe 100644 --- a/test/algorithms/distance/test_distance_geo_common.hpp +++ b/test/algorithms/distance/test_distance_geo_common.hpp @@ -426,10 +426,10 @@ struct test_distance_of_geometries << " -> " << string_from_type::name() << std::endl; - std::cout << "expected distance = " + std::cout << "expected distance = " << std::setprecision(10) << expected_distance << " ; " << std::endl; - std::cout << "distance = " + std::cout << "distance = " << std::setprecision(10) << dist << " ; " << std::endl; @@ -451,7 +451,7 @@ struct test_distance_of_geometries dist, expected_distance); #ifdef BOOST_GEOMETRY_TEST_DEBUG - std::cout << "distance[reversed args] = " + std::cout << "distance[reversed args] = " << std::setprecision(10) << dist << std::endl; #endif @@ -479,7 +479,7 @@ struct test_distance_of_geometries dist, expected_distance); #ifdef BOOST_GEOMETRY_TEST_DEBUG - std::cout << "distance[swap geometry args] = " + std::cout << "distance[swap geometry args] = " << std::setprecision(10) << dist << std::endl; std::cout << std::endl; @@ -507,7 +507,7 @@ struct test_distance_of_geometries dist, expected_distance); #ifdef BOOST_GEOMETRY_TEST_DEBUG - std::cout << "distance[mirror geometries] = " + std::cout << "distance[mirror geometries] = " << std::setprecision(10) << dist << std::endl; std::cout << std::endl; From 861fc385335c7ef24e2f38ec311a0fbeaaa45309 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 22 May 2019 14:01:05 +0200 Subject: [PATCH 25/68] [TEST] Unify different defines into BOOST_GEOMETRY_TEST_ENABLE_FAILURES --- test/algorithms/buffer/buffer_linestring.cpp | 6 +++--- .../buffer/buffer_linestring_aimes.cpp | 2 -- test/algorithms/buffer/buffer_multi_point.cpp | 2 +- test/algorithms/buffer/buffer_multi_polygon.cpp | 10 +++++----- test/algorithms/buffer/buffer_polygon.cpp | 4 ++-- test/algorithms/buffer/test_buffer.hpp | 2 +- .../envelope_expand/envelope_on_spheroid.cpp | 16 ++++++++-------- .../test_envelope_expand_on_spheroid.hpp | 4 ++-- test/algorithms/is_valid.cpp | 4 ++-- .../overlay/get_turns_linear_linear.cpp | 2 +- test/algorithms/overlay/traverse.cpp | 2 +- test/algorithms/overlay/traverse_multi.cpp | 2 +- .../set_operations/difference/difference.cpp | 8 ++++---- .../difference/difference_linear_linear.cpp | 2 +- .../difference/difference_multi.cpp | 4 ++-- .../difference/difference_multi_spike.cpp | 2 +- .../difference/test_difference.hpp | 4 ++-- .../set_operations/intersection/intersection.cpp | 4 ++-- .../intersection/intersection_multi.cpp | 2 +- .../intersection/test_intersection.hpp | 2 +- .../sym_difference_linear_linear.cpp | 2 +- .../set_operations/union/test_union.hpp | 3 +-- test/algorithms/set_operations/union/union.cpp | 12 ++++++------ .../set_operations/union/union_multi.cpp | 2 +- 24 files changed, 50 insertions(+), 53 deletions(-) diff --git a/test/algorithms/buffer/buffer_linestring.cpp b/test/algorithms/buffer/buffer_linestring.cpp index 826ecdd6d..2d9869588 100644 --- a/test/algorithms/buffer/buffer_linestring.cpp +++ b/test/algorithms/buffer/buffer_linestring.cpp @@ -187,7 +187,7 @@ void test_all() // Having flat end test_one("for_collinear", for_collinear, join_round, end_flat, 68.561, 2.0); test_one("for_collinear", for_collinear, join_miter, end_flat, 72, 2.0); -#if defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("for_collinear2", for_collinear2, join_round, end_flat, 74.387, 2.0, 2.0); test_one("for_collinear2", for_collinear2, join_miter, end_flat, 78.0, 2.0, 2.0); #endif @@ -286,7 +286,7 @@ void test_all() 27862.733459829971, 5.9518403867035365); -#if defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("mysql_report_2015_09_08a", mysql_report_2015_09_08a, join_round32, end_round32, 0.0, 1.0); test_one("mysql_report_2015_09_08b", mysql_report_2015_09_08b, join_round32, end_round32, 0.0, 1099511627778.0); test_one("mysql_report_2015_09_08c", mysql_report_2015_09_08c, join_round32, end_round32, 0.0, 0xbe); @@ -314,7 +314,7 @@ void test_all() test_one("mysql_25662426a_5", mysql_25662426a, join_round32, end_flat, 227.8325, 5.0); test_one("mysql_25662426a_10", mysql_25662426a, join_round32, end_flat, 534.1084, 10.0); -#if defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if defined(BOOST_GEOMETRY_TEST_FAILURES) // Left test_one("mysql_25662426a_1", mysql_25662426a, join_round32, end_round32, 54.9018, 1.0, ut_settings(), 0.0); test_one("mysql_25662426a_2", mysql_25662426a, join_round32, end_round32, 103.6072, 2.0, ut_settings(), 0.0); diff --git a/test/algorithms/buffer/buffer_linestring_aimes.cpp b/test/algorithms/buffer/buffer_linestring_aimes.cpp index 6468a80dc..54b6381eb 100644 --- a/test/algorithms/buffer/buffer_linestring_aimes.cpp +++ b/test/algorithms/buffer/buffer_linestring_aimes.cpp @@ -474,8 +474,6 @@ void test_aimes() int test_main(int, char* []) { -#if defined(BOOST_GEOMETRY_USE_RESCALING) test_aimes >(); -#endif return 0; } diff --git a/test/algorithms/buffer/buffer_multi_point.cpp b/test/algorithms/buffer/buffer_multi_point.cpp index ee7793997..ca4d42f16 100644 --- a/test/algorithms/buffer/buffer_multi_point.cpp +++ b/test/algorithms/buffer/buffer_multi_point.cpp @@ -47,7 +47,7 @@ void test_all() test_one("simplex3", simplex, join, end_flat, 44.5692, 3.0); test_one("three1", three, join, end_flat, 3.0 * pi, 1.0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) // For no-rescaling, fails in CCW mode test_one("three2", three, join, end_flat, 36.7592, 2.0); #endif diff --git a/test/algorithms/buffer/buffer_multi_polygon.cpp b/test/algorithms/buffer/buffer_multi_polygon.cpp index af6f4a9a5..a76908917 100644 --- a/test/algorithms/buffer/buffer_multi_polygon.cpp +++ b/test/algorithms/buffer/buffer_multi_polygon.cpp @@ -368,7 +368,7 @@ void test_all() test_one("rt_d", rt_d, join_round, end_flat, 18.8726, 0.3); test_one("rt_e", rt_e, join_round, end_flat, 14.1866, 0.3); -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("rt_g1", rt_g1, join_round, end_flat, 24.719, 1.0); #endif test_one("rt_g3", rt_g3, join_miter, end_flat, 16.5711, 1.0); @@ -382,7 +382,7 @@ void test_all() test_one("rt_h", rt_h, join_round, end_flat, 47.6012, 1.0); test_one("rt_h", rt_h, join_miter, end_flat, 61.7058, 1.0); test_one("rt_i", rt_i, join_round, end_flat, 10.7528, 1.0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("rt_i", rt_i, join_miter, end_flat, 13.6569, 1.0); test_one("rt_j", rt_j, join_round, end_flat, 28.7309, 1.0); #endif @@ -427,11 +427,11 @@ void test_all() test_one("rt_p18", rt_p18, join_miter, end_flat, 23.3137, 1.0); test_one("rt_p19", rt_p19, join_miter, end_flat, 25.5637, 1.0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("rt_p20", rt_p20, join_miter, end_flat, 25.4853, 1.0); #endif -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("rt_p21", rt_p21, join_miter, end_flat, 17.1716, 1.0); #endif @@ -441,7 +441,7 @@ void test_all() test_one("rt_q2", rt_q2, join_miter, end_flat, 26.4853, 1.0); test_one("rt_q2", rt_q2, join_miter, end_flat, 0.9697, -0.25); -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("rt_r", rt_r, join_miter, end_flat, 21.0761, 1.0); #endif diff --git a/test/algorithms/buffer/buffer_polygon.cpp b/test/algorithms/buffer/buffer_polygon.cpp index 359ea6a6f..b0cf23733 100644 --- a/test/algorithms/buffer/buffer_polygon.cpp +++ b/test/algorithms/buffer/buffer_polygon.cpp @@ -374,7 +374,7 @@ void test_all() test_one("snake4", snake, join_miter, end_flat, 64.44, 0.4); test_one("snake5", snake, join_miter, end_flat, 72, 0.5); test_one("snake6", snake, join_miter, end_flat, 75.44, 0.6); -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("snake16", snake, join_miter, end_flat, 114.24, 1.6); #endif @@ -554,7 +554,7 @@ void test_all() test_one("ticket_10412", ticket_10412, join_miter, end_flat, 3109.6616, 1.5, settings); test_one("ticket_11580_100", ticket_11580, join_miter, end_flat, 52.0221000, 1.00, settings); - #if defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) + #if defined(BOOST_GEOMETRY_TEST_FAILURES) // Larger distance, resulting in only one circle test_one("ticket_11580_237", ticket_11580, join_miter, end_flat, 999.999, 2.37, settings); #endif diff --git a/test/algorithms/buffer/test_buffer.hpp b/test/algorithms/buffer/test_buffer.hpp index 6a92540b9..3b745996e 100644 --- a/test/algorithms/buffer/test_buffer.hpp +++ b/test/algorithms/buffer/test_buffer.hpp @@ -349,7 +349,7 @@ void test_buffer(std::string const& caseid, // } } -#if ! defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if ! defined(BOOST_GEOMETRY_TEST_ALWAYS_CHECK_VALIDITY) if (settings.test_validity) #endif { diff --git a/test/algorithms/envelope_expand/envelope_on_spheroid.cpp b/test/algorithms/envelope_expand/envelope_on_spheroid.cpp index be7802276..cbc5e536e 100644 --- a/test/algorithms/envelope_expand/envelope_on_spheroid.cpp +++ b/test/algorithms/envelope_expand/envelope_on_spheroid.cpp @@ -2308,11 +2308,11 @@ BOOST_AUTO_TEST_CASE( envelope_sphere_multilinestring ) from_wkt("MULTILINESTRING((10 15))"), 10, 15, 10, 15); -#ifdef BOOST_GEOMETRY_INCLUDE_FAILING_TESTS +#ifdef BOOST_GEOMETRY_TEST_FAILURES tester::apply("ml01a", from_wkt("MULTILINESTRING((),(),(10 15),())"), 10, 15, 10, 15); -#endif // BOOST_GEOMETRY_INCLUDE_FAILING_TESTS +#endif tester::apply("ml02", from_wkt("MULTILINESTRING((-170 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"), @@ -2372,11 +2372,11 @@ BOOST_AUTO_TEST_CASE( envelope_spheroid_multilinestring ) from_wkt("MULTILINESTRING((10 15))"), 10, 15, 10, 15); -#ifdef BOOST_GEOMETRY_INCLUDE_FAILING_TESTS +#ifdef BOOST_GEOMETRY_TEST_FAILURES tester::apply("ml01a", from_wkt("MULTILINESTRING((),(),(10 15),())"), 10, 15, 10, 15); -#endif // BOOST_GEOMETRY_INCLUDE_FAILING_TESTS +#endif tester::apply("ml02", from_wkt("MULTILINESTRING((-170 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"), @@ -2416,11 +2416,11 @@ BOOST_AUTO_TEST_CASE( envelope_multilinestring_sphere_with_height ) from_wkt("MULTILINESTRING((10 15 1000))"), 10, 15, 1000, 10, 15, 1000); -#ifdef BOOST_GEOMETRY_INCLUDE_FAILING_TESTS +#ifdef BOOST_GEOMETRY_TEST_FAILURES tester::apply("mlh01a", from_wkt("MULTILINESTRING((),(),(10 15 1000),())"), 10, 15, 1000, 10, 15, 1000); -#endif // BOOST_GEOMETRY_INCLUDE_FAILING_TESTS +#endif tester::apply("mlh02", from_wkt("MULTILINESTRING((-170 40 400,-100 80 300),(-10 25 600,10 35 700,120 45 450))"), @@ -2439,11 +2439,11 @@ BOOST_AUTO_TEST_CASE( envelope_multilinestring_spheroid_with_height ) from_wkt("MULTILINESTRING((10 15 1000))"), 10, 15, 1000, 10, 15, 1000); -#ifdef BOOST_GEOMETRY_INCLUDE_FAILING_TESTS +#ifdef BOOST_GEOMETRY_TEST_FAILURES tester::apply("mlh01a", from_wkt("MULTILINESTRING((),(),(10 15 1000),())"), 10, 15, 1000, 10, 15, 1000); -#endif // BOOST_GEOMETRY_INCLUDE_FAILING_TESTS +#endif tester::apply("mlh02", from_wkt("MULTILINESTRING((-170 40 400,-100 80 300),(-10 25 600,10 35 700,120 45 450))"), diff --git a/test/algorithms/envelope_expand/test_envelope_expand_on_spheroid.hpp b/test/algorithms/envelope_expand/test_envelope_expand_on_spheroid.hpp index e604552e5..cd6c0e2a8 100644 --- a/test/algorithms/envelope_expand/test_envelope_expand_on_spheroid.hpp +++ b/test/algorithms/envelope_expand/test_envelope_expand_on_spheroid.hpp @@ -243,7 +243,7 @@ struct box_check_equals { equals_with_tolerance equals(tol); -#ifndef BOOST_GEOMETRY_TEST_ENABLE_FAILING +#ifndef BOOST_GEOMETRY_TEST_FAILURES // check latitude with tolerance when necessary return equals_with_eps(bg::get<0, 0>(box), lon_min) && (bg::get<0, 1>(box) < 0 @@ -276,7 +276,7 @@ struct box_check_equals T3 const& lon_max, T4 const& lat_max, double height_max, double tol) { -#ifndef BOOST_GEOMETRY_TEST_ENABLE_FAILING +#ifndef BOOST_GEOMETRY_TEST_FAILURES equals_with_tolerance equals(tol); return box_check_equals::apply(box, diff --git a/test/algorithms/is_valid.cpp b/test/algorithms/is_valid.cpp index cc06a0164..6b4b164a4 100644 --- a/test/algorithms/is_valid.cpp +++ b/test/algorithms/is_valid.cpp @@ -1009,7 +1009,7 @@ inline void test_open_multipolygons() } // MySQL report 30.06.2015 -#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING +#ifdef BOOST_GEOMETRY_TEST_FAILURES { std::string wkt = "MULTIPOLYGON(((153.60036248974487 -86.4072234353084,134.8924761503673 -92.0821987136617,151.87887755950274 -92.0821987136617,153.60036248974487 -86.4072234353084)),((-162.3619975827558 -20.37135271519032,-170.42498886764488 -34.35970444494861,-168.21072335866987 -37.67358696575207,-162.3619975827558 -20.37135271519032)),((25.982352329146433 -1.793573272167862,25.81900562736861 -2.0992322130216032,24.216310496207715 -2.737558757030656,25.9822948153016 -1.7936204725604972,25.982352329146433 -1.793573272167862)))"; @@ -1200,7 +1200,7 @@ inline void test_open_multipolygons() BOOST_CHECK_MESSAGE(bg::is_valid(mpoly, msg), msg); } -#endif // BOOST_GEOMETRY_TEST_ENABLE_FAILING +#endif // BOOST_GEOMETRY_TEST_FAILURES } BOOST_AUTO_TEST_CASE( test_is_valid_multipolygon ) diff --git a/test/algorithms/overlay/get_turns_linear_linear.cpp b/test/algorithms/overlay/get_turns_linear_linear.cpp index 1db5ade85..df543bf2d 100644 --- a/test/algorithms/overlay/get_turns_linear_linear.cpp +++ b/test/algorithms/overlay/get_turns_linear_linear.cpp @@ -268,7 +268,7 @@ void test_all() { // BUG - the operations are correct but IP coordinates are wrong // ok now also the 3rd turn is wrong -#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING +#ifdef BOOST_GEOMETRY_TEST_FAILURES test_geometry("LINESTRING(8 5,5 1,-2 3,1 10)", "LINESTRING(1.9375 1.875, 1.7441860465116283 1.9302325581395348, -0.7692307692307692 2.6483516483516487, -2 3, -1.0071942446043165 5.316546762589928)", expected("mii++")("ccc==")("ccc==")("mux==")); diff --git a/test/algorithms/overlay/traverse.cpp b/test/algorithms/overlay/traverse.cpp index cd432d0c5..256d905f9 100644 --- a/test/algorithms/overlay/traverse.cpp +++ b/test/algorithms/overlay/traverse.cpp @@ -580,7 +580,7 @@ void test_all(bool test_self_tangencies = true, bool test_mixed = false) 2, 2.0, case_82[0], case_82[2]); // other -#ifdef BOOST_GEOMETRY_ENABLE_FAILING_TESTS +#ifdef BOOST_GEOMETRY_TEST_FAILURES // simplified version of 82, area should be different // missing IP at (1.5 3.5) from (1 4,1.5 3.5,2 4)x(2 4,1 3) test_traverse_intersection::apply("83", diff --git a/test/algorithms/overlay/traverse_multi.cpp b/test/algorithms/overlay/traverse_multi.cpp index ef424763a..dd20f9567 100644 --- a/test/algorithms/overlay/traverse_multi.cpp +++ b/test/algorithms/overlay/traverse_multi.cpp @@ -61,7 +61,7 @@ void test_geometries() case_58_multi[4], case_58_multi[2] ); -#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS +#ifdef BOOST_GEOMETRY_TEST_FAILURES test_traverse_intersection::apply ( "case_58_multi_b5", 1, 1, diff --git a/test/algorithms/set_operations/difference/difference.cpp b/test/algorithms/set_operations/difference/difference.cpp index 43b071eeb..88fb141b4 100644 --- a/test/algorithms/set_operations/difference/difference.cpp +++ b/test/algorithms/set_operations/difference/difference.cpp @@ -308,7 +308,7 @@ void test_all() settings); } -#if defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("geos_1", geos_1[0], geos_1[1], 21, -1, 0.31640625, @@ -374,7 +374,7 @@ void test_all() 1, -1, 35723.8506317139 + 58456.4964294434); } -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) { // symmetric difference is not valid due to robustness issue, it has // two turns (touch_only) and a midpoint is located in other polygon @@ -443,7 +443,7 @@ void test_all() 2, 12, 0.0451236449624935, 0, 0, 0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("ticket_9563", ticket_9563[0], ticket_9563[1], 0, -1, 0, @@ -559,7 +559,7 @@ void test_all() TEST_DIFFERENCE(mysql_23023665_2, 1, 96.0, 1, 16.0, 2); TEST_DIFFERENCE(mysql_23023665_3, 1, 225.0, 1, 66.0, 2); TEST_DIFFERENCE(mysql_23023665_5, 2, 165.23735, 2, 105.73735, 4); -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) TEST_DIFFERENCE(mysql_23023665_6, 2, 105.68756, 3, 10.18756, 5); TEST_DIFFERENCE(mysql_23023665_13, 3, 99.74526, 3, 37.74526, 6); #endif diff --git a/test/algorithms/set_operations/difference/difference_linear_linear.cpp b/test/algorithms/set_operations/difference/difference_linear_linear.cpp index 485a3418b..df8227d93 100644 --- a/test/algorithms/set_operations/difference/difference_linear_linear.cpp +++ b/test/algorithms/set_operations/difference/difference_linear_linear.cpp @@ -503,7 +503,7 @@ BOOST_AUTO_TEST_CASE( test_difference_linestring_linestring ) "lldf29d" ); -#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS +#ifdef BOOST_GEOMETRY_TEST_FAILURES tester::apply (from_wkt("LINESTRING(8 5,5 1,-2 3,1 10)"), from_wkt("LINESTRING(1.9375 1.875,\ diff --git a/test/algorithms/set_operations/difference/difference_multi.cpp b/test/algorithms/set_operations/difference/difference_multi.cpp index eedadd3ee..4a25ac433 100644 --- a/test/algorithms/set_operations/difference/difference_multi.cpp +++ b/test/algorithms/set_operations/difference/difference_multi.cpp @@ -166,7 +166,7 @@ void test_areal() #endif } -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) { // Without rescaling, this one misses one of the output polygons // With rescaling, it is complete but invalid @@ -316,7 +316,7 @@ void test_areal() TEST_DIFFERENCE(case_recursive_boxes_59, 8, 6.5, 7, 7.0, 12); TEST_DIFFERENCE(case_recursive_boxes_60, 6, 5.25, 7, 5.25, 11); TEST_DIFFERENCE(case_recursive_boxes_61, 2, 1.5, 6, 2.0, 7); -#if defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if defined(BOOST_GEOMETRY_TEST_FAILURES) // Misses one triangle TEST_DIFFERENCE(case_recursive_boxes_62, 5, 5.0, 11, 5.75, 12); #endif diff --git a/test/algorithms/set_operations/difference/difference_multi_spike.cpp b/test/algorithms/set_operations/difference/difference_multi_spike.cpp index 05a1737d1..8e173b74a 100644 --- a/test/algorithms/set_operations/difference/difference_multi_spike.cpp +++ b/test/algorithms/set_operations/difference/difference_multi_spike.cpp @@ -37,7 +37,7 @@ void test_spikes_in_ticket_8364() // The difference of polygons below result in a spike. The spike should be there, it is also generated in ttmath, // and (e.g.) in SQL Server. However, using int-coordinates, the spike makes the polygon invalid. Therefore it is now (since August 2013) checked and removed. -#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS +#ifdef BOOST_GEOMETRY_TEST_FAILURES // TODO: commented working at ii/validity, this changes the area slightly, to be checked // So using int's, the spike is removed automatically. Therefore there is one polygon less, and less points. Also area differs test_one("ticket_8364_step3", diff --git a/test/algorithms/set_operations/difference/test_difference.hpp b/test/algorithms/set_operations/difference/test_difference.hpp index 4230413bc..f1b6c02cc 100644 --- a/test/algorithms/set_operations/difference/test_difference.hpp +++ b/test/algorithms/set_operations/difference/test_difference.hpp @@ -189,7 +189,7 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g typename bg::default_area_result::type const area = bg::area(result); #if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST) -#if ! defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if ! defined(BOOST_GEOMETRY_TEST_ALWAYS_CHECK_VALIDITY) if (settings.test_validity) #endif { @@ -342,7 +342,7 @@ std::string test_one(std::string const& caseid, expected_count2, expected_rings_count2, expected_point_count2, expected_area2, false, settings); -#if ! defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if ! defined(BOOST_GEOMETRY_TEST_ALWAYS_CHECK_SYMDIFFERENCE) if (settings.sym_difference) #endif { diff --git a/test/algorithms/set_operations/intersection/intersection.cpp b/test/algorithms/set_operations/intersection/intersection.cpp index a8703b51f..b2f4cd8fd 100644 --- a/test/algorithms/set_operations/intersection/intersection.cpp +++ b/test/algorithms/set_operations/intersection/intersection.cpp @@ -316,7 +316,7 @@ void test_areal() 1, 8, 129.90381, settings); } -#if ! defined(BOOST_GEOMETRY_USE_RESCALING) +#if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) // With rescaling the output is empty TEST_INTERSECTION(issue_548, 1, -1, 1958824415.2151); #endif @@ -939,7 +939,7 @@ int test_main(int, char* []) test_boxes_nd(); -#if defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if defined(BOOST_GEOMETRY_TEST_FAILURES) // ticket #10868 still fails for 32-bit integers test_ticket_10868("MULTIPOLYGON(((33520458 6878575,33480192 14931538,31446819 18947953,30772384 19615678,30101303 19612322,30114725 16928001,33520458 6878575)))"); diff --git a/test/algorithms/set_operations/intersection/intersection_multi.cpp b/test/algorithms/set_operations/intersection/intersection_multi.cpp index f3e14fbed..e29dd612e 100644 --- a/test/algorithms/set_operations/intersection/intersection_multi.cpp +++ b/test/algorithms/set_operations/intersection/intersection_multi.cpp @@ -135,7 +135,7 @@ void test_areal() case_107_multi[1], case_107_multi[2], 3, 13, 3.0); -#if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) { ut_settings ignore_validity; diff --git a/test/algorithms/set_operations/intersection/test_intersection.hpp b/test/algorithms/set_operations/intersection/test_intersection.hpp index ed53d68fe..099b1c047 100644 --- a/test/algorithms/set_operations/intersection/test_intersection.hpp +++ b/test/algorithms/set_operations/intersection/test_intersection.hpp @@ -105,7 +105,7 @@ check_result( } } -#if ! defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if ! defined(BOOST_GEOMETRY_TEST_ALWAYS_CHECK_VALIDITY) if (settings.test_validity) #endif { diff --git a/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp b/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp index 3ae7f840f..93ff46e1a 100644 --- a/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp +++ b/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp @@ -629,7 +629,7 @@ BOOST_AUTO_TEST_CASE( test_sym_difference_linestring_multilinestring ) "lmlsdf18d" ); -#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS +#ifdef BOOST_GEOMETRY_TEST_FAILURES tester::apply (from_wkt("LINESTRING(1 5,4 2,1 -1.1,1 6,1 189.7654,2 5,-0.7654 3)"), from_wkt("MULTILINESTRING((2 5,-0.7654 2),\ diff --git a/test/algorithms/set_operations/union/test_union.hpp b/test/algorithms/set_operations/union/test_union.hpp index bc263b156..2ea8f00d4 100644 --- a/test/algorithms/set_operations/union/test_union.hpp +++ b/test/algorithms/set_operations/union/test_union.hpp @@ -125,7 +125,7 @@ void test_union(std::string const& caseid, G1 const& g1, G2 const& g2, } #endif -#if ! defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if ! defined(BOOST_GEOMETRY_TEST_ALWAYS_CHECK_VALIDITY) if (settings.test_validity) #endif { @@ -136,7 +136,6 @@ void test_union(std::string const& caseid, G1 const& g1, G2 const& g2, << " type: " << (type_for_assert_message())); } - typename bg::default_area_result::type area = 0; std::size_t n = 0; std::size_t holes = 0; diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index add1e4552..cc1281a09 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -274,7 +274,7 @@ void test_areal() TEST_UNION(case_precision_17, 1, 1, -1, 73.0); TEST_UNION(case_precision_18, 1, 1, -1, 73.0); TEST_UNION(case_precision_19, 1, 1, -1, 73.0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) TEST_UNION(case_precision_20, 1, 0, -1, 22.0); #endif @@ -297,7 +297,7 @@ void test_areal() TEST_UNION_REV(case_precision_17, 1, 1, -1, 73.0); TEST_UNION_REV(case_precision_18, 1, 1, -1, 73.0); TEST_UNION_REV(case_precision_19, 1, 1, -1, 73.0); -#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) TEST_UNION_REV(case_precision_20, 1, 0, -1, 22.0); #endif @@ -350,7 +350,7 @@ void test_areal() ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1], 1, 1, 15, 129904.197692871); -#if defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("ggl_list_20110820_christophe", ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1], -1, // Either 1 or 2, depending if the intersection/turn point (eps.region) is missed @@ -466,7 +466,7 @@ void test_areal() test_one("buffer_rt_a_rev", buffer_rt_a[1], buffer_rt_a[0], 1, 0, -1, 19.28, settings); } -#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1], 1, 0, -1, 4.60853); test_one("buffer_rt_f_rev", buffer_rt_f[1], buffer_rt_f[0], @@ -476,7 +476,7 @@ void test_areal() 1, 0, -1, 16.571); test_one("buffer_rt_g_rev", buffer_rt_g[1], buffer_rt_g[0], 1, 0, -1, 16.571); -#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("buffer_rt_i", buffer_rt_i[0], buffer_rt_i[1], 1, 0, -1, 13.6569); #endif @@ -507,7 +507,7 @@ void test_areal() 1, 0, -1, 18.5710); test_one("buffer_rt_q_rev", buffer_rt_q[1], buffer_rt_q[0], 1, 0, -1, 18.5710); -#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) +#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) test_one("buffer_rt_r", buffer_rt_r[0], buffer_rt_r[1], 1, 0, -1, 21.07612); test_one("buffer_rt_r_rev", buffer_rt_r[1], buffer_rt_r[0], diff --git a/test/algorithms/set_operations/union/union_multi.cpp b/test/algorithms/set_operations/union/union_multi.cpp index 4ff8fb1a5..1a2d274d4 100644 --- a/test/algorithms/set_operations/union/union_multi.cpp +++ b/test/algorithms/set_operations/union/union_multi.cpp @@ -407,7 +407,7 @@ void test_areal() ticket_12118[0], ticket_12118[1], 1, -1, 27, 2221.38713); -#if defined(BOOST_GEOMETRY_TEST_ENABLE_FAILING) || ! defined(BOOST_GEOMETRY_USE_RESCALING) +#if defined(BOOST_GEOMETRY_TEST_FAILURES) || ! defined(BOOST_GEOMETRY_USE_RESCALING) // No output if rescaling is done test_one("ticket_12125", ticket_12125[0], ticket_12125[1], From 5eed0d779db4adb8d635326bdfa880212759df3e Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 29 May 2019 15:53:29 +0200 Subject: [PATCH 26/68] [TEST] Add extra define BOOST_GEOMETRY_USE_KRAMER_RULE to indicate using the Kramer-rule intersection strategy. This can change some test behaviour --- include/boost/geometry/core/config.hpp | 3 +++ test/algorithms/set_operations/union/union.cpp | 13 +++++++------ .../algorithms/set_operations/union/union_multi.cpp | 7 ++++++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/include/boost/geometry/core/config.hpp b/include/boost/geometry/core/config.hpp index c068e98cc..d510d1322 100644 --- a/include/boost/geometry/core/config.hpp +++ b/include/boost/geometry/core/config.hpp @@ -1,5 +1,6 @@ // Boost.Geometry +// Copyright (c) 2019 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -17,6 +18,8 @@ #define BOOST_GEOMETRY_CXX11_ARRAY_UNIFIED_INITIALIZATION #endif +#define BOOST_GEOMETRY_USE_KRAMER_RULE + // Rescaling is turned on, unless NO_ROBUSTNESS is defined // In future versions of Boost.Geometry, it will be turned off by default #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index cc1281a09..9073e783f 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -418,12 +418,13 @@ void test_areal() 1, 0, 10, if_typed(1291.5469, 1289.08374)); // Can generate one polygon, or two splitted, both is OK - test_one("ticket_10108_a", ticket_10108_a[0], ticket_10108_a[1], - BG_IF_RESCALED(2, 1), 0, 8, 0.0435229); - - // Can generate one combined polygon, or two splitted, both is acceptable - test_one("ticket_10108_b", ticket_10108_b[0], ticket_10108_b[1], - BG_IF_RESCALED(1, 2), 0, 10, 2424.3449); +#if ! defined(BOOST_GEOMETRY_USE_KRAMER_RULE) + TEST_UNION(ticket_10108_a, 2, 0, 8, 0.0435229); + TEST_UNION(ticket_10108_b, 1, 0, 10, 2424.3449); +#else + TEST_UNION(ticket_10108_a, BG_IF_RESCALED(2, 1), 0, 8, 0.0435229); + TEST_UNION(ticket_10108_b, BG_IF_RESCALED(1, 2), 0, 10, 2424.3449); +#endif test_one("ticket_10866", ticket_10866[0], ticket_10866[1], 1, 0, 14, if_typed(332752493.0, 332760303.5)); diff --git a/test/algorithms/set_operations/union/union_multi.cpp b/test/algorithms/set_operations/union/union_multi.cpp index 1a2d274d4..7263f95b0 100644 --- a/test/algorithms/set_operations/union/union_multi.cpp +++ b/test/algorithms/set_operations/union/union_multi.cpp @@ -416,8 +416,13 @@ void test_areal() TEST_UNION(ticket_12503, 42, 1, -1, 945.625); - // Generates two polygons, which should (without rescaling) be merged into one +#if defined(BOOST_GEOMETRY_USE_KRAMER_RULE) + // Two polygons, should ideally be merged TEST_UNION(mail_2019_01_21_johan, 2, 0, -1, 0.00058896); +#else + // Correct: one polygon + TEST_UNION(mail_2019_01_21_johan, 1, 0, -1, 0.00058896); +#endif TEST_UNION(mysql_23023665_7, 1, 1, -1, 99.19494); TEST_UNION(mysql_23023665_8, 1, 2, -1, 1400.0); From 1465e26502e093e325ab75b1ac4b4b09ca1da67a Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 29 May 2019 16:42:57 +0200 Subject: [PATCH 27/68] [TEST] Add two testcases --- test/algorithms/overlay/overlay_cases.hpp | 12 ++++++++++++ .../set_operations/intersection/intersection.cpp | 4 ++++ test/algorithms/set_operations/union/union.cpp | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/test/algorithms/overlay/overlay_cases.hpp b/test/algorithms/overlay/overlay_cases.hpp index 6e6e55959..d5373f065 100644 --- a/test/algorithms/overlay/overlay_cases.hpp +++ b/test/algorithms/overlay/overlay_cases.hpp @@ -826,6 +826,18 @@ static std::string case_precision_20[2] = "POLYGON((2 7,4 7,4 3,2.00000000000000044 3,2 7))" }; +static std::string case_precision_21[2] = +{ + "POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))", + "POLYGON((2 7,4 7,4 3.00001000000000007,2 3,2 7))" +}; + +static std::string case_precision_22[2] = +{ + "POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))", + "POLYGON((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,2 3,4.00000000200000017 2.99999999000000006,4 7,2 7))" +}; + // ticket_17 is keyholed, so has a hole formed by an deliberate intersection // This will fail the intersection/traversal process diff --git a/test/algorithms/set_operations/intersection/intersection.cpp b/test/algorithms/set_operations/intersection/intersection.cpp index b2f4cd8fd..e92575880 100644 --- a/test/algorithms/set_operations/intersection/intersection.cpp +++ b/test/algorithms/set_operations/intersection/intersection.cpp @@ -386,6 +386,8 @@ void test_areal() TEST_INTERSECTION(case_precision_18, 1, -1, 14.0); TEST_INTERSECTION(case_precision_19, 1, -1, 14.0); TEST_INTERSECTION(case_precision_20, 0, 0, 0.0); + TEST_INTERSECTION(case_precision_21, 0, 0, 0.0); + TEST_INTERSECTION(case_precision_22, 1, -1, 14.0); TEST_INTERSECTION_REV(case_precision_1, 0, 0, 0.0); TEST_INTERSECTION_REV(case_precision_2, 0, 0, 0.0); @@ -406,6 +408,8 @@ void test_areal() TEST_INTERSECTION_REV(case_precision_18, 1, -1, 14.0); TEST_INTERSECTION_REV(case_precision_19, 1, -1, 14.0); TEST_INTERSECTION_REV(case_precision_20, 0, 0, 0.0); + TEST_INTERSECTION_REV(case_precision_21, 0, 0, 0.0); + TEST_INTERSECTION_REV(case_precision_22, 1, -1, 14.0); test_one("mysql_21964049", mysql_21964049[0], mysql_21964049[1], diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index 9073e783f..7ebdc3241 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -277,6 +277,8 @@ void test_areal() #if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) TEST_UNION(case_precision_20, 1, 0, -1, 22.0); #endif + TEST_UNION(case_precision_21, 1, 0, -1, 22.0); + TEST_UNION(case_precision_22, 1, 1, -1, 73.0); TEST_UNION_REV(case_precision_1, 1, 0, -1, 22.0); TEST_UNION_REV(case_precision_2, 1, 0, -1, 22.0); @@ -300,6 +302,8 @@ void test_areal() #if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) TEST_UNION_REV(case_precision_20, 1, 0, -1, 22.0); #endif + TEST_UNION_REV(case_precision_21, 1, 0, -1, 22.0); + TEST_UNION_REV(case_precision_22, 1, 1, -1, 73.0); /* test_one(102, From c59ad6a07b1aa42f1f9c86fe0ae4593a0490239d Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 29 May 2019 16:47:46 +0200 Subject: [PATCH 28/68] [TEST] Add robustness test to find corner cases in floating point precision --- .../general_intersection_precision.cpp | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100755 test/robustness/overlay/areal_areal/general_intersection_precision.cpp diff --git a/test/robustness/overlay/areal_areal/general_intersection_precision.cpp b/test/robustness/overlay/areal_areal/general_intersection_precision.cpp new file mode 100755 index 000000000..6413f2d18 --- /dev/null +++ b/test/robustness/overlay/areal_areal/general_intersection_precision.cpp @@ -0,0 +1,224 @@ +// Boost.Geometry +// Robustness Test + +// Copyright (c) 2019 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 + +#include + +#include +#include + +// Basic case. Union should deliver 22.0 +static std::string case_a[2] = + { + "MULTIPOLYGON(((0 0,0 4,2 4,2 3,4 3,4 0,0 0)))", + "MULTIPOLYGON(((2 7,4 7,4 3,2 3,2 7)))" + }; + +// Case with an interior ring. Union should deliver 73.0 +static std::string case_b[2] = + { + "MULTIPOLYGON(((0 0,0 4,2 4,2 3,4 3,4 0,0 0)))", + "MULTIPOLYGON(((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,2 3,4 3,4 7,2 7)))" + }; + +static std::string case_c[2] = + { + "MULTIPOLYGON(((0 0,0 4,2 4,2 3,4 3,4 0,0 0)))", + "MULTIPOLYGON(((1 1,0 1,0 3,1 3,1 1)))" + }; + +template +bool test_overlay(std::string const& caseid, + Geometry const& g1, Geometry const& g2, + double expected_area, + bool do_output) +{ + + typedef typename boost::range_value::type geometry_out; + typedef bg::detail::overlay::overlay + < + Geometry, Geometry, + bg::detail::overlay::do_reverse::value>::value, + OverlayType == bg::overlay_difference + ? ! bg::detail::overlay::do_reverse::value>::value + : bg::detail::overlay::do_reverse::value>::value, + bg::detail::overlay::do_reverse::value>::value, + geometry_out, + OverlayType + > overlay; + + typedef typename bg::strategy::intersection::services::default_strategy + < + typename bg::cs_tag::type + >::type strategy_type; + + strategy_type strategy; + + typedef typename bg::rescale_overlay_policy_type + < + Geometry, + Geometry + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = bg::get_rescale_policy(g1, g2); + + Geometry result; + bg::detail::overlay::overlay_null_visitor visitor; + overlay::apply(g1, g2, robust_policy, std::back_inserter(result), + strategy, visitor); + + const double detected_area = bg::area(result); + if (std::fabs(detected_area - expected_area) > 0.01) + { + if (do_output) + { + std::cout << "ERROR: " << caseid << std::setprecision(18) + << " detected=" << detected_area + << " expected=" << expected_area << std::endl + << " " << bg::wkt(g1) << std::endl + << " " << bg::wkt(g2) << std::endl; + } + return false; + } + return true; +} + +template +void update(Ring& ring, double x, double y, std::size_t index) +{ + if (index >= ring.size()) + { + return; + } + bg::set<0>(ring[index], bg::get<0>(ring[index]) + x); + bg::set<1>(ring[index], bg::get<1>(ring[index]) + y); + if (index == 0) + { + ring.back() = ring.front(); + } +} + +template +std::size_t test_case(std::size_t& error_count, + std::size_t case_index, std::size_t i, std::size_t j, + std::size_t min_vertex_index, std::size_t max_vertex_index, + double x, double y, double expectation, + MultiPolygon const& poly1, MultiPolygon const& poly2, + bool do_output) +{ + std::size_t n = 0; + for (std::size_t k = min_vertex_index; k <= max_vertex_index; k++, ++n) + { + MultiPolygon poly2_adapted = poly2; + + switch (case_index) + { + case 2 : + update(bg::interior_rings(poly2_adapted.front()).front(), x, y, k); + break; + default : + update(bg::exterior_ring(poly2_adapted.front()), x, y, k); + break; + } + + std::ostringstream out; + out << "case_" << i << "_" << j << "_" << k; + if (! test_overlay(out.str(), poly1, poly2_adapted, expectation, do_output)) + { + if (error_count == 0) + { + // First failure is always reported + test_overlay(out.str(), poly1, poly2_adapted, expectation, true); + } + error_count++; + } + } + return n; +} + +template +std::size_t test_all(std::size_t case_index, std::size_t min_vertex_index, + std::size_t max_vertex_index, + double expectation, bool do_output) +{ + typedef bg::model::point point_type; + typedef bg::model::polygon polygon; + typedef bg::model::multi_polygon multi_polygon; + + const std::string& first = case_a[0]; + + const std::string& second + = case_index == 1 ? case_a[1] + : case_index == 2 ? case_b[1] + : case_index == 3 ? case_c[1] + : ""; + + multi_polygon poly1; + bg::read_wkt(first, poly1); + + multi_polygon poly2; + bg::read_wkt(second, poly2); + + std::size_t error_count = 0; + std::size_t n = 0; + for (double factor = 1.0; factor > 1.0e-10; factor /= 10.0) + { + std::size_t i = 0; + double const bound = 1.0e-5 * factor; + double const step = 1.0e-6 * factor; + for (double x = -bound; x <= bound; x += step, ++i) + { + std::size_t j = 0; + for (double y = -bound; y <= bound; y += step, ++j, ++n) + { + n += test_case(error_count, + case_index, i, j, + min_vertex_index, max_vertex_index, + x, y, expectation, + poly1, poly2, do_output); + } + } + } + + std::cout << case_index + << " #cases: " << n << " #errors: " << error_count << std::endl; + BOOST_CHECK_EQUAL(error_count, 0u); + + return error_count; +} + +int test_main(int argc, char** argv) +{ + typedef double coordinate_type; + + const double factor = argc > 1 ? atof(argv[1]) : 2.0; + const bool do_output = argc > 2 && atol(argv[2]) == 1; + + std::cout << std::endl << " -> TESTING " + << string_from_type::name() + << " " << factor + << std::endl; + + test_all(1, 0, 3, 22.0, do_output); + test_all(2, 0, 3, 73.0, do_output); + test_all(3, 1, 2, 2.0, do_output); + test_all(3, 1, 2, 14.0, do_output); + + return 0; + } + + From fb0c9d3b8e0558005ad9c7048f0e5603b502419e Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 29 May 2019 16:54:52 +0200 Subject: [PATCH 29/68] [TEST] Minor fixes in buffer tests --- test/algorithms/buffer/buffer_linestring.cpp | 4 ++-- test/algorithms/buffer/buffer_polygon.cpp | 2 +- test/algorithms/buffer/test_buffer_svg.hpp | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/test/algorithms/buffer/buffer_linestring.cpp b/test/algorithms/buffer/buffer_linestring.cpp index 2d9869588..b4e17fabe 100644 --- a/test/algorithms/buffer/buffer_linestring.cpp +++ b/test/algorithms/buffer/buffer_linestring.cpp @@ -188,8 +188,8 @@ void test_all() test_one("for_collinear", for_collinear, join_round, end_flat, 68.561, 2.0); test_one("for_collinear", for_collinear, join_miter, end_flat, 72, 2.0); #if defined(BOOST_GEOMETRY_TEST_FAILURES) - test_one("for_collinear2", for_collinear2, join_round, end_flat, 74.387, 2.0, 2.0); - test_one("for_collinear2", for_collinear2, join_miter, end_flat, 78.0, 2.0, 2.0); + test_one("for_collinear2", for_collinear2, join_round, end_flat, 74.387, 2.0); + test_one("for_collinear2", for_collinear2, join_miter, end_flat, 78.0, 2.0); #endif test_one("curve", curve, join_round, end_flat, 58.1944, 5.0, ut_settings(), 3.0); diff --git a/test/algorithms/buffer/buffer_polygon.cpp b/test/algorithms/buffer/buffer_polygon.cpp index b0cf23733..6e1801eeb 100644 --- a/test/algorithms/buffer/buffer_polygon.cpp +++ b/test/algorithms/buffer/buffer_polygon.cpp @@ -555,7 +555,7 @@ void test_all() test_one("ticket_10412", ticket_10412, join_miter, end_flat, 3109.6616, 1.5, settings); test_one("ticket_11580_100", ticket_11580, join_miter, end_flat, 52.0221000, 1.00, settings); #if defined(BOOST_GEOMETRY_TEST_FAILURES) - // Larger distance, resulting in only one circle + // Larger distance, resulting in only one circle. Not solved yet in non-rescaled mode. test_one("ticket_11580_237", ticket_11580, join_miter, end_flat, 999.999, 2.37, settings); #endif } diff --git a/test/algorithms/buffer/test_buffer_svg.hpp b/test/algorithms/buffer/test_buffer_svg.hpp index 8a52b9ecd..9642d6233 100644 --- a/test/algorithms/buffer/test_buffer_svg.hpp +++ b/test/algorithms/buffer/test_buffer_svg.hpp @@ -228,10 +228,12 @@ private : { continue; } +#if 0 // Does not compile (SVG is not enabled by default) if (m_zoom && bg::disjoint(corner, m_alternate_box)) { continue; } +#endif if (m_zoom && do_pieces) { From d0981b0a98104f1011b652428af6ac1a8ebd12a8 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 29 May 2019 16:56:25 +0200 Subject: [PATCH 30/68] [TEST] Remove define for union --- test/algorithms/set_operations/union/union.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index 7ebdc3241..c2799eabe 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -614,10 +614,8 @@ int test_main(int, char* []) #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) -#if defined(BOOST_GEOMETRY_USE_RESCALING) test_all >(); test_all >(); -#endif #if defined(HAVE_TTMATH) std::cout << "Testing TTMATH" << std::endl; From ffdf6f8dd257dd2f5d99710825b2bfbe56afe8dd Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Fri, 31 May 2019 16:05:07 +0300 Subject: [PATCH 31/68] [stategies] Remove unused calls to formulas for azimuth and distance computation --- .../geographic/distance_cross_track.hpp | 121 ++++++++---------- 1 file changed, 54 insertions(+), 67 deletions(-) diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 454080359..161044ac3 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2016-2018, Oracle and/or its affiliates. +// Copyright (c) 2016-2019, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -212,7 +212,7 @@ private : CT const& lon2, CT const& lat2, //p2 CT const& lon3, CT const& lat3, //query point p3 Spheroid const& spheroid, - CT& s14, CT const& a12, + CT const& s14_start, CT const& a12, result_distance_point_segment& result) { typedef typename FormulaPolicy::template direct @@ -230,8 +230,7 @@ private : CT pr_lon = lon2; CT pr_lat = lat2; - s14 = geometry::strategy::distance::geographic - ::apply(lon1, lat1, lon2, lat2, spheroid) / 2; + CT s14 = s14_start; do{ // Solve the direct problem to find p4 (GEO) @@ -301,13 +300,13 @@ private : CT const& lon2, CT const& lat2, //p2 CT const& lon3, CT const& lat3, //query point p3 Spheroid const& spheroid, - CT& s14, CT const& a12, + CT const& s14_start, CT const& a12, result_distance_point_segment& result) { typedef typename FormulaPolicy::template inverse inverse_distance_azimuth_quantities_type; typedef typename FormulaPolicy::template inverse - inverse_azimuth_type; + inverse_dist_azimuth_type; typedef typename FormulaPolicy::template direct direct_distance_type; @@ -321,6 +320,7 @@ private : CT g4; CT delta_g4; bool dist_improve = true; + CT s14 = s14_start; do{ prev_distance = res34.distance; @@ -331,7 +331,7 @@ private : // Solve an inverse problem to find g4 // g4 is the angle between segment (p1,p2) and segment (p3,p4) that meet on p4 (GEO) - CT a4 = inverse_azimuth_type::apply(res14.lon2, res14.lat2, + CT a4 = inverse_dist_azimuth_type::apply(res14.lon2, res14.lat2, lon2, lat2, spheroid).azimuth; res34 = inverse_distance_azimuth_quantities_type::apply(res14.lon2, res14.lat2, lon3, lat3, spheroid); @@ -352,7 +352,7 @@ private : result.distance = prev_distance; } - #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK +#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "p4=" << res14.lon2 * math::r2d() << "," << res14.lat2 * math::r2d() << std::endl; std::cout << "a34=" << res34.azimuth * math::r2d() << std::endl; @@ -361,7 +361,6 @@ private : std::cout << "delta_g4=" << delta_g4 * math::r2d() << std::endl; std::cout << "der=" << der << std::endl; std::cout << "M43=" << M43 << std::endl; - //std::cout << "spherical limit=" << cos(s14/earth_radius) << std::endl; std::cout << "m34=" << m34 << std::endl; std::cout << "new_s14=" << s14 << std::endl; std::cout << std::setprecision(16) << "dist =" << res34.distance << std::endl; @@ -382,7 +381,7 @@ private : { std::cout << "Stop msg: counter" << std::endl; } - #endif +#endif } while (g4 != half_pi && dist_improve @@ -400,7 +399,7 @@ private : CT s31 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon1, lat1, spheroid).distance; CT s32 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon2, lat2, spheroid).distance; - CT a4 = inverse_azimuth_type::apply(res14.lon2, res14.lat2, lon2, lat2, spheroid).azimuth; + CT a4 = inverse_dist_azimuth_type::apply(res14.lon2, res14.lat2, lon2, lat2, spheroid).azimuth; geometry::formula::result_direct res4 = direct_distance_type::apply(res14.lon2, res14.lat2, .04, a4, spheroid); CT p4_plus = inverse_distance_azimuth_quantities_type::apply(res4.lon2, res4.lat2, lon3, lat3, spheroid).distance; @@ -430,10 +429,10 @@ private : CT const& lo3, CT const& la3, //query point p3 Spheroid const& spheroid) { - typedef typename FormulaPolicy::template inverse - inverse_azimuth_type; - typedef typename FormulaPolicy::template inverse - inverse_azimuth_reverse_type; + typedef typename FormulaPolicy::template inverse + inverse_dist_azimuth_type; + typedef typename FormulaPolicy::template inverse + inverse_dist_azimuth_reverse_type; CT const earth_radius = geometry::formula::mean_radius(spheroid); @@ -519,49 +518,43 @@ private : std::cout << "Meridian segment crossing pole" << std::endl; #endif CT sign_non_zero = lat3 >= c0 ? 1 : -1; - result_distance_point_segment d1 = + result_distance_point_segment res13 = apply(lon1, lat1, lon1, half_pi * sign_non_zero, lon3, lat3, spheroid); - result_distance_point_segment d2 = + result_distance_point_segment res23 = apply(lon2, lat2, lon2, half_pi * sign_non_zero, lon3, lat3, spheroid); - if (d1.distance < d2.distance) + if (res13.distance < res23.distance) { - return d1; + return res13; } else { - return d2; + return res23; } } - CT d1 = geometry::strategy::distance::geographic - ::apply(lon1, lat1, lon3, lat3, spheroid); + geometry::formula::result_inverse res13 = + inverse_dist_azimuth_type::apply(lon1, lat1, lon3, lat3, spheroid); + geometry::formula::result_inverse res12 = + inverse_dist_azimuth_reverse_type::apply(lon1, lat1, lon2, lat2, spheroid); - CT d3 = geometry::strategy::distance::geographic - ::apply(lon1, lat1, lon2, lat2, spheroid); - - if (geometry::math::equals(d3, c0)) + if (geometry::math::equals(res12.distance, c0)) { #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "Degenerate segment" << std::endl; - std::cout << "distance between points=" << d1 << std::endl; + std::cout << "distance between points=" << res13.distance << std::endl; #endif - return non_iterative_case(lon1, lat2, d1); + return non_iterative_case(lon1, lat2, res13.distance); } - CT d2 = geometry::strategy::distance::geographic - ::apply(lon2, lat2, lon3, lat3, spheroid); + geometry::formula::result_inverse res23 = + inverse_dist_azimuth_type::apply(lon2, lat2, lon3, lat3, spheroid); // Compute a12 (GEO) - geometry::formula::result_inverse res12 = - inverse_azimuth_reverse_type::apply(lon1, lat1, lon2, lat2, spheroid); - CT a12 = res12.azimuth; - CT a13 = inverse_azimuth_type::apply(lon1, lat1, lon3, lat3, spheroid).azimuth; - - CT a312 = a13 - a12; + CT a312 = res13.azimuth - res12.azimuth; // TODO: meridian case optimization if (geometry::math::equals(a312, c0) && meridian_not_crossing_pole) @@ -577,11 +570,11 @@ private : } } - CT projection1 = cos( a312 ) * d1 / d3; + CT projection1 = cos( a312 ) * res13.distance / res12.distance; #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "a1=" << a12 * math::r2d() << std::endl; - std::cout << "a13=" << a13 * math::r2d() << std::endl; + std::cout << "a1=" << res12.azimuth * math::r2d() << std::endl; + std::cout << "a13=" << res13.azimuth * math::r2d() << std::endl; std::cout << "a312=" << a312 * math::r2d() << std::endl; std::cout << "cos(a312)=" << cos(a312) << std::endl; std::cout << "projection 1=" << projection1 << std::endl; @@ -597,16 +590,12 @@ private : return non_iterative_case(lon1, lat1, lon3, lat3, spheroid); } - CT a21 = res12.reverse_azimuth - pi; - CT a23 = inverse_azimuth_type::apply(lon2, lat2, lon3, lat3, spheroid).azimuth; - - CT a321 = a23 - a21; - - CT projection2 = cos( a321 ) * d2 / d3; + CT a321 = res23.azimuth - res12.reverse_azimuth + pi; + CT projection2 = cos( a321 ) * res23.distance / res12.distance; #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "a21=" << a21 * math::r2d() << std::endl; - std::cout << "a23=" << a23 * math::r2d() << std::endl; + std::cout << "a21=" << res12.reverse_azimuth * math::r2d() << std::endl; + std::cout << "a23=" << res23.azimuth * math::r2d() << std::endl; std::cout << "a321=" << a321 * math::r2d() << std::endl; std::cout << "cos(a321)=" << cos(a321) << std::endl; std::cout << "projection 2=" << projection2 << std::endl; @@ -634,36 +623,31 @@ private : point p3 = point(lon3, lat3); geometry::strategy::distance::cross_track cross_track(earth_radius); - CT s34 = cross_track.apply(p3, p1, p2); + CT s34_sph = cross_track.apply(p3, p1, p2); geometry::strategy::distance::haversine str(earth_radius); - CT s13 = str.apply(p1, p3); + CT s13_sph = str.apply(p1, p3); //CT s14 = acos( cos(s13/earth_radius) / cos(s34/earth_radius) ) * earth_radius; - CT cos_frac = cos(s13/earth_radius) / cos(s34/earth_radius); - CT s14 = cos_frac >= 1 ? CT(0) - : cos_frac <= -1 ? pi * earth_radius - : acos(cos_frac) * earth_radius; + CT cos_frac = cos(s13_sph / earth_radius) / cos(s34_sph / earth_radius); + CT s14_sph = cos_frac >= 1 ? CT(0) + : cos_frac <= -1 ? pi * earth_radius + : acos(cos_frac) * earth_radius; CT a12_sph = geometry::formula::spherical_azimuth<>(lon1, lat1, lon2, lat2); geometry::formula::result_direct res = geometry::formula::spherical_direct - (lon1, lat1, s14, a12_sph, srs::sphere(earth_radius)); + (lon1, lat1, s14_sph, a12_sph, srs::sphere(earth_radius)); - s14 = geometry::strategy::distance::geographic - ::apply(lon1, lat1, res.lon2, res.lat2, spheroid); - - // this is used in postgis, at least in 2.5 - //std::cout << "spherical + geo= " - // << geometry::strategy::distance::geographic - // ::apply(lon3, lat3, res.lon2, res.lat2, spheroid) - // << std::endl; + // this is what postgis (version 2.5) returns + // geometry::strategy::distance::geographic + // ::apply(lon3, lat3, res.lon2, res.lat2, spheroid); #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK - std::cout << "s34=" << s34 << std::endl; - std::cout << "s13=" << s13 << std::endl; - std::cout << "s14=" << s14 << std::endl; + std::cout << "s34=" << s34_sph << std::endl; + std::cout << "s13=" << res13.distance << std::endl; + std::cout << "s14=" << s14_sph << std::endl; std::cout << "===============" << std::endl; #endif @@ -672,12 +656,15 @@ private : if (Bisection) { bisection(lon1, lat1, lon2, lat2, lon3, lat3, - spheroid, s14, a12, result); + spheroid, res12.distance/2, res12.azimuth, result); } else { + CT s14_start = geometry::strategy::distance::geographic + ::apply(lon1, lat1, res.lon2, res.lat2, spheroid); + newton(lon1, lat1, lon2, lat2, lon3, lat3, - spheroid, s14, a12, result); + spheroid, s14_start, res12.azimuth, result); } return result; From cc15b8cbd05cb6feffdb3fe0d2d1574ca151a9e8 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Mon, 3 Jun 2019 11:54:15 +0300 Subject: [PATCH 32/68] [tests] Remove output strings from cross_track geo distance --- test/strategies/distance_cross_track.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/strategies/distance_cross_track.cpp b/test/strategies/distance_cross_track.cpp index c8f2b6839..cd54a1b93 100644 --- a/test/strategies/distance_cross_track.cpp +++ b/test/strategies/distance_cross_track.cpp @@ -57,8 +57,6 @@ void test_all(expected_results const& results) // WGS84 Spheroid spheroid(6378137.0, 6356752.3142451793); - std::string output; - error errors [] { {0.00000001, 0.00000001, 0.00000001, 0.000001}, //vincenty @@ -71,41 +69,33 @@ void test_all(expected_results const& results) double distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); check_result(distance, results.vincenty_bisection, results.reference, errors[0]); - output += boost::lexical_cast(distance) + ",\n"; distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); check_result(distance, results.vincenty, results.reference, errors[0]); - output += boost::lexical_cast(distance) + ",\n"; //thomas distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); check_result(distance, results.thomas_bisection, results.reference, errors[1]); - output += boost::lexical_cast(distance) + ",\n";; distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); check_result(distance, results.thomas, results.reference, errors[1]); - output += boost::lexical_cast(distance) + ",\n"; //andoyer distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); check_result(distance, results.andoyer_bisection, results.reference, errors[2]); - output += boost::lexical_cast(distance) + ",\n"; distance = bg::strategy::distance::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); check_result(distance, results.andoyer, results.reference, errors[2]); - output += boost::lexical_cast(distance) + ",\n"; //spherical distance = bg::strategy::distance::cross_track<>(bg::formula::mean_radius(spheroid)) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); check_result(distance, results.spherical, results.reference, errors[3]); - output += boost::lexical_cast(distance) + ",\n"; - std::cout << std::setprecision(20) << output << "\n"; } From 2832223ba6f4ac8ae520f497227d46990c547249 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 4 Jun 2019 20:04:38 +0200 Subject: [PATCH 33/68] [algorithms][strategies] Propagate CS-specific strategies in algorithms. --- .../buffer/buffered_piece_collection.hpp | 13 +- .../algorithms/detail/direction_code.hpp | 61 +++++--- .../detail/disjoint/multipoint_geometry.hpp | 40 ++--- .../detail/equals/collect_vectors.hpp | 23 +-- .../algorithms/detail/is_simple/areal.hpp | 55 ++++--- .../algorithms/detail/is_simple/linear.hpp | 63 +++++--- .../detail/is_simple/multipoint.hpp | 15 +- .../detail/is_valid/complement_graph.hpp | 10 +- .../is_valid/debug_complement_graph.hpp | 10 +- .../detail/is_valid/has_duplicates.hpp | 11 +- .../algorithms/detail/is_valid/has_spikes.hpp | 39 +++-- .../algorithms/detail/is_valid/linear.hpp | 8 +- .../detail/is_valid/multipolygon.hpp | 16 +- .../algorithms/detail/is_valid/polygon.hpp | 43 +++-- .../algorithms/detail/is_valid/ring.hpp | 29 ++-- .../algorithms/detail/is_valid/segment.hpp | 9 +- .../detail/overlay/assign_parents.hpp | 18 ++- .../overlay/enrich_intersection_points.hpp | 26 +-- .../detail/overlay/get_turn_info_helpers.hpp | 9 +- .../detail/overlay/handle_self_turns.hpp | 124 ++++++++++++--- .../algorithms/detail/overlay/overlay.hpp | 12 +- .../detail/overlay/pointlike_linear.hpp | 17 +- .../detail/overlay/pointlike_pointlike.hpp | 6 +- .../detail/overlay/sort_by_side.hpp | 14 +- .../detail/point_is_spike_or_equal.hpp | 4 +- .../detail/relate/boundary_checker.hpp | 8 +- .../algorithms/detail/relate/point_point.hpp | 17 +- .../detail/relate/topology_check.hpp | 3 +- .../algorithms/detail/within/multi_point.hpp | 9 +- include/boost/geometry/policies/compare.hpp | 148 +++++++++++++++++- .../strategies/cartesian/intersection.hpp | 2 + .../strategies/cartesian/point_in_point.hpp | 6 +- .../cartesian/point_in_poly_winding.hpp | 17 +- .../strategies/cartesian/side_by_triangle.hpp | 6 +- .../strategies/geographic/intersection.hpp | 2 + .../geometry/strategies/geographic/side.hpp | 6 +- .../geometry/strategies/spherical/compare.hpp | 22 ++- .../strategies/spherical/intersection.hpp | 2 + .../strategies/spherical/point_in_point.hpp | 7 +- .../spherical/point_in_poly_winding.hpp | 15 +- .../geometry/strategies/spherical/ssf.hpp | 6 +- 41 files changed, 683 insertions(+), 268 deletions(-) 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 128f2beef..00b6a5178 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-2018. -// Modifications copyright (c) 2016-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2019. +// Modifications copyright (c) 2016-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, @@ -1419,8 +1419,13 @@ struct buffered_piece_collection inline void enrich() { enrich_intersection_points(m_turns, - m_clusters, offsetted_rings, offsetted_rings, - m_robust_policy, m_side_strategy); + m_clusters, offsetted_rings, offsetted_rings, + m_robust_policy, + m_intersection_strategy.template get_point_in_geometry_strategy + < + buffered_ring, + buffered_ring + >()); } // Discards all rings which do have not-OK intersection points only. diff --git a/include/boost/geometry/algorithms/detail/direction_code.hpp b/include/boost/geometry/algorithms/detail/direction_code.hpp index 3a7d3d878..9acd2c301 100644 --- a/include/boost/geometry/algorithms/detail/direction_code.hpp +++ b/include/boost/geometry/algorithms/detail/direction_code.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2015, 2017. -// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017, 2019. +// Modifications copyright (c) 2015-2019 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 @@ -46,14 +46,14 @@ inline int sign_of_difference(Point1 const& point1, Point2 const& point2) } -template ::type> +template struct direction_code_impl { BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_CS, (CSTag)); }; -template -struct direction_code_impl +template <> +struct direction_code_impl { template static inline int apply(Point1 const& segment_a, Point1 const& segment_b, @@ -96,8 +96,8 @@ struct direction_code_impl } }; -template -struct direction_code_impl +template <> +struct direction_code_impl { template static inline int apply(Point1 const& segment_a, Point1 const& segment_b, @@ -105,8 +105,8 @@ struct direction_code_impl { typedef typename coordinate_type::type coord1_t; typedef typename coordinate_type::type coord2_t; - typedef typename coordinate_system::type::units units_t; - typedef typename coordinate_system::type::units units2_t; + typedef typename cs_angular_units::type units_t; + typedef typename cs_angular_units::type units2_t; BOOST_MPL_ASSERT_MSG((boost::is_same::value), NOT_IMPLEMENTED_FOR_DIFFERENT_UNITS, (units_t, units2_t)); @@ -196,8 +196,8 @@ struct direction_code_impl } }; -template -struct direction_code_impl +template <> +struct direction_code_impl { template static inline int apply(Point1 segment_a, Point1 segment_b, @@ -206,12 +206,12 @@ struct direction_code_impl typedef math::detail::constants_on_spheroid < typename coordinate_type::type, - typename coordinate_system::type::units + typename cs_angular_units::type > constants1; typedef math::detail::constants_on_spheroid < typename coordinate_type::type, - typename coordinate_system::type::units + typename cs_angular_units::type > constants2; geometry::set<1>(segment_a, @@ -228,9 +228,34 @@ struct direction_code_impl } }; -template -struct direction_code_impl - : direction_code_impl +// if spherical_tag is passed then pick cs_tag based on Point1 type +// with spherical_equatorial_tag as the default +template <> +struct direction_code_impl +{ + template + static inline int apply(Point1 segment_a, Point1 segment_b, + Point2 p) + { + return direction_code_impl + < + typename boost::mpl::if_c + < + boost::is_same + < + typename geometry::cs_tag::type, + spherical_polar_tag + >::value, + spherical_polar_tag, + spherical_equatorial_tag + >::type + >::apply(segment_a, segment_b, p); + } +}; + +template <> +struct direction_code_impl + : direction_code_impl {}; // Gives sense of direction for point p, collinear w.r.t. segment (a,b) @@ -238,11 +263,11 @@ struct direction_code_impl // Returns 1 if p goes forward, so extends (a,b) // Returns 0 if p is equal with b, or if (a,b) is degenerate // Note that it does not do any collinearity test, that should be done before -template +template inline int direction_code(Point1 const& segment_a, Point1 const& segment_b, Point2 const& p) { - return direction_code_impl::apply(segment_a, segment_b, p); + return direction_code_impl::apply(segment_a, segment_b, p); } diff --git a/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp index 029d68be5..5bc8af77d 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp @@ -2,7 +2,7 @@ // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// Copyright (c) 2014-2018, Oracle and/or its affiliates. +// Copyright (c) 2014-2019, 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 @@ -51,16 +51,15 @@ namespace detail { namespace disjoint { -template class multipoint_multipoint { private: - template + template class unary_disjoint_predicate - : geometry::less<> + : geometry::less { private: - typedef geometry::less<> base_type; + typedef geometry::less base_type; public: unary_disjoint_predicate(Iterator first, Iterator last) @@ -81,9 +80,14 @@ private: }; public: + template static inline bool apply(MultiPoint1 const& multipoint1, - MultiPoint2 const& multipoint2) + MultiPoint2 const& multipoint2, + Strategy const&) { + typedef typename Strategy::cs_tag cs_tag; + typedef geometry::less less_type; + BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) ); typedef typename boost::range_value::type point1_type; @@ -91,11 +95,12 @@ public: std::vector points1(boost::begin(multipoint1), boost::end(multipoint1)); - std::sort(points1.begin(), points1.end(), geometry::less<>()); + std::sort(points1.begin(), points1.end(), less_type()); typedef unary_disjoint_predicate < - typename std::vector::const_iterator + typename std::vector::const_iterator, + cs_tag > predicate_type; return check_iterator_range @@ -112,12 +117,13 @@ template class multipoint_linear { private: + template struct expand_box_point { template static inline void apply(Box& total, Point const& point) { - geometry::expand(total, point); + geometry::expand(total, point, ExpandPointBoxStrategy()); } }; @@ -132,7 +138,8 @@ private: inline void apply(Box& total, Segment const& segment) const { geometry::expand(total, - geometry::return_envelope(segment, m_strategy)); + geometry::return_envelope(segment, m_strategy), + typename EnvelopeStrategy::box_expand_strategy_type()); } EnvelopeStrategy const& m_strategy; @@ -225,6 +232,7 @@ 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; @@ -238,7 +246,7 @@ public: < geometry::model::box::type> >::apply(multipoint, segment_range(linear), visitor, - expand_box_point(), + expand_box_point(), overlaps_box_point(), expand_box_segment(strategy.get_envelope_strategy()), overlaps_box_segment(strategy.get_disjoint_strategy())); @@ -493,20 +501,16 @@ struct disjoint template static inline bool apply(MultiPoint1 const& multipoint1, MultiPoint2 const& multipoint2, - Strategy const& ) + Strategy const& strategy) { if ( boost::size(multipoint2) < boost::size(multipoint1) ) { return detail::disjoint::multipoint_multipoint - < - MultiPoint2, MultiPoint1 - >::apply(multipoint2, multipoint1); + ::apply(multipoint2, multipoint1, strategy); } return detail::disjoint::multipoint_multipoint - < - MultiPoint1, MultiPoint2 - >::apply(multipoint1, multipoint2); + ::apply(multipoint1, multipoint2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp index 9625f1842..fd5c3caa4 100644 --- a/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp +++ b/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2014-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, 2019. +// Modifications copyright (c) 2017, 2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -42,13 +42,12 @@ #include #include +#include namespace boost { namespace geometry { -// TODO: dispatch only by SideStrategy instead of Geometry/CSTag? - // Since these vectors (though ray would be a better name) are used in the // implementation of equals() for Areal geometries the internal representation // should be consistent with the side strategy. @@ -159,7 +158,8 @@ private: }; // Compatible with spherical_side_formula which currently -// is the default spherical and geographical strategy +// is the default spherical_equatorial and geographic strategy +// so CSTag is spherical_equatorial_tag or geographic_tag template struct collected_vector < @@ -168,8 +168,8 @@ struct collected_vector { typedef T type; - typedef typename coordinate_system::type cs_type; - typedef model::point point_type; + typedef typename geometry::detail::cs_angular_units::type units_type; + typedef model::point > point_type; typedef model::point vector_type; collected_vector() @@ -179,7 +179,9 @@ struct collected_vector collected_vector(Point const& p1, Point const& p2) : origin(get<0>(p1), get<1>(p1)) { - origin = detail::return_normalized(origin); + origin = detail::return_normalized( + origin, + strategy::normalize::spherical_point()); using namespace geometry::formula; prev = sph_to_cart3d(p1); @@ -290,7 +292,7 @@ struct collected_vector private: template - Point polar_to_equatorial(Point const& p) + Point to_equatorial(Point const& p) { typedef typename coordinate_type::type coord_type; @@ -309,6 +311,9 @@ private: }; +// TODO: specialize collected_vector for geographic_tag + + #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace collect_vectors { diff --git a/include/boost/geometry/algorithms/detail/is_simple/areal.hpp b/include/boost/geometry/algorithms/detail/is_simple/areal.hpp index d4d6db9bc..b4eb9fb99 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-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2019, 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 @@ -35,28 +35,22 @@ namespace detail { namespace is_simple { -template +template struct is_simple_ring { - template - static inline bool apply(Ring const& ring, Strategy const&) - { - return apply(ring); - } - static inline bool apply(Ring const& ring) { simplicity_failure_policy policy; return ! boost::empty(ring) && ! detail::is_valid::has_duplicates < - Ring, geometry::closure::value + Ring, geometry::closure::value, CSTag >::apply(ring, policy); } }; -template +template class is_simple_polygon { private: @@ -69,25 +63,21 @@ private: < is_simple_ring < - typename boost::range_value::type + typename boost::range_value::type, + CSTag > >::apply(boost::begin(interior_rings), boost::end(interior_rings)); } public: - template - static inline bool apply(Polygon const& polygon, Strategy const&) - { - return apply(polygon); - } - static inline bool apply(Polygon const& polygon) { return is_simple_ring < - typename ring_type::type + typename ring_type::type, + CSTag >::apply(exterior_ring(polygon)) && are_simple_interior_rings(geometry::interior_rings(polygon)); @@ -112,8 +102,17 @@ namespace dispatch // Reference (for polygon validity): OGC 06-103r4 (6.1.11.1) template struct is_simple - : detail::is_simple::is_simple_ring -{}; +{ + template + static inline bool apply(Ring const& ring, Strategy const&) + { + return detail::is_simple::is_simple_ring + < + Ring, + typename Strategy::cs_tag + >::apply(ring); + } +}; // A Polygon is always a simple geometric object provided that it is valid. @@ -121,8 +120,17 @@ struct is_simple // Reference (for validity of Polygons): OGC 06-103r4 (6.1.11.1) template struct is_simple - : detail::is_simple::is_simple_polygon -{}; +{ + template + static inline bool apply(Polygon const& polygon, Strategy const&) + { + return detail::is_simple::is_simple_polygon + < + Polygon, + typename Strategy::cs_tag + >::apply(polygon); + } +}; // Not clear what the definition is. @@ -140,7 +148,8 @@ struct is_simple < detail::is_simple::is_simple_polygon < - typename boost::range_value::type + typename boost::range_value::type, + typename Strategy::cs_tag >, true // allow empty multi-polygon >::apply(boost::begin(multipolygon), boost::end(multipolygon)); diff --git a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp index e36049a96..57bc295e5 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/linear.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/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-2019, 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 @@ -29,7 +29,6 @@ #include #include -#include #include #include @@ -37,6 +36,7 @@ #include #include +#include #include #include #include @@ -74,19 +74,25 @@ inline bool check_segment_indices(Turn const& turn, } -template ::type> +template +< + typename Geometry, + typename EqPPStrategy, + typename Tag = typename tag::type +> class is_acceptable_turn : not_implemented {}; -template -class is_acceptable_turn +template +class is_acceptable_turn { public: is_acceptable_turn(Linestring const& linestring) : m_linestring(linestring) - , m_is_closed(geometry::equals(range::front(linestring), - range::back(linestring))) + , m_is_closed(geometry::detail::equals::equals_point_point(range::front(linestring), + range::back(linestring), + EqPPStrategy())) {} template @@ -104,12 +110,16 @@ private: bool const m_is_closed; }; -template -class is_acceptable_turn +template +class is_acceptable_turn { private: - typedef typename boost::range_value::type linestring_type; - typedef is_acceptable_turn base_type; + template + static inline bool equals_point_point(Point1 const& point1, Point2 const& point2) + { + return geometry::detail::equals::equals_point_point(point1, point2, + EqPPStrategy()); + } template static inline bool is_boundary_point_of(Point const& point, @@ -117,11 +127,10 @@ private: { BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1); return - ! geometry::equals(range::front(linestring), - range::back(linestring)) + !equals_point_point(range::front(linestring), range::back(linestring)) && - (geometry::equals(point, range::front(linestring)) - || geometry::equals(point, range::back(linestring))); + (equals_point_point(point, range::front(linestring)) + || equals_point_point(point, range::back(linestring))); } template @@ -134,7 +143,7 @@ private: && check_segment_indices(turn, boost::size(linestring) - 2) && - geometry::equals(range::front(linestring), range::back(linestring)) + equals_point_point(range::front(linestring), range::back(linestring)) && turn.operations[0].fraction.is_zero(); ; @@ -145,13 +154,13 @@ private: Linestring2 const& ls2) { return - geometry::equals(range::front(ls1), range::front(ls2)) + equals_point_point(range::front(ls1), range::front(ls2)) ? - geometry::equals(range::back(ls1), range::back(ls2)) + equals_point_point(range::back(ls1), range::back(ls2)) : - (geometry::equals(range::front(ls1), range::back(ls2)) + (equals_point_point(range::front(ls1), range::back(ls2)) && - geometry::equals(range::back(ls1), range::front(ls2))) + equals_point_point(range::back(ls1), range::front(ls2))) ; } @@ -163,6 +172,8 @@ public: template inline bool apply(Turn const& turn) const { + typedef typename boost::range_value::type linestring_type; + linestring_type const& ls1 = range::at(m_multilinestring, turn.operations[0].seg_id.multi_index); @@ -211,10 +222,16 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg detail::disjoint::assign_disjoint_policy > turn_policy; - is_acceptable_turn predicate(linear); + typedef is_acceptable_turn + < + Linear, + typename Strategy::equals_point_point_strategy_type + > is_acceptable_turn_type; + + is_acceptable_turn_type predicate(linear); detail::overlay::predicate_based_interrupt_policy < - is_acceptable_turn + is_acceptable_turn_type > interrupt_policy(predicate); // TODO: skip_adjacent should be set to false @@ -245,7 +262,7 @@ struct is_simple_linestring return ! boost::empty(linestring) && ! detail::is_valid::has_duplicates < - Linestring, closed + Linestring, closed, typename Strategy::cs_tag >::apply(linestring, policy) && ! detail::is_valid::has_spikes < diff --git a/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp b/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp index 61f0bc913..dfc98041b 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2019, 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 @@ -42,19 +42,26 @@ struct is_simple_multipoint template static inline bool apply(MultiPoint const& multipoint, Strategy const&) { + typedef typename Strategy::cs_tag cs_tag; + typedef geometry::less + < + typename point_type::type, + -1, + cs_tag + > less_type; + if (boost::empty(multipoint)) { return true; } MultiPoint mp(multipoint); - std::sort(boost::begin(mp), boost::end(mp), - geometry::less::type>()); + std::sort(boost::begin(mp), boost::end(mp), less_type()); simplicity_failure_policy policy; return !detail::is_valid::has_duplicates < - MultiPoint, closed + MultiPoint, closed, cs_tag >::apply(mp, policy); } }; diff --git a/include/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp b/include/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp index 1d3bda191..67a94f101 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, 2018, Oracle and/or its affiliates. +// Copyright (c) 2014, 2018, 2019, 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 @@ -32,7 +32,7 @@ namespace detail { namespace is_valid { -template +template class complement_graph_vertex { public: @@ -55,7 +55,7 @@ public: { return geometry::less < - TurnPoint + TurnPoint, -1, CSTag >()(*m_turn_point, *other.m_turn_point); } if ( m_turn_point == NULL && other.m_turn_point == NULL ) @@ -77,11 +77,11 @@ private: -template +template class complement_graph { private: - typedef complement_graph_vertex vertex; + typedef complement_graph_vertex vertex; typedef std::set vertex_container; public: diff --git a/include/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp b/include/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp index 749dd3fc2..5d16e2ea3 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, 2018, Oracle and/or its affiliates. +// Copyright (c) 2014, 2018, 2019, 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,10 +25,10 @@ namespace detail { namespace is_valid #ifdef BOOST_GEOMETRY_TEST_DEBUG -template +template inline void debug_print_complement_graph(OutputStream& os, - complement_graph const& graph) + complement_graph const& graph) { typedef typename complement_graph::vertex_handle vertex_handle; @@ -58,9 +58,9 @@ debug_print_complement_graph(OutputStream& os, } } #else -template +template inline void debug_print_complement_graph(OutputStream&, - complement_graph const&) + complement_graph const&) { } #endif 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 685a4aac3..76dd119f1 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2019, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -30,7 +30,7 @@ namespace boost { namespace geometry namespace detail { namespace is_valid { -template +template struct has_duplicates { template @@ -51,7 +51,12 @@ struct has_duplicates return ! visitor.template apply(); } - geometry::equal_to::type> equal; + geometry::equal_to + < + typename boost::range_value::type, + -1, + CSTag + > equal; const_iterator it = boost::const_begin(view); const_iterator next = it; 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 8bb6e3bce..c1e1804fa 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2019, 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 @@ -28,7 +28,7 @@ #include -#include +#include #include #include #include @@ -42,7 +42,7 @@ namespace boost { namespace geometry namespace detail { namespace is_valid { -template +template struct equal_to { Point const& m_point; @@ -54,11 +54,11 @@ struct equal_to template inline bool operator()(OtherPoint const& other) const { - return geometry::equals(m_point, other); + return geometry::detail::equals::equals_point_point(m_point, other, Strategy()); } }; -template +template struct not_equal_to { Point const& m_point; @@ -70,7 +70,7 @@ struct not_equal_to template inline bool operator()(OtherPoint const& other) const { - return ! geometry::equals(other, m_point); + return ! geometry::detail::equals::equals_point_point(other, m_point, Strategy()); } }; @@ -79,11 +79,16 @@ struct not_equal_to template struct has_spikes { - template + template static inline Iterator find_different_from_first(Iterator first, - Iterator last) + Iterator last, + SideStrategy const& ) { - typedef not_equal_to::type> not_equal; + typedef not_equal_to + < + typename point_type::type, + typename SideStrategy::equals_point_point_strategy_type + > not_equal; BOOST_GEOMETRY_ASSERT(first != last); @@ -108,7 +113,7 @@ struct has_spikes iterator prev = boost::begin(view); - iterator cur = find_different_from_first(prev, boost::end(view)); + iterator cur = find_different_from_first(prev, boost::end(view), strategy); if (cur == boost::end(view)) { // the range has only one distinct point, so it @@ -116,7 +121,7 @@ struct has_spikes return ! visitor.template apply(); } - iterator next = find_different_from_first(cur, boost::end(view)); + iterator next = find_different_from_first(cur, boost::end(view), strategy); if (next == boost::end(view)) { // the range has only two distinct points, so it @@ -137,19 +142,23 @@ struct has_spikes } prev = cur; cur = next; - next = find_different_from_first(cur, boost::end(view)); + next = find_different_from_first(cur, boost::end(view), strategy); } - if (geometry::equals(range::front(view), range::back(view))) + if (geometry::detail::equals:: + equals_point_point(range::front(view), range::back(view), + strategy.get_equals_point_point_strategy())) { iterator cur = boost::begin(view); typename boost::range_reverse_iterator < view_type const >::type prev = find_different_from_first(boost::rbegin(view), - boost::rend(view)); + boost::rend(view), + strategy); - iterator next = find_different_from_first(cur, boost::end(view)); + iterator next = find_different_from_first(cur, boost::end(view), + strategy); if (detail::is_spike_or_equal(*next, *cur, *prev, strategy)) { return diff --git a/include/boost/geometry/algorithms/detail/is_valid/linear.hpp b/include/boost/geometry/algorithms/detail/is_valid/linear.hpp index 39cb36ef5..edec3ae54 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/linear.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/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-2019, 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 @@ -63,7 +63,11 @@ struct is_valid_linestring Linestring, 3u, true, - not_equal_to::type> + not_equal_to + < + typename point_type::type, + typename Strategy::equals_point_point_strategy_type + > >::apply(linestring); if (num_distinct < 2u) diff --git a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp index 8fe580332..25aa579f5 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2019, 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 @@ -119,6 +119,9 @@ private: 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); @@ -127,8 +130,15 @@ private: < geometry::model::box::type> >::apply(polygon_iterators, item_visitor, - typename base::template expand_box(envelope_strategy), - typename base::template overlaps_box(envelope_strategy)); + 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)); 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 834ce5af2..b799b383f 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -2,7 +2,7 @@ // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// Copyright (c) 2014-2018, Oracle and/or its affiliates. +// Copyright (c) 2014-2019, 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 @@ -180,29 +180,40 @@ protected: template struct expand_box { - explicit expand_box(EnvelopeStrategy const& strategy) : m_strategy(strategy) {} + explicit expand_box(EnvelopeStrategy const& strategy) + : m_strategy(strategy) + {} template inline void apply(Box& total, partition_item const& item) const { - geometry::expand(total, item.get_envelope(m_strategy)); + geometry::expand(total, + item.get_envelope(m_strategy), + m_strategy.get_box_expand_strategy()); } EnvelopeStrategy const& m_strategy; }; - template + template struct overlaps_box { - explicit overlaps_box(EnvelopeStrategy const& strategy) : m_strategy(strategy) {} + explicit overlaps_box(EnvelopeStrategy const& envelope_strategy, + DisjointBoxBoxStrategy const& disjoint_strategy) + : m_envelope_strategy(envelope_strategy) + , m_disjoint_strategy(disjoint_strategy) + {} template inline bool apply(Box const& box, partition_item const& item) const { - return ! geometry::disjoint(item.get_envelope(m_strategy), box); + return ! geometry::disjoint(item.get_envelope(m_envelope_strategy), + box, + m_disjoint_strategy); } - EnvelopeStrategy const& m_strategy; + EnvelopeStrategy const& m_envelope_strategy; + DisjointBoxBoxStrategy const& m_disjoint_strategy; }; @@ -322,6 +333,9 @@ protected: 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 @@ -331,8 +345,15 @@ protected: < box_type >::apply(ring_iterators, item_visitor, - expand_box(envelope_strategy), - overlaps_box(envelope_strategy)); + expand_box + < + envelope_strategy_type + >(envelope_strategy), + overlaps_box + < + envelope_strategy_type, + disjoint_box_box_strategy_type + >(envelope_strategy, disjoint_strategy)); if (item_visitor.items_overlap) { @@ -398,13 +419,15 @@ protected: VisitPolicy& visitor, Strategy const& ) { + typedef typename Strategy::cs_tag cs_tag; + boost::ignore_unused(visitor); typedef typename std::iterator_traits < TurnIterator >::value_type turn_type; - typedef complement_graph graph; + typedef complement_graph graph; graph g(geometry::num_interior_rings(polygon) + 1); for (TurnIterator tit = first; tit != beyond; ++tit) diff --git a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp index 5a55d998e..8927b2a5e 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp @@ -2,7 +2,7 @@ // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// Copyright (c) 2014-2018, Oracle and/or its affiliates. +// Copyright (c) 2014-2019, 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,13 +25,12 @@ #include #include -#include - #include #include #include #include +#include #include #include #include @@ -58,8 +57,8 @@ namespace detail { namespace is_valid template struct is_topologically_closed { - template - static inline bool apply(Ring const&, VisitPolicy& visitor) + template + static inline bool apply(Ring const&, VisitPolicy& visitor, EqPPStrategy const&) { boost::ignore_unused(visitor); @@ -70,12 +69,14 @@ struct is_topologically_closed template struct is_topologically_closed { - template - static inline bool apply(Ring const& ring, VisitPolicy& visitor) + template + static inline bool apply(Ring const& ring, VisitPolicy& visitor, EqPPStrategy const&) { boost::ignore_unused(visitor); - if (geometry::equals(range::front(ring), range::back(ring))) + if (geometry::detail::equals::equals_point_point(range::front(ring), + range::back(ring), + EqPPStrategy())) { return visitor.template apply(); } @@ -157,6 +158,8 @@ 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 @@ -189,7 +192,11 @@ struct is_valid_ring if (detail::num_distinct_consecutive_points < view_type, 4u, true, - not_equal_to::type> + not_equal_to + < + typename point_type::type, + typename Strategy::equals_point_point_strategy_type + > >::apply(view) < 4u) { @@ -198,8 +205,8 @@ struct is_valid_ring } return - is_topologically_closed::apply(ring, visitor) - && ! has_duplicates::apply(ring, visitor) + 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()) && (! CheckSelfIntersections || has_valid_self_turns::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 30cbf7afd..244a6ff3b 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/segment.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/segment.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2019, 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,8 +17,8 @@ #include #include -#include #include +#include #include #include @@ -47,6 +47,8 @@ struct is_valid template static inline bool apply(Segment const& segment, VisitPolicy& visitor, Strategy const&) { + typedef typename Strategy::equals_point_point_strategy_type eq_pp_strategy_type; + boost::ignore_unused(visitor); typename point_type::type p[2]; @@ -60,7 +62,8 @@ struct is_valid { return false; } - else if (! geometry::equals(p[0], p[1])) + else if (! geometry::detail::equals::equals_point_point( + p[0], p[1], eq_pp_strategy_type())) { return visitor.template apply(); } diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index 6d3c602ff..f3fc32d74 100644 --- a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/assign_parents.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 2017, 2018. -// Modifications copyright (c) 2017-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-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, @@ -125,12 +125,13 @@ struct ring_info_helper }; +template struct ring_info_helper_get_box { template static inline void apply(Box& total, InputItem const& item) { - geometry::expand(total, item.envelope); + geometry::expand(total, item.envelope, BoxExpandStrategy()); } }; @@ -145,6 +146,7 @@ struct ring_info_helper_ovelaps_box } }; +// Segments intersection Strategy template < typename Geometry1, @@ -190,7 +192,8 @@ struct assign_visitor { ring_info_type& inner_in_map = m_ring_map[inner.id]; - if (geometry::covered_by(inner_in_map.point, outer.envelope) + if (geometry::covered_by(inner_in_map.point, outer.envelope, + Strategy::disjoint_point_box_strategy_type()) && within_selected_input(inner_in_map, inner.id, outer.id, m_geometry1, m_geometry2, m_collection, m_strategy) @@ -329,6 +332,10 @@ 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_ovelaps_box < typename Strategy::disjoint_box_box_strategy_type @@ -337,8 +344,7 @@ inline void assign_parents(Geometry1 const& geometry1, geometry::partition < box_type - >::apply(vector, visitor, ring_info_helper_get_box(), - overlaps_box_type()); + >::apply(vector, visitor, expand_box_type(), overlaps_box_type()); } if (check_for_orientation) 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 6eb93b4b5..d82c34cc7 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.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 2017. -// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2019. +// Modifications copyright (c) 2017, 2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -381,13 +381,13 @@ inline void calculate_remaining_distance(Turns& turns) \tparam Clusters type of cluster container \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry -\tparam SideStrategy side strategy type +\tparam PointInGeometryStrategy point in geometry strategy type \param turns container containing intersection points \param clusters container containing clusters \param geometry1 \param_geometry \param geometry2 \param_geometry \param robust_policy policy to handle robustness issues -\param strategy strategy +\param strategy point in geometry strategy */ template < @@ -397,13 +397,13 @@ template typename Clusters, typename Geometry1, typename Geometry2, typename RobustPolicy, - typename SideStrategy + typename IntersectionStrategy > inline void enrich_intersection_points(Turns& turns, Clusters& clusters, Geometry1 const& geometry1, Geometry2 const& geometry2, RobustPolicy const& robust_policy, - SideStrategy const& strategy) + IntersectionStrategy const& strategy) { static const detail::overlay::operation_type target_operation = detail::overlay::operation_from_overlay::value; @@ -481,14 +481,16 @@ inline void enrich_intersection_points(Turns& turns, { detail::overlay::discard_closed_turns < - OverlayType, - target_operation - >::apply(turns, clusters, geometry1, geometry2); + OverlayType, + target_operation + >::apply(turns, clusters, geometry1, geometry2, + strategy); detail::overlay::discard_open_turns < OverlayType, target_operation - >::apply(turns, clusters, geometry1, geometry2); + >::apply(turns, clusters, geometry1, geometry2, + strategy); } // Create a map of vectors of indexed operation-types to be able @@ -511,7 +513,7 @@ inline void enrich_intersection_points(Turns& turns, detail::overlay::enrich_sort( mit->second, turns, geometry1, geometry2, - robust_policy, strategy); + robust_policy, strategy.get_side_strategy()); } for (typename mapped_vector_type::iterator mit @@ -541,7 +543,7 @@ inline void enrich_intersection_points(Turns& turns, Reverse2, OverlayType >(clusters, turns, target_operation, - geometry1, geometry2, strategy); + geometry1, geometry2, strategy.get_side_strategy()); detail::overlay::cleanup_clusters(turns, clusters); } 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 4b0aa162f..478811860 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 @@ -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, 2014, 2015, 2017, 2018, 2019. +// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -389,6 +389,7 @@ public: typedef UmbrellaStrategy intersection_strategy_type; typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type; + typedef typename UmbrellaStrategy::cs_tag cs_tag; typedef model::referring_segment segment_type1; typedef model::referring_segment segment_type2; @@ -452,7 +453,7 @@ public: { // qk is collinear with both p1 and p2, // verify if pk goes backwards w.r.t. pi/pj - return direction_code(base::rpi(), base::rpj(), base::rpk()) == -1; + return direction_code(base::rpi(), base::rpj(), base::rpk()) == -1; } // qk is at opposite side of p1/p2, therefore @@ -488,7 +489,7 @@ public: { if (pk_q1 == 0) { - return direction_code(base::rqi(), base::rqj(), base::rqk()) == -1; + return direction_code(base::rqi(), base::rqj(), base::rqk()) == -1; } return true; 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 5ec2a10cf..7124675b5 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp @@ -3,6 +3,11 @@ // Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -25,18 +30,68 @@ 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 { - template + template + < + typename Turn, typename Geometry0, typename Geometry1, + typename UmbrellaStrategy + > static inline bool apply(Turn const& turn, Geometry0 const& geometry0, - Geometry1 const& geometry1) + 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) - : geometry::within(turn.point, geometry0); + ? geometry::within(turn.point, geometry1, + check_within_strategy::within(strategy)) + : geometry::within(turn.point, geometry0, + check_within_strategy::within(strategy)); } }; @@ -44,24 +99,39 @@ struct check_within template <> struct check_within { - template + template + < + typename Turn, typename Geometry0, typename Geometry1, + typename UmbrellaStrategy + > static inline bool apply(Turn const& turn, Geometry0 const& geometry0, - Geometry1 const& geometry1) + 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) - : geometry::within(turn.point, geometry0); + ? ! geometry::covered_by(turn.point, geometry1, + check_within_strategy::covered_by(strategy)) + : geometry::within(turn.point, geometry0, + check_within_strategy::within(strategy)); } }; struct discard_turns { - template + template + < + typename Turns, typename Clusters, + typename Geometry0, typename Geometry1, + typename Strategy + > static inline - void apply(Turns& , Clusters const& , Geometry0 const& , Geometry1 const& ) + void apply(Turns& , Clusters const& , + Geometry0 const& , Geometry1 const& , + Strategy const& ) {} }; @@ -72,11 +142,17 @@ struct discard_closed_turns : discard_turns {}; template <> struct discard_closed_turns { - - template + // Point in Geometry Strategy + template + < + typename Turns, typename Clusters, + typename Geometry0, typename Geometry1, + typename Strategy + > static inline void apply(Turns& turns, Clusters const& /*clusters*/, - Geometry0 const& geometry0, Geometry1 const& geometry1) + Geometry0 const& geometry0, Geometry1 const& geometry1, + Strategy const& strategy) { typedef typename boost::range_value::type turn_type; @@ -89,8 +165,8 @@ struct discard_closed_turns if (! turn.discarded && is_self_turn(turn) - && check_within::apply(turn, - geometry0, geometry1)) + && check_within::apply(turn, geometry0, + geometry1, strategy)) { // Turn is in the interior of other geometry turn.discarded = true; @@ -130,10 +206,11 @@ private : } template + typename Geometry0, typename Geometry1, typename Strategy> static inline void discard_clusters(Turns& turns, Clusters const& clusters, - Geometry0 const& geometry0, Geometry1 const& geometry1) + Geometry0 const& geometry0, Geometry1 const& geometry1, + Strategy const& strategy) { for (typename Clusters::const_iterator cit = clusters.begin(); cit != clusters.end(); ++cit) @@ -148,7 +225,8 @@ private : cluster_info const& cinfo = cit->second; signed_size_type const index = *cinfo.turn_indices.begin(); if (! check_within::apply(turns[index], - geometry0, geometry1)) + geometry0, geometry1, + strategy)) { // Discard all turns in cluster for (std::set::const_iterator sit @@ -165,12 +243,13 @@ private : public : template + typename Geometry0, typename Geometry1, typename Strategy> static inline void apply(Turns& turns, Clusters const& clusters, - Geometry0 const& geometry0, Geometry1 const& geometry1) + Geometry0 const& geometry0, Geometry1 const& geometry1, + Strategy const& strategy) { - discard_clusters(turns, clusters, geometry0, geometry1); + discard_clusters(turns, clusters, geometry0, geometry1, strategy); typedef typename boost::range_value::type turn_type; @@ -185,7 +264,8 @@ public : // Check if it is within the other geometry if (! turn.discarded && is_self_turn(turn) - && ! check_within::apply(turn, geometry0, geometry1)) + && ! check_within::apply(turn, geometry0, + geometry1, strategy)) { // It is not within another geometry, set it as non startable. // It still might be traveled (#case_recursive_boxes_70) diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index 8a8561c13..e52d3741a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2015, 2017. -// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017, 2019. +// Modifications copyright (c) 2015-2019, 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 @@ -334,14 +334,12 @@ std::cout << "get turns" << std::endl; #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE std::cout << "enrich" << std::endl; #endif - typename Strategy::side_strategy_type side_strategy = strategy.get_side_strategy(); + cluster_type clusters; std::map turn_info_per_ring; - geometry::enrich_intersection_points(turns, - clusters, geometry1, geometry2, - robust_policy, - side_strategy); + geometry::enrich_intersection_points( + turns, clusters, geometry1, geometry2, robust_policy, strategy); visitor.visit_turns(2, turns); diff --git a/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp index 6f8fdd32b..ca1e0adf5 100644 --- a/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp @@ -2,7 +2,7 @@ // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// Copyright (c) 2015-2017, Oracle and/or its affiliates. +// Copyright (c) 2015-2019, 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 @@ -128,12 +128,13 @@ class multipoint_linear_point { private: // structs for partition -- start + template struct expand_box_point { template static inline void apply(Box& total, Point const& point) { - geometry::expand(total, point); + geometry::expand(total, point, ExpandPointStrategy()); } }; @@ -148,18 +149,20 @@ private: inline void apply(Box& total, Segment const& segment) const { geometry::expand(total, - geometry::return_envelope(segment, m_strategy)); + geometry::return_envelope(segment, m_strategy), + m_strategy.get_box_expand_strategy()); } EnvelopeStrategy const& m_strategy; }; + template struct overlaps_box_point { template static inline bool apply(Box const& box, Point const& point) { - return ! geometry::disjoint(point, box); + return ! geometry::disjoint(point, box, DisjointPointBoxStrategy()); } }; @@ -239,6 +242,8 @@ private: 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 @@ -252,8 +257,8 @@ private: typename boost::range_value::type > >::apply(multipoint, segment_range(linear), item_visitor, - expand_box_point(), - overlaps_box_point(), + expand_box_point(), + overlaps_box_point(), expand_box_segment(strategy.get_envelope_strategy()), overlaps_box_segment(strategy.get_disjoint_strategy())); diff --git a/include/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp b/include/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp index afe8f680b..22ed82bfe 100644 --- a/include/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2018, Oracle and/or its affiliates. +// Copyright (c) 2014-2019, 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 @@ -257,6 +257,8 @@ struct multipoint_multipoint_point OutputIterator oit, Strategy const& strategy) { + typedef geometry::less less_type; + if ( OverlayType != overlay_difference && boost::size(multipoint1) > boost::size(multipoint2) ) { @@ -271,7 +273,7 @@ struct multipoint_multipoint_point std::vector points2(boost::begin(multipoint2), boost::end(multipoint2)); - geometry::less<> const less = geometry::less<>(); + less_type const less = less_type(); std::sort(points2.begin(), points2.end(), less); for (typename boost::range_iterator::type 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 eae68403e..68e994094 100644 --- a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2015 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, 2019. +// Modifications copyright (c) 2017, 2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -132,6 +132,8 @@ struct less_by_side template inline bool operator()(const T& first, const T& second) const { + typedef typename SideStrategy::cs_tag cs_tag; + LessOnSame on_same; Compare compare; @@ -143,8 +145,8 @@ struct less_by_side // Both collinear. They might point into different directions: <------*------> // If so, order the one going backwards as the very first. - int const first_code = direction_code(m_p1, m_p2, first.point); - int const second_code = direction_code(m_p1, m_p2, second.point); + int const first_code = direction_code(m_p1, m_p2, first.point); + int const second_code = direction_code(m_p1, m_p2, second.point); // Order by code, backwards first, then forward. return first_code != second_code @@ -153,14 +155,14 @@ struct less_by_side ; } else if (side_first == 0 - && direction_code(m_p1, m_p2, first.point) == -1) + && direction_code(m_p1, m_p2, first.point) == -1) { // First collinear and going backwards. // Order as the very first, so return always true return true; } else if (side_second == 0 - && direction_code(m_p1, m_p2, second.point) == -1) + && direction_code(m_p1, m_p2, second.point) == -1) { // Second is collinear and going backwards // Order as very last, so return always false diff --git a/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp b/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp index 35ede0a0b..f83162966 100644 --- a/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp +++ b/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp @@ -75,6 +75,8 @@ inline bool point_is_spike_or_equal(Point1 const& last_point, // prev | back Point3 const& segment_b, // curr | back - 1 | spike's vertex SideStrategy const& strategy) { + typedef SideStrategy::cs_tag cs_tag; + int const side = strategy.apply(segment_a, segment_b, last_point); if (side == 0) { @@ -86,7 +88,7 @@ inline bool point_is_spike_or_equal(Point1 const& last_point, // prev | back std::cout << "spike detection failure with: " << r1 << " " << r2 << std::endl; return r2; #else - return direction_code(segment_a, segment_b, last_point) < 1; + return direction_code(segment_a, segment_b, last_point) < 1; #endif } return false; diff --git a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp index dc927d902..89101ff93 100644 --- a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp +++ b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp @@ -81,7 +81,7 @@ class boundary_checker public: typedef WithinStrategy equals_strategy_type; - + boundary_checker(Geometry const& g) : is_filled(false), geometry(g) {} @@ -91,6 +91,8 @@ public: template bool is_endpoint_boundary(point_type const& pt) const { + typedef geometry::less less_type; + typedef typename boost::range_size::type size_type; size_type multi_count = boost::size(geometry); @@ -142,7 +144,7 @@ public: std::sort(boundary_points.begin(), boundary_points.end(), - geometry::less()); + less_type()); is_filled = true; } @@ -152,7 +154,7 @@ public: std::equal_range(boundary_points.begin(), boundary_points.end(), pt, - geometry::less()) + less_type()) ); return equal_points_count % 2 != 0;// && equal_points_count > 0; // the number is odd and > 0 diff --git a/include/boost/geometry/algorithms/detail/relate/point_point.hpp b/include/boost/geometry/algorithms/detail/relate/point_point.hpp index d2a373f3c..7103e2dc9 100644 --- a/include/boost/geometry/algorithms/detail/relate/point_point.hpp +++ b/include/boost/geometry/algorithms/detail/relate/point_point.hpp @@ -148,6 +148,8 @@ struct multipoint_multipoint Result & result, Strategy const& /*strategy*/) { + typedef typename Strategy::cs_tag cs_tag; + { // TODO: throw on empty input? bool empty1 = boost::empty(multi_point1); @@ -171,17 +173,17 @@ struct multipoint_multipoint // The geometry containing smaller number of points will be analysed first if ( boost::size(multi_point1) < boost::size(multi_point2) ) { - search_both(multi_point1, multi_point2, result); + search_both(multi_point1, multi_point2, result); } else { - search_both(multi_point2, multi_point1, result); + search_both(multi_point2, multi_point1, result); } relate::set::value>(result); } - template + template static inline void search_both(MPt1 const& first_sorted_mpt, MPt2 const& first_iterated_mpt, Result & result) { @@ -190,7 +192,7 @@ struct multipoint_multipoint || relate::may_update(result) ) { // NlogN + MlogN - bool is_disjoint = search(first_sorted_mpt, first_iterated_mpt, result); + bool is_disjoint = search(first_sorted_mpt, first_iterated_mpt, result); if ( BOOST_GEOMETRY_CONDITION(is_disjoint || result.interrupt) ) return; @@ -201,11 +203,12 @@ struct multipoint_multipoint || relate::may_update(result) ) { // MlogM + NlogM - search(first_iterated_mpt, first_sorted_mpt, result); + search(first_iterated_mpt, first_sorted_mpt, result); } } template @@ -215,9 +218,11 @@ struct multipoint_multipoint { // sort points from the 1 MPt typedef typename geometry::point_type::type point_type; + typedef geometry::less less_type; + std::vector points(boost::begin(sorted_mpt), boost::end(sorted_mpt)); - geometry::less<> const less = geometry::less<>(); + less_type const less = less_type(); std::sort(points.begin(), points.end(), less); bool found_inside = false; diff --git a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp index a12acaf42..ab42504ec 100644 --- a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp +++ b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp @@ -163,8 +163,7 @@ struct topology_check } private: -// TODO: CS-specific less derived from EqPPStrategy - typedef geometry::less<> less_type; + typedef geometry::less less_type; void init() const { diff --git a/include/boost/geometry/algorithms/detail/within/multi_point.hpp b/include/boost/geometry/algorithms/detail/within/multi_point.hpp index 359853f6a..711c5b61c 100644 --- a/include/boost/geometry/algorithms/detail/within/multi_point.hpp +++ b/include/boost/geometry/algorithms/detail/within/multi_point.hpp @@ -73,8 +73,10 @@ struct multi_point_multi_point Strategy const& /*strategy*/) { typedef typename boost::range_value::type point2_type; + typedef typename Strategy::cs_tag cs_tag; + typedef geometry::less less_type; - geometry::less<> const less = geometry::less<>(); + less_type const less = less_type(); std::vector points2(boost::begin(multi_point2), boost::end(multi_point2)); std::sort(points2.begin(), points2.end(), less); @@ -123,10 +125,7 @@ struct multi_point_single_geometry geometry::envelope(linear_or_areal, box, strategy.get_envelope_strategy()); geometry::detail::expand_by_epsilon(box); - typedef typename strategy::covered_by::services::default_strategy - < - point1_type, box2_type - >::type point_in_box_type; + 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 diff --git a/include/boost/geometry/policies/compare.hpp b/include/boost/geometry/policies/compare.hpp index 7f32b7ab3..66f76b2b2 100644 --- a/include/boost/geometry/policies/compare.hpp +++ b/include/boost/geometry/policies/compare.hpp @@ -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, 2019. +// Modifications copyright (c) 2017, 2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -39,7 +39,8 @@ namespace boost { namespace geometry template < typename Point = void, - int Dimension = -1 + int Dimension = -1, + typename CSTag = void > struct less { @@ -47,6 +48,47 @@ struct less typedef Point second_argument_type; typedef bool result_type; + inline bool operator()(Point const& left, Point const& right) const + { + typedef typename strategy::compare::services::default_strategy + < + strategy::compare::less, + Point, Point, + Dimension, + CSTag, CSTag + >::type strategy_type; + + return strategy_type::apply(left, right); + } +}; + +template +struct less +{ + typedef bool result_type; + + template + inline bool operator()(Point1 const& left, Point2 const& right) const + { + typedef typename strategy::compare::services::default_strategy + < + strategy::compare::less, + Point1, Point2, + Dimension, + CSTag, CSTag + >::type strategy_type; + + return strategy_type::apply(left, right); + } +}; + +template +struct less +{ + typedef Point first_argument_type; + typedef Point second_argument_type; + typedef bool result_type; + inline bool operator()(Point const& left, Point const& right) const { typedef typename strategy::compare::services::default_strategy @@ -61,8 +103,10 @@ struct less }; template -struct less +struct less { + typedef bool result_type; + template inline bool operator()(Point1 const& left, Point2 const& right) const { @@ -87,7 +131,8 @@ struct less template < typename Point = void, - int Dimension = -1 + int Dimension = -1, + typename CSTag = void > struct greater { @@ -95,6 +140,47 @@ struct greater typedef Point second_argument_type; typedef bool result_type; + bool operator()(Point const& left, Point const& right) const + { + typedef typename strategy::compare::services::default_strategy + < + strategy::compare::greater, + Point, Point, + Dimension, + CSTag, CSTag + >::type strategy_type; + + return strategy_type::apply(left, right); + } +}; + +template +struct greater +{ + typedef bool result_type; + + template + bool operator()(Point1 const& left, Point2 const& right) const + { + typedef typename strategy::compare::services::default_strategy + < + strategy::compare::greater, + Point, Point, + Dimension + CSTag, CSTag + >::type strategy_type; + + return strategy_type::apply(left, right); + } +}; + +template +struct greater +{ + typedef Point first_argument_type; + typedef Point second_argument_type; + typedef bool result_type; + bool operator()(Point const& left, Point const& right) const { typedef typename strategy::compare::services::default_strategy @@ -109,8 +195,10 @@ struct greater }; template -struct greater +struct greater { + typedef bool result_type; + template bool operator()(Point1 const& left, Point2 const& right) const { @@ -137,7 +225,8 @@ struct greater template < typename Point, - int Dimension = -1 + int Dimension = -1, + typename CSTag = void > struct equal_to { @@ -145,6 +234,47 @@ struct equal_to typedef Point second_argument_type; typedef bool result_type; + bool operator()(Point const& left, Point const& right) const + { + typedef typename strategy::compare::services::default_strategy + < + strategy::compare::equal_to, + Point, Point, + Dimension, + CSTag, CSTag + >::type strategy_type; + + return strategy_type::apply(left, right); + } +}; + +template +struct equal_to +{ + typedef bool result_type; + + template + bool operator()(Point1 const& left, Point2 const& right) const + { + typedef typename strategy::compare::services::default_strategy + < + strategy::compare::equal_to, + Point1, Point2, + Dimension, + CSTag, CSTag + >::type strategy_type; + + return strategy_type::apply(left, right); + } +}; + +template +struct equal_to +{ + typedef Point first_argument_type; + typedef Point second_argument_type; + typedef bool result_type; + bool operator()(Point const& left, Point const& right) const { typedef typename strategy::compare::services::default_strategy @@ -159,8 +289,10 @@ struct equal_to }; template -struct equal_to +struct equal_to { + typedef bool result_type; + template bool operator()(Point1 const& left, Point2 const& right) const { diff --git a/include/boost/geometry/strategies/cartesian/intersection.hpp b/include/boost/geometry/strategies/cartesian/intersection.hpp index fe8584a8c..61ff25957 100644 --- a/include/boost/geometry/strategies/cartesian/intersection.hpp +++ b/include/boost/geometry/strategies/cartesian/intersection.hpp @@ -182,6 +182,8 @@ struct cartesian_segments } typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type; + typedef covered_by::cartesian_point_box covered_by_point_box_strategy_type; + typedef within::cartesian_point_box within_point_box_strategy_type; typedef expand::cartesian_box expand_box_strategy_type; template diff --git a/include/boost/geometry/strategies/cartesian/point_in_point.hpp b/include/boost/geometry/strategies/cartesian/point_in_point.hpp index fc849dcd4..fe1713638 100644 --- a/include/boost/geometry/strategies/cartesian/point_in_point.hpp +++ b/include/boost/geometry/strategies/cartesian/point_in_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, 2014, 2015, 2017, 2018, 2019. +// Modifications copyright (c) 2013-2019, 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 @@ -76,6 +76,8 @@ namespace strategy { namespace within struct cartesian_point_point { + typedef cartesian_tag cs_tag; + template static inline bool apply(Point1 const& point1, Point2 const& point2) { diff --git a/include/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp b/include/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp index 696a86c98..8bf647cc4 100644 --- a/include/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018, 2019. +// Modifications copyright (c) 2013-2019 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 @@ -58,8 +58,6 @@ template > class cartesian_winding { - typedef side::side_by_triangle side_strategy_type; - typedef typename select_calculation_type < Point, @@ -89,6 +87,17 @@ class cartesian_winding }; public: + typedef cartesian_tag cs_tag; + + typedef side::side_by_triangle side_strategy_type; + + static inline side_strategy_type get_side_strategy() + { + return side_strategy_type(); + } + + typedef expand::cartesian_point expand_point_strategy_type; + typedef typename side_strategy_type::envelope_strategy_type envelope_strategy_type; static inline envelope_strategy_type get_envelope_strategy() diff --git a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp index 9760f560c..e41e4bedb 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, 2017, 2018. -// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017, 2018, 2019. +// Modifications copyright (c) 2015-2019, 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 @@ -71,6 +71,8 @@ class side_by_triangle }; public : + typedef cartesian_tag cs_tag; + typedef strategy::envelope::cartesian envelope_strategy_type; static inline envelope_strategy_type get_envelope_strategy() diff --git a/include/boost/geometry/strategies/geographic/intersection.hpp b/include/boost/geometry/strategies/geographic/intersection.hpp index 3020deb59..9fbf90f69 100644 --- a/include/boost/geometry/strategies/geographic/intersection.hpp +++ b/include/boost/geometry/strategies/geographic/intersection.hpp @@ -195,6 +195,8 @@ struct geographic_segments } typedef covered_by::spherical_point_box disjoint_point_box_strategy_type; + typedef covered_by::spherical_point_box covered_by_point_box_strategy_type; + typedef within::spherical_point_box within_point_box_strategy_type; typedef expand::spherical_box expand_box_strategy_type; enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 }; diff --git a/include/boost/geometry/strategies/geographic/side.hpp b/include/boost/geometry/strategies/geographic/side.hpp index e22718f32..2a16d33f4 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-2018. -// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2019. +// Modifications copyright (c) 2014-2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -65,6 +65,8 @@ template class geographic { public: + typedef geographic_tag cs_tag; + typedef strategy::envelope::geographic < FormulaPolicy, diff --git a/include/boost/geometry/strategies/spherical/compare.hpp b/include/boost/geometry/strategies/spherical/compare.hpp index bf28fe75a..67acdcf6d 100644 --- a/include/boost/geometry/strategies/spherical/compare.hpp +++ b/include/boost/geometry/strategies/spherical/compare.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -70,9 +70,9 @@ template struct spherical_latitude { typedef typename geometry::coordinate_type::type coordinate1_type; - typedef typename geometry::coordinate_system::type::units units1_type; + typedef typename geometry::detail::cs_angular_units::type units1_type; typedef typename geometry::coordinate_type::type coordinate2_type; - typedef typename geometry::coordinate_system::type::units units2_type; + typedef typename geometry::detail::cs_angular_units::type units2_type; typedef typename boost::is_same::type same_units_type; template @@ -136,9 +136,9 @@ template struct spherical_longitude { typedef typename geometry::coordinate_type::type coordinate1_type; - typedef typename geometry::coordinate_system::type::units units1_type; + typedef typename geometry::detail::cs_angular_units::type units1_type; typedef typename geometry::coordinate_type::type coordinate2_type; - typedef typename geometry::coordinate_system::type::units units2_type; + typedef typename geometry::detail::cs_angular_units::type units2_type; typedef typename boost::is_same::type same_units_type; typedef typename boost::mpl::if_::type units_type; @@ -280,6 +280,16 @@ namespace services { +template +struct default_strategy + < + ComparePolicy, Point1, Point2, Dimension, + spherical_tag, spherical_tag + > +{ + typedef compare::spherical type; +}; + template struct default_strategy < diff --git a/include/boost/geometry/strategies/spherical/intersection.hpp b/include/boost/geometry/strategies/spherical/intersection.hpp index 05e1c476a..7b1c6af95 100644 --- a/include/boost/geometry/strategies/spherical/intersection.hpp +++ b/include/boost/geometry/strategies/spherical/intersection.hpp @@ -200,6 +200,8 @@ struct ecef_segments } typedef covered_by::spherical_point_box disjoint_point_box_strategy_type; + typedef covered_by::spherical_point_box covered_by_point_box_strategy_type; + typedef within::spherical_point_box within_point_box_strategy_type; typedef expand::spherical_box expand_box_strategy_type; enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 }; diff --git a/include/boost/geometry/strategies/spherical/point_in_point.hpp b/include/boost/geometry/strategies/spherical/point_in_point.hpp index 372e9cfac..b6e6973bd 100644 --- a/include/boost/geometry/strategies/spherical/point_in_point.hpp +++ b/include/boost/geometry/strategies/spherical/point_in_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, 2014, 2015, 2017, 2018, 2019. +// Modifications copyright (c) 2013-2019, 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 @@ -56,6 +56,9 @@ namespace detail { namespace within class point_point_on_spheroid { +public: + typedef spherical_tag cs_tag; + private: template struct are_same_points 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 c283b5333..75a2b39c3 100644 --- a/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018. -// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018, 2019. +// Modifications copyright (c) 2013-2019 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 @@ -128,6 +128,17 @@ class spherical_winding_base }; public: + typedef typename SideStrategy::cs_tag cs_tag; + + typedef SideStrategy side_strategy_type; + + inline side_strategy_type get_side_strategy() const + { + return m_side_strategy; + } + + typedef expand::spherical_point expand_point_strategy_type; + typedef typename SideStrategy::envelope_strategy_type envelope_strategy_type; inline envelope_strategy_type get_envelope_strategy() const diff --git a/include/boost/geometry/strategies/spherical/ssf.hpp b/include/boost/geometry/strategies/spherical/ssf.hpp index 18c547ced..2567cf56c 100644 --- a/include/boost/geometry/strategies/spherical/ssf.hpp +++ b/include/boost/geometry/strategies/spherical/ssf.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2011-2012 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, 2018, 2019. +// Modifications copyright (c) 2016-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, @@ -85,6 +85,8 @@ class spherical_side_formula { public : + typedef spherical_tag cs_tag; + typedef strategy::envelope::spherical envelope_strategy_type; static inline envelope_strategy_type get_envelope_strategy() From bfdd09c12c7390d86d1527603d0daf9136df6faa Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 4 Jun 2019 20:45:59 +0200 Subject: [PATCH 34/68] [test][overlay] Pass intersection strategy in sort_by_side test. --- test/algorithms/overlay/sort_by_side.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/algorithms/overlay/sort_by_side.cpp b/test/algorithms/overlay/sort_by_side.cpp index e836bef63..8acfe73df 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. -// Modifications copyright (c) 2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2019. +// Modifications copyright (c) 2017, 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, @@ -157,13 +157,10 @@ std::vector apply_overlay( detail::overlay::assign_null_policy >(geometry1, geometry2, strategy, robust_policy, turns, policy); - typename Strategy::side_strategy_type side_strategy; cluster_type clusters; bg::enrich_intersection_points(turns, - clusters, geometry1, geometry2, - robust_policy, - side_strategy); + clusters, geometry1, geometry2, robust_policy, strategy); // Gather cluster properties, with test option return ::gather_cluster_properties( From ec62cc9afaa0371bc7015dc71d067c62d74ef2ef Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 4 Jun 2019 22:43:29 +0200 Subject: [PATCH 35/68] [strategies] Refactor within/covered_by Box/Box strategies. --- .../strategies/cartesian/box_in_box.hpp | 196 +++++++++++++----- .../strategies/concepts/within_concept.hpp | 6 +- 2 files changed, 143 insertions(+), 59 deletions(-) diff --git a/include/boost/geometry/strategies/cartesian/box_in_box.hpp b/include/boost/geometry/strategies/cartesian/box_in_box.hpp index 4641aafcb..fef054cdb 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. -// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016, 2017, 2019. +// Modifications copyright (c) 2016-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -36,6 +36,11 @@ namespace within { +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + + struct box_within_coord { template @@ -63,18 +68,6 @@ struct box_covered_by_coord }; -template -struct box_within_range - : box_within_coord -{}; - - -template -struct box_covered_by_range - : box_covered_by_coord -{}; - - struct box_within_longitude_diff { template @@ -109,7 +102,7 @@ struct box_longitude_range BoxContainedValue, BoxContainingValue >::type calc_t; - typedef typename coordinate_system::type::units units_t; + typedef typename geometry::detail::cs_angular_units::type units_t; typedef math::detail::constants_on_spheroid constants; if (CoordCheck::apply(bed_min, bed_max, bing_min, bing_max)) @@ -144,35 +137,21 @@ struct box_longitude_range }; -// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag -template -struct box_within_range - : box_longitude_range -{}; - - -template -struct box_covered_by_range - : box_longitude_range -{}; - - template < template class SubStrategy, - typename Box1, - typename Box2, + typename CSTag, std::size_t Dimension, std::size_t DimensionCount > struct relate_box_box_loop { + template static inline bool apply(Box1 const& b_contained, Box2 const& b_containing) { assert_dimension_equal(); - typedef typename tag_cast::type, spherical_tag>::type cs_tag_t; - - if (! SubStrategy::apply( + + if (! SubStrategy::apply( get(b_contained), get(b_contained), get(b_containing), @@ -183,10 +162,9 @@ struct relate_box_box_loop return false; } - return relate_box_box_loop + return within::detail::relate_box_box_loop < - SubStrategy, - Box1, Box2, + SubStrategy, CSTag, Dimension + 1, DimensionCount >::apply(b_contained, b_containing); } @@ -195,32 +173,110 @@ struct relate_box_box_loop template < template class SubStrategy, - typename Box1, - typename Box2, + typename CSTag, std::size_t DimensionCount > -struct relate_box_box_loop +struct relate_box_box_loop { + template static inline bool apply(Box1 const& , Box2 const& ) { return true; } }; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +// for backward compatibility +template +struct box_within_range + : within::detail::box_within_coord +{}; + + +template +struct box_covered_by_range + : within::detail::box_covered_by_coord +{}; + + +// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag +template +struct box_within_range + : within::detail::box_longitude_range + < + Geometry, + within::detail::box_within_coord, + within::detail::box_within_longitude_diff + > +{}; + + +template +struct box_covered_by_range + : within::detail::box_longitude_range + < + Geometry, + within::detail::box_covered_by_coord, + within::detail::box_covered_by_longitude_diff + > +{}; + + +// for backward compatibility template < - typename Box1, - typename Box2, + 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) { - return relate_box_box_loop + typedef typename tag_cast < - SubStrategy, - Box1, Box2, 0, dimension::type::value + 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); + } +}; + + +struct cartesian_box_box +{ + template + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + return within::detail::relate_box_box_loop + < + box_within_range, + cartesian_tag, + 0, dimension::type::value + >::apply(box1, box2); + } +}; + +struct spherical_box_box +{ + template + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + return within::detail::relate_box_box_loop + < + box_within_range, + spherical_tag, + 0, dimension::type::value >::apply(box1, box2); } }; @@ -229,6 +285,42 @@ struct box_in_box } // namespace within +namespace covered_by +{ + + +struct cartesian_box_box +{ + template + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + return within::detail::relate_box_box_loop + < + strategy::within::box_covered_by_range, + cartesian_tag, + 0, dimension::type::value + >::apply(box1, box2); + } +}; + +struct spherical_box_box +{ + template + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + return within::detail::relate_box_box_loop + < + strategy::within::box_covered_by_range, + spherical_tag, + 0, dimension::type::value + >::apply(box1, box2); + } +}; + + +} + + #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS @@ -244,7 +336,7 @@ struct default_strategy cartesian_tag, cartesian_tag > { - typedef within::box_in_box type; + typedef cartesian_box_box type; }; // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag @@ -257,7 +349,7 @@ struct default_strategy spherical_tag, spherical_tag > { - typedef within::box_in_box type; + typedef spherical_box_box type; }; @@ -275,11 +367,7 @@ struct default_strategy cartesian_tag, cartesian_tag > { - typedef within::box_in_box - < - BoxContained, BoxContaining, - within::box_covered_by_range - > type; + typedef cartesian_box_box type; }; // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag @@ -292,11 +380,7 @@ struct default_strategy spherical_tag, spherical_tag > { - typedef within::box_in_box - < - BoxContained, BoxContaining, - within::box_covered_by_range - > type; + typedef spherical_box_box type; }; diff --git a/include/boost/geometry/strategies/concepts/within_concept.hpp b/include/boost/geometry/strategies/concepts/within_concept.hpp index e8b0b767a..f2a104d56 100644 --- a/include/boost/geometry/strategies/concepts/within_concept.hpp +++ b/include/boost/geometry/strategies/concepts/within_concept.hpp @@ -181,7 +181,7 @@ public : #endif }; -template +template class WithinStrategyBoxBox { #ifndef DOXYGEN_NO_CONCEPT_MEMBERS @@ -239,7 +239,7 @@ class WithinStrategyBoxBox public : BOOST_CONCEPT_USAGE(WithinStrategyBoxBox) { - checker::apply(&Strategy::apply); + checker::apply(&Strategy::template apply); } #endif }; @@ -283,7 +283,7 @@ struct check_within struct check_within { - BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox) ); + BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox) ); }; From d5d0564a1dd082bd30b84e9014a3c4aec40b0cf5 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 5 Jun 2019 10:48:39 +0200 Subject: [PATCH 36/68] [doc] Document define. --- include/boost/geometry/core/config.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/geometry/core/config.hpp b/include/boost/geometry/core/config.hpp index d510d1322..852cda479 100644 --- a/include/boost/geometry/core/config.hpp +++ b/include/boost/geometry/core/config.hpp @@ -18,6 +18,8 @@ #define BOOST_GEOMETRY_CXX11_ARRAY_UNIFIED_INITIALIZATION #endif +// Defining this selects Kramer rule for segment-intersection +// That is default behaviour. #define BOOST_GEOMETRY_USE_KRAMER_RULE // Rescaling is turned on, unless NO_ROBUSTNESS is defined From 30979a59e0cca3ba7322e4d4395b1925402e2dd4 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Thu, 13 Jun 2019 12:09:43 +0300 Subject: [PATCH 37/68] [strategies] Avoid divisions by zero --- .../strategies/geographic/distance_cross_track.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 161044ac3..72df65f03 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -339,11 +339,13 @@ private : CT M43 = res34.geodesic_scale; // cos(s14/earth_radius) is the spherical limit CT m34 = res34.reduced_length; - CT der = (M43 / m34) * sin(g4); - //normalize - delta_g4 = normalize(g4, der); - s14 = s14 - delta_g4 / der; + if (m34 != 0) + { + CT der = (M43 / m34) * sin(g4); + delta_g4 = normalize(g4, der); + s14 -= der != 0 ? delta_g4 / der : 0; + } result.distance = res34.distance; dist_improve = prev_distance > res34.distance || prev_distance == -1; From 5e509c06398081a79cbc87940ff081b606d9847e Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Tue, 18 Jun 2019 15:15:11 +0300 Subject: [PATCH 38/68] [stategies] Add meridian case optimization for degenerate segments --- .../geographic/distance_cross_track.hpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 72df65f03..003da0ec3 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -346,6 +346,7 @@ private : delta_g4 = normalize(g4, der); s14 -= der != 0 ? delta_g4 / der : 0; } + result.distance = res34.distance; dist_improve = prev_distance > res34.distance || prev_distance == -1; @@ -538,10 +539,10 @@ private : } } - geometry::formula::result_inverse res13 = - inverse_dist_azimuth_type::apply(lon1, lat1, lon3, lat3, spheroid); geometry::formula::result_inverse res12 = inverse_dist_azimuth_reverse_type::apply(lon1, lat1, lon2, lat2, spheroid); + geometry::formula::result_inverse res13 = + inverse_dist_azimuth_type::apply(lon1, lat1, lon3, lat3, spheroid); if (geometry::math::equals(res12.distance, c0)) { @@ -549,11 +550,12 @@ private : std::cout << "Degenerate segment" << std::endl; std::cout << "distance between points=" << res13.distance << std::endl; #endif - return non_iterative_case(lon1, lat2, res13.distance); - } + typename meridian_inverse::result res = + meridian_inverse::apply(lon1, lat1, lon3, lat3, spheroid); - geometry::formula::result_inverse res23 = - inverse_dist_azimuth_type::apply(lon2, lat2, lon3, lat3, spheroid); + return non_iterative_case(lon1, lat2, + res.meridian ? res.distance : res13.distance); + } // Compute a12 (GEO) CT a312 = res13.azimuth - res12.azimuth; @@ -589,9 +591,13 @@ private : #endif // projection of p3 on geodesic spanned by segment (p1,p2) fall // outside of segment on the side of p1 + return non_iterative_case(lon1, lat1, lon3, lat3, spheroid); } + geometry::formula::result_inverse res23 = + inverse_dist_azimuth_type::apply(lon2, lat2, lon3, lat3, spheroid); + CT a321 = res23.azimuth - res12.reverse_azimuth + pi; CT projection2 = cos( a321 ) * res23.distance / res12.distance; From d226019924200ac54424c760463c364153cec542 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Tue, 18 Jun 2019 15:17:10 +0300 Subject: [PATCH 39/68] [strategies] Initialize delta_g4 in newton method for pt-segment distance --- .../geometry/strategies/geographic/distance_cross_track.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 003da0ec3..3c4bd311f 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -318,7 +318,7 @@ private : int counter = 0; // robustness CT g4; - CT delta_g4; + CT delta_g4 = 0; bool dist_improve = true; CT s14 = s14_start; From a24578181fe7eaf2c4fc365a35c14c7622330655 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 24 Jun 2019 11:56:20 +0200 Subject: [PATCH 40/68] [strategies] Allow now specifying Point types in point_in_poly_* strategies. --- .../agnostic/point_in_poly_winding.hpp | 8 +- .../point_in_poly_crossings_multiply.hpp | 40 +++-- .../cartesian/point_in_poly_franklin.hpp | 60 ++++--- .../cartesian/point_in_poly_winding.hpp | 76 ++++----- .../strategies/concepts/within_concept.hpp | 13 +- .../geographic/point_in_poly_winding.hpp | 15 +- .../spherical/point_in_poly_winding.hpp | 161 ++++++++++-------- 7 files changed, 198 insertions(+), 175 deletions(-) diff --git a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp index 774294b57..19a3e628d 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2016, 2017. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2019. +// Modifications copyright (c) 2013-2019 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 @@ -62,7 +62,7 @@ struct winding_base_type template struct winding_base_type { - typedef within::cartesian_winding type; + typedef within::cartesian_winding type; }; template @@ -70,8 +70,6 @@ struct winding_base_type { typedef within::detail::spherical_winding_base < - Point, - PointOfSegment, typename strategy::side::services::default_strategy < typename cs_tag::type diff --git a/include/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp b/include/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp index a8e0de7b7..e8864df29 100644 --- a/include/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp +++ b/include/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.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, 2019. +// Modifications copyright (c) 2018, 2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -47,18 +47,21 @@ namespace strategy { namespace within template < - typename Point, - typename PointOfSegment = Point, + typename Point_, // for backward compatibility + typename PointOfSegment_ = Point_, // for backward compatibility typename CalculationType = void > class crossings_multiply { - typedef typename select_calculation_type - < - Point, - PointOfSegment, - CalculationType - >::type calculation_type; + template + struct calculation_type + : select_calculation_type + < + Point, + PointOfSegment, + CalculationType + > + {}; class flags { @@ -79,20 +82,21 @@ class crossings_multiply public : - typedef Point point_type; - typedef PointOfSegment segment_point_type; typedef flags state_type; + template static inline bool apply(Point const& point, PointOfSegment const& seg1, PointOfSegment const& seg2, flags& state) { - calculation_type const tx = get<0>(point); - calculation_type const ty = get<1>(point); - calculation_type const x0 = get<0>(seg1); - calculation_type const y0 = get<1>(seg1); - calculation_type const x1 = get<0>(seg2); - calculation_type const y1 = get<1>(seg2); + typedef typename calculation_type::type calc_t; + + calc_t const tx = get<0>(point); + calc_t const ty = get<1>(point); + calc_t const x0 = get<0>(seg1); + calc_t const y0 = get<1>(seg1); + calc_t const x1 = get<0>(seg2); + calc_t const y1 = get<1>(seg2); if (state.first) { diff --git a/include/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp b/include/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp index 16e798747..2afa7f130 100644 --- a/include/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp +++ b/include/boost/geometry/strategies/cartesian/point_in_poly_franklin.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, 2019. +// Modifications copyright (c) 2018, 2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -51,48 +51,52 @@ namespace strategy { namespace within template < - typename Point, - typename PointOfSegment = Point, + typename Point_, // for backward compatibility + typename PointOfSegment_ = Point_, // for backward compatibility typename CalculationType = void > class franklin { - typedef typename select_calculation_type - < - Point, - PointOfSegment, - CalculationType - >::type calculation_type; + template + struct calculation_type + : select_calculation_type + < + Point, + PointOfSegment, + CalculationType + > + {}; - /*! subclass to keep state */ - class crossings - { - bool crosses; + /*! subclass to keep state */ + class crossings + { + bool crosses; - public : + public : - friend class franklin; - inline crossings() - : crosses(false) - {} - }; + friend class franklin; + inline crossings() + : crosses(false) + {} + }; public : - typedef Point point_type; - typedef PointOfSegment segment_point_type; typedef crossings state_type; + template static inline bool apply(Point const& point, PointOfSegment const& seg1, PointOfSegment const& seg2, crossings& state) { - calculation_type const& px = get<0>(point); - calculation_type const& py = get<1>(point); - calculation_type const& x1 = get<0>(seg1); - calculation_type const& y1 = get<1>(seg1); - calculation_type const& x2 = get<0>(seg2); - calculation_type const& y2 = get<1>(seg2); + typedef typename calculation_type::type calc_t; + + calc_t const& px = get<0>(point); + calc_t const& py = get<1>(point); + calc_t const& x1 = get<0>(seg1); + calc_t const& y1 = get<1>(seg1); + calc_t const& x2 = get<0>(seg2); + calc_t const& y2 = get<1>(seg2); if ( ( (y2 <= py && py < y1) || (y1 <= py && py < y2) ) diff --git a/include/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp b/include/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp index 8bf647cc4..bb0fe3f81 100644 --- a/include/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp @@ -40,8 +40,8 @@ namespace strategy { namespace within /*! \brief Within detection using winding rule in cartesian coordinate system. \ingroup strategies -\tparam Point \tparam_point -\tparam PointOfSegment \tparam_segment_point +\tparam Point_ \tparam_point +\tparam PointOfSegment_ \tparam_segment_point \tparam CalculationType \tparam_calculation \author Barend Gehrels @@ -52,18 +52,21 @@ namespace strategy { namespace within */ template < - typename Point, - typename PointOfSegment = Point, + typename Point_ = void, // for backward compatibility + typename PointOfSegment_ = Point_, // for backward compatibility typename CalculationType = void > class cartesian_winding { - typedef typename select_calculation_type - < - Point, - PointOfSegment, - CalculationType - >::type calculation_type; + template + struct calculation_type + : select_calculation_type + < + Point, + PointOfSegment, + CalculationType + > + {}; /*! subclass to keep state */ class counter @@ -127,10 +130,9 @@ public: typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type; // Typedefs and static methods to fulfill the concept - typedef Point point_type; - typedef PointOfSegment segment_point_type; typedef counter state_type; + template static inline bool apply(Point const& point, PointOfSegment const& s1, PointOfSegment const& s2, counter& state) @@ -178,6 +180,7 @@ public: } private: + template static inline int check_segment(Point const& point, PointOfSegment const& seg1, PointOfSegment const& seg2, @@ -192,15 +195,18 @@ private: return calculate_count(point, seg1, seg2, eq1, eq2); } + template static inline bool check_touch(Point const& point, PointOfSegment const& seg1, PointOfSegment const& seg2, counter& state, bool& eq1, bool& eq2) { - calculation_type const px = get<0>(point); - calculation_type const s1x = get<0>(seg1); - calculation_type const s2x = get<0>(seg2); + typedef typename calculation_type::type calc_t; + + calc_t const px = get<0>(point); + calc_t const s1x = get<0>(seg1); + calc_t const s2x = get<0>(seg2); eq1 = math::equals(s1x, px); eq2 = math::equals(s2x, px); @@ -209,9 +215,9 @@ private: // The only thing which has to be done is check if point is ON segment if (eq1 && eq2) { - calculation_type const py = get<1>(point); - calculation_type const s1y = get<1>(seg1); - calculation_type const s2y = get<1>(seg2); + calc_t const py = get<1>(point); + calc_t const s1y = get<1>(seg1); + calc_t const s2y = get<1>(seg2); if ((s1y <= py && s2y >= py) || (s2y <= py && s1y >= py)) { state.m_touches = true; @@ -221,14 +227,17 @@ private: return false; } + template static inline int calculate_count(Point const& point, PointOfSegment const& seg1, PointOfSegment const& seg2, bool eq1, bool eq2) { - calculation_type const p = get<0>(point); - calculation_type const s1 = get<0>(seg1); - calculation_type const s2 = get<0>(seg2); + typedef typename calculation_type::type calc_t; + + calc_t const p = get<0>(point); + calc_t const s1 = get<0>(seg1); + calc_t const s2 = get<0>(seg2); return eq1 ? (s2 > p ? 1 : -1) // Point on level s1, E/W depending on s2 : eq2 ? (s1 > p ? -1 : 1) // idem @@ -237,6 +246,7 @@ private: : 0; } + template static inline int side_equal(Point const& point, PointOfSegment const& se, int count) @@ -260,21 +270,13 @@ namespace services template struct default_strategy { - typedef cartesian_winding - < - typename geometry::point_type::type, - typename geometry::point_type::type - > type; + typedef cartesian_winding<> type; }; template struct default_strategy { - typedef cartesian_winding - < - typename geometry::point_type::type, - typename geometry::point_type::type - > type; + typedef cartesian_winding<> type; }; } // namespace services @@ -292,21 +294,13 @@ namespace strategy { namespace covered_by { namespace services template struct default_strategy { - typedef within::cartesian_winding - < - typename geometry::point_type::type, - typename geometry::point_type::type - > type; + typedef within::cartesian_winding<> type; }; template struct default_strategy { - typedef within::cartesian_winding - < - typename geometry::point_type::type, - typename geometry::point_type::type - > type; + typedef within::cartesian_winding<> type; }; }}} // namespace strategy::covered_by::services diff --git a/include/boost/geometry/strategies/concepts/within_concept.hpp b/include/boost/geometry/strategies/concepts/within_concept.hpp index f2a104d56..65077647e 100644 --- a/include/boost/geometry/strategies/concepts/within_concept.hpp +++ b/include/boost/geometry/strategies/concepts/within_concept.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, 2019. +// Modifications copyright (c) 2018, 2019 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 @@ -42,11 +42,13 @@ namespace boost { namespace geometry { namespace concepts \brief Checks strategy for within (point-in-polygon) \ingroup within */ -template +template class WithinStrategyPolygonal { #ifndef DOXYGEN_NO_CONCEPT_MEMBERS + typedef typename geometry::point_type::type point_of_segment; + // 1) must define state_type typedef typename Strategy::state_type state_type; @@ -113,7 +115,8 @@ class WithinStrategyPolygonal public : BOOST_CONCEPT_USAGE(WithinStrategyPolygonal) { - checker::apply(&Strategy::apply, &Strategy::result); + checker::apply(&Strategy::template apply, + &Strategy::result); } #endif }; @@ -270,7 +273,7 @@ template > struct check_within { - BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal) ); + BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal) ); }; diff --git a/include/boost/geometry/strategies/geographic/point_in_poly_winding.hpp b/include/boost/geometry/strategies/geographic/point_in_poly_winding.hpp index 95a196147..fe45f8db7 100644 --- a/include/boost/geometry/strategies/geographic/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/geographic/point_in_poly_winding.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2017 Oracle and/or its affiliates. +// Copyright (c) 2017, 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, @@ -38,8 +38,8 @@ namespace strategy { namespace within */ template < - typename Point, - typename PointOfSegment = Point, + typename Point = void, // for backward compatibility + typename PointOfSegment = Point, // for backward compatibility typename FormulaPolicy = strategy::andoyer, typename Spheroid = srs::spheroid, typename CalculationType = void @@ -47,16 +47,12 @@ template class geographic_winding : public within::detail::spherical_winding_base < - Point, - PointOfSegment, side::geographic, CalculationType > { typedef within::detail::spherical_winding_base < - Point, - PointOfSegment, side::geographic, CalculationType > base_t; @@ -68,6 +64,11 @@ public: explicit geographic_winding(Spheroid const& model) : base_t(model) {} + + Spheroid const& model() const + { + return base_t::m_side_strategy.model(); + } }; 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 75a2b39c3..aa64241e5 100644 --- a/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp +++ b/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp @@ -46,28 +46,19 @@ namespace strategy { namespace within namespace detail { -template -< - typename Point, - typename PointOfSegment = Point, - typename SideStrategy = typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type, - typename CalculationType = void -> +template class spherical_winding_base { - typedef typename select_calculation_type - < - Point, - PointOfSegment, - CalculationType - >::type calculation_type; + template + struct calculation_type + : select_calculation_type + < + Point, + PointOfSegment, + CalculationType + > + {}; - typedef typename geometry::detail::cs_angular_units::type units_t; - typedef math::detail::constants_on_spheroid constants; - /*! subclass to keep state */ class counter { @@ -176,14 +167,17 @@ public: {} // Typedefs and static methods to fulfill the concept - typedef Point point_type; - typedef PointOfSegment segment_point_type; typedef counter state_type; + template inline bool apply(Point const& point, PointOfSegment const& s1, PointOfSegment const& s2, counter& state) const { + typedef typename calculation_type::type calc_t; + typedef typename geometry::detail::cs_angular_units::type units_t; + typedef math::detail::constants_on_spheroid constants; + bool eq1 = false; bool eq2 = false; bool s_antipodal = false; @@ -207,9 +201,9 @@ public: } else { - calculation_type const pi = constants::half_period(); - calculation_type const s1_lat = get<1>(s1); - calculation_type const s2_lat = get<1>(s2); + calc_t const pi = constants::half_period(); + calc_t const s1_lat = get<1>(s1); + calc_t const s2_lat = get<1>(s2); side = math::sign(ci.count) * (pi - s1_lat - s2_lat <= pi // segment goes through north pole @@ -261,8 +255,8 @@ public: return state.code(); } -private: - +protected: + template static inline count_info check_segment(Point const& point, PointOfSegment const& seg1, PointOfSegment const& seg2, @@ -277,6 +271,7 @@ private: return calculate_count(point, seg1, seg2, eq1, eq2, s_antipodal); } + template static inline int check_touch(Point const& point, PointOfSegment const& seg1, PointOfSegment const& seg2, @@ -285,39 +280,43 @@ private: bool& eq2, bool& s_antipodal) { - calculation_type const c0 = 0; - calculation_type const c2 = 2; - calculation_type const pi = constants::half_period(); - calculation_type const half_pi = pi / c2; + typedef typename calculation_type::type calc_t; + typedef typename geometry::detail::cs_angular_units::type units_t; + typedef math::detail::constants_on_spheroid constants; - calculation_type const p_lon = get<0>(point); - calculation_type const s1_lon = get<0>(seg1); - calculation_type const s2_lon = get<0>(seg2); - calculation_type const p_lat = get<1>(point); - calculation_type const s1_lat = get<1>(seg1); - calculation_type const s2_lat = get<1>(seg2); + calc_t const c0 = 0; + calc_t const c2 = 2; + calc_t const pi = constants::half_period(); + calc_t const half_pi = pi / c2; + + calc_t const p_lon = get<0>(point); + calc_t const s1_lon = get<0>(seg1); + calc_t const s2_lon = get<0>(seg2); + calc_t const p_lat = get<1>(point); + calc_t const s1_lat = get<1>(seg1); + calc_t const s2_lat = get<1>(seg2); // NOTE: lat in {-90, 90} and arbitrary lon // it doesn't matter what lon it is if it's a pole // so e.g. if one of the segment endpoints is a pole // then only the other lon matters - bool eq1_strict = longitudes_equal(s1_lon, p_lon); - bool eq2_strict = longitudes_equal(s2_lon, p_lon); + bool eq1_strict = longitudes_equal(s1_lon, p_lon); + bool eq2_strict = longitudes_equal(s2_lon, p_lon); bool eq1_anti = false; bool eq2_anti = false; - calculation_type const anti_p_lon = p_lon + (p_lon <= c0 ? pi : -pi); + calc_t const anti_p_lon = p_lon + (p_lon <= c0 ? pi : -pi); eq1 = eq1_strict // lon strictly equal to s1 - || (eq1_anti = longitudes_equal(s1_lon, anti_p_lon)) // anti-lon strictly equal to s1 + || (eq1_anti = longitudes_equal(s1_lon, anti_p_lon)) // anti-lon strictly equal to s1 || math::equals(math::abs(s1_lat), half_pi); // s1 is pole eq2 = eq2_strict // lon strictly equal to s2 - || (eq2_anti = longitudes_equal(s2_lon, anti_p_lon)) // anti-lon strictly equal to s2 + || (eq2_anti = longitudes_equal(s2_lon, anti_p_lon)) // anti-lon strictly equal to s2 || math::equals(math::abs(s2_lat), half_pi); // s2 is pole // segment overlapping pole - calculation_type const s_lon_diff = math::longitude_distance_signed(s1_lon, s2_lon); + calc_t const s_lon_diff = math::longitude_distance_signed(s1_lon, s2_lon); s_antipodal = math::equals(s_lon_diff, pi); if (s_antipodal) { @@ -382,36 +381,41 @@ private: } // Called if point is not aligned with a vertical segment + template static inline count_info calculate_count(Point const& point, PointOfSegment const& seg1, PointOfSegment const& seg2, bool eq1, bool eq2, bool s_antipodal) { + typedef typename calculation_type::type calc_t; + typedef typename geometry::detail::cs_angular_units::type units_t; + typedef math::detail::constants_on_spheroid constants; + // If both segment endpoints were poles below checks wouldn't be enough // but this means that either both are the same or that they are N/S poles // and therefore the segment is not valid. // If needed (eq1 && eq2 ? 0) could be returned - calculation_type const c0 = 0; - calculation_type const pi = constants::half_period(); + calc_t const c0 = 0; + calc_t const pi = constants::half_period(); - calculation_type const p = get<0>(point); - calculation_type const s1 = get<0>(seg1); - calculation_type const s2 = get<0>(seg2); + calc_t const p = get<0>(point); + calc_t const s1 = get<0>(seg1); + calc_t const s2 = get<0>(seg2); - calculation_type const s1_p = math::longitude_distance_signed(s1, p); + calc_t const s1_p = math::longitude_distance_signed(s1, p); if (s_antipodal) { return count_info(s1_p < c0 ? -2 : 2, false); // choose W/E } - calculation_type const s1_s2 = math::longitude_distance_signed(s1, s2); + calc_t const s1_s2 = math::longitude_distance_signed(s1, s2); if (eq1 || eq2) // Point on level s1 or s2 { return count_info(s1_s2 < c0 ? -1 : 1, // choose W/E - longitudes_equal(p + pi, (eq1 ? s1 : s2))); + longitudes_equal(p + pi, (eq1 ? s1 : s2))); } // Point between s1 and s2 @@ -421,7 +425,7 @@ private: return count_info(s1_s2 < c0 ? -2 : 2, false); // choose W/E } - calculation_type const s1_p_anti = math::longitude_distance_signed(s1, p + pi); + calc_t const s1_p_anti = math::longitude_distance_signed(s1, p + pi); // Anti-Point between s1 and s2 if ( math::sign(s1_p_anti) == math::sign(s1_s2) @@ -456,12 +460,13 @@ private: // In the code below actually D = 0, so segments are nearly-vertical // Called when the point is on the same level as one of the segment's points // but the point is not aligned with a vertical segment + template inline int side_equal(Point const& point, PointOfSegment const& se, count_info const& ci) const { typedef typename coordinate_type::type scoord_t; - typedef typename geometry::detail::cs_angular_units::type units_t; + typedef typename geometry::detail::cs_angular_units::type units_t; if (math::equals(get<1>(point), get<1>(se))) { @@ -477,11 +482,11 @@ private: scoord_t ss20 = get<0>(se); if (ci.count > 0) { - ss20 += small_angle(); + ss20 += small_angle(); } else { - ss20 -= small_angle(); + ss20 -= small_angle(); } math::normalize_longitude(ss20); set<0>(ss2, ss20); @@ -491,16 +496,20 @@ private: } // 1 deg or pi/180 rad - static inline calculation_type small_angle() + template + static inline CalcT small_angle() { - return constants::half_period() / calculation_type(180); + typedef math::detail::constants_on_spheroid constants; + + return constants::half_period() / CalcT(180); }; - static inline bool longitudes_equal(calculation_type const& lon1, calculation_type const& lon2) + template + static inline bool longitudes_equal(CalcT const& lon1, CalcT const& lon2) { return math::equals( - math::longitude_distance_signed(lon1, lon2), - calculation_type(0)); + math::longitude_distance_signed(lon1, lon2), + CalcT(0)); } SideStrategy m_side_strategy; @@ -525,15 +534,13 @@ private: */ template < - typename Point, - typename PointOfSegment = Point, + typename Point = void, // for backward compatibility + typename PointOfSegment = Point, // for backward compatibility typename CalculationType = void > class spherical_winding : public within::detail::spherical_winding_base < - Point, - PointOfSegment, side::spherical_side_formula, CalculationType > @@ -550,8 +557,11 @@ struct default_strategy::type, - typename geometry::point_type::type + typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type, + void > type; }; @@ -560,8 +570,11 @@ struct default_strategy::type, - typename geometry::point_type::type + typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type, + void > type; }; @@ -582,8 +595,11 @@ struct default_strategy::type, - typename geometry::point_type::type + typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type, + void > type; }; @@ -592,8 +608,11 @@ struct default_strategy::type, - typename geometry::point_type::type + typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type, + void > type; }; From f62214787d31b338c4f3bb4386a290c912eff575 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 24 Jun 2019 12:04:07 +0200 Subject: [PATCH 41/68] [strategies] Add model() getter to geographic side strategy. --- include/boost/geometry/strategies/geographic/side.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/boost/geometry/strategies/geographic/side.hpp b/include/boost/geometry/strategies/geographic/side.hpp index 2a16d33f4..1a9648e74 100644 --- a/include/boost/geometry/strategies/geographic/side.hpp +++ b/include/boost/geometry/strategies/geographic/side.hpp @@ -125,6 +125,11 @@ public: return formula::azimuth_side_value(a1p, a12); } + Spheroid const& model() const + { + return m_model; + } + private: template Date: Mon, 24 Jun 2019 12:05:07 +0200 Subject: [PATCH 42/68] [strategies] Do not use BoxIn type as temporary type (may be non-mutable). --- .../strategies/spherical/envelope_box.hpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/boost/geometry/strategies/spherical/envelope_box.hpp b/include/boost/geometry/strategies/spherical/envelope_box.hpp index 0a9436d12..5a080f4a6 100644 --- a/include/boost/geometry/strategies/spherical/envelope_box.hpp +++ b/include/boost/geometry/strategies/spherical/envelope_box.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-2018. -// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2019. +// Modifications copyright (c) 2015-2019, 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 @@ -27,12 +27,15 @@ #include +#include #include #include #include #include +#include + #include @@ -88,9 +91,11 @@ struct spherical_box template static inline void apply(BoxIn const& box_in, BoxOut& mbr) { - BoxIn box_in_normalized = box_in; - - if (!is_inverse_spheroidal_coordinates(box_in)) + // BoxIn can be non-mutable + typename helper_geometry::type box_in_normalized; + geometry::convert(box_in, box_in_normalized); + + if (! is_inverse_spheroidal_coordinates(box_in)) { strategy::normalize::spherical_box::apply(box_in, box_in_normalized); } From 9777b2a0cb1544aa81ff0202f930b5b9afcf5841 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 24 Jun 2019 12:09:06 +0200 Subject: [PATCH 43/68] [strategies] Add strategies getters in disjoint and distance strategies (Seg/Box). --- .../cartesian/disjoint_segment_box.hpp | 22 +++------ .../cartesian/distance_projected_point.hpp | 25 +++++++++- .../cartesian/distance_segment_box.hpp | 22 +++++++++ .../geographic/disjoint_segment_box.hpp | 24 +++------- .../geographic/distance_cross_track.hpp | 31 ++++++++++++- .../geographic/distance_segment_box.hpp | 32 ++++++++++++- .../spherical/disjoint_segment_box.hpp | 19 ++------ .../spherical/distance_cross_track.hpp | 45 +++++++++++++++++- .../spherical/distance_segment_box.hpp | 46 +++++++++++++++++-- 9 files changed, 207 insertions(+), 59 deletions(-) diff --git a/include/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp b/include/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp index 4da4bc450..37ae77f2b 100644 --- a/include/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp +++ b/include/boost/geometry/strategies/cartesian/disjoint_segment_box.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-2019. +// Modifications copyright (c) 2013-2019, 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 @@ -35,6 +35,7 @@ #include +#include #include @@ -246,22 +247,11 @@ struct disjoint_segment_box_impl // other strategies that are used are intersection and covered_by strategies. struct segment_box { - template - struct point_in_geometry_strategy - : services::default_strategy - < - typename point_type::type, - Box - > - {}; + typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type; - template - static inline typename point_in_geometry_strategy::type - get_point_in_geometry_strategy() + static inline disjoint_point_box_strategy_type get_disjoint_point_box_strategy() { - typedef typename point_in_geometry_strategy::type strategy_type; - - return strategy_type(); + return disjoint_point_box_strategy_type(); } template diff --git a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp index bd4f7130c..16515a7a2 100644 --- a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2014, 2018. -// Modifications copyright (c) 2014-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2018, 2019. +// Modifications copyright (c) 2014-2019, 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 @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -80,6 +81,26 @@ class projected_point public : typedef within::cartesian_point_point equals_point_point_strategy_type; + typedef 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(); + } + + typedef within::cartesian_winding + < + void, void, CalculationType + > point_in_geometry_strategy_type; + + static inline point_in_geometry_strategy_type get_point_in_geometry_strategy() + { + return point_in_geometry_strategy_type(); + } + // The three typedefs below are necessary to calculate distances // from segments defined in integer coordinates. diff --git a/include/boost/geometry/strategies/cartesian/distance_segment_box.hpp b/include/boost/geometry/strategies/cartesian/distance_segment_box.hpp index b623822ec..2d7cd2f9b 100644 --- a/include/boost/geometry/strategies/cartesian/distance_segment_box.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_segment_box.hpp @@ -14,7 +14,10 @@ #include #include +#include +#include #include +#include namespace boost { namespace geometry { @@ -43,6 +46,8 @@ struct cartesian_segment_box > {}; + typedef cartesian_tag cs_tag; + // point-point strategy getters struct distance_pp_strategy { @@ -64,6 +69,23 @@ struct cartesian_segment_box return typename distance_ps_strategy::type(); } + struct distance_pb_strategy + { + typedef pythagoras_point_box type; + }; + + inline typename distance_pb_strategy::type get_distance_pb_strategy() const + { + return typename distance_pb_strategy::type(); + } + + typedef side::side_by_triangle side_strategy_type; + + static inline side_strategy_type get_side_strategy() + { + return side_strategy_type(); + } + typedef within::cartesian_point_point equals_point_point_strategy_type; static inline equals_point_point_strategy_type get_equals_point_point_strategy() diff --git a/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp b/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp index 49c80a5e7..c4b843072 100644 --- a/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp +++ b/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2017-2018 Oracle and/or its affiliates. +// Copyright (c) 2017-2019 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -31,11 +31,12 @@ #include +// TODO: spherical_point_box currently defined in the same file as cartesian +#include #include #include #include #include -#include #include @@ -65,22 +66,11 @@ public: : m_spheroid(spheroid) {} - template - struct point_in_geometry_strategy - : services::default_strategy - < - typename point_type::type, - Box - > - {}; - - template - static inline typename point_in_geometry_strategy::type - get_point_in_geometry_strategy() + typedef covered_by::spherical_point_box disjoint_point_box_strategy_type; + + static inline disjoint_point_box_strategy_type get_disjoint_point_box_strategy() { - typedef typename point_in_geometry_strategy::type strategy_type; - - return strategy_type(); + return disjoint_point_box_strategy_type(); } template diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 53942529b..51bcef0a8 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2016-2018, Oracle and/or its affiliates. +// Copyright (c) 2016-2019, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -89,6 +90,29 @@ class geographic_cross_track public : typedef within::spherical_point_point equals_point_point_strategy_type; + typedef intersection::geographic_segments + < + FormulaPolicy, + 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 within::geographic_winding + < + void, void, FormulaPolicy, Spheroid, CalculationType + > point_in_geometry_strategy_type; + + inline point_in_geometry_strategy_type get_point_in_geometry_strategy() const + { + return point_in_geometry_strategy_type(m_spheroid); + } + template struct return_type : promote_floating_point @@ -132,6 +156,11 @@ public : m_spheroid); } + Spheroid const& model() const + { + return m_spheroid; + } + private : template diff --git a/include/boost/geometry/strategies/geographic/distance_segment_box.hpp b/include/boost/geometry/strategies/geographic/distance_segment_box.hpp index 615f93873..99b181fa2 100644 --- a/include/boost/geometry/strategies/geographic/distance_segment_box.hpp +++ b/include/boost/geometry/strategies/geographic/distance_segment_box.hpp @@ -16,9 +16,10 @@ #include #include -#include #include #include +#include +#include #include #include #include @@ -55,6 +56,8 @@ struct geographic_segment_box > {}; + typedef geographic_tag cs_tag; + // point-point strategy getters struct distance_pp_strategy { @@ -83,6 +86,33 @@ struct geographic_segment_box return distance_type(m_spheroid); } + struct distance_pb_strategy + { + typedef geographic_cross_track_point_box + < + FormulaPolicy, + Spheroid, + CalculationType + > type; + }; + + inline typename distance_pb_strategy::type get_distance_pb_strategy() const + { + return typename distance_pb_strategy::type(m_spheroid); + } + + typedef side::geographic + < + FormulaPolicy, + Spheroid, + CalculationType + > side_strategy_type; + + inline side_strategy_type get_side_strategy() const + { + return side_strategy_type(m_spheroid); + } + typedef within::spherical_point_point equals_point_point_strategy_type; static inline equals_point_point_strategy_type get_equals_point_point_strategy() diff --git a/include/boost/geometry/strategies/spherical/disjoint_segment_box.hpp b/include/boost/geometry/strategies/spherical/disjoint_segment_box.hpp index 9c6711dea..29b6bdaf5 100644 --- a/include/boost/geometry/strategies/spherical/disjoint_segment_box.hpp +++ b/include/boost/geometry/strategies/spherical/disjoint_segment_box.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2017-2018 Oracle and/or its affiliates. +// Copyright (c) 2017-2019 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -46,22 +46,11 @@ namespace boost { namespace geometry { namespace strategy { namespace disjoint // other strategies that are used are intersection and covered_by strategies. struct segment_box_spherical { - template - struct point_in_geometry_strategy - : services::default_strategy - < - typename point_type::type, - Box - > - {}; + typedef covered_by::spherical_point_box disjoint_point_box_strategy_type; - template - static inline typename point_in_geometry_strategy::type - get_point_in_geometry_strategy() + static inline disjoint_point_box_strategy_type get_disjoint_point_box_strategy() { - typedef typename point_in_geometry_strategy::type strategy_type; - - return strategy_type(); + return disjoint_point_box_strategy_type(); } template diff --git a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp index 280bf76b4..439de0d03 100644 --- a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014-2018. -// Modifications copyright (c) 2014-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2019. +// Modifications copyright (c) 2014-2019, 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 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -332,6 +333,26 @@ class cross_track public : typedef within::spherical_point_point equals_point_point_strategy_type; + typedef 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(); + } + + typedef within::spherical_winding + < + void, void, CalculationType + > point_in_geometry_strategy_type; + + static inline point_in_geometry_strategy_type get_point_in_geometry_strategy() + { + return point_in_geometry_strategy_type(); + } + template struct return_type : promote_floating_point @@ -513,6 +534,26 @@ class cross_track public : typedef within::spherical_point_point equals_point_point_strategy_type; + typedef 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(); + } + + typedef within::spherical_winding + < + void, void, CalculationType + > point_in_geometry_strategy_type; + + static inline point_in_geometry_strategy_type get_point_in_geometry_strategy() + { + return point_in_geometry_strategy_type(); + } + template struct return_type : promote_floating_point diff --git a/include/boost/geometry/strategies/spherical/distance_segment_box.hpp b/include/boost/geometry/strategies/spherical/distance_segment_box.hpp index bb622ec52..addc2b9e1 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 // spherical +#include namespace boost { namespace geometry { @@ -58,14 +59,28 @@ struct generic_segment_box { ReturnType result; typename LessEqual::other less_equal; - typedef geometry::model::segment Segment; - typedef typename cs_tag::type segment_cs_type; + typedef geometry::model::segment segment_type; + // if cs_tag is spherical_tag check segment's cs_tag with spherical_equatorial_tag as default + typedef typename boost::mpl::if_c + < + boost::is_same::value, + typename boost::mpl::if_c + < + boost::is_same + < + typename geometry::cs_tag::type, + spherical_polar_tag + >::value, + spherical_polar_tag, spherical_equatorial_tag + >::type, + typename SegmentBoxStrategy::cs_tag + >::type cs_tag; typedef geometry::detail::disjoint:: - disjoint_segment_box_sphere_or_spheroid + disjoint_segment_box_sphere_or_spheroid disjoint_sb; typedef typename disjoint_sb::disjoint_info disjoint_info_type; - Segment seg(p0, p1); + segment_type seg(p0, p1); geometry::model::box input_box; geometry::set_from_radian @@ -120,7 +135,7 @@ struct generic_segment_box CT vertex_lon = geometry::formula::vertex_longitude < CT, - segment_cs_type + cs_tag >::apply(lon1, lat1, lon2, lat2, vertex_lat, alp1, az_strategy); @@ -196,6 +211,8 @@ struct spherical_segment_box > {}; + typedef spherical_tag cs_tag; + // strategy getters // point-point strategy getters @@ -219,6 +236,25 @@ struct spherical_segment_box return typename distance_ps_strategy::type(); } + struct distance_pb_strategy + { + typedef cross_track_point_box type; + }; + + inline typename distance_pb_strategy::type get_distance_pb_strategy() const + { + return typename distance_pb_strategy::type(); + } + + // TODO: why is the Radius not propagated above? + + typedef side::spherical_side_formula side_strategy_type; + + static inline side_strategy_type get_side_strategy() + { + return side_strategy_type(); + } + typedef within::spherical_point_point equals_point_point_strategy_type; static inline equals_point_point_strategy_type get_equals_point_point_strategy() From 1d07ed1b3de75e0c77c5d55f43053a98e27b5025 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 24 Jun 2019 12:14:48 +0200 Subject: [PATCH 44/68] [policies] Get default compare strategy with 2 different point types. --- include/boost/geometry/policies/compare.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/policies/compare.hpp b/include/boost/geometry/policies/compare.hpp index 66f76b2b2..6a081af83 100644 --- a/include/boost/geometry/policies/compare.hpp +++ b/include/boost/geometry/policies/compare.hpp @@ -165,8 +165,8 @@ struct greater typedef typename strategy::compare::services::default_strategy < strategy::compare::greater, - Point, Point, - Dimension + Point1, Point2, + Dimension, CSTag, CSTag >::type strategy_type; From be9114bb661c986cf6c0177b3fbba9ca60fda1bd Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 24 Jun 2019 12:16:35 +0200 Subject: [PATCH 45/68] [policies] Get CSTag in rescale_policy_type, by default taken from Geometry type. --- .../robustness/get_rescale_policy.hpp | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/include/boost/geometry/policies/robustness/get_rescale_policy.hpp b/include/boost/geometry/policies/robustness/get_rescale_policy.hpp index 9bb3f885a..fd677ec2b 100644 --- a/include/boost/geometry/policies/robustness/get_rescale_policy.hpp +++ b/include/boost/geometry/policies/robustness/get_rescale_policy.hpp @@ -5,10 +5,11 @@ // Copyright (c) 2014-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2019. +// Modifications copyright (c) 2015, 2019, 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 // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -245,7 +246,11 @@ struct get_rescale_policy }} // namespace detail::get_rescale_policy #endif // DOXYGEN_NO_DETAIL -template +template +< + typename Point, + typename CSTag = typename geometry::cs_tag::type +> struct rescale_policy_type : public detail::get_rescale_policy::rescale_policy_type < @@ -258,8 +263,8 @@ struct rescale_policy_type && boost::is_same < - typename geometry::coordinate_system::type, - geometry::cs::cartesian + CSTag, + geometry::cartesian_tag >::value #else false @@ -283,6 +288,7 @@ template < typename Geometry1, typename Geometry2, + typename CSTag = typename geometry::cs_tag::type, typename Tag1 = typename tag_cast < typename tag::type, @@ -313,12 +319,14 @@ struct rescale_overlay_policy_type template < typename Geometry1, - typename Geometry2 + typename Geometry2, + typename CSTag > -struct rescale_overlay_policy_type +struct rescale_overlay_policy_type : public rescale_policy_type < - typename geometry::point_type::type + typename geometry::point_type::type, + CSTag > {}; From 147c5711c04b7d3c996a2dad34ef2532d50fe378 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 24 Jun 2019 12:17:52 +0200 Subject: [PATCH 46/68] [strategies] Implement index/rtree (umbrella) strategies. --- .../geometry/strategies/cartesian/index.hpp | 197 ++++++++++++++++ .../geometry/strategies/geographic/index.hpp | 216 ++++++++++++++++++ include/boost/geometry/strategies/index.hpp | 71 ++++++ .../geometry/strategies/spherical/index.hpp | 198 ++++++++++++++++ 4 files changed, 682 insertions(+) create mode 100644 include/boost/geometry/strategies/cartesian/index.hpp create mode 100644 include/boost/geometry/strategies/geographic/index.hpp create mode 100644 include/boost/geometry/strategies/index.hpp create mode 100644 include/boost/geometry/strategies/spherical/index.hpp diff --git a/include/boost/geometry/strategies/cartesian/index.hpp b/include/boost/geometry/strategies/cartesian/index.hpp new file mode 100644 index 000000000..80b79bf31 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/index.hpp @@ -0,0 +1,197 @@ +// 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_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/geographic/index.hpp b/include/boost/geometry/strategies/geographic/index.hpp new file mode 100644 index 000000000..202f0620d --- /dev/null +++ b/include/boost/geometry/strategies/geographic/index.hpp @@ -0,0 +1,216 @@ +// 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 // backward compatibility +#include +#include +#include +#include // backward compatibility +#include // backward compatibility +#include +#include +#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/index.hpp b/include/boost/geometry/strategies/index.hpp new file mode 100644 index 000000000..049b29c5b --- /dev/null +++ b/include/boost/geometry/strategies/index.hpp @@ -0,0 +1,71 @@ +// 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_INDEX_HPP +#define BOOST_GEOMETRY_STRATEGIES_INDEX_HPP + + +#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_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THESE_TYPES + , (types) + );*/ + + 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_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THESE_TYPES + , (types) + );*/ + + 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/spherical/index.hpp b/include/boost/geometry/strategies/spherical/index.hpp new file mode 100644 index 000000000..cd1734e94 --- /dev/null +++ b/include/boost/geometry/strategies/spherical/index.hpp @@ -0,0 +1,198 @@ +// 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_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 From cf6d5b4618d08a6f7dffaa79b2602ea7dfc14132 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 24 Jun 2019 12:18:45 +0200 Subject: [PATCH 47/68] [index] Allow passing strategy into the rtree with bgi::parameters<>. --- .../index/detail/algorithms/bounds.hpp | 186 +++++++++++++--- .../algorithms/intersection_content.hpp | 44 +++- .../geometry/index/detail/bounded_view.hpp | 146 ++++++++++--- .../index/detail/distance_predicates.hpp | 187 ++++++++++++++-- .../geometry/index/detail/predicates.hpp | 200 +++++++++++------- .../rtree/linear/redistribute_elements.hpp | 43 +++- .../geometry/index/detail/rtree/node/node.hpp | 20 +- .../geometry/index/detail/rtree/options.hpp | 19 ++ .../index/detail/rtree/pack_create.hpp | 31 +-- .../rtree/quadratic/redistribute_elements.hpp | 40 ++-- .../index/detail/rtree/query_iterators.hpp | 18 +- .../detail/rtree/rstar/choose_next_node.hpp | 45 ++-- .../index/detail/rtree/rstar/insert.hpp | 57 ++++- .../rtree/rstar/redistribute_elements.hpp | 78 ++++--- .../detail/rtree/utilities/are_boxes_ok.hpp | 23 +- .../detail/rtree/visitors/children_box.hpp | 21 +- .../index/detail/rtree/visitors/count.hpp | 39 ++-- .../detail/rtree/visitors/distance_query.hpp | 58 +++-- .../index/detail/rtree/visitors/insert.hpp | 20 +- .../index/detail/rtree/visitors/remove.hpp | 20 +- .../detail/rtree/visitors/spatial_query.hpp | 54 ++++- .../geometry/index/detail/translator.hpp | 41 +++- include/boost/geometry/index/equal_to.hpp | 119 +++++++++-- include/boost/geometry/index/parameters.hpp | 74 +++++++ include/boost/geometry/index/rtree.hpp | 65 ++++-- 25 files changed, 1277 insertions(+), 371 deletions(-) diff --git a/include/boost/geometry/index/detail/algorithms/bounds.hpp b/include/boost/geometry/index/detail/algorithms/bounds.hpp index a62fda070..2a0fa9ced 100644 --- a/include/boost/geometry/index/detail/algorithms/bounds.hpp +++ b/include/boost/geometry/index/detail/algorithms/bounds.hpp @@ -4,6 +4,10 @@ // // 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. +// 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) @@ -13,9 +17,11 @@ #include -namespace boost { namespace geometry { namespace index { namespace detail { +namespace boost { namespace geometry { namespace index { namespace detail +{ -namespace dispatch { +namespace dispatch +{ template ::type> struct bounds { - static inline void apply(Geometry const& g, Bounds & b) + template + static inline void apply(Geometry const& g, Bounds & b, Strategy const& ) { geometry::convert(g, b); } @@ -32,59 +39,184 @@ struct bounds template struct bounds { - static inline void apply(Geometry const& g, Bounds & b) + template + static inline void apply(Geometry const& g, Bounds & b, Strategy const& s) { - index::detail::bounded_view v(g); + index::detail::bounded_view v(g, s); geometry::convert(v, b); } }; + } // namespace dispatch -template -inline void bounds(Geometry const& g, Bounds & b) + +template +inline void bounds(Geometry const& g, Bounds & b, Strategy const& s) { concepts::check_concepts_and_equal_dimensions(); - dispatch::bounds::apply(g, b); + dispatch::bounds::apply(g, b, s); } -namespace dispatch { -template ::type, typename TagGeometry = typename geometry::tag::type> -struct return_ref_or_bounds +struct expand { - typedef Geometry const& result_type; + // STATIC ASSERT +}; - static inline result_type apply(Geometry const& g) +template +struct expand +{ + static inline void apply(Bounds & b, Geometry const& g) { - return g; + geometry::expand(b, g); + } + + template + static inline void apply(Bounds & b, Geometry const& g, Strategy const& ) + { + geometry::expand(b, g, typename Strategy::expand_point_strategy_type()); } }; -template -struct return_ref_or_bounds +template +struct expand { - typedef typename point_type::type point_type; - typedef geometry::model::box bounds_type; - typedef index::detail::bounded_view result_type; - - static inline result_type apply(Geometry const& g) + static inline void apply(Bounds & b, Geometry const& g) { - return result_type(g); + geometry::expand(b, g); + } + + template + static inline void apply(Bounds & b, Geometry const& g, Strategy const& ) + { + geometry::expand(b, g, typename Strategy::expand_box_strategy_type()); } }; +template +struct expand +{ + static inline void apply(Bounds & b, Geometry const& g) + { + geometry::expand(b, g); + } + + 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()); + } +}; + + } // namespace dispatch -template -inline -typename dispatch::return_ref_or_bounds::result_type -return_ref_or_bounds(Geometry const& g) + +template +inline void expand(Bounds & b, Geometry const& g, Strategy const& s) { - return dispatch::return_ref_or_bounds::apply(g); + dispatch::expand::apply(b, g, s); } +template +inline void expand(Bounds & b, Geometry const& g, default_strategy const& ) +{ + dispatch::expand::apply(b, g); +} + + +namespace dispatch +{ + + +template ::type, + typename TagBounds = typename geometry::tag::type> +struct covered_by_bounds +{}; + +template +struct covered_by_bounds +{ + static inline bool apply(Geometry const& g, Bounds & b) + { + return geometry::covered_by(g, b); + } + + template + static inline bool apply(Geometry const& g, Bounds & b, Strategy const&) + { + return geometry::covered_by(g, b, typename Strategy::covered_by_point_box_strategy_type()); + } +}; + +template +struct covered_by_bounds +{ + static inline bool apply(Geometry const& g, Bounds & b) + { + return geometry::covered_by(g, b); + } + + template + static inline bool apply(Geometry const& g, Bounds & b, Strategy const&) + { + return geometry::covered_by(g, b, typename Strategy::covered_by_box_box_strategy_type()); + } +}; + +template +struct covered_by_bounds +{ + static inline bool apply(Geometry const& g, Bounds & b) + { + typedef typename point_type::type point_type; + typedef geometry::model::box bounds_type; + typedef index::detail::bounded_view view_type; + + return geometry::covered_by(view_type(g, default_strategy()), b); + } + + template + static inline bool apply(Geometry const& g, Bounds & b, Strategy const& strategy) + { + typedef typename point_type::type point_type; + 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()); + } +}; + + +} // namespace dispatch + + +template +inline bool covered_by_bounds(Geometry const& g, Bounds & b, Strategy const& s) +{ + return dispatch::covered_by_bounds::apply(g, b, s); +} + +template +inline bool covered_by_bounds(Geometry const& g, Bounds & b, default_strategy const& ) +{ + return dispatch::covered_by_bounds::apply(g, b); +} + + }}}} // namespace boost::geometry::index::detail + #endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP diff --git a/include/boost/geometry/index/detail/algorithms/intersection_content.hpp b/include/boost/geometry/index/detail/algorithms/intersection_content.hpp index b8ef9e716..9519162b8 100644 --- a/include/boost/geometry/index/detail/algorithms/intersection_content.hpp +++ b/include/boost/geometry/index/detail/algorithms/intersection_content.hpp @@ -4,6 +4,10 @@ // // 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. +// 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) @@ -18,18 +22,32 @@ namespace boost { namespace geometry { namespace index { namespace detail { -/** - * \brief Compute the area of the intersection of b1 and b2 - */ -template -inline typename default_content_result::type intersection_content(Box const& box1, Box const& box2) +// Util to distinguish between default and non-default index strategy +template +inline bool disjoint_box_box(Box const& box1, Box const& box2, Strategy const& strategy) { - typedef typename strategy::disjoint::services::default_strategy - < - Box, Box - >::type strategy_type; + return geometry::detail::disjoint::disjoint_box_box(box1, box2, + typename Strategy::disjoint_box_box_strategy_type()); +} - bool const intersects = ! geometry::detail::disjoint::disjoint_box_box(box1, box2, strategy_type()); +template +inline bool disjoint_box_box(Box const& box1, Box const& box2, default_strategy const& ) +{ + typedef typename strategy::disjoint::services::default_strategy::type strategy_type; + return geometry::detail::disjoint::disjoint_box_box(box1, box2, strategy_type()); +} + +/** + * \brief Compute the area, volume, ... of the intersection of b1 and b2 + */ +template +inline typename default_content_result::type intersection_content(Box const& box1, Box const& box2, Strategy const& strategy) +{ + bool const intersects = ! index::detail::disjoint_box_box(box1, box2, strategy); + + // NOTE: the code below may be inconsistent with the disjoint_box_box() + // however intersection_box_box checks if the boxes intersect on the fly so it should be ok + // but this also means that disjoint_box_box() is probably not needed if ( intersects ) { @@ -46,6 +64,12 @@ inline typename default_content_result::type intersection_content(Box const return 0; } +template +inline typename default_content_result::type intersection_content(Box const& box1, Box const& box2) +{ + return intersection_content(box1, box2, default_strategy()); +} + }}}} // namespace boost::geometry::index::detail #endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP diff --git a/include/boost/geometry/index/detail/bounded_view.hpp b/include/boost/geometry/index/detail/bounded_view.hpp index e5f489d76..f6df2fa79 100644 --- a/include/boost/geometry/index/detail/bounded_view.hpp +++ b/include/boost/geometry/index/detail/bounded_view.hpp @@ -5,6 +5,10 @@ // // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -12,35 +16,59 @@ #ifndef BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP #define BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP +#include + #include +#include + namespace boost { namespace geometry { namespace index { namespace detail { -template ::type, - typename BoundingTag = typename geometry::tag::type, - typename CSystem = typename geometry::coordinate_system::type> -struct bounded_view + +template +struct bounded_view_base_cs_tag +{ + typedef typename Strategy::cs_tag type; +}; + +template +struct bounded_view_base_cs_tag + : geometry::cs_tag +{}; + + +template +< + typename Geometry, + typename BoundingGeometry, + typename Strategy, + typename Tag = typename geometry::tag::type, + typename BoundingTag = typename geometry::tag::type, + typename CSTag = typename bounded_view_base_cs_tag + < + Geometry, BoundingGeometry, Strategy + >::type +> +struct bounded_view_base { BOOST_MPL_ASSERT_MSG( (false), NOT_IMPLEMENTED_FOR_THOSE_GEOMETRIES, - (BoundingTag, Tag)); + (types)); }; // Segment -> Box -template -struct bounded_view +template +struct bounded_view_base { public: typedef typename geometry::coordinate_type::type coordinate_type; - explicit bounded_view(Segment const& segment) + bounded_view_base(Segment const& segment, Strategy const& ) : m_segment(segment) {} @@ -64,15 +92,27 @@ private: Segment const& m_segment; }; -template -struct bounded_view +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; - explicit bounded_view(Segment const& segment) + bounded_view_base(Segment const& segment, Strategy const& strategy) { - geometry::envelope(segment, m_box); + envelope(segment, strategy); } template @@ -93,13 +133,13 @@ private: // Box -> Box -template -struct bounded_view +template +struct bounded_view_base { public: typedef typename geometry::coordinate_type::type coordinate_type; - explicit bounded_view(BoxIn const& box) + bounded_view_base(BoxIn const& box, Strategy const& ) : m_box(box) {} @@ -123,13 +163,13 @@ private: // Point -> Box -template -struct bounded_view +template +struct bounded_view_base { public: typedef typename geometry::coordinate_type::type coordinate_type; - explicit bounded_view(Point const& point) + bounded_view_base(Point const& point, Strategy const& ) : m_point(point) {} @@ -151,6 +191,52 @@ private: Point const& m_point; }; + +template ::type, + typename BoundingTag = typename geometry::tag::type> +struct bounded_view + : bounded_view_base +{ + typedef bounded_view_base base_type; + + bounded_view(Geometry const& geometry, Strategy const& strategy) + : base_type(geometry, strategy) + {} +}; + +template +struct bounded_view + : bounded_view_base + < + Geometry, + BoundingGeometry, + typename strategy::index::services::default_strategy::type + > +{ + typedef typename strategy::index::services::default_strategy + < + Geometry + >::type strategy_type; + + typedef bounded_view_base + < + Geometry, + BoundingGeometry, + strategy_type + > base_type; + + explicit bounded_view(Geometry const& geometry, default_strategy const& ) + : base_type(geometry, strategy_type()) + {} +}; + + }} // namespace index::detail // XXX -> Box @@ -159,23 +245,23 @@ private: namespace traits { -template -struct tag< index::detail::bounded_view > +template +struct tag< index::detail::bounded_view > { typedef box_tag type; }; -template -struct point_type< index::detail::bounded_view > +template +struct point_type< index::detail::bounded_view > { typedef typename point_type::type type; }; -template -struct indexed_access, +template +struct indexed_access, min_corner, Dimension> { - typedef index::detail::bounded_view box_type; + typedef index::detail::bounded_view box_type; typedef typename geometry::coordinate_type::type coordinate_type; static inline coordinate_type get(box_type const& b) @@ -189,11 +275,11 @@ struct indexed_access -struct indexed_access, +template +struct indexed_access, max_corner, Dimension> { - typedef index::detail::bounded_view box_type; + typedef index::detail::bounded_view box_type; typedef typename geometry::coordinate_type::type coordinate_type; static inline coordinate_type get(box_type const& b) diff --git a/include/boost/geometry/index/detail/distance_predicates.hpp b/include/boost/geometry/index/detail/distance_predicates.hpp index 9a9371df9..446797450 100644 --- a/include/boost/geometry/index/detail/distance_predicates.hpp +++ b/include/boost/geometry/index/detail/distance_predicates.hpp @@ -5,6 +5,10 @@ // // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -92,65 +96,212 @@ struct relation< to_furthest > static inline T & value(to_furthest & r) { return r.value; } }; +// ------------------------------------------------------------------ // + +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 +{}; + +template +< + typename G1, typename G2 +> +struct comparable_distance_call + : comparable_distance_call_base +{}; + // ------------------------------------------------------------------ // // calculate_distance // ------------------------------------------------------------------ // -template +template struct calculate_distance { BOOST_MPL_ASSERT_MSG((false), INVALID_PREDICATE_OR_TAG, (calculate_distance)); }; // this handles nearest() with default Point parameter, to_nearest() and bounds -template -struct calculate_distance< predicates::nearest, Indexable, Tag > +template +struct calculate_distance< predicates::nearest, Indexable, Strategy, Tag> { typedef detail::relation relation; - typedef typename relation::value_type point_type; - typedef typename geometry::default_comparable_distance_result::type result_type; + typedef comparable_distance_call + < + typename relation::value_type, + Indexable, + Strategy + > call_type; + typedef typename call_type::result_type result_type; - static inline bool apply(predicates::nearest const& p, Indexable const& i, result_type & result) + static inline bool apply(predicates::nearest const& p, Indexable const& i, + Strategy const& s, result_type & result) { - result = geometry::comparable_distance(relation::value(p.point_or_relation), i); + result = call_type::apply(relation::value(p.point_or_relation), i, s); return true; } }; -template -struct calculate_distance< predicates::nearest< to_centroid >, Indexable, value_tag> +template +struct calculate_distance< predicates::nearest< to_centroid >, Indexable, Strategy, value_tag> { typedef Point point_type; - typedef typename geometry::default_comparable_distance_result::type result_type; + typedef typename geometry::default_comparable_distance_result + < + point_type, Indexable + >::type result_type; - static inline bool apply(predicates::nearest< to_centroid > const& p, Indexable const& i, result_type & result) + static inline bool apply(predicates::nearest< to_centroid > const& p, Indexable const& i, + Strategy const& , result_type & result) { result = index::detail::comparable_distance_centroid(p.point_or_relation.value, i); return true; } }; -template -struct calculate_distance< predicates::nearest< to_furthest >, Indexable, value_tag> +template +struct calculate_distance< predicates::nearest< to_furthest >, Indexable, Strategy, value_tag> { typedef Point point_type; - typedef typename geometry::default_comparable_distance_result::type result_type; + typedef typename geometry::default_comparable_distance_result + < + point_type, Indexable + >::type result_type; - static inline bool apply(predicates::nearest< to_furthest > const& p, Indexable const& i, result_type & result) + static inline bool apply(predicates::nearest< to_furthest > const& p, Indexable const& i, + Strategy const& , result_type & result) { result = index::detail::comparable_distance_far(p.point_or_relation.value, i); return true; } }; -template -struct calculate_distance< predicates::path, Indexable, Tag> +template +struct calculate_distance< predicates::path, Indexable, Strategy, Tag> { typedef typename index::detail::default_path_intersection_distance_type< Indexable, SegmentOrLinestring >::type result_type; - static inline bool apply(predicates::path const& p, Indexable const& i, result_type & result) + static inline bool apply(predicates::path const& p, Indexable const& i, + Strategy const& , result_type & result) { return index::detail::path_intersection(i, p.geometry, result); } diff --git a/include/boost/geometry/index/detail/predicates.hpp b/include/boost/geometry/index/detail/predicates.hpp index 72c6c661b..ba564f8c5 100644 --- a/include/boost/geometry/index/detail/predicates.hpp +++ b/include/boost/geometry/index/detail/predicates.hpp @@ -4,6 +4,10 @@ // // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -128,8 +132,8 @@ struct predicate_check template struct predicate_check, value_tag> { - template - static inline bool apply(predicates::satisfies const& p, Value const& v, Indexable const&) + template + static inline bool apply(predicates::satisfies const& p, Value const& v, Indexable const& , Strategy const&) { return p.fun(v); } @@ -138,8 +142,8 @@ struct predicate_check, value_tag> template struct predicate_check, value_tag> { - template - static inline bool apply(predicates::satisfies const& p, Value const& v, Indexable const&) + template + static inline bool apply(predicates::satisfies const& p, Value const& v, Indexable const& , Strategy const&) { return !p.fun(v); } @@ -156,8 +160,8 @@ struct spatial_predicate_call template <> struct spatial_predicate_call { - template - static inline bool apply(G1 const& g1, G2 const& g2) + template + static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::within(g2, g1); } @@ -166,8 +170,8 @@ struct spatial_predicate_call template <> struct spatial_predicate_call { - template - static inline bool apply(G1 const& g1, G2 const& g2) + template + static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::covered_by(g1, g2); } @@ -176,8 +180,8 @@ struct spatial_predicate_call template <> struct spatial_predicate_call { - template - static inline bool apply(G1 const& g1, G2 const& g2) + template + static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::covered_by(g2, g1); } @@ -186,28 +190,60 @@ struct spatial_predicate_call template <> struct spatial_predicate_call { - template - static inline bool apply(G1 const& g1, G2 const& g2) + template + static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::disjoint(g1, g2); } }; +// TEMP: used to implement CS-specific intersects predicate for certain +// combinations of geometries until umbrella strategies are implemented +template +< + typename G1, typename G2, + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type +> +struct spatial_predicate_intersects +{ + template + static inline bool apply(G1 const& g1, G2 const& g2, S const&) + { + return geometry::intersects(g1, g2); + } +}; +// TEMP: used in within and relate +template +struct spatial_predicate_intersects +{ + static inline bool apply(G1 const& g1, G2 const& g2, default_strategy const&) + { + return geometry::intersects(g1, g2); + } + + template + static inline bool apply(G1 const& g1, G2 const& g2, S const& ) + { + return geometry::intersects(g1, g2, typename S::covered_by_point_box_strategy_type()); + } +}; + template <> struct spatial_predicate_call { - template - static inline bool apply(G1 const& g1, G2 const& g2) + template + static inline bool apply(G1 const& g1, G2 const& g2, S const& s) { - return geometry::intersects(g1, g2); + return spatial_predicate_intersects::apply(g1, g2, s); } }; template <> struct spatial_predicate_call { - template - static inline bool apply(G1 const& g1, G2 const& g2) + template + static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::overlaps(g1, g2); } @@ -216,8 +252,8 @@ struct spatial_predicate_call template <> struct spatial_predicate_call { - template - static inline bool apply(G1 const& g1, G2 const& g2) + template + static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::touches(g1, g2); } @@ -226,8 +262,8 @@ struct spatial_predicate_call template <> struct spatial_predicate_call { - template - static inline bool apply(G1 const& g1, G2 const& g2) + template + static inline bool apply(G1 const& g1, G2 const& g2, S const&) { return geometry::within(g1, g2); } @@ -241,10 +277,10 @@ struct predicate_check, valu { typedef predicates::spatial_predicate Pred; - template - static inline bool apply(Pred const& p, Value const&, Indexable const& i) + template + static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { - return spatial_predicate_call::apply(i, p.geometry); + return spatial_predicate_call::apply(i, p.geometry, s); } }; @@ -254,10 +290,10 @@ struct predicate_check, value { typedef predicates::spatial_predicate Pred; - template - static inline bool apply(Pred const& p, Value const&, Indexable const& i) + template + static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { - return !spatial_predicate_call::apply(i, p.geometry); + return !spatial_predicate_call::apply(i, p.geometry, s); } }; @@ -266,8 +302,8 @@ struct predicate_check, value template struct predicate_check, value_tag> { - template - static inline bool apply(predicates::nearest const&, Value const&, Box const&) + template + static inline bool apply(predicates::nearest const&, Value const&, Box const&, Strategy const&) { return true; } @@ -276,8 +312,8 @@ struct predicate_check, value_tag> template struct predicate_check, value_tag> { - template - static inline bool apply(predicates::path const&, Value const&, Box const&) + template + static inline bool apply(predicates::path const&, Value const&, Box const&, Strategy const&) { return true; } @@ -290,8 +326,8 @@ struct predicate_check, value_tag> template struct predicate_check, bounds_tag> { - template - static bool apply(predicates::satisfies const&, Value const&, Box const&) + template + static bool apply(predicates::satisfies const&, Value const&, Box const&, Strategy const&) { return true; } @@ -317,10 +353,10 @@ struct predicate_check, boun { typedef predicates::spatial_predicate Pred; - template - static inline bool apply(Pred const& p, Value const&, Indexable const& i) + template + static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { - return spatial_predicate_call::apply(i, p.geometry); + return spatial_predicate_call::apply(i, p.geometry, s); } }; @@ -330,10 +366,10 @@ struct predicate_check Pred; - template - static inline bool apply(Pred const& p, Value const&, Indexable const& i) + template + static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { - return spatial_predicate_call::apply(i, p.geometry); + return spatial_predicate_call::apply(i, p.geometry, s); } }; @@ -343,10 +379,10 @@ struct predicate_check Pred; - template - static inline bool apply(Pred const& p, Value const&, Indexable const& i) + template + static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { - return spatial_predicate_call::apply(i, p.geometry); + return spatial_predicate_call::apply(i, p.geometry, s); } }; @@ -356,10 +392,10 @@ struct predicate_check Pred; - template - static inline bool apply(Pred const& p, Value const&, Indexable const& i) + template + static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { - return !spatial_predicate_call::apply(i, p.geometry); + return !spatial_predicate_call::apply(i, p.geometry, s); } }; @@ -381,10 +417,10 @@ struct predicate_check, bound { typedef predicates::spatial_predicate Pred; - template - static inline bool apply(Pred const& p, Value const&, Indexable const& i) + template + static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { - return !spatial_predicate_call::apply(i, p.geometry); + return !spatial_predicate_call::apply(i, p.geometry, s); } }; @@ -394,8 +430,8 @@ struct predicate_check Pred; - template - static inline bool apply(Pred const& , Value const&, Indexable const& ) + template + static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&) { return true; } @@ -407,8 +443,8 @@ struct predicate_check Pred; - template - static inline bool apply(Pred const& , Value const&, Indexable const& ) + template + static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&) { return true; } @@ -420,10 +456,10 @@ struct predicate_check Pred; - template - static inline bool apply(Pred const& p, Value const&, Indexable const& i) + template + static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s) { - return !spatial_predicate_call::apply(i, p.geometry); + return !spatial_predicate_call::apply(i, p.geometry, s); } }; @@ -433,8 +469,8 @@ struct predicate_check Pred; - template - static inline bool apply(Pred const& , Value const&, Indexable const& ) + template + static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&) { return true; } @@ -446,8 +482,8 @@ struct predicate_check Pred; - template - static inline bool apply(Pred const& p, Value const&, Indexable const& i) + template + static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const&) { return !spatial_predicate_call::apply(i, p.geometry); } @@ -458,8 +494,8 @@ struct predicate_check struct predicate_check, bounds_tag> { - template - static inline bool apply(predicates::nearest const&, Value const&, Box const&) + template + static inline bool apply(predicates::nearest const&, Value const&, Box const&, Strategy const&) { return true; } @@ -468,8 +504,8 @@ struct predicate_check, bounds_tag> template struct predicate_check, bounds_tag> { - template - static inline bool apply(predicates::path const&, Value const&, Box const&) + template + static inline bool apply(predicates::path const&, Value const&, Box const&, Strategy const&) { return true; } @@ -600,23 +636,23 @@ struct predicates_element< I, boost::tuples::cons > template struct predicates_check_tuple { - template - static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i) + template + static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i, Strategy const& s) { - return - predicate_check< - typename boost::tuples::element::type, - Tag - >::apply(boost::get(p), v, i) && - predicates_check_tuple::apply(p, v, i); + return predicate_check + < + typename boost::tuples::element::type, + Tag + >::apply(boost::get(p), v, i, s) + && predicates_check_tuple::apply(p, v, i, s); } }; template struct predicates_check_tuple { - template - static inline bool apply(TuplePredicates const& , Value const& , Indexable const& ) + template + static inline bool apply(TuplePredicates const& , Value const& , Indexable const& , Strategy const& ) { return true; } @@ -628,10 +664,10 @@ struct predicates_check_impl static const bool check = First < 1 && Last <= 1 && First <= Last; BOOST_MPL_ASSERT_MSG((check), INVALID_INDEXES, (predicates_check_impl)); - template - static inline bool apply(Predicate const& p, Value const& v, Indexable const& i) + template + static inline bool apply(Predicate const& p, Value const& v, Indexable const& i, Strategy const& s) { - return predicate_check::apply(p, v, i); + return predicate_check::apply(p, v, i, s); } }; @@ -685,21 +721,21 @@ struct predicates_check_impl< static const bool check = First < pred_len && Last <= pred_len && First <= Last; BOOST_MPL_ASSERT_MSG((check), INVALID_INDEXES, (predicates_check_impl)); - template - static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i) + template + static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i, Strategy const& s) { return predicates_check_tuple< predicates_type, Tag, First, Last - >::apply(p, v, i); + >::apply(p, v, i, s); } }; -template -inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i) +template +inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i, Strategy const& s) { return detail::predicates_check_impl - ::apply(p, v, i); + ::apply(p, v, i, s); } // ------------------------------------------------------------------ // diff --git a/include/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp b/include/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp index c794a6426..a0635acab 100644 --- a/include/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp +++ b/include/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp @@ -5,6 +5,10 @@ // Copyright (c) 2008 Federico J. Fernandez. // 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. +// 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) @@ -15,6 +19,7 @@ #include #include +#include #include #include @@ -90,7 +95,11 @@ struct find_greatest_normalized_separation typedef typename geometry::point_type::type point_type; typedef geometry::model::box bounds_type; - typedef index::detail::bounded_view bounded_view_type; + typedef index::detail::bounded_view + < + indexable_type, bounds_type, + typename index::detail::strategy_type::type + > bounded_view_type; static inline void apply(Elements const& elements, Parameters const& parameters, @@ -103,8 +112,12 @@ struct find_greatest_normalized_separation BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected number of elements"); BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements"); + typename index::detail::strategy_type::type const& + strategy = index::detail::get_strategy(parameters); + // find the lowest low, highest high - bounded_view_type bounded_indexable_0(rtree::element_indexable(elements[0], translator)); + bounded_view_type bounded_indexable_0(rtree::element_indexable(elements[0], translator), + strategy); coordinate_type lowest_low = geometry::get(bounded_indexable_0); coordinate_type highest_high = geometry::get(bounded_indexable_0); @@ -113,7 +126,8 @@ struct find_greatest_normalized_separation size_t lowest_high_index = 0; for ( size_t i = 1 ; i < elements_count ; ++i ) { - bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator)); + bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator), + strategy); coordinate_type min_coord = geometry::get(bounded_indexable); coordinate_type max_coord = geometry::get(bounded_indexable); @@ -132,11 +146,13 @@ struct find_greatest_normalized_separation // find the highest low size_t highest_low_index = lowest_high_index == 0 ? 1 : 0; - bounded_view_type bounded_indexable_hl(rtree::element_indexable(elements[highest_low_index], translator)); + bounded_view_type bounded_indexable_hl(rtree::element_indexable(elements[highest_low_index], translator), + strategy); coordinate_type highest_low = geometry::get(bounded_indexable_hl); for ( size_t i = highest_low_index ; i < elements_count ; ++i ) { - bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator)); + bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator), + strategy); coordinate_type min_coord = geometry::get(bounded_indexable); if ( highest_low < min_coord && i != lowest_high_index ) @@ -329,6 +345,9 @@ struct redistribute_elements::type indexable_type; typedef typename index::detail::default_content_result::type content_type; + typename index::detail::strategy_type::type const& + strategy = index::detail::get_strategy(parameters); + elements_type & elements1 = rtree::elements(n); elements_type & elements2 = rtree::elements(second_node); const size_t elements1_count = parameters.get_max_elements() + 1; @@ -357,8 +376,10 @@ struct redistribute_elements -inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr) +template +inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr, + Strategy const& strategy) { Box result; @@ -57,11 +62,11 @@ inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr) if ( first == last ) return result; - detail::bounds(element_indexable(*first, tr), result); + detail::bounds(element_indexable(*first, tr), result, strategy); ++first; for ( ; first != last ; ++first ) - geometry::expand(result, element_indexable(*first, tr)); + detail::expand(result, element_indexable(*first, tr), strategy); return result; } @@ -71,15 +76,16 @@ inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr) // This ensures that leafs bounds correspond to the stored elements. // NOTE: this is done only if the Indexable is not a Box // in the future don't do it also for NSphere -template -inline Box values_box(FwdIter first, FwdIter last, Translator const& tr) +template +inline Box values_box(FwdIter first, FwdIter last, Translator const& tr, + Strategy const& strategy) { typedef typename std::iterator_traits::value_type element_type; BOOST_MPL_ASSERT_MSG((is_leaf_element::value), SHOULD_BE_CALLED_ONLY_FOR_LEAF_ELEMENTS, (element_type)); - Box result = elements_box(first, last, tr); + Box result = elements_box(first, last, tr, strategy); #ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON if (BOOST_GEOMETRY_CONDITION(( diff --git a/include/boost/geometry/index/detail/rtree/options.hpp b/include/boost/geometry/index/detail/rtree/options.hpp index ff772834d..ba104b0c2 100644 --- a/include/boost/geometry/index/detail/rtree/options.hpp +++ b/include/boost/geometry/index/detail/rtree/options.hpp @@ -4,6 +4,10 @@ // // 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. +// 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) @@ -148,6 +152,21 @@ struct options_type< index::dynamic_rstar > > type; }; +template +struct options_type< index::parameters > + : options_type +{ + typedef typename options_type::type opt; + typedef options< + index::parameters, + typename opt::insert_tag, + typename opt::choose_next_node_tag, + typename opt::split_tag, + typename opt::redistribute_tag, + typename opt::node_tag + > type; +}; + }} // namespace detail::rtree }}} // namespace boost::geometry::index diff --git a/include/boost/geometry/index/detail/rtree/pack_create.hpp b/include/boost/geometry/index/detail/rtree/pack_create.hpp index 78e4712d2..2d212949a 100644 --- a/include/boost/geometry/index/detail/rtree/pack_create.hpp +++ b/include/boost/geometry/index/detail/rtree/pack_create.hpp @@ -4,6 +4,10 @@ // // Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -137,6 +141,7 @@ class pack typedef typename geometry::coordinate_type::type coordinate_type; typedef typename detail::default_content_result::type content_type; typedef typename Options::parameters_type parameters_type; + typedef typename detail::strategy_type::type strategy_type; static const std::size_t dimension = geometry::dimension::value; typedef typename rtree::container_from_elements_type< @@ -165,7 +170,7 @@ public: values_count = static_cast(diff); entries.reserve(values_count); - expandable_box hint_box; + expandable_box hint_box(detail::get_strategy(parameters)); for ( ; first != last ; ++first ) { // NOTE: support for iterators not returning true references adapted @@ -194,19 +199,19 @@ public: } private: - template + template class expandable_box { public: - expandable_box() - : m_initialized(false) + explicit expandable_box(Strategy const& strategy) + : m_strategy(strategy), m_initialized(false) {} template - explicit expandable_box(Indexable const& indexable) - : m_initialized(true) + explicit expandable_box(Indexable const& indexable, Strategy const& strategy) + : m_strategy(strategy), m_initialized(true) { - detail::bounds(indexable, m_box); + detail::bounds(indexable, m_box, m_strategy); } template @@ -217,12 +222,12 @@ private: // it's guaranteed that the Box will be initialized // only for Points, Boxes and Segments but that's ok // since only those Geometries can be stored - detail::bounds(indexable, m_box); + detail::bounds(indexable, m_box, m_strategy); m_initialized = true; } else { - geometry::expand(m_box, indexable); + detail::expand(m_box, indexable, m_strategy); } } @@ -238,8 +243,9 @@ private: } private: - bool m_initialized; BoxType m_box; + Strategy const& m_strategy; + bool m_initialized; }; struct subtree_elements_counts @@ -273,7 +279,8 @@ private: // calculate values box and copy values // initialize the box explicitly to avoid GCC-4.4 uninitialized variable warnings with O2 - expandable_box elements_box(translator(*(first->second))); + expandable_box elements_box(translator(*(first->second)), + detail::get_strategy(parameters)); rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C) for ( ++first ; first != last ; ++first ) { @@ -319,7 +326,7 @@ private: std::size_t nodes_count = calculate_nodes_count(values_count, subtree_counts); rtree::elements(in).reserve(nodes_count); // MAY THROW (A) // calculate values box and copy values - expandable_box elements_box; + expandable_box elements_box(detail::get_strategy(parameters)); per_level_packets(first, last, hint_box, values_count, subtree_counts, next_subtree_counts, rtree::elements(in), elements_box, diff --git a/include/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp b/include/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp index 1ee7554f0..9bec03a70 100644 --- a/include/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp +++ b/include/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp @@ -4,6 +4,10 @@ // // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -41,7 +45,11 @@ inline void pick_seeds(Elements const& elements, typedef typename rtree::element_indexable_type::type indexable_type; typedef Box box_type; typedef typename index::detail::default_content_result::type content_type; - typedef index::detail::bounded_view bounded_indexable_view; + typedef index::detail::bounded_view + < + indexable_type, box_type, + typename strategy_type::type + > bounded_indexable_view; const size_t elements_count = parameters.get_max_elements() + 1; BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "wrong number of elements"); @@ -59,11 +67,11 @@ inline void pick_seeds(Elements const& elements, indexable_type const& ind2 = rtree::element_indexable(elements[j], tr); box_type enlarged_box; - detail::bounds(ind1, enlarged_box); - geometry::expand(enlarged_box, ind2); + index::detail::bounds(ind1, enlarged_box, get_strategy(parameters)); + index::detail::expand(enlarged_box, ind2, get_strategy(parameters)); - bounded_indexable_view bounded_ind1(ind1); - bounded_indexable_view bounded_ind2(ind2); + bounded_indexable_view bounded_ind1(ind1, get_strategy(parameters)); + bounded_indexable_view bounded_ind2(ind2, get_strategy(parameters)); content_type free_content = ( index::detail::content(enlarged_box) - index::detail::content(bounded_ind1) ) - index::detail::content(bounded_ind2); @@ -134,8 +142,12 @@ struct redistribute_elements::type const& strategy, content_type & out_content_increase1, content_type & out_content_increase2) { typedef typename boost::iterator_value::type element_type; @@ -266,8 +282,8 @@ struct redistribute_elements class spatial_query_iterator { + typedef typename Options::parameters_type parameters_type; typedef visitors::spatial_query_incremental visitor_type; typedef typename visitor_type::node_pointer node_pointer; @@ -74,12 +75,12 @@ public: inline spatial_query_iterator() {} - inline spatial_query_iterator(Translator const& t, Predicates const& p) - : m_visitor(t, p) + inline spatial_query_iterator(parameters_type const& par, Translator const& t, Predicates const& p) + : m_visitor(par, t, p) {} - inline spatial_query_iterator(node_pointer root, Translator const& t, Predicates const& p) - : m_visitor(t, p) + inline spatial_query_iterator(node_pointer root, parameters_type const& par, Translator const& t, Predicates const& p) + : m_visitor(par, t, p) { m_visitor.initialize(root); } @@ -129,6 +130,7 @@ private: template class distance_query_iterator { + typedef typename Options::parameters_type parameters_type; typedef visitors::distance_query_incremental visitor_type; typedef typename visitor_type::node_pointer node_pointer; @@ -142,12 +144,12 @@ public: inline distance_query_iterator() {} - inline distance_query_iterator(Translator const& t, Predicates const& p) - : m_visitor(t, p) + inline distance_query_iterator(parameters_type const& par, Translator const& t, Predicates const& p) + : m_visitor(par, t, p) {} - inline distance_query_iterator(node_pointer root, Translator const& t, Predicates const& p) - : m_visitor(t, p) + inline distance_query_iterator(node_pointer root, parameters_type const& par, Translator const& t, Predicates const& p) + : m_visitor(par, t, p) { m_visitor.initialize(root); } diff --git a/include/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp b/include/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp index 2ac6eb27c..209f6ebb2 100644 --- a/include/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp +++ b/include/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp @@ -4,6 +4,10 @@ // // Copyright (c) 2011-2019 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -57,11 +61,16 @@ public: // children are leafs if ( node_relative_level <= 1 ) { - return choose_by_minimum_overlap_cost(children, indexable, parameters.get_overlap_cost_threshold()); + return choose_by_minimum_overlap_cost(children, indexable, + parameters.get_overlap_cost_threshold(), + index::detail::get_strategy(parameters)); } // children are internal nodes else - return choose_by_minimum_content_cost(children, indexable); + { + return choose_by_minimum_content_cost(children, indexable, + index::detail::get_strategy(parameters)); + } } private: @@ -79,10 +88,11 @@ private: } }; - template + template static inline size_t choose_by_minimum_overlap_cost(children_type const& children, Indexable const& indexable, - size_t overlap_cost_threshold) + size_t overlap_cost_threshold, + Strategy const& strategy) { const size_t children_count = children.size(); @@ -100,7 +110,7 @@ private: // expanded child node's box Box box_exp(ch_i.first); - geometry::expand(box_exp, indexable); + index::detail::expand(box_exp, indexable, strategy); // areas difference content_type content = index::detail::content(box_exp); @@ -131,7 +141,11 @@ private: } // calculate minimum or nearly minimum overlap cost - choosen_index = choose_by_minimum_overlap_cost_first_n(children, indexable, first_n_children_count, children_count, children_contents); + choosen_index = choose_by_minimum_overlap_cost_first_n(children, indexable, + first_n_children_count, + children_count, + children_contents, + strategy); } return choosen_index; @@ -143,12 +157,13 @@ private: || (p1.content_diff == p2.content_diff && (p1.content) < (p2.content)); } - template + template static inline size_t choose_by_minimum_overlap_cost_first_n(children_type const& children, Indexable const& indexable, size_t const first_n_children_count, size_t const children_count, - ChildrenContents const& children_contents) + ChildrenContents const& children_contents, + Strategy const& strategy) { BOOST_GEOMETRY_INDEX_ASSERT(first_n_children_count <= children_count, "unexpected value"); BOOST_GEOMETRY_INDEX_ASSERT(children_contents.size() == children_count, "unexpected number of elements"); @@ -170,7 +185,7 @@ private: Box box_exp(ch_i.first); // calculate expanded box of child node ch_i - geometry::expand(box_exp, indexable); + index::detail::expand(box_exp, indexable, strategy); content_type overlap_diff = 0; @@ -181,10 +196,10 @@ private: { child_type const& ch_j = children[j]; - content_type overlap_exp = index::detail::intersection_content(box_exp, ch_j.first); + content_type overlap_exp = index::detail::intersection_content(box_exp, ch_j.first, strategy); if ( overlap_exp < -std::numeric_limits::epsilon() || std::numeric_limits::epsilon() < overlap_exp ) { - overlap_diff += overlap_exp - index::detail::intersection_content(ch_i.first, ch_j.first); + overlap_diff += overlap_exp - index::detail::intersection_content(ch_i.first, ch_j.first, strategy); } } } @@ -205,8 +220,10 @@ private: return choosen_index; } - template - static inline size_t choose_by_minimum_content_cost(children_type const& children, Indexable const& indexable) + template + static inline size_t choose_by_minimum_content_cost(children_type const& children, + Indexable const& indexable, + Strategy const& strategy) { size_t children_count = children.size(); @@ -222,7 +239,7 @@ private: // expanded child node's box Box box_exp(ch_i.first); - geometry::expand(box_exp, indexable); + index::detail::expand(box_exp, indexable, strategy); // areas difference content_type content = index::detail::content(box_exp); diff --git a/include/boost/geometry/index/detail/rtree/rstar/insert.hpp b/include/boost/geometry/index/detail/rtree/rstar/insert.hpp index 0abf96ddf..73a5ccefc 100644 --- a/include/boost/geometry/index/detail/rtree/rstar/insert.hpp +++ b/include/boost/geometry/index/detail/rtree/rstar/insert.hpp @@ -4,6 +4,10 @@ // // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -21,6 +25,37 @@ namespace detail { namespace rtree { namespace visitors { namespace rstar { +// Utility to distinguish between default and non-default index strategy +template +struct comparable_distance_point_point +{ + typedef typename Strategy::comparable_distance_point_point_strategy_type strategy_type; + typedef typename geometry::comparable_distance_result + < + Point1, Point2, strategy_type + >::type result_type; + + static inline strategy_type get_strategy(Strategy const& strategy) + { + return strategy.get_comparable_distance_point_point_strategy(); + } +}; + +template +struct comparable_distance_point_point +{ + 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& ) + { + return strategy_type(); + } +}; + template class remove_elements_to_reinsert { @@ -46,10 +81,13 @@ public: typedef typename rtree::elements_type::type elements_type; typedef typename elements_type::value_type element_type; 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 typename - geometry::default_comparable_distance_result::type - comparable_distance_type; + typedef rstar::comparable_distance_point_point + < + point_type, point_type, strategy_type + > comparable_distance_pp; + typedef typename comparable_distance_pp::result_type comparable_distance_type; elements_type & elements = rtree::elements(n); @@ -74,13 +112,16 @@ 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)); + for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it ) { 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), + geometry::comparable_distance(node_center, element_center, cdist_strategy), *it)); // MAY THROW (V, E: copy) } @@ -246,13 +287,17 @@ struct level_insert_base inline void recalculate_aabb(Node const& n) const { base::m_traverse_data.current_element().first = - elements_box(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator); + elements_box(rtree::elements(n).begin(), rtree::elements(n).end(), + base::m_translator, + index::detail::get_strategy(base::m_parameters)); } inline void recalculate_aabb(leaf const& n) const { base::m_traverse_data.current_element().first = - values_box(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator); + values_box(rtree::elements(n).begin(), rtree::elements(n).end(), + base::m_translator, + index::detail::get_strategy(base::m_parameters)); } size_type result_relative_level; diff --git a/include/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp b/include/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp index 6a9261ba5..3894d7c99 100644 --- a/include/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp +++ b/include/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp @@ -4,6 +4,10 @@ // // Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -30,37 +34,42 @@ namespace detail { namespace rtree { namespace rstar { -template +template class element_axis_corner_less { typedef typename rtree::element_indexable_type::type indexable_type; typedef typename geometry::point_type::type point_type; typedef geometry::model::box bounds_type; - typedef index::detail::bounded_view bounded_view_type; + typedef typename index::detail::strategy_type::type strategy_type; + typedef index::detail::bounded_view + < + indexable_type, bounds_type, strategy_type + > bounded_view_type; public: - element_axis_corner_less(Translator const& tr) - : m_tr(tr) + element_axis_corner_less(Parameters const& parameters, Translator const& tr) + : m_strategy(index::detail::get_strategy(parameters)), m_tr(tr) {} bool operator()(Element const& e1, Element const& e2) const { - bounded_view_type bounded_ind1(rtree::element_indexable(e1, m_tr)); - bounded_view_type bounded_ind2(rtree::element_indexable(e2, m_tr)); + bounded_view_type bounded_ind1(rtree::element_indexable(e1, m_tr), m_strategy); + bounded_view_type bounded_ind2(rtree::element_indexable(e2, m_tr), m_strategy); return geometry::get(bounded_ind1) < geometry::get(bounded_ind2); } private: + strategy_type const& m_strategy; Translator const& m_tr; }; -template -class element_axis_corner_less +template +class element_axis_corner_less { public: - element_axis_corner_less(Translator const& tr) + element_axis_corner_less(Parameters const& parameters, Translator const& tr) : m_tr(tr) {} @@ -74,11 +83,11 @@ private: Translator const& m_tr; }; -template -class element_axis_corner_less +template +class element_axis_corner_less { public: - element_axis_corner_less(Translator const& tr) + element_axis_corner_less(Parameters const& parameters, Translator const& tr) : m_tr(tr) {} @@ -120,7 +129,10 @@ struct choose_split_axis_and_index_for_corner size_t const index_last = parameters.get_max_elements() - parameters.get_min_elements() + 2; // sort elements - element_axis_corner_less elements_less(translator); + element_axis_corner_less + < + element_type, Parameters, Translator, indexable_tag, Corner, AxisIndex + > elements_less(parameters, translator); std::sort(elements_copy.begin(), elements_copy.end(), elements_less); // MAY THROW, BASIC (copy) // { // typename Elements::iterator f = elements_copy.begin() + index_first; @@ -137,18 +149,23 @@ struct choose_split_axis_and_index_for_corner smallest_overlap = (std::numeric_limits::max)(); smallest_content = (std::numeric_limits::max)(); + typename index::detail::strategy_type::type + strategy = index::detail::get_strategy(parameters); + // calculate sum of margins for all distributions for ( size_t i = index_first ; i < index_last ; ++i ) { // TODO - awulkiew: may be optimized - box of group 1 may be initialized with // box of min_elems number of elements and expanded for each iteration by another element - Box box1 = rtree::elements_box(elements_copy.begin(), elements_copy.begin() + i, translator); - Box box2 = rtree::elements_box(elements_copy.begin() + i, elements_copy.end(), translator); + Box box1 = rtree::elements_box(elements_copy.begin(), elements_copy.begin() + i, + translator, strategy); + Box box2 = rtree::elements_box(elements_copy.begin() + i, elements_copy.end(), + translator, strategy); sum_of_margins += index::detail::comparable_margin(box1) + index::detail::comparable_margin(box2); - content_type ovl = index::detail::intersection_content(box1, box2); + content_type ovl = index::detail::intersection_content(box1, box2, strategy); content_type con = index::detail::content(box1) + index::detail::content(box2); // TODO - shouldn't here be < instead of <= ? @@ -337,14 +354,15 @@ struct nth_element BOOST_STATIC_ASSERT(0 < Dimension); BOOST_STATIC_ASSERT(I < Dimension); - template - static inline void apply(Elements & elements, const size_t axis, const size_t index, Translator const& tr) + template + static inline void apply(Elements & elements, Parameters const& parameters, + const size_t axis, const size_t index, Translator const& tr) { //BOOST_GEOMETRY_INDEX_ASSERT(axis < Dimension, "unexpected axis value"); if ( axis != I ) { - nth_element::apply(elements, axis, index, tr); // MAY THROW, BASIC (copy) + nth_element::apply(elements, parameters, axis, index, tr); // MAY THROW, BASIC (copy) } else { @@ -352,7 +370,10 @@ struct nth_element typedef typename rtree::element_indexable_type::type indexable_type; typedef typename tag::type indexable_tag; - element_axis_corner_less less(tr); + element_axis_corner_less + < + element_type, Parameters, Translator, indexable_tag, Corner, I + > less(parameters, tr); index::detail::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy) } } @@ -361,8 +382,9 @@ struct nth_element template struct nth_element { - template - static inline void apply(Elements & /*elements*/, const size_t /*axis*/, const size_t /*index*/, Translator const& /*tr*/) + template + static inline void apply(Elements & /*elements*/, Parameters const& /*parameters*/, + const size_t /*axis*/, const size_t /*index*/, Translator const& /*tr*/) {} }; @@ -432,12 +454,12 @@ struct redistribute_elements(min_corner) ) { rstar::nth_element - ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy) + ::apply(elements_copy, parameters, split_axis, split_index, translator); // MAY THROW, BASIC (copy) } else { rstar::nth_element - ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy) + ::apply(elements_copy, parameters, split_axis, split_index, translator); // MAY THROW, BASIC (copy) } BOOST_TRY @@ -447,8 +469,12 @@ struct redistribute_elements(elements1.begin(), elements1.end(), translator); - box2 = rtree::elements_box(elements2.begin(), elements2.end(), translator); + box1 = rtree::elements_box(elements1.begin(), elements1.end(), + translator, + index::detail::get_strategy(parameters)); + box2 = rtree::elements_box(elements2.begin(), elements2.end(), + translator, + index::detail::get_strategy(parameters)); } BOOST_CATCH(...) { diff --git a/include/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp b/include/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp index 8e0560379..b5fe5a0e2 100644 --- a/include/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp +++ b/include/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp @@ -4,6 +4,10 @@ // // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -22,12 +26,14 @@ template ::type { - typedef typename rtree::internal_node::type internal_node; - typedef typename rtree::leaf::type leaf; + typedef typename Options::parameters_type parameters_type; + + typedef typename rtree::internal_node::type internal_node; + typedef typename rtree::leaf::type leaf; public: - are_boxes_ok(Translator const& tr, bool exact_match) - : result(false), m_tr(tr), m_is_root(true), m_exact_match(exact_match) + are_boxes_ok(parameters_type const& parameters, Translator const& tr, bool exact_match) + : result(false), m_parameters(parameters), m_tr(tr), m_is_root(true), m_exact_match(exact_match) {} void operator()(internal_node const& n) @@ -60,7 +66,8 @@ public: m_box = box_bckup; m_is_root = is_root_bckup; - Box box_exp = rtree::elements_box(elements.begin(), elements.end(), m_tr); + Box box_exp = rtree::elements_box(elements.begin(), elements.end(), m_tr, + index::detail::get_strategy(m_parameters)); if ( m_exact_match ) result = m_is_root || geometry::equals(box_exp, m_box); @@ -82,7 +89,8 @@ public: return; } - Box box_exp = rtree::values_box(elements.begin(), elements.end(), m_tr); + Box box_exp = rtree::values_box(elements.begin(), elements.end(), m_tr, + index::detail::get_strategy(m_parameters)); if ( m_exact_match ) result = geometry::equals(box_exp, m_box); @@ -96,6 +104,7 @@ public: bool result; private: + parameters_type const& m_parameters; Translator const& m_tr; Box m_box; bool m_is_root; @@ -116,7 +125,7 @@ bool are_boxes_ok(Rtree const& tree, bool exact_match = true) typename RTV::translator_type, typename RTV::box_type, typename RTV::allocators_type - > v(rtv.translator(), exact_match); + > v(tree.parameters(), rtv.translator(), exact_match); rtv.apply_visitor(v); diff --git a/include/boost/geometry/index/detail/rtree/visitors/children_box.hpp b/include/boost/geometry/index/detail/rtree/visitors/children_box.hpp index 6c1bafd3d..0d26a79c3 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/children_box.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/children_box.hpp @@ -4,6 +4,10 @@ // // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -19,12 +23,14 @@ template ::type { - typedef typename rtree::internal_node::type internal_node; - typedef typename rtree::leaf::type leaf; + typedef typename Options::parameters_type parameters_type; + + typedef typename rtree::internal_node::type internal_node; + typedef typename rtree::leaf::type leaf; public: - inline children_box(Box & result, Translator const& tr) - : m_result(result), m_tr(tr) + inline children_box(Box & result, parameters_type const& parameters, Translator const& tr) + : m_result(result), m_parameters(parameters), m_tr(tr) {} inline void operator()(internal_node const& n) @@ -32,7 +38,8 @@ public: typedef typename rtree::elements_type::type elements_type; elements_type const& elements = rtree::elements(n); - m_result = rtree::elements_box(elements.begin(), elements.end(), m_tr); + m_result = rtree::elements_box(elements.begin(), elements.end(), m_tr, + index::detail::get_strategy(m_parameters)); } inline void operator()(leaf const& n) @@ -40,11 +47,13 @@ public: typedef typename rtree::elements_type::type elements_type; elements_type const& elements = rtree::elements(n); - m_result = rtree::values_box(elements.begin(), elements.end(), m_tr); + m_result = rtree::values_box(elements.begin(), elements.end(), m_tr, + index::detail::get_strategy(m_parameters)); } private: Box & m_result; + parameters_type const& m_parameters; Translator const& m_tr; }; diff --git a/include/boost/geometry/index/detail/rtree/visitors/count.hpp b/include/boost/geometry/index/detail/rtree/visitors/count.hpp index 7efd5b702..2cdbd8c0e 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/count.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/count.hpp @@ -4,6 +4,10 @@ // // 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. +// 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) @@ -23,10 +27,10 @@ struct count_helper { return i; } - template - static inline bool equals(Indexable const& i, Value const& v, Translator const& tr) + template + static inline bool equals(Indexable const& i, Value const& v, Translator const& tr, Strategy const& s) { - return geometry::equals(i, tr(v)); + return index::detail::equals::apply(i, tr(v), s); } }; @@ -38,10 +42,10 @@ struct count_helper { return tr(v); } - template - static inline bool equals(Value const& v1, Value const& v2, Translator const& tr) + template + static inline bool equals(Value const& v1, Value const& v2, Translator const& tr, Strategy const& s) { - return tr.equals(v1, v2); + return tr.equals(v1, v2, s); } }; @@ -49,14 +53,16 @@ template ::type { - typedef typename rtree::node::type node; - typedef typename rtree::internal_node::type internal_node; - typedef typename rtree::leaf::type leaf; + typedef typename Options::parameters_type parameters_type; + + typedef typename rtree::node::type node; + typedef typename rtree::internal_node::type internal_node; + typedef typename rtree::leaf::type leaf; typedef count_helper count_help; - inline count(ValueOrIndexable const& vori, Translator const& t) - : value_or_indexable(vori), tr(t), found_count(0) + inline count(ValueOrIndexable const& vori, parameters_type const& parameters, Translator const& t) + : value_or_indexable(vori), m_parameters(parameters), tr(t), found_count(0) {} inline void operator()(internal_node const& n) @@ -68,10 +74,9 @@ struct count for (typename elements_type::const_iterator it = elements.begin(); it != elements.end(); ++it) { - if ( geometry::covered_by( - return_ref_or_bounds( - count_help::indexable(value_or_indexable, tr)), - it->first) ) + if ( index::detail::covered_by_bounds(count_help::indexable(value_or_indexable, tr), + it->first, + index::detail::get_strategy(m_parameters)) ) { rtree::apply_visitor(*this, *it->second); } @@ -88,7 +93,8 @@ struct count it != elements.end(); ++it) { // if value meets predicates - if ( count_help::equals(value_or_indexable, *it, tr) ) + if ( count_help::equals(value_or_indexable, *it, tr, + index::detail::get_strategy(m_parameters)) ) { ++found_count; } @@ -96,6 +102,7 @@ struct count } ValueOrIndexable const& value_or_indexable; + parameters_type const& m_parameters; Translator const& tr; typename Allocators::size_type found_count; }; diff --git a/include/boost/geometry/index/detail/rtree/visitors/distance_query.hpp b/include/boost/geometry/index/detail/rtree/visitors/distance_query.hpp index b93071443..20a954dc4 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/distance_query.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/distance_query.hpp @@ -4,6 +4,10 @@ // // 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. +// 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) @@ -104,6 +108,7 @@ class distance_query { public: typedef typename Options::parameters_type parameters_type; + typedef typename index::detail::strategy_type::type strategy_type; typedef typename rtree::node::type node; typedef typename rtree::internal_node::type internal_node; @@ -113,8 +118,8 @@ public: typedef typename nearest_predicate_access::type nearest_predicate_type; typedef typename indexable_type::type indexable_type; - typedef index::detail::calculate_distance calculate_value_distance; - typedef index::detail::calculate_distance calculate_node_distance; + typedef index::detail::calculate_distance calculate_value_distance; + typedef index::detail::calculate_distance calculate_node_distance; typedef typename calculate_value_distance::result_type value_distance_type; typedef typename calculate_node_distance::result_type node_distance_type; @@ -124,6 +129,7 @@ public: : m_parameters(parameters), m_translator(translator) , m_pred(pred) , m_result(nearest_predicate_access::get(m_pred).count, out_it) + , m_strategy(index::detail::get_strategy(parameters)) {} inline void operator()(internal_node const& n) @@ -147,12 +153,16 @@ public: { // if current node meets predicates // 0 - dummy value - if ( index::detail::predicates_check(m_pred, 0, it->first) ) + if ( index::detail::predicates_check + < + index::detail::bounds_tag, 0, predicates_len + >(m_pred, 0, it->first, m_strategy) ) { // calculate node's distance(s) for distance predicate node_distance_type node_distance; // if distance isn't ok - move to the next node - if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) ) + if ( !calculate_node_distance::apply(predicate(), it->first, + m_strategy, node_distance) ) { continue; } @@ -226,12 +236,16 @@ public: it != elements.end(); ++it) { // if value meets predicates - if ( index::detail::predicates_check(m_pred, *it, m_translator(*it)) ) + if ( index::detail::predicates_check + < + index::detail::value_tag, 0, predicates_len + >(m_pred, *it, m_translator(*it), m_strategy) ) { // calculate values distance for distance predicate value_distance_type value_distance; // if distance is ok - if ( calculate_value_distance::apply(predicate(), m_translator(*it), value_distance) ) + if ( calculate_value_distance::apply(predicate(), m_translator(*it), + m_strategy, value_distance) ) { // store value m_result.store(*it, value_distance); @@ -276,6 +290,8 @@ private: Predicates m_pred; distance_query_result m_result; + + strategy_type m_strategy; }; template < @@ -292,6 +308,7 @@ class distance_query_incremental { public: typedef typename Options::parameters_type parameters_type; + typedef typename index::detail::strategy_type::type strategy_type; typedef typename rtree::node::type node; typedef typename rtree::internal_node::type internal_node; @@ -301,8 +318,8 @@ public: typedef typename nearest_predicate_access::type nearest_predicate_type; typedef typename indexable_type::type indexable_type; - typedef index::detail::calculate_distance calculate_value_distance; - typedef index::detail::calculate_distance calculate_node_distance; + typedef index::detail::calculate_distance calculate_value_distance; + typedef index::detail::calculate_distance calculate_node_distance; typedef typename calculate_value_distance::result_type value_distance_type; typedef typename calculate_node_distance::result_type node_distance_type; @@ -342,14 +359,15 @@ public: // , m_pred() , current_neighbor((std::numeric_limits::max)()) // , next_closest_node_distance((std::numeric_limits::max)()) +// , m_strategy_type() {} - inline distance_query_incremental(Translator const& translator, Predicates const& pred) + inline distance_query_incremental(parameters_type const& params, Translator const& translator, Predicates const& pred) : m_translator(::boost::addressof(translator)) , m_pred(pred) , current_neighbor((std::numeric_limits::max)()) - , next_closest_node_distance((std::numeric_limits::max)()) + , m_strategy(index::detail::get_strategy(params)) { BOOST_GEOMETRY_INDEX_ASSERT(0 < max_count(), "k must be greather than 0"); } @@ -457,12 +475,16 @@ public: { // if current node meets predicates // 0 - dummy value - if ( index::detail::predicates_check(m_pred, 0, it->first) ) + if ( index::detail::predicates_check + < + index::detail::bounds_tag, 0, predicates_len + >(m_pred, 0, it->first, m_strategy) ) { // calculate node's distance(s) for distance predicate node_distance_type node_distance; // if distance isn't ok - move to the next node - if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) ) + if ( !calculate_node_distance::apply(predicate(), it->first, + m_strategy, node_distance) ) { continue; } @@ -502,12 +524,16 @@ public: for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it) { // if value meets predicates - if ( index::detail::predicates_check(m_pred, *it, (*m_translator)(*it)) ) + if ( index::detail::predicates_check + < + index::detail::value_tag, 0, predicates_len + >(m_pred, *it, (*m_translator)(*it), m_strategy) ) { // calculate values distance for distance predicate value_distance_type value_distance; // if distance is ok - if ( calculate_value_distance::apply(predicate(), (*m_translator)(*it), value_distance) ) + if ( calculate_value_distance::apply(predicate(), (*m_translator)(*it), + m_strategy, value_distance) ) { // if there is not enough values or current value is closer than furthest neighbour if ( not_enough_neighbors || value_distance < greatest_distance ) @@ -574,11 +600,13 @@ private: const Translator * m_translator; Predicates m_pred; - + internal_stack_type internal_stack; std::vector< std::pair > neighbors; size_type current_neighbor; node_distance_type next_closest_node_distance; + + strategy_type m_strategy; }; }}} // namespace detail::rtree::visitors diff --git a/include/boost/geometry/index/detail/rtree/visitors/insert.hpp b/include/boost/geometry/index/detail/rtree/visitors/insert.hpp index 87d5bbbcc..3c9501f37 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/insert.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/insert.hpp @@ -4,6 +4,10 @@ // // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -16,6 +20,7 @@ #include #include +#include #include namespace boost { namespace geometry { namespace index { @@ -43,7 +48,7 @@ public: template static inline size_t apply(internal_node & n, Indexable const& indexable, - parameters_type const& /*parameters*/, + parameters_type const& parameters, size_t /*node_relative_level*/) { children_type & children = rtree::elements(n); @@ -65,7 +70,8 @@ public: // expanded child node's box Box box_exp(ch_i.first); - geometry::expand(box_exp, indexable); + index::detail::expand(box_exp, indexable, + index::detail::get_strategy(parameters)); // areas difference content_type content = index::detail::content(box_exp); @@ -274,7 +280,9 @@ protected: // NOTE: This is actually only needed because conditionally the bounding // object may be expanded below. Otherwise the indexable could be // directly used instead - index::detail::bounds(rtree::element_indexable(m_element, m_translator), m_element_bounds); + index::detail::bounds(rtree::element_indexable(m_element, m_translator), + m_element_bounds, + index::detail::get_strategy(m_parameters)); #ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON // Enlarge it in case if it's not bounding geometry type. @@ -300,10 +308,10 @@ protected: apply(n, rtree::element_indexable(m_element, m_translator), m_parameters, m_leafs_level - m_traverse_data.current_level); // expand the node to contain value - geometry::expand( + index::detail::expand( rtree::elements(n)[choosen_node_index].first, - m_element_bounds - /*rtree::element_indexable(m_element, m_translator)*/); + m_element_bounds, + index::detail::get_strategy(m_parameters)); // next traversing step traverse_apply_visitor(visitor, n, choosen_node_index); // MAY THROW (V, E: alloc, copy, N:alloc) diff --git a/include/boost/geometry/index/detail/rtree/visitors/remove.hpp b/include/boost/geometry/index/detail/rtree/visitors/remove.hpp index 7e6162a61..1a3ccd796 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/remove.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/remove.hpp @@ -4,6 +4,10 @@ // // Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -71,9 +75,9 @@ public: internal_size_type child_node_index = 0; for ( ; child_node_index < children.size() ; ++child_node_index ) { - if ( geometry::covered_by( - return_ref_or_bounds(m_translator(m_value)), - children[child_node_index].first) ) + if ( index::detail::covered_by_bounds(m_translator(m_value), + children[child_node_index].first, + index::detail::get_strategy(m_parameters)) ) { // next traversing step traverse_apply_visitor(n, child_node_index); // MAY THROW @@ -112,7 +116,8 @@ public: BOOST_GEOMETRY_INDEX_ASSERT((elements.size() < m_parameters.get_min_elements()) == m_is_underflow, "unexpected state"); rtree::elements(*m_parent)[m_current_child_index].first - = rtree::elements_box(elements.begin(), elements.end(), m_translator); + = rtree::elements_box(elements.begin(), elements.end(), m_translator, + index::detail::get_strategy(m_parameters)); } // n is root node else @@ -145,11 +150,11 @@ public: { typedef typename rtree::elements_type::type elements_type; elements_type & elements = rtree::elements(n); - + // find value and remove it for ( typename elements_type::iterator it = elements.begin() ; it != elements.end() ; ++it ) { - if ( m_translator.equals(*it, m_value) ) + if ( m_translator.equals(*it, m_value, index::detail::get_strategy(m_parameters)) ) { rtree::move_from_back(elements, it); // MAY THROW (V: copy) elements.pop_back(); @@ -170,7 +175,8 @@ public: if ( 0 != m_parent ) { rtree::elements(*m_parent)[m_current_child_index].first - = rtree::values_box(elements.begin(), elements.end(), m_translator); + = rtree::values_box(elements.begin(), elements.end(), m_translator, + index::detail::get_strategy(m_parameters)); } } } diff --git a/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp b/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp index b9cd0ae2c..c94248cfd 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp @@ -4,6 +4,10 @@ // // 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. +// 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) @@ -19,16 +23,19 @@ template ::type { - typedef typename rtree::node::type node; - typedef typename rtree::internal_node::type internal_node; - typedef typename rtree::leaf::type leaf; + typedef typename Options::parameters_type parameters_type; + typedef typename index::detail::strategy_type::type strategy_type; + + typedef typename rtree::node::type node; + typedef typename rtree::internal_node::type internal_node; + typedef typename rtree::leaf::type leaf; typedef typename Allocators::size_type size_type; static const unsigned predicates_len = index::detail::predicates_length::value; - inline spatial_query(Translator const& t, Predicates const& p, OutIter out_it) - : tr(t), pred(p), out_iter(out_it), found_count(0) + inline spatial_query(parameters_type const& par, Translator const& t, Predicates const& p, OutIter out_it) + : tr(t), pred(p), out_iter(out_it), found_count(0), strategy(index::detail::get_strategy(par)) {} inline void operator()(internal_node const& n) @@ -42,8 +49,13 @@ struct spatial_query { // if node meets predicates // 0 - dummy value - if ( index::detail::predicates_check(pred, 0, it->first) ) + if ( index::detail::predicates_check + < + index::detail::bounds_tag, 0, predicates_len + >(pred, 0, it->first, strategy) ) + { rtree::apply_visitor(*this, *it->second); + } } } @@ -57,7 +69,10 @@ struct spatial_query it != elements.end(); ++it) { // if value meets predicates - if ( index::detail::predicates_check(pred, *it, tr(*it)) ) + if ( index::detail::predicates_check + < + index::detail::value_tag, 0, predicates_len + >(pred, *it, tr(*it), strategy) ) { *out_iter = *it; ++out_iter; @@ -73,12 +88,17 @@ struct spatial_query OutIter out_iter; size_type found_count; + + strategy_type strategy; }; template class spatial_query_incremental : public rtree::visitor::type { + typedef typename Options::parameters_type parameters_type; + typedef typename index::detail::strategy_type::type strategy_type; + public: typedef typename rtree::node::type node; typedef typename rtree::internal_node::type internal_node; @@ -99,13 +119,15 @@ public: // , m_pred() , m_values(NULL) , m_current() +// , m_strategy() {} - inline spatial_query_incremental(Translator const& t, Predicates const& p) + inline spatial_query_incremental(parameters_type const& params, Translator const& t, Predicates const& p) : m_translator(::boost::addressof(t)) , m_pred(p) , m_values(NULL) , m_current() + , m_strategy(index::detail::get_strategy(params)) {} inline void operator()(internal_node const& n) @@ -151,8 +173,13 @@ public: { // return if next value is found Value const& v = *m_current; - if ( index::detail::predicates_check(m_pred, v, (*m_translator)(v)) ) + if (index::detail::predicates_check + < + index::detail::value_tag, 0, predicates_len + >(m_pred, v, (*m_translator)(v), m_strategy)) + { return; + } ++m_current; } @@ -180,8 +207,13 @@ public: ++m_internal_stack.back().first; // next node is found, push it to the stack - if ( index::detail::predicates_check(m_pred, 0, it->first) ) + if (index::detail::predicates_check + < + index::detail::bounds_tag, 0, predicates_len + >(m_pred, 0, it->first, m_strategy)) + { rtree::apply_visitor(*this, *(it->second)); + } } } } @@ -205,6 +237,8 @@ private: std::vector< std::pair > m_internal_stack; const leaf_elements * m_values; leaf_iterator m_current; + + strategy_type m_strategy; }; }}} // namespace detail::rtree::visitors diff --git a/include/boost/geometry/index/detail/translator.hpp b/include/boost/geometry/index/detail/translator.hpp index f377c720a..dd49b61fe 100644 --- a/include/boost/geometry/index/detail/translator.hpp +++ b/include/boost/geometry/index/detail/translator.hpp @@ -2,6 +2,10 @@ // // Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -13,6 +17,30 @@ namespace boost { namespace geometry { namespace index { namespace detail { +template +struct translator_equals +{ + template + static inline bool apply(EqualTo const& equal_to, + Value const& v1, Value const& v2, + Strategy const& strategy) + { + return equal_to(v1, v2, strategy); + } +}; + +template <> +struct translator_equals +{ + template + static inline bool apply(EqualTo const& equal_to, + Value const& v1, Value const& v2, + default_strategy const&) + { + return equal_to(v1, v2); + } +}; + template struct translator : public IndexableGetter @@ -30,11 +58,14 @@ struct translator return IndexableGetter::operator()(value); } - template - bool equals(Value const& v1, Value const& v2) const - { - return EqualTo::operator()(v1, v2); - } + template + bool equals(Value const& v1, Value const& v2, Strategy const& strategy) const + { + return translator_equals + < + Strategy + >::apply(static_cast(*this), v1, v2, strategy); + } }; template diff --git a/include/boost/geometry/index/equal_to.hpp b/include/boost/geometry/index/equal_to.hpp index 2fb1ed216..f457f5184 100644 --- a/include/boost/geometry/index/equal_to.hpp +++ b/include/boost/geometry/index/equal_to.hpp @@ -2,6 +2,10 @@ // // 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. +// 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,22 +16,73 @@ #include #include -namespace boost { namespace geometry { namespace index { namespace detail { +namespace boost { namespace geometry { namespace index { namespace detail +{ template ::type> struct equals { - inline static bool apply(Geometry const& g1, Geometry const& g2) + template + inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const&) { return geometry::equals(g1, g2); } }; +template +struct equals +{ + inline static bool apply(Geometry const& g1, Geometry const& g2, default_strategy const&) + { + return geometry::equals(g1, g2); + } + + template + inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const&) + { + return geometry::equals(g1, g2, typename Strategy::within_point_point_strategy_type()); + } +}; + +template +struct equals +{ + inline static bool apply(Geometry const& g1, Geometry const& g2, default_strategy const&) + { + return geometry::equals(g1, g2); + } + + template + inline static bool apply(Geometry const& g1, Geometry const& g2, Strategy const&) + { + // 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); + } +}; + +template +struct equals +{ + inline static bool apply(Geometry const& g1, Geometry const& g2, default_strategy const&) + { + return geometry::equals(g1, g2); + } + + 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()); + } +}; + + template struct equals { - inline static bool apply(const Geometry * g1, const Geometry * g2) + template + inline static bool apply(const Geometry * g1, const Geometry * g2, Strategy const&) { return g1 == g2; } @@ -36,7 +91,8 @@ struct equals template struct equals { - inline static bool apply(T const& v1, T const& v2) + template + inline static bool apply(T const& v1, T const& v2, Strategy const&) { return v1 == v2; } @@ -45,7 +101,8 @@ struct equals template struct equals { - inline static bool apply(const T * v1, const T * v2) + template + inline static bool apply(const T * v1, const T * v2, Strategy const&) { return v1 == v2; } @@ -54,19 +111,21 @@ struct equals template struct tuple_equals { - inline static bool apply(Tuple const& t1, Tuple const& t2) + template + inline static bool apply(Tuple const& t1, Tuple const& t2, Strategy const& strategy) { typedef typename boost::tuples::element::type T; - return equals::apply(boost::get(t1), boost::get(t2)) - && tuple_equals::apply(t1, t2); + return equals::apply(boost::get(t1), boost::get(t2), strategy) + && tuple_equals::apply(t1, t2, strategy); } }; template struct tuple_equals { - inline static bool apply(Tuple const&, Tuple const&) + template + inline static bool apply(Tuple const&, Tuple const&, Strategy const&) { return true; } @@ -102,9 +161,10 @@ struct equal_to \param r Second value. \return true if values are equal. */ - inline bool operator()(Value const& l, Value const& r) const + template + inline bool operator()(Value const& l, Value const& r, Strategy const& strategy) const { - return detail::equals::apply(l ,r); + return detail::equals::apply(l, r, strategy); } }; @@ -130,10 +190,12 @@ struct equal_to, false> \param r Second value. \return true if values are equal. */ - inline bool operator()(std::pair const& l, std::pair const& r) const + template + inline bool operator()(std::pair const& l, std::pair const& r, + Strategy const& strategy) const { - return detail::equals::apply(l.first, r.first) - && detail::equals::apply(l.second, r.second); + return detail::equals::apply(l.first, r.first, strategy) + && detail::equals::apply(l.second, r.second, strategy); } }; @@ -159,11 +221,13 @@ struct equal_to, false> \param r Second value. \return true if values are equal. */ - inline bool operator()(value_type const& l, value_type const& r) const + template + inline bool operator()(value_type const& l, value_type const& r, + Strategy const& strategy) const { return detail::tuple_equals< value_type, 0, boost::tuples::length::value - >::apply(l ,r); + >::apply(l, r, strategy); } }; @@ -178,19 +242,21 @@ namespace boost { namespace geometry { namespace index { namespace detail { template struct std_tuple_equals { - inline static bool apply(Tuple const& t1, Tuple const& t2) + template + inline static bool apply(Tuple const& t1, Tuple const& t2, Strategy const& strategy) { typedef typename std::tuple_element::type T; - return equals::apply(std::get(t1), std::get(t2)) - && std_tuple_equals::apply(t1, t2); + return equals::apply(std::get(t1), std::get(t2), strategy) + && std_tuple_equals::apply(t1, t2, strategy); } }; template struct std_tuple_equals { - inline static bool apply(Tuple const&, Tuple const&) + template + inline static bool apply(Tuple const&, Tuple const&, Strategy const&) { return true; } @@ -218,11 +284,12 @@ struct equal_to, false> \param r Second value. \return true if values are equal. */ - bool operator()(value_type const& l, value_type const& r) const + template + bool operator()(value_type const& l, value_type const& r, Strategy const& strategy) const { return detail::std_tuple_equals< value_type, 0, std::tuple_size::value - >::apply(l ,r); + >::apply(l, r, strategy); } }; @@ -258,7 +325,13 @@ struct equal_to */ inline bool operator()(Value const& l, Value const& r) const { - return detail::equal_to::operator()(l ,r); + return detail::equal_to::operator()(l, r, default_strategy()); + } + + template + inline bool operator()(Value const& l, Value const& r, Strategy const& strategy) const + { + return detail::equal_to::operator()(l, r, strategy); } }; diff --git a/include/boost/geometry/index/parameters.hpp b/include/boost/geometry/index/parameters.hpp index 1a9469c10..b19762436 100644 --- a/include/boost/geometry/index/parameters.hpp +++ b/include/boost/geometry/index/parameters.hpp @@ -4,6 +4,10 @@ // // Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -253,6 +257,76 @@ private: size_t m_overlap_cost_threshold; }; + +template +class parameters + : public Parameters + , private Strategy +{ +public: + parameters() + : Parameters(), Strategy() + {} + + parameters(Parameters const& params) + : Parameters(params), Strategy() + {} + + parameters(Parameters const& params, Strategy const& strategy) + : Parameters(params), Strategy(strategy) + {} + + Strategy const& strategy() const + { + return static_cast(*this); + } +}; + + +namespace detail +{ + +template +struct strategy_type +{ + typedef default_strategy type; +}; + +template +struct strategy_type< parameters > +{ + typedef Strategy type; +}; + + +template +struct get_strategy_impl +{ + static inline default_strategy apply(Parameters const& parameters) + { + return default_strategy(); + } +}; + +template +struct get_strategy_impl > +{ + static inline Strategy const& apply(parameters const& parameters) + { + return parameters.strategy(); + } +}; + +template +inline typename strategy_type::type + get_strategy(Parameters const& parameters) +{ + return get_strategy_impl::apply(parameters); +} + +} // namespace detail + + }}} // namespace boost::geometry::index #endif // BOOST_GEOMETRY_INDEX_PARAMETERS_HPP diff --git a/include/boost/geometry/index/rtree.hpp b/include/boost/geometry/index/rtree.hpp index 1a8be031d..ab770fd6a 100644 --- a/include/boost/geometry/index/rtree.hpp +++ b/include/boost/geometry/index/rtree.hpp @@ -5,6 +5,10 @@ // Copyright (c) 2008 Federico J. Fernandez. // Copyright (c) 2011-2019 Adam Wulkiewicz, Lodz, Poland. // +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -191,15 +195,46 @@ private: typedef bounds_type box_type; typedef typename detail::rtree::options_type::type options_type; typedef typename options_type::node_tag node_tag; - typedef detail::rtree::allocators allocators_type; + typedef detail::rtree::allocators + < + allocator_type, + value_type, + typename options_type::parameters_type, + box_type, + node_tag + > allocators_type; - typedef typename detail::rtree::node::type node; - typedef typename detail::rtree::internal_node::type internal_node; - typedef typename detail::rtree::leaf::type leaf; + typedef typename detail::rtree::node + < + value_type, + typename options_type::parameters_type, + box_type, + allocators_type, + node_tag + >::type node; + typedef typename detail::rtree::internal_node + < + value_type, + typename options_type::parameters_type, + box_type, + allocators_type, + node_tag + >::type internal_node; + typedef typename detail::rtree::leaf + < + value_type, + typename options_type::parameters_type, + box_type, + allocators_type, + node_tag + >::type leaf; typedef typename allocators_type::node_pointer node_pointer; typedef ::boost::container::allocator_traits allocator_traits_type; - typedef detail::rtree::subtree_destroyer subtree_destroyer; + typedef detail::rtree::subtree_destroyer + < + value_type, options_type, translator_type, box_type, allocators_type + > subtree_destroyer; friend class detail::rtree::utilities::view; #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL @@ -1009,9 +1044,9 @@ private: >::type iterator_type; if ( !m_members.root ) - return iterator_type(m_members.translator(), predicates); + return iterator_type(m_members.parameters(), m_members.translator(), predicates); - return iterator_type(m_members.root, m_members.translator(), predicates); + return iterator_type(m_members.root, m_members.parameters(), m_members.translator(), predicates); } /*! @@ -1069,7 +1104,7 @@ private: > >::type iterator_type; - return iterator_type(m_members.translator(), predicates); + return iterator_type(m_members.parameters(), m_members.translator(), predicates); } /*! @@ -1268,8 +1303,10 @@ public: if ( m_members.root ) { - detail::rtree::visitors::children_box - box_v(result, m_members.translator()); + detail::rtree::visitors::children_box + < + value_type, options_type, translator_type, box_type, allocators_type + > box_v(result, m_members.parameters(), m_members.translator()); detail::rtree::apply_visitor(box_v, *m_members.root); } @@ -1643,8 +1680,10 @@ private: template size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_ const& /*is_distance_predicate*/) const { - detail::rtree::visitors::spatial_query - find_v(m_members.translator(), predicates, out_it); + detail::rtree::visitors::spatial_query + < + value_type, options_type, translator_type, box_type, allocators_type, Predicates, OutIter + >find_v(m_members.parameters(), m_members.translator(), predicates, out_it); detail::rtree::apply_visitor(find_v, *m_members.root); @@ -1698,7 +1737,7 @@ private: translator_type, box_type, allocators_type - > count_v(vori, m_members.translator()); + > count_v(vori, m_members.parameters(), m_members.translator()); detail::rtree::apply_visitor(count_v, *m_members.root); From 7bf8c0dca8dcfe39ddab48693e66bbffeae72665 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 24 Jun 2019 12:19:21 +0200 Subject: [PATCH 48/68] [strategies] Add headers to strategies.hpp --- .../boost/geometry/strategies/strategies.hpp | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/strategies/strategies.hpp b/include/boost/geometry/strategies/strategies.hpp index 026214173..d1c4c8cd2 100644 --- a/include/boost/geometry/strategies/strategies.hpp +++ b/include/boost/geometry/strategies/strategies.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014-2018. -// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014-2019. +// Modifications copyright (c) 2014-2019 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -64,9 +64,17 @@ #include #include #include +#include +#include +#include #include +#include +#include +#include +#include #include #include +#include #include #include #include @@ -83,8 +91,16 @@ #include #include #include +#include +#include +#include #include +#include +#include +#include +#include #include +#include #include #include #include @@ -103,6 +119,8 @@ #include #include #include +#include +#include #include //#include #include From d772e36632e4a2cacc754e649baefec32191c8ed Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 24 Jun 2019 12:20:04 +0200 Subject: [PATCH 49/68] [algorithms] Propagate CS-specific strategies in algorithms. --- include/boost/geometry/algorithms/buffer.hpp | 10 ++- .../buffer/buffered_piece_collection.hpp | 3 +- .../detail/closest_feature/range_to_range.hpp | 17 ++++- .../detail/comparable_distance/interface.hpp | 19 ++++-- .../algorithms/detail/direction_code.hpp | 2 +- .../detail/disjoint/linear_segment_or_box.hpp | 63 ++++++++++++++----- .../detail/disjoint/multipoint_geometry.hpp | 18 ++++-- .../distance/geometry_to_segment_or_box.hpp | 26 +++++++- .../distance/linear_or_areal_to_areal.hpp | 9 ++- .../distance/multipoint_to_geometry.hpp | 20 ++++-- .../detail/distance/point_to_geometry.hpp | 12 ++-- .../detail/distance/segment_to_box.hpp | 25 +++----- .../detail/distance/segment_to_segment.hpp | 5 +- .../detail/intersection/interface.hpp | 41 +++++++----- .../detail/is_valid/has_valid_self_turns.hpp | 9 +-- .../detail/is_valid/multipolygon.hpp | 2 +- .../algorithms/detail/is_valid/polygon.hpp | 2 +- .../algorithms/detail/is_valid/ring.hpp | 2 +- .../detail/overlay/assign_parents.hpp | 2 +- .../detail/overlay/intersection_insert.hpp | 7 ++- .../detail/overlay/linear_linear.hpp | 18 +++--- .../detail/point_is_spike_or_equal.hpp | 6 +- .../algorithms/detail/relate/areal_areal.hpp | 9 ++- .../algorithms/detail/relate/linear_areal.hpp | 16 ++--- .../detail/relate/linear_linear.hpp | 9 ++- .../detail/relate/multi_point_geometry.hpp | 36 ++++++++--- .../algorithms/detail/relate/turns.hpp | 41 ++++++++---- .../algorithms/detail/within/multi_point.hpp | 16 ++++- .../boost/geometry/algorithms/difference.hpp | 41 +++++++----- .../geometry/algorithms/sym_difference.hpp | 41 +++++++----- include/boost/geometry/algorithms/union.hpp | 41 +++++++----- 31 files changed, 372 insertions(+), 196 deletions(-) diff --git a/include/boost/geometry/algorithms/buffer.hpp b/include/boost/geometry/algorithms/buffer.hpp index ec2f9c5ac..c7343c4bb 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. -// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2019. +// Modifications copyright (c) 2017, 2019 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 @@ -224,7 +224,11 @@ inline void buffer(GeometryIn const& geometry_in, concepts::check(); typedef typename point_type::type point_type; - typedef typename rescale_policy_type::type rescale_policy_type; + typedef typename rescale_policy_type + < + point_type, + typename geometry::cs_tag::type + >::type rescale_policy_type; geometry_out.clear(); 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 00b6a5178..8a4618da4 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -175,7 +175,8 @@ struct buffered_piece_collection typedef typename geometry::rescale_policy_type < - typename geometry::point_type::type + typename geometry::point_type::type, + typename IntersectionStrategy::cs_tag >::type rescale_policy_type; typedef typename geometry::segment_ratio_type 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 26b868482..a3e99bec7 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 @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014, 2019, 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 @@ -53,7 +54,15 @@ private: QueryRangeIterator& qit_min, Distance& dist_min) { - typedef index::rtree > rtree_type; + typedef strategy::index::services::from_strategy + < + Strategy + > index_strategy_from; + typedef index::parameters + < + index::linear<8>, typename index_strategy_from::type + > index_parameters_type; + typedef index::rtree rtree_type; BOOST_GEOMETRY_ASSERT( rtree_first != rtree_last ); BOOST_GEOMETRY_ASSERT( queries_first != queries_last ); @@ -62,7 +71,9 @@ private: dist_min = zero; // create -- packing algorithm - rtree_type rt(rtree_first, rtree_last); + rtree_type rt(rtree_first, rtree_last, + index_parameters_type(index::linear<8>(), + index_strategy_from::get(strategy))); RTreeValueType t_v; bool first = true; diff --git a/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp b/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp index 3e48a05ba..27174a71b 100644 --- a/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp +++ b/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp @@ -4,10 +4,11 @@ // Copyright (c) 2008-2014 Bruno Lalande, Paris, France. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. -// 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, 2019. +// Modifications copyright (c) 2014, 2019, 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 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -35,9 +36,10 @@ namespace boost { namespace geometry namespace resolve_strategy { +template struct comparable_distance { - template + template static inline typename comparable_distance_result::type apply(Geometry1 const& geometry1, @@ -59,7 +61,11 @@ struct comparable_distance Strategy >::apply(strategy)); } +}; +template <> +struct comparable_distance +{ template static inline typename comparable_distance_result < @@ -101,9 +107,10 @@ struct comparable_distance Geometry2 const& geometry2, Strategy const& strategy) { - return resolve_strategy::comparable_distance::apply(geometry1, - geometry2, - strategy); + return resolve_strategy::comparable_distance + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/direction_code.hpp b/include/boost/geometry/algorithms/detail/direction_code.hpp index 9acd2c301..ab3b1e0a2 100644 --- a/include/boost/geometry/algorithms/detail/direction_code.hpp +++ b/include/boost/geometry/algorithms/detail/direction_code.hpp @@ -223,7 +223,7 @@ struct direction_code_impl return direction_code_impl < - Point, spherical_equatorial_tag + spherical_equatorial_tag >::apply(segment_a, segment_b, p); } }; 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 b4c71c8f3..ebf41e896 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 @@ -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-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2019. +// Modifications copyright (c) 2013-2019, 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 @@ -21,19 +21,14 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP -#include -#include - -#include - -#include - -#include - -#include #include #include +#include +#include +#include +#include +#include namespace boost { namespace geometry @@ -45,6 +40,44 @@ namespace detail { namespace disjoint { +template +< + typename SegmentOrBox, + typename Tag = typename tag::type +> +struct disjoint_point_segment_or_box + : not_implemented +{}; + +template +struct disjoint_point_segment_or_box +{ + template + static inline bool apply(Point const& point, Segment const& segment, Strategy const& strategy) + { + return dispatch::disjoint + < + Point, Segment + >::apply(point, segment, + strategy.template get_point_in_geometry_strategy()); + } +}; + +template +struct disjoint_point_segment_or_box +{ + template + static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) + { + return dispatch::disjoint + < + Point, Box + >::apply(point, box, + strategy.get_disjoint_point_box_strategy()); + } +}; + + template < typename Range, @@ -83,12 +116,12 @@ struct disjoint_range_segment_or_box } else if ( count == 1 ) { - return dispatch::disjoint + return disjoint_point_segment_or_box < - point_type, SegmentOrBox + SegmentOrBox >::apply(geometry::range::front(view), segment_or_box, - strategy.template get_point_in_geometry_strategy()); + strategy); } else { diff --git a/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp index 5bc8af77d..58fe2b4fd 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp @@ -307,21 +307,23 @@ template class multi_point_multi_geometry { private: + template struct expand_box_point { template static inline void apply(Box& total, Point const& point) { - geometry::expand(total, point); + geometry::expand(total, point, ExpandPointStrategy()); } }; + template struct expand_box_box_pair { template inline void apply(Box& total, BoxPair const& box_pair) const { - geometry::expand(total, box_pair.first); + geometry::expand(total, box_pair.first, ExpandBoxStrategy()); } }; @@ -411,10 +413,18 @@ public: 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 + < + typename Strategy::envelope_strategy_type::box_expand_strategy_type + > expand_box_box_pair_type; typedef overlaps_box_box_pair < typename Strategy::disjoint_box_box_strategy_type @@ -424,9 +434,9 @@ public: < box1_type >::apply(multi_point, boxes, visitor, - expand_box_point(), + expand_box_point_type(), overlaps_box_point_type(), - expand_box_box_pair(), + expand_box_box_pair_type(), overlaps_box_box_pair_type()); return ! visitor.intersection_found(); diff --git a/include/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp b/include/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp index d6de7cac9..964f3e218 100644 --- a/include/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp +++ b/include/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014, 2019, 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 @@ -165,6 +166,27 @@ private: } }; + template + < + typename SegOrBox, + typename SegOrBoxTag = typename tag::type + > + struct intersects + { + static inline bool apply(Geometry const& g1, SegOrBox const& g2, Strategy const&) + { + return geometry::intersects(g1, g2); + } + }; + + template + struct intersects + { + static inline bool apply(Geometry const& g1, SegOrBox const& g2, Strategy const& s) + { + return geometry::intersects(g1, g2, s.get_relate_segment_segment_strategy()); + } + }; public: typedef typename strategy::distance::services::return_type @@ -194,7 +216,7 @@ public: if (check_intersection - && geometry::intersects(geometry, segment_or_box)) + && intersects::apply(geometry, segment_or_box, strategy)) { return 0; } diff --git a/include/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp b/include/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp index 7b81d68bb..dfd9d770e 100644 --- a/include/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp +++ b/include/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014, 2019, 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 @@ -40,7 +41,8 @@ struct linear_to_areal Areal const& areal, Strategy const& strategy) { - if ( geometry::intersects(linear, areal) ) + if ( geometry::intersects(linear, areal, + strategy.get_relate_segment_segment_strategy()) ) { return 0; } @@ -74,7 +76,8 @@ struct areal_to_areal Areal2 const& areal2, Strategy const& strategy) { - if ( geometry::intersects(areal1, areal2) ) + if ( geometry::intersects(areal1, areal2, + strategy.get_relate_segment_segment_strategy()) ) { return 0; } diff --git a/include/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp b/include/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp index 8f1b33cfb..da54f20a4 100644 --- a/include/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014, 2019, 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 @@ -113,19 +114,21 @@ template class multipoint_to_areal { private: + template struct not_covered_by_areal { - not_covered_by_areal(Areal const& areal) - : m_areal(areal) + not_covered_by_areal(Areal const& areal, CoveredByStrategy const& strategy) + : m_areal(areal), m_strategy(strategy) {} template inline bool apply(Point const& point) const { - return !geometry::covered_by(point, m_areal); + return !geometry::covered_by(point, m_areal, m_strategy); } Areal const& m_areal; + CoveredByStrategy const& m_strategy; }; public: @@ -140,11 +143,16 @@ public: Areal const& areal, Strategy const& strategy) { - not_covered_by_areal predicate(areal); + typedef not_covered_by_areal + < + typename Strategy::point_in_geometry_strategy_type + > predicate_type; + + predicate_type predicate(areal, strategy.get_point_in_geometry_strategy()); if (check_iterator_range < - not_covered_by_areal, false + predicate_type, false >::apply(boost::begin(multipoint), boost::end(multipoint), predicate)) 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 f41cf5c76..177eb19f1 100644 --- a/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp @@ -161,7 +161,8 @@ struct point_to_ring Strategy const& strategy) { // TODO: pass strategy - if (within::within_point_geometry(point, ring)) + if (within::within_point_geometry(point, ring, + strategy.get_point_in_geometry_strategy())) { return return_type(0); } @@ -206,7 +207,8 @@ private: for (InteriorRingIterator it = first; it != last; ++it) { // TODO: pass strategy - if (within::within_point_geometry(point, *it)) + if (within::within_point_geometry(point, *it, + strategy.get_point_in_geometry_strategy())) { // the point is inside a polygon hole, so its distance // to the polygon its distance to the polygon's @@ -236,7 +238,8 @@ public: Strategy const& strategy) { // TODO: pass strategy - if (! within::covered_by_point_geometry(point, exterior_ring(polygon))) + if (! within::covered_by_point_geometry(point, exterior_ring(polygon), + strategy.get_point_in_geometry_strategy())) { // the point is outside the exterior ring, so its distance // to the polygon is its distance to the polygon's exterior ring @@ -334,7 +337,8 @@ struct point_to_multigeometry Strategy const& strategy) { // TODO: pass strategy - if (within::covered_by_point_geometry(point, multipolygon)) + if (within::covered_by_point_geometry(point, multipolygon, + strategy.get_point_in_geometry_strategy())) { 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 d88a6699c..93ebebe18 100644 --- a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp +++ b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp @@ -542,10 +542,8 @@ private: SBStrategy const& sb_strategy, ReturnType& result) { - typedef typename geometry::strategy::side::services::default_strategy - < - typename geometry::cs_tag::type - >::type side; + typename SBStrategy::side_strategy_type + side_strategy = sb_strategy.get_side_strategy(); typedef cast_to_result cast; ReturnType diff1 = cast::apply(geometry::get<1>(p1)) @@ -555,12 +553,12 @@ private: sb_strategy.get_distance_ps_strategy(); int sign = diff1 < 0 ? -1 : 1; - if (side::apply(p0, p1, corner1) * sign < 0) + if (side_strategy.apply(p0, p1, corner1) * sign < 0) { result = cast::apply(ps_strategy.apply(corner1, p0, p1)); return true; } - if (side::apply(p0, p1, corner2) * sign > 0) + if (side_strategy.apply(p0, p1, corner2) * sign > 0) { result = cast::apply(ps_strategy.apply(corner2, p0, p1)); return true; @@ -682,7 +680,7 @@ public: BoxPoint const& bottom_right, SBStrategy const& sb_strategy) { - BOOST_GEOMETRY_ASSERT( geometry::less()(p0, p1) + BOOST_GEOMETRY_ASSERT( (geometry::less()(p0, p1)) || geometry::has_nan_coordinate(p0) || geometry::has_nan_coordinate(p1) ); @@ -782,15 +780,9 @@ public: >, typename strategy::distance::services::comparable_type < - typename detail::distance::default_strategy - < - segment_point, Box - >::type + typename SBStrategy::distance_pb_strategy::type >::type, - typename detail::distance::default_strategy - < - segment_point, Box - >::type + typename SBStrategy::distance_pb_strategy::type >::type point_box_strategy_type; return dispatch::distance @@ -809,7 +801,8 @@ public: bottom_left, bottom_right, top_left, top_right); - if (geometry::less()(p[0], p[1])) + typedef geometry::less less_type; + if (less_type()(p[0], p[1])) { return segment_to_box_2D < diff --git a/include/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp b/include/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp index bdf056d76..55380a3a8 100644 --- a/include/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp +++ b/include/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014, 2019, 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 @@ -70,7 +71,7 @@ public: apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& strategy) { - if (geometry::intersects(segment1, segment2)) + if (geometry::intersects(segment1, segment2, strategy.get_relate_segment_segment_strategy())) { return 0; } diff --git a/include/boost/geometry/algorithms/detail/intersection/interface.hpp b/include/boost/geometry/algorithms/detail/intersection/interface.hpp index 0efc9731b..a928e6ea5 100644 --- a/include/boost/geometry/algorithms/detail/intersection/interface.hpp +++ b/include/boost/geometry/algorithms/detail/intersection/interface.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, 2017, 2019. +// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -109,16 +109,25 @@ struct intersection < typename Geometry1, typename Geometry2, - typename RobustPolicy, typename GeometryOut, typename Strategy > static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - RobustPolicy const& robust_policy, GeometryOut & geometry_out, Strategy const& strategy) { + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2, + typename Strategy::cs_tag + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + return dispatch::intersection < Geometry1, @@ -131,15 +140,24 @@ struct intersection < typename Geometry1, typename Geometry2, - typename RobustPolicy, typename GeometryOut > static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - RobustPolicy const& robust_policy, GeometryOut & geometry_out, default_strategy) { + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2, + typename geometry::cs_tag::type + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + typedef typename strategy::relate::services::default_strategy < Geometry1, Geometry2 @@ -172,19 +190,8 @@ struct intersection concepts::check(); concepts::check(); - typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2 - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - return resolve_strategy::intersection::apply(geometry1, geometry2, - robust_policy, geometry_out, strategy); } 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 82818b099..3fc6ce6b8 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 @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2018, Oracle and/or its affiliates. +// Copyright (c) 2014-2019, 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 @@ -41,7 +41,7 @@ namespace detail { namespace is_valid template < typename Geometry, - typename IsAcceptableTurn = is_acceptable_turn + typename CSTag > class has_valid_self_turns { @@ -50,7 +50,8 @@ private: typedef typename geometry::rescale_policy_type < - point_type + point_type, + CSTag >::type rescale_policy_type; typedef detail::overlay::get_turn_info @@ -83,7 +84,7 @@ public: detail::overlay::stateless_predicate_based_interrupt_policy < - IsAcceptableTurn + is_acceptable_turn > interrupt_policy; detail::self_get_turn_points::self_turns(geometry, diff --git a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp index 25aa579f5..36c1979fb 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp @@ -317,7 +317,7 @@ public: // compute turns and check if all are acceptable debug_phase::apply(2); - typedef has_valid_self_turns has_valid_turns; + typedef has_valid_self_turns has_valid_turns; std::deque turns; bool has_invalid_turns = diff --git a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp index b799b383f..142500a9c 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -476,7 +476,7 @@ public: // compute turns and check if all are acceptable debug_phase::apply(3); - typedef has_valid_self_turns has_valid_turns; + typedef has_valid_self_turns has_valid_turns; std::deque turns; bool has_invalid_turns diff --git a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp index 8927b2a5e..2a377ee8c 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp @@ -209,7 +209,7 @@ struct is_valid_ring && ! has_duplicates::apply(ring, visitor) && ! has_spikes::apply(ring, visitor, strategy.get_side_strategy()) && (! CheckSelfIntersections - || has_valid_self_turns::apply(ring, visitor, strategy)) + || has_valid_self_turns::apply(ring, visitor, strategy)) && is_properly_oriented::apply(ring, visitor, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index f3fc32d74..6f36a44fe 100644 --- a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -193,7 +193,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, - Strategy::disjoint_point_box_strategy_type()) + typename Strategy::disjoint_point_box_strategy_type()) && within_selected_input(inner_in_map, inner.id, outer.id, m_geometry1, m_geometry2, m_collection, m_strategy) diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 60255cd95..58f10936c 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// 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, 2015, 2017, 2019. +// Modifications copyright (c) 2014-2019 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 @@ -1290,7 +1290,8 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1, typedef typename geometry::rescale_policy_type < - typename geometry::point_type::type // TODO from both + typename geometry::point_type::type, // TODO from both + typename Strategy::cs_tag >::type rescale_policy_type; rescale_policy_type robust_policy diff --git a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp index f0a7d6a7a..a6e66b03d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/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-2019, Oracle and/or its affiliates. // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html @@ -169,8 +169,7 @@ protected: LinearGeometry1, LinearGeometry2, assign_policy - >, - RobustPolicy + > >::apply(turns, linear1, linear2, interrupt_policy, strategy, robust_policy); } @@ -237,13 +236,12 @@ public: Linear1, Linear2, detail::get_turns::get_turn_info_type - < - Linear1, - Linear2, - assign_policy - >, - RobustPolicy - >::turn_info turn_info; + < + Linear1, + Linear2, + assign_policy + > + >::template turn_info_type::type turn_info; typedef std::vector turns_container; diff --git a/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp b/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp index f83162966..502a5b0bb 100644 --- a/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp +++ b/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.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, 2017. -// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017, 2019. +// Modifications copyright (c) 2015-2019 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 @@ -75,7 +75,7 @@ inline bool point_is_spike_or_equal(Point1 const& last_point, // prev | back Point3 const& segment_b, // curr | back - 1 | spike's vertex SideStrategy const& strategy) { - typedef SideStrategy::cs_tag cs_tag; + typedef typename SideStrategy::cs_tag cs_tag; int const side = strategy.apply(segment_a, segment_b, last_point); if (side == 0) diff --git a/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp index fa0ab1ea0..06192e38d 100644 --- a/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/areal_areal.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, 2014, 2015, 2017, 2018, 2019. +// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -223,7 +223,10 @@ struct areal_areal return; // get and analyse turns - typedef typename turns::get_turns::turn_info turn_type; + typedef typename turns::get_turns + < + Geometry1, Geometry2 + >::template turn_info_type::type turn_type; std::vector turns; interrupt_policy_areal_areal interrupt_policy(geometry1, geometry2, result); diff --git a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp index 81fc9e5b3..018565f2e 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_areal.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, 2014, 2015, 2017, 2018, 2019. +// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -219,21 +219,21 @@ struct linear_areal > {}; - template + template struct multi_turn_info - : turns::get_turns::turn_info + : turns::get_turns::template turn_info_type::type { multi_turn_info() : priority(0) {} int priority; // single-geometry sorting priority }; - template + template struct turn_info_type : boost::mpl::if_c < is_multi::value, - multi_turn_info, - typename turns::get_turns::turn_info + multi_turn_info, + typename turns::get_turns::template turn_info_type::type > {}; @@ -251,7 +251,7 @@ 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); diff --git a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp index 6c5d82fde..7be6bc788 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_linear.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, 2014, 2015, 2017, 2018, 2019. +// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -133,7 +133,10 @@ struct linear_linear return; // get and analyse turns - typedef typename turns::get_turns::turn_info turn_type; + typedef typename turns::get_turns + < + Geometry1, Geometry2 + >::template turn_info_type::type turn_type; std::vector turns; interrupt_policy_linear_linear interrupt_policy(result); 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 8dec5ccda..7f9e13839 100644 --- a/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2017-2018 Oracle and/or its affiliates. +// Copyright (c) 2017-2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -113,7 +113,7 @@ template struct multi_point_geometry_eb { // TODO: CS-specific less compare strategy derived from EqPPStrategy - typedef geometry::less<> less_type; + typedef geometry::less less_type; template struct boundary_visitor @@ -257,21 +257,23 @@ struct multi_point_single_geometry template class multi_point_multi_geometry_ii_ib { + template struct expand_box_point { template static inline void apply(Box& total, Point const& point) { - geometry::expand(total, point); + geometry::expand(total, point, ExpandPointStrategy()); } }; + template struct expand_box_box_pair { template static inline void apply(Box& total, BoxPair const& box_pair) { - geometry::expand(total, box_pair.first); + geometry::expand(total, box_pair.first, ExpandBoxStrategy()); } }; @@ -384,10 +386,18 @@ public: { 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 + < + typename Strategy::envelope_strategy_type::box_expand_strategy_type + > expand_box_box_pair_type; typedef overlaps_box_box_pair < typename Strategy::disjoint_box_box_strategy_type @@ -397,9 +407,9 @@ public: < box1_type >::apply(multi_point, boxes, visitor, - expand_box_point(), + expand_box_point_type(), overlaps_box_point_type(), - expand_box_box_pair(), + expand_box_box_pair_type(), overlaps_box_box_pair_type()); } @@ -431,7 +441,17 @@ struct multi_point_multi_geometry_ii_ib_ie Result & result, Strategy const& strategy) { - index::rtree > rt(boxes.begin(), boxes.end()); + typedef strategy::index::services::from_strategy + < + Strategy + > index_strategy_from; + typedef index::parameters + < + index::rstar<4>, typename index_strategy_from::type + > index_parameters_type; + index::rtree + rtree(boxes.begin(), boxes.end(), + index_parameters_type(index::rstar<4>(), index_strategy_from::get(strategy))); typedef typename boost::range_const_iterator::type iterator; for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) @@ -446,7 +466,7 @@ struct multi_point_multi_geometry_ii_ib_ie typename boost::range_value::type const& point = *it; boxes_type boxes_found; - rt.query(index::intersects(point), std::back_inserter(boxes_found)); + rtree.query(index::intersects(point), std::back_inserter(boxes_found)); bool found_ii_or_ib = false; for (boxes_iterator bi = boxes_found.begin() ; bi != boxes_found.end() ; ++bi) diff --git a/include/boost/geometry/algorithms/detail/relate/turns.hpp b/include/boost/geometry/algorithms/detail/relate/turns.hpp index 01c4304fa..ff3807f16 100644 --- a/include/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/include/boost/geometry/algorithms/detail/relate/turns.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// 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, 2014, 2015, 2017, 2019. +// Modifications copyright (c) 2013-2019 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 @@ -47,18 +47,30 @@ template typename GetTurnPolicy = detail::get_turns::get_turn_info_type < Geometry1, Geometry2, assign_policy<> - >, - typename RobustPolicy = typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2 - >::type + > > struct get_turns { typedef typename geometry::point_type::type point1_type; - typedef overlay::turn_info + template + struct robust_policy_type + : geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2, + typename Strategy::cs_tag + > + {}; + + template + < + typename Strategy, + typename RobustPolicy = typename robust_policy_type::type + > + struct turn_info_type + { + typedef overlay::turn_info < point1_type, typename segment_ratio_type::type, @@ -70,7 +82,8 @@ struct get_turns point1_type, RobustPolicy >::type >::type - > turn_info; + > type; + }; template static inline void apply(Turns & turns, @@ -94,15 +107,17 @@ struct get_turns InterruptPolicy & interrupt_policy, IntersectionStrategy const& intersection_strategy) { - RobustPolicy robust_policy = geometry::get_rescale_policy + typedef typename robust_policy_type::type robust_policy_t; + + robust_policy_t robust_policy = geometry::get_rescale_policy < - RobustPolicy + robust_policy_t >(geometry1, geometry2); apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy, robust_policy); } - template + template static inline void apply(Turns & turns, Geometry1 const& geometry1, Geometry2 const& geometry2, diff --git a/include/boost/geometry/algorithms/detail/within/multi_point.hpp b/include/boost/geometry/algorithms/detail/within/multi_point.hpp index 711c5b61c..66ae88240 100644 --- a/include/boost/geometry/algorithms/detail/within/multi_point.hpp +++ b/include/boost/geometry/algorithms/detail/within/multi_point.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2017 Oracle and/or its affiliates. +// Copyright (c) 2017, 2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -116,7 +116,7 @@ struct multi_point_single_geometry LinearOrAreal const& linear_or_areal, Strategy const& strategy) { - typedef typename boost::range_value::type point1_type; + //typedef typename boost::range_value::type point1_type; typedef typename point_type::type point2_type; typedef model::box box2_type; @@ -195,7 +195,17 @@ struct multi_point_multi_geometry } // Create R-tree - index::rtree > rtree(boxes.begin(), boxes.end()); + typedef strategy::index::services::from_strategy + < + Strategy + > index_strategy_from; + typedef index::parameters + < + index::rstar<4>, typename index_strategy_from::type + > index_parameters_type; + index::rtree + rtree(boxes.begin(), boxes.end(), + index_parameters_type(index::rstar<4>(), index_strategy_from::get(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/difference.hpp b/include/boost/geometry/algorithms/difference.hpp index c11ceca24..31216c78d 100644 --- a/include/boost/geometry/algorithms/difference.hpp +++ b/include/boost/geometry/algorithms/difference.hpp @@ -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, 2019. +// Modifications copyright (c) 2017, 2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -131,18 +131,27 @@ struct difference < typename Geometry1, typename Geometry2, - typename RobustPolicy, typename Collection, typename Strategy > static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - RobustPolicy const& robust_policy, Collection & output_collection, Strategy const& strategy) { typedef typename boost::range_value::type geometry_out; + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2, + typename Strategy::cs_tag + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + detail::difference::difference_insert( geometry1, geometry2, robust_policy, range::back_inserter(output_collection), @@ -153,17 +162,26 @@ struct difference < typename Geometry1, typename Geometry2, - typename RobustPolicy, typename Collection > static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - RobustPolicy const& robust_policy, Collection & output_collection, default_strategy) { typedef typename boost::range_value::type geometry_out; + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2, + typename geometry::cs_tag::type + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + detail::difference::difference_insert( geometry1, geometry2, robust_policy, range::back_inserter(output_collection)); @@ -185,18 +203,7 @@ struct difference Collection& output_collection, Strategy const& strategy) { - typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2 - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - resolve_strategy::difference::apply(geometry1, geometry2, - robust_policy, output_collection, strategy); } diff --git a/include/boost/geometry/algorithms/sym_difference.hpp b/include/boost/geometry/algorithms/sym_difference.hpp index 725230cd5..221d7bde3 100644 --- a/include/boost/geometry/algorithms/sym_difference.hpp +++ b/include/boost/geometry/algorithms/sym_difference.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2015, 2017. -// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017, 2019. +// Modifications copyright (c) 2015-2019 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 @@ -305,18 +305,27 @@ struct sym_difference < typename Geometry1, typename Geometry2, - typename RobustPolicy, typename Collection, typename Strategy > static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - RobustPolicy const& robust_policy, Collection & output_collection, Strategy const& strategy) { typedef typename boost::range_value::type geometry_out; + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2, + typename Strategy::cs_tag + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + detail::sym_difference::sym_difference_insert( geometry1, geometry2, robust_policy, range::back_inserter(output_collection), @@ -327,17 +336,26 @@ struct sym_difference < typename Geometry1, typename Geometry2, - typename RobustPolicy, typename Collection > static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - RobustPolicy const& robust_policy, Collection & output_collection, default_strategy) { typedef typename boost::range_value::type geometry_out; + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2, + typename geometry::cs_tag::type + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + detail::sym_difference::sym_difference_insert( geometry1, geometry2, robust_policy, range::back_inserter(output_collection)); @@ -359,18 +377,7 @@ struct sym_difference Collection& output_collection, Strategy const& strategy) { - typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2 - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - resolve_strategy::sym_difference::apply(geometry1, geometry2, - robust_policy, output_collection, strategy); } diff --git a/include/boost/geometry/algorithms/union.hpp b/include/boost/geometry/algorithms/union.hpp index d1d04d404..44619b4e5 100644 --- a/include/boost/geometry/algorithms/union.hpp +++ b/include/boost/geometry/algorithms/union.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. -// 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, 2017, 2018, 2019. +// Modifications copyright (c) 2014-2019 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 @@ -244,18 +244,27 @@ struct union_ < typename Geometry1, typename Geometry2, - typename RobustPolicy, typename Collection, typename Strategy > static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - RobustPolicy const& robust_policy, Collection & output_collection, Strategy const& strategy) { typedef typename boost::range_value::type geometry_out; + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2, + typename Strategy::cs_tag + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + dispatch::union_insert < Geometry1, Geometry2, geometry_out @@ -268,12 +277,10 @@ struct union_ < typename Geometry1, typename Geometry2, - typename RobustPolicy, typename Collection > static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, - RobustPolicy const& robust_policy, Collection & output_collection, default_strategy) { @@ -285,6 +292,17 @@ struct union_ Geometry2 >::type strategy_type; + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2, + typename geometry::cs_tag::type + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + dispatch::union_insert < Geometry1, Geometry2, geometry_out @@ -313,18 +331,7 @@ struct union_ concepts::check(); concepts::check::type>(); - typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2 - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - resolve_strategy::union_::apply(geometry1, geometry2, - robust_policy, output_collection, strategy); } From 970bce222f5f724e353c4209f9bf9e03e92ea9e2 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 24 Jun 2019 12:21:19 +0200 Subject: [PATCH 50/68] [test] Update tests WRT recent changes related to CS-specific strategies propagation. --- index/test/rtree/test_rtree.hpp | 18 ++++++++++++------ .../set_operations/check_turn_less.hpp | 15 +++++++++------ .../test_get_turns_ll_invariance.hpp | 14 ++++++++++---- test/strategies/test_within.hpp | 6 +++--- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/index/test/rtree/test_rtree.hpp b/index/test/rtree/test_rtree.hpp index 3433beefe..f937e768a 100644 --- a/index/test/rtree/test_rtree.hpp +++ b/index/test/rtree/test_rtree.hpp @@ -3,6 +3,10 @@ // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -922,10 +926,10 @@ struct covered_by_impl BOOST_FOREACH(Value const& v, input) { - if ( bg::covered_by( - bgi::detail::return_ref_or_bounds( - tree.indexable_get()(v)), - qbox) ) + if ( bgi::detail::covered_by_bounds( + tree.indexable_get()(v), + qbox, + bgi::detail::get_strategy(tree.parameters())) ) { expected_output.push_back(v); } @@ -1839,7 +1843,8 @@ void test_rtree_bounds(Parameters const& parameters, Allocator const& allocator) generate::rtree(t, input, qbox); - b = bgi::detail::rtree::values_box(input.begin(), input.end(), t.indexable_get()); + b = bgi::detail::rtree::values_box(input.begin(), input.end(), t.indexable_get(), + bgi::detail::get_strategy(parameters)); BOOST_CHECK(bg::equals(t.bounds(), b)); BOOST_CHECK(bg::equals(t.bounds(), bgi::bounds(t))); @@ -1851,7 +1856,8 @@ void test_rtree_bounds(Parameters const& parameters, Allocator const& allocator) input.pop_back(); } - b = bgi::detail::rtree::values_box(input.begin(), input.end(), t.indexable_get()); + b = bgi::detail::rtree::values_box(input.begin(), input.end(), t.indexable_get(), + bgi::detail::get_strategy(parameters)); BOOST_CHECK(bg::equals(t.bounds(), b)); diff --git a/test/algorithms/set_operations/check_turn_less.hpp b/test/algorithms/set_operations/check_turn_less.hpp index 980862810..0e9984d4a 100644 --- a/test/algorithms/set_operations/check_turn_less.hpp +++ b/test/algorithms/set_operations/check_turn_less.hpp @@ -1,12 +1,13 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2015, Oracle and/or its affiliates. +// Copyright (c) 2015, 2019, 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_CHECK_TURN_LESS_HPP #define BOOST_GEOMETRY_TEST_CHECK_TURN_LESS_HPP @@ -86,11 +87,13 @@ struct check_turn_less bg::detail::get_turns::get_turn_info_type < Geometry1, Geometry2, assign_policy<> - >, - robust_policy_type + > > get_turns_type; - typedef typename get_turns_type::turn_info turn_info; + typedef typename get_turns_type::template turn_info_type + < + strategy_type, robust_policy_type + >::type turn_info; typedef std::vector turns_container; 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 42a3a729d..22b01cab2 100644 --- a/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp +++ b/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp @@ -1,12 +1,13 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014, Oracle and/or its affiliates. +// Copyright (c) 2014, 2019, 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_GET_TURNS_LL_INVARIANCE_HPP #define BOOST_GEOMETRY_TEST_GET_TURNS_LL_INVARIANCE_HPP @@ -91,10 +92,15 @@ public: static inline void apply(Linear1 const& lineargeometry1, Linear2 const& lineargeometry2) { + typedef typename bg::strategy::relate::services::default_strategy + < + Linear1, Linear2 + >::type strategy_type; + typedef typename bg_detail::relate::turns::get_turns < Linear1, Linear2 - >::turn_info turn_info; + >::template turn_info_type::type turn_info; typedef std::vector turns_container; diff --git a/test/strategies/test_within.hpp b/test/strategies/test_within.hpp index d47080ccf..ae9b06dde 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. -// Modifications copyright (c) 2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2019. +// Modifications copyright (c) 2014, 2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -72,7 +72,7 @@ void test_point_in_polygon(std::string const& case_id, bool expected, bool use_within = true) { - BOOST_CONCEPT_ASSERT( (bg::concepts::WithinStrategyPolygonal) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::WithinStrategyPolygonal) ); bool detected = use_within ? bg::within(point, polygon, strategy) : bg::covered_by(point, polygon, strategy); From 5e0e1cf75c9166a731effc609b579995c7f0883b Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Mon, 24 Jun 2019 14:17:46 +0300 Subject: [PATCH 51/68] [strategy] Put bisection method for distance pt-sgmt into detail namespace --- .../geographic/distance_cross_track.hpp | 80 ++++++++++++++++--- .../distance/test_distance_geo_common.hpp | 2 +- test/strategies/distance_cross_track.cpp | 6 +- 3 files changed, 75 insertions(+), 13 deletions(-) diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index 3c4bd311f..7d868cd91 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -64,6 +64,8 @@ namespace boost { namespace geometry namespace strategy { namespace distance { +namespace detail +{ /*! \brief Strategy functor for distance point to segment calculation on ellipsoid Algorithm uses direct and inverse geodesic problems as subroutines. @@ -681,7 +683,37 @@ private : Spheroid m_spheroid; }; +} // namespace detail +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid, + typename CalculationType = void +> +class geographic_cross_track + : public detail::geographic_cross_track + < + FormulaPolicy, + Spheroid, + CalculationType, + false, + false + > +{ +public : + explicit geographic_cross_track(Spheroid const& spheroid = Spheroid()) + : + detail::geographic_cross_track< + FormulaPolicy, + Spheroid, + CalculationType, + false, + false + >(spheroid) + {} + +}; #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS namespace services @@ -722,12 +754,11 @@ template typename CalculationType, bool Bisection > -struct tag > +struct tag > { typedef strategy_tag_distance_point_segment type; }; - //return types template struct return_type, P, PS> @@ -766,11 +797,26 @@ template typename P, typename PS > -struct return_type, P, PS> - : geographic_cross_track::template return_type +struct return_type, P, PS> + : detail::geographic_cross_track::template return_type {}; //comparable types +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType +> +struct comparable_type > +{ + typedef geographic_cross_track + < + FormulaPolicy, Spheroid, CalculationType + > type; +}; + + template < typename FormulaPolicy, @@ -778,14 +824,30 @@ template typename CalculationType, bool Bisection > -struct comparable_type > +struct comparable_type > { - typedef geographic_cross_track + typedef detail::geographic_cross_track < FormulaPolicy, Spheroid, CalculationType, Bisection > type; }; +template +< + typename FormulaPolicy, + typename Spheroid, + typename CalculationType +> +struct get_comparable > +{ +public : + static inline geographic_cross_track + apply(geographic_cross_track const& strategy) + { + return strategy; + } +}; + template < typename FormulaPolicy, @@ -793,11 +855,11 @@ template typename CalculationType, bool Bisection > -struct get_comparable > +struct get_comparable > { public : - static inline geographic_cross_track - apply(geographic_cross_track const& strategy) + static inline detail::geographic_cross_track + apply(detail::geographic_cross_track const& strategy) { return strategy; } diff --git a/test/algorithms/distance/test_distance_geo_common.hpp b/test/algorithms/distance/test_distance_geo_common.hpp index 252759cfe..dfb4c7e64 100644 --- a/test/algorithms/distance/test_distance_geo_common.hpp +++ b/test/algorithms/distance/test_distance_geo_common.hpp @@ -71,7 +71,7 @@ typedef bg::strategy::distance::geographic_cross_track vincenty_ps; -typedef bg::strategy::distance::geographic_cross_track +typedef bg::strategy::distance::detail::geographic_cross_track vincenty_ps_bisection; // Spherical strategy for point-box distance diff --git a/test/strategies/distance_cross_track.cpp b/test/strategies/distance_cross_track.cpp index cd54a1b93..42207b285 100644 --- a/test/strategies/distance_cross_track.cpp +++ b/test/strategies/distance_cross_track.cpp @@ -66,7 +66,7 @@ void test_all(expected_results const& results) }; //vincenty - double distance = bg::strategy::distance::geographic_cross_track(spheroid) + double distance = bg::strategy::distance::detail::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); check_result(distance, results.vincenty_bisection, results.reference, errors[0]); @@ -75,7 +75,7 @@ void test_all(expected_results const& results) check_result(distance, results.vincenty, results.reference, errors[0]); //thomas - distance = bg::strategy::distance::geographic_cross_track(spheroid) + distance = bg::strategy::distance::detail::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); check_result(distance, results.thomas_bisection, results.reference, errors[1]); @@ -84,7 +84,7 @@ void test_all(expected_results const& results) check_result(distance, results.thomas, results.reference, errors[1]); //andoyer - distance = bg::strategy::distance::geographic_cross_track(spheroid) + distance = bg::strategy::distance::detail::geographic_cross_track(spheroid) .apply(Point(lon3r, lat3r), Point(lon1r, lat1r), Point(lon2r, lat2r)); check_result(distance, results.andoyer_bisection, results.reference, errors[2]); From 283a0bc571a8f59d761e849528a810b125786278 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 26 Jun 2019 14:45:42 +0200 Subject: [PATCH 52/68] [buffer] fix line/line intersection point calculation for some cases, now using general form (which will be used later more widely). This fixes some numerical issues. Including testcase, reported as #596 --- .../detail/buffer/line_line_intersection.hpp | 41 +++++++++---------- test/algorithms/buffer/buffer_linestring.cpp | 11 +++++ 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp b/include/boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp index 618afe5fb..11f1c689a 100644 --- a/include/boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2012-2019 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 @@ -10,7 +10,6 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP -#include #include #include #include @@ -35,14 +34,19 @@ struct line_line_intersection static inline strategy::buffer::join_selector apply(Point const& pi, Point const& pj, Point const& qi, Point const& qj, Point& ip) { - // See http://mathworld.wolfram.com/Line-LineIntersection.html - typedef typename coordinate_type::type coordinate_type; + typedef typename coordinate_type::type ct; - coordinate_type const denominator - = determinant(get<0>(pi) - get<0>(pj), - get<1>(pi) - get<1>(pj), - get<0>(qi) - get<0>(qj), - get<1>(qi) - get<1>(qj)); + // Construct lines in general form (ax + by + c = 0), + // (will be replaced by a general_form structure in a next PR) + ct const pa = get<1>(pi) - get<1>(pj); + ct const pb = get<0>(pj) - get<0>(pi); + ct const pc = -pa * get<0>(pi) - pb * get<1>(pi); + + ct const qa = get<1>(qi) - get<1>(qj); + ct const qb = get<0>(qj) - get<0>(qi); + ct const qc = -qa * get<0>(qi) - qb * get<1>(qi); + + ct const denominator = pb * qa - pa * qb; // Even if the corner was checked before (so it is convex now), that // was done on the original geometry. This function runs on the buffered @@ -51,27 +55,20 @@ struct line_line_intersection // to check it again. // For round joins, it will not be used at all. - // For miter joints, there is a miter limit + // For miter joins, there is a miter limit // If segments are parallel/collinear we must be distinguish two cases: // they continue each other, or they form a spike - if (math::equals(denominator, coordinate_type())) + ct const zero = ct(); + if (math::equals(denominator, zero)) { - return parallel_continue(get<0>(qj) - get<0>(qi), - get<1>(qj) - get<1>(qi), - get<0>(pj) - get<0>(pi), - get<1>(pj) - get<1>(pi)) + return parallel_continue(qb, -qa, pb, -pa) ? strategy::buffer::join_continue : strategy::buffer::join_spike ; } - coordinate_type d1 = determinant(get<0>(pi), get<1>(pi), get<0>(pj), get<1>(pj)); - coordinate_type d2 = determinant(get<0>(qi), get<1>(qi), get<0>(qj), get<1>(qj)); - - double const multiplier = 1.0 / denominator; - - set<0>(ip, determinant(d1, get<0>(pi) - get<0>(pj), d2, get<0>(qi) - get<0>(qj)) * multiplier); - set<1>(ip, determinant(d1, get<1>(pi) - get<1>(pj), d2, get<1>(qi) - get<1>(qj)) * multiplier); + set<0>(ip, (pc * qb - pb * qc) / denominator); + set<1>(ip, (pa * qc - pc * qa) / denominator); return strategy::buffer::join_convex; } diff --git a/test/algorithms/buffer/buffer_linestring.cpp b/test/algorithms/buffer/buffer_linestring.cpp index b4e17fabe..83e72e235 100644 --- a/test/algorithms/buffer/buffer_linestring.cpp +++ b/test/algorithms/buffer/buffer_linestring.cpp @@ -106,6 +106,8 @@ static std::string const mysql_23023665 = "LINESTRING(0 0, 0 5, 5 5, 5 0, 0 0)"; static std::string const mysql_25662426 = "LINESTRING(170 4756, 168 4756, 168 4759, 168 4764, 171 4764, 171 4700)"; static std::string const mysql_25662426a = "LINESTRING(170 4756, 168 4756, 168 4759, 168 4764, 171 4764, 171 4750)"; +static std::string const issue_596 = "LINESTRING(292979.660 6688731.370, 292979.600 6688733.420, 292979.540 6688735.440, 292979.540 6688735.500)"; + template void test_all() { @@ -281,6 +283,15 @@ void test_all() test_one("mikado1", mikado1, join_round32, end_round32, 5441135039.0979, 41751.0); + { + // This case gave a spike (invalid result) up to 1.70 + // Fixed by general form for line/line intersection in miter calculation + using bg::strategy::buffer::join_round; + using bg::strategy::buffer::end_round; + test_one("issue_596", issue_596, join_round(12), end_round(12), 0.12462779, 0.015); + test_one("issue_596", issue_596, join_miter, end_round(12), 0.12462807, 0.015); + } + test_one("mysql_report_2015_06_11", mysql_report_2015_06_11, join_round32, end_round32, 27862.733459829971, From 6dcf062d8f2fc9e7092d851512ccee3c719c30d2 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 26 Jun 2019 14:51:54 +0200 Subject: [PATCH 53/68] [valid] Fix warning (iterator variables shadow earlier declarations) by moving the code to a specific function --- .../algorithms/detail/is_valid/has_spikes.hpp | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) 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 8bb6e3bce..7dd8d5459 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -92,6 +92,35 @@ struct has_spikes return std::find_if(second, last, not_equal(*first)); } + template + static inline bool apply_at_closure(View const& view, VisitPolicy& visitor, + SideStrategy const& strategy, + bool is_linear) + { + boost::ignore_unused(visitor); + + typedef typename boost::range_iterator::type iterator; + + iterator cur = boost::begin(view); + typename boost::range_reverse_iterator + < + View const + >::type prev = find_different_from_first(boost::rbegin(view), + boost::rend(view)); + + iterator next = find_different_from_first(cur, boost::end(view)); + if (detail::is_spike_or_equal(*next, *cur, *prev, strategy)) + { + return + ! visitor.template apply(is_linear, *cur); + } + else + { + return ! visitor.template apply(); + } + } + + template static inline bool apply(Range const& range, VisitPolicy& visitor, SideStrategy const& strategy) @@ -142,23 +171,7 @@ struct has_spikes if (geometry::equals(range::front(view), range::back(view))) { - iterator cur = boost::begin(view); - typename boost::range_reverse_iterator - < - view_type const - >::type prev = find_different_from_first(boost::rbegin(view), - boost::rend(view)); - - iterator next = find_different_from_first(cur, boost::end(view)); - if (detail::is_spike_or_equal(*next, *cur, *prev, strategy)) - { - return - ! visitor.template apply(is_linear, *cur); - } - else - { - return ! visitor.template apply(); - } + return apply_at_closure(view, visitor, strategy, is_linear); } return ! visitor.template apply(); From c905acf9640a3b6c80ebb293820a415b4615894a Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 26 Jun 2019 14:53:35 +0200 Subject: [PATCH 54/68] [const] disable various compiler warnings --- .../algorithms/detail/is_valid/multipolygon.hpp | 4 ++-- .../algorithms/detail/is_valid/polygon.hpp | 3 ++- .../detail/overlay/handle_colocations.hpp | 2 +- .../algorithms/detail/overlay/sort_by_side.hpp | 2 +- .../algorithms/detail/overlay/traversal.hpp | 15 +++++++++------ include/boost/geometry/io/wkt/write.hpp | 2 +- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp index 8fe580332..575ad33d3 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp @@ -283,8 +283,8 @@ public: { typedef debug_validity_phase debug_phase; - if (BOOST_GEOMETRY_CONDITION( - AllowEmptyMultiGeometries && boost::empty(multipolygon))) + if (BOOST_GEOMETRY_CONDITION(AllowEmptyMultiGeometries) + && boost::empty(multipolygon)) { return visitor.template apply(); } diff --git a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp index 834ce5af2..88b0df4e5 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -76,7 +76,6 @@ template class is_valid_polygon { protected: - typedef debug_validity_phase debug_phase; template struct per_ring @@ -121,6 +120,7 @@ protected: VisitPolicy& visitor, Strategy const& strategy) { + typedef debug_validity_phase debug_phase; typedef typename ring_type::type ring_type; // check validity of exterior ring @@ -451,6 +451,7 @@ public: } // compute turns and check if all are acceptable + typedef debug_validity_phase debug_phase; debug_phase::apply(3); typedef has_valid_self_turns has_valid_turns; diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp index 1ba54ae6b..c417e7d1a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp @@ -932,7 +932,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns, continue; } - if (OverlayType != overlay_difference + if (BOOST_GEOMETRY_CONDITION(OverlayType != overlay_difference) && is_self_turn(turn)) { // Difference needs the self-turns, TODO: investigate 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 eae68403e..d6ec05f16 100644 --- a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp @@ -368,7 +368,7 @@ public : void find_open() { - if (OverlayType == overlay_buffer) + if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_buffer)) { // For buffers, use piece index std::map handled; diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp index ee993e0d9..9eb94636a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp @@ -282,7 +282,7 @@ public : { // For uu/ii, only switch sources if indicated - if (OverlayType == overlay_buffer) + if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_buffer)) { // Buffer does not use source_index (always 0). return select_source_generic<&segment_identifier::multi_index>( @@ -391,7 +391,8 @@ public : return true; } - if (OverlayType == overlay_buffer && possible[0] && possible[1]) + if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_buffer) + && possible[0] && possible[1]) { // Buffers sometimes have multiple overlapping pieces, where remaining // distance could lead to the wrong choice. Take the matching operation. @@ -565,7 +566,7 @@ public : result = select_cc_operation(turn, start_turn_index, selected_op_index); } - else if (OverlayType == overlay_dissolve) + else if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_dissolve)) { result = select_preferred_operation(turn, turn_index, start_turn_index, selected_op_index); @@ -636,7 +637,7 @@ public : return 0; } - if (OverlayType != overlay_dissolve + if (BOOST_GEOMETRY_CONDITION(OverlayType != overlay_dissolve) && (op.enriched.count_left != 0 || op.enriched.count_right == 0)) { // Check counts: in some cases interior rings might be generated with @@ -897,7 +898,8 @@ public : // Points to different target return false; } - if (OverlayType == overlay_buffer && target.turn_index > 0) + if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_buffer) + && target.turn_index > 0) { // Target already assigned, so there are more targets // or more ways to the same target @@ -1028,7 +1030,8 @@ public : turn_operation_type const& start_op, int start_op_index) const { - if (OverlayType != overlay_buffer && OverlayType != overlay_dissolve) + if (BOOST_GEOMETRY_CONDITION(OverlayType != overlay_buffer + && OverlayType != overlay_dissolve)) { return; } diff --git a/include/boost/geometry/io/wkt/write.hpp b/include/boost/geometry/io/wkt/write.hpp index 62d1d6cb4..9796edd1b 100644 --- a/include/boost/geometry/io/wkt/write.hpp +++ b/include/boost/geometry/io/wkt/write.hpp @@ -159,7 +159,7 @@ struct wkt_range } // optionally, close range to ring by repeating the first point - if (ForceClosurePossible + if (BOOST_GEOMETRY_CONDITION(ForceClosurePossible) && force_closure && boost::size(range) > 1 && wkt_range::disjoint(*begin, *(end - 1))) From e46c6ee70f5cde1148e5af351eb949853f6553d4 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Wed, 26 Jun 2019 14:54:58 +0200 Subject: [PATCH 55/68] [fix] add method which was added later, for integer types --- .../geometry/algorithms/detail/overlay/get_distance_measure.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp index f879e850b..a306cb442 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp @@ -35,6 +35,7 @@ struct distance_measure bool is_small() const { return true; } bool is_zero() const { return true; } bool is_positive() const { return false; } + bool is_negative() const { return false; } }; template From 39e19c469c3864dd1c25c5c0d429889c0d262cc3 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 28 Jun 2019 14:12:40 +0200 Subject: [PATCH 56/68] [algorithms] Remove typedef in is_valid. --- .../boost/geometry/algorithms/detail/is_valid/polygon.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp index 142500a9c..c0abe5696 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -419,15 +419,17 @@ protected: VisitPolicy& visitor, Strategy const& ) { - typedef typename Strategy::cs_tag cs_tag; - boost::ignore_unused(visitor); typedef typename std::iterator_traits < TurnIterator >::value_type turn_type; - typedef complement_graph graph; + typedef complement_graph + < + typename turn_type::point_type, + typename Strategy::cs_tag + > graph; graph g(geometry::num_interior_rings(polygon) + 1); for (TurnIterator tit = first; tit != beyond; ++tit) From b4634fdb4520d722246ebfa06682fbd111cfe4d8 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 28 Jun 2019 14:35:28 +0200 Subject: [PATCH 57/68] [algorithms][io] Add missing includes. --- .../geometry/algorithms/detail/overlay/sort_by_side.hpp | 6 ++++-- include/boost/geometry/io/wkt/write.hpp | 7 +++++-- 2 files changed, 9 insertions(+), 4 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 d6ec05f16..93219060c 100644 --- a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2015 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, 2019. +// Modifications copyright (c) 2017, 2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -24,6 +24,8 @@ #include #include +#include + namespace boost { namespace geometry { diff --git a/include/boost/geometry/io/wkt/write.hpp b/include/boost/geometry/io/wkt/write.hpp index 9796edd1b..3daecadb4 100644 --- a/include/boost/geometry/io/wkt/write.hpp +++ b/include/boost/geometry/io/wkt/write.hpp @@ -5,10 +5,11 @@ // Copyright (c) 2009-2017 Mateusz Loskot, London, UK. // Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2015, 2018. -// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2018, 2019. +// Modifications copyright (c) 2015-2019, 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 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -45,6 +46,8 @@ #include +#include + namespace boost { namespace geometry { From 03fdd412b04c730b685b386643d395e712141422 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 28 Jun 2019 21:43:03 +0200 Subject: [PATCH 58/68] [strategies] Add envelope_box_strategy_type to intersection strategies. --- include/boost/geometry/strategies/cartesian/intersection.hpp | 1 + include/boost/geometry/strategies/geographic/intersection.hpp | 1 + include/boost/geometry/strategies/spherical/intersection.hpp | 1 + 3 files changed, 3 insertions(+) diff --git a/include/boost/geometry/strategies/cartesian/intersection.hpp b/include/boost/geometry/strategies/cartesian/intersection.hpp index 61ff25957..22272426c 100644 --- a/include/boost/geometry/strategies/cartesian/intersection.hpp +++ b/include/boost/geometry/strategies/cartesian/intersection.hpp @@ -184,6 +184,7 @@ struct cartesian_segments typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type; typedef covered_by::cartesian_point_box covered_by_point_box_strategy_type; typedef within::cartesian_point_box within_point_box_strategy_type; + typedef envelope::cartesian_box envelope_box_strategy_type; typedef expand::cartesian_box expand_box_strategy_type; template diff --git a/include/boost/geometry/strategies/geographic/intersection.hpp b/include/boost/geometry/strategies/geographic/intersection.hpp index 9fbf90f69..a4d13c9bf 100644 --- a/include/boost/geometry/strategies/geographic/intersection.hpp +++ b/include/boost/geometry/strategies/geographic/intersection.hpp @@ -197,6 +197,7 @@ struct geographic_segments typedef covered_by::spherical_point_box disjoint_point_box_strategy_type; typedef covered_by::spherical_point_box covered_by_point_box_strategy_type; typedef within::spherical_point_box within_point_box_strategy_type; + typedef envelope::spherical_box envelope_box_strategy_type; typedef expand::spherical_box expand_box_strategy_type; enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 }; diff --git a/include/boost/geometry/strategies/spherical/intersection.hpp b/include/boost/geometry/strategies/spherical/intersection.hpp index 7b1c6af95..e0d807a96 100644 --- a/include/boost/geometry/strategies/spherical/intersection.hpp +++ b/include/boost/geometry/strategies/spherical/intersection.hpp @@ -202,6 +202,7 @@ struct ecef_segments typedef covered_by::spherical_point_box disjoint_point_box_strategy_type; typedef covered_by::spherical_point_box covered_by_point_box_strategy_type; typedef within::spherical_point_box within_point_box_strategy_type; + typedef envelope::spherical_box envelope_box_strategy_type; typedef expand::spherical_box expand_box_strategy_type; enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 }; From 850c58f4644d336e1b09d2ebba0358ac95c7cef5 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 28 Jun 2019 21:43:55 +0200 Subject: [PATCH 59/68] [strategies] Add getters for expand box strategies in envelope box strategies. --- .../strategies/cartesian/envelope_box.hpp | 13 ++- .../strategies/spherical/envelope_box.hpp | 82 ++--------------- .../strategies/spherical/expand_box.hpp | 91 +++++++++++++++++-- 3 files changed, 101 insertions(+), 85 deletions(-) diff --git a/include/boost/geometry/strategies/cartesian/envelope_box.hpp b/include/boost/geometry/strategies/cartesian/envelope_box.hpp index c6dd21835..b05f4f6e7 100644 --- a/include/boost/geometry/strategies/cartesian/envelope_box.hpp +++ b/include/boost/geometry/strategies/cartesian/envelope_box.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-2018. -// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2019. +// Modifications copyright (c) 2015-2019, 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 @@ -32,6 +32,8 @@ #include +#include + #include @@ -78,6 +80,13 @@ namespace strategy { namespace envelope struct cartesian_box { + typedef typename strategy::expand::cartesian_box box_expand_strategy_type; + + static inline box_expand_strategy_type get_box_expand_strategy() + { + return box_expand_strategy_type(); + } + template static inline void apply(BoxIn const& box_in, BoxOut& mbr) { diff --git a/include/boost/geometry/strategies/spherical/envelope_box.hpp b/include/boost/geometry/strategies/spherical/envelope_box.hpp index 5a080f4a6..768a9c076 100644 --- a/include/boost/geometry/strategies/spherical/envelope_box.hpp +++ b/include/boost/geometry/strategies/spherical/envelope_box.hpp @@ -18,23 +18,8 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_BOX_HPP #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_BOX_HPP -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - -#include +#include #include @@ -42,73 +27,18 @@ namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace envelope -{ - - -template -< - std::size_t Index, - std::size_t DimensionCount -> -struct envelope_indexed_box_on_spheroid -{ - template - static inline void apply(BoxIn const& box_in, BoxOut& mbr) - { - // transform() does not work with boxes of dimension higher - // than 2; to account for such boxes we transform the min/max - // points of the boxes using the indexed_point_view - detail::indexed_point_view box_in_corner(box_in); - detail::indexed_point_view mbr_corner(mbr); - - // first transform the units - transform_units(box_in_corner, mbr_corner); - - // now transform the remaining coordinates - detail::conversion::point_to_point - < - detail::indexed_point_view, - detail::indexed_point_view, - 2, - DimensionCount - >::apply(box_in_corner, mbr_corner); - } -}; - - -}} // namespace detail::envelope -#endif // DOXYGEN_NO_DETAIL - - namespace strategy { namespace envelope { struct spherical_box + : geometry::detail::envelope::envelope_box_on_spheroid { - template - static inline void apply(BoxIn const& box_in, BoxOut& mbr) + typedef typename strategy::expand::spherical_box box_expand_strategy_type; + + static inline box_expand_strategy_type get_box_expand_strategy() { - // BoxIn can be non-mutable - typename helper_geometry::type box_in_normalized; - geometry::convert(box_in, box_in_normalized); - - if (! is_inverse_spheroidal_coordinates(box_in)) - { - strategy::normalize::spherical_box::apply(box_in, box_in_normalized); - } - - geometry::detail::envelope::envelope_indexed_box_on_spheroid - < - min_corner, dimension::value - >::apply(box_in_normalized, mbr); - - geometry::detail::envelope::envelope_indexed_box_on_spheroid - < - max_corner, dimension::value - >::apply(box_in_normalized, mbr); + return box_expand_strategy_type(); } }; diff --git a/include/boost/geometry/strategies/spherical/expand_box.hpp b/include/boost/geometry/strategies/spherical/expand_box.hpp index e3801861b..e4bfafadd 100644 --- a/include/boost/geometry/strategies/spherical/expand_box.hpp +++ b/include/boost/geometry/strategies/spherical/expand_box.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. -// This file was modified by Oracle on 2015, 2016, 2017, 2018. -// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016, 2017, 2018, 2019. +// Modifications copyright (c) 2015-2019, 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 @@ -19,18 +19,95 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_BOX_HPP #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_BOX_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 envelope +{ + +template +< + std::size_t Index, + std::size_t DimensionCount +> +struct envelope_indexed_box_on_spheroid +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + // transform() does not work with boxes of dimension higher + // than 2; to account for such boxes we transform the min/max + // points of the boxes using the indexed_point_view + detail::indexed_point_view box_in_corner(box_in); + detail::indexed_point_view mbr_corner(mbr); + + // first transform the units + transform_units(box_in_corner, mbr_corner); + + // now transform the remaining coordinates + detail::conversion::point_to_point + < + detail::indexed_point_view, + detail::indexed_point_view, + 2, + DimensionCount + >::apply(box_in_corner, mbr_corner); + } +}; + +struct envelope_box_on_spheroid +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + // BoxIn can be non-mutable + typename helper_geometry::type box_in_normalized; + geometry::convert(box_in, box_in_normalized); + + if (! is_inverse_spheroidal_coordinates(box_in)) + { + strategy::normalize::spherical_box::apply(box_in, box_in_normalized); + } + + geometry::detail::envelope::envelope_indexed_box_on_spheroid + < + min_corner, dimension::value + >::apply(box_in_normalized, mbr); + + geometry::detail::envelope::envelope_indexed_box_on_spheroid + < + max_corner, dimension::value + >::apply(box_in_normalized, mbr); + } +}; + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + namespace strategy { namespace expand { @@ -45,8 +122,8 @@ struct box_on_spheroid { // normalize both boxes and convert box-in to be of type of box-out BoxOut mbrs[2]; - strategy::envelope::spherical_box::apply(box_in, mbrs[0]); - strategy::envelope::spherical_box::apply(box_out, mbrs[1]); + geometry::detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]); + geometry::detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]); // compute the envelope of the two boxes geometry::detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out); From 614c05423e73916882ab518c468698b8297a6b08 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 28 Jun 2019 21:45:01 +0200 Subject: [PATCH 60/68] [algorithms] Pass strategy into get_rescale_policy() internally used to get envelope and expand strategies. --- include/boost/geometry/algorithms/buffer.hpp | 3 +- .../detail/has_self_intersections.hpp | 6 +- .../detail/intersection/interface.hpp | 20 +- .../detail/is_valid/has_valid_self_turns.hpp | 2 +- .../detail/overlay/intersection_insert.hpp | 3 +- .../algorithms/detail/relate/turns.hpp | 7 +- .../boost/geometry/algorithms/difference.hpp | 45 ++-- .../geometry/algorithms/sym_difference.hpp | 45 ++-- include/boost/geometry/algorithms/union.hpp | 37 +-- .../extensions/algorithms/dissolve.hpp | 10 +- .../robustness/get_rescale_policy.hpp | 233 ++++++++++++++++-- 11 files changed, 275 insertions(+), 136 deletions(-) diff --git a/include/boost/geometry/algorithms/buffer.hpp b/include/boost/geometry/algorithms/buffer.hpp index c7343c4bb..6321d9905 100644 --- a/include/boost/geometry/algorithms/buffer.hpp +++ b/include/boost/geometry/algorithms/buffer.hpp @@ -248,7 +248,8 @@ inline void buffer(GeometryIn const& geometry_in, >::type intersection_strategy; rescale_policy_type rescale_policy - = boost::geometry::get_rescale_policy(box); + = boost::geometry::get_rescale_policy( + box, intersection_strategy); detail::buffer::buffer_inserter(geometry_in, range::back_inserter(geometry_out), distance_strategy, diff --git a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp index 1289d946a..82ace9d0a 100644 --- a/include/boost/geometry/algorithms/detail/has_self_intersections.hpp +++ b/include/boost/geometry/algorithms/detail/has_self_intersections.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2011-2012 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, 2019. +// Modifications copyright (c) 2017, 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, @@ -150,7 +150,7 @@ inline bool has_self_intersections(Geometry const& geometry, >::type strategy; rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry); + = geometry::get_rescale_policy(geometry, strategy); return has_self_intersections(geometry, strategy, robust_policy, throw_on_self_intersection); diff --git a/include/boost/geometry/algorithms/detail/intersection/interface.hpp b/include/boost/geometry/algorithms/detail/intersection/interface.hpp index a928e6ea5..3a688b9a8 100644 --- a/include/boost/geometry/algorithms/detail/intersection/interface.hpp +++ b/include/boost/geometry/algorithms/detail/intersection/interface.hpp @@ -125,8 +125,8 @@ struct intersection >::type rescale_policy_type; rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); + = geometry::get_rescale_policy( + geometry1, geometry2, strategy); return dispatch::intersection < @@ -154,21 +154,21 @@ struct intersection typename geometry::cs_tag::type >::type rescale_policy_type; - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - - typedef typename strategy::relate::services::default_strategy + typename strategy::relate::services::default_strategy < Geometry1, Geometry2 - >::type strategy_type; - + >::type strategy; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy( + geometry1, geometry2, strategy); + return dispatch::intersection < Geometry1, Geometry2 >::apply(geometry1, geometry2, robust_policy, geometry_out, - strategy_type()); + strategy); } }; 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 3fc6ce6b8..1978e8309 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 @@ -80,7 +80,7 @@ public: boost::ignore_unused(visitor); rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry); + = geometry::get_rescale_policy(geometry, strategy); detail::overlay::stateless_predicate_based_interrupt_policy < diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 58f10936c..5e55d9db2 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -1295,7 +1295,8 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1, >::type rescale_policy_type; rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, geometry2); + = geometry::get_rescale_policy( + geometry1, geometry2, strategy); return detail::intersection::insert < diff --git a/include/boost/geometry/algorithms/detail/relate/turns.hpp b/include/boost/geometry/algorithms/detail/relate/turns.hpp index ff3807f16..1ea6c4dba 100644 --- a/include/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/include/boost/geometry/algorithms/detail/relate/turns.hpp @@ -109,10 +109,9 @@ struct get_turns { typedef typename robust_policy_type::type robust_policy_t; - robust_policy_t robust_policy = geometry::get_rescale_policy - < - robust_policy_t - >(geometry1, geometry2); + robust_policy_t robust_policy + = geometry::get_rescale_policy( + geometry1, geometry2, intersection_strategy); apply(turns, geometry1, geometry2, interrupt_policy, intersection_strategy, robust_policy); } diff --git a/include/boost/geometry/algorithms/difference.hpp b/include/boost/geometry/algorithms/difference.hpp index 31216c78d..7a96e130d 100644 --- a/include/boost/geometry/algorithms/difference.hpp +++ b/include/boost/geometry/algorithms/difference.hpp @@ -55,13 +55,11 @@ template typename GeometryOut, typename Geometry1, typename Geometry2, - typename RobustPolicy, typename OutputIterator, typename Strategy > inline OutputIterator difference_insert(Geometry1 const& geometry1, Geometry2 const& geometry2, - RobustPolicy const& robust_policy, OutputIterator out, Strategy const& strategy) { @@ -69,6 +67,17 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, concepts::check(); concepts::check(); + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2, + typename Strategy::cs_tag + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy( + geometry1, geometry2, strategy); + return geometry::dispatch::intersection_insert < Geometry1, Geometry2, @@ -100,12 +109,10 @@ template typename GeometryOut, typename Geometry1, typename Geometry2, - typename RobustPolicy, typename OutputIterator > inline OutputIterator difference_insert(Geometry1 const& geometry1, Geometry2 const& geometry2, - RobustPolicy const& robust_policy, OutputIterator out) { typedef typename strategy::relate::services::default_strategy @@ -114,8 +121,8 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, Geometry2 >::type strategy_type; - return difference_insert(geometry1, geometry2, - robust_policy, out, strategy_type()); + return difference_insert(geometry1, geometry2, out, + strategy_type()); } @@ -141,19 +148,8 @@ struct difference { typedef typename boost::range_value::type geometry_out; - typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2, - typename Strategy::cs_tag - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - detail::difference::difference_insert( - geometry1, geometry2, robust_policy, + geometry1, geometry2, range::back_inserter(output_collection), strategy); } @@ -171,19 +167,8 @@ struct difference { typedef typename boost::range_value::type geometry_out; - typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2, - typename geometry::cs_tag::type - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - detail::difference::difference_insert( - geometry1, geometry2, robust_policy, + geometry1, geometry2, range::back_inserter(output_collection)); } }; diff --git a/include/boost/geometry/algorithms/sym_difference.hpp b/include/boost/geometry/algorithms/sym_difference.hpp index 221d7bde3..a281bf1db 100644 --- a/include/boost/geometry/algorithms/sym_difference.hpp +++ b/include/boost/geometry/algorithms/sym_difference.hpp @@ -234,13 +234,11 @@ template typename GeometryOut, typename Geometry1, typename Geometry2, - typename RobustPolicy, typename OutputIterator, typename Strategy > inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, Geometry2 const& geometry2, - RobustPolicy const& robust_policy, OutputIterator out, Strategy const& strategy) { @@ -248,6 +246,17 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, concepts::check(); concepts::check(); + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2, + typename Strategy::cs_tag + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy( + geometry1, geometry2, strategy); + return dispatch::sym_difference_insert < Geometry1, Geometry2, GeometryOut @@ -274,12 +283,10 @@ template typename GeometryOut, typename Geometry1, typename Geometry2, - typename RobustPolicy, typename OutputIterator > inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, - Geometry2 const& geometry2, - RobustPolicy const& robust_policy, OutputIterator out) + Geometry2 const& geometry2, OutputIterator out) { concepts::check(); concepts::check(); @@ -290,7 +297,7 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, typename cs_tag::type >::type strategy_type; - return sym_difference_insert(geometry1, geometry2, robust_policy, out, strategy_type()); + return sym_difference_insert(geometry1, geometry2, out, strategy_type()); } }} // namespace detail::sym_difference @@ -315,19 +322,8 @@ struct sym_difference { typedef typename boost::range_value::type geometry_out; - typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2, - typename Strategy::cs_tag - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - detail::sym_difference::sym_difference_insert( - geometry1, geometry2, robust_policy, + geometry1, geometry2, range::back_inserter(output_collection), strategy); } @@ -345,19 +341,8 @@ struct sym_difference { typedef typename boost::range_value::type geometry_out; - typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2, - typename geometry::cs_tag::type - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - detail::sym_difference::sym_difference_insert( - geometry1, geometry2, robust_policy, + geometry1, geometry2, range::back_inserter(output_collection)); } }; diff --git a/include/boost/geometry/algorithms/union.hpp b/include/boost/geometry/algorithms/union.hpp index 44619b4e5..de4779562 100644 --- a/include/boost/geometry/algorithms/union.hpp +++ b/include/boost/geometry/algorithms/union.hpp @@ -211,19 +211,20 @@ inline OutputIterator union_insert(Geometry1 const& geometry1, concepts::check(); concepts::check(); + typename strategy::intersection::services::default_strategy + < + typename cs_tag::type + >::type strategy; + typedef typename geometry::rescale_overlay_policy_type < Geometry1, Geometry2 >::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(geometry1, geometry2); + = geometry::get_rescale_policy( + geometry1, geometry2, strategy); return dispatch::union_insert < @@ -262,8 +263,8 @@ struct union_ >::type rescale_policy_type; rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); + = geometry::get_rescale_policy( + geometry1, geometry2, strategy); dispatch::union_insert < @@ -284,31 +285,13 @@ struct union_ Collection & output_collection, default_strategy) { - typedef typename boost::range_value::type geometry_out; - typedef typename strategy::relate::services::default_strategy < Geometry1, Geometry2 >::type strategy_type; - typedef typename geometry::rescale_overlay_policy_type - < - Geometry1, - Geometry2, - typename geometry::cs_tag::type - >::type rescale_policy_type; - - rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry1, - geometry2); - - dispatch::union_insert - < - Geometry1, Geometry2, geometry_out - >::apply(geometry1, geometry2, robust_policy, - range::back_inserter(output_collection), - strategy_type()); + apply(geometry1, geometry2, output_collection, strategy_type()); } }; diff --git a/include/boost/geometry/extensions/algorithms/dissolve.hpp b/include/boost/geometry/extensions/algorithms/dissolve.hpp index c0c5bfbe4..080371bdc 100644 --- a/include/boost/geometry/extensions/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/algorithms/dissolve.hpp @@ -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, 2019. +// Modifications 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, @@ -452,7 +452,8 @@ inline OutputIterator dissolve_inserter(Geometry const& geometry, >::type rescale_policy_type; rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry); + = geometry::get_rescale_policy( + geometry, strategy); detail::overlay::overlay_null_visitor visitor; @@ -519,7 +520,8 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection, >::type rescale_policy_type; rescale_policy_type robust_policy - = geometry::get_rescale_policy(geometry); + = geometry::get_rescale_policy( + geometry, strategy); detail::overlay::overlay_null_visitor visitor; diff --git a/include/boost/geometry/policies/robustness/get_rescale_policy.hpp b/include/boost/geometry/policies/robustness/get_rescale_policy.hpp index fd677ec2b..4fa04fe41 100644 --- a/include/boost/geometry/policies/robustness/get_rescale_policy.hpp +++ b/include/boost/geometry/policies/robustness/get_rescale_policy.hpp @@ -92,29 +92,45 @@ inline void scale_box_to_integer_range(Box const& box, assign_values(min_robust_point, min_coordinate, min_coordinate); } -template +template +< + typename Point, typename RobustPoint, typename Geometry, + typename Factor, typename EnvelopeStrategy +> static inline void init_rescale_policy(Geometry const& geometry, Point& min_point, RobustPoint& min_robust_point, - Factor& factor) + Factor& factor, + EnvelopeStrategy const& strategy) { if (geometry::is_empty(geometry)) { return; } - // Get bounding boxes - model::box env = geometry::return_envelope >(geometry); + // Get bounding box + model::box env = geometry::return_envelope + < + model::box + >(geometry, strategy); scale_box_to_integer_range(env, min_point, min_robust_point, factor); } -template +// NOTE: Actually it should take 2 separate strategies, one for each geometry +// in case one of them was e.g. a Box +template +< + typename Point, typename RobustPoint, typename Geometry1, typename Geometry2, + typename Factor, typename EnvelopeStrategy1, typename EnvelopeStrategy2 +> static inline void init_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2, Point& min_point, RobustPoint& min_robust_point, - Factor& factor) + Factor& factor, + EnvelopeStrategy1 const& strategy1, + EnvelopeStrategy2 const& strategy2) { // Get bounding boxes (when at least one of the geometries is not empty) bool const is_empty1 = geometry::is_empty(geometry1); @@ -127,11 +143,11 @@ static inline void init_rescale_policy(Geometry1 const& geometry1, model::box env; if (is_empty1) { - geometry::envelope(geometry2, env); + geometry::envelope(geometry2, env, strategy2); } else if (is_empty2) { - geometry::envelope(geometry1, env); + geometry::envelope(geometry1, env, strategy1); } else { @@ -139,12 +155,12 @@ static inline void init_rescale_policy(Geometry1 const& geometry1, // optimal MBR when then two geometries are in the spherical // equatorial or geographic coordinate systems. // TODO: implement envelope for two (or possibly more geometries) - geometry::envelope(geometry1, env); + geometry::envelope(geometry1, env, strategy1); model::box env2 = geometry::return_envelope < model::box - >(geometry2); - geometry::expand(env, env2); + >(geometry2, strategy2); + geometry::expand(env, env2, strategy1.get_box_expand_strategy()); } scale_box_to_integer_range(env, min_point, min_robust_point, factor); @@ -182,8 +198,9 @@ struct rescale_policy_type template struct get_rescale_policy { - template - static inline Policy apply(Geometry const& geometry) + template + static inline Policy apply(Geometry const& geometry, + EnvelopeStrategy const& strategy) { typedef typename point_type::type point_type; typedef typename geometry::coordinate_type::type coordinate_type; @@ -198,13 +215,16 @@ struct get_rescale_policy point_type min_point; robust_point_type min_robust_point; factor_type factor; - init_rescale_policy(geometry, min_point, min_robust_point, factor); + init_rescale_policy(geometry, min_point, min_robust_point, + factor, strategy); return Policy(min_point, min_robust_point, factor); } - template - static inline Policy apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + template + static inline Policy apply(Geometry1 const& geometry1, Geometry2 const& geometry2, + EnvelopeStrategy1 const& strategy1, + EnvelopeStrategy2 const& strategy2) { typedef typename point_type::type point_type; typedef typename geometry::coordinate_type::type coordinate_type; @@ -219,7 +239,8 @@ struct get_rescale_policy point_type min_point; robust_point_type min_robust_point; factor_type factor; - init_rescale_policy(geometry1, geometry2, min_point, min_robust_point, factor); + init_rescale_policy(geometry1, geometry2, min_point, min_robust_point, + factor, strategy1, strategy2); return Policy(min_point, min_robust_point, factor); } @@ -229,14 +250,15 @@ struct get_rescale_policy template <> struct get_rescale_policy { - template - static inline no_rescale_policy apply(Geometry const& ) + template + static inline no_rescale_policy apply(Geometry const& , EnvelopeStrategy const&) { return no_rescale_policy(); } - template - static inline no_rescale_policy apply(Geometry1 const& , Geometry2 const& ) + template + static inline no_rescale_policy apply(Geometry1 const& , Geometry2 const& , + EnvelopeStrategy1 const& , EnvelopeStrategy2 const& ) { return no_rescale_policy(); } @@ -331,16 +353,177 @@ 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) { - return detail::get_rescale_policy::get_rescale_policy::apply(geometry); + typename geometry::strategy::envelope::services::default_strategy + < + typename geometry::tag::type, + typename geometry::cs_tag::type + >::type strategy; + + return detail::get_rescale_policy::get_rescale_policy::apply(geometry, strategy); } -template -inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2) +template +inline Policy get_rescale_policy(Geometry const& geometry, Geometry2OrStrategy const& geometry2_or_strategy) { - return detail::get_rescale_policy::get_rescale_policy::apply(geometry1, geometry2); + // 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 + < + Geometry2OrStrategy + > ::template apply(geometry, geometry2_or_strategy); +} + +template +inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2, + IntersectionStrategy 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)); } From f17be7dabaa350472e7290ee5864fea6d30afdde Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 28 Jun 2019 21:47:36 +0200 Subject: [PATCH 61/68] [test][algorithms] Update tests due to change of arguments in difference_insert and sym_difference_insert. --- test/algorithms/overlay/assemble.cpp | 16 +++++++--------- .../difference/test_difference.hpp | 15 ++++----------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/test/algorithms/overlay/assemble.cpp b/test/algorithms/overlay/assemble.cpp index 7be262fd7..78965692a 100644 --- a/test/algorithms/overlay/assemble.cpp +++ b/test/algorithms/overlay/assemble.cpp @@ -3,6 +3,11 @@ // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2019. +// Modifications 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) @@ -41,18 +46,11 @@ template inline void test_assemble(std::string const& id, Geometry const& p, Geometry const& q, char operation = 'i') { - typedef typename bg::point_type::type point_type; - typedef typename bg::rescale_policy_type::type - rescale_policy_type; - rescale_policy_type rescale_policy - = bg::get_rescale_policy(p, q); - - std::vector u, i, d1, d2; bg::detail::union_::union_insert(p, q, std::back_inserter(u)); bg::detail::intersection::intersection_insert(p, q, std::back_inserter(i)); - bg::detail::difference::difference_insert(p, q, rescale_policy, std::back_inserter(d1)); - bg::detail::difference::difference_insert(q, p, rescale_policy, std::back_inserter(d2)); + bg::detail::difference::difference_insert(p, q, std::back_inserter(d1)); + bg::detail::difference::difference_insert(q, p, std::back_inserter(d2)); if (operation == 'i') { diff --git a/test/algorithms/set_operations/difference/test_difference.hpp b/test/algorithms/set_operations/difference/test_difference.hpp index f1b6c02cc..b1e479fcf 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. -// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2016, 2017, 2019. +// Modifications copyright (c) 2016-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, @@ -209,13 +209,6 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g { // Test inserter functionality // Test if inserter returns output-iterator (using Boost.Range copy) - typedef typename bg::point_type::type point_type; - typedef typename bg::rescale_policy_type::type - rescale_policy_type; - - rescale_policy_type rescale_policy - = bg::get_rescale_policy(g1, g2); - typename setop_output_type::type inserted, array_with_one_empty_geometry; array_with_one_empty_geometry.push_back(OutputType()); @@ -223,13 +216,13 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g { boost::copy(array_with_one_empty_geometry, bg::detail::sym_difference::sym_difference_insert - (g1, g2, rescale_policy, std::back_inserter(inserted))); + (g1, g2, std::back_inserter(inserted))); } else { boost::copy(array_with_one_empty_geometry, bg::detail::difference::difference_insert( - g1, g2, rescale_policy, std::back_inserter(inserted))); + g1, g2, std::back_inserter(inserted))); } BOOST_CHECK_EQUAL(boost::size(result), boost::size(inserted) - 1); From b73a401480a0de685b3ca1b8c62ad02ccbd913d2 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 28 Jun 2019 23:25:46 +0200 Subject: [PATCH 62/68] [test] Add cs::undefined tests. --- test/Jamfile.v2 | 5 +- test/cs_undefined/Jamfile.v2 | 20 ++ test/cs_undefined/common.hpp | 69 +++++++ test/cs_undefined/distance.cpp | 113 +++++++++++ test/cs_undefined/envelope_expand.cpp | 53 +++++ test/cs_undefined/index.cpp | 101 +++++++++ test/cs_undefined/is.cpp | 44 ++++ test/cs_undefined/measure.cpp | 51 +++++ test/cs_undefined/other.cpp | 40 ++++ test/cs_undefined/relops.cpp | 228 +++++++++++++++++++++ test/cs_undefined/setops.cpp | 281 ++++++++++++++++++++++++++ 11 files changed, 1003 insertions(+), 2 deletions(-) create mode 100644 test/cs_undefined/Jamfile.v2 create mode 100644 test/cs_undefined/common.hpp create mode 100644 test/cs_undefined/distance.cpp create mode 100644 test/cs_undefined/envelope_expand.cpp create mode 100644 test/cs_undefined/index.cpp create mode 100644 test/cs_undefined/is.cpp create mode 100644 test/cs_undefined/measure.cpp create mode 100644 test/cs_undefined/other.cpp create mode 100644 test/cs_undefined/relops.cpp create mode 100644 test/cs_undefined/setops.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7e24f0e48..d179fe7c3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -4,8 +4,8 @@ # Copyright (c) 2008-2012 Bruno Lalande, Paris, France. # Copyright (c) 2009-2018 Mateusz Loskot, London, UK. # -# This file was modified by Oracle on 2017, 2018. -# Modifications copyright (c) 2017-2018 Oracle and/or its affiliates. +# This file was modified by Oracle on 2017, 2018, 2019. +# Modifications copyright (c) 2017-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, @@ -49,6 +49,7 @@ build-project strategies ; build-project policies ; build-project io ; build-project srs ; +build-project cs_undefined ; build-project util ; build-project views ; diff --git a/test/cs_undefined/Jamfile.v2 b/test/cs_undefined/Jamfile.v2 new file mode 100644 index 000000000..f0ea382da --- /dev/null +++ b/test/cs_undefined/Jamfile.v2 @@ -0,0 +1,20 @@ +# 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/LICENSE_1_0.txt) + +test-suite boost-geometry-cs_undefined + : + [ compile distance.cpp : : csundef_distance ] + [ compile envelope_expand.cpp : : csundef_envelope_expand ] + [ compile index.cpp : : csundef_index ] + [ compile is.cpp : : csundef_is ] + [ compile measure.cpp : : csundef_measure ] + [ compile other.cpp : : csundef_other ] + [ compile relops.cpp : : csundef_relops ] + [ compile setops.cpp : : csundef_setops ] + ; diff --git a/test/cs_undefined/common.hpp b/test/cs_undefined/common.hpp new file mode 100644 index 000000000..92cb80680 --- /dev/null +++ b/test/cs_undefined/common.hpp @@ -0,0 +1,69 @@ +// 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_TEST_CS_UNDEFINED_COMMON_HPP +#define BOOST_GEOMETRY_TEST_CS_UNDEFINED_COMMON_HPP + +#include + +#include + +#include + +#include + +struct geom +{ + //typedef bg::model::point point; + typedef bg::model::point point; + typedef bg::model::box box; + typedef bg::model::segment segment; + typedef bg::model::linestring linestring; + typedef bg::model::ring ring; + typedef bg::model::polygon polygon; + typedef bg::model::multi_linestring multi_linestring; + typedef bg::model::multi_polygon multi_polygon; + typedef bg::model::multi_point multi_point; + + geom() + { + pt = point(0, 0); + b = box(point(-1, -1), point(1, 1)); + s = segment(point(0, 0), point(1, 1)); + ls.push_back(point(0, 0)); + ls.push_back(point(1, 1)); + ls.push_back(point(1.1, 1.1)); + r.push_back(point(0, 0)); + r.push_back(point(0, 1)); + r.push_back(point(1, 1)); + r.push_back(point(1, 0)); + r.push_back(point(0, 0)); + po.outer() = r; + po.inners().push_back(ring()); + po.inners().back().push_back(point(0, 0)); + po.inners().back().push_back(point(0.2, 0.1)); + po.inners().back().push_back(point(0.1, 0.2)); + po.inners().back().push_back(point(0, 0)); + mls.push_back(ls); + mpo.push_back(po); + mpt.push_back(pt); + } + + point pt; + box b; + segment s; + linestring ls; + ring r; + polygon po; + multi_linestring mls; + multi_polygon mpo; + multi_point mpt; +}; + +#endif // BOOST_GEOMETRY_TEST_CS_UNDEFINED_COMMON_HPP diff --git a/test/cs_undefined/distance.cpp b/test/cs_undefined/distance.cpp new file mode 100644 index 000000000..8bd03a44c --- /dev/null +++ b/test/cs_undefined/distance.cpp @@ -0,0 +1,113 @@ +// 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 + +#include "common.hpp" + +#include + +int test_main(int, char*[]) +{ + geom g; + + bg::distance(g.pt, g.pt, bg::strategy::distance::pythagoras<>()); + bg::distance(g.pt, g.pt, bg::strategy::distance::haversine<>()); + bg::distance(g.pt, g.pt, bg::strategy::distance::geographic<>()); + bg::distance(g.pt, g.mpt, bg::strategy::distance::pythagoras<>()); + bg::distance(g.pt, g.mpt, bg::strategy::distance::haversine<>()); + bg::distance(g.pt, g.mpt, bg::strategy::distance::geographic<>()); + bg::distance(g.mpt, g.mpt, bg::strategy::distance::pythagoras<>()); + bg::distance(g.mpt, g.mpt, bg::strategy::distance::haversine<>()); + bg::distance(g.mpt, g.mpt, bg::strategy::distance::geographic<>()); + bg::distance(g.pt, g.ls, bg::strategy::distance::projected_point<>()); + bg::distance(g.pt, g.ls, bg::strategy::distance::cross_track<>()); + bg::distance(g.pt, g.ls, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.pt, g.mls, bg::strategy::distance::projected_point<>()); + bg::distance(g.pt, g.mls, bg::strategy::distance::cross_track<>()); + bg::distance(g.pt, g.mls, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mpt, g.ls, bg::strategy::distance::projected_point<>()); + bg::distance(g.mpt, g.ls, bg::strategy::distance::cross_track<>()); + bg::distance(g.mpt, g.ls, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mpt, g.mls, bg::strategy::distance::projected_point<>()); + bg::distance(g.mpt, g.mls, bg::strategy::distance::cross_track<>()); + bg::distance(g.mpt, g.mls, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.ls, g.ls, bg::strategy::distance::projected_point<>()); + bg::distance(g.ls, g.ls, bg::strategy::distance::cross_track<>()); + bg::distance(g.ls, g.ls, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.ls, g.mls, bg::strategy::distance::projected_point<>()); + bg::distance(g.ls, g.mls, bg::strategy::distance::cross_track<>()); + bg::distance(g.ls, g.mls, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mls, g.mls, bg::strategy::distance::projected_point<>()); + bg::distance(g.mls, g.mls, bg::strategy::distance::cross_track<>()); + bg::distance(g.mls, g.mls, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.pt, g.r, bg::strategy::distance::projected_point<>()); + bg::distance(g.pt, g.r, bg::strategy::distance::cross_track<>()); + bg::distance(g.pt, g.r, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.pt, g.po, bg::strategy::distance::projected_point<>()); + bg::distance(g.pt, g.po, bg::strategy::distance::cross_track<>()); + bg::distance(g.pt, g.po, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.pt, g.mpo, bg::strategy::distance::projected_point<>()); + bg::distance(g.pt, g.mpo, bg::strategy::distance::cross_track<>()); + bg::distance(g.pt, g.mpo, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mpt, g.r, bg::strategy::distance::projected_point<>()); + bg::distance(g.mpt, g.r, bg::strategy::distance::cross_track<>()); + bg::distance(g.mpt, g.r, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mpt, g.po, bg::strategy::distance::projected_point<>()); + bg::distance(g.mpt, g.po, bg::strategy::distance::cross_track<>()); + bg::distance(g.mpt, g.po, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mpt, g.mpo, bg::strategy::distance::projected_point<>()); + bg::distance(g.mpt, g.mpo, bg::strategy::distance::cross_track<>()); + bg::distance(g.mpt, g.mpo, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.ls, g.r, bg::strategy::distance::projected_point<>()); + bg::distance(g.ls, g.r, bg::strategy::distance::cross_track<>()); + bg::distance(g.ls, g.r, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.ls, g.po, bg::strategy::distance::projected_point<>()); + bg::distance(g.ls, g.po, bg::strategy::distance::cross_track<>()); + bg::distance(g.ls, g.po, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.ls, g.mpo, bg::strategy::distance::projected_point<>()); + bg::distance(g.ls, g.mpo, bg::strategy::distance::cross_track<>()); + bg::distance(g.ls, g.mpo, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mls, g.r, bg::strategy::distance::projected_point<>()); + bg::distance(g.mls, g.r, bg::strategy::distance::cross_track<>()); + bg::distance(g.mls, g.r, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mls, g.po, bg::strategy::distance::projected_point<>()); + bg::distance(g.mls, g.po, bg::strategy::distance::cross_track<>()); + bg::distance(g.mls, g.po, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mls, g.mpo, bg::strategy::distance::projected_point<>()); + bg::distance(g.mls, g.mpo, bg::strategy::distance::cross_track<>()); + bg::distance(g.mls, g.mpo, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.r, g.r, bg::strategy::distance::projected_point<>()); + bg::distance(g.r, g.r, bg::strategy::distance::cross_track<>()); + bg::distance(g.r, g.r, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.r, g.po, bg::strategy::distance::projected_point<>()); + bg::distance(g.r, g.po, bg::strategy::distance::cross_track<>()); + bg::distance(g.r, g.po, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.r, g.mpo, bg::strategy::distance::projected_point<>()); + bg::distance(g.r, g.mpo, bg::strategy::distance::cross_track<>()); + bg::distance(g.r, g.mpo, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.po, g.r, bg::strategy::distance::projected_point<>()); + bg::distance(g.po, g.r, bg::strategy::distance::cross_track<>()); + bg::distance(g.po, g.r, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.po, g.po, bg::strategy::distance::projected_point<>()); + bg::distance(g.po, g.po, bg::strategy::distance::cross_track<>()); + bg::distance(g.po, g.po, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.po, g.mpo, bg::strategy::distance::projected_point<>()); + bg::distance(g.po, g.mpo, bg::strategy::distance::cross_track<>()); + bg::distance(g.po, g.mpo, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mpo, g.r, bg::strategy::distance::projected_point<>()); + bg::distance(g.mpo, g.r, bg::strategy::distance::cross_track<>()); + bg::distance(g.mpo, g.r, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mpo, g.po, bg::strategy::distance::projected_point<>()); + bg::distance(g.mpo, g.po, bg::strategy::distance::cross_track<>()); + bg::distance(g.mpo, g.po, bg::strategy::distance::geographic_cross_track<>()); + bg::distance(g.mpo, g.mpo, bg::strategy::distance::projected_point<>()); + bg::distance(g.mpo, g.mpo, bg::strategy::distance::cross_track<>()); + bg::distance(g.mpo, g.mpo, bg::strategy::distance::geographic_cross_track<>()); + + return 0; +} diff --git a/test/cs_undefined/envelope_expand.cpp b/test/cs_undefined/envelope_expand.cpp new file mode 100644 index 000000000..5d16e6f25 --- /dev/null +++ b/test/cs_undefined/envelope_expand.cpp @@ -0,0 +1,53 @@ +// 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 + +#include "common.hpp" + +#include +#include + +int test_main(int, char*[]) +{ + geom g; + + bg::expand(g.b, g.pt, bg::strategy::expand::cartesian_point()); + bg::expand(g.b, g.pt, bg::strategy::expand::spherical_point()); + bg::expand(g.b, g.b, bg::strategy::expand::cartesian_box()); + bg::expand(g.b, g.b, bg::strategy::expand::spherical_box()); + bg::expand(g.b, g.s, bg::strategy::expand::cartesian_segment()); + bg::expand(g.b, g.s, bg::strategy::expand::spherical_segment<>()); + bg::expand(g.b, g.s, bg::strategy::expand::geographic_segment<>()); + + bg::envelope(g.pt, g.b, bg::strategy::envelope::cartesian_point()); + bg::envelope(g.pt, g.b, bg::strategy::envelope::spherical_point()); + bg::envelope(g.b, g.b, bg::strategy::envelope::cartesian_box()); + bg::envelope(g.b, g.b, bg::strategy::envelope::spherical_box()); + bg::envelope(g.s, g.b, bg::strategy::envelope::cartesian_segment<>()); + bg::envelope(g.s, g.b, bg::strategy::envelope::spherical_segment<>()); + bg::envelope(g.s, g.b, bg::strategy::envelope::geographic_segment<>()); + bg::envelope(g.ls, g.b, bg::strategy::envelope::cartesian<>()); + bg::envelope(g.ls, g.b, bg::strategy::envelope::spherical<>()); + bg::envelope(g.ls, g.b, bg::strategy::envelope::geographic<>()); + bg::envelope(g.r, g.b, bg::strategy::envelope::cartesian<>()); + bg::envelope(g.r, g.b, bg::strategy::envelope::spherical<>()); + bg::envelope(g.r, g.b, bg::strategy::envelope::geographic<>()); + bg::envelope(g.po, g.b, bg::strategy::envelope::cartesian<>()); + bg::envelope(g.po, g.b, bg::strategy::envelope::spherical<>()); + bg::envelope(g.po, g.b, bg::strategy::envelope::geographic<>()); + bg::envelope(g.mls, g.b, bg::strategy::envelope::cartesian<>()); + bg::envelope(g.mls, g.b, bg::strategy::envelope::spherical<>()); + bg::envelope(g.mls, g.b, bg::strategy::envelope::geographic<>()); + bg::envelope(g.mpo, g.b, bg::strategy::envelope::cartesian<>()); + bg::envelope(g.mpo, g.b, bg::strategy::envelope::spherical<>()); + bg::envelope(g.mpo, g.b, bg::strategy::envelope::geographic<>()); + bg::envelope(g.mpt, g.b, bg::strategy::envelope::cartesian_multipoint()); + bg::envelope(g.mpt, g.b, bg::strategy::envelope::spherical_multipoint()); + + return 0; +} diff --git a/test/cs_undefined/index.cpp b/test/cs_undefined/index.cpp new file mode 100644 index 000000000..008187044 --- /dev/null +++ b/test/cs_undefined/index.cpp @@ -0,0 +1,101 @@ +// 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 + +#include "common.hpp" + +// These includes are required for the following code to compile. +// This is probably wrong. +#include +#include +#include +#include + +#include + +#include + +namespace bgi = boost::geometry::index; + +template +< + typename VG, typename QG, + typename VTag = typename bg::tag::type, + typename QTag = typename bg::tag::type +> +struct call_query +{ + template + static inline void apply(Rtree const& , Res const& ) + {} +}; + +template +struct call_query +{ + template + static inline void apply(Rtree const& rtree, QG const& qg) + { + std::vector res; + rtree.query(bgi::intersects(qg), std::back_inserter(res)); + } +}; + +template +inline void rtree_test(G const& g, P const& p) +{ + { + bgi::rtree rtree; + } + + std::vector de2(100, g); + + bgi::rtree rtree(de2, p); + rtree.insert(g); + rtree.remove(g); + rtree.count(g); + + call_query::apply(rtree, geom::point(0, 0)); +} + +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::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::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<> >()); + + return 0; +} diff --git a/test/cs_undefined/is.cpp b/test/cs_undefined/is.cpp new file mode 100644 index 000000000..c043d301b --- /dev/null +++ b/test/cs_undefined/is.cpp @@ -0,0 +1,44 @@ +// 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 + +#include "common.hpp" + +#include +#include + +template +inline void is(G const& g, S const& s) +{ + bg::is_simple(g, s); + bg::is_valid(g, s); +} + +template +inline void is_x(G const& g) +{ + ::is(g, bg::strategy::intersection::cartesian_segments<>()); + ::is(g, bg::strategy::intersection::spherical_segments<>()); + ::is(g, bg::strategy::intersection::geographic_segments<>()); +} + +int test_main(int, char*[]) +{ + geom g; + + ::is_x(g.pt); + ::is_x(g.mpt); + ::is_x(g.s); + ::is_x(g.ls); + ::is_x(g.mls); + ::is_x(g.r); + ::is_x(g.po); + ::is_x(g.mpo); + + return 0; +} diff --git a/test/cs_undefined/measure.cpp b/test/cs_undefined/measure.cpp new file mode 100644 index 000000000..40d8a4f97 --- /dev/null +++ b/test/cs_undefined/measure.cpp @@ -0,0 +1,51 @@ +// 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 + +#include "common.hpp" + +#include +#include +#include + +int test_main(int, char*[]) +{ + geom g; + + bg::area(g.r, bg::strategy::area::cartesian<>()); + bg::area(g.r, bg::strategy::area::spherical<>()); + bg::area(g.r, bg::strategy::area::geographic<>()); + bg::area(g.po, bg::strategy::area::cartesian<>()); + bg::area(g.po, bg::strategy::area::spherical<>()); + bg::area(g.po, bg::strategy::area::geographic<>()); + bg::area(g.mpo, bg::strategy::area::cartesian<>()); + bg::area(g.mpo, bg::strategy::area::spherical<>()); + bg::area(g.mpo, bg::strategy::area::geographic<>()); + + bg::length(g.s, bg::strategy::distance::pythagoras<>()); + bg::length(g.s, bg::strategy::distance::haversine<>()); + bg::length(g.s, bg::strategy::distance::geographic<>()); + bg::length(g.ls, bg::strategy::distance::pythagoras<>()); + bg::length(g.ls, bg::strategy::distance::haversine<>()); + bg::length(g.ls, bg::strategy::distance::geographic<>()); + bg::length(g.mls, bg::strategy::distance::pythagoras<>()); + bg::length(g.mls, bg::strategy::distance::haversine<>()); + bg::length(g.mls, bg::strategy::distance::geographic<>()); + + bg::perimeter(g.r, bg::strategy::distance::pythagoras<>()); + bg::perimeter(g.r, bg::strategy::distance::haversine<>()); + bg::perimeter(g.r, bg::strategy::distance::geographic<>()); + bg::perimeter(g.po, bg::strategy::distance::pythagoras<>()); + bg::perimeter(g.po, bg::strategy::distance::haversine<>()); + bg::perimeter(g.po, bg::strategy::distance::geographic<>()); + bg::perimeter(g.mpo, bg::strategy::distance::pythagoras<>()); + bg::perimeter(g.mpo, bg::strategy::distance::haversine<>()); + bg::perimeter(g.mpo, bg::strategy::distance::geographic<>()); + + return 0; +} diff --git a/test/cs_undefined/other.cpp b/test/cs_undefined/other.cpp new file mode 100644 index 000000000..fe2ad6501 --- /dev/null +++ b/test/cs_undefined/other.cpp @@ -0,0 +1,40 @@ +// 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 + +#include "common.hpp" + +#include +#include + +template +inline void simplify(G const& g1, G & g2) +{ + bg::simplify(g1, g2, 1, bg::strategy::simplify::douglas_peucker >()); + bg::simplify(g1, g2, 1, bg::strategy::simplify::douglas_peucker >()); + + // TODO: douglas_peucker does not define a ctor taking distance strategy + // which is needed in geographic CS + bg::simplify(g1, g2, 1, bg::strategy::simplify::douglas_peucker >()); +} + +int test_main(int, char*[]) +{ + geom g, o; + + // this compiles but it shouldn't! + // internally default_strategy is defined as not_applicable_strategy for box + bg::centroid(g.b, o.pt); + + ::simplify(g.ls, o.ls); + // TODO: + //::simplify(g.r, o.r); // area (point order) strategy not propagated + //::simplify(g.po, o.po); // area (point order) strategy not propagated + + return 0; +} diff --git a/test/cs_undefined/relops.cpp b/test/cs_undefined/relops.cpp new file mode 100644 index 000000000..a019fe876 --- /dev/null +++ b/test/cs_undefined/relops.cpp @@ -0,0 +1,228 @@ +// 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 + +#include "common.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +< + typename G1, + typename G2, + std::size_t Dim1 = bg::topological_dimension::value, + std::size_t Dim2 = bg::topological_dimension::value +> +struct call_equals +{ + template + static void apply(G1 const& g1, G2 const& g2, S const& s) {} +}; + +template +struct call_equals +{ + template + static void apply(G1 const& g1, G2 const& g2, S const& s) + { + bg::equals(g1, g2, s); + } +}; + +template +< + typename G1, + typename G2, + std::size_t Dim1 = bg::topological_dimension::value, + std::size_t Dim2 = bg::topological_dimension::value +> +struct call_overlaps +{ + template + static void apply(G1 const& g1, G2 const& g2, S const& s) {} +}; + +template +struct call_overlaps +{ + template + static void apply(G1 const& g1, G2 const& g2, S const& s) + { + bg::overlaps(g1, g2, s); + } +}; + +template +< + typename G1, + typename G2, + std::size_t Dim1 = bg::topological_dimension::value, + std::size_t Dim2 = bg::topological_dimension::value +> +struct call_touches +{ + template + static void apply(G1 const& g1, G2 const& g2, S const& s) + { + bg::touches(g1, g2, s); + } +}; + +template +struct call_touches +{ + template + static void apply(G1 const& g1, G2 const& g2, S const& s) {} +}; + +template +< + typename G1, + typename G2, + std::size_t Dim1 = bg::topological_dimension::value, + std::size_t Dim2 = bg::topological_dimension::value +> +struct call_crosses +{ + template + static void apply(G1 const& g1, G2 const& g2, S const& s) + { + bg::crosses(g1, g2, s); + } +}; + +template +struct call_crosses +{ + template + static void apply(G1 const& g1, G2 const& g2, S const& s) {} +}; + +template +struct call_crosses +{ + template + static void apply(G1 const& g1, G2 const& g2, S const& s) {} +}; + +template +inline void rel(G1 const& g1, G2 const& g2, S const& s) +{ + bg::relation(g1, g2, s); + bg::relate(g1, g2, bg::de9im::mask("*********"), s); + bg::covered_by(g1, g2, s); + call_crosses::apply(g1, g2, s); + bg::disjoint(g1, g2, s); + call_equals::apply(g1, g2, s); + bg::intersects(g1, g2, s); + call_overlaps::apply(g1, g2, s); + call_touches::apply(g1, g2, s); + bg::within(g1, g2, s); +} + +template +inline void rel_pp(G1 const& g1, G2 const& g2) +{ + ::rel(g1, g2, bg::strategy::within::cartesian_point_point()); + ::rel(g1, g2, bg::strategy::within::spherical_point_point()); +} + +template +inline void rel_ps(G1 const& g1, G2 const& g2) +{ + typedef typename bg::point_type::type point; + ::rel(g1, g2, bg::strategy::within::cartesian_winding()); + ::rel(g1, g2, bg::strategy::within::spherical_winding()); + ::rel(g1, g2, bg::strategy::within::geographic_winding()); +} + +template +inline void rel_ss(G1 const& g1, G2 const& g2) +{ + ::rel(g1, g2, bg::strategy::intersection::cartesian_segments<>()); + ::rel(g1, g2, bg::strategy::intersection::spherical_segments<>()); + ::rel(g1, g2, bg::strategy::intersection::geographic_segments<>()); +} + +int test_main(int, char*[]) +{ + geom g; + + bg::disjoint(g.pt, g.b, bg::strategy::covered_by::cartesian_point_box()); + bg::disjoint(g.pt, g.b, bg::strategy::covered_by::spherical_point_box()); + bg::disjoint(g.b, g.b, bg::strategy::disjoint::cartesian_box_box()); + bg::disjoint(g.b, g.b, bg::strategy::disjoint::spherical_box_box()); + bg::within(g.pt, g.b, bg::strategy::within::cartesian_point_box()); + bg::within(g.pt, g.b, bg::strategy::within::spherical_point_box()); + bg::within(g.b, g.b, bg::strategy::within::cartesian_box_box()); + bg::within(g.b, g.b, bg::strategy::within::spherical_box_box()); + bg::covered_by(g.pt, g.b, bg::strategy::covered_by::cartesian_point_box()); + bg::covered_by(g.pt, g.b, bg::strategy::covered_by::spherical_point_box()); + bg::covered_by(g.b, g.b, bg::strategy::covered_by::cartesian_box_box()); + bg::covered_by(g.b, g.b, bg::strategy::covered_by::spherical_box_box()); + + // P/P + ::rel_pp(g.pt, g.pt); + ::rel_pp(g.pt, g.mpt); + ::rel_pp(g.mpt, g.mpt); + // P/L + //::rel_ps(g.pt, g.s); // relate not implemented + ::rel_ps(g.pt, g.ls); + ::rel_ps(g.pt, g.mls); + //::rel_ps(g.mpt, g.s); // relate not implemented + ::rel_ps(g.mpt, g.ls); + ::rel_ps(g.mpt, g.mls); + // P/A + ::rel_ps(g.pt, g.r); + ::rel_ps(g.mpt, g.r); + ::rel_ps(g.pt, g.po); + ::rel_ps(g.mpt, g.po); + ::rel_ps(g.pt, g.mpo); + ::rel_ps(g.mpt, g.mpo); + // L/L + //::rel_ss(g.s, g.s); // relate not implemented + //::rel_ss(g.s, g.ls); // relate not implemented + //::rel_ss(g.s, g.mls); // relate not implemented + //::rel_ss(g.ls, g.s); // relate not implemented + ::rel_ss(g.ls, g.ls); + ::rel_ss(g.ls, g.mls); + //::rel_ss(g.mls, g.s); // relate not implemented + ::rel_ss(g.mls, g.ls); + ::rel_ss(g.mls, g.mls); + // L/A + //::rel_ss(g.s, g.r); // relate not implemented + ::rel_ss(g.ls, g.r); + ::rel_ss(g.mls, g.r); + //::rel_ss(g.s, g.po); // relate not implemented + ::rel_ss(g.ls, g.po); + ::rel_ss(g.mls, g.po); + //::rel_ss(g.s, g.mpo); // relate not implemented + ::rel_ss(g.ls, g.mpo); + ::rel_ss(g.mls, g.mpo); + // A/A + ::rel_ss(g.r, g.r); + ::rel_ss(g.po, g.r); + ::rel_ss(g.mpo, g.r); + ::rel_ss(g.r, g.po); + ::rel_ss(g.po, g.po); + ::rel_ss(g.mpo, g.po); + ::rel_ss(g.r, g.mpo); + ::rel_ss(g.po, g.mpo); + ::rel_ss(g.mpo, g.mpo); + + return 0; +} diff --git a/test/cs_undefined/setops.cpp b/test/cs_undefined/setops.cpp new file mode 100644 index 000000000..d684214a4 --- /dev/null +++ b/test/cs_undefined/setops.cpp @@ -0,0 +1,281 @@ +// 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 + +#include "common.hpp" + +#include +#include +#include +#include + +template +inline void set_idsu(G1 const& g1, G2 const& g2, G3 & g3, S const& s) +{ + bg::intersection(g1, g2, g3, s); + bg::difference(g1, g2, g3, s); + bg::sym_difference(g1, g2, g3, s); + bg::union_(g1, g2, g3, s); +} + +template +inline void set_ids(G1 const& g1, G2 const& g2, G3 & g3, S const& s) +{ + bg::intersection(g1, g2, g3, s); + bg::difference(g1, g2, g3, s); + bg::sym_difference(g1, g2, g3, s); +} + +template +inline void set_id(G1 const& g1, G2 const& g2, G3 & g3, S const& s) +{ + bg::intersection(g1, g2, g3, s); + bg::difference(g1, g2, g3, s); +} + +template +inline void set_i(G1 const& g1, G2 const& g2, G3 & g3, S const& s) +{ + bg::intersection(g1, g2, g3, s); +} + +template +inline void set_d(G1 const& g1, G2 const& g2, G3 & g3, S const& s) +{ + bg::difference(g1, g2, g3, s); +} + +template +inline void set_idsu_pp(G1 const& g1, G2 const& g2, G3 & g3) +{ + ::set_idsu(g1, g2, g3, bg::strategy::within::cartesian_point_point()); + ::set_idsu(g1, g2, g3, bg::strategy::within::spherical_point_point()); +} + +template +inline void set_idsu_ps(G1 const& g1, G2 const& g2, G3 & g3) +{ + typedef typename bg::point_type::type point_type; + ::set_idsu(g1, g2, g3, bg::strategy::within::cartesian_winding()); + ::set_idsu(g1, g2, g3, bg::strategy::within::spherical_winding()); + ::set_idsu(g1, g2, g3, bg::strategy::within::geographic_winding()); +} + +template +inline void set_idsu_ss(G1 const& g1, G2 const& g2, G3 & g3) +{ + ::set_idsu(g1, g2, g3, bg::strategy::intersection::cartesian_segments<>()); + ::set_idsu(g1, g2, g3, bg::strategy::intersection::spherical_segments<>()); + ::set_idsu(g1, g2, g3, bg::strategy::intersection::geographic_segments<>()); +} + +template +inline void set_ids_pp(G1 const& g1, G2 const& g2, G3 & g3) +{ + ::set_ids(g1, g2, g3, bg::strategy::within::cartesian_point_point()); + ::set_ids(g1, g2, g3, bg::strategy::within::spherical_point_point()); +} + +template +inline void set_ids_ps(G1 const& g1, G2 const& g2, G3 & g3) +{ + typedef typename bg::point_type::type point_type; + ::set_ids(g1, g2, g3, bg::strategy::within::cartesian_winding()); + ::set_ids(g1, g2, g3, bg::strategy::within::spherical_winding()); + ::set_ids(g1, g2, g3, bg::strategy::within::geographic_winding()); +} + +template +inline void set_ids_ss(G1 const& g1, G2 const& g2, G3 & g3) +{ + ::set_ids(g1, g2, g3, bg::strategy::intersection::cartesian_segments<>()); + ::set_ids(g1, g2, g3, bg::strategy::intersection::spherical_segments<>()); + ::set_ids(g1, g2, g3, bg::strategy::intersection::geographic_segments<>()); +} + +template +inline void set_id_pp(G1 const& g1, G2 const& g2, G3 & g3) +{ + ::set_id(g1, g2, g3, bg::strategy::within::cartesian_point_point()); + ::set_id(g1, g2, g3, bg::strategy::within::spherical_point_point()); +} + +template +inline void set_id_ps(G1 const& g1, G2 const& g2, G3 & g3) +{ + typedef typename bg::point_type::type point_type; + ::set_id(g1, g2, g3, bg::strategy::within::cartesian_winding()); + ::set_id(g1, g2, g3, bg::strategy::within::spherical_winding()); + ::set_id(g1, g2, g3, bg::strategy::within::geographic_winding()); +} + +template +inline void set_id_ss(G1 const& g1, G2 const& g2, G3 & g3) +{ + ::set_id(g1, g2, g3, bg::strategy::intersection::cartesian_segments<>()); + ::set_id(g1, g2, g3, bg::strategy::intersection::spherical_segments<>()); + ::set_id(g1, g2, g3, bg::strategy::intersection::geographic_segments<>()); +} + +template +inline void set_i_pp(G1 const& g1, G2 const& g2, G3 & g3) +{ + ::set_i(g1, g2, g3, bg::strategy::within::cartesian_point_point()); + ::set_i(g1, g2, g3, bg::strategy::within::spherical_point_point()); +} + +template +inline void set_i_ps(G1 const& g1, G2 const& g2, G3 & g3) +{ + typedef typename bg::point_type::type point_type; + ::set_i(g1, g2, g3, bg::strategy::within::cartesian_winding()); + ::set_i(g1, g2, g3, bg::strategy::within::spherical_winding()); + ::set_i(g1, g2, g3, bg::strategy::within::geographic_winding()); +} + +template +inline void set_i_ss(G1 const& g1, G2 const& g2, G3 & g3) +{ + ::set_i(g1, g2, g3, bg::strategy::intersection::cartesian_segments<>()); + ::set_i(g1, g2, g3, bg::strategy::intersection::spherical_segments<>()); + ::set_i(g1, g2, g3, bg::strategy::intersection::geographic_segments<>()); +} + +template +inline void set_d_pp(G1 const& g1, G2 const& g2, G3 & g3) +{ + ::set_d(g1, g2, g3, bg::strategy::within::cartesian_point_point()); + ::set_d(g1, g2, g3, bg::strategy::within::spherical_point_point()); +} + +template +inline void set_d_ps(G1 const& g1, G2 const& g2, G3 & g3) +{ + typedef typename bg::point_type::type point_type; + ::set_d(g1, g2, g3, bg::strategy::within::cartesian_winding()); + ::set_d(g1, g2, g3, bg::strategy::within::spherical_winding()); + ::set_d(g1, g2, g3, bg::strategy::within::geographic_winding()); +} + +template +inline void set_d_ss(G1 const& g1, G2 const& g2, G3 & g3) +{ + ::set_d(g1, g2, g3, bg::strategy::intersection::cartesian_segments<>()); + ::set_d(g1, g2, g3, bg::strategy::intersection::spherical_segments<>()); + ::set_d(g1, g2, g3, bg::strategy::intersection::geographic_segments<>()); +} + +int test_main(int, char*[]) +{ + geom g; + + // P/P->P + ::set_idsu_pp(g.pt, g.pt, g.mpt); + ::set_idsu_pp(g.pt, g.mpt, g.mpt); + ::set_idsu_pp(g.mpt, g.mpt, g.mpt); + + // P/L->P + ::set_id_ps(g.pt, g.s, g.mpt); + ::set_id_ps(g.pt, g.ls, g.mpt); + ::set_id_ps(g.pt, g.mls, g.mpt); + ::set_id_ps(g.mpt, g.s, g.mpt); + ::set_id_ps(g.mpt, g.ls, g.mpt); + ::set_id_ps(g.mpt, g.mls, g.mpt); + + // P/A->P + // no intersection nor difference + //::set_id_ps(g.pt, g.r, g.mpt); + //::set_id_ps(g.pt, g.po, g.mpt); + //::set_id_ps(g.pt, g.mpo, g.mpt); + //::set_id_ps(g.mpt, g.r, g.mpt); + //::set_id_ps(g.mpt, g.po, g.mpt); + //::set_id_ps(g.mpt, g.mpo, g.mpt); + + // L/L->P + ::set_ids_ss(g.s, g.s, g.mpt); + //::set_i_ss(g.s, g.ls, g.mpt); // no intersection nor difference + //::set_i_ss(g.s, g.mls, g.mpt); // no intersection nor difference + //::set_i_ss(g.ls, g.s, g.mpt); // no intersection nor difference + ::set_ids_ss(g.ls, g.ls, g.mpt); + ::set_i_ss(g.ls, g.mls, g.mpt); // no difference nor sym_difference + //::set_i_ss(g.mls, g.s, g.mpt); // no intersection nor difference + ::set_i_ss(g.mls, g.ls, g.mpt); // no difference nor sym_difference + ::set_ids_ss(g.mls, g.mls, g.mpt); + + // L/L->L + //::set_ids_ss(g.s, g.s, g.mls); // union not implemented, missing specialization + //::set_idsu_ss(g.s, g.ls, g.mls); // missing specialization + //::set_idsu_ss(g.s, g.mls, g.mls); // missing specialization + //::set_idsu_ss(g.ls, g.s, g.mls); // missing specialization + ::set_idsu_ss(g.ls, g.ls, g.mls); + ::set_idsu_ss(g.ls, g.mls, g.mls); + //::set_idsu_ss(g.mls, g.s, g.mls); // missing specialization + ::set_idsu_ss(g.mls, g.ls, g.mls); + ::set_idsu_ss(g.mls, g.mls, g.mls); + + // S/B->L ? + + // L/B->L ? + + // L/A->P + //::set_ids_ss(g.s, g.r, g.mpt); // no intersection + //::set_ids_ss(g.s, g.po, g.mpt); // no intersection + //::set_ids_ss(g.s, g.mpo, g.mpt); // no intersection + ::set_ids_ss(g.ls, g.r, g.mpt); + ::set_ids_ss(g.ls, g.po, g.mpt); + ::set_ids_ss(g.ls, g.mpo, g.mpt); + ::set_ids_ss(g.mls, g.r, g.mpt); + ::set_ids_ss(g.mls, g.po, g.mpt); + ::set_ids_ss(g.mls, g.mpo, g.mpt); + + // L/A->L + //::set_id_ss(g.s, g.r, g.mls); // no intersection + //::set_id_ss(g.s, g.po, g.mls); // no intersection + //::set_id_ss(g.s, g.mpo, g.mls); // no intersection + ::set_id_ss(g.ls, g.r, g.mls); + ::set_id_ss(g.ls, g.po, g.mls); + ::set_id_ss(g.ls, g.mpo, g.mls); + ::set_id_ss(g.mls, g.r, g.mls); + ::set_id_ss(g.mls, g.po, g.mls); + ::set_id_ss(g.mls, g.mpo, g.mls); + + // A/A->P + ::set_i_ss(g.r, g.r, g.mpt); + ::set_i_ss(g.r, g.po, g.mpt); + ::set_i_ss(g.r, g.mpo, g.mpt); + ::set_i_ss(g.po, g.r, g.mpt); + ::set_i_ss(g.po, g.po, g.mpt); + ::set_i_ss(g.po, g.mpo, g.mpt); + ::set_i_ss(g.mpo, g.r, g.mpt); + ::set_i_ss(g.mpo, g.po, g.mpt); + ::set_i_ss(g.mpo, g.mpo, g.mpt); + + // A/A->L + ::set_i_ss(g.r, g.r, g.mls); + ::set_i_ss(g.r, g.po, g.mls); + ::set_i_ss(g.r, g.mpo, g.mls); + ::set_i_ss(g.po, g.r, g.mls); + ::set_i_ss(g.po, g.po, g.mls); + ::set_i_ss(g.po, g.mpo, g.mls); + ::set_i_ss(g.mpo, g.r, g.mls); + ::set_i_ss(g.mpo, g.po, g.mls); + ::set_i_ss(g.mpo, g.mpo, g.mls); + + // A/A->A + ::set_idsu_ss(g.r, g.r, g.mpo); + ::set_idsu_ss(g.r, g.po, g.mpo); + ::set_idsu_ss(g.r, g.mpo, g.mpo); + ::set_idsu_ss(g.po, g.r, g.mpo); + ::set_idsu_ss(g.po, g.po, g.mpo); + ::set_idsu_ss(g.po, g.mpo, g.mpo); + ::set_idsu_ss(g.mpo, g.r, g.mpo); + ::set_idsu_ss(g.mpo, g.po, g.mpo); + ::set_idsu_ss(g.mpo, g.mpo, g.mpo); + + return 0; +} From 4a279fefc3871ea25a476685955aca5efa72e324 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 28 Jun 2019 23:34:40 +0200 Subject: [PATCH 63/68] [ci] Add cs::undefined tests to CircleCI script. --- .circleci/config.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5f702a168..aa19b3401 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -274,6 +274,15 @@ jobs: root: ~/project paths: - shared-coverage/core + cs_undefined: + <<: *config + steps: + - *attach_workspace + - run: ./$BOOST_DIR/libs/geometry/.circleci/run_test.sh cs_undefined test/cs_undefined + - persist_to_workspace: + root: ~/project + paths: + - shared-coverage/cs_undefined formulas: <<: *config steps: @@ -483,6 +492,7 @@ requires_4: &requires_4 - index_rtree_b2d - index_rtree_exceptions - index_varray + - cs_undefined only_master_develop: &only_master_develop filters: @@ -620,6 +630,9 @@ workflows: - index_varray: <<: *requires_3 <<: *only_master_develop + - cs_undefined: + <<: *requires_3 + <<: *only_master_develop # master, develop: level 5, coverage - coverage: <<: *requires_4 From ea72a91746b50e97d768138834467d085f6c5425 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 30 Jun 2019 20:00:06 +0200 Subject: [PATCH 64/68] [ci] Test cs::undefined 1 job at a time to decrease memory consumption. --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index aa19b3401..b97c7d20a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -278,7 +278,8 @@ jobs: <<: *config steps: - *attach_workspace - - run: ./$BOOST_DIR/libs/geometry/.circleci/run_test.sh cs_undefined test/cs_undefined + # 1 test at a time to decrease memory consumption causing gcc internal error + - run: ./$BOOST_DIR/libs/geometry/.circleci/run_test.sh cs_undefined test/cs_undefined 1 - persist_to_workspace: root: ~/project paths: From 0c77558db25f38815e845ee598e9955683d8f869 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 30 Jun 2019 22:17:26 +0200 Subject: [PATCH 65/68] [test] Divide cs::undefined relops test into two deparate files. --- test/cs_undefined/Jamfile.v2 | 3 +- test/cs_undefined/relops1.cpp | 50 +++++++++++++ test/cs_undefined/relops2.cpp | 48 +++++++++++++ .../{relops.cpp => test_relops.hpp} | 72 ++----------------- 4 files changed, 104 insertions(+), 69 deletions(-) create mode 100644 test/cs_undefined/relops1.cpp create mode 100644 test/cs_undefined/relops2.cpp rename test/cs_undefined/{relops.cpp => test_relops.hpp} (64%) diff --git a/test/cs_undefined/Jamfile.v2 b/test/cs_undefined/Jamfile.v2 index f0ea382da..b5e53d916 100644 --- a/test/cs_undefined/Jamfile.v2 +++ b/test/cs_undefined/Jamfile.v2 @@ -15,6 +15,7 @@ test-suite boost-geometry-cs_undefined [ compile is.cpp : : csundef_is ] [ compile measure.cpp : : csundef_measure ] [ compile other.cpp : : csundef_other ] - [ compile relops.cpp : : csundef_relops ] + [ compile relops1.cpp : : csundef_relops1 ] + [ compile relops2.cpp : : csundef_relops2 ] [ compile setops.cpp : : csundef_setops ] ; diff --git a/test/cs_undefined/relops1.cpp b/test/cs_undefined/relops1.cpp new file mode 100644 index 000000000..c22bb6b07 --- /dev/null +++ b/test/cs_undefined/relops1.cpp @@ -0,0 +1,50 @@ +// 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 + +#include "test_relops.hpp" + +int test_main(int, char*[]) +{ + geom g; + + bg::disjoint(g.pt, g.b, bg::strategy::covered_by::cartesian_point_box()); + bg::disjoint(g.pt, g.b, bg::strategy::covered_by::spherical_point_box()); + bg::disjoint(g.b, g.b, bg::strategy::disjoint::cartesian_box_box()); + bg::disjoint(g.b, g.b, bg::strategy::disjoint::spherical_box_box()); + bg::within(g.pt, g.b, bg::strategy::within::cartesian_point_box()); + bg::within(g.pt, g.b, bg::strategy::within::spherical_point_box()); + bg::within(g.b, g.b, bg::strategy::within::cartesian_box_box()); + bg::within(g.b, g.b, bg::strategy::within::spherical_box_box()); + bg::covered_by(g.pt, g.b, bg::strategy::covered_by::cartesian_point_box()); + bg::covered_by(g.pt, g.b, bg::strategy::covered_by::spherical_point_box()); + bg::covered_by(g.b, g.b, bg::strategy::covered_by::cartesian_box_box()); + bg::covered_by(g.b, g.b, bg::strategy::covered_by::spherical_box_box()); + + // P/P + ::rel_pp(g.pt, g.pt); + ::rel_pp(g.pt, g.mpt); + ::rel_pp(g.mpt, g.mpt); + + // P/L + //::rel_ps(g.pt, g.s); // relate not implemented + ::rel_ps(g.pt, g.ls); + ::rel_ps(g.pt, g.mls); + //::rel_ps(g.mpt, g.s); // relate not implemented + ::rel_ps(g.mpt, g.ls); + ::rel_ps(g.mpt, g.mls); + // P/A + ::rel_ps(g.pt, g.r); + ::rel_ps(g.mpt, g.r); + ::rel_ps(g.pt, g.po); + ::rel_ps(g.mpt, g.po); + ::rel_ps(g.pt, g.mpo); + ::rel_ps(g.mpt, g.mpo); + + return 0; +} diff --git a/test/cs_undefined/relops2.cpp b/test/cs_undefined/relops2.cpp new file mode 100644 index 000000000..11f971b87 --- /dev/null +++ b/test/cs_undefined/relops2.cpp @@ -0,0 +1,48 @@ +// 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 + +#include "test_relops.hpp" + +int test_main(int, char*[]) +{ + geom g; + + // L/L + //::rel_ss(g.s, g.s); // relate not implemented + //::rel_ss(g.s, g.ls); // relate not implemented + //::rel_ss(g.s, g.mls); // relate not implemented + //::rel_ss(g.ls, g.s); // relate not implemented + ::rel_ss(g.ls, g.ls); + ::rel_ss(g.ls, g.mls); + //::rel_ss(g.mls, g.s); // relate not implemented + ::rel_ss(g.mls, g.ls); + ::rel_ss(g.mls, g.mls); + // L/A + //::rel_ss(g.s, g.r); // relate not implemented + ::rel_ss(g.ls, g.r); + ::rel_ss(g.mls, g.r); + //::rel_ss(g.s, g.po); // relate not implemented + ::rel_ss(g.ls, g.po); + ::rel_ss(g.mls, g.po); + //::rel_ss(g.s, g.mpo); // relate not implemented + ::rel_ss(g.ls, g.mpo); + ::rel_ss(g.mls, g.mpo); + // A/A + ::rel_ss(g.r, g.r); + ::rel_ss(g.po, g.r); + ::rel_ss(g.mpo, g.r); + ::rel_ss(g.r, g.po); + ::rel_ss(g.po, g.po); + ::rel_ss(g.mpo, g.po); + ::rel_ss(g.r, g.mpo); + ::rel_ss(g.po, g.mpo); + ::rel_ss(g.mpo, g.mpo); + + return 0; +} diff --git a/test/cs_undefined/relops.cpp b/test/cs_undefined/test_relops.hpp similarity index 64% rename from test/cs_undefined/relops.cpp rename to test/cs_undefined/test_relops.hpp index a019fe876..7a366bcd6 100644 --- a/test/cs_undefined/relops.cpp +++ b/test/cs_undefined/test_relops.hpp @@ -7,6 +7,9 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html +#ifndef BOOST_GEOMETRY_TEST_CS_UNDEFINED_TEST_RELOPS_HPP +#define BOOST_GEOMETRY_TEST_CS_UNDEFINED_TEST_RELOPS_HPP + #include "common.hpp" #include @@ -158,71 +161,4 @@ inline void rel_ss(G1 const& g1, G2 const& g2) ::rel(g1, g2, bg::strategy::intersection::geographic_segments<>()); } -int test_main(int, char*[]) -{ - geom g; - - bg::disjoint(g.pt, g.b, bg::strategy::covered_by::cartesian_point_box()); - bg::disjoint(g.pt, g.b, bg::strategy::covered_by::spherical_point_box()); - bg::disjoint(g.b, g.b, bg::strategy::disjoint::cartesian_box_box()); - bg::disjoint(g.b, g.b, bg::strategy::disjoint::spherical_box_box()); - bg::within(g.pt, g.b, bg::strategy::within::cartesian_point_box()); - bg::within(g.pt, g.b, bg::strategy::within::spherical_point_box()); - bg::within(g.b, g.b, bg::strategy::within::cartesian_box_box()); - bg::within(g.b, g.b, bg::strategy::within::spherical_box_box()); - bg::covered_by(g.pt, g.b, bg::strategy::covered_by::cartesian_point_box()); - bg::covered_by(g.pt, g.b, bg::strategy::covered_by::spherical_point_box()); - bg::covered_by(g.b, g.b, bg::strategy::covered_by::cartesian_box_box()); - bg::covered_by(g.b, g.b, bg::strategy::covered_by::spherical_box_box()); - - // P/P - ::rel_pp(g.pt, g.pt); - ::rel_pp(g.pt, g.mpt); - ::rel_pp(g.mpt, g.mpt); - // P/L - //::rel_ps(g.pt, g.s); // relate not implemented - ::rel_ps(g.pt, g.ls); - ::rel_ps(g.pt, g.mls); - //::rel_ps(g.mpt, g.s); // relate not implemented - ::rel_ps(g.mpt, g.ls); - ::rel_ps(g.mpt, g.mls); - // P/A - ::rel_ps(g.pt, g.r); - ::rel_ps(g.mpt, g.r); - ::rel_ps(g.pt, g.po); - ::rel_ps(g.mpt, g.po); - ::rel_ps(g.pt, g.mpo); - ::rel_ps(g.mpt, g.mpo); - // L/L - //::rel_ss(g.s, g.s); // relate not implemented - //::rel_ss(g.s, g.ls); // relate not implemented - //::rel_ss(g.s, g.mls); // relate not implemented - //::rel_ss(g.ls, g.s); // relate not implemented - ::rel_ss(g.ls, g.ls); - ::rel_ss(g.ls, g.mls); - //::rel_ss(g.mls, g.s); // relate not implemented - ::rel_ss(g.mls, g.ls); - ::rel_ss(g.mls, g.mls); - // L/A - //::rel_ss(g.s, g.r); // relate not implemented - ::rel_ss(g.ls, g.r); - ::rel_ss(g.mls, g.r); - //::rel_ss(g.s, g.po); // relate not implemented - ::rel_ss(g.ls, g.po); - ::rel_ss(g.mls, g.po); - //::rel_ss(g.s, g.mpo); // relate not implemented - ::rel_ss(g.ls, g.mpo); - ::rel_ss(g.mls, g.mpo); - // A/A - ::rel_ss(g.r, g.r); - ::rel_ss(g.po, g.r); - ::rel_ss(g.mpo, g.r); - ::rel_ss(g.r, g.po); - ::rel_ss(g.po, g.po); - ::rel_ss(g.mpo, g.po); - ::rel_ss(g.r, g.mpo); - ::rel_ss(g.po, g.mpo); - ::rel_ss(g.mpo, g.mpo); - - return 0; -} +#endif // BOOST_GEOMETRY_TEST_CS_UNDEFINED_TEST_RELOPS_HPP From c3e8642f52499fb790e5bf734478f1367bf61028 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 1 Jul 2019 14:45:58 +0200 Subject: [PATCH 66/68] [strategies] Remove typename keywords. --- include/boost/geometry/strategies/cartesian/envelope_box.hpp | 2 +- include/boost/geometry/strategies/spherical/envelope_box.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/strategies/cartesian/envelope_box.hpp b/include/boost/geometry/strategies/cartesian/envelope_box.hpp index b05f4f6e7..ce723a1b2 100644 --- a/include/boost/geometry/strategies/cartesian/envelope_box.hpp +++ b/include/boost/geometry/strategies/cartesian/envelope_box.hpp @@ -80,7 +80,7 @@ namespace strategy { namespace envelope struct cartesian_box { - typedef typename strategy::expand::cartesian_box box_expand_strategy_type; + typedef strategy::expand::cartesian_box box_expand_strategy_type; static inline box_expand_strategy_type get_box_expand_strategy() { diff --git a/include/boost/geometry/strategies/spherical/envelope_box.hpp b/include/boost/geometry/strategies/spherical/envelope_box.hpp index 768a9c076..b7fa2ebea 100644 --- a/include/boost/geometry/strategies/spherical/envelope_box.hpp +++ b/include/boost/geometry/strategies/spherical/envelope_box.hpp @@ -34,7 +34,7 @@ namespace strategy { namespace envelope struct spherical_box : geometry::detail::envelope::envelope_box_on_spheroid { - typedef typename strategy::expand::spherical_box box_expand_strategy_type; + typedef strategy::expand::spherical_box box_expand_strategy_type; static inline box_expand_strategy_type get_box_expand_strategy() { From bb7cf70069a30d088feb2c13461a835f37ccff3d Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Mon, 1 Jul 2019 14:46:55 +0200 Subject: [PATCH 67/68] [index] Fix get_strategy return value and take care about references to temporaries. --- .../index/detail/rtree/pack_create.hpp | 2 +- .../rtree/quadratic/redistribute_elements.hpp | 31 ++++++++-------- .../rtree/rstar/redistribute_elements.hpp | 36 +++++++++++-------- include/boost/geometry/index/parameters.hpp | 4 ++- 4 files changed, 42 insertions(+), 31 deletions(-) diff --git a/include/boost/geometry/index/detail/rtree/pack_create.hpp b/include/boost/geometry/index/detail/rtree/pack_create.hpp index 2d212949a..f8565bfb3 100644 --- a/include/boost/geometry/index/detail/rtree/pack_create.hpp +++ b/include/boost/geometry/index/detail/rtree/pack_create.hpp @@ -244,7 +244,7 @@ private: private: BoxType m_box; - Strategy const& m_strategy; + Strategy m_strategy; bool m_initialized; }; diff --git a/include/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp b/include/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp index 9bec03a70..3fd51d56f 100644 --- a/include/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp +++ b/include/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp @@ -45,16 +45,18 @@ inline void pick_seeds(Elements const& elements, typedef typename rtree::element_indexable_type::type indexable_type; typedef Box box_type; typedef typename index::detail::default_content_result::type content_type; + typedef typename index::detail::strategy_type::type strategy_type; typedef index::detail::bounded_view < - indexable_type, box_type, - typename strategy_type::type + indexable_type, box_type, strategy_type > bounded_indexable_view; const size_t elements_count = parameters.get_max_elements() + 1; BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "wrong number of elements"); BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements"); + strategy_type const& strategy = index::detail::get_strategy(parameters); + content_type greatest_free_content = 0; seed1 = 0; seed2 = 1; @@ -67,11 +69,11 @@ inline void pick_seeds(Elements const& elements, indexable_type const& ind2 = rtree::element_indexable(elements[j], tr); box_type enlarged_box; - index::detail::bounds(ind1, enlarged_box, get_strategy(parameters)); - index::detail::expand(enlarged_box, ind2, get_strategy(parameters)); + index::detail::bounds(ind1, enlarged_box, strategy); + index::detail::expand(enlarged_box, ind2, strategy); - bounded_indexable_view bounded_ind1(ind1, get_strategy(parameters)); - bounded_indexable_view bounded_ind2(ind2, get_strategy(parameters)); + bounded_indexable_view bounded_ind1(ind1, strategy); + bounded_indexable_view bounded_ind2(ind2, strategy); content_type free_content = ( index::detail::content(enlarged_box) - index::detail::content(bounded_ind1) ) - index::detail::content(bounded_ind2); @@ -137,17 +139,18 @@ struct redistribute_elements::type const& + strategy = index::detail::get_strategy(parameters); + // add seeds elements1.push_back(elements_copy[seed1]); // MAY THROW, STRONG (copy) elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy) // calculate boxes detail::bounds(rtree::element_indexable(elements_copy[seed1], translator), - box1, - index::detail::get_strategy(parameters)); + box1, strategy); detail::bounds(rtree::element_indexable(elements_copy[seed2], translator), - box2, - index::detail::get_strategy(parameters)); + box2, strategy); // remove seeds if (seed1 < seed2) @@ -198,7 +201,7 @@ struct redistribute_elements bounded_view_type; public: - element_axis_corner_less(Parameters const& parameters, Translator const& tr) - : m_strategy(index::detail::get_strategy(parameters)), m_tr(tr) + element_axis_corner_less(Translator const& tr, strategy_type const& strategy) + : m_tr(tr), m_strategy(strategy) {} bool operator()(Element const& e1, Element const& e2) const @@ -61,15 +61,17 @@ public: } private: - strategy_type const& m_strategy; Translator const& m_tr; + strategy_type const& m_strategy; }; template class element_axis_corner_less { + typedef typename index::detail::strategy_type::type strategy_type; + public: - element_axis_corner_less(Parameters const& parameters, Translator const& tr) + element_axis_corner_less(Translator const& tr, strategy_type const&) : m_tr(tr) {} @@ -86,8 +88,10 @@ private: template class element_axis_corner_less { + typedef typename index::detail::strategy_type::type strategy_type; + public: - element_axis_corner_less(Parameters const& parameters, Translator const& tr) + element_axis_corner_less(Translator const& tr, strategy_type const& ) : m_tr(tr) {} @@ -122,6 +126,9 @@ struct choose_split_axis_and_index_for_corner BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == parameters.get_max_elements() + 1, "wrong number of elements"); + typename index::detail::strategy_type::type const& + strategy = index::detail::get_strategy(parameters); + // copy elements Elements elements_copy(elements); // MAY THROW, STRONG (alloc, copy) @@ -132,7 +139,7 @@ struct choose_split_axis_and_index_for_corner element_axis_corner_less < element_type, Parameters, Translator, indexable_tag, Corner, AxisIndex - > elements_less(parameters, translator); + > elements_less(translator, strategy); std::sort(elements_copy.begin(), elements_copy.end(), elements_less); // MAY THROW, BASIC (copy) // { // typename Elements::iterator f = elements_copy.begin() + index_first; @@ -149,9 +156,6 @@ struct choose_split_axis_and_index_for_corner smallest_overlap = (std::numeric_limits::max)(); smallest_content = (std::numeric_limits::max)(); - typename index::detail::strategy_type::type - strategy = index::detail::get_strategy(parameters); - // calculate sum of margins for all distributions for ( size_t i = index_first ; i < index_last ; ++i ) { @@ -370,10 +374,13 @@ struct nth_element typedef typename rtree::element_indexable_type::type indexable_type; typedef typename tag::type indexable_tag; + typename index::detail::strategy_type::type + strategy = index::detail::get_strategy(parameters); + element_axis_corner_less < element_type, Parameters, Translator, indexable_tag, Corner, I - > less(parameters, tr); + > less(tr, strategy); index::detail::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy) } } @@ -464,17 +471,18 @@ struct redistribute_elements::type const& + strategy = index::detail::get_strategy(parameters); + // copy elements to nodes elements1.assign(elements_copy.begin(), elements_copy.begin() + split_index); // MAY THROW, BASIC elements2.assign(elements_copy.begin() + split_index, elements_copy.end()); // MAY THROW, BASIC // calculate boxes box1 = rtree::elements_box(elements1.begin(), elements1.end(), - translator, - index::detail::get_strategy(parameters)); + translator, strategy); box2 = rtree::elements_box(elements2.begin(), elements2.end(), - translator, - index::detail::get_strategy(parameters)); + translator, strategy); } BOOST_CATCH(...) { diff --git a/include/boost/geometry/index/parameters.hpp b/include/boost/geometry/index/parameters.hpp index b19762436..bdd5f1cd6 100644 --- a/include/boost/geometry/index/parameters.hpp +++ b/include/boost/geometry/index/parameters.hpp @@ -290,12 +290,14 @@ template struct strategy_type { typedef default_strategy type; + typedef default_strategy result_type; }; template struct strategy_type< parameters > { typedef Strategy type; + typedef Strategy const& result_type; }; @@ -318,7 +320,7 @@ struct get_strategy_impl > }; template -inline typename strategy_type::type +inline typename strategy_type::result_type get_strategy(Parameters const& parameters) { return get_strategy_impl::apply(parameters); From 5a13eea5edbad79c9512dd66ac18e6c0b553b489 Mon Sep 17 00:00:00 2001 From: tinko92 Date: Mon, 1 Jul 2019 16:19:43 +0200 Subject: [PATCH 68/68] [strategies] Add a constructor that takes QVM matrix_type to matrix_transformers. --- .../strategies/transform/matrix_transformers.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/geometry/strategies/transform/matrix_transformers.hpp b/include/boost/geometry/strategies/transform/matrix_transformers.hpp index a3f3223c9..3de143501 100644 --- a/include/boost/geometry/strategies/transform/matrix_transformers.hpp +++ b/include/boost/geometry/strategies/transform/matrix_transformers.hpp @@ -117,6 +117,7 @@ template class matrix_transformer : public matrix_transformer { typedef CalculationType ct; + typedef boost::qvm::mat matrix_type; public : inline matrix_transformer( @@ -129,6 +130,10 @@ public : m_2_0, m_2_1, m_2_2) {} + inline matrix_transformer(matrix_type const& matrix) + : matrix_transformer(matrix) + {} + inline matrix_transformer() : matrix_transformer() {} @@ -157,6 +162,10 @@ public : qvm::A<3,0>(m_matrix) = m_3_0; qvm::A<3,1>(m_matrix) = m_3_1; qvm::A<3,2>(m_matrix) = m_3_2; qvm::A<3,3>(m_matrix) = m_3_3; } + inline matrix_transformer(matrix_type const& matrix) + : m_matrix(matrix) + {} + inline matrix_transformer() {} template