diff --git a/doc/src/examples/views/segment_view.cpp b/doc/src/examples/views/segment_view.cpp index 56f21d1f4..e02aab3c8 100644 --- a/doc/src/examples/views/segment_view.cpp +++ b/doc/src/examples/views/segment_view.cpp @@ -50,8 +50,8 @@ int main() /*` Output: [pre - (0, 0) (0, 4) (4, 4) (4, 0) (0, 0) -Area: 16 + (0, 0) (1, 1) +Length: 1.41421 ] */ //] diff --git a/include/boost/geometry/algorithms/area.hpp b/include/boost/geometry/algorithms/area.hpp index 26ff5c505..b5ec53392 100644 --- a/include/boost/geometry/algorithms/area.hpp +++ b/include/boost/geometry/algorithms/area.hpp @@ -216,15 +216,20 @@ struct area : detail::multi_sum namespace resolve_strategy { +template struct area { - template + template static inline typename area_result::type apply(Geometry const& geometry, Strategy const& strategy) { return dispatch::area::apply(geometry, strategy); } +}; +template <> +struct area +{ template static inline typename area_result::type apply(Geometry const& geometry, default_strategy) @@ -252,7 +257,7 @@ struct area static inline typename area_result::type apply(Geometry const& geometry, Strategy const& strategy) { - return resolve_strategy::area::apply(geometry, strategy); + return resolve_strategy::area::apply(geometry, strategy); } }; 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 d1c3f9fbf..c781e18b2 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-2017. -// Modifications copyright (c) 2016-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2016-2018. +// Modifications copyright (c) 2016-2018 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, @@ -633,6 +633,15 @@ struct buffered_piece_collection { // Check if a turn is inside any of the originals + typedef turn_in_original_ovelaps_box + < + typename IntersectionStrategy::disjoint_point_box_strategy_type + > turn_in_original_ovelaps_box_type; + typedef original_ovelaps_box + < + typename IntersectionStrategy::disjoint_box_box_strategy_type + > original_ovelaps_box_type; + turn_in_original_visitor visitor(m_turns); geometry::partition < @@ -640,8 +649,8 @@ struct buffered_piece_collection include_turn_policy, detail::partition::include_all_policy >::apply(m_turns, robust_originals, visitor, - turn_get_box(), turn_in_original_ovelaps_box(), - original_get_box(), original_ovelaps_box()); + turn_get_box(), turn_in_original_ovelaps_box_type(), + original_get_box(), original_ovelaps_box_type()); bool const deflate = distance_strategy.negative(); @@ -905,12 +914,21 @@ struct buffered_piece_collection > visitor(m_pieces, offsetted_rings, m_turns, m_intersection_strategy, m_robust_policy); + typedef detail::section::get_section_box + < + typename IntersectionStrategy::expand_box_strategy_type + > get_section_box_type; + typedef detail::section::overlaps_section_box + < + typename IntersectionStrategy::disjoint_box_box_strategy_type + > overlaps_section_box_type; + geometry::partition < robust_box_type >::apply(monotonic_sections, visitor, - detail::section::get_section_box(), - detail::section::overlaps_section_box()); + get_section_box_type(), + overlaps_section_box_type()); } insert_rescaled_piece_turns(); @@ -929,12 +947,21 @@ struct buffered_piece_collection turn_vector_type, piece_vector_type > visitor(m_turns, m_pieces); + typedef turn_ovelaps_box + < + typename IntersectionStrategy::disjoint_point_box_strategy_type + > turn_ovelaps_box_type; + typedef piece_ovelaps_box + < + typename IntersectionStrategy::disjoint_box_box_strategy_type + > piece_ovelaps_box_type; + geometry::partition < robust_box_type >::apply(m_turns, m_pieces, visitor, - turn_get_box(), turn_ovelaps_box(), - piece_get_box(), piece_ovelaps_box()); + turn_get_box(), turn_ovelaps_box_type(), + piece_get_box(), piece_ovelaps_box_type()); } } @@ -1400,6 +1427,8 @@ struct buffered_piece_collection inline bool point_coveredby_original(point_type const& point) { + typedef typename IntersectionStrategy::disjoint_point_box_strategy_type d_pb_strategy_type; + robust_point_type any_point; geometry::recalculate(any_point, point, m_robust_policy); @@ -1416,7 +1445,8 @@ struct buffered_piece_collection { robust_original const& original = *it; if (detail::disjoint::disjoint_point_box(any_point, - original.m_box)) + original.m_box, + d_pb_strategy_type())) { continue; } diff --git a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp index 3fb2dfbe4..b2af001be 100644 --- a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.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 2017. -// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018. +// Modifications copyright (c) 2017-2018 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, @@ -315,7 +315,8 @@ public: || is_adjacent(piece1, piece2) || is_on_same_convex_ring(piece1, piece2) || detail::disjoint::disjoint_box_box(section1.bounding_box, - section2.bounding_box) ) + section2.bounding_box, + m_intersection_strategy.get_disjoint_box_box_strategy()) ) { return true; } diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp index 70053536f..665d4e4be 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2016. -// Modifications copyright (c) 2016 Oracle and/or its affiliates. +// This file was modified by Oracle on 2016, 2018. +// Modifications copyright (c) 2016-2018 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,12 +38,14 @@ struct original_get_box } }; +template struct original_ovelaps_box { template static inline bool apply(Box const& box, Original const& original) { - return ! detail::disjoint::disjoint_box_box(box, original.m_box); + return ! detail::disjoint::disjoint_box_box(box, original.m_box, + DisjointBoxBoxStrategy()); } }; @@ -56,6 +58,7 @@ struct include_turn_policy } }; +template struct turn_in_original_ovelaps_box { template @@ -68,7 +71,7 @@ struct turn_in_original_ovelaps_box } return ! geometry::detail::disjoint::disjoint_point_box( - turn.robust_point, box); + turn.robust_point, box, DisjointPointBoxStrategy()); } }; diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp index 6c649db05..db27e34bb 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.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. -// Modifications copyright (c) 2016 Oracle and/or its affiliates. +// This file was modified by Oracle on 2016, 2018. +// Modifications copyright (c) 2016-2018 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, @@ -55,6 +55,7 @@ struct piece_get_box } }; +template struct piece_ovelaps_box { template @@ -70,7 +71,8 @@ struct piece_ovelaps_box return false; } - return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope); + return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope, + DisjointBoxBoxStrategy()); } }; @@ -83,12 +85,14 @@ struct turn_get_box } }; +template struct turn_ovelaps_box { template static inline bool apply(Box const& box, Turn const& turn) { - return ! geometry::detail::disjoint::disjoint_point_box(turn.robust_point, box); + return ! geometry::detail::disjoint::disjoint_point_box(turn.robust_point, box, + DisjointPointBoxStrategy()); } }; diff --git a/include/boost/geometry/algorithms/detail/covered_by/interface.hpp b/include/boost/geometry/algorithms/detail/covered_by/interface.hpp index 659907821..bdc92db43 100644 --- a/include/boost/geometry/algorithms/detail/covered_by/interface.hpp +++ b/include/boost/geometry/algorithms/detail/covered_by/interface.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013, 2014, 2017. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2017, 2018. +// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -63,13 +63,7 @@ struct covered_by Geometry2 const& geometry2, Strategy const& strategy) { - concepts::within::check - < - typename tag::type, - typename tag::type, - typename tag_cast::type, areal_tag>::type, - Strategy - >(); + concepts::within::check(); concepts::check(); concepts::check(); assert_dimension_equal(); diff --git a/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp index 87618939b..67f063321 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2018. +// Modifications copyright (c) 2013-2018, 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 @@ -23,139 +23,30 @@ #include -#include -#include - #include -#include -#include - +// For backward compatibility +#include +#include namespace boost { namespace geometry { + #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace disjoint { -template -< - typename Box1, typename Box2, - std::size_t Dimension = 0, - std::size_t DimensionCount = dimension::value, - typename CSTag = typename tag_cast - < - typename cs_tag::type, - spherical_tag - >::type -> -struct box_box -{ - template - static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&) - { - return apply(box1, box2); - } - - static inline bool apply(Box1 const& box1, Box2 const& box2) - { - if (get(box1) < get(box2)) - { - return true; - } - if (get(box1) > get(box2)) - { - return true; - } - return box_box - < - Box1, Box2, - Dimension + 1, DimensionCount - >::apply(box1, box2); - } -}; - - -template -struct box_box -{ - static inline bool apply(Box1 const& , Box2 const& ) - { - return false; - } -}; - - -template -struct box_box -{ - template - static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&) - { - return apply(box1, box2); - } - - static inline bool apply(Box1 const& box1, Box2 const& box2) - { - typedef typename geometry::select_most_precise - < - typename coordinate_type::type, - typename coordinate_type::type - >::type calc_t; - typedef typename coordinate_system::type::units units_t; - typedef math::detail::constants_on_spheroid constants; - - calc_t const b1_min = get(box1); - calc_t const b1_max = get(box1); - calc_t const b2_min = get(box2); - calc_t const b2_max = get(box2); - - // min <= max <=> diff >= 0 - calc_t const diff1 = b1_max - b1_min; - calc_t const diff2 = b2_max - b2_min; - - // check the intersection if neither box cover the whole globe - if (diff1 < constants::period() && diff2 < constants::period()) - { - // calculate positive longitude translation with b1_min as origin - calc_t const diff_min = math::longitude_distance_unsigned(b1_min, b2_min); - calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min - calc_t b2_max_transl = b2_min_transl - constants::period() + diff2; - - // if the translation is too close then use the original point - // note that math::abs(b2_max_transl - b2_max) takes values very - // close to k*2*constants::period() for k=0,1,2,... - if (math::abs(b2_max_transl - b2_max) < constants::period() / 2) - { - b2_max_transl = b2_max; - } - - if (b2_min_transl > b1_max // b2_min right of b1_max - && b2_max_transl < b1_min) // b2_max left of b1_min - { - return true; - } - } - - return box_box - < - Box1, Box2, - 1, DimensionCount - >::apply(box1, box2); - } -}; - /*! \brief Internal utility function to detect if boxes are disjoint \note Is used from other algorithms, declared separately to avoid circular references */ -template -inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2) +template +inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const&) { - return box_box::apply(box1, box2); + return Strategy::apply(box1, box2); } @@ -170,8 +61,13 @@ namespace dispatch template struct disjoint - : detail::disjoint::box_box -{}; +{ + template + static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&) + { + return Strategy::apply(box1, box2); + } +}; } // namespace dispatch diff --git a/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp index d7aa9089e..029d68be5 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp @@ -1,8 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2014-2018, 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 @@ -138,13 +138,15 @@ private: EnvelopeStrategy const& m_strategy; }; + template struct overlaps_box_point { template static inline bool apply(Box const& box, Point const& point) { // The default strategy is enough in this case - return ! detail::disjoint::disjoint_point_box(point, box); + return ! detail::disjoint::disjoint_point_box(point, box, + DisjointPointBoxStrategy()); } }; @@ -225,6 +227,7 @@ public: typedef typename Strategy::envelope_strategy_type envelope_strategy_type; typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type; + typedef typename Strategy::disjoint_point_box_strategy_type disjoint_pb_strategy_type; // TODO: disjoint Segment/Box may be called in partition multiple times // possibly for non-cartesian segments which could be slow. We should consider @@ -236,7 +239,7 @@ public: geometry::model::box::type> >::apply(multipoint, segment_range(linear), visitor, expand_box_point(), - overlaps_box_point(), + overlaps_box_point(), expand_box_segment(strategy.get_envelope_strategy()), overlaps_box_segment(strategy.get_disjoint_strategy())); @@ -256,8 +259,12 @@ class multi_point_single_geometry { public: template - static inline bool apply(MultiPoint const& multi_point, SingleGeometry const& single_geometry, Strategy const& strategy) + static inline bool apply(MultiPoint const& multi_point, + SingleGeometry const& single_geometry, + Strategy const& strategy) { + typedef typename Strategy::disjoint_point_box_strategy_type d_pb_strategy_type; + typedef typename point_type::type point1_type; typedef typename point_type::type point2_type; typedef model::box box2_type; @@ -270,7 +277,7 @@ public: for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it ) { // The default strategy is enough for Point/Box - if (! detail::disjoint::disjoint_point_box(*it, box2) + if (! detail::disjoint::disjoint_point_box(*it, box2, d_pb_strategy_type()) && ! dispatch::disjoint::apply(*it, single_geometry, strategy)) { return false; @@ -310,23 +317,27 @@ private: } }; + template struct overlaps_box_point { template static inline bool apply(Box const& box, Point const& point) { // The default strategy is enough for Point/Box - return ! detail::disjoint::disjoint_point_box(point, box); + return ! detail::disjoint::disjoint_point_box(point, box, + DisjointPointBoxStrategy()); } }; + template struct overlaps_box_box_pair { template inline bool apply(Box const& box, BoxPair const& box_pair) const { // The default strategy is enough for Box/Box - return ! detail::disjoint::disjoint_box_box(box_pair.first, box); + return ! detail::disjoint::disjoint_box_box(box_pair.first, box, + DisjointBoxBoxStrategy()); } }; @@ -344,11 +355,13 @@ private: template inline bool apply(Point const& point, BoxPair const& box_pair) { + typedef typename PtSegStrategy::disjoint_point_box_strategy_type d_pb_strategy_type; + typedef typename boost::range_value::type single_type; // The default strategy is enough for Point/Box if (! m_intersection_found - && ! detail::disjoint::disjoint_point_box(point, box_pair.first) + && ! detail::disjoint::disjoint_point_box(point, box_pair.first, d_pb_strategy_type()) && ! dispatch::disjoint::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy)) { m_intersection_found = true; @@ -390,14 +403,23 @@ public: item_visitor_type visitor(multi_geometry, strategy); + typedef overlaps_box_point + < + typename Strategy::disjoint_point_box_strategy_type + > overlaps_box_point_type; + typedef overlaps_box_box_pair + < + typename Strategy::disjoint_box_box_strategy_type + > overlaps_box_box_pair_type; + geometry::partition < box1_type >::apply(multi_point, boxes, visitor, expand_box_point(), - overlaps_box_point(), + overlaps_box_point_type(), expand_box_box_pair(), - overlaps_box_box_pair()); + overlaps_box_box_pair_type()); return ! visitor.intersection_found(); } diff --git a/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp index 2e6773d22..b4c402646 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2013-2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2018. +// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -41,16 +41,11 @@ namespace detail { namespace disjoint /*! \brief Internal utility function to detect if point/box are disjoint */ -template -inline bool disjoint_point_box(Point const& point, Box const& box) +template +inline bool disjoint_point_box(Point const& point, Box const& box, Strategy const& ) { - typedef typename strategy::disjoint::services::default_strategy - < - Point, Box - >::type strategy_type; - // ! covered_by(point, box) - return ! strategy_type::apply(point, box); + return ! Strategy::apply(point, box); } diff --git a/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp b/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp index 13ac34d71..f91712934 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2013, 2014, 2015, 2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. +// Modifications copyright (c) 2013-2018, 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 @@ -23,29 +23,15 @@ #include -#include - -#include -#include -#include -#include -#include -#include #include -#include -#include - -#include - -#include - -#include - -#include - #include +// For backward compatibility +#include +#include +#include + namespace boost { namespace geometry { @@ -56,169 +42,15 @@ namespace detail { namespace disjoint { -template -struct point_point_generic -{ - template - static inline bool apply(Point1 const& p1, Point2 const& p2, Strategy const& ) - { - return apply(p1, p2); - } - - template - static inline bool apply(Point1 const& p1, Point2 const& p2) - { - if (! geometry::math::equals(get(p1), get(p2))) - { - return true; - } - return - point_point_generic::apply(p1, p2); - } -}; - -template -struct point_point_generic -{ - template - static inline bool apply(Point1 const&, Point2 const& ) - { - return false; - } -}; - - -class point_point_on_spheroid -{ -private: - template - struct are_same_points - { - static inline bool apply(Point1 const& point1, Point2 const& point2) - { - typedef typename helper_geometry::type helper_point_type1; - typedef typename helper_geometry::type helper_point_type2; - - helper_point_type1 point1_normalized - = return_normalized(point1); - helper_point_type2 point2_normalized - = return_normalized(point2); - - return point_point_generic - < - 0, dimension::value - >::apply(point1_normalized, point2_normalized); - } - }; - - template - struct are_same_points // points have different units - { - static inline bool apply(Point1 const& point1, Point2 const& point2) - { - typedef typename geometry::select_most_precise - < - typename fp_coordinate_type::type, - typename fp_coordinate_type::type - >::type calculation_type; - - typename helper_geometry - < - Point1, calculation_type, radian - >::type helper_point1, helper_point2; - - Point1 point1_normalized = return_normalized(point1); - Point2 point2_normalized = return_normalized(point2); - - geometry::transform(point1_normalized, helper_point1); - geometry::transform(point2_normalized, helper_point2); - - return point_point_generic - < - 0, dimension::value - >::apply(helper_point1, helper_point2); - } - }; - -public: - template - static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& ) - { - return apply(point1, point2); - } - - template - static inline bool apply(Point1 const& point1, Point2 const& point2) - { - return are_same_points - < - Point1, - Point2, - boost::is_same - < - typename coordinate_system::type::units, - typename coordinate_system::type::units - >::value - >::apply(point1, point2); - } -}; - - -template -< - typename Point1, typename Point2, - std::size_t Dimension, std::size_t DimensionCount, - typename CSTag1 = typename cs_tag::type, - typename CSTag2 = CSTag1 -> -struct point_point - : point_point -{}; - -template -< - typename Point1, typename Point2, - std::size_t Dimension, std::size_t DimensionCount -> -struct point_point - < - Point1, Point2, Dimension, DimensionCount, spherical_equatorial_tag - > : point_point_on_spheroid -{}; - -template -< - typename Point1, typename Point2, - std::size_t Dimension, std::size_t DimensionCount -> -struct point_point - < - Point1, Point2, Dimension, DimensionCount, geographic_tag - > : point_point_on_spheroid -{}; - -template -< - typename Point1, typename Point2, - std::size_t Dimension, std::size_t DimensionCount -> -struct point_point - : point_point_generic -{}; - - /*! \brief Internal utility function to detect of points are disjoint \note To avoid circular references */ -template -inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2) +template +inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2, + Strategy const& ) { - return point_point - < - Point1, Point2, - 0, dimension::type::value - >::apply(point1, point2); + return ! Strategy::apply(point1, point2); } @@ -226,8 +58,6 @@ inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2) #endif // DOXYGEN_NO_DETAIL - - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { @@ -235,8 +65,14 @@ namespace dispatch template struct disjoint - : detail::disjoint::point_point -{}; +{ + template + static inline bool apply(Point1 const& point1, Point2 const& point2, + Strategy const& ) + { + return ! Strategy::apply(point1, point2); + } +}; } // namespace dispatch diff --git a/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp index baa4cf83d..d4d37725c 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp +++ b/include/boost/geometry/algorithms/detail/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-2018. +// Modifications copyright (c) 2013-2018, 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 @@ -39,6 +39,9 @@ #include +// Temporary, for envelope_segment_impl +#include + namespace boost { namespace geometry { @@ -50,21 +53,6 @@ namespace detail { namespace disjoint template struct disjoint_segment_box_sphere_or_spheroid { -private: - - template - static inline void swap(CT& lon1, - CT& lat1, - CT& lon2, - CT& lat2) - { - std::swap(lon1, lon2); - std::swap(lat1, lat2); - } - - -public: - struct disjoint_info { enum type @@ -82,21 +70,46 @@ public: operator T () const; }; - template + template + < + typename Segment, typename Box, + typename AzimuthStrategy, + typename NormalizeStrategy, + typename DisjointPointBoxStrategy, + typename DisjointBoxBoxStrategy + > static inline bool apply(Segment const& segment, Box const& box, - Strategy const& azimuth_strategy) + AzimuthStrategy const& azimuth_strategy, + NormalizeStrategy const& normalize_strategy, + DisjointPointBoxStrategy const& disjoint_point_box_strategy, + DisjointBoxBoxStrategy const& disjoint_box_box_strategy) { typedef typename point_type::type segment_point; segment_point vertex; - return (apply(segment, box, azimuth_strategy, vertex) != disjoint_info::intersect); + return apply(segment, box, vertex, + azimuth_strategy, + normalize_strategy, + disjoint_point_box_strategy, + disjoint_box_box_strategy) != disjoint_info::intersect; } - template + template + < + typename Segment, typename Box, + typename P, + typename AzimuthStrategy, + typename NormalizeStrategy, + typename DisjointPointBoxStrategy, + typename DisjointBoxBoxStrategy + > static inline disjoint_info apply(Segment const& segment, Box const& box, - Strategy const& azimuth_strategy, - P& vertex) + P& vertex, + AzimuthStrategy const& azimuth_strategy, + NormalizeStrategy const& , + DisjointPointBoxStrategy const& disjoint_point_box_strategy, + DisjointBoxBoxStrategy const& disjoint_box_box_strategy) { assert_dimension_equal(); @@ -113,7 +126,8 @@ public: // Simplest cases first // Case 1: if box contains one of segment's endpoints then they are not disjoint - if (! disjoint_point_box(p0, box) || ! disjoint_point_box(p1, box)) + if ( ! disjoint_point_box(p0, box, disjoint_point_box_strategy) + || ! disjoint_point_box(p1, box, disjoint_point_box_strategy) ) { return disjoint_info::intersect; } @@ -122,10 +136,10 @@ public: typedef typename coordinate_type::type CT; - segment_point_type p0_normalized = - geometry::detail::return_normalized(p0); - segment_point_type p1_normalized = - geometry::detail::return_normalized(p1); + segment_point_type p0_normalized; + NormalizeStrategy::apply(p0, p0_normalized); + segment_point_type p1_normalized; + NormalizeStrategy::apply(p1, p1_normalized); CT lon1 = geometry::get_as_radian<0>(p0_normalized); CT lat1 = geometry::get_as_radian<1>(p0_normalized); @@ -134,7 +148,8 @@ public: if (lon1 > lon2) { - swap(lon1, lat1, lon2, lat2); + std::swap(lon1, lon2); + std::swap(lat1, lat2); } //Compute alp1 outside envelope and pass it to envelope_segment_impl @@ -145,14 +160,17 @@ public: geometry::model::box box_seg; - geometry::detail::envelope::envelope_segment_impl - ::template apply(lon1, lat1, - lon2, lat2, - box_seg, - azimuth_strategy, - alp1); + // TODO: Shouldn't CSTag be taken from the caller, not from the segment? + strategy::envelope::detail::envelope_segment_impl + < + segment_cs_type + >::template apply(lon1, lat1, + lon2, lat2, + box_seg, + azimuth_strategy, + alp1); - if (disjoint_box_box(box, box_seg)) + if (disjoint_box_box(box, box_seg, disjoint_box_box_strategy)) { return disjoint_return_value; } diff --git a/include/boost/geometry/algorithms/detail/distance/interface.hpp b/include/boost/geometry/algorithms/detail/distance/interface.hpp index 4122ecfe1..2338abbeb 100644 --- a/include/boost/geometry/algorithms/detail/distance/interface.hpp +++ b/include/boost/geometry/algorithms/detail/distance/interface.hpp @@ -95,9 +95,10 @@ struct distance namespace resolve_strategy { +template struct distance { - template + template static inline typename distance_result::type apply(Geometry1 const& geometry1, Geometry2 const& geometry2, @@ -108,7 +109,11 @@ struct distance Geometry1, Geometry2, Strategy >::apply(geometry1, geometry2, strategy); } +}; +template <> +struct distance +{ template static inline typename distance_result::type @@ -144,8 +149,10 @@ struct distance Geometry2 const& geometry2, Strategy const& strategy) { - return - resolve_strategy::distance::apply(geometry1, geometry2, strategy); + return resolve_strategy::distance + < + Strategy + >::apply(geometry1, geometry2, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/envelope/areal.hpp b/include/boost/geometry/algorithms/detail/envelope/areal.hpp index 034a98c0a..3c9b5c576 100644 --- a/include/boost/geometry/algorithms/detail/envelope/areal.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/areal.hpp @@ -3,6 +3,7 @@ // Copyright (c) 2018 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -28,7 +29,6 @@ namespace boost { namespace geometry namespace detail { namespace envelope { -template struct envelope_polygon { template @@ -42,13 +42,13 @@ struct envelope_polygon // if the exterior ring is empty, consider the interior rings envelope_multi_range < - EnvelopePolicy + envelope_range >::apply(interior_rings(polygon), mbr, strategy); } else { // otherwise, consider only the exterior ring - EnvelopePolicy::apply(ext_ring, mbr, strategy); + envelope_range::apply(ext_ring, mbr, strategy); } } }; @@ -62,77 +62,21 @@ namespace dispatch { -template -struct envelope +template +struct envelope : detail::envelope::envelope_range {}; -template -struct envelope - : detail::envelope::envelope_linestring_or_ring_on_spheroid -{}; - -template -struct envelope - : detail::envelope::envelope_linestring_or_ring_on_spheroid -{}; - - -template -struct envelope - : detail::envelope::envelope_polygon - < - detail::envelope::envelope_range - > -{}; - template -struct envelope +struct envelope : detail::envelope::envelope_polygon - < - detail::envelope::envelope_linestring_or_ring_on_spheroid - > -{}; - -template -struct envelope - : detail::envelope::envelope_polygon - < - detail::envelope::envelope_linestring_or_ring_on_spheroid - > -{}; - - -template -struct envelope - : detail::envelope::envelope_multi_range - < - detail::envelope::envelope_polygon - < - detail::envelope::envelope_range - > - > {}; template -struct envelope +struct envelope : detail::envelope::envelope_multi_range < detail::envelope::envelope_polygon - < - detail::envelope::envelope_linestring_or_ring_on_spheroid - > - > -{}; - -template -struct envelope - : detail::envelope::envelope_multi_range - < - detail::envelope::envelope_polygon - < - detail::envelope::envelope_linestring_or_ring_on_spheroid - > > {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/box.hpp b/include/boost/geometry/algorithms/detail/envelope/box.hpp index cf039a292..b085a14b9 100644 --- a/include/boost/geometry/algorithms/detail/envelope/box.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/box.hpp @@ -18,134 +18,17 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP -#include -#include -#include -#include #include -#include - -#include -#include -#include - -#include +// For backward compatibility +#include +#include namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace envelope -{ - - -template -< - std::size_t Index, - std::size_t Dimension, - std::size_t DimensionCount -> -struct envelope_indexed_box -{ - template - static inline void apply(BoxIn const& box_in, BoxOut& mbr) - { - detail::indexed_point_view box_in_corner(box_in); - detail::indexed_point_view mbr_corner(mbr); - - detail::conversion::point_to_point - < - detail::indexed_point_view, - detail::indexed_point_view, - Dimension, - DimensionCount - >::apply(box_in_corner, mbr_corner); - } -}; - -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 -{ - template - static inline void apply(BoxIn const& box_in, - BoxOut& mbr, - Strategy const&) - { - envelope_indexed_box - < - min_corner, 0, dimension::value - >::apply(box_in, mbr); - - envelope_indexed_box - < - max_corner, 0, dimension::value - >::apply(box_in, mbr); - } -}; - - -struct envelope_box_on_spheroid -{ - template - static inline void apply(BoxIn const& box_in, - BoxOut& mbr, - Strategy const&) - { - BoxIn box_in_normalized = box_in; - - if (!is_inverse_spheroidal_coordinates(box_in)) - { - box_in_normalized = detail::return_normalized(box_in); - } - - envelope_indexed_box_on_spheroid - < - min_corner, dimension::value - >::apply(box_in_normalized, mbr); - - envelope_indexed_box_on_spheroid - < - max_corner, dimension::value - >::apply(box_in_normalized, mbr); - } -}; - - -}} // namespace detail::envelope -#endif // DOXYGEN_NO_DETAIL #ifndef DOXYGEN_NO_DISPATCH namespace dispatch @@ -153,27 +36,14 @@ namespace dispatch template -struct envelope - : detail::envelope::envelope_box -{}; - - -template -struct envelope - : detail::envelope::envelope_box_on_spheroid -{}; - - -template -struct envelope - : detail::envelope::envelope_box_on_spheroid -{}; - - -template -struct envelope - : detail::envelope::envelope_box_on_spheroid -{}; +struct envelope +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& mbr, Strategy const& ) + { + Strategy::apply(box_in, mbr); + } +}; } // namespace dispatch diff --git a/include/boost/geometry/algorithms/detail/envelope/interface.hpp b/include/boost/geometry/algorithms/detail/envelope/interface.hpp index 8e9c35b39..28c815f4c 100644 --- a/include/boost/geometry/algorithms/detail/envelope/interface.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/interface.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015, 2016, 2017. -// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016, 2017, 2018. +// Modifications copyright (c) 2015-2018, 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 @@ -21,19 +21,24 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP + #include #include #include -#include - #include +#include +#include +#include + +#include + #include #include -#include -#include -#include + +#include + namespace boost { namespace geometry { @@ -57,13 +62,15 @@ struct envelope Box& box, default_strategy) { - typedef typename point_type::type point_type; - typedef typename coordinate_type::type coordinate_type; - typedef typename strategy::envelope::services::default_strategy < - typename cs_tag::type, - coordinate_type + typename tag::type, + typename cs_tag::type, + typename select_most_precise + < + typename coordinate_type::type, + typename coordinate_type::type + >::type >::type strategy_type; dispatch::envelope::apply(geometry, box, strategy_type()); diff --git a/include/boost/geometry/algorithms/detail/envelope/linear.hpp b/include/boost/geometry/algorithms/detail/envelope/linear.hpp index 7fa788b73..e2f05f2e3 100644 --- a/include/boost/geometry/algorithms/detail/envelope/linear.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/linear.hpp @@ -4,11 +4,12 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015, 2016. -// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016, 2018. +// Modifications copyright (c) 2015-2018, 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 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -17,92 +18,40 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP -#include -#include -#include +#include #include #include +// For backward compatibility +#include +#include +#include namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace envelope -{ - -struct envelope_linestring_or_ring_on_spheroid -{ - template - static inline void apply(LinestringRing const& linestring_or_ring, - Box& mbr, - Strategy const& strategy) - { - envelope_range::apply(geometry::segments_begin(linestring_or_ring), - geometry::segments_end(linestring_or_ring), - mbr, - strategy); - } -}; - - -}} // namespace detail::envelope -#endif // DOXYGEN_NO_DETAIL - - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { -template -struct envelope +template +struct envelope : detail::envelope::envelope_range {}; -template -struct envelope - : detail::envelope::envelope_linestring_or_ring_on_spheroid -{}; -template -struct envelope - : detail::envelope::envelope_linestring_or_ring_on_spheroid -{}; - - -template -struct envelope - < - MultiLinestring, multi_linestring_tag, CS_Tag - > : detail::envelope::envelope_multi_range +template +struct envelope + : detail::envelope::envelope_multi_range < detail::envelope::envelope_range > {}; -template -struct envelope - < - MultiLinestring, multi_linestring_tag, spherical_equatorial_tag - > : detail::envelope::envelope_multi_range_on_spheroid - < - detail::envelope::envelope_linestring_or_ring_on_spheroid - > -{}; - -template -struct envelope - < - MultiLinestring, multi_linestring_tag, geographic_tag - > : detail::envelope::envelope_multi_range_on_spheroid - < - detail::envelope::envelope_linestring_or_ring_on_spheroid - > -{}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp index eef756379..ce112e4d7 100644 --- a/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2015-2017, Oracle and/or its affiliates. +// Copyright (c) 2015-2018, 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 @@ -13,361 +13,32 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include #include -#include -#include - -#include - -#include - -#include -#include -#include -#include - #include +// For backward compatibility +#include +#include namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace envelope -{ - - -class envelope_multipoint_on_spheroid -{ -private: - template - struct coordinate_less - { - template - inline bool operator()(Point const& point1, Point const& point2) const - { - return math::smaller(geometry::get(point1), - geometry::get(point2)); - } - }; - - template - static inline void analyze_point_coordinates(MultiPoint const& multipoint, - bool& has_south_pole, - bool& has_north_pole, - OutputIterator oit) - { - typedef typename boost::range_value::type point_type; - typedef typename boost::range_iterator - < - MultiPoint const - >::type iterator_type; - - // analyze point coordinates: - // (1) normalize point coordinates - // (2) check if any point is the north or the south pole - // (3) put all non-pole points in a container - // - // notice that at this point in the algorithm, we have at - // least two points on the spheroid - has_south_pole = false; - has_north_pole = false; - - for (iterator_type it = boost::begin(multipoint); - it != boost::end(multipoint); - ++it) - { - point_type point = detail::return_normalized(*it); - - if (math::equals(geometry::get<1>(point), - Constants::min_latitude())) - { - has_south_pole = true; - } - else if (math::equals(geometry::get<1>(point), - Constants::max_latitude())) - { - has_north_pole = true; - } - else - { - *oit++ = point; - } - } - } - - template - static inline Value maximum_gap(SortedRange const& sorted_range, - Value& max_gap_left, - Value& max_gap_right) - { - typedef typename boost::range_iterator - < - SortedRange const - >::type iterator_type; - - iterator_type it1 = boost::begin(sorted_range), it2 = it1; - ++it2; - max_gap_left = geometry::get<0>(*it1); - max_gap_right = geometry::get<0>(*it2); - - Value max_gap = max_gap_right - max_gap_left; - for (++it1, ++it2; it2 != boost::end(sorted_range); ++it1, ++it2) - { - Value gap = geometry::get<0>(*it2) - geometry::get<0>(*it1); - if (math::larger(gap, max_gap)) - { - max_gap_left = geometry::get<0>(*it1); - max_gap_right = geometry::get<0>(*it2); - max_gap = gap; - } - } - - return max_gap; - } - - template - < - typename Constants, - typename PointRange, - typename LongitudeLess, - typename CoordinateType - > - static inline void get_min_max_longitudes(PointRange& range, - LongitudeLess const& lon_less, - CoordinateType& lon_min, - CoordinateType& lon_max) - { - typedef typename boost::range_iterator - < - PointRange const - >::type iterator_type; - - // compute min and max longitude values - std::pair min_max_longitudes - = boost::minmax_element(boost::begin(range), - boost::end(range), - lon_less); - - lon_min = geometry::get<0>(*min_max_longitudes.first); - lon_max = geometry::get<0>(*min_max_longitudes.second); - - // if the longitude span is "large" compute the true maximum gap - if (math::larger(lon_max - lon_min, Constants::half_period())) - { - std::sort(boost::begin(range), boost::end(range), lon_less); - - CoordinateType max_gap_left = 0, max_gap_right = 0; - CoordinateType max_gap - = maximum_gap(range, max_gap_left, max_gap_right); - - CoordinateType complement_gap - = Constants::period() + lon_min - lon_max; - - if (math::larger(max_gap, complement_gap)) - { - lon_min = max_gap_right; - lon_max = max_gap_left + Constants::period(); - } - } - } - - template - < - typename Constants, - typename Iterator, - typename LatitudeLess, - typename CoordinateType - > - static inline void get_min_max_latitudes(Iterator const first, - Iterator const last, - LatitudeLess const& lat_less, - bool has_south_pole, - bool has_north_pole, - CoordinateType& lat_min, - CoordinateType& lat_max) - { - if (has_south_pole && has_north_pole) - { - lat_min = Constants::min_latitude(); - lat_max = Constants::max_latitude(); - } - else if (has_south_pole) - { - lat_min = Constants::min_latitude(); - lat_max - = geometry::get<1>(*std::max_element(first, last, lat_less)); - } - else if (has_north_pole) - { - lat_min - = geometry::get<1>(*std::min_element(first, last, lat_less)); - lat_max = Constants::max_latitude(); - } - else - { - std::pair min_max_latitudes - = boost::minmax_element(first, last, lat_less); - - lat_min = geometry::get<1>(*min_max_latitudes.first); - lat_max = geometry::get<1>(*min_max_latitudes.second); - } - } - -public: - template - static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& strategy) - { - typedef typename point_type::type point_type; - typedef typename coordinate_type::type coordinate_type; - typedef typename boost::range_iterator - < - MultiPoint const - >::type iterator_type; - - typedef math::detail::constants_on_spheroid - < - coordinate_type, - typename coordinate_system::type::units - > constants; - - if (boost::empty(multipoint)) - { - initialize::value>::apply(mbr); - return; - } - - initialize::apply(mbr); - - if (boost::size(multipoint) == 1) - { - return dispatch::envelope - < - typename boost::range_value::type - >::apply(range::front(multipoint), mbr, strategy); - } - - // analyze the points and put the non-pole ones in the - // points vector - std::vector points; - bool has_north_pole = false, has_south_pole = false; - - analyze_point_coordinates(multipoint, - has_south_pole, has_north_pole, - std::back_inserter(points)); - - coordinate_type lon_min, lat_min, lon_max, lat_max; - if (points.size() == 1) - { - // we have one non-pole point and at least one pole point - lon_min = geometry::get<0>(range::front(points)); - lon_max = geometry::get<0>(range::front(points)); - lat_min = has_south_pole - ? constants::min_latitude() - : constants::max_latitude(); - lat_max = has_north_pole - ? constants::max_latitude() - : constants::min_latitude(); - } - else if (points.empty()) - { - // all points are pole points - BOOST_GEOMETRY_ASSERT(has_south_pole || has_north_pole); - lon_min = coordinate_type(0); - lon_max = coordinate_type(0); - lat_min = has_south_pole - ? constants::min_latitude() - : constants::max_latitude(); - lat_max = (has_north_pole) - ? constants::max_latitude() - : constants::min_latitude(); - } - else - { - get_min_max_longitudes(points, - coordinate_less<0>(), - lon_min, - lon_max); - - get_min_max_latitudes(points.begin(), - points.end(), - coordinate_less<1>(), - has_south_pole, - has_north_pole, - lat_min, - lat_max); - } - - typedef typename helper_geometry - < - Box, - coordinate_type, - typename coordinate_system::type::units - >::type helper_box_type; - - helper_box_type helper_mbr; - - geometry::set(helper_mbr, lon_min); - geometry::set(helper_mbr, lat_min); - geometry::set(helper_mbr, lon_max); - geometry::set(helper_mbr, lat_max); - - // now transform to output MBR (per index) - envelope_indexed_box_on_spheroid::apply(helper_mbr, mbr); - envelope_indexed_box_on_spheroid::apply(helper_mbr, mbr); - - // compute envelope for higher coordinates - iterator_type it = boost::begin(multipoint); - envelope_one_point<2, dimension::value>::apply(*it, mbr, strategy); - - for (++it; it != boost::end(multipoint); ++it) - { - detail::expand::point_loop - < - 2, dimension::value - >::apply(mbr, *it, strategy); - } - } -}; - - -}} // namespace detail::envelope -#endif // DOXYGEN_NO_DETAIL - - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { -template -struct envelope - : detail::envelope::envelope_range -{}; - template -struct envelope - : detail::envelope::envelope_multipoint_on_spheroid -{}; - -template -struct envelope - : detail::envelope::envelope_multipoint_on_spheroid -{}; +struct envelope +{ + template + static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& ) + { + Strategy::apply(multipoint, mbr); + } +}; } // namespace dispatch diff --git a/include/boost/geometry/algorithms/detail/envelope/point.hpp b/include/boost/geometry/algorithms/detail/envelope/point.hpp index 86e73f3aa..164274a28 100644 --- a/include/boost/geometry/algorithms/detail/envelope/point.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/point.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, 2016, 2017. -// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016, 2017, 2018. +// Modifications copyright (c) 2015-2018, 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 @@ -18,23 +18,14 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP -#include - -#include -#include -#include -#include #include -#include - -#include -#include - -#include - #include +// For backward compatibility +#include +#include + namespace boost { namespace geometry { @@ -44,53 +35,12 @@ namespace detail { namespace envelope { -template -struct envelope_one_point +struct envelope_point { - template - static inline void apply(Point const& point, Box& mbr) - { - detail::indexed_point_view box_corner(mbr); - detail::conversion::point_to_point - < - Point, - detail::indexed_point_view, - Dimension, - DimensionCount - >::apply(point, box_corner); - } - template - static inline void apply(Point const& point, Box& mbr, Strategy const&) + static inline void apply(Point const& point, Box& mbr, Strategy const& ) { - apply(point, mbr); - apply(point, mbr); - } -}; - - -struct envelope_point_on_spheroid -{ - template - static inline void apply(Point const& point, Box& mbr, Strategy const& strategy) - { - Point normalized_point = detail::return_normalized(point); - - typename point_type::type box_point; - - // transform units of input point to units of a box point - transform_units(normalized_point, box_point); - - geometry::set(mbr, geometry::get<0>(box_point)); - geometry::set(mbr, geometry::get<1>(box_point)); - - geometry::set(mbr, geometry::get<0>(box_point)); - geometry::set(mbr, geometry::get<1>(box_point)); - - envelope_one_point - < - 2, dimension::value - >::apply(normalized_point, mbr, strategy); + Strategy::apply(point, mbr); } }; @@ -104,26 +54,8 @@ namespace dispatch template -struct envelope - : detail::envelope::envelope_one_point<0, dimension::value> -{}; - - -template -struct envelope - : detail::envelope::envelope_point_on_spheroid -{}; - - -template -struct envelope - : detail::envelope::envelope_point_on_spheroid -{}; - - -template -struct envelope - : detail::envelope::envelope_point_on_spheroid +struct envelope + : detail::envelope::envelope_point {}; diff --git a/include/boost/geometry/algorithms/detail/envelope/range.hpp b/include/boost/geometry/algorithms/detail/envelope/range.hpp index b5591f61a..2d33600d0 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range.hpp @@ -4,11 +4,12 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2015, 2016. -// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016, 2018. +// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -23,23 +24,17 @@ #include #include -#include - -#include - -#include +#include +#include #include #include -#include - #include #include #include -#include - +#include namespace boost { namespace geometry { @@ -53,7 +48,7 @@ namespace detail { namespace envelope struct envelope_range { template - static inline void apply(Iterator first, + static inline void apply(Iterator it, Iterator last, Box& mbr, Strategy const& strategy) @@ -63,16 +58,21 @@ struct envelope_range // initialize MBR initialize::value>::apply(mbr); - Iterator it = first; if (it != last) { // initialize box with first element in range - dispatch::envelope::apply(*it, mbr, strategy); + dispatch::envelope + < + value_type + >::apply(*it, mbr, strategy.get_element_envelope_strategy()); // consider now the remaining elements in the range (if any) for (++it; it != last; ++it) { - dispatch::expand::apply(mbr, *it, strategy); + dispatch::expand + < + Box, value_type + >::apply(mbr, *it, strategy.get_element_expand_strategy()); } } } @@ -80,7 +80,7 @@ struct envelope_range template static inline void apply(Range const& range, Box& mbr, Strategy const& strategy) { - return apply(boost::begin(range), boost::end(range), mbr, strategy); + return apply(Strategy::begin(range), Strategy::end(range), mbr, strategy); } }; @@ -94,86 +94,26 @@ struct envelope_multi_range Box& mbr, Strategy const& strategy) { - typedef typename boost::range_iterator - < - MultiRange const - >::type iterator_type; - - bool initialized = false; - for (iterator_type it = boost::begin(multirange); - it != boost::end(multirange); - ++it) - { - if (! geometry::is_empty(*it)) - { - if (initialized) - { - Box helper_mbr; - EnvelopePolicy::apply(*it, helper_mbr, strategy); - - dispatch::expand::apply(mbr, helper_mbr, strategy); - } - else - { - // compute the initial envelope - EnvelopePolicy::apply(*it, mbr, strategy); - initialized = true; - } - } - } - - if (! initialized) - { - // if not already initialized, initialize MBR - initialize::value>::apply(mbr); - } + apply(boost::begin(multirange), boost::end(multirange), mbr, strategy); } -}; - -// implementation for multi-range on a spheroid (longitude is periodic) -template -struct envelope_multi_range_on_spheroid -{ - template - static inline void apply(MultiRange const& multirange, + template + static inline void apply(Iter it, + Iter last, Box& mbr, Strategy const& strategy) { - typedef typename boost::range_iterator - < - MultiRange const - >::type iterator_type; - - // due to the periodicity of longitudes we need to compute the boxes - // of all the single geometries and keep them in a container - std::vector boxes; - for (iterator_type it = boost::begin(multirange); - it != boost::end(multirange); - ++it) + typename Strategy::template multi_state state; + for (; it != last; ++it) { if (! geometry::is_empty(*it)) { - Box helper_box; - EnvelopePolicy::apply(*it, helper_box, strategy); - boxes.push_back(helper_box); + Box helper_mbr; + EnvelopePolicy::apply(*it, helper_mbr, strategy); + state.apply(helper_mbr); } } - - // now we need to compute the envelope of the range of boxes - // (cannot be done in an incremental fashion as in the - // Cartesian coordinate system) - // if all single geometries are empty no boxes have been found - // and the MBR is simply initialized - if (! boxes.empty()) - { - envelope_range_of_boxes::apply(boxes, mbr, strategy); - } - else - { - initialize::value>::apply(mbr); - } - + state.result(mbr); } }; diff --git a/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp index 92d1fe395..111441036 100644 --- a/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp @@ -151,10 +151,8 @@ struct envelope_range_of_longitudes template struct envelope_range_of_boxes_by_expansion { - template - static inline void apply(RangeOfBoxes const& range_of_boxes, - Box& mbr, - Strategy const& strategy) + template + static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr) { typedef typename boost::range_value::type box_type; @@ -198,14 +196,14 @@ struct envelope_range_of_boxes_by_expansion min_corner, Dimension, DimensionCount - >::apply(mbr, *it, strategy); + >::apply(mbr, *it); detail::expand::indexed_loop < max_corner, Dimension, DimensionCount - >::apply(mbr, *it, strategy); + >::apply(mbr, *it); } } @@ -225,16 +223,14 @@ struct envelope_range_of_boxes } }; - template - static inline void apply(RangeOfBoxes const& range_of_boxes, - Box& mbr, - Strategy const& strategy) + template + static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr) { // boxes in the range are assumed to be normalized already typedef typename boost::range_value::type box_type; typedef typename coordinate_type::type coordinate_type; - typedef typename coordinate_system::type::units units_type; + typedef typename detail::cs_angular_units::type units_type; typedef typename boost::range_iterator < RangeOfBoxes const @@ -326,7 +322,7 @@ struct envelope_range_of_boxes envelope_range_of_boxes_by_expansion < 2, dimension::value - >::apply(range_of_boxes, mbr, strategy); + >::apply(range_of_boxes, mbr); } }; diff --git a/include/boost/geometry/algorithms/detail/envelope/segment.hpp b/include/boost/geometry/algorithms/detail/envelope/segment.hpp index cfa139a08..af79f3450 100644 --- a/include/boost/geometry/algorithms/detail/envelope/segment.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/segment.hpp @@ -19,33 +19,17 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP #include -#include -#include -#include - -#include -#include -#include -#include -#include -#include #include -#include - -#include - -#include -#include - #include -#include -#include -#include - #include +// For backward compatibility +#include +#include +#include + namespace boost { namespace geometry { @@ -53,385 +37,6 @@ namespace boost { namespace geometry namespace detail { namespace envelope { -template -struct envelope_segment_call_vertex_latitude -{ - template - static inline CalculationType apply(T1 const& lat1, - T2 const& alp1, - Strategy const& ) - { - return geometry::formula::vertex_latitude - ::apply(lat1, alp1); - } -}; - -template -struct envelope_segment_call_vertex_latitude -{ - template - static inline CalculationType apply(T1 const& lat1, - T2 const& alp1, - Strategy const& strategy) - { - return geometry::formula::vertex_latitude - ::apply(lat1, alp1, strategy.model()); - } -}; - -template -struct envelope_segment_convert_polar -{ - template - static inline void pre(T & , T & ) {} - - template - static inline void post(T & , T & ) {} -}; - -template -struct envelope_segment_convert_polar -{ - template - static inline void pre(T & lat1, T & lat2) - { - lat1 = math::latitude_convert_ep(lat1); - lat2 = math::latitude_convert_ep(lat2); - } - - template - static inline void post(T & lat1, T & lat2) - { - lat1 = math::latitude_convert_ep(lat1); - lat2 = math::latitude_convert_ep(lat2); - std::swap(lat1, lat2); - } -}; - -template -class envelope_segment_impl -{ -private: - - // degrees or radians - template - static inline void swap(CalculationType& lon1, - CalculationType& lat1, - CalculationType& lon2, - CalculationType& lat2) - { - std::swap(lon1, lon2); - std::swap(lat1, lat2); - } - - // radians - template - static inline bool contains_pi_half(CalculationType const& a1, - CalculationType const& a2) - { - // azimuths a1 and a2 are assumed to be in radians - BOOST_GEOMETRY_ASSERT(! math::equals(a1, a2)); - - static CalculationType const pi_half = math::half_pi(); - - return (a1 < a2) - ? (a1 < pi_half && pi_half < a2) - : (a1 > pi_half && pi_half > a2); - } - - // radians or degrees - template - static inline bool crosses_antimeridian(CoordinateType const& lon1, - CoordinateType const& lon2) - { - typedef math::detail::constants_on_spheroid - < - CoordinateType, Units - > constants; - - return math::abs(lon1 - lon2) > constants::half_period(); // > pi - } - - // degrees or radians - template - static inline void compute_box_corners(CalculationType& lon1, - CalculationType& lat1, - CalculationType& lon2, - CalculationType& lat2, - CalculationType a1, - CalculationType a2, - Strategy const& strategy) - { - // coordinates are assumed to be in radians - BOOST_GEOMETRY_ASSERT(lon1 <= lon2); - boost::ignore_unused(lon1, lon2); - - CalculationType lat1_rad = math::as_radian(lat1); - CalculationType lat2_rad = math::as_radian(lat2); - - if (math::equals(a1, a2)) - { - // the segment must lie on the equator or is very short or is meridian - return; - } - - if (lat1 > lat2) - { - std::swap(lat1, lat2); - std::swap(lat1_rad, lat2_rad); - std::swap(a1, a2); - } - - if (contains_pi_half(a1, a2)) - { - CalculationType p_max = envelope_segment_call_vertex_latitude - ::apply(lat1_rad, a1, strategy); - - CalculationType const mid_lat = lat1 + lat2; - if (mid_lat < 0) - { - // update using min latitude - CalculationType const lat_min_rad = -p_max; - CalculationType const lat_min - = math::from_radian(lat_min_rad); - - if (lat1 > lat_min) - { - lat1 = lat_min; - } - } - else - { - // update using max latitude - CalculationType const lat_max_rad = p_max; - CalculationType const lat_max - = math::from_radian(lat_max_rad); - - if (lat2 < lat_max) - { - lat2 = lat_max; - } - } - } - } - - template - static inline void special_cases(CalculationType& lon1, - CalculationType& lat1, - CalculationType& lon2, - CalculationType& lat2) - { - typedef math::detail::constants_on_spheroid - < - CalculationType, Units - > constants; - - bool is_pole1 = math::equals(math::abs(lat1), constants::max_latitude()); - bool is_pole2 = math::equals(math::abs(lat2), constants::max_latitude()); - - if (is_pole1 && is_pole2) - { - // both points are poles; nothing more to do: - // longitudes are already normalized to 0 - // but just in case - lon1 = 0; - lon2 = 0; - } - else if (is_pole1 && !is_pole2) - { - // first point is a pole, second point is not: - // make the longitude of the first point the same as that - // of the second point - lon1 = lon2; - } - else if (!is_pole1 && is_pole2) - { - // second point is a pole, first point is not: - // make the longitude of the second point the same as that - // of the first point - lon2 = lon1; - } - - if (lon1 == lon2) - { - // segment lies on a meridian - if (lat1 > lat2) - { - std::swap(lat1, lat2); - } - return; - } - - BOOST_GEOMETRY_ASSERT(!is_pole1 && !is_pole2); - - if (lon1 > lon2) - { - swap(lon1, lat1, lon2, lat2); - } - - if (crosses_antimeridian(lon1, lon2)) - { - lon1 += constants::period(); - swap(lon1, lat1, lon2, lat2); - } - } - - template - < - typename Units, - typename CalculationType, - typename Box - > - static inline void create_box(CalculationType lon1, - CalculationType lat1, - CalculationType lon2, - CalculationType lat2, - Box& mbr) - { - typedef typename coordinate_type::type box_coordinate_type; - - typedef typename helper_geometry - < - Box, box_coordinate_type, Units - >::type helper_box_type; - - helper_box_type helper_mbr; - - geometry::set - < - min_corner, 0 - >(helper_mbr, boost::numeric_cast(lon1)); - - geometry::set - < - min_corner, 1 - >(helper_mbr, boost::numeric_cast(lat1)); - - geometry::set - < - max_corner, 0 - >(helper_mbr, boost::numeric_cast(lon2)); - - geometry::set - < - max_corner, 1 - >(helper_mbr, boost::numeric_cast(lat2)); - - transform_units(helper_mbr, mbr); - } - - - template - static inline void apply(CalculationType& lon1, - CalculationType& lat1, - CalculationType& lon2, - CalculationType& lat2, - Strategy const& strategy) - { - special_cases(lon1, lat1, lon2, lat2); - - CalculationType lon1_rad = math::as_radian(lon1); - CalculationType lat1_rad = math::as_radian(lat1); - CalculationType lon2_rad = math::as_radian(lon2); - CalculationType lat2_rad = math::as_radian(lat2); - CalculationType alp1, alp2; - strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, alp1, alp2); - - compute_box_corners(lon1, lat1, lon2, lat2, alp1, alp2, strategy); - } - - template - static inline void apply(CalculationType& lon1, - CalculationType& lat1, - CalculationType& lon2, - CalculationType& lat2, - Strategy const& strategy, - CalculationType alp1) - { - special_cases(lon1, lat1, lon2, lat2); - - CalculationType lon1_rad = math::as_radian(lon1); - CalculationType lat1_rad = math::as_radian(lat1); - CalculationType lon2_rad = math::as_radian(lon2); - CalculationType lat2_rad = math::as_radian(lat2); - CalculationType alp2; - strategy.apply_reverse(lon1_rad, lat1_rad, lon2_rad, lat2_rad, alp2); - - compute_box_corners(lon1, lat1, lon2, lat2, alp1, alp2, strategy); - } - -public: - template - < - typename Units, - typename CalculationType, - typename Box, - typename Strategy - > - static inline void apply(CalculationType lon1, - CalculationType lat1, - CalculationType lon2, - CalculationType lat2, - Box& mbr, - Strategy const& strategy) - { - typedef envelope_segment_convert_polar::type> convert_polar; - - convert_polar::pre(lat1, lat2); - - apply(lon1, lat1, lon2, lat2, strategy); - - convert_polar::post(lat1, lat2); - - create_box(lon1, lat1, lon2, lat2, mbr); - } - - template - < - typename Units, - typename CalculationType, - typename Box, - typename Strategy - > - static inline void apply(CalculationType lon1, - CalculationType lat1, - CalculationType lon2, - CalculationType lat2, - Box& mbr, - Strategy const& strategy, - CalculationType alp1) - { - typedef envelope_segment_convert_polar::type> convert_polar; - - convert_polar::pre(lat1, lat2); - - apply(lon1, lat1, lon2, lat2, strategy, alp1); - - convert_polar::post(lat1, lat2); - - create_box(lon1, lat1, lon2, lat2, mbr); - } -}; - -template -struct envelope_one_segment -{ - template - static inline void apply(Point const& p1, - Point const& p2, - Box& mbr, - Strategy const& strategy) - { - envelope_one_point::apply(p1, mbr, strategy); - detail::expand::point_loop - < - Dimension, - DimensionCount - >::apply(mbr, p2, strategy); - } -}; - - template struct envelope_segment { @@ -441,12 +46,7 @@ struct envelope_segment Box& mbr, Strategy const& strategy) { - // first compute the envelope range for the first two coordinates strategy.apply(p1, p2, mbr); - - // now compute the envelope range for coordinates of - // dimension 2 and higher - envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr, strategy); } template diff --git a/include/boost/geometry/algorithms/detail/equals/implementation.hpp b/include/boost/geometry/algorithms/detail/equals/implementation.hpp index 310059a42..f39ae0b8b 100644 --- a/include/boost/geometry/algorithms/detail/equals/implementation.hpp +++ b/include/boost/geometry/algorithms/detail/equals/implementation.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014, 2015, 2016, 2017. -// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2015, 2016, 2017, 2018. +// Modifications copyright (c) 2014-2018 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 @@ -64,13 +64,9 @@ template struct point_point { template - static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy) + static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& ) { - return ! detail::disjoint::point_point - < - Point1, Point2, - Dimension, DimensionCount - >::apply(point1, point2, strategy); + return Strategy::apply(point1, point2); } }; @@ -108,20 +104,28 @@ struct box_box struct segment_segment { template - static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& ) + static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, + Strategy const& strategy) { + typename Strategy::point_in_point_strategy_type const& + pt_pt_strategy = strategy.get_point_in_point_strategy(); + return equals::equals_point_point( indexed_point_view(segment1), - indexed_point_view(segment2) ) + indexed_point_view(segment2), + pt_pt_strategy) ? equals::equals_point_point( indexed_point_view(segment1), - indexed_point_view(segment2) ) + indexed_point_view(segment2), + pt_pt_strategy) : ( equals::equals_point_point( indexed_point_view(segment1), - indexed_point_view(segment2) ) + indexed_point_view(segment2), + pt_pt_strategy) && equals::equals_point_point( indexed_point_view(segment1), - indexed_point_view(segment2) ) + indexed_point_view(segment2), + pt_pt_strategy) ); } }; diff --git a/include/boost/geometry/algorithms/detail/equals/point_point.hpp b/include/boost/geometry/algorithms/detail/equals/point_point.hpp index 12daa85e9..06a784284 100644 --- a/include/boost/geometry/algorithms/detail/equals/point_point.hpp +++ b/include/boost/geometry/algorithms/detail/equals/point_point.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland -// This file was modified by Oracle on 2013-2014. -// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2018. +// Modifications copyright (c) 2013-2018, 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,13 +21,10 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP -#include - namespace boost { namespace geometry { - #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace equals { @@ -36,17 +33,16 @@ namespace detail { namespace equals \brief Internal utility function to detect of points are disjoint \note To avoid circular references */ -template -inline bool equals_point_point(Point1 const& point1, Point2 const& point2) +template +inline bool equals_point_point(Point1 const& point1, Point2 const& point2, + Strategy const& ) { - return ! detail::disjoint::disjoint_point_point(point1, point2); + return Strategy::apply(point1, point2); } - }} // namespace detail::equals #endif // DOXYGEN_NO_DETAIL - }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP diff --git a/include/boost/geometry/algorithms/detail/expand/box.hpp b/include/boost/geometry/algorithms/detail/expand/box.hpp index 485f4d25e..41571dba6 100644 --- a/include/boost/geometry/algorithms/detail/expand/box.hpp +++ b/include/boost/geometry/algorithms/detail/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. -// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016, 2017, 2018. +// Modifications copyright (c) 2015-2018, 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,52 +19,19 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#include #include +#include + +// For backward compatibility +#include +#include + namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace expand -{ - - -struct box_on_spheroid -{ - template - static inline void apply(BoxOut& box_out, - BoxIn const& box_in, - Strategy const& strategy) - { - // normalize both boxes and convert box-in to be of type of box-out - BoxOut mbrs[2]; - detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0], strategy); - detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1], strategy); - - // compute the envelope of the two boxes - detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out, strategy); - } -}; - - -}} // namespace detail::expand -#endif // DOXYGEN_NO_DETAIL - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { @@ -73,59 +40,23 @@ namespace dispatch // Box + box -> new box containing two input boxes template < - typename BoxOut, typename BoxIn, - typename CSTagOut, typename CSTag + typename BoxOut, typename BoxIn > struct expand < BoxOut, BoxIn, - box_tag, box_tag, - CSTagOut, CSTag + box_tag, box_tag > { - BOOST_MPL_ASSERT_MSG((false), - NOT_IMPLEMENTED_FOR_THESE_COORDINATE_SYSTEMS, - (types())); + template + static inline void apply(BoxOut& box_out, + BoxIn const& box_in, + Strategy const& ) + { + Strategy::apply(box_out, box_in); + } }; -template -struct expand - < - BoxOut, BoxIn, - box_tag, box_tag, - cartesian_tag, cartesian_tag - > : detail::expand::expand_indexed - < - 0, dimension::value - > -{}; - -template -struct expand - < - BoxOut, BoxIn, - box_tag, box_tag, - spherical_equatorial_tag, spherical_equatorial_tag - > : detail::expand::box_on_spheroid -{}; - -template -struct expand - < - BoxOut, BoxIn, - box_tag, box_tag, - spherical_polar_tag, spherical_polar_tag - > : detail::expand::box_on_spheroid -{}; - -template -struct expand - < - BoxOut, BoxIn, - box_tag, box_tag, - geographic_tag, geographic_tag - > : detail::expand::box_on_spheroid -{}; } // namespace dispatch diff --git a/include/boost/geometry/algorithms/detail/expand/indexed.hpp b/include/boost/geometry/algorithms/detail/expand/indexed.hpp index fe7ee4f78..08463689d 100644 --- a/include/boost/geometry/algorithms/detail/expand/indexed.hpp +++ b/include/boost/geometry/algorithms/detail/expand/indexed.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. -// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016, 2017, 2018. +// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -48,8 +48,8 @@ template > struct indexed_loop { - template - static inline void apply(Box& box, Geometry const& source, Strategy const& strategy) + template + static inline void apply(Box& box, Geometry const& source) { typedef typename select_coordinate_type < @@ -75,7 +75,7 @@ struct indexed_loop indexed_loop < Index, Dimension + 1, DimensionCount - >::apply(box, source, strategy); + >::apply(box, source); } }; @@ -86,8 +86,8 @@ struct indexed_loop Index, DimensionCount, DimensionCount > { - template - static inline void apply(Box&, Geometry const&, Strategy const&) {} + template + static inline void apply(Box&, Geometry const&) {} }; @@ -96,20 +96,18 @@ struct indexed_loop template struct expand_indexed { - template - static inline void apply(Box& box, - Geometry const& geometry, - Strategy const& strategy) + template + static inline void apply(Box& box, Geometry const& geometry) { indexed_loop < 0, Dimension, DimensionCount - >::apply(box, geometry, strategy); + >::apply(box, geometry); indexed_loop < 1, Dimension, DimensionCount - >::apply(box, geometry, strategy); + >::apply(box, geometry); } }; diff --git a/include/boost/geometry/algorithms/detail/expand/interface.hpp b/include/boost/geometry/algorithms/detail/expand/interface.hpp index 5aacd8e72..28241b379 100644 --- a/include/boost/geometry/algorithms/detail/expand/interface.hpp +++ b/include/boost/geometry/algorithms/detail/expand/interface.hpp @@ -5,11 +5,12 @@ // 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. -// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016, 2018. +// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -25,16 +26,17 @@ #include #include +#include +#include +#include + #include #include #include +#include -#include -#include -#include -#include namespace boost { namespace geometry { @@ -58,14 +60,11 @@ struct expand Geometry const& geometry, default_strategy) { - typedef typename point_type::type point_type; - typedef typename coordinate_type::type coordinate_type; - - typedef typename strategy::envelope::services::default_strategy - < - typename cs_tag::type, - coordinate_type - >::type strategy_type; + typedef typename strategy::expand::services::default_strategy + < + typename tag::type, + typename cs_tag::type + >::type strategy_type; dispatch::expand::apply(box, geometry, strategy_type()); } diff --git a/include/boost/geometry/algorithms/detail/expand/point.hpp b/include/boost/geometry/algorithms/detail/expand/point.hpp index 88ebe75db..d4a9097cb 100644 --- a/include/boost/geometry/algorithms/detail/expand/point.hpp +++ b/include/boost/geometry/algorithms/detail/expand/point.hpp @@ -22,263 +22,25 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include #include +#include + +// For backward compatibility +#include +#include + + namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace expand -{ - - -template -struct point_loop -{ - template - static inline void apply(Box& box, Point const& source, Strategy const& strategy) - { - typedef typename select_coordinate_type - < - Point, Box - >::type coordinate_type; - - std::less less; - std::greater greater; - - coordinate_type const coord = get(source); - - if (less(coord, get(box))) - { - set(box, coord); - } - - if (greater(coord, get(box))) - { - set(box, coord); - } - - point_loop::apply(box, source, strategy); - } -}; - - -template -struct point_loop -{ - template - static inline void apply(Box&, Point const&, Strategy const&) {} -}; - - -// implementation for the spherical and geographic coordinate systems -template -struct point_loop_on_spheroid -{ - template - static inline void apply(Box& box, - Point const& point, - Strategy const& strategy) - { - typedef typename point_type::type box_point_type; - typedef typename coordinate_type::type box_coordinate_type; - typedef typename coordinate_system::type::units units_type; - - typedef math::detail::constants_on_spheroid - < - box_coordinate_type, - units_type - > constants; - - // normalize input point and input box - Point p_normalized = detail::return_normalized(point); - - // transform input point to be of the same type as the box point - box_point_type box_point; - detail::envelope::transform_units(p_normalized, box_point); - - if (is_inverse_spheroidal_coordinates(box)) - { - geometry::set_from_radian(box, geometry::get_as_radian<0>(p_normalized)); - geometry::set_from_radian(box, geometry::get_as_radian<1>(p_normalized)); - geometry::set_from_radian(box, geometry::get_as_radian<0>(p_normalized)); - geometry::set_from_radian(box, geometry::get_as_radian<1>(p_normalized)); - - } else { - - detail::normalize(box, box); - - box_coordinate_type p_lon = geometry::get<0>(box_point); - box_coordinate_type p_lat = geometry::get<1>(box_point); - - typename coordinate_type::type - b_lon_min = geometry::get(box), - b_lat_min = geometry::get(box), - b_lon_max = geometry::get(box), - b_lat_max = geometry::get(box); - - if (math::is_latitude_pole(p_lat)) - { - // the point of expansion is the either the north or the - // south pole; the only important coordinate here is the - // pole's latitude, as the longitude can be anything; - // we, thus, take into account the point's latitude only and return - geometry::set(box, (std::min)(p_lat, b_lat_min)); - geometry::set(box, (std::max)(p_lat, b_lat_max)); - return; - } - - if (math::equals(b_lat_min, b_lat_max) - && math::is_latitude_pole(b_lat_min)) - { - // the box degenerates to either the north or the south pole; - // the only important coordinate here is the pole's latitude, - // as the longitude can be anything; - // we thus take into account the box's latitude only and return - geometry::set(box, p_lon); - geometry::set(box, (std::min)(p_lat, b_lat_min)); - geometry::set(box, p_lon); - geometry::set(box, (std::max)(p_lat, b_lat_max)); - return; - } - - // update latitudes - b_lat_min = (std::min)(b_lat_min, p_lat); - b_lat_max = (std::max)(b_lat_max, p_lat); - - // update longitudes - if (math::smaller(p_lon, b_lon_min)) - { - box_coordinate_type p_lon_shifted = p_lon + constants::period(); - - if (math::larger(p_lon_shifted, b_lon_max)) - { - // here we could check using: ! math::larger(.., ..) - if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max)) - { - b_lon_min = p_lon; - } - else - { - b_lon_max = p_lon_shifted; - } - } - } - else if (math::larger(p_lon, b_lon_max)) - { - // in this case, and since p_lon is normalized in the range - // (-180, 180], we must have that b_lon_max <= 180 - if (b_lon_min < 0 - && math::larger(p_lon - b_lon_max, - constants::period() - p_lon + b_lon_min)) - { - b_lon_min = p_lon; - b_lon_max += constants::period(); - } - else - { - b_lon_max = p_lon; - } - } - - geometry::set(box, b_lon_min); - geometry::set(box, b_lat_min); - geometry::set(box, b_lon_max); - geometry::set(box, b_lat_max); - } - - point_loop - < - 2, DimensionCount - >::apply(box, point, strategy); - } -}; - - -}} // namespace detail::expand -#endif // DOXYGEN_NO_DETAIL - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { // Box + point -> new box containing also point -template -< - typename BoxOut, typename Point, - typename CSTagOut, typename CSTag -> -struct expand - < - BoxOut, Point, - box_tag, point_tag, - CSTagOut, CSTag - > -{ - BOOST_MPL_ASSERT_MSG((false), - NOT_IMPLEMENTED_FOR_THESE_COORDINATE_SYSTEMS, - (types())); -}; - - -template -struct expand - < - BoxOut, Point, - box_tag, point_tag, - cartesian_tag, cartesian_tag - > : detail::expand::point_loop - < - 0, dimension::value - > -{}; - -template -struct expand - < - BoxOut, Point, - box_tag, point_tag, - spherical_equatorial_tag, spherical_equatorial_tag - > : detail::expand::point_loop_on_spheroid - < - dimension::value - > -{}; - -template -struct expand - < - BoxOut, Point, - box_tag, point_tag, - spherical_polar_tag, spherical_polar_tag - > : detail::expand::point_loop_on_spheroid - < - dimension::value, - false - > -{}; - template < typename BoxOut, typename Point @@ -286,13 +48,18 @@ template struct expand < BoxOut, Point, - box_tag, point_tag, - geographic_tag, geographic_tag - > : detail::expand::point_loop_on_spheroid - < - dimension::value - > -{}; + box_tag, point_tag + > +{ + template + static inline void apply(BoxOut& box, + Point const& point, + Strategy const& ) + { + Strategy::apply(box, point); + } +}; + } // namespace dispatch diff --git a/include/boost/geometry/algorithms/detail/expand/segment.hpp b/include/boost/geometry/algorithms/detail/expand/segment.hpp index dddd3d2c7..3f6f19602 100644 --- a/include/boost/geometry/algorithms/detail/expand/segment.hpp +++ b/include/boost/geometry/algorithms/detail/expand/segment.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. -// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016, 2017, 2018. +// Modifications copyright (c) 2015-2018, 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,79 +19,26 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP -#include -#include -#include -#include - -#include -#include -#include - -#include +#include #include +#include + +// For backward compatibility +#include +#include +#include + namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace expand -{ - -struct segment -{ - template - static inline void apply(Box& box, - Segment const& segment, - Strategy const& strategy) - { - Box mbrs[2]; - - // compute the envelope of the segment - typename point_type::type p[2]; - detail::assign_point_from_index<0>(segment, p[0]); - detail::assign_point_from_index<1>(segment, p[1]); - detail::envelope::envelope_segment - < - dimension::value - >::apply(p[0], p[1], mbrs[0], strategy); - - // normalize the box - detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1], strategy); - - // compute the envelope of the two boxes - detail::envelope::envelope_range_of_boxes::apply(mbrs, box, strategy); - } -}; - - -}} // namespace detail::expand -#endif // DOXYGEN_NO_DETAIL - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { -template -< - typename Box, typename Segment, - typename CSTagOut, typename CSTag -> -struct expand - < - Box, Segment, - box_tag, segment_tag, - CSTagOut, CSTag - > -{ - BOOST_MPL_ASSERT_MSG((false), - NOT_IMPLEMENTED_FOR_THESE_COORDINATE_SYSTEMS, - (types())); -}; - template < typename Box, typename Segment @@ -99,40 +46,19 @@ template struct expand < Box, Segment, - box_tag, segment_tag, - cartesian_tag, cartesian_tag - > : detail::expand::expand_indexed - < - 0, dimension::value - > -{}; + box_tag, segment_tag + > +{ + template + static inline void apply(Box& box, + Segment const& segment, + Strategy const& strategy) + { + boost::ignore_unused(strategy); + strategy.apply(box, segment); + } +}; -template -struct expand - < - Box, Segment, - box_tag, segment_tag, - spherical_polar_tag, spherical_polar_tag - > : detail::expand::segment -{}; - -template -struct expand - < - Box, Segment, - box_tag, segment_tag, - spherical_equatorial_tag, spherical_equatorial_tag - > : detail::expand::segment -{}; - -template -struct expand - < - Box, Segment, - box_tag, segment_tag, - geographic_tag, geographic_tag - > : detail::expand::segment -{}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp index ed24b1381..8fe580332 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp @@ -116,19 +116,12 @@ private: } // prepare strategies - typedef typename std::iterator_traits::value_type polygon_type; - typedef typename Strategy::template point_in_geometry_strategy - < - polygon_type, polygon_type - >::type within_strategy_type; - within_strategy_type const within_strategy - = strategy.template get_point_in_geometry_strategy(); typedef typename Strategy::envelope_strategy_type envelope_strategy_type; envelope_strategy_type const envelope_strategy = strategy.get_envelope_strategy(); // call partition to check if polygons are disjoint from each other - typename base::template item_visitor_type item_visitor(within_strategy); + typename base::template item_visitor_type item_visitor(strategy); geometry::partition < diff --git a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp index 5c6229b79..834ce5af2 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-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2018, 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 @@ -217,26 +217,19 @@ protected: , m_strategy(strategy) {} - template - inline bool is_within(Item const& first, Item const& second) - { - typename point_type::type point; - typedef detail::point_on_border::point_on_range pob; - - // TODO: this should check for a point on the interior, instead - // of on border. Or it should check using the overlap function. - - return pob::apply(point, points_begin(first), points_end(first)) - && geometry::within(point, second, m_strategy); - } - template inline bool apply(partition_item const& item1, partition_item const& item2) { - if (! items_overlap - && (is_within(*item1.get(), *item2.get()) - || is_within(*item2.get(), *item1.get()))) + typedef boost::mpl::vector + < + geometry::de9im::static_mask<'T'>, + geometry::de9im::static_mask<'*', 'T'>, + geometry::de9im::static_mask<'*', '*', '*', 'T'> + > relate_mask_t; + + if ( ! items_overlap + && geometry::relate(*item1.get(), *item2.get(), relate_mask_t(), m_strategy) ) { items_overlap = true; return false; // interrupt @@ -326,19 +319,13 @@ protected: } // prepare strategies - typedef typename Strategy::template point_in_geometry_strategy - < - inter_ring_type, inter_ring_type - >::type in_interior_strategy_type; - in_interior_strategy_type const in_interior_strategy - = strategy.template get_point_in_geometry_strategy(); typedef typename Strategy::envelope_strategy_type envelope_strategy_type; envelope_strategy_type const envelope_strategy = strategy.get_envelope_strategy(); // call partition to check if interior rings are disjoint from // each other - item_visitor_type item_visitor(in_interior_strategy); + item_visitor_type item_visitor(strategy); geometry::partition < diff --git a/include/boost/geometry/algorithms/detail/normalize.hpp b/include/boost/geometry/algorithms/detail/normalize.hpp index 7a761d42b..b53243f08 100644 --- a/include/boost/geometry/algorithms/detail/normalize.hpp +++ b/include/boost/geometry/algorithms/detail/normalize.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2015-2017, Oracle and/or its affiliates. +// Copyright (c) 2015-2018, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -11,298 +11,31 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include +// For backward compatibility +#include namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace normalization -{ - - -struct do_nothing -{ - template - static inline void apply(GeometryIn const&, GeometryOut&) - { - } -}; - - -template -struct assign_loop -{ - template - static inline void apply(CoordinateType const& longitude, - CoordinateType const& latitude, - PointIn const& point_in, - PointOut& point_out) - { - geometry::set(point_out, boost::numeric_cast - < - typename coordinate_type::type - >(geometry::get(point_in))); - - assign_loop - < - Dimension + 1, DimensionCount - >::apply(longitude, latitude, point_in, point_out); - } -}; - -template -struct assign_loop -{ - template - static inline void apply(CoordinateType const&, - CoordinateType const&, - PointIn const&, - PointOut&) - { - } -}; - -template -struct assign_loop<0, DimensionCount> -{ - template - static inline void apply(CoordinateType const& longitude, - CoordinateType const& latitude, - PointIn const& point_in, - PointOut& point_out) - { - geometry::set<0>(point_out, boost::numeric_cast - < - typename coordinate_type::type - >(longitude)); - - assign_loop - < - 1, DimensionCount - >::apply(longitude, latitude, point_in, point_out); - } -}; - -template -struct assign_loop<1, DimensionCount> -{ - template - static inline void apply(CoordinateType const& longitude, - CoordinateType const& latitude, - PointIn const& point_in, - PointOut& point_out) - { - geometry::set<1>(point_out, boost::numeric_cast - < - typename coordinate_type::type - >(latitude)); - - assign_loop - < - 2, DimensionCount - >::apply(longitude, latitude, point_in, point_out); - } -}; - - -template -struct normalize_point -{ - static inline void apply(PointIn const& point_in, PointOut& point_out) - { - typedef typename coordinate_type::type in_coordinate_type; - - in_coordinate_type longitude = geometry::get<0>(point_in); - in_coordinate_type latitude = geometry::get<1>(point_in); - - math::normalize_spheroidal_coordinates - < - typename coordinate_system::type::units, - IsEquatorial, - in_coordinate_type - >(longitude, latitude); - - assign_loop - < - 0, dimension::value - >::apply(longitude, latitude, point_in, point_out); - } -}; - - -template -class normalize_box -{ - template - static inline void apply_to_coordinates(CoordinateInType& lon_min, - CoordinateInType& lat_min, - CoordinateInType& lon_max, - CoordinateInType& lat_max, - BoxIn const& box_in, - BoxOut& box_out) - { - detail::indexed_point_view p_min_out(box_out); - assign_loop - < - 0, dimension::value - >::apply(lon_min, - lat_min, - detail::indexed_point_view - < - BoxIn const, min_corner - >(box_in), - p_min_out); - - detail::indexed_point_view p_max_out(box_out); - assign_loop - < - 0, dimension::value - >::apply(lon_max, - lat_max, - detail::indexed_point_view - < - BoxIn const, max_corner - >(box_in), - p_max_out); - } - -public: - static inline void apply(BoxIn const& box_in, BoxOut& box_out) - { - typedef typename coordinate_type::type in_coordinate_type; - - in_coordinate_type lon_min = geometry::get(box_in); - in_coordinate_type lat_min = geometry::get(box_in); - in_coordinate_type lon_max = geometry::get(box_in); - in_coordinate_type lat_max = geometry::get(box_in); - - math::normalize_spheroidal_box_coordinates - < - typename coordinate_system::type::units, - IsEquatorial, - in_coordinate_type - >(lon_min, lat_min, lon_max, lat_max); - - apply_to_coordinates - < - typename coordinate_system::type::units, - typename coordinate_system::type::units - >(lon_min, lat_min, lon_max, lat_max, box_in, box_out); - } -}; - - -}} // namespace detail::normalization -#endif // DOXYGEN_NO_DETAIL - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - -template -< - typename GeometryIn, - typename GeometryOut, - typename TagIn = typename tag::type, - typename TagOut = typename tag::type, - typename CSTagIn = typename cs_tag::type, - typename CSTagOut = typename cs_tag::type -> -struct normalize : detail::normalization::do_nothing -{}; - - -template -struct normalize - < - PointIn, PointOut, point_tag, point_tag, - spherical_equatorial_tag, spherical_equatorial_tag - > : detail::normalization::normalize_point -{}; - - -template -struct normalize - < - PointIn, PointOut, point_tag, point_tag, - spherical_polar_tag, spherical_polar_tag - > : detail::normalization::normalize_point -{}; - - -template -struct normalize - < - PointIn, PointOut, point_tag, point_tag, geographic_tag, geographic_tag - > : detail::normalization::normalize_point -{}; - - -template -struct normalize - < - BoxIn, BoxOut, box_tag, box_tag, - spherical_equatorial_tag, spherical_equatorial_tag - > : detail::normalization::normalize_box -{}; - - -template -struct normalize - < - BoxIn, BoxOut, box_tag, box_tag, - spherical_polar_tag, spherical_polar_tag - > : detail::normalization::normalize_box -{}; - - -template -struct normalize - < - BoxIn, BoxOut, box_tag, box_tag, geographic_tag, geographic_tag - > : detail::normalization::normalize_box -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - #ifndef DOXYGEN_NO_DETAIL namespace detail { -template -inline void normalize(GeometryIn const& geometry_in, GeometryOut& geometry_out) +template +inline void normalize(GeometryIn const& geometry_in, GeometryOut& geometry_out, Strategy const& ) { - dispatch::normalize - < - GeometryIn, GeometryOut - >::apply(geometry_in, geometry_out); + Strategy::apply(geometry_in, geometry_out); } -template -inline GeometryOut return_normalized(GeometryIn const& geometry_in) +template +inline GeometryOut return_normalized(GeometryIn const& geometry_in, Strategy const& strategy) { GeometryOut geometry_out; - detail::normalize(geometry_in, geometry_out); + detail::normalize(geometry_in, geometry_out, strategy); return geometry_out; } diff --git a/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp b/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp index 0fd1fe4de..34e9fc79c 100644 --- a/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp @@ -2,6 +2,11 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2018. +// Modifications copyright (c) 2018 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -10,11 +15,10 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP -#include - #include #include +#include namespace boost { namespace geometry @@ -26,11 +30,24 @@ namespace detail { namespace overlay { template -inline void append_no_duplicates(Range& range, Point const& point, bool force = false) +inline void append_with_duplicates(Range& range, Point const& point) { - if (boost::size(range) == 0 - || force - || ! geometry::detail::equals::equals_point_point(*(boost::end(range)-1), point)) +#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION + std::cout << " add: (" + << geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")" + << std::endl; +#endif + geometry::append(range, point); +} + +template +inline void append_no_duplicates(Range& range, Point const& point, + EqPPStrategy const& strategy) +{ + if ( boost::empty(range) + || ! geometry::detail::equals::equals_point_point(geometry::range::back(range), + point, + strategy) ) { #ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION std::cout << " add: (" diff --git a/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp b/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp index 724996ae3..bc9db32f8 100644 --- a/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp @@ -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, 2018. +// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -15,6 +15,7 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPS_OR_SPIKES_HPP #include +#include #include #include @@ -33,12 +34,13 @@ namespace detail { namespace overlay { // TODO: move this / rename this -template +template inline bool points_equal_or_close(Point1 const& point1, Point2 const& point2, + EqualsStrategy const& strategy, RobustPolicy const& robust_policy) { - if (detail::equals::equals_point_point(point1, point2)) + if (detail::equals::equals_point_point(point1, point2, strategy)) { return true; } @@ -59,7 +61,14 @@ inline bool points_equal_or_close(Point1 const& point1, geometry::recalculate(point1_rob, point1, robust_policy); geometry::recalculate(point2_rob, point2, robust_policy); - return detail::equals::equals_point_point(point1_rob, point2_rob); + // Only if this is the case the same strategy can be used. + BOOST_STATIC_ASSERT((boost::is_same + < + typename geometry::cs_tag::type, + typename geometry::cs_tag::type + >::value)); + + return detail::equals::equals_point_point(point1_rob, point2_rob, strategy); } @@ -76,8 +85,10 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point, // The code below this condition checks all spikes/dups // for geometries >= 3 points. // So we have to check the first potential duplicate differently - if (boost::size(range) == 1 - && points_equal_or_close(*(boost::begin(range)), point, robust_policy)) + if ( boost::size(range) == 1 + && points_equal_or_close(*(boost::begin(range)), point, + strategy.get_equals_point_point_strategy(), + robust_policy) ) { return; } @@ -113,8 +124,10 @@ inline void append_no_collinear(Range& range, Point const& point, // The code below this condition checks all spikes/dups // for geometries >= 3 points. // So we have to check the first potential duplicate differently - if (boost::size(range) == 1 - && points_equal_or_close(*(boost::begin(range)), point, robust_policy)) + if ( boost::size(range) == 1 + && points_equal_or_close(*(boost::begin(range)), point, + strategy.get_equals_point_point_strategy(), + robust_policy) ) { return; } diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index e654164c5..6d3c602ff 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. -// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018. +// Modifications copyright (c) 2017-2018 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, @@ -134,12 +134,14 @@ struct ring_info_helper_get_box } }; +template struct ring_info_helper_ovelaps_box { template static inline bool apply(Box const& box, InputItem const& item) { - return ! geometry::detail::disjoint::disjoint_box_box(box, item.envelope); + return ! geometry::detail::disjoint::disjoint_box_box( + box, item.envelope, DisjointBoxBoxStrategy()); } }; @@ -327,11 +329,16 @@ inline void assign_parents(Geometry1 const& geometry1, Strategy > visitor(geometry1, geometry2, collection, ring_map, strategy, check_for_orientation); + typedef ring_info_helper_ovelaps_box + < + typename Strategy::disjoint_box_box_strategy_type + > overlaps_box_type; + geometry::partition < box_type >::apply(vector, visitor, ring_info_helper_get_box(), - ring_info_helper_ovelaps_box()); + overlaps_box_type()); } if (check_for_orientation) diff --git a/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp index 8cb37d695..ead9e7014 100644 --- a/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp @@ -2,10 +2,11 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// 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, 2018. +// Modifications copyright (c) 2015-2018 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 @@ -24,6 +25,8 @@ #include #include +#include + namespace boost { namespace geometry { @@ -83,6 +86,15 @@ private: public: +// TODO: Temporary, this strategy should be moved, it is cartesian-only + + typedef strategy::within::cartesian_point_point equals_point_point_strategy_type; + + static inline equals_point_point_strategy_type get_equals_point_point_strategy() + { + return equals_point_point_strategy_type(); + } + inline bool clip_segment(Box const& b, segment_type& s, bool& sp1_clipped, bool& sp2_clipped) const { typedef typename select_coordinate_type::type coordinate_type; @@ -224,9 +236,10 @@ OutputIterator clip_range_with_box(Box const& b, Range const& range, // b. Add p1 only if it is the first point, then add p2 if (boost::empty(line_out)) { - detail::overlay::append_no_duplicates(line_out, p1, true); + detail::overlay::append_with_duplicates(line_out, p1); } - detail::overlay::append_no_duplicates(line_out, p2); + detail::overlay::append_no_duplicates(line_out, p2, + strategy.get_equals_point_point_strategy()); // c. If c2 is clipped, finish the line if (c2) diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp index c6f540a97..286ac4b71 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2014 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, 2018. +// Modifications copyright (c) 2014-2018 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 @@ -137,11 +137,11 @@ private: template static inline void append_to_output(RangeOut& current_output, Point const& point, - SideStrategy const&, + SideStrategy const& strategy, RobustPolicy const&, boost::false_type const&) { - detail::overlay::append_no_duplicates(current_output, point); + detail::overlay::append_no_duplicates(current_output, point, strategy.get_equals_point_point_strategy()); } public: diff --git a/include/boost/geometry/algorithms/detail/overlay/follow.hpp b/include/boost/geometry/algorithms/detail/overlay/follow.hpp index d948c4f67..5d62e0c47 100644 --- a/include/boost/geometry/algorithms/detail/overlay/follow.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/follow.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// 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, 2018. +// Modifications copyright (c) 2014-2018 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 @@ -159,7 +159,7 @@ struct action_selector typename LineString, typename Point, typename Operation, - typename SideStrategy, + typename Strategy, typename RobustPolicy > static inline void enter(LineStringOut& current_piece, @@ -167,13 +167,13 @@ struct action_selector segment_identifier& segment_id, signed_size_type , Point const& point, Operation const& operation, - SideStrategy const& , + Strategy const& strategy, RobustPolicy const& , OutputIterator& ) { // On enter, append the intersection point and remember starting point // TODO: we don't check on spikes for linestrings (?). Consider this. - detail::overlay::append_no_duplicates(current_piece, point); + detail::overlay::append_no_duplicates(current_piece, point, strategy.get_equals_point_point_strategy()); segment_id = operation.seg_id; } @@ -184,7 +184,7 @@ struct action_selector typename LineString, typename Point, typename Operation, - typename SideStrategy, + typename Strategy, typename RobustPolicy > static inline void leave(LineStringOut& current_piece, @@ -192,7 +192,7 @@ struct action_selector segment_identifier& segment_id, signed_size_type index, Point const& point, Operation const& , - SideStrategy const& strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, OutputIterator& out) { @@ -202,7 +202,7 @@ struct action_selector < false, RemoveSpikes >::apply(linestring, segment_id, index, strategy, robust_policy, current_piece); - detail::overlay::append_no_duplicates(current_piece, point); + detail::overlay::append_no_duplicates(current_piece, point, strategy.get_equals_point_point_strategy()); if (::boost::size(current_piece) > 1) { *out++ = current_piece; @@ -260,7 +260,7 @@ struct action_selector typename LineString, typename Point, typename Operation, - typename SideStrategy, + typename Strategy, typename RobustPolicy > static inline void enter(LineStringOut& current_piece, @@ -268,7 +268,7 @@ struct action_selector segment_identifier& segment_id, signed_size_type index, Point const& point, Operation const& operation, - SideStrategy const& strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, OutputIterator& out) { @@ -283,7 +283,7 @@ struct action_selector typename LineString, typename Point, typename Operation, - typename SideStrategy, + typename Strategy, typename RobustPolicy > static inline void leave(LineStringOut& current_piece, @@ -291,7 +291,7 @@ struct action_selector segment_identifier& segment_id, signed_size_type index, Point const& point, Operation const& operation, - SideStrategy const& strategy, + Strategy const& strategy, RobustPolicy const& robust_policy, OutputIterator& out) { diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index fef551715..58126fd96 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2017. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2017, 2018. +// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -109,11 +109,12 @@ namespace detail { namespace overlay { class linear_intersections { public: - template + template linear_intersections(Point1 const& pi, Point2 const& qi, IntersectionResult const& result, - bool is_p_last, bool is_q_last) + bool is_p_last, bool is_q_last, + EqPPStrategy const& strategy) { int arrival_a = result.template get<1>().arrival[0]; int arrival_b = result.template get<1>().arrival[1]; @@ -133,10 +134,10 @@ public: ips[0].is_pi = equals::equals_point_point( - pi, result.template get<0>().intersections[0]); + pi, result.template get<0>().intersections[0], strategy); ips[0].is_qi = equals::equals_point_point( - qi, result.template get<0>().intersections[0]); + qi, result.template get<0>().intersections[0], strategy); ips[1].is_pj = arrival_a != -1; ips[1].is_qj = arrival_b != -1; } @@ -233,14 +234,16 @@ struct get_turn_info_for_endpoint typename UniqueSubRange2, typename TurnInfo, typename IntersectionInfo, - typename OutputIterator + typename OutputIterator, + typename EqPPStrategy > static inline bool apply(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, TurnInfo const& tp_model, IntersectionInfo const& inters, method_type /*method*/, - OutputIterator out) + OutputIterator out, + EqPPStrategy const& strategy) { std::size_t ip_count = inters.i_info().count; // no intersection points @@ -262,7 +265,8 @@ struct get_turn_info_for_endpoint range_q.at(0), inters.result(), range_p.is_last_segment(), - range_q.is_last_segment()); + range_q.is_last_segment(), + strategy); bool append0_last = analyse_segment_and_assign_ip(range_p, range_q, 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 476569603..f8272794b 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2015, 2017. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. +// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -52,7 +52,7 @@ struct get_turn_info_linear_areal UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, TurnInfo const& tp_model, - IntersectionStrategy const& intersection_strategy, + IntersectionStrategy const& strategy, RobustPolicy const& robust_policy, OutputIterator out) { @@ -64,8 +64,7 @@ struct get_turn_info_linear_areal RobustPolicy > inters_info; - inters_info inters(range_p, range_q, - intersection_strategy, robust_policy); + inters_info inters(range_p, range_q, strategy, robust_policy); char const method = inters.d_info().how; @@ -79,7 +78,8 @@ struct get_turn_info_linear_areal case 'f' : // collinear, "from" case 's' : // starts from the middle get_turn_info_for_endpoint(range_p, range_q, - tp_model, inters, method_none, out); + tp_model, inters, method_none, out, + strategy.get_point_in_point_strategy()); break; case 'd' : // disjoint: never do anything @@ -88,7 +88,8 @@ struct get_turn_info_linear_areal case 'm' : { if ( get_turn_info_for_endpoint(range_p, range_q, - tp_model, inters, method_touch_interior, out) ) + tp_model, inters, method_touch_interior, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -125,7 +126,8 @@ 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); + inters, + strategy.get_point_in_point_strategy()); *out++ = tp; } @@ -144,7 +146,8 @@ 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) ) + tp_model, inters, method_touch, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -216,7 +219,8 @@ struct get_turn_info_linear_areal bool ignore_spike = calculate_spike_operation(tp.operations[0].operation, - inters); + inters, + strategy.get_point_in_point_strategy()); if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) || ignore_spike @@ -231,7 +235,8 @@ struct get_turn_info_linear_areal case 'e': { if ( get_turn_info_for_endpoint(range_p, range_q, - tp_model, inters, method_equal, out) ) + tp_model, inters, method_equal, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -274,7 +279,8 @@ struct get_turn_info_linear_areal // Collinear if ( get_turn_info_for_endpoint( range_p, range_q, - tp_model, inters, method_collinear, out) ) + tp_model, inters, method_collinear, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -352,12 +358,14 @@ struct get_turn_info_linear_areal only_convert::apply(tp, inters.i_info()); if ( range_p.is_first_segment() - && equals::equals_point_point(range_p.at(0), tp.point) ) + && equals::equals_point_point(range_p.at(0), tp.point, + 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) ) + && equals::equals_point_point(range_p.at(1), tp.point, + strategy.get_point_in_point_strategy()) ) { tp.operations[0].position = position_back; } @@ -383,9 +391,11 @@ struct get_turn_info_linear_areal } template + typename IntersectionInfo, + typename EqPPStrategy> static inline bool calculate_spike_operation(Operation & op, - IntersectionInfo const& inters) + IntersectionInfo const& inters, + EqPPStrategy const& strategy) { bool is_p_spike = ( op == operation_union || op == operation_intersection ) && inters.is_spike_p(); @@ -405,7 +415,7 @@ struct get_turn_info_linear_areal // spike on the edge point // if it's already known that the spike is going out this musn't be checked if ( ! going_out - && equals::equals_point_point(inters.rpj(), inters.rqj()) ) + && detail::equals::equals_point_point(inters.rpj(), inters.rqj(), strategy) ) { int const pk_q2 = inters.sides().pk_wrt_q2(); going_in = pk_q1 < 0 && pk_q2 < 0; // Pk on the right of both @@ -417,7 +427,7 @@ struct get_turn_info_linear_areal // spike on the edge point // if it's already known that the spike is going in this musn't be checked if ( ! going_in - && equals::equals_point_point(inters.rpj(), inters.rqj()) ) + && detail::equals::equals_point_point(inters.rpj(), inters.rqj(), strategy) ) { int const pk_q2 = inters.sides().pk_wrt_q2(); going_in = pk_q1 < 0 || pk_q2 < 0; // Pk on the right of one of them @@ -664,18 +674,20 @@ struct get_turn_info_linear_areal template + typename TurnInfo, + typename IntersectionInfo, + typename OutputIterator, + typename EqPPStrategy> static inline bool get_turn_info_for_endpoint( UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q, TurnInfo const& tp_model, IntersectionInfo const& inters, method_type /*method*/, - OutputIterator out) + OutputIterator out, + EqPPStrategy const& strategy) { namespace ov = overlay; typedef ov::get_turn_info_for_endpoint get_info_e; @@ -700,7 +712,8 @@ struct get_turn_info_linear_areal range_q.at(0), inters.result(), range_p.is_last_segment(), - range_q.is_last_segment()); + range_q.is_last_segment(), + strategy); linear_intersections::ip_info const& ip0 = intersections.template get<0>(); linear_intersections::ip_info const& ip1 = intersections.template get<1>(); @@ -725,14 +738,6 @@ struct get_turn_info_linear_areal } else { - // The code below should avoid using a side_calculator. - // Mainly because it is constructed with the wrong points. - // It should never be constructed other than pi,pj,pk / qi,qj,qk - // That side calculator might not be necessary here. - // Relevant sides can be passed to the method operations_and_equal - // (and that method can assign the operations, no need to return - // a pair, that is not done anywhere in all turns/operations) - // pi is the intersection point at qj or in the middle of q1 // so consider segments // 1. pi at qj: qi-qj-pj and qi-qj-qk @@ -858,6 +863,14 @@ struct get_turn_info_linear_areal // don't ignore anything for now return false; } + + template + static inline bool equals_point_point(Point1 const& point1, Point2 const& point2, + IntersectionStrategy const& strategy) + { + return detail::equals::equals_point_point(point1, point2, + strategy.get_point_in_point_strategy()); + } }; }} // namespace detail::overlay diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index 0ef41cef3..217f4a340 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 @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2015, 2017. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. +// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -74,7 +74,8 @@ struct get_turn_info_linear_linear case 's' : // starts from the middle get_turn_info_for_endpoint ::apply(range_p, range_q, - tp_model, inters, method_none, out); + tp_model, inters, method_none, out, + strategy.get_point_in_point_strategy()); break; case 'd' : // disjoint: never do anything @@ -84,7 +85,8 @@ struct get_turn_info_linear_linear { if ( get_turn_info_for_endpoint ::apply(range_p, range_q, - tp_model, inters, method_touch_interior, out) ) + tp_model, inters, method_touch_interior, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -141,7 +143,8 @@ struct get_turn_info_linear_linear // Both touch (both arrive there) if ( get_turn_info_for_endpoint ::apply(range_p, range_q, - tp_model, inters, method_touch, out) ) + tp_model, inters, method_touch, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -270,7 +273,8 @@ struct get_turn_info_linear_linear { if ( get_turn_info_for_endpoint ::apply(range_p, range_q, - tp_model, inters, method_equal, out) ) + tp_model, inters, method_equal, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -323,7 +327,8 @@ struct get_turn_info_linear_linear // Collinear if ( get_turn_info_for_endpoint ::apply(range_p, range_q, - tp_model, inters, method_collinear, out) ) + tp_model, inters, method_collinear, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -405,26 +410,29 @@ struct get_turn_info_linear_linear // degenerate points if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) ) { + typedef typename IntersectionStrategy::point_in_point_strategy_type + equals_strategy_type; + only_convert::apply(tp, inters.i_info()); // if any, only one of those should be true if ( range_p.is_first_segment() - && equals::equals_point_point(range_p.at(0), tp.point) ) + && equals::equals_point_point(range_p.at(0), tp.point, equals_strategy_type()) ) { tp.operations[0].position = position_front; } else if ( range_p.is_last_segment() - && equals::equals_point_point(range_p.at(1), tp.point) ) + && equals::equals_point_point(range_p.at(1), tp.point, equals_strategy_type()) ) { tp.operations[0].position = position_back; } else if ( range_q.is_first_segment() - && equals::equals_point_point(range_q.at(0), tp.point) ) + && equals::equals_point_point(range_q.at(0), tp.point, equals_strategy_type()) ) { tp.operations[1].position = position_front; } else if ( range_q.is_last_segment() - && equals::equals_point_point(range_q.at(1), tp.point) ) + && equals::equals_point_point(range_q.at(1), tp.point, equals_strategy_type()) ) { tp.operations[1].position = position_back; } diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index 0556c1360..886f8b683 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014, 2016, 2017. -// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2016, 2017, 2018. +// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -108,6 +108,7 @@ template typename Section, typename Point, typename CircularIterator, + typename IntersectionStrategy, typename RobustPolicy > struct unique_sub_range_from_section @@ -169,6 +170,7 @@ private : inline void advance_to_non_duplicate_next(Point const& current, CircularIterator& circular_iterator) const { + typedef typename IntersectionStrategy::point_in_point_strategy_type disjoint_strategy_type; typedef typename robust_point_type::type robust_point_type; robust_point_type current_robust_point; robust_point_type next_robust_point; @@ -187,7 +189,8 @@ private : std::size_t check = 0; while(! detail::disjoint::disjoint_point_point ( - current_robust_point, next_robust_point + current_robust_point, next_robust_point, + disjoint_strategy_type() ) && check++ < m_section.range_count) { @@ -349,8 +352,14 @@ public : it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec1.bounding_box, sec2.bounding_box, robust_policy); ++prev1, ++it1, ++index1, ++next1, ++ndi1) { - unique_sub_range_from_section unique_sub_range1(sec1, index1, - circular1_iterator(begin_range_1, end_range_1, next1, true), *prev1, *it1, robust_policy); + unique_sub_range_from_section + < + areal1, Section1, point1_type, circular1_iterator, + IntersectionStrategy, RobustPolicy + > unique_sub_range1(sec1, index1, + circular1_iterator(begin_range_1, end_range_1, next1, true), + *prev1, *it1, + robust_policy); signed_size_type index2 = sec2.begin_index; signed_size_type ndi2 = sec2.non_duplicate_index; @@ -396,8 +405,14 @@ public : if (! skip) { - unique_sub_range_from_section unique_sub_range2(sec2, index2, - circular2_iterator(begin_range_2, end_range_2, next2), *prev2, *it2, robust_policy); + unique_sub_range_from_section + < + areal2, Section2, point2_type, circular2_iterator, + IntersectionStrategy, RobustPolicy + > unique_sub_range2(sec2, index2, + circular2_iterator(begin_range_2, end_range_2, next2), + *prev2, *it2, + robust_policy); typedef typename boost::range_value::type turn_info; @@ -502,7 +517,9 @@ struct section_visitor template inline bool apply(Section const& sec1, Section const& sec2) { - if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box)) + if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, + sec2.bounding_box, + m_intersection_strategy.get_disjoint_box_box_strategy())) { // false if interrupted return get_turns_in_sections @@ -561,11 +578,13 @@ public: typename IntersectionStrategy::envelope_strategy_type const envelope_strategy = intersection_strategy.get_envelope_strategy(); + typename IntersectionStrategy::expand_strategy_type const + expand_strategy = intersection_strategy.get_expand_strategy(); geometry::sectionalize(geometry1, robust_policy, - sec1, envelope_strategy, 0); + sec1, envelope_strategy, expand_strategy, 0); geometry::sectionalize(geometry2, robust_policy, - sec2, envelope_strategy, 1); + sec2, envelope_strategy, expand_strategy, 1); // ... and then partition them, intersecting overlapping sections in visitor method section_visitor @@ -579,12 +598,21 @@ public: intersection_strategy, robust_policy, turns, interrupt_policy); + typedef detail::section::get_section_box + < + typename IntersectionStrategy::expand_box_strategy_type + > get_section_box_type; + typedef detail::section::overlaps_section_box + < + typename IntersectionStrategy::disjoint_box_box_strategy_type + > overlaps_section_box_type; + geometry::partition < box_type >::apply(sec1, sec2, visitor, - detail::section::get_section_box(), - detail::section::overlaps_section_box()); + get_section_box_type(), + overlaps_section_box_type()); } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp b/include/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp index 88aedecf8..afe8f680b 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-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2018, 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 @@ -148,13 +148,13 @@ struct point_point_point Point2 const& point2, RobustPolicy const& , OutputIterator oit, - Strategy const&) + Strategy const& strategy) { action_selector_pl_pl < PointOut, OverlayType >::apply(point1, - detail::equals::equals_point_point(point1, point2), + detail::equals::equals_point_point(point1, point2, strategy), oit); return oit; @@ -182,7 +182,7 @@ struct multipoint_point_point Point const& point, RobustPolicy const& , OutputIterator oit, - Strategy const&) + Strategy const& strategy) { BOOST_GEOMETRY_ASSERT( OverlayType == overlay_difference ); @@ -194,7 +194,7 @@ struct multipoint_point_point < PointOut, OverlayType >::apply(*it, - detail::equals::equals_point_point(*it, point), + detail::equals::equals_point_point(*it, point, strategy), oit); } @@ -218,7 +218,7 @@ struct point_multipoint_point MultiPoint const& multipoint, RobustPolicy const& , OutputIterator oit, - Strategy const&) + Strategy const& strategy) { typedef action_selector_pl_pl action; @@ -226,7 +226,7 @@ struct point_multipoint_point it = boost::begin(multipoint); it != boost::end(multipoint); ++it) { - if ( detail::equals::equals_point_point(*it, point) ) + if ( detail::equals::equals_point_point(*it, point, strategy) ) { action::apply(point, true, oit); return oit; diff --git a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp index 3cc98d3b7..a7a87a16a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/self_turn_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, 2018. +// Modifications copyright (c) 2017-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -99,7 +99,9 @@ struct self_section_visitor template inline bool apply(Section const& sec1, Section const& sec2) { - if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box) + if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, + sec2.bounding_box, + m_intersection_strategy.get_disjoint_box_box_strategy()) && ! sec1.duplicate && ! sec2.duplicate) { @@ -154,7 +156,8 @@ struct get_turns sections_type sec; geometry::sectionalize(geometry, robust_policy, sec, - intersection_strategy.get_envelope_strategy()); + intersection_strategy.get_envelope_strategy(), + intersection_strategy.get_expand_strategy()); self_section_visitor < @@ -162,13 +165,22 @@ struct get_turns Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy > visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy, source_index, skip_adjacent); + typedef detail::section::get_section_box + < + typename IntersectionStrategy::expand_box_strategy_type + > get_section_box_type; + typedef detail::section::overlaps_section_box + < + typename IntersectionStrategy::disjoint_box_box_strategy_type + > overlaps_section_box_type; + // false if interrupted geometry::partition < box_type >::apply(sec, visitor, - detail::section::get_section_box(), - detail::section::overlaps_section_box()); + get_section_box_type(), + overlaps_section_box_type()); return ! interrupt_policy.has_intersections; } diff --git a/include/boost/geometry/algorithms/detail/point_on_border.hpp b/include/boost/geometry/algorithms/detail/point_on_border.hpp index 831081aa6..b3e14fecb 100644 --- a/include/boost/geometry/algorithms/detail/point_on_border.hpp +++ b/include/boost/geometry/algorithms/detail/point_on_border.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, 2018. +// Modifications copyright (c) 2017-2018 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 @@ -56,117 +56,47 @@ struct get_point } }; -template -struct midpoint_helper -{ - template - static inline bool apply(Point& p, InputPoint const& p1, InputPoint const& p2) - { - typename coordinate_type::type const two = 2; - set(p, - (get(p1) + get(p2)) / two); - return midpoint_helper::apply(p, p1, p2); - } -}; - -template -struct midpoint_helper -{ - template - static inline bool apply(Point& , InputPoint const& , InputPoint const& ) - { - return true; - } -}; - - -template struct point_on_range { // Version with iterator template static inline bool apply(Point& point, Iterator begin, Iterator end) { - Iterator it = begin; - if (it == end) + if (begin == end) { return false; } - if (! Midpoint) - { - geometry::detail::conversion::convert_point_to_point(*it, point); - return true; - } - - Iterator prev = it++; - - // Go to next non-duplicate point - while (it != end - && detail::equals::equals_point_point(*it, *prev)) - { - prev = it++; - } - if (it != end) - { - return midpoint_helper - < - Point, - 0, dimension::value - >::apply(point, *prev, *it); - } - return false; + geometry::detail::conversion::convert_point_to_point(*begin, point); + return true; } // Version with range template static inline bool apply(Point& point, Range const& range) { - typedef typename geometry::cs_tag::type cs_tag; - BOOST_STATIC_ASSERT((! Midpoint || boost::is_same::value)); - return apply(point, boost::begin(range), boost::end(range)); } }; -template struct point_on_polygon { template static inline bool apply(Point& point, Polygon const& polygon) { - return point_on_range - < - Midpoint - >::apply(point, exterior_ring(polygon)); + return point_on_range::apply(point, exterior_ring(polygon)); } }; -template struct point_on_box { template static inline bool apply(Point& point, Box const& box) { - if (BOOST_GEOMETRY_CONDITION(Midpoint)) - { - Point p1, p2; - detail::assign::assign_box_2d_corner(box, p1); - detail::assign::assign_box_2d_corner(box, p2); - midpoint_helper - < - Point, - 0, dimension::value - >::apply(point, p1, p2); - } - else - { - detail::assign::assign_box_2d_corner(box, point); - } - + detail::assign::assign_box_2d_corner(box, point); return true; } }; @@ -206,60 +136,50 @@ namespace dispatch { -template -< - typename GeometryTag, - bool Midpoint - -> +template struct point_on_border {}; - -template -struct point_on_border +template <> +struct point_on_border : detail::point_on_border::get_point {}; +template <> +struct point_on_border + : detail::point_on_border::point_on_range +{}; -template -struct point_on_border - : detail::point_on_border::point_on_range +template <> +struct point_on_border + : detail::point_on_border::point_on_range +{}; + +template <> +struct point_on_border + : detail::point_on_border::point_on_polygon +{}; + +template <> +struct point_on_border + : detail::point_on_border::point_on_box {}; -template -struct point_on_border - : detail::point_on_border::point_on_range -{}; - - -template -struct point_on_border - : detail::point_on_border::point_on_polygon -{}; - - -template -struct point_on_border - : detail::point_on_border::point_on_box -{}; - - -template -struct point_on_border +template <> +struct point_on_border : detail::point_on_border::point_on_multi < - detail::point_on_border::point_on_polygon + detail::point_on_border::point_on_polygon > {}; -template -struct point_on_border +template <> +struct point_on_border : detail::point_on_border::point_on_multi < - detail::point_on_border::point_on_range + detail::point_on_border::point_on_range > {}; @@ -286,33 +206,11 @@ inline bool point_on_border(Point& point, Geometry const& geometry) return dispatch::point_on_border < - typename tag::type, - false + typename tag::type >::apply(point, geometry); } -/*! -\tparam Midpoint boolean flag, true if the point should not be a vertex, but some point - in between of two vertices -\note for Midpoint, it is not taken from two consecutive duplicate vertices, - (unless there are no other). - */ -/* -template -inline bool point_on_border(Point& point, Geometry const& geometry) -{ - concepts::check(); - concepts::check(); - - return dispatch::point_on_border - < - typename tag::type, - Midpoint - >::apply(point, geometry); -} -*/ - }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp index 800fbb2e9..fa0ab1ea0 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. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. +// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -277,7 +277,8 @@ struct areal_areal { // analyse sorted turns turns_analyser analyser; - analyse_each_turn(result, analyser, turns.begin(), turns.end()); + analyse_each_turn(result, analyser, turns.begin(), turns.end(), + point_in_areal_strategy12.get_equals_point_point_strategy()); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; @@ -317,7 +318,8 @@ struct areal_areal { // analyse sorted turns turns_analyser analyser; - analyse_each_turn(result, analyser, turns.begin(), turns.end()); + analyse_each_turn(result, analyser, turns.begin(), turns.end(), + point_in_areal_strategy21.get_equals_point_point_strategy()); if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; @@ -441,9 +443,8 @@ struct areal_areal , m_exit_detected(false) {} - template - void apply(Result & result, TurnIt it) + template + void apply(Result & result, TurnIt it, EqPPStrategy const& strategy) { //BOOST_GEOMETRY_ASSERT( it != last ); @@ -468,7 +469,7 @@ struct areal_areal { // real exit point - may be multiple if ( first_in_range - || ! turn_on_the_same_ip(*m_previous_turn_ptr, *it) ) + || ! turn_on_the_same_ip(*m_previous_turn_ptr, *it, strategy) ) { update_exit(result); m_exit_detected = false; @@ -484,7 +485,7 @@ struct areal_areal { // real entry point if ( first_in_range - || ! turn_on_the_same_ip(*m_previous_turn_ptr, *it) ) + || ! turn_on_the_same_ip(*m_previous_turn_ptr, *it, strategy) ) { update_enter(result); m_enter_detected = false; @@ -581,19 +582,24 @@ struct areal_areal // call analyser.apply() for each turn in range // IMPORTANT! The analyser is also called for the end iterator - last - template + template + < + typename Result, + typename Analyser, + typename TurnIt, + typename EqPPStrategy + > static inline void analyse_each_turn(Result & res, Analyser & analyser, - TurnIt first, TurnIt last) + TurnIt first, TurnIt last, + EqPPStrategy const& strategy) { if ( first == last ) return; for ( TurnIt it = first ; it != last ; ++it ) { - analyser.apply(res, it); + analyser.apply(res, it, strategy); if ( BOOST_GEOMETRY_CONDITION(res.interrupt) ) return; diff --git a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp index 99385e06f..775b14f45 100644 --- a/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp +++ b/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp @@ -1,17 +1,18 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014 Oracle and/or its affiliates. +// Copyright (c) 2014-2018 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) -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP #include + #include #include #include @@ -29,19 +30,26 @@ namespace detail { namespace relate { enum boundary_query { boundary_front, boundary_back, boundary_any }; template ::type> class boundary_checker {}; -template -class boundary_checker +template +class boundary_checker { typedef typename point_type::type point_type; public: + typedef WithinStrategy equals_strategy_type; + boundary_checker(Geometry const& g) : has_boundary( boost::size(g) >= 2 - && !detail::equals::equals_point_point(range::front(g), range::back(g)) ) + && !detail::equals::equals_point_point(range::front(g), + range::back(g), + equals_strategy_type()) ) +#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER , geometry(g) +#endif {} template @@ -51,24 +59,28 @@ public: #ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER // may give false positives for INT BOOST_GEOMETRY_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any) - && detail::equals::equals_point_point(pt, range::front(geometry)) + && detail::equals::equals_point_point(pt, range::front(geometry), WithinStrategy()) || (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any) - && detail::equals::equals_point_point(pt, range::back(geometry)) ); + && detail::equals::equals_point_point(pt, range::back(geometry), WithinStrategy()) ); #endif return has_boundary; } private: bool has_boundary; +#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER Geometry const& geometry; +#endif }; -template -class boundary_checker +template +class boundary_checker { typedef typename point_type::type point_type; public: + typedef WithinStrategy equals_strategy_type; + boundary_checker(Geometry const& g) : is_filled(false), geometry(g) {} @@ -111,7 +123,7 @@ public: point_reference back_pt = range::back(ls); // linear ring or point - no boundary - if (! equals::equals_point_point(front_pt, back_pt)) + if (! equals::equals_point_point(front_pt, back_pt, equals_strategy_type())) { // do not add points containing NaN coordinates // because they cannot be reasonably compared, e.g. with MSVC diff --git a/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp b/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp index 11e95a0b3..fc858fc87 100644 --- a/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp +++ b/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// 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, 2014, 2018. +// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -333,8 +333,9 @@ private: std::vector m_other_entry_points; // TODO: use map here or sorted vector? }; -template -inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn) +template +inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn, + EqPPStrategy const& strategy) { segment_identifier const& prev_seg_id = prev_turn.operations[OpId].seg_id; segment_identifier const& curr_seg_id = curr_turn.operations[OpId].seg_id; @@ -354,7 +355,7 @@ inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn) return false; } - return detail::equals::equals_point_point(prev_turn.point, curr_turn.point); + return detail::equals::equals_point_point(prev_turn.point, curr_turn.point, strategy); } template ::type within_strategy_type; within_strategy_type const within_strategy = intersection_strategy.template get_point_in_geometry_strategy(); - boundary_checker boundary_checker1(geometry1); + + typedef typename within_strategy_type::equals_point_point_strategy_type eq_pp_strategy_type; + + typedef boundary_checker + < + Geometry1, + eq_pp_strategy_type + > boundary_checker1_type; + boundary_checker1_type boundary_checker1(geometry1); + no_turns_la_linestring_pred < Geometry2, Result, within_strategy_type, - boundary_checker, + boundary_checker1_type, TransposeResult > pred1(geometry2, result, @@ -393,12 +402,14 @@ struct linear_areal typedef turns::less<1, turns::less_op_areal_linear<1> > less; std::sort(it, next, less()); + eq_pp_strategy_type const eq_pp_strategy = within_strategy.get_equals_point_point_strategy(); + // analyse areal_boundary_analyser analyser; for ( turn_iterator rit = it ; rit != next ; ++rit ) { // if the analyser requests, break the search - if ( !analyser.apply(it, rit, next) ) + if ( !analyser.apply(it, rit, next, eq_pp_strategy) ) break; } @@ -701,7 +712,8 @@ struct linear_areal { // real exit point - may be multiple // we know that we entered and now we exit - if ( ! turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it) ) + if ( ! turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it, + side_strategy.get_equals_point_point_strategy()) ) { m_exit_watcher.reset_detected_exit(); @@ -743,7 +755,8 @@ struct linear_areal if ( ( op == overlay::operation_intersection || op == overlay::operation_continue ) - && turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it) ) + && turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it, + side_strategy.get_equals_point_point_strategy()) ) { fake_enter_detected = true; } @@ -763,7 +776,8 @@ struct linear_areal && ( op != overlay::operation_blocked // operation different than block || seg_id.multi_index != m_previous_turn_ptr->operations[op_id].seg_id.multi_index ) ) // or the next single-geometry || ( m_previous_operation == overlay::operation_union - && ! turn_on_the_same_ip(*m_previous_turn_ptr, *it) ) + && ! turn_on_the_same_ip(*m_previous_turn_ptr, *it, + side_strategy.get_equals_point_point_strategy()) ) ) { update(res); @@ -795,7 +809,8 @@ struct linear_areal BOOST_GEOMETRY_ASSERT_MSG(m_previous_turn_ptr, "non-NULL ptr expected"); // real interior overlap - if ( ! turn_on_the_same_ip(*m_previous_turn_ptr, *it) ) + if ( ! turn_on_the_same_ip(*m_previous_turn_ptr, *it, + side_strategy.get_equals_point_point_strategy()) ) { update(res); m_interior_detected = false; @@ -1234,7 +1249,7 @@ struct linear_areal point2_type const& qj = range::at(range2, q_seg_ij + 1); point1_type qi_conv; geometry::convert(qi, qi_conv); - bool const is_ip_qj = equals::equals_point_point(turn.point, qj); + bool const is_ip_qj = equals::equals_point_point(turn.point, qj, side_strategy.get_equals_point_point_strategy()); // TODO: test this! // BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi)); // BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi)); @@ -1248,7 +1263,8 @@ struct linear_areal // It would be good to replace it with some O(1) mechanism range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2), range::pos(range2, q_seg_jk), - boost::end(range2)); + boost::end(range2), + side_strategy.get_equals_point_point_strategy()); // Will this sequence of points be always correct? la_side_calculator @@ -1268,8 +1284,9 @@ struct linear_areal } } - template - static inline It find_next_non_duplicated(It first, It current, It last) + template + static inline It find_next_non_duplicated(It first, It current, It last, + EqPPStrategy const& strategy) { BOOST_GEOMETRY_ASSERT( current != last ); @@ -1277,14 +1294,14 @@ struct linear_areal for ( ++it ; it != last ; ++it ) { - if ( !equals::equals_point_point(*current, *it) ) + if ( !equals::equals_point_point(*current, *it, strategy) ) return it; } // if not found start from the beginning for ( it = first ; it != current ; ++it ) { - if ( !equals::equals_point_point(*current, *it) ) + if ( !equals::equals_point_point(*current, *it, strategy) ) return it; } @@ -1427,8 +1444,9 @@ struct linear_areal , m_previous_turn_ptr(NULL) {} - template - bool apply(TurnIt /*first*/, TurnIt it, TurnIt last) + template + bool apply(TurnIt /*first*/, TurnIt it, TurnIt last, + EqPPStrategy const& strategy) { overlay::operation_type op = it->operations[1].operation; @@ -1443,7 +1461,7 @@ struct linear_areal if ( is_union_detected ) { BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr != NULL); - if ( !detail::equals::equals_point_point(it->point, m_previous_turn_ptr->point) ) + if ( !detail::equals::equals_point_point(it->point, m_previous_turn_ptr->point, strategy) ) { // break return false; diff --git a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp index 520f2bd77..6c5d82fde 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. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. +// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -42,6 +42,8 @@ namespace detail { namespace relate { template class disjoint_linestring_pred { + typedef typename BoundaryChecker::equals_strategy_type equals_strategy_type; + public: disjoint_linestring_pred(Result & res, BoundaryChecker const& boundary_checker) @@ -80,7 +82,8 @@ public: // point-like linestring if ( count == 2 && equals::equals_point_point(range::front(linestring), - range::back(linestring)) ) + range::back(linestring), + equals_strategy_type()) ) { update(m_result); } @@ -145,14 +148,24 @@ struct linear_linear if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; - boundary_checker boundary_checker1(geometry1); - disjoint_linestring_pred, false> pred1(result, boundary_checker1); + typedef boundary_checker + < + Geometry1, + typename IntersectionStrategy::point_in_point_strategy_type + > boundary_checker1_type; + boundary_checker1_type boundary_checker1(geometry1); + disjoint_linestring_pred pred1(result, boundary_checker1); for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; - boundary_checker boundary_checker2(geometry2); - disjoint_linestring_pred, true> pred2(result, boundary_checker2); + typedef boundary_checker + < + Geometry2, + typename IntersectionStrategy::point_in_point_strategy_type + > boundary_checker2_type; + boundary_checker2_type boundary_checker2(geometry2); + disjoint_linestring_pred pred2(result, boundary_checker2); for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2); if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; @@ -274,6 +287,8 @@ struct linear_linear BoundaryChecker const& boundary_checker, OtherBoundaryChecker const& other_boundary_checker) { + typedef typename BoundaryChecker::equals_strategy_type equals_strategy_type; + overlay::operation_type const op = it->operations[op_id].operation; segment_identifier const& seg_id = it->operations[op_id].seg_id; @@ -323,7 +338,9 @@ struct linear_linear { // real exit point - may be multiple // we know that we entered and now we exit - if ( ! turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it) ) + if ( ! turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), + *it, + equals_strategy_type()) ) { m_exit_watcher.reset_detected_exit(); @@ -344,7 +361,9 @@ struct linear_linear return; if ( op == overlay::operation_intersection - && turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it) ) + && turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), + *it, + equals_strategy_type()) ) { fake_enter_detected = true; } @@ -647,6 +666,11 @@ struct linear_linear OtherBoundaryChecker const& /*other_boundary_checker*/, bool first_in_range) { + typedef typename BoundaryChecker::equals_strategy_type + equals_strategy1_type; + typedef typename OtherBoundaryChecker::equals_strategy_type + equals_strategy2_type; + typename detail::single_geometry_return_type::type ls1_ref = detail::single_geometry(geometry, turn.operations[op_id].seg_id); typename detail::single_geometry_return_type::type @@ -714,9 +738,13 @@ struct linear_linear // here we don't know which one is degenerated bool const is_point1 = boost::size(ls1_ref) == 2 - && equals::equals_point_point(range::front(ls1_ref), range::back(ls1_ref)); + && equals::equals_point_point(range::front(ls1_ref), + range::back(ls1_ref), + equals_strategy1_type()); bool const is_point2 = boost::size(ls2_ref) == 2 - && equals::equals_point_point(range::front(ls2_ref), range::back(ls2_ref)); + && equals::equals_point_point(range::front(ls2_ref), + range::back(ls2_ref), + equals_strategy2_type()); // if the second one is degenerated if ( !is_point1 && is_point2 ) diff --git a/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp b/include/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp index 8d5f21555..471dfe66e 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 Oracle and/or its affiliates. +// Copyright (c) 2017-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -40,20 +40,21 @@ namespace detail { namespace relate template < typename Geometry, + typename EqPPStrategy, typename Tag = typename tag::type > struct multi_point_geometry_eb { template static inline bool apply(MultiPoint const& , - detail::relate::topology_check const& ) + detail::relate::topology_check const& ) { return true; } }; -template -struct multi_point_geometry_eb +template +struct multi_point_geometry_eb { template struct boundary_visitor @@ -73,7 +74,7 @@ struct multi_point_geometry_eb template bool operator()(Pt const& pt) const { - return detail::equals::equals_point_point(pt, m_point); + return detail::equals::equals_point_point(pt, m_point, EqPPStrategy()); } Point const& m_point; @@ -99,7 +100,7 @@ struct multi_point_geometry_eb template static inline bool apply(MultiPoint const& multi_point, - detail::relate::topology_check const& tc) + detail::relate::topology_check const& tc) { boundary_visitor visitor(multi_point); tc.for_each_boundary_point(visitor); @@ -107,9 +108,12 @@ struct multi_point_geometry_eb } }; -template -struct multi_point_geometry_eb +template +struct multi_point_geometry_eb { + // TODO: CS-specific less compare strategy derived from EqPPStrategy + typedef geometry::less<> less_type; + template struct boundary_visitor { @@ -121,7 +125,7 @@ struct multi_point_geometry_eb template bool apply(Point const& boundary_point) { - if (! std::binary_search(m_points.begin(), m_points.end(), boundary_point, geometry::less<>())) + if (! std::binary_search(m_points.begin(), m_points.end(), boundary_point, less_type())) { m_boundary_found = true; return false; @@ -138,12 +142,12 @@ struct multi_point_geometry_eb template static inline bool apply(MultiPoint const& multi_point, - detail::relate::topology_check const& tc) + detail::relate::topology_check const& tc) { typedef typename boost::range_value::type point_type; typedef std::vector points_type; points_type points(boost::begin(multi_point), boost::end(multi_point)); - std::sort(points.begin(), points.end(), geometry::less<>()); + std::sort(points.begin(), points.end(), less_type()); boundary_visitor visitor(points); tc.for_each_boundary_point(visitor); @@ -165,6 +169,8 @@ struct multi_point_single_geometry { typedef typename point_type::type point2_type; typedef model::box box2_type; + typedef typename Strategy::equals_point_point_strategy_type eq_pp_strategy_type; + typedef typename Strategy::disjoint_point_box_strategy_type d_pb_strategy_type; box2_type box2; geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy()); @@ -181,7 +187,7 @@ struct multi_point_single_geometry } // The default strategy is enough for Point/Box - if (detail::disjoint::disjoint_point_box(*it, box2)) + if (detail::disjoint::disjoint_point_box(*it, box2, d_pb_strategy_type())) { relate::set(result); } @@ -209,7 +215,10 @@ struct multi_point_single_geometry } } - typedef detail::relate::topology_check tc_t; + typedef detail::relate::topology_check + < + SingleGeometry, eq_pp_strategy_type + > tc_t; if ( relate::may_update(result) || relate::may_update(result) ) { @@ -226,8 +235,13 @@ struct multi_point_single_geometry if ( relate::may_update(result) && tc.has_boundary() ) { - if (multi_point_geometry_eb::apply(multi_point, tc)) + if (multi_point_geometry_eb + < + SingleGeometry, eq_pp_strategy_type + >::apply(multi_point, tc)) + { relate::set(result); + } } } @@ -260,32 +274,40 @@ class multi_point_multi_geometry_ii_ib } }; + template struct overlaps_box_point { template static inline bool apply(Box const& box, Point const& point) { // The default strategy is enough for Point/Box - return ! detail::disjoint::disjoint_point_box(point, box); + return ! detail::disjoint::disjoint_point_box(point, box, + DisjointPointBoxStrategy()); } }; + template struct overlaps_box_box_pair { template static inline bool apply(Box const& box, BoxPair const& box_pair) { // The default strategy is enough for Box/Box - return ! detail::disjoint::disjoint_box_box(box_pair.first, box); + return ! detail::disjoint::disjoint_box_box(box_pair.first, box, + DisjointBoxBoxStrategy()); } }; template class item_visitor_type { + typedef typename PtSegStrategy::equals_point_point_strategy_type pp_strategy_type; + typedef typename PtSegStrategy::disjoint_point_box_strategy_type d_pp_strategy_type; + typedef detail::relate::topology_check topology_check_type; + public: item_visitor_type(MultiGeometry const& multi_geometry, - detail::relate::topology_check const& tc, + topology_check_type const& tc, Result & result, PtSegStrategy const& strategy) : m_multi_geometry(multi_geometry) @@ -298,7 +320,7 @@ class multi_point_multi_geometry_ii_ib inline bool apply(Point const& point, BoxPair const& box_pair) { // The default strategy is enough for Point/Box - if (! detail::disjoint::disjoint_point_box(point, box_pair.first)) + if (! detail::disjoint::disjoint_point_box(point, box_pair.first, d_pp_strategy_type())) { typename boost::range_value::type const& single = range::at(m_multi_geometry, box_pair.second); @@ -335,7 +357,7 @@ class multi_point_multi_geometry_ii_ib private: MultiGeometry const& m_multi_geometry; - detail::relate::topology_check const& m_tc; + topology_check_type const& m_tc; Result & m_result; PtSegStrategy const& m_strategy; }; @@ -351,20 +373,33 @@ public: static inline void apply(MultiPoint const& multi_point, MultiGeometry const& multi_geometry, std::vector const& boxes, - detail::relate::topology_check const& tc, + detail::relate::topology_check + < + MultiGeometry, + typename Strategy::equals_point_point_strategy_type + > const& tc, Result & result, Strategy const& strategy) { item_visitor_type visitor(multi_geometry, tc, result, strategy); + typedef overlaps_box_point + < + typename Strategy::disjoint_point_box_strategy_type + > overlaps_box_point_type; + typedef overlaps_box_box_pair + < + typename Strategy::disjoint_box_box_strategy_type + > overlaps_box_box_pair_type; + geometry::partition < box1_type >::apply(multi_point, boxes, visitor, expand_box_point(), - overlaps_box_point(), + overlaps_box_point_type(), expand_box_box_pair(), - overlaps_box_box_pair()); + overlaps_box_box_pair_type()); } }; @@ -387,7 +422,11 @@ struct multi_point_multi_geometry_ii_ib_ie static inline void apply(MultiPoint const& multi_point, MultiGeometry const& multi_geometry, std::vector const& boxes, - detail::relate::topology_check const& tc, + detail::relate::topology_check + < + MultiGeometry, + typename Strategy::equals_point_point_strategy_type + > const& tc, Result & result, Strategy const& strategy) { @@ -461,6 +500,8 @@ struct multi_point_multi_geometry typedef model::box box2_type; typedef std::pair box_pair_type; + typedef typename Strategy::equals_point_point_strategy_type eq_pp_strategy_type; + typename Strategy::envelope_strategy_type const envelope_strategy = strategy.get_envelope_strategy(); @@ -473,7 +514,7 @@ struct multi_point_multi_geometry boxes[i].second = i; } - typedef detail::relate::topology_check tc_t; + typedef detail::relate::topology_check tc_t; tc_t tc(multi_geometry); if ( relate::may_update(result) @@ -512,8 +553,13 @@ struct multi_point_multi_geometry if ( relate::may_update(result) && tc.has_boundary() ) { - if (multi_point_geometry_eb::apply(multi_point, tc)) + if (multi_point_geometry_eb + < + MultiGeometry, eq_pp_strategy_type + >::apply(multi_point, tc)) + { relate::set(result); + } } } diff --git a/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp index e78a404b2..7b1726abe 100644 --- a/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015, 2017. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. +// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -60,7 +60,11 @@ struct point_geometry if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; - typedef detail::relate::topology_check tc_t; + typedef detail::relate::topology_check + < + Geometry, + typename Strategy::equals_point_point_strategy_type + > tc_t; if ( relate::may_update(result) || relate::may_update(result) ) { diff --git a/include/boost/geometry/algorithms/detail/relate/point_point.hpp b/include/boost/geometry/algorithms/detail/relate/point_point.hpp index e0bed72ba..d2a373f3c 100644 --- a/include/boost/geometry/algorithms/detail/relate/point_point.hpp +++ b/include/boost/geometry/algorithms/detail/relate/point_point.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2017, 2018. +// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -39,9 +39,9 @@ struct point_point template static inline void apply(Point1 const& point1, Point2 const& point2, Result & result, - Strategy const& /*strategy*/) + Strategy const& strategy) { - bool equal = detail::equals::equals_point_point(point1, point2); + bool equal = detail::equals::equals_point_point(point1, point2, strategy); if ( equal ) { relate::set(result); @@ -56,8 +56,10 @@ struct point_point } }; -template -std::pair point_multipoint_check(Point const& point, MultiPoint const& multi_point) +template +std::pair point_multipoint_check(Point const& point, + MultiPoint const& multi_point, + EqPPStrategy const& strategy) { bool found_inside = false; bool found_outside = false; @@ -70,7 +72,7 @@ std::pair point_multipoint_check(Point const& point, MultiPoint cons iterator last = boost::end(multi_point); for ( ; it != last ; ++it ) { - bool ii = detail::equals::equals_point_point(point, *it); + bool ii = detail::equals::equals_point_point(point, *it, strategy); if ( ii ) found_inside = true; @@ -92,7 +94,7 @@ struct point_multipoint template static inline void apply(Point const& point, MultiPoint const& multi_point, Result & result, - Strategy const& /*strategy*/) + Strategy const& strategy) { if ( boost::empty(multi_point) ) { @@ -101,7 +103,7 @@ struct point_multipoint return; } - std::pair rel = point_multipoint_check(point, multi_point); + std::pair rel = point_multipoint_check(point, multi_point, strategy); if ( rel.first ) // some point of MP is equal to P { diff --git a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp index 810466ec0..2dff68fe5 100644 --- a/include/boost/geometry/algorithms/detail/relate/topology_check.hpp +++ b/include/boost/geometry/algorithms/detail/relate/topology_check.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017, Oracle and/or its affiliates. +// Copyright (c) 2014-2018, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -28,6 +28,7 @@ namespace detail { namespace relate { // TODO: change the name for e.g. something with the word "exterior" template ::type> struct topology_check : not_implemented @@ -47,8 +48,8 @@ struct topology_check // topology_check(Point const&, IgnoreBoundaryPoint const&) {} //}; -template -struct topology_check +template +struct topology_check { static const char interior = '1'; static const char boundary = '0'; @@ -100,7 +101,9 @@ private: m_has_interior = count > 0; // NOTE: Linestring with all points equal is treated as 1d linear ring m_has_boundary = count > 1 - && ! detail::equals::equals_point_point(range::front(m_ls), range::back(m_ls)); + && ! detail::equals::equals_point_point(range::front(m_ls), + range::back(m_ls), + EqPPStrategy()); m_is_initialized = true; } @@ -112,8 +115,8 @@ private: mutable bool m_has_boundary; }; -template -struct topology_check +template +struct topology_check { static const char interior = '1'; static const char boundary = '0'; @@ -159,6 +162,9 @@ struct topology_check } private: +// TODO: CS-specific less derived from EqPPStrategy + typedef geometry::less<> less_type; + void init() const { if (m_is_initialized) @@ -192,7 +198,7 @@ private: point_reference back_pt = range::back(ls); // don't store boundaries of linear rings, this doesn't change anything - if (! equals::equals_point_point(front_pt, back_pt)) + if (! equals::equals_point_point(front_pt, back_pt, EqPPStrategy())) { // do not add points containing NaN coordinates // because they cannot be reasonably compared, e.g. with MSVC @@ -215,7 +221,7 @@ private: if (! m_endpoints.empty() ) { - std::sort(m_endpoints.begin(), m_endpoints.end(), geometry::less<>()); + std::sort(m_endpoints.begin(), m_endpoints.end(), less_type()); m_has_boundary = find_odd_count(m_endpoints.begin(), m_endpoints.end()); } @@ -225,7 +231,7 @@ private: template static inline std::size_t count_equal(It first, It last, Point const& point) { - std::pair rng = std::equal_range(first, last, point, geometry::less<>()); + std::pair rng = std::equal_range(first, last, point, less_type()); return (std::size_t)std::distance(rng.first, rng.second); } @@ -261,7 +267,7 @@ private: for ( ; first != last ; ++first, ++prev ) { // the end of the equal points subrange - if ( ! equals::equals_point_point(*first, *prev) ) + if ( ! equals::equals_point_point(*first, *prev, EqPPStrategy()) ) { // odd count -> boundary if ( count % 2 != 0 ) @@ -298,40 +304,35 @@ private: mutable std::vector m_endpoints; }; -template -struct topology_check +struct topology_check_areal { static const char interior = '2'; static const char boundary = '1'; + static bool has_interior() { return true; } + static bool has_boundary() { return true; } +}; + +template +struct topology_check + : topology_check_areal +{ topology_check(Ring const&) {} - - static bool has_interior() { return true; } - static bool has_boundary() { return true; } }; -template -struct topology_check +template +struct topology_check + : topology_check_areal { - static const char interior = '2'; - static const char boundary = '1'; - topology_check(Polygon const&) {} - - static bool has_interior() { return true; } - static bool has_boundary() { return true; } }; -template -struct topology_check +template +struct topology_check + : topology_check_areal { - static const char interior = '2'; - static const char boundary = '1'; - topology_check(MultiPolygon const&) {} - - static bool has_interior() { return true; } - static bool has_boundary() { return true; } + template static bool check_boundary_point(Point const& ) { return true; } }; diff --git a/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp b/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp index cf0670030..e6342ff70 100644 --- a/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp +++ b/include/boost/geometry/algorithms/detail/sections/section_box_policies.hpp @@ -2,6 +2,10 @@ // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. +// This file was modified by Oracle on 2018. +// Modifications copyright (c) 2018, Oracle and/or its affiliates. +// 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,21 +25,25 @@ namespace boost { namespace geometry namespace detail { namespace section { +template struct get_section_box { template static inline void apply(Box& total, Section const& section) { - geometry::expand(total, section.bounding_box); + geometry::expand(total, section.bounding_box, + ExpandBoxStrategy()); } }; +template struct overlaps_section_box { template static inline bool apply(Box const& box, Section const& section) { - return ! detail::disjoint::disjoint_box_box(box, section.bounding_box); + return ! detail::disjoint::disjoint_box_box(box, section.bounding_box, + DisjointBoxBoxStrategy()); } }; diff --git a/include/boost/geometry/algorithms/detail/sections/section_functions.hpp b/include/boost/geometry/algorithms/detail/sections/section_functions.hpp index d283784e2..33deb9474 100644 --- a/include/boost/geometry/algorithms/detail/sections/section_functions.hpp +++ b/include/boost/geometry/algorithms/detail/sections/section_functions.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, 2018. +// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -30,6 +30,8 @@ namespace boost { namespace geometry namespace detail { namespace section { +// TODO: This code is CS-specific, should be moved to strategies + template < std::size_t Dimension, @@ -68,7 +70,7 @@ struct preceding_check<0, Geometry, spherical_tag> calc_t const other_min = get(other_box); calc_t const other_max = get(other_box); - bool const pt_covered = strategy::within::covered_by_range + bool const pt_covered = strategy::within::detail::covered_by_range < Point, 0, spherical_tag >::apply(value, diff --git a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp index 7a8638f5c..aca1029ee 100644 --- a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 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, 2018. +// Modifications copyright (c) 2013-2018 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 @@ -58,6 +58,7 @@ #include #include +#include namespace boost { namespace geometry { @@ -330,9 +331,9 @@ struct assign_loop template struct box_first_in_section { - template + template static inline void apply(Box & box, Point const& prev, Point const& curr, - Strategy const& strategy) + EnvelopeStrategy const& strategy) { geometry::model::referring_segment seg(prev, curr); geometry::envelope(seg, box, strategy); @@ -342,9 +343,9 @@ struct box_first_in_section template <> struct box_first_in_section { - template + template static inline void apply(Box & box, Point const& prev, Point const& curr, - Strategy const& ) + ExpandStrategy const& ) { geometry::envelope(prev, box); geometry::expand(box, curr); @@ -399,11 +400,20 @@ struct sectionalize_part { typedef typename strategy::envelope::services::default_strategy < + segment_tag, typename cs_tag::type >::type envelope_strategy_type; + typedef typename strategy::expand::services::default_strategy + < + segment_tag, + typename cs_tag::type + >::type expand_strategy_type; + apply(sections, begin, end, - robust_policy, envelope_strategy_type(), + robust_policy, + envelope_strategy_type(), + expand_strategy_type(), ring_id, max_count); } @@ -412,12 +422,14 @@ struct sectionalize_part typename Iterator, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy + typename EnvelopeStrategy, + typename ExpandStrategy > static inline void apply(Sections& sections, Iterator begin, Iterator end, RobustPolicy const& robust_policy, - EnvelopeStrategy const& strategy, + EnvelopeStrategy const& envelope_strategy, + ExpandStrategy const& expand_strategy, ring_identifier ring_id, std::size_t max_count) { @@ -535,14 +547,14 @@ struct sectionalize_part // In cartesian this is envelope of previous point expanded with current point // in non-cartesian this is envelope of a segment box_first_in_section::type> - ::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy); + ::apply(section.bounding_box, previous_robust_point, current_robust_point, envelope_strategy); } else { // In cartesian this is expand with current point // in non-cartesian this is expand with a segment box_next_in_section::type> - ::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy); + ::apply(section.bounding_box, previous_robust_point, current_robust_point, expand_strategy); } section.end_index = index + 1; @@ -588,12 +600,14 @@ struct sectionalize_range typename Range, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy + typename EnvelopeStrategy, + typename ExpandStrategy > static inline void apply(Range const& range, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& strategy, + EnvelopeStrategy const& envelope_strategy, + ExpandStrategy const& expand_strategy, ring_identifier ring_id, std::size_t max_count) { @@ -622,7 +636,8 @@ struct sectionalize_range sectionalize_part::apply(sections, boost::begin(view), boost::end(view), - robust_policy, strategy, ring_id, max_count); + robust_policy, envelope_strategy, expand_strategy, + ring_id, max_count); } }; @@ -638,12 +653,14 @@ struct sectionalize_polygon typename Polygon, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy + typename EnvelopeStrategy, + typename ExpandStrategy > static inline void apply(Polygon const& poly, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& strategy, + EnvelopeStrategy const& envelope_strategy, + ExpandStrategy const& expand_strategy, ring_identifier ring_id, std::size_t max_count) { @@ -655,7 +672,8 @@ struct sectionalize_polygon > per_range; ring_id.ring_index = -1; - per_range::apply(exterior_ring(poly), robust_policy, sections, strategy, ring_id, max_count); + per_range::apply(exterior_ring(poly), robust_policy, sections, + envelope_strategy, expand_strategy, ring_id, max_count); ring_id.ring_index++; typename interior_return_type::type @@ -663,7 +681,8 @@ struct sectionalize_polygon for (typename detail::interior_iterator::type it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index) { - per_range::apply(*it, robust_policy, sections, strategy, ring_id, max_count); + per_range::apply(*it, robust_policy, sections, + envelope_strategy, expand_strategy, ring_id, max_count); } } }; @@ -676,12 +695,14 @@ struct sectionalize_box typename Box, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy + typename EnvelopeStrategy, + typename ExpandStrategy > static inline void apply(Box const& box, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& , + EnvelopeStrategy const& envelope_strategy, + ExpandStrategy const& expand_strategy, ring_identifier const& ring_id, std::size_t max_count) { typedef typename point_type::type point_type; @@ -714,7 +735,7 @@ struct sectionalize_box point_type, DimensionVector >::apply(points, robust_policy, sections, - strategy::envelope::cartesian_segment<>(), + envelope_strategy, expand_strategy, ring_id, max_count); } }; @@ -727,12 +748,14 @@ struct sectionalize_multi typename MultiGeometry, typename RobustPolicy, typename Sections, - typename EnvelopeStrategy + typename EnvelopeStrategy, + typename ExpandStrategy > static inline void apply(MultiGeometry const& multi, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& strategy, + EnvelopeStrategy const& envelope_strategy, + ExpandStrategy const& expand_strategy, ring_identifier ring_id, std::size_t max_count) { @@ -742,7 +765,9 @@ struct sectionalize_multi it != boost::end(multi); ++it, ++ring_id.multi_index) { - Policy::apply(*it, robust_policy, sections, strategy, ring_id, max_count); + Policy::apply(*it, robust_policy, sections, + envelope_strategy, expand_strategy, + ring_id, max_count); } } }; @@ -915,12 +940,14 @@ template typename Geometry, typename Sections, typename RobustPolicy, - typename EnvelopeStrategy + typename EnvelopeStrategy, + typename ExpandStrategy > inline void sectionalize(Geometry const& geometry, RobustPolicy const& robust_policy, Sections& sections, - EnvelopeStrategy const& strategy, + EnvelopeStrategy const& envelope_strategy, + ExpandStrategy const& expand_strategy, int source_index = 0, std::size_t max_count = 10) { @@ -959,7 +986,9 @@ inline void sectionalize(Geometry const& geometry, Geometry, Reverse, DimensionVector - >::apply(geometry, robust_policy, sections, strategy, ring_id, max_count); + >::apply(geometry, robust_policy, sections, + envelope_strategy, expand_strategy, + ring_id, max_count); detail::sectionalize::enlarge_sections(sections); } @@ -981,14 +1010,27 @@ inline void sectionalize(Geometry const& geometry, { typedef typename strategy::envelope::services::default_strategy < + typename tag::type, typename cs_tag::type >::type envelope_strategy_type; + typedef typename strategy::expand::services::default_strategy + < + typename boost::mpl::if_c + < + boost::is_same::type, box_tag>::value, + box_tag, + segment_tag + >::type, + typename cs_tag::type + >::type expand_strategy_type; + boost::geometry::sectionalize < Reverse, DimensionVector >(geometry, robust_policy, sections, envelope_strategy_type(), + expand_strategy_type(), source_index, max_count); } diff --git a/include/boost/geometry/algorithms/detail/within/interface.hpp b/include/boost/geometry/algorithms/detail/within/interface.hpp index 23263604c..048cc01f7 100644 --- a/include/boost/geometry/algorithms/detail/within/interface.hpp +++ b/include/boost/geometry/algorithms/detail/within/interface.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013, 2014, 2017. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2017, 2018. +// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -70,13 +70,7 @@ struct within Geometry2 const& geometry2, Strategy const& strategy) { - concepts::within::check - < - typename tag::type, - typename tag::type, - typename tag_cast::type, areal_tag>::type, - Strategy - >(); + concepts::within::check(); return dispatch::within::apply(geometry1, geometry2, strategy); } diff --git a/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp index a24f4d21e..1509528d7 100644 --- a/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013, 2014, 2015, 2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018. +// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -45,6 +45,11 @@ namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace within { +template +inline bool equals_point_point(Point1 const& p1, Point2 const& p2, Strategy const& strategy) +{ + return equals::equals_point_point(p1, p2, strategy.get_equals_point_point_strategy()); +} // TODO: is this needed? inline int check_result_type(int result) @@ -139,8 +144,8 @@ struct point_in_geometry return -1; // exterior // if the point is equal to the one of the terminal points - if ( detail::equals::equals_point_point(point, p0) - || detail::equals::equals_point_point(point, p1) ) + if ( detail::within::equals_point_point(point, p0, strategy) + || detail::within::equals_point_point(point, p1, strategy) ) return 0; // boundary else return 1; // interior @@ -161,11 +166,11 @@ struct point_in_geometry return -1; // exterior // if the linestring doesn't have a boundary - if (detail::equals::equals_point_point(range::front(linestring), range::back(linestring))) + if (detail::within::equals_point_point(range::front(linestring), range::back(linestring), strategy)) return 1; // interior // else if the point is equal to the one of the terminal points - else if (detail::equals::equals_point_point(point, range::front(linestring)) - || detail::equals::equals_point_point(point, range::back(linestring))) + else if (detail::within::equals_point_point(point, range::front(linestring), strategy) + || detail::within::equals_point_point(point, range::back(linestring), strategy)) return 0; // boundary else return 1; // interior @@ -304,12 +309,12 @@ struct point_in_geometry point_type const& back = range::back(*it); // is closed_ring - no boundary - if ( detail::equals::equals_point_point(front, back) ) + if ( detail::within::equals_point_point(front, back, strategy) ) continue; // is point on boundary - if ( detail::equals::equals_point_point(point, front) - || detail::equals::equals_point_point(point, back) ) + if ( detail::within::equals_point_point(point, front, strategy) + || detail::within::equals_point_point(point, back, strategy) ) { ++boundaries; } @@ -361,13 +366,7 @@ namespace detail { namespace within { template inline int point_in_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy) { - concepts::within::check - < - typename tag::type, - typename tag::type, - typename tag_cast::type, areal_tag>::type, - Strategy - >(); + concepts::within::check(); return detail_dispatch::within::point_in_geometry::apply(point, geometry, strategy); } diff --git a/include/boost/geometry/algorithms/dispatch/envelope.hpp b/include/boost/geometry/algorithms/dispatch/envelope.hpp index bb8a99f5a..bfe0f0d44 100644 --- a/include/boost/geometry/algorithms/dispatch/envelope.hpp +++ b/include/boost/geometry/algorithms/dispatch/envelope.hpp @@ -4,10 +4,11 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// 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, 2018. +// Modifications copyright (c) 2015-2018, 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,8 +36,7 @@ namespace dispatch template < typename Geometry, - typename Tag = typename tag::type, - typename CS_Tag = typename cs_tag::type + typename Tag = typename tag::type > struct envelope : not_implemented {}; diff --git a/include/boost/geometry/algorithms/dispatch/expand.hpp b/include/boost/geometry/algorithms/dispatch/expand.hpp index c7a769648..204bbc6ce 100644 --- a/include/boost/geometry/algorithms/dispatch/expand.hpp +++ b/include/boost/geometry/algorithms/dispatch/expand.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, 2017. -// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017, 2018. +// Modifications copyright (c) 2015-2018, 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,9 +41,7 @@ template < typename GeometryOut, typename Geometry, typename TagOut = typename tag::type, - typename Tag = typename tag::type, - typename CSTagOut = typename cs_tag::type, - typename CSTag = typename cs_tag::type + typename Tag = typename tag::type > struct expand : not_implemented {}; diff --git a/include/boost/geometry/algorithms/is_convex.hpp b/include/boost/geometry/algorithms/is_convex.hpp index 4a9251b27..1df778d1b 100644 --- a/include/boost/geometry/algorithms/is_convex.hpp +++ b/include/boost/geometry/algorithms/is_convex.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017. -// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018. +// Modifications copyright (c) 2017-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -45,6 +45,9 @@ struct ring_is_convex template static inline bool apply(Ring const& ring, SideStrategy const& strategy) { + typename SideStrategy::equals_point_point_strategy_type + eq_pp_strategy = strategy.get_equals_point_point_strategy(); + std::size_t n = boost::size(ring); if (boost::size(ring) < core_detail::closure::minimum_ring_size < @@ -67,7 +70,8 @@ struct ring_is_convex current++; std::size_t index = 1; - while (equals::equals_point_point(*current, *previous) && index < n) + while (equals::equals_point_point(*current, *previous, eq_pp_strategy) + && index < n) { current++; index++; @@ -81,7 +85,7 @@ struct ring_is_convex it_type next = current; next++; - while (equals::equals_point_point(*current, *next)) + while (equals::equals_point_point(*current, *next, eq_pp_strategy)) { next++; } @@ -105,7 +109,7 @@ struct ring_is_convex // Advance next to next different point // (because there are non-equal points, this loop is not infinite) next++; - while (equals::equals_point_point(*current, *next)) + while (equals::equals_point_point(*current, *next, eq_pp_strategy)) { next++; } diff --git a/include/boost/geometry/algorithms/simplify.hpp b/include/boost/geometry/algorithms/simplify.hpp index 298f9c640..8daac6dda 100644 --- a/include/boost/geometry/algorithms/simplify.hpp +++ b/include/boost/geometry/algorithms/simplify.hpp @@ -4,6 +4,11 @@ // Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// This file was modified by Oracle on 2018. +// Modifications copyright (c) 2018 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -53,12 +58,13 @@ namespace boost { namespace geometry namespace detail { namespace simplify { -template -inline bool is_degenerate(Range const& range) +template +inline bool is_degenerate(Range const& range, EqualsStrategy const& strategy) { return boost::size(range) == 2 && detail::equals::equals_point_point(geometry::range::front(range), - geometry::range::back(range)); + geometry::range::back(range), + strategy); } struct simplify_range_insert @@ -67,9 +73,12 @@ struct simplify_range_insert static inline void apply(Range const& range, OutputIterator out, Distance const& max_distance, Strategy const& strategy) { + typedef typename Strategy::distance_strategy_type::equals_point_point_strategy_type + equals_strategy_type; + boost::ignore_unused(strategy); - if (is_degenerate(range)) + if (is_degenerate(range, equals_strategy_type())) { std::copy(boost::begin(range), boost::begin(range) + 1, out); } @@ -107,6 +116,9 @@ struct simplify_range static inline void apply(RangeIn const& range, RangeOut& out, Distance const& max_distance, Strategy const& strategy) { + typedef typename Strategy::distance_strategy_type::equals_point_point_strategy_type + equals_strategy_type; + // For a RING: // Note that, especially if max_distance is too large, // the output ring might be self intersecting while the input ring is @@ -126,7 +138,7 @@ struct simplify_range // Verify the two remaining points are equal. If so, remove one of them. // This can cause the output being under the minimum size - if (is_degenerate(out)) + if (is_degenerate(out, equals_strategy_type())) { range::resize(out, 1); } diff --git a/include/boost/geometry/algorithms/union.hpp b/include/boost/geometry/algorithms/union.hpp index d3a2daf66..d1d04d404 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. -// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2017, 2018. +// Modifications copyright (c) 2014-2018 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 @@ -279,9 +279,10 @@ struct union_ { typedef typename boost::range_value::type geometry_out; - typedef typename strategy::intersection::services::default_strategy + typedef typename strategy::relate::services::default_strategy < - typename cs_tag::type + Geometry1, + Geometry2 >::type strategy_type; dispatch::union_insert diff --git a/include/boost/geometry/core/cs.hpp b/include/boost/geometry/core/cs.hpp index 301fb6b76..c39eec3d4 100644 --- a/include/boost/geometry/core/cs.hpp +++ b/include/boost/geometry/core/cs.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, 2018. +// Modifications copyright (c) 2014-2018, 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. @@ -22,7 +23,6 @@ #include #include -#include #include #include @@ -56,7 +56,7 @@ namespace core_detail { template -struct coordinate_system_units +struct define_angular_units { BOOST_MPL_ASSERT_MSG ((false), @@ -65,13 +65,13 @@ struct coordinate_system_units }; template <> -struct coordinate_system_units +struct define_angular_units { typedef geometry::degree units; }; template <> -struct coordinate_system_units +struct define_angular_units { typedef geometry::radian units; }; @@ -107,12 +107,8 @@ known as lat,long or lo,la or phi,lambda */ template struct geographic -{ - typedef typename core_detail::coordinate_system_units - < - DegreeOrRadian - >::units units; -}; + : core_detail::define_angular_units +{}; @@ -136,12 +132,8 @@ struct geographic */ template struct spherical -{ - typedef typename core_detail::coordinate_system_units - < - DegreeOrRadian - >::units units; -}; + : core_detail::define_angular_units +{}; /*! @@ -156,12 +148,8 @@ struct spherical */ template struct spherical_equatorial -{ - typedef typename core_detail::coordinate_system_units - < - DegreeOrRadian - >::units units; -}; + : core_detail::define_angular_units +{}; @@ -174,12 +162,15 @@ struct spherical_equatorial */ template struct polar -{ - typedef typename core_detail::coordinate_system_units - < - DegreeOrRadian - >::units units; -}; + : core_detail::define_angular_units +{}; + + +/*! +\brief Undefined coordinate system +\ingroup cs +*/ +struct undefined {}; } // namespace cs @@ -227,9 +218,18 @@ struct cs_tag }; +template <> +struct cs_tag +{ + typedef cs_undefined_tag type; +}; + #endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS + + } // namespace traits + /*! \brief Meta-function returning coordinate system tag (cs family) of any geometry \tparam Geometry \tparam_geometry @@ -245,24 +245,97 @@ struct cs_tag }; -/*! -\brief Meta-function to verify if a coordinate system is radian -\tparam CoordinateSystem Any coordinate system. -\ingroup core -*/ -template -struct is_radian : boost::true_type {}; - - -#ifndef DOXYGEN_NO_SPECIALIZATIONS - -// Specialization for any degree coordinate systems -template class CoordinateSystem> -struct is_radian< CoordinateSystem > : boost::false_type +namespace traits { + +// cartesian or undefined +template +struct cs_angular_units +{ + typedef geometry::radian type; }; -#endif // DOXYGEN_NO_SPECIALIZATIONS +#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS + +template +struct cs_angular_units > +{ + typedef DegreeOrRadian type; +}; + +template +struct cs_angular_units > +{ + typedef DegreeOrRadian type; +}; + +template +struct cs_angular_units > +{ + typedef DegreeOrRadian type; +}; + +#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS + + +} // namespace traits + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct cs_angular_units +{ + typedef typename traits::cs_angular_units + < + typename geometry::coordinate_system::type + >::type type; +}; + + +template +struct cs_tag_to_coordinate_system +{ + BOOST_MPL_ASSERT_MSG((false), + NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM, + (types)); +}; + +template +struct cs_tag_to_coordinate_system +{ + typedef cs::undefined type; +}; + +template +struct cs_tag_to_coordinate_system +{ + typedef cs::cartesian type; +}; + +template +struct cs_tag_to_coordinate_system +{ + typedef cs::spherical_equatorial type; +}; + +template +struct cs_tag_to_coordinate_system +{ + typedef cs::spherical type; +}; + +template +struct cs_tag_to_coordinate_system +{ + typedef cs::geographic type; +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + }} // namespace boost::geometry diff --git a/include/boost/geometry/core/tags.hpp b/include/boost/geometry/core/tags.hpp index 5d6acb187..f5bebbacb 100644 --- a/include/boost/geometry/core/tags.hpp +++ b/include/boost/geometry/core/tags.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2014. -// Modifications copyright (c) 2014 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2018. +// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -25,6 +25,9 @@ namespace boost { namespace geometry // Tags defining strategies linked to coordinate systems +/// Tag used for undefined coordinate system +struct cs_undefined_tag {}; + /// Tag used for casting spherical/geographic coordinate systems struct spherical_tag {}; diff --git a/include/boost/geometry/formulas/spherical.hpp b/include/boost/geometry/formulas/spherical.hpp index 5599cd6e8..964e2de30 100644 --- a/include/boost/geometry/formulas/spherical.hpp +++ b/include/boost/geometry/formulas/spherical.hpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -98,7 +99,7 @@ static inline PointSph cart3d_to_sph(Point3d const& point_3d) math::normalize_spheroidal_coordinates < - typename coordinate_system::type::units, + typename detail::cs_angular_units::type, coord_t >(lon, lat); @@ -183,6 +184,7 @@ inline T spherical_azimuth(T const& lon1, T const& lat1, T const& lon2, T const& template inline int azimuth_side_value(T const& azi_a1_p, T const& azi_a1_a2) { + T const c0 = 0; T const pi = math::pi(); T const two_pi = math::two_pi(); @@ -213,7 +215,7 @@ inline int azimuth_side_value(T const& azi_a1_p, T const& azi_a1_a2) // the difference to 0 as well // positive azimuth is on the right side - return math::equals(a_diff, 0) + return math::equals(a_diff, c0) || math::equals(a_diff, pi) || math::equals(a_diff, -pi) ? 0 : a_diff > 0 ? -1 // right diff --git a/include/boost/geometry/geometries/helper_geometry.hpp b/include/boost/geometry/geometries/helper_geometry.hpp index f3102fee9..e110dd2b1 100644 --- a/include/boost/geometry/geometries/helper_geometry.hpp +++ b/include/boost/geometry/geometries/helper_geometry.hpp @@ -32,60 +32,6 @@ namespace boost { namespace geometry namespace detail { namespace helper_geometries { -template ::type> -struct default_units -{ - typedef typename coordinate_system::type::units type; -}; - -// The Cartesian coordinate system does not define the type units. -// For that reason the generic implementation for default_units cannot be used -// and specialization needs to be defined. -// Moreover, it makes sense to define the units for the Cartesian -// coordinate system to be radians, as this way a Cartesian point can -// potentially be used in algorithms taking non-Cartesian strategies -// and work as if it was as point in the non-Cartesian coordinate -// system with radian units. -template -struct default_units -{ - typedef radian type; -}; - - -template -struct cs_tag_to_coordinate_system -{ - BOOST_MPL_ASSERT_MSG((false), - NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM, - (types)); -}; - -template -struct cs_tag_to_coordinate_system -{ - typedef cs::cartesian type; -}; - -template -struct cs_tag_to_coordinate_system -{ - typedef cs::spherical_equatorial type; -}; - -template -struct cs_tag_to_coordinate_system -{ - typedef cs::spherical type; -}; - -template -struct cs_tag_to_coordinate_system -{ - typedef cs::geographic type; -}; - - template < typename Point, @@ -154,10 +100,7 @@ template < typename Geometry, typename NewCoordinateType = typename coordinate_type::type, - typename NewUnits = typename detail::helper_geometries::default_units - < - Geometry - >::type + typename NewUnits = typename detail::cs_angular_units::type > struct helper_geometry { diff --git a/include/boost/geometry/index/detail/algorithms/intersection_content.hpp b/include/boost/geometry/index/detail/algorithms/intersection_content.hpp index 437f90b46..b8ef9e716 100644 --- a/include/boost/geometry/index/detail/algorithms/intersection_content.hpp +++ b/include/boost/geometry/index/detail/algorithms/intersection_content.hpp @@ -2,7 +2,7 @@ // // boxes union/intersection area/volume // -// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland. // // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -24,7 +24,12 @@ namespace boost { namespace geometry { namespace index { namespace detail { template inline typename default_content_result::type intersection_content(Box const& box1, Box const& box2) { - bool const intersects = ! geometry::detail::disjoint::box_box::apply(box1, box2); + typedef typename strategy::disjoint::services::default_strategy + < + Box, Box + >::type strategy_type; + + bool const intersects = ! geometry::detail::disjoint::disjoint_box_box(box1, box2, strategy_type()); if ( intersects ) { diff --git a/include/boost/geometry/io/wkt/read.hpp b/include/boost/geometry/io/wkt/read.hpp index 9caa36cb4..414024b46 100644 --- a/include/boost/geometry/io/wkt/read.hpp +++ b/include/boost/geometry/io/wkt/read.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, 2015. -// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2015, 2018. +// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include @@ -295,7 +295,7 @@ struct stateful_range_appender should_append = is_next_expected || pt_index < core_detail::closure::minimum_ring_size::value - || !detail::equals::equals_point_point(point, first_point); + || disjoint(point, first_point); } ++pt_index; @@ -306,6 +306,17 @@ struct stateful_range_appender } private: + static inline bool disjoint(point_type const& p1, point_type const& p2) + { + // TODO: pass strategy + typedef typename strategy::disjoint::services::default_strategy + < + point_type, point_type + >::type strategy_type; + + return detail::disjoint::disjoint_point_point(p1, p2, strategy_type()); + } + size_type pt_index; point_type first_point; }; diff --git a/include/boost/geometry/io/wkt/write.hpp b/include/boost/geometry/io/wkt/write.hpp index 34af432fc..62d1d6cb4 100644 --- a/include/boost/geometry/io/wkt/write.hpp +++ b/include/boost/geometry/io/wkt/write.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2017 Mateusz Loskot, London, UK. // Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2018. +// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -162,7 +162,7 @@ struct wkt_range if (ForceClosurePossible && force_closure && boost::size(range) > 1 - && detail::disjoint::disjoint_point_point(*begin, *(end - 1))) + && wkt_range::disjoint(*begin, *(end - 1))) { os << ","; stream_type::apply(os, *begin); @@ -174,6 +174,17 @@ struct wkt_range private: typedef typename boost::range_value::type point_type; + + static inline bool disjoint(point_type const& p1, point_type const& p2) + { + // TODO: pass strategy + typedef typename strategy::disjoint::services::default_strategy + < + point_type, point_type + >::type strategy_type; + + return detail::disjoint::disjoint_point_point(p1, p2, strategy_type()); + } }; /*! diff --git a/include/boost/geometry/srs/transformation.hpp b/include/boost/geometry/srs/transformation.hpp index 38e6ce04c..b8ab4e077 100644 --- a/include/boost/geometry/srs/transformation.hpp +++ b/include/boost/geometry/srs/transformation.hpp @@ -59,15 +59,11 @@ template < typename PtIn, typename PtOut, - bool SameUnits = geometry::is_radian + bool SameUnits = boost::is_same < - typename geometry::coordinate_system::type - >::type::value - == - geometry::is_radian - < - typename geometry::coordinate_system::type - >::type::value + typename geometry::detail::cs_angular_units::type, + typename geometry::detail::cs_angular_units::type + >::value > struct transform_geometry_point_coordinates { diff --git a/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp b/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp index 8493b57c3..80cad8523 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp @@ -4,6 +4,10 @@ // 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. +// 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. @@ -60,16 +64,17 @@ struct decide_covered_by // This strategy is not suitable for boxes in non-cartesian CSes having edges // longer than 180deg because e.g. the SSF formula picks the side of the closer // longitude, so for long edges the side is the opposite. -template +template struct point_in_box_by_side { - typedef typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type side_strategy_type; - + template static inline bool apply(Point const& point, Box const& box) { + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy_type; + // Create (counterclockwise) array of points, the fifth one closes it // Every point should be on the LEFT side (=1), or ON the border (=0), // So >= 1 or >= 0 diff --git a/include/boost/geometry/strategies/agnostic/point_in_point.hpp b/include/boost/geometry/strategies/agnostic/point_in_point.hpp index d4692766c..051b87f40 100644 --- a/include/boost/geometry/strategies/agnostic/point_in_point.hpp +++ b/include/boost/geometry/strategies/agnostic/point_in_point.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2017 Oracle and/or its affiliates. +// Copyright (c) 2014-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -12,10 +12,12 @@ #ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP #define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP -#include -#include -#include +#include +#include + +#include +#include namespace boost { namespace geometry @@ -26,59 +28,32 @@ namespace strategy { namespace within template < - typename Point1, typename Point2 + typename Point1, typename Point2, + typename CSTag = typename cs_tag::type > struct point_in_point -{ - static inline bool apply(Point1 const& point1, Point2 const& point2) - { - return geometry::detail::equals::equals_point_point(point1, point2); - } -}; + : strategy::within::cartesian_point_point +{}; +template +struct point_in_point + : strategy::within::spherical_point_point +{}; -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +template +struct point_in_point + : strategy::within::spherical_point_point +{}; -namespace services -{ - -template -struct default_strategy -{ - typedef strategy::within::point_in_point - < - typename point_type::type, - typename point_type::type - > type; -}; - - -} // namespace services - -#endif +template +struct point_in_point + : strategy::within::spherical_point_point +{}; }} // namespace strategy::within -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS -namespace strategy { namespace covered_by { namespace services -{ - -template -struct default_strategy -{ - typedef strategy::within::point_in_point - < - typename point_type::type, - typename point_type::type - > type; -}; - -}}} // namespace strategy::covered_by::services -#endif - - }} // namespace boost::geometry diff --git a/include/boost/geometry/strategies/cartesian/disjoint_box_box.hpp b/include/boost/geometry/strategies/cartesian/disjoint_box_box.hpp new file mode 100644 index 000000000..da8ae7b1d --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/disjoint_box_box.hpp @@ -0,0 +1,111 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2013-2018. +// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_BOX_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_BOX_BOX_HPP + +#include + +#include +#include + +#include + + +namespace boost { namespace geometry { namespace strategy { namespace disjoint +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +< + typename Box1, typename Box2, + std::size_t Dimension = 0, + std::size_t DimensionCount = dimension::value +> +struct box_box +{ + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + if (get(box1) < get(box2)) + { + return true; + } + if (get(box1) > get(box2)) + { + return true; + } + return box_box + < + Box1, Box2, + Dimension + 1, DimensionCount + >::apply(box1, box2); + } +}; + + +template +struct box_box +{ + static inline bool apply(Box1 const& , Box2 const& ) + { + return false; + } +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +struct cartesian_box_box +{ + template + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + return detail::box_box::apply(box1, box2); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +namespace services +{ + +template +struct default_strategy +{ + typedef disjoint::cartesian_box_box type; +}; + + +} // namespace services + + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}}}} // namespace boost::geometry::strategy::disjoint + + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_BOX_BOX_HPP diff --git a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp index 84f1c948c..bd4f7130c 100644 --- a/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_projected_point.hpp @@ -4,10 +4,11 @@ // 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. -// Modifications copyright (c) 2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2018. +// Modifications copyright (c) 2014-2018, 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. @@ -36,6 +37,7 @@ #include #include #include +#include #include @@ -76,6 +78,8 @@ template class projected_point { public : + typedef within::cartesian_point_point equals_point_point_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/envelope.hpp b/include/boost/geometry/strategies/cartesian/envelope.hpp new file mode 100644 index 000000000..2a11dc5a5 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/envelope.hpp @@ -0,0 +1,153 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015, 2016, 2018. +// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under 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_ENVELOPE_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_HPP + +#include +#include + +#include + +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace envelope +{ + +template +class cartesian +{ +public: + typedef cartesian_point element_envelope_strategy_type; + static inline element_envelope_strategy_type get_element_envelope_strategy() + { + return element_envelope_strategy_type(); + } + + typedef expand::cartesian_point element_expand_strategy_type; + static inline element_expand_strategy_type get_element_expand_strategy() + { + return element_expand_strategy_type(); + } + + typedef expand::cartesian_box box_expand_strategy_type; + static inline box_expand_strategy_type get_box_expand_strategy() + { + return box_expand_strategy_type(); + } + + // Linestring, Ring, Polygon + + template + static inline typename boost::range_iterator::type begin(Range const& range) + { + return boost::begin(range); + } + + template + static inline typename boost::range_iterator::type end(Range const& range) + { + return boost::end(range); + } + + // MultiLinestring, MultiPolygon + + template + struct multi_state + { + multi_state() + : m_initialized(false) + {} + + void apply(Box const& single_box) + { + if (! m_initialized) + { + m_box = single_box; + m_initialized = true; + } + else + { + box_expand_strategy_type::apply(m_box, single_box); + } + } + + void result(Box & box) + { + if (m_initialized) + { + box = m_box; + } + else + { + geometry::detail::envelope::initialize::value>::apply(box); + } + } + + private: + bool m_initialized; + Box m_box; + }; + + // Segment + + template + static inline void apply(Point1 const& point1, Point2 const& point2, + Box& box) + { + cartesian_segment::apply(point1, point2, box); + } + + // Box + + template + static inline void apply(BoxIn const& box_in, Box& box) + { + cartesian_box::apply(box_in, box); + } +}; + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef strategy::envelope::cartesian type; +}; + +} // namespace services + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + +}} //namepsace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_HPP diff --git a/include/boost/geometry/strategies/cartesian/envelope_box.hpp b/include/boost/geometry/strategies/cartesian/envelope_box.hpp new file mode 100644 index 000000000..c6dd21835 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/envelope_box.hpp @@ -0,0 +1,119 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015-2018. +// Modifications copyright (c) 2015-2018, 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 + +// Distributed under 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_ENVELOPE_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_BOX_HPP + +#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 Dimension, + std::size_t DimensionCount +> +struct envelope_indexed_box +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + detail::indexed_point_view box_in_corner(box_in); + detail::indexed_point_view mbr_corner(mbr); + + detail::conversion::point_to_point + < + detail::indexed_point_view, + detail::indexed_point_view, + Dimension, + DimensionCount + >::apply(box_in_corner, mbr_corner); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +namespace strategy { namespace envelope +{ + + +struct cartesian_box +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + geometry::detail::envelope::envelope_indexed_box + < + min_corner, 0, dimension::value + >::apply(box_in, mbr); + + geometry::detail::envelope::envelope_indexed_box + < + max_corner, 0, dimension::value + >::apply(box_in, mbr); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef strategy::envelope::cartesian_box type; +}; + +} + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_BOX_HPP diff --git a/include/boost/geometry/strategies/cartesian/envelope_multipoint.hpp b/include/boost/geometry/strategies/cartesian/envelope_multipoint.hpp new file mode 100644 index 000000000..28c2374ce --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/envelope_multipoint.hpp @@ -0,0 +1,59 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Distributed under 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_ENVELOPE_MULTIPOINT_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_MULTIPOINT_HPP + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace envelope +{ + +class cartesian_multipoint +{ +public: + template + static inline void apply(MultiPoint const& multipoint, Box& mbr) + { + geometry::detail::envelope::envelope_range::apply(multipoint, mbr, cartesian<>()); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef strategy::envelope::cartesian_multipoint type; +}; + + +} // namespace services + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_MULTIPOINT_HPP diff --git a/include/boost/geometry/strategies/cartesian/envelope_point.hpp b/include/boost/geometry/strategies/cartesian/envelope_point.hpp new file mode 100644 index 000000000..3f900c718 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/envelope_point.hpp @@ -0,0 +1,111 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015, 2016, 2017, 2018. +// Modifications copyright (c) 2015-2018, 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 + +// Distributed under 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_ENVELOPE_POINT_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_POINT_HPP + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + +template +struct envelope_one_point +{ + template + static inline void apply(Point const& point, Box& mbr) + { + detail::indexed_point_view box_corner(mbr); + detail::conversion::point_to_point + < + Point, + detail::indexed_point_view, + Dimension, + DimensionCount + >::apply(point, box_corner); + } + + template + static inline void apply(Point const& point, Box& mbr) + { + apply(point, mbr); + apply(point, mbr); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +namespace strategy { namespace envelope +{ + +struct cartesian_point +{ + template + static inline void apply(Point const& point, Box& mbr) + { + geometry::detail::envelope::envelope_one_point + < + 0, dimension::value + >::apply(point, mbr); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef strategy::envelope::cartesian_point type; +}; + + +} + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_POINT_HPP diff --git a/include/boost/geometry/strategies/cartesian/envelope_segment.hpp b/include/boost/geometry/strategies/cartesian/envelope_segment.hpp index a591996b8..cd52775da 100644 --- a/include/boost/geometry/strategies/cartesian/envelope_segment.hpp +++ b/include/boost/geometry/strategies/cartesian/envelope_segment.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2017 Oracle and/or its affiliates. +// Copyright (c) 2017-2018 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -11,40 +11,61 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP +#include -#include +#include #include + +#include +#include #include -#include - -namespace boost { namespace geometry +namespace boost { namespace geometry { namespace strategy { namespace envelope { -namespace strategy { namespace envelope +#ifndef DOXYGEN_NO_DETAIL +namespace detail { +template +struct envelope_one_segment +{ + template + static inline void apply(Point const& p1, + Point const& p2, + Box& mbr) + { + geometry::detail::envelope::envelope_one_point + < + Dimension, DimensionCount + >::apply(p1, mbr); + + strategy::expand::detail::point_loop + < + Dimension, DimensionCount + >::apply(mbr, p2); + } +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + template < typename CalculationType = void > class cartesian_segment { -public : - - template - inline void - apply(Point1 const& point1, Point2 const& point2, Box& box) const +public: + template + static inline void apply(Point const& point1, Point const& point2, Box& box) { - geometry::detail::envelope::envelope_one_segment - < - 0, - dimension::value - > - ::apply(point1, - point2, - box, - strategy::envelope::cartesian_segment()); + strategy::envelope::detail::envelope_one_segment + < + 0, + dimension::value + >::apply(point1, point2, box); } }; @@ -55,7 +76,7 @@ namespace services { template -struct default_strategy +struct default_strategy { typedef strategy::envelope::cartesian_segment type; }; diff --git a/include/boost/geometry/strategies/cartesian/expand_box.hpp b/include/boost/geometry/strategies/cartesian/expand_box.hpp new file mode 100644 index 000000000..68b8824f8 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/expand_box.hpp @@ -0,0 +1,69 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015, 2016, 2017. +// Modifications copyright (c) 2015-2017, 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 + +// Distributed under 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_EXPAND_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_BOX_HPP + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +struct cartesian_box +{ + template + static void apply(BoxOut & box_out, BoxIn const& box_in) + { + geometry::detail::expand::expand_indexed + < + 0, dimension::value + >::apply(box_out, box_in); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef cartesian_box type; +}; + + +} // namespace services + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::expand + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_BOX_HPP diff --git a/include/boost/geometry/strategies/cartesian/expand_point.hpp b/include/boost/geometry/strategies/cartesian/expand_point.hpp new file mode 100644 index 000000000..87d82dca0 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/expand_point.hpp @@ -0,0 +1,125 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015-2018. +// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under 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_EXPAND_POINT_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_POINT_HPP + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct point_loop +{ + template + static inline void apply(Box& box, Point const& source) + { + typedef typename select_coordinate_type + < + Point, Box + >::type coordinate_type; + + std::less less; + std::greater greater; + + coordinate_type const coord = get(source); + + if (less(coord, get(box))) + { + set(box, coord); + } + + if (greater(coord, get(box))) + { + set(box, coord); + } + + point_loop::apply(box, source); + } +}; + + +template +struct point_loop +{ + template + static inline void apply(Box&, Point const&) {} +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +struct cartesian_point +{ + template + static void apply(Box & box, Point const& point) + { + expand::detail::point_loop + < + 0, dimension::value + >::apply(box, point); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef cartesian_point type; +}; + + +} // namespace services + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::expand + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_POINT_HPP diff --git a/include/boost/geometry/strategies/cartesian/expand_segment.hpp b/include/boost/geometry/strategies/cartesian/expand_segment.hpp new file mode 100644 index 000000000..18fd9c9a7 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/expand_segment.hpp @@ -0,0 +1,71 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// 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. + +// 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 + +// Distributed under 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_EXPAND_SEGMENT_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_SEGMENT_HPP + + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +class cartesian_segment +{ +public: + template + static void apply(Box & box, Segment const& segment) + { + geometry::detail::expand::expand_indexed + < + 0, dimension::value + >::apply(box, segment); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef cartesian_segment type; +}; + + +} // namespace services + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::expand + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_SEGMENT_HPP diff --git a/include/boost/geometry/strategies/cartesian/intersection.hpp b/include/boost/geometry/strategies/cartesian/intersection.hpp index 10fd73ba5..fea98af1b 100644 --- a/include/boost/geometry/strategies/cartesian/intersection.hpp +++ b/include/boost/geometry/strategies/cartesian/intersection.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014, 2016, 2017. -// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2016, 2017, 2018. +// Modifications copyright (c) 2014-2018, 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 @@ -34,8 +34,12 @@ #include #include +#include #include -#include +#include +#include +#include +#include #include #include #include @@ -132,14 +136,44 @@ struct cartesian_segments return strategy_type(); } - typedef envelope::cartesian_segment - envelope_strategy_type; + typedef envelope::cartesian envelope_strategy_type; static inline envelope_strategy_type get_envelope_strategy() { return envelope_strategy_type(); } + typedef expand::cartesian_segment expand_strategy_type; + + static inline expand_strategy_type get_expand_strategy() + { + return expand_strategy_type(); + } + + typedef within::cartesian_point_point point_in_point_strategy_type; + + static inline point_in_point_strategy_type get_point_in_point_strategy() + { + return point_in_point_strategy_type(); + } + + typedef within::cartesian_point_point equals_point_point_strategy_type; + + static inline equals_point_point_strategy_type get_equals_point_point_strategy() + { + return equals_point_point_strategy_type(); + } + + typedef disjoint::cartesian_box_box disjoint_box_box_strategy_type; + + static inline disjoint_box_box_strategy_type get_disjoint_box_box_strategy() + { + return disjoint_box_box_strategy_type(); + } + + typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type; + typedef expand::cartesian_box expand_box_strategy_type; + template struct segment_intersection_info { @@ -314,12 +348,12 @@ struct cartesian_segments BOOST_CONCEPT_ASSERT( (concepts::ConstSegment) ); using geometry::detail::equals::equals_point_point; - bool const a_is_point = equals_point_point(robust_a1, robust_a2); - bool const b_is_point = equals_point_point(robust_b1, robust_b2); + bool const a_is_point = equals_point_point(robust_a1, robust_a2, point_in_point_strategy_type()); + bool const b_is_point = equals_point_point(robust_b1, robust_b2, point_in_point_strategy_type()); if(a_is_point && b_is_point) { - return equals_point_point(robust_a1, robust_b2) + return equals_point_point(robust_a1, robust_b2, point_in_point_strategy_type()) ? Policy::degenerate(a, true) : Policy::disjoint() ; diff --git a/include/boost/geometry/strategies/cartesian/point_in_box.hpp b/include/boost/geometry/strategies/cartesian/point_in_box.hpp index 1c14125a6..468e167c6 100644 --- a/include/boost/geometry/strategies/cartesian/point_in_box.hpp +++ b/include/boost/geometry/strategies/cartesian/point_in_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-2017. -// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015-2018. +// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,10 @@ namespace boost { namespace geometry { namespace strategy namespace within { +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + struct within_coord { template @@ -101,7 +106,7 @@ struct longitude_range < Value1, Value2 >::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(value, min_value, max_value)) @@ -142,18 +147,16 @@ struct covered_by_range template < template class SubStrategy, - typename Point, - typename Box, + typename CSTag, // cartesian_tag or spherical_tag std::size_t Dimension, std::size_t DimensionCount > struct relate_point_box_loop { + template static inline bool apply(Point const& point, Box const& box) { - typedef typename tag_cast::type, spherical_tag>::type cs_tag_t; - - if (! SubStrategy::apply(get(point), + if (! SubStrategy::apply(get(point), get(box), get(box)) ) @@ -164,7 +167,7 @@ struct relate_point_box_loop return relate_point_box_loop < SubStrategy, - Point, Box, + CSTag, Dimension + 1, DimensionCount >::apply(point, box); } @@ -174,78 +177,119 @@ struct relate_point_box_loop template < template class SubStrategy, - typename Point, - typename Box, + typename CSTag, std::size_t DimensionCount > -struct relate_point_box_loop +struct relate_point_box_loop { + template static inline bool apply(Point const& , Box const& ) { return true; } }; +} // namespace detail +#endif // DOXYGEN_NO_DETAIL -template -< - typename Point, - typename Box, - template class SubStrategy = within_range -> -struct point_in_box +struct cartesian_point_box { + template static inline bool apply(Point const& point, Box const& box) { - return relate_point_box_loop + return detail::relate_point_box_loop < - SubStrategy, - Point, Box, - 0, dimension::type::value + detail::within_range, + cartesian_tag, + 0, dimension::value + >::apply(point, box); + } +}; + +struct spherical_point_box +{ + template + static inline bool apply(Point const& point, Box const& box) + { + return detail::relate_point_box_loop + < + detail::within_range, + spherical_tag, + 0, dimension::value >::apply(point, box); } }; +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template +struct default_strategy + < + Point, Box, + point_tag, box_tag, + pointlike_tag, areal_tag, + cartesian_tag, cartesian_tag + > +{ + typedef within::cartesian_point_box type; +}; + +// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag +template +struct default_strategy + < + Point, Box, + point_tag, box_tag, + pointlike_tag, areal_tag, + spherical_tag, spherical_tag + > +{ + typedef within::spherical_point_box type; +}; + + +} // namespace services +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + } // namespace within +namespace covered_by +{ + +struct cartesian_point_box +{ + template + static inline bool apply(Point const& point, Box const& box) + { + return within::detail::relate_point_box_loop + < + within::detail::covered_by_range, + cartesian_tag, + 0, dimension::value + >::apply(point, box); + } +}; + +struct spherical_point_box +{ + template + static inline bool apply(Point const& point, Box const& box) + { + return within::detail::relate_point_box_loop + < + within::detail::covered_by_range, + spherical_tag, + 0, dimension::value + >::apply(point, box); + } +}; + #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS - - -namespace within { namespace services -{ - -template -struct default_strategy - < - Point, Box, - point_tag, box_tag, - pointlike_tag, areal_tag, - cartesian_tag, cartesian_tag - > -{ - typedef within::point_in_box type; -}; - -// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag -template -struct default_strategy - < - Point, Box, - point_tag, box_tag, - pointlike_tag, areal_tag, - spherical_tag, spherical_tag - > -{ - typedef within::point_in_box type; -}; - - -}} // namespace within::services - - -namespace covered_by { namespace services +namespace services { @@ -258,11 +302,7 @@ struct default_strategy cartesian_tag, cartesian_tag > { - typedef within::point_in_box - < - Point, Box, - within::covered_by_range - > type; + typedef covered_by::cartesian_point_box type; }; // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag @@ -275,20 +315,17 @@ struct default_strategy spherical_tag, spherical_tag > { - typedef within::point_in_box - < - Point, Box, - within::covered_by_range - > type; + typedef covered_by::spherical_point_box type; }; -}} // namespace covered_by::services - - +} // namespace services #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +} // namespace covered_by + + }}} // namespace boost::geometry::strategy diff --git a/include/boost/geometry/strategies/cartesian/point_in_point.hpp b/include/boost/geometry/strategies/cartesian/point_in_point.hpp new file mode 100644 index 000000000..fc849dcd4 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/point_in_point.hpp @@ -0,0 +1,124 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// 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. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POINT_HPP +#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POINT_HPP + +#include + +#include +#include +#include + +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace within +{ + + +template +struct point_point_generic +{ + template + static inline bool apply(Point1 const& p1, Point2 const& p2) + { + if (! geometry::math::equals(get(p1), get(p2))) + { + return false; + } + return + point_point_generic::apply(p1, p2); + } +}; + +template +struct point_point_generic +{ + template + static inline bool apply(Point1 const&, Point2 const& ) + { + return true; + } +}; + +}} // namespace detail::within +#endif // DOXYGEN_NO_DETAIL + + +namespace strategy { namespace within +{ + +struct cartesian_point_point +{ + template + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + return geometry::detail::within::point_point_generic + < + 0, dimension::type::value + >::apply(point1, point2); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template +struct default_strategy +{ + typedef strategy::within::cartesian_point_point type; +}; + +} // namespace services +#endif + + +}} // namespace strategy::within + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace strategy { namespace covered_by { namespace services +{ + +template +struct default_strategy +{ + typedef strategy::within::cartesian_point_point type; +}; + +}}} // namespace strategy::covered_by::services +#endif + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POINT_HPP 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 c41bc9b83..d7f972758 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. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018. +// Modifications copyright (c) 2013-2018 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 @@ -23,6 +23,8 @@ #include #include +#include +#include #include #include #include @@ -103,6 +105,20 @@ public: return side_strategy_type::get_disjoint_strategy(); } + typedef typename side_strategy_type::equals_point_point_strategy_type equals_point_point_strategy_type; + static inline equals_point_point_strategy_type get_equals_point_point_strategy() + { + return side_strategy_type::get_equals_point_point_strategy(); + } + + typedef disjoint::cartesian_box_box disjoint_box_box_strategy_type; + static inline disjoint_box_box_strategy_type get_disjoint_box_box_strategy() + { + return disjoint_box_box_strategy_type(); + } + + 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; diff --git a/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/include/boost/geometry/strategies/cartesian/side_by_triangle.hpp index 91bbee7bb..9760f560c 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. -// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017, 2018. +// Modifications copyright (c) 2015-2018, 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,8 @@ #include #include -#include +#include +#include #include #include @@ -70,7 +71,7 @@ class side_by_triangle }; public : - typedef strategy::envelope::cartesian_segment envelope_strategy_type; + typedef strategy::envelope::cartesian envelope_strategy_type; static inline envelope_strategy_type get_envelope_strategy() { @@ -84,6 +85,12 @@ public : return disjoint_strategy_type(); } + typedef strategy::within::cartesian_point_point equals_point_point_strategy_type; + static inline equals_point_point_strategy_type get_equals_point_point_strategy() + { + return equals_point_point_strategy_type(); + } + // Template member function, because it is not always trivial // or convenient to explicitly mention the typenames in the // strategy-struct itself. @@ -166,9 +173,9 @@ public : // For robustness purposes, first check if any two points are // the same; in this case simply return that the points are // collinear - if (geometry::detail::equals::equals_point_point(p1, p2) - || geometry::detail::equals::equals_point_point(p1, p) - || geometry::detail::equals::equals_point_point(p2, p)) + if (equals_point_point(p1, p2) + || equals_point_point(p1, p) + || equals_point_point(p2, p)) { return PromotedType(0); } @@ -258,6 +265,13 @@ public : : -1; } +private: + template + static inline bool equals_point_point(P1 const& p1, P2 const& p2) + { + typedef equals_point_point_strategy_type strategy_t; + return geometry::detail::equals::equals_point_point(p1, p2, strategy_t()); + } }; diff --git a/include/boost/geometry/strategies/concepts/within_concept.hpp b/include/boost/geometry/strategies/concepts/within_concept.hpp index c02d0dc50..93680f693 100644 --- a/include/boost/geometry/strategies/concepts/within_concept.hpp +++ b/include/boost/geometry/strategies/concepts/within_concept.hpp @@ -4,6 +4,10 @@ // 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. +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -20,6 +24,10 @@ #include #include +#include +#include +#include + #include @@ -107,7 +115,7 @@ public : #endif }; -template +template class WithinStrategyPointBox { #ifndef DOXYGEN_NO_CONCEPT_MEMBERS @@ -165,7 +173,7 @@ class WithinStrategyPointBox public : BOOST_CONCEPT_USAGE(WithinStrategyPointBox) { - checker::apply(&Strategy::apply); + checker::apply(&Strategy::template apply); } #endif }; @@ -241,26 +249,36 @@ namespace within namespace dispatch { -template +template +< + typename Geometry1, typename Geometry2, + typename FirstTag, typename SecondTag, typename CastedTag, + typename Strategy +> struct check_within {}; -template -struct check_within +template +< + typename Geometry1, typename Geometry2, + typename AnyTag, + typename Strategy +> +struct check_within { BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal) ); }; -template -struct check_within +template +struct check_within { - BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox) ); + BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox) ); }; -template -struct check_within +template +struct check_within { BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox) ); }; @@ -274,10 +292,18 @@ struct check_within \brief Checks, in compile-time, the concept of any within-strategy \ingroup concepts */ -template +template inline void check() { - dispatch::check_within c; + dispatch::check_within + < + Geometry1, + Geometry2, + typename tag::type, + typename tag::type, + typename tag_cast::type, areal_tag>::type, + Strategy + > c; boost::ignore_unused(c); } diff --git a/include/boost/geometry/strategies/disjoint.hpp b/include/boost/geometry/strategies/disjoint.hpp index 23d2cede4..c111d2b8f 100644 --- a/include/boost/geometry/strategies/disjoint.hpp +++ b/include/boost/geometry/strategies/disjoint.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2017, Oracle and/or its affiliates. +// Copyright (c) 2017-2018, 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 @@ -77,13 +77,6 @@ struct default_strategy > {}; -template -struct default_strategy -{ - // dummy strategy which will be ignored - typedef geometry::default_strategy type; -}; - } // namespace services #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS diff --git a/include/boost/geometry/strategies/envelope.hpp b/include/boost/geometry/strategies/envelope.hpp index fde9c858a..050ed4658 100644 --- a/include/boost/geometry/strategies/envelope.hpp +++ b/include/boost/geometry/strategies/envelope.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2016-2017 Oracle and/or its affiliates. +// Copyright (c) 2016-2018 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -23,16 +23,17 @@ namespace strategy { namespace envelope { namespace services /*! \brief Traits class binding a default envelope strategy to a coordinate system \ingroup util +\tparam Tag tag of geometry \tparam CSTag tag of coordinate system \tparam CalculationType \tparam_calculation */ -template +template struct default_strategy { BOOST_MPL_ASSERT_MSG ( false, NOT_IMPLEMENTED_FOR_THIS_TYPE - , (types) + , (types) ); }; diff --git a/include/boost/geometry/strategies/expand.hpp b/include/boost/geometry/strategies/expand.hpp new file mode 100644 index 000000000..39d414514 --- /dev/null +++ b/include/boost/geometry/strategies/expand.hpp @@ -0,0 +1,45 @@ +// Boost.Geometry + +// Copyright (c) 2018 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_EXPAND_HPP +#define BOOST_GEOMETRY_STRATEGIES_EXPAND_HPP + +#include + +namespace boost { namespace geometry +{ + + +namespace strategy { namespace expand { namespace services +{ + +/*! +\brief Traits class binding a default envelope strategy to a coordinate system +\ingroup util +\tparam Tag tag of geometry +\tparam CSTag tag of coordinate system +\tparam CalculationType \tparam_calculation +*/ +template +struct default_strategy +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_TYPE + , (types) + ); +}; + +}}} // namespace strategy::expand::services + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_EXPAND_HPP + diff --git a/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp b/include/boost/geometry/strategies/geographic/disjoint_segment_box.hpp index afc9d6677..49c80a5e7 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 Oracle and/or its affiliates. +// Copyright (c) 2017-2018 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 @@ -29,9 +29,14 @@ #include #include +#include + #include #include #include +#include +#include +#include namespace boost { namespace geometry { namespace strategy { namespace disjoint @@ -89,7 +94,13 @@ public: > azimuth_geographic(m_spheroid); return geometry::detail::disjoint::disjoint_segment_box_sphere_or_spheroid - ::apply(segment, box, azimuth_geographic); + < + geographic_tag + >::apply(segment, box, + azimuth_geographic, + strategy::normalize::spherical_point(), + strategy::covered_by::spherical_point_box(), + strategy::disjoint::spherical_box_box()); } private: diff --git a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp index f84bb4134..eddd50302 100644 --- a/include/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +85,8 @@ template class geographic_cross_track { public : + typedef within::spherical_point_point equals_point_point_strategy_type; + template struct return_type : promote_floating_point @@ -105,7 +108,7 @@ public : inline typename return_type::type apply(Point const& p, PointOfSegment const& sp1, PointOfSegment const& sp2) const { - typedef typename coordinate_system::type::units units_type; + typedef typename geometry::detail::cs_angular_units::type units_type; return (apply(get<0>(sp1), get<1>(sp1), get<0>(sp2), get<1>(sp2), diff --git a/include/boost/geometry/strategies/geographic/distance_segment_box.hpp b/include/boost/geometry/strategies/geographic/distance_segment_box.hpp index 6bde78ca2..02168e649 100644 --- a/include/boost/geometry/strategies/geographic/distance_segment_box.hpp +++ b/include/boost/geometry/strategies/geographic/distance_segment_box.hpp @@ -2,6 +2,7 @@ // Copyright (c) 2018 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // 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,8 +11,21 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_SEGMENT_BOX_HPP #define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_SEGMENT_BOX_HPP +#include + #include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + namespace boost { namespace geometry { @@ -107,7 +121,10 @@ struct geographic_segment_box ReturnType >(p0,p1,top_left,top_right,bottom_left,bottom_right, geographic_segment_box(), - az_strategy, es_strategy); + az_strategy, es_strategy, + normalize::spherical_point(), + covered_by::spherical_point_box(), + disjoint::spherical_box_box()); } template diff --git a/include/boost/geometry/strategies/geographic/envelope.hpp b/include/boost/geometry/strategies/geographic/envelope.hpp new file mode 100644 index 000000000..c98d995fe --- /dev/null +++ b/include/boost/geometry/strategies/geographic/envelope.hpp @@ -0,0 +1,111 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015, 2016, 2018. +// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under 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_ENVELOPE_HPP +#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_HPP + +#include + +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace envelope +{ + + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = geometry::srs::spheroid, + typename CalculationType = void +> +class geographic + : public spherical +{ +public: + typedef Spheroid model_type; + + inline geographic() + : m_spheroid() + {} + + explicit inline geographic(Spheroid const& spheroid) + : m_spheroid(spheroid) + {} + + typedef geographic_segment + < + FormulaPolicy, Spheroid, CalculationType + > element_envelope_strategy_type; + inline element_envelope_strategy_type get_element_envelope_strategy() const + { + return element_envelope_strategy_type(m_spheroid); + } + + typedef expand::geographic_segment + < + FormulaPolicy, Spheroid, CalculationType + > element_expand_strategy_type; + inline element_expand_strategy_type get_element_expand_strategy() const + { + return element_expand_strategy_type(m_spheroid); + } + + template + inline void apply(Point1 const& point1, Point2 const& point2, Box& box) const + { + geographic_segment + < + FormulaPolicy, + Spheroid, + CalculationType + >(m_spheroid).apply(point1, point2, box); + } + +private: + Spheroid m_spheroid; +}; + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef strategy::envelope::geographic type; +}; + +} + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + +}} //namepsace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_HPP diff --git a/include/boost/geometry/strategies/geographic/envelope_segment.hpp b/include/boost/geometry/strategies/geographic/envelope_segment.hpp index 5bada63f6..fda7868af 100644 --- a/include/boost/geometry/strategies/geographic/envelope_segment.hpp +++ b/include/boost/geometry/strategies/geographic/envelope_segment.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2017 Oracle and/or its affiliates. +// Copyright (c) 2017-2018 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -12,15 +12,15 @@ #define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_SEGMENT_HPP -#include -#include - #include +#include #include #include #include - +#include +#include +#include namespace boost { namespace geometry { @@ -47,11 +47,18 @@ public: : m_spheroid(spheroid) {} - template - inline void apply(Point1 const& point1, Point2 const& point2, Box& box) const + typedef strategy::expand::spherical_box box_expand_strategy_type; + static inline box_expand_strategy_type get_box_expand_strategy() { - Point1 p1_normalized = detail::return_normalized(point1); - Point2 p2_normalized = detail::return_normalized(point2); + return box_expand_strategy_type(); + } + + template + inline void apply(Point const& point1, Point const& point2, Box& box) const + { + Point p1_normalized, p2_normalized; + strategy::normalize::spherical_point::apply(point1, p1_normalized); + strategy::normalize::spherical_point::apply(point2, p2_normalized); geometry::strategy::azimuth::geographic < @@ -60,9 +67,13 @@ public: CalculationType > azimuth_geographic(m_spheroid); - typedef typename coordinate_system::type::units units_type; + typedef typename geometry::detail::cs_angular_units + < + Point + >::type units_type; - detail::envelope::envelope_segment_impl + // first compute the envelope range for the first two coordinates + strategy::envelope::detail::envelope_segment_impl < geographic_tag >::template apply(geometry::get<0>(p1_normalized), @@ -72,6 +83,12 @@ public: box, azimuth_geographic); + // now compute the envelope range for coordinates of + // dimension 2 and higher + strategy::envelope::detail::envelope_one_segment + < + 2, dimension::value + >::apply(point1, point2, box); } private: @@ -84,7 +101,7 @@ namespace services { template -struct default_strategy +struct default_strategy { typedef strategy::envelope::geographic_segment < diff --git a/include/boost/geometry/strategies/geographic/expand_segment.hpp b/include/boost/geometry/strategies/geographic/expand_segment.hpp new file mode 100644 index 000000000..66779c109 --- /dev/null +++ b/include/boost/geometry/strategies/geographic/expand_segment.hpp @@ -0,0 +1,102 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// 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. + +// 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 + +// Distributed under 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_EXPAND_SEGMENT_HPP +#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_EXPAND_SEGMENT_HPP + +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = geometry::srs::spheroid, + typename CalculationType = void +> +class geographic_segment +{ +public: + inline geographic_segment() + : m_envelope_strategy() + {} + + explicit inline geographic_segment(Spheroid const& spheroid) + : m_envelope_strategy(spheroid) + {} + + template + inline void apply(Box& box, Segment const& segment) const + { + detail::segment_on_spheroid::apply(box, segment, m_envelope_strategy); + } + +private: + strategy::envelope::geographic_segment + < + FormulaPolicy, Spheroid, CalculationType + > m_envelope_strategy; +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef geographic_segment + < + strategy::andoyer, + geometry::srs::spheroid, + CalculationType + > type; +}; + +} // namespace services + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::expand + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_EXPAND_SEGMENT_HPP diff --git a/include/boost/geometry/strategies/geographic/intersection.hpp b/include/boost/geometry/strategies/geographic/intersection.hpp index b095f8aef..0bfa2f881 100644 --- a/include/boost/geometry/strategies/geographic/intersection.hpp +++ b/include/boost/geometry/strategies/geographic/intersection.hpp @@ -38,10 +38,13 @@ #include #include -#include +#include #include #include #include +#include +#include +#include #include #include #include @@ -141,7 +144,7 @@ struct geographic_segments return strategy_type(m_spheroid); } - typedef envelope::geographic_segment + typedef envelope::geographic envelope_strategy_type; inline envelope_strategy_type get_envelope_strategy() const @@ -149,6 +152,38 @@ struct geographic_segments return envelope_strategy_type(m_spheroid); } + typedef expand::geographic_segment + expand_strategy_type; + + inline expand_strategy_type get_expand_strategy() const + { + return expand_strategy_type(m_spheroid); + } + + typedef within::spherical_point_point point_in_point_strategy_type; + + static inline point_in_point_strategy_type get_point_in_point_strategy() + { + return point_in_point_strategy_type(); + } + + typedef within::spherical_point_point equals_point_point_strategy_type; + + static inline equals_point_point_strategy_type get_equals_point_point_strategy() + { + return equals_point_point_strategy_type(); + } + + typedef disjoint::spherical_box_box disjoint_box_box_strategy_type; + + static inline disjoint_box_box_strategy_type get_disjoint_box_box_strategy() + { + return disjoint_box_box_strategy_type(); + } + + typedef covered_by::spherical_point_box disjoint_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 }; template @@ -285,7 +320,6 @@ private: spheroid_type spheroid = formula::unit_spheroid(m_spheroid); // TODO: check only 2 first coordinates here? - using geometry::detail::equals::equals_point_point; bool a_is_point = equals_point_point(a1, a2); bool b_is_point = equals_point_point(b1, b2); @@ -688,7 +722,6 @@ private: dist_b1_b2 = res_b1_b2.distance; // assign the IP if some endpoints overlap - using geometry::detail::equals::equals_point_point; if (equals_point_point(a1, b1)) { lon = a1_lon; @@ -888,7 +921,6 @@ private: P1 const& ai, P2 const& b1) { static CalcT const c0 = 0; - using geometry::detail::equals::equals_point_point; return is_near(dist) && (math::equals(dist, c0) || equals_point_point(ai, b1)); } @@ -948,6 +980,13 @@ private: ip_flag; } + template + static inline bool equals_point_point(Point1 const& point1, Point2 const& point2) + { + return detail::equals::equals_point_point(point1, point2, + point_in_point_strategy_type()); + } + private: Spheroid m_spheroid; }; diff --git a/include/boost/geometry/strategies/geographic/side.hpp b/include/boost/geometry/strategies/geographic/side.hpp index 1201dc2f6..e22718f32 100644 --- a/include/boost/geometry/strategies/geographic/side.hpp +++ b/include/boost/geometry/strategies/geographic/side.hpp @@ -28,9 +28,10 @@ #include #include -#include +#include #include #include +#include //#include @@ -64,7 +65,7 @@ template class geographic { public: - typedef strategy::envelope::geographic_segment + typedef strategy::envelope::geographic < FormulaPolicy, Spheroid, @@ -88,6 +89,12 @@ public: return disjoint_strategy_type(m_model); } + typedef strategy::within::spherical_point_point equals_point_point_strategy_type; + static inline equals_point_point_strategy_type get_equals_point_point_strategy() + { + return equals_point_point_strategy_type(); + } + geographic() {} diff --git a/include/boost/geometry/strategies/normalize.hpp b/include/boost/geometry/strategies/normalize.hpp new file mode 100644 index 000000000..1887c1e63 --- /dev/null +++ b/include/boost/geometry/strategies/normalize.hpp @@ -0,0 +1,268 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015-2018, 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 + +#ifndef BOOST_GEOMETRY_STRATEGIES_NORMALIZE_HPP +#define BOOST_GEOMETRY_STRATEGIES_NORMALIZE_HPP + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace normalize +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +struct do_nothing +{ + template + static inline void apply(GeometryIn const&, GeometryOut&) + { + } +}; + + +template +struct assign_loop +{ + template + static inline void apply(CoordinateType const& longitude, + CoordinateType const& latitude, + PointIn const& point_in, + PointOut& point_out) + { + geometry::set(point_out, boost::numeric_cast + < + typename coordinate_type::type + >(geometry::get(point_in))); + + assign_loop + < + Dimension + 1, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + +template +struct assign_loop +{ + template + static inline void apply(CoordinateType const&, + CoordinateType const&, + PointIn const&, + PointOut&) + { + } +}; + +template +struct assign_loop<0, DimensionCount> +{ + template + static inline void apply(CoordinateType const& longitude, + CoordinateType const& latitude, + PointIn const& point_in, + PointOut& point_out) + { + geometry::set<0>(point_out, boost::numeric_cast + < + typename coordinate_type::type + >(longitude)); + + assign_loop + < + 1, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + +template +struct assign_loop<1, DimensionCount> +{ + template + static inline void apply(CoordinateType const& longitude, + CoordinateType const& latitude, + PointIn const& point_in, + PointOut& point_out) + { + geometry::set<1>(point_out, boost::numeric_cast + < + typename coordinate_type::type + >(latitude)); + + assign_loop + < + 2, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + + +template +struct normalize_point +{ + static inline void apply(PointIn const& point_in, PointOut& point_out) + { + typedef typename coordinate_type::type in_coordinate_type; + + in_coordinate_type longitude = geometry::get<0>(point_in); + in_coordinate_type latitude = geometry::get<1>(point_in); + + math::normalize_spheroidal_coordinates + < + typename geometry::detail::cs_angular_units::type, + IsEquatorial, + in_coordinate_type + >(longitude, latitude); + + assign_loop + < + 0, dimension::value + >::apply(longitude, latitude, point_in, point_out); + } +}; + + +template +class normalize_box +{ + template + static inline void apply_to_coordinates(CoordinateInType& lon_min, + CoordinateInType& lat_min, + CoordinateInType& lon_max, + CoordinateInType& lat_max, + BoxIn const& box_in, + BoxOut& box_out) + { + geometry::detail::indexed_point_view p_min_out(box_out); + assign_loop + < + 0, dimension::value + >::apply(lon_min, + lat_min, + geometry::detail::indexed_point_view + < + BoxIn const, min_corner + >(box_in), + p_min_out); + + geometry::detail::indexed_point_view p_max_out(box_out); + assign_loop + < + 0, dimension::value + >::apply(lon_max, + lat_max, + geometry::detail::indexed_point_view + < + BoxIn const, max_corner + >(box_in), + p_max_out); + } + +public: + static inline void apply(BoxIn const& box_in, BoxOut& box_out) + { + typedef typename coordinate_type::type in_coordinate_type; + + in_coordinate_type lon_min = geometry::get(box_in); + in_coordinate_type lat_min = geometry::get(box_in); + in_coordinate_type lon_max = geometry::get(box_in); + in_coordinate_type lat_max = geometry::get(box_in); + + math::normalize_spheroidal_box_coordinates + < + typename geometry::detail::cs_angular_units::type, + IsEquatorial, + in_coordinate_type + >(lon_min, lat_min, lon_max, lat_max); + + apply_to_coordinates + < + typename geometry::detail::cs_angular_units::type, + typename geometry::detail::cs_angular_units::type + >(lon_min, lat_min, lon_max, lat_max, box_in, box_out); + } +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +struct cartesian_point + : detail::do_nothing +{}; + +struct cartesian_box + : detail::do_nothing +{}; + +struct spherical_point +{ + template + static inline void apply(PointIn const& point_in, PointOut& point_out) + { + detail::normalize_point + < + PointIn, PointOut, + boost::mpl::not_ + < + boost::is_same + < + typename cs_tag::type, + spherical_polar_tag + > + >::value + >::apply(point_in, point_out); + } +}; + +struct spherical_box +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& box_out) + { + detail::normalize_box + < + BoxIn, BoxOut, + boost::mpl::not_ + < + boost::is_same + < + typename cs_tag::type, + spherical_polar_tag + > + >::value + >::apply(box_in, box_out); + } +}; + +}} // namespace strategy::normalize + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_NORMALIZE_HPP diff --git a/include/boost/geometry/strategies/spherical/disjoint_box_box.hpp b/include/boost/geometry/strategies/spherical/disjoint_box_box.hpp new file mode 100644 index 000000000..f0504a8b1 --- /dev/null +++ b/include/boost/geometry/strategies/spherical/disjoint_box_box.hpp @@ -0,0 +1,134 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2013-2018. +// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_BOX_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_BOX_BOX_HPP + +#include + +#include + +#include +#include + +#include +#include + + +namespace boost { namespace geometry { namespace strategy { namespace disjoint +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +struct box_box_on_spheroid +{ + template + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + typedef typename geometry::select_most_precise + < + typename coordinate_type::type, + typename coordinate_type::type + >::type calc_t; + typedef typename geometry::detail::cs_angular_units::type units_t; + typedef math::detail::constants_on_spheroid constants; + + calc_t const b1_min = get(box1); + calc_t const b1_max = get(box1); + calc_t const b2_min = get(box2); + calc_t const b2_max = get(box2); + + // min <= max <=> diff >= 0 + calc_t const diff1 = b1_max - b1_min; + calc_t const diff2 = b2_max - b2_min; + + // check the intersection if neither box cover the whole globe + if (diff1 < constants::period() && diff2 < constants::period()) + { + // calculate positive longitude translation with b1_min as origin + calc_t const diff_min = math::longitude_distance_unsigned(b1_min, b2_min); + calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min + calc_t b2_max_transl = b2_min_transl - constants::period() + diff2; + + // if the translation is too close then use the original point + // note that math::abs(b2_max_transl - b2_max) takes values very + // close to k*2*constants::period() for k=0,1,2,... + if (math::abs(b2_max_transl - b2_max) < constants::period() / 2) + { + b2_max_transl = b2_max; + } + + if (b2_min_transl > b1_max // b2_min right of b1_max + && b2_max_transl < b1_min) // b2_max left of b1_min + { + return true; + } + } + + return box_box + < + Box1, Box2, 1 + >::apply(box1, box2); + } +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +struct spherical_box_box +{ + template + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + return detail::box_box_on_spheroid::apply(box1, box2); + } +}; + + +namespace services +{ + +template +struct default_strategy +{ + typedef disjoint::spherical_box_box type; +}; + +template +struct default_strategy +{ + typedef disjoint::spherical_box_box type; +}; + +template +struct default_strategy +{ + typedef disjoint::spherical_box_box type; +}; + +} // namespace services + +}}}} // namespace boost::geometry::strategy::disjoint + + +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISJOINT_BOX_BOX_HPP diff --git a/include/boost/geometry/strategies/spherical/disjoint_segment_box.hpp b/include/boost/geometry/strategies/spherical/disjoint_segment_box.hpp index bda62a77f..9c6711dea 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 Oracle and/or its affiliates. +// Copyright (c) 2017-2018 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 @@ -29,8 +29,13 @@ #include #include -#include +// TODO: spherical_point_box currently defined in the same file as cartesian +#include #include +#include +#include +#include + namespace boost { namespace geometry { namespace strategy { namespace disjoint { @@ -67,7 +72,13 @@ struct segment_box_spherical geometry::strategy::azimuth::spherical azimuth_strategy; return geometry::detail::disjoint::disjoint_segment_box_sphere_or_spheroid - ::apply(segment, box, azimuth_strategy); + < + spherical_equatorial_tag + >::apply(segment, box, + azimuth_strategy, + strategy::normalize::spherical_point(), + strategy::covered_by::spherical_point_box(), + strategy::disjoint::spherical_box_box()); } }; diff --git a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp index 97a36b8b2..d9f1ac350 100644 --- a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp @@ -2,11 +2,12 @@ // Copyright (c) 2007-2014 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-2018. +// Modifications copyright (c) 2014-2018, 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 // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -30,6 +31,7 @@ #include #include #include +#include #include #include @@ -326,6 +328,8 @@ template class cross_track { public : + typedef within::spherical_point_point equals_point_point_strategy_type; + template struct return_type : promote_floating_point @@ -505,6 +509,8 @@ template class cross_track { public : + typedef within::spherical_point_point equals_point_point_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 d5647182a..25adbeb46 100644 --- a/include/boost/geometry/strategies/spherical/distance_segment_box.hpp +++ b/include/boost/geometry/strategies/spherical/distance_segment_box.hpp @@ -2,6 +2,7 @@ // Copyright (c) 2018 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -12,6 +13,11 @@ #include +#include +#include +#include +#include // spherical + namespace boost { namespace geometry { @@ -29,7 +35,10 @@ struct generic_segment_box typename BoxPoint, typename SegmentBoxStrategy, typename AzimuthStrategy, - typename EnvelopeSegmentStrategy + typename EnvelopeSegmentStrategy, + typename NormalizePointStrategy, + typename DisjointPointBoxStrategy, + typename DisjointBoxBoxStrategy > static inline ReturnType segment_below_of_box( SegmentPoint const& p0, @@ -39,8 +48,11 @@ struct generic_segment_box BoxPoint const& bottom_left, BoxPoint const& bottom_right, SegmentBoxStrategy const& sb_strategy, - AzimuthStrategy & az_strategy, - EnvelopeSegmentStrategy & es_strategy) + AzimuthStrategy const& az_strategy, + EnvelopeSegmentStrategy const& es_strategy, + NormalizePointStrategy const& np_strategy, + DisjointPointBoxStrategy const& dpb_strategy, + DisjointBoxBoxStrategy const& dbb_strategy) { ReturnType result; typename LessEqual::other less_equal; @@ -66,7 +78,8 @@ struct generic_segment_box SegmentPoint p_max; disjoint_info_type disjoint_result = disjoint_sb:: - apply(seg, input_box, az_strategy, p_max); + apply(seg, input_box, p_max, + az_strategy, np_strategy, dpb_strategy, dbb_strategy); if (disjoint_result == disjoint_info_type::intersect) //intersect { @@ -222,7 +235,10 @@ struct spherical_segment_box ReturnType >(p0,p1,top_left,top_right,bottom_left,bottom_right, spherical_segment_box(), - az_strategy, es_strategy); + az_strategy, es_strategy, + normalize::spherical_point(), + covered_by::spherical_point_box(), + disjoint::spherical_box_box()); } template diff --git a/include/boost/geometry/strategies/spherical/envelope.hpp b/include/boost/geometry/strategies/spherical/envelope.hpp new file mode 100644 index 000000000..4353f0180 --- /dev/null +++ b/include/boost/geometry/strategies/spherical/envelope.hpp @@ -0,0 +1,146 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015, 2016, 2018. +// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under 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_ENVELOPE_HPP +#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_HPP + +#include +#include + +#include + +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace envelope +{ + +template +class spherical +{ +public: + typedef spherical_segment element_envelope_strategy_type; + static inline element_envelope_strategy_type get_element_envelope_strategy() + { + return element_envelope_strategy_type(); + } + + typedef expand::spherical_segment element_expand_strategy_type; + static inline element_expand_strategy_type get_element_expand_strategy() + { + return element_expand_strategy_type(); + } + + typedef strategy::expand::spherical_box box_expand_strategy_type; + static inline box_expand_strategy_type get_box_expand_strategy() + { + return box_expand_strategy_type(); + } + + // Linestring, Ring, Polygon + + template + static inline geometry::segment_iterator begin(Range const& range) + { + return geometry::segments_begin(range); + } + + template + static inline geometry::segment_iterator end(Range const& range) + { + return geometry::segments_end(range); + } + + // MultiLinestring, MultiPolygon + + template + struct multi_state + { + void apply(Box const& single_box) + { + m_boxes.push_back(single_box); + } + + void result(Box & box) + { + if (!m_boxes.empty()) + { + geometry::detail::envelope::envelope_range_of_boxes::apply(m_boxes, box); + } + else + { + geometry::detail::envelope::initialize::value>::apply(box); + } + } + + private: + std::vector m_boxes; + }; + + // Segment + + template + static inline void apply(Point1 const& point1, Point2 const& point2, + Box& box) + { + spherical_segment::apply(point1, point2, box); + } + + // Box + + template + static inline void apply(BoxIn const& box_in, Box& box) + { + spherical_box::apply(box_in, box); + } +}; + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef strategy::envelope::spherical type; +}; + +template +struct default_strategy +{ + typedef strategy::envelope::spherical type; +}; + +} + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + +}} //namepsace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_HPP diff --git a/include/boost/geometry/strategies/spherical/envelope_box.hpp b/include/boost/geometry/strategies/spherical/envelope_box.hpp new file mode 100644 index 000000000..0a9436d12 --- /dev/null +++ b/include/boost/geometry/strategies/spherical/envelope_box.hpp @@ -0,0 +1,145 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015-2018. +// Modifications copyright (c) 2015-2018, 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 + +// Distributed under 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_ENVELOPE_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_BOX_HPP + +#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); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +namespace strategy { namespace envelope +{ + + +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)) + { + 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); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef strategy::envelope::spherical_box type; +}; + +template +struct default_strategy +{ + typedef strategy::envelope::spherical_box type; +}; + +template +struct default_strategy +{ + typedef strategy::envelope::spherical_box type; +}; + +} + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_BOX_HPP diff --git a/include/boost/geometry/strategies/spherical/envelope_multipoint.hpp b/include/boost/geometry/strategies/spherical/envelope_multipoint.hpp new file mode 100644 index 000000000..e7817370f --- /dev/null +++ b/include/boost/geometry/strategies/spherical/envelope_multipoint.hpp @@ -0,0 +1,379 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015-2018, 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 + +// Distributed under 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_ENVELOPE_MULTIPOINT_HPP +#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_MULTIPOINT_HPP + +#include +#include +#include +#include + +#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 envelope +{ + +class spherical_multipoint +{ +private: + template + struct coordinate_less + { + template + inline bool operator()(Point const& point1, Point const& point2) const + { + return math::smaller(geometry::get(point1), + geometry::get(point2)); + } + }; + + template + static inline void analyze_point_coordinates(MultiPoint const& multipoint, + bool& has_south_pole, + bool& has_north_pole, + OutputIterator oit) + { + typedef typename boost::range_value::type point_type; + typedef typename boost::range_iterator + < + MultiPoint const + >::type iterator_type; + + // analyze point coordinates: + // (1) normalize point coordinates + // (2) check if any point is the north or the south pole + // (3) put all non-pole points in a container + // + // notice that at this point in the algorithm, we have at + // least two points on the spheroid + has_south_pole = false; + has_north_pole = false; + + for (iterator_type it = boost::begin(multipoint); + it != boost::end(multipoint); + ++it) + { + point_type point; + normalize::spherical_point::apply(*it, point); + + if (math::equals(geometry::get<1>(point), + Constants::min_latitude())) + { + has_south_pole = true; + } + else if (math::equals(geometry::get<1>(point), + Constants::max_latitude())) + { + has_north_pole = true; + } + else + { + *oit++ = point; + } + } + } + + template + static inline Value maximum_gap(SortedRange const& sorted_range, + Value& max_gap_left, + Value& max_gap_right) + { + typedef typename boost::range_iterator + < + SortedRange const + >::type iterator_type; + + iterator_type it1 = boost::begin(sorted_range), it2 = it1; + ++it2; + max_gap_left = geometry::get<0>(*it1); + max_gap_right = geometry::get<0>(*it2); + + Value max_gap = max_gap_right - max_gap_left; + for (++it1, ++it2; it2 != boost::end(sorted_range); ++it1, ++it2) + { + Value gap = geometry::get<0>(*it2) - geometry::get<0>(*it1); + if (math::larger(gap, max_gap)) + { + max_gap_left = geometry::get<0>(*it1); + max_gap_right = geometry::get<0>(*it2); + max_gap = gap; + } + } + + return max_gap; + } + + template + < + typename Constants, + typename PointRange, + typename LongitudeLess, + typename CoordinateType + > + static inline void get_min_max_longitudes(PointRange& range, + LongitudeLess const& lon_less, + CoordinateType& lon_min, + CoordinateType& lon_max) + { + typedef typename boost::range_iterator + < + PointRange const + >::type iterator_type; + + // compute min and max longitude values + std::pair min_max_longitudes + = boost::minmax_element(boost::begin(range), + boost::end(range), + lon_less); + + lon_min = geometry::get<0>(*min_max_longitudes.first); + lon_max = geometry::get<0>(*min_max_longitudes.second); + + // if the longitude span is "large" compute the true maximum gap + if (math::larger(lon_max - lon_min, Constants::half_period())) + { + std::sort(boost::begin(range), boost::end(range), lon_less); + + CoordinateType max_gap_left = 0, max_gap_right = 0; + CoordinateType max_gap + = maximum_gap(range, max_gap_left, max_gap_right); + + CoordinateType complement_gap + = Constants::period() + lon_min - lon_max; + + if (math::larger(max_gap, complement_gap)) + { + lon_min = max_gap_right; + lon_max = max_gap_left + Constants::period(); + } + } + } + + template + < + typename Constants, + typename Iterator, + typename LatitudeLess, + typename CoordinateType + > + static inline void get_min_max_latitudes(Iterator const first, + Iterator const last, + LatitudeLess const& lat_less, + bool has_south_pole, + bool has_north_pole, + CoordinateType& lat_min, + CoordinateType& lat_max) + { + if (has_south_pole && has_north_pole) + { + lat_min = Constants::min_latitude(); + lat_max = Constants::max_latitude(); + } + else if (has_south_pole) + { + lat_min = Constants::min_latitude(); + lat_max + = geometry::get<1>(*std::max_element(first, last, lat_less)); + } + else if (has_north_pole) + { + lat_min + = geometry::get<1>(*std::min_element(first, last, lat_less)); + lat_max = Constants::max_latitude(); + } + else + { + std::pair min_max_latitudes + = boost::minmax_element(first, last, lat_less); + + lat_min = geometry::get<1>(*min_max_latitudes.first); + lat_max = geometry::get<1>(*min_max_latitudes.second); + } + } + +public: + template + static inline void apply(MultiPoint const& multipoint, Box& mbr) + { + typedef typename point_type::type point_type; + typedef typename coordinate_type::type coordinate_type; + typedef typename boost::range_iterator + < + MultiPoint const + >::type iterator_type; + + typedef math::detail::constants_on_spheroid + < + coordinate_type, + typename geometry::detail::cs_angular_units::type + > constants; + + if (boost::empty(multipoint)) + { + geometry::detail::envelope::initialize::value>::apply(mbr); + return; + } + + geometry::detail::envelope::initialize::apply(mbr); + + if (boost::size(multipoint) == 1) + { + return dispatch::envelope + < + typename boost::range_value::type + >::apply(range::front(multipoint), mbr, strategy::envelope::spherical_point()); + } + + // analyze the points and put the non-pole ones in the + // points vector + std::vector points; + bool has_north_pole = false, has_south_pole = false; + + analyze_point_coordinates(multipoint, + has_south_pole, has_north_pole, + std::back_inserter(points)); + + coordinate_type lon_min, lat_min, lon_max, lat_max; + if (points.size() == 1) + { + // we have one non-pole point and at least one pole point + lon_min = geometry::get<0>(range::front(points)); + lon_max = geometry::get<0>(range::front(points)); + lat_min = has_south_pole + ? constants::min_latitude() + : constants::max_latitude(); + lat_max = has_north_pole + ? constants::max_latitude() + : constants::min_latitude(); + } + else if (points.empty()) + { + // all points are pole points + BOOST_GEOMETRY_ASSERT(has_south_pole || has_north_pole); + lon_min = coordinate_type(0); + lon_max = coordinate_type(0); + lat_min = has_south_pole + ? constants::min_latitude() + : constants::max_latitude(); + lat_max = (has_north_pole) + ? constants::max_latitude() + : constants::min_latitude(); + } + else + { + get_min_max_longitudes(points, + coordinate_less<0>(), + lon_min, + lon_max); + + get_min_max_latitudes(points.begin(), + points.end(), + coordinate_less<1>(), + has_south_pole, + has_north_pole, + lat_min, + lat_max); + } + + typedef typename helper_geometry + < + Box, + coordinate_type, + typename geometry::detail::cs_angular_units::type + >::type helper_box_type; + + helper_box_type helper_mbr; + + geometry::set(helper_mbr, lon_min); + geometry::set(helper_mbr, lat_min); + geometry::set(helper_mbr, lon_max); + geometry::set(helper_mbr, lat_max); + + // now transform to output MBR (per index) + geometry::detail::envelope::envelope_indexed_box_on_spheroid::apply(helper_mbr, mbr); + geometry::detail::envelope::envelope_indexed_box_on_spheroid::apply(helper_mbr, mbr); + + // compute envelope for higher coordinates + iterator_type it = boost::begin(multipoint); + geometry::detail::envelope::envelope_one_point<2, dimension::value>::apply(*it, mbr); + + for (++it; it != boost::end(multipoint); ++it) + { + strategy::expand::detail::point_loop + < + 2, dimension::value + >::apply(mbr, *it); + } + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef strategy::envelope::spherical_multipoint type; +}; + +template +struct default_strategy +{ + typedef strategy::envelope::spherical_multipoint type; +}; + +template +struct default_strategy +{ + typedef strategy::envelope::spherical_multipoint type; +}; + +} // namespace services + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_MULTIPOINT_HPP diff --git a/include/boost/geometry/strategies/spherical/envelope_point.hpp b/include/boost/geometry/strategies/spherical/envelope_point.hpp new file mode 100644 index 000000000..8302d7e56 --- /dev/null +++ b/include/boost/geometry/strategies/spherical/envelope_point.hpp @@ -0,0 +1,111 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015, 2016, 2017, 2018. +// Modifications copyright (c) 2015-2018, 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 + +// Distributed under 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_ENVELOPE_POINT_HPP +#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_POINT_HPP + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace envelope +{ + +struct spherical_point +{ + template + static inline void apply(Point const& point, Box& mbr) + { + Point normalized_point; + strategy::normalize::spherical_point::apply(point, normalized_point); + + typename point_type::type box_point; + + // transform units of input point to units of a box point + geometry::detail::envelope::transform_units(normalized_point, box_point); + + geometry::set(mbr, geometry::get<0>(box_point)); + geometry::set(mbr, geometry::get<1>(box_point)); + + geometry::set(mbr, geometry::get<0>(box_point)); + geometry::set(mbr, geometry::get<1>(box_point)); + + typedef geometry::detail::envelope::envelope_one_point + < + 2, dimension::value + > per_corner; + per_corner::template apply(normalized_point, mbr); + per_corner::template apply(normalized_point, mbr); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef strategy::envelope::spherical_point type; +}; + +template +struct default_strategy +{ + typedef strategy::envelope::spherical_point type; +}; + +template +struct default_strategy +{ + typedef strategy::envelope::spherical_point type; +}; + + +} + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_POINT_HPP diff --git a/include/boost/geometry/strategies/spherical/envelope_segment.hpp b/include/boost/geometry/strategies/spherical/envelope_segment.hpp index 98f085fe7..a35922271 100644 --- a/include/boost/geometry/strategies/spherical/envelope_segment.hpp +++ b/include/boost/geometry/strategies/spherical/envelope_segment.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2017 Oracle and/or its affiliates. +// Copyright (c) 2017-2018 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -11,47 +11,451 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_SEGMENT_HPP #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_SEGMENT_HPP -#include -#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include #include +#include #include +#include -namespace boost { namespace geometry +#include + +namespace boost { namespace geometry { namespace strategy { namespace envelope { -namespace strategy { namespace envelope +#ifndef DOXYGEN_NO_DETAIL +namespace detail { +template +struct envelope_segment_call_vertex_latitude +{ + template + static inline CalculationType apply(T1 const& lat1, + T2 const& alp1, + Strategy const& ) + { + return geometry::formula::vertex_latitude + ::apply(lat1, alp1); + } +}; + +template +struct envelope_segment_call_vertex_latitude +{ + template + static inline CalculationType apply(T1 const& lat1, + T2 const& alp1, + Strategy const& strategy) + { + return geometry::formula::vertex_latitude + ::apply(lat1, alp1, strategy.model()); + } +}; + +template +struct envelope_segment_convert_polar +{ + template + static inline void pre(T & , T & ) {} + + template + static inline void post(T & , T & ) {} +}; + +template +struct envelope_segment_convert_polar +{ + template + static inline void pre(T & lat1, T & lat2) + { + lat1 = math::latitude_convert_ep(lat1); + lat2 = math::latitude_convert_ep(lat2); + } + + template + static inline void post(T & lat1, T & lat2) + { + lat1 = math::latitude_convert_ep(lat1); + lat2 = math::latitude_convert_ep(lat2); + std::swap(lat1, lat2); + } +}; + +template +class envelope_segment_impl +{ +private: + + // degrees or radians + template + static inline void swap(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2) + { + std::swap(lon1, lon2); + std::swap(lat1, lat2); + } + + // radians + template + static inline bool contains_pi_half(CalculationType const& a1, + CalculationType const& a2) + { + // azimuths a1 and a2 are assumed to be in radians + BOOST_GEOMETRY_ASSERT(! math::equals(a1, a2)); + + static CalculationType const pi_half = math::half_pi(); + + return (a1 < a2) + ? (a1 < pi_half && pi_half < a2) + : (a1 > pi_half && pi_half > a2); + } + + // radians or degrees + template + static inline bool crosses_antimeridian(CoordinateType const& lon1, + CoordinateType const& lon2) + { + typedef math::detail::constants_on_spheroid + < + CoordinateType, Units + > constants; + + return math::abs(lon1 - lon2) > constants::half_period(); // > pi + } + + // degrees or radians + template + static inline void compute_box_corners(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2, + CalculationType a1, + CalculationType a2, + Strategy const& strategy) + { + // coordinates are assumed to be in radians + BOOST_GEOMETRY_ASSERT(lon1 <= lon2); + boost::ignore_unused(lon1, lon2); + + CalculationType lat1_rad = math::as_radian(lat1); + CalculationType lat2_rad = math::as_radian(lat2); + + if (math::equals(a1, a2)) + { + // the segment must lie on the equator or is very short or is meridian + return; + } + + if (lat1 > lat2) + { + std::swap(lat1, lat2); + std::swap(lat1_rad, lat2_rad); + std::swap(a1, a2); + } + + if (contains_pi_half(a1, a2)) + { + CalculationType p_max = envelope_segment_call_vertex_latitude + ::apply(lat1_rad, a1, strategy); + + CalculationType const mid_lat = lat1 + lat2; + if (mid_lat < 0) + { + // update using min latitude + CalculationType const lat_min_rad = -p_max; + CalculationType const lat_min + = math::from_radian(lat_min_rad); + + if (lat1 > lat_min) + { + lat1 = lat_min; + } + } + else + { + // update using max latitude + CalculationType const lat_max_rad = p_max; + CalculationType const lat_max + = math::from_radian(lat_max_rad); + + if (lat2 < lat_max) + { + lat2 = lat_max; + } + } + } + } + + template + static inline void special_cases(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2) + { + typedef math::detail::constants_on_spheroid + < + CalculationType, Units + > constants; + + bool is_pole1 = math::equals(math::abs(lat1), constants::max_latitude()); + bool is_pole2 = math::equals(math::abs(lat2), constants::max_latitude()); + + if (is_pole1 && is_pole2) + { + // both points are poles; nothing more to do: + // longitudes are already normalized to 0 + // but just in case + lon1 = 0; + lon2 = 0; + } + else if (is_pole1 && !is_pole2) + { + // first point is a pole, second point is not: + // make the longitude of the first point the same as that + // of the second point + lon1 = lon2; + } + else if (!is_pole1 && is_pole2) + { + // second point is a pole, first point is not: + // make the longitude of the second point the same as that + // of the first point + lon2 = lon1; + } + + if (lon1 == lon2) + { + // segment lies on a meridian + if (lat1 > lat2) + { + std::swap(lat1, lat2); + } + return; + } + + BOOST_GEOMETRY_ASSERT(!is_pole1 && !is_pole2); + + if (lon1 > lon2) + { + swap(lon1, lat1, lon2, lat2); + } + + if (crosses_antimeridian(lon1, lon2)) + { + lon1 += constants::period(); + swap(lon1, lat1, lon2, lat2); + } + } + + template + < + typename Units, + typename CalculationType, + typename Box + > + static inline void create_box(CalculationType lon1, + CalculationType lat1, + CalculationType lon2, + CalculationType lat2, + Box& mbr) + { + typedef typename coordinate_type::type box_coordinate_type; + + typedef typename helper_geometry + < + Box, box_coordinate_type, Units + >::type helper_box_type; + + helper_box_type helper_mbr; + + geometry::set + < + min_corner, 0 + >(helper_mbr, boost::numeric_cast(lon1)); + + geometry::set + < + min_corner, 1 + >(helper_mbr, boost::numeric_cast(lat1)); + + geometry::set + < + max_corner, 0 + >(helper_mbr, boost::numeric_cast(lon2)); + + geometry::set + < + max_corner, 1 + >(helper_mbr, boost::numeric_cast(lat2)); + + geometry::detail::envelope::transform_units(helper_mbr, mbr); + } + + + template + static inline void apply(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2, + Strategy const& strategy) + { + special_cases(lon1, lat1, lon2, lat2); + + CalculationType lon1_rad = math::as_radian(lon1); + CalculationType lat1_rad = math::as_radian(lat1); + CalculationType lon2_rad = math::as_radian(lon2); + CalculationType lat2_rad = math::as_radian(lat2); + CalculationType alp1, alp2; + strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, alp1, alp2); + + compute_box_corners(lon1, lat1, lon2, lat2, alp1, alp2, strategy); + } + + template + static inline void apply(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2, + Strategy const& strategy, + CalculationType alp1) + { + special_cases(lon1, lat1, lon2, lat2); + + CalculationType lon1_rad = math::as_radian(lon1); + CalculationType lat1_rad = math::as_radian(lat1); + CalculationType lon2_rad = math::as_radian(lon2); + CalculationType lat2_rad = math::as_radian(lat2); + CalculationType alp2; + strategy.apply_reverse(lon1_rad, lat1_rad, lon2_rad, lat2_rad, alp2); + + compute_box_corners(lon1, lat1, lon2, lat2, alp1, alp2, strategy); + } + +public: + template + < + typename Units, + typename CalculationType, + typename Box, + typename Strategy + > + static inline void apply(CalculationType lon1, + CalculationType lat1, + CalculationType lon2, + CalculationType lat2, + Box& mbr, + Strategy const& strategy) + { + typedef envelope_segment_convert_polar::type> convert_polar; + + convert_polar::pre(lat1, lat2); + + apply(lon1, lat1, lon2, lat2, strategy); + + convert_polar::post(lat1, lat2); + + create_box(lon1, lat1, lon2, lat2, mbr); + } + + template + < + typename Units, + typename CalculationType, + typename Box, + typename Strategy + > + static inline void apply(CalculationType lon1, + CalculationType lat1, + CalculationType lon2, + CalculationType lat2, + Box& mbr, + Strategy const& strategy, + CalculationType alp1) + { + typedef envelope_segment_convert_polar::type> convert_polar; + + convert_polar::pre(lat1, lat2); + + apply(lon1, lat1, lon2, lat2, strategy, alp1); + + convert_polar::post(lat1, lat2); + + create_box(lon1, lat1, lon2, lat2, mbr); + } +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + template < typename CalculationType = void > class spherical_segment { -public : - - inline spherical_segment() - {} - - template - inline void - apply(Point1 const& point1, Point2 const& point2, Box& box) const +public: + typedef strategy::expand::spherical_box box_expand_strategy_type; + static inline box_expand_strategy_type get_box_expand_strategy() { - Point1 p1_normalized = detail::return_normalized(point1); - Point2 p2_normalized = detail::return_normalized(point2); + return box_expand_strategy_type(); + } + + template + static inline void apply(Point const& point1, Point const& point2, + Box& box) + { + Point p1_normalized, p2_normalized; + strategy::normalize::spherical_point::apply(point1, p1_normalized); + strategy::normalize::spherical_point::apply(point2, p2_normalized); geometry::strategy::azimuth::spherical azimuth_spherical; - typedef typename coordinate_system::type::units units_type; + typedef typename geometry::detail::cs_angular_units::type units_type; - geometry::detail::envelope::envelope_segment_impl - ::template apply(geometry::get<0>(p1_normalized), - geometry::get<1>(p1_normalized), - geometry::get<0>(p2_normalized), - geometry::get<1>(p2_normalized), - box, - azimuth_spherical); + // first compute the envelope range for the first two coordinates + strategy::envelope::detail::envelope_segment_impl + < + spherical_equatorial_tag + >::template apply(geometry::get<0>(p1_normalized), + geometry::get<1>(p1_normalized), + geometry::get<0>(p2_normalized), + geometry::get<1>(p2_normalized), + box, + azimuth_spherical); + // now compute the envelope range for coordinates of + // dimension 2 and higher + strategy::envelope::detail::envelope_one_segment + < + 2, dimension::value + >::apply(point1, point2, box); } }; @@ -61,14 +465,14 @@ namespace services { template -struct default_strategy +struct default_strategy { typedef strategy::envelope::spherical_segment type; }; template -struct default_strategy +struct default_strategy { typedef strategy::envelope::spherical_segment type; }; diff --git a/include/boost/geometry/strategies/spherical/expand_box.hpp b/include/boost/geometry/strategies/spherical/expand_box.hpp new file mode 100644 index 000000000..e3801861b --- /dev/null +++ b/include/boost/geometry/strategies/spherical/expand_box.hpp @@ -0,0 +1,98 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// 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. + +// 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 + +// Distributed under 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_EXPAND_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_BOX_HPP + +#include +#include + +#include +#include + +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +struct box_on_spheroid +{ + template + static inline void apply(BoxOut& box_out, BoxIn const& box_in) + { + // 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]); + + // compute the envelope of the two boxes + geometry::detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out); + } +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +struct spherical_box + : detail::box_on_spheroid +{}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef spherical_box type; +}; + +template +struct default_strategy +{ + typedef spherical_box type; +}; + +template +struct default_strategy +{ + typedef spherical_box type; +}; + +} // namespace services + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::expand + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_BOX_HPP diff --git a/include/boost/geometry/strategies/spherical/expand_point.hpp b/include/boost/geometry/strategies/spherical/expand_point.hpp new file mode 100644 index 000000000..b2cff013a --- /dev/null +++ b/include/boost/geometry/strategies/spherical/expand_point.hpp @@ -0,0 +1,233 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015-2018. +// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under 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_EXPAND_POINT_HPP +#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_POINT_HPP + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +// implementation for the spherical and geographic coordinate systems +template +struct point_loop_on_spheroid +{ + template + static inline void apply(Box& box, Point const& point) + { + typedef typename point_type::type box_point_type; + typedef typename coordinate_type::type box_coordinate_type; + typedef typename geometry::detail::cs_angular_units::type units_type; + + typedef math::detail::constants_on_spheroid + < + box_coordinate_type, + units_type + > constants; + + // normalize input point and input box + Point p_normalized; + strategy::normalize::spherical_point::apply(point, p_normalized); + + // transform input point to be of the same type as the box point + box_point_type box_point; + geometry::detail::envelope::transform_units(p_normalized, box_point); + + if (is_inverse_spheroidal_coordinates(box)) + { + geometry::set_from_radian(box, geometry::get_as_radian<0>(p_normalized)); + geometry::set_from_radian(box, geometry::get_as_radian<1>(p_normalized)); + geometry::set_from_radian(box, geometry::get_as_radian<0>(p_normalized)); + geometry::set_from_radian(box, geometry::get_as_radian<1>(p_normalized)); + + } else { + + strategy::normalize::spherical_box::apply(box, box); + + box_coordinate_type p_lon = geometry::get<0>(box_point); + box_coordinate_type p_lat = geometry::get<1>(box_point); + + typename coordinate_type::type + b_lon_min = geometry::get(box), + b_lat_min = geometry::get(box), + b_lon_max = geometry::get(box), + b_lat_max = geometry::get(box); + + if (math::is_latitude_pole(p_lat)) + { + // the point of expansion is the either the north or the + // south pole; the only important coordinate here is the + // pole's latitude, as the longitude can be anything; + // we, thus, take into account the point's latitude only and return + geometry::set(box, (std::min)(p_lat, b_lat_min)); + geometry::set(box, (std::max)(p_lat, b_lat_max)); + return; + } + + if (math::equals(b_lat_min, b_lat_max) + && math::is_latitude_pole(b_lat_min)) + { + // the box degenerates to either the north or the south pole; + // the only important coordinate here is the pole's latitude, + // as the longitude can be anything; + // we thus take into account the box's latitude only and return + geometry::set(box, p_lon); + geometry::set(box, (std::min)(p_lat, b_lat_min)); + geometry::set(box, p_lon); + geometry::set(box, (std::max)(p_lat, b_lat_max)); + return; + } + + // update latitudes + b_lat_min = (std::min)(b_lat_min, p_lat); + b_lat_max = (std::max)(b_lat_max, p_lat); + + // update longitudes + if (math::smaller(p_lon, b_lon_min)) + { + box_coordinate_type p_lon_shifted = p_lon + constants::period(); + + if (math::larger(p_lon_shifted, b_lon_max)) + { + // here we could check using: ! math::larger(.., ..) + if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max)) + { + b_lon_min = p_lon; + } + else + { + b_lon_max = p_lon_shifted; + } + } + } + else if (math::larger(p_lon, b_lon_max)) + { + // in this case, and since p_lon is normalized in the range + // (-180, 180], we must have that b_lon_max <= 180 + if (b_lon_min < 0 + && math::larger(p_lon - b_lon_max, + constants::period() - p_lon + b_lon_min)) + { + b_lon_min = p_lon; + b_lon_max += constants::period(); + } + else + { + b_lon_max = p_lon; + } + } + + geometry::set(box, b_lon_min); + geometry::set(box, b_lat_min); + geometry::set(box, b_lon_max); + geometry::set(box, b_lat_max); + } + + point_loop + < + 2, DimensionCount + >::apply(box, point); + } +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +struct spherical_point +{ + template + static void apply(Box & box, Point const& point) + { + expand::detail::point_loop_on_spheroid + < + dimension::value, + ! boost::is_same::type, spherical_polar_tag>::value + >::apply(box, point); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef spherical_point type; +}; + +template +struct default_strategy +{ + typedef spherical_point type; +}; + +template +struct default_strategy +{ + typedef spherical_point type; +}; + + +} // namespace services + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::expand + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_POINT_HPP diff --git a/include/boost/geometry/strategies/spherical/expand_segment.hpp b/include/boost/geometry/strategies/spherical/expand_segment.hpp new file mode 100644 index 000000000..75f4698ff --- /dev/null +++ b/include/boost/geometry/strategies/spherical/expand_segment.hpp @@ -0,0 +1,118 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// 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. + +// 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 + +// Distributed under 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_EXPAND_SEGMENT_HPP +#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_SEGMENT_HPP + +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +struct segment_on_spheroid +{ + template + static inline void apply(Box& box, Segment const& segment, EnvelopeStrategy const& strategy) + { + Box mbrs[2]; + + // compute the envelope of the segment + typename point_type::type p[2]; + geometry::detail::assign_point_from_index<0>(segment, p[0]); + geometry::detail::assign_point_from_index<1>(segment, p[1]); + geometry::detail::envelope::envelope_segment + < + dimension::value + >::apply(p[0], p[1], mbrs[0], strategy); + + // normalize the box + strategy::envelope::spherical_box::apply(box, mbrs[1]); + + // compute the envelope of the two boxes + geometry::detail::envelope::envelope_range_of_boxes::apply(mbrs, box); + } +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +template +< + typename CalculationType = void +> +class spherical_segment +{ +public: + template + static inline void apply(Box& box, Segment const& segment) + { + detail::segment_on_spheroid::apply(box, segment, + strategy::envelope::spherical_segment()); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template +struct default_strategy +{ + typedef spherical_segment type; +}; + +template +struct default_strategy +{ + typedef spherical_segment type; +}; + +} // namespace services + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::expand + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_EXPAND_SEGMENT_HPP diff --git a/include/boost/geometry/strategies/spherical/intersection.hpp b/include/boost/geometry/strategies/spherical/intersection.hpp index 2bdc8b51a..9142009fe 100644 --- a/include/boost/geometry/strategies/spherical/intersection.hpp +++ b/include/boost/geometry/strategies/spherical/intersection.hpp @@ -41,8 +41,11 @@ #include #include #include +#include #include -#include +#include +#include +#include #include #include #include @@ -149,7 +152,7 @@ struct ecef_segments return strategy_type(); } - typedef envelope::spherical_segment + typedef envelope::spherical envelope_strategy_type; static inline envelope_strategy_type get_envelope_strategy() @@ -157,6 +160,38 @@ struct ecef_segments return envelope_strategy_type(); } + typedef expand::spherical_segment + expand_strategy_type; + + static inline expand_strategy_type get_expand_strategy() + { + return expand_strategy_type(); + } + + typedef within::spherical_point_point point_in_point_strategy_type; + + static inline point_in_point_strategy_type get_point_in_point_strategy() + { + return point_in_point_strategy_type(); + } + + typedef within::spherical_point_point equals_point_point_strategy_type; + + static inline equals_point_point_strategy_type get_equals_point_point_strategy() + { + return equals_point_point_strategy_type(); + } + + typedef disjoint::spherical_box_box disjoint_box_box_strategy_type; + + static inline disjoint_box_box_strategy_type get_disjoint_box_box_strategy() + { + return disjoint_box_box_strategy_type(); + } + + typedef covered_by::spherical_point_box disjoint_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 }; // segment_intersection_info cannot outlive relate_ecef_segments @@ -252,7 +287,6 @@ struct ecef_segments BOOST_CONCEPT_ASSERT( (concepts::ConstSegment) ); // TODO: check only 2 first coordinates here? - using geometry::detail::equals::equals_point_point; bool a_is_point = equals_point_point(a1, a2); bool b_is_point = equals_point_point(b1, b2); @@ -645,7 +679,6 @@ private: } // reassign the IP if some endpoints overlap - using geometry::detail::equals::equals_point_point; if (is_near_a1) { if (is_near_b1 && equals_point_point(a1, b1)) @@ -822,7 +855,6 @@ private: P1 const& ai, P2 const& b1) { static CalcT const c0 = 0; - using geometry::detail::equals::equals_point_point; return is_near(dist) && (math::equals(dist, c0) || equals_point_point(ai, b1)); } @@ -850,6 +882,13 @@ private: : ca1 < cb2 ? 4 : 2 ); } + + template + static inline bool equals_point_point(Point1 const& point1, Point2 const& point2) + { + return detail::equals::equals_point_point(point1, point2, + point_in_point_strategy_type()); + } }; struct spherical_segments_calc_policy @@ -921,7 +960,7 @@ struct spherical_segments_calc_policy multiply_value(ip2, coord_t(-1)); return true; - } + } }; diff --git a/include/boost/geometry/strategies/spherical/point_in_point.hpp b/include/boost/geometry/strategies/spherical/point_in_point.hpp new file mode 100644 index 000000000..372e9cfac --- /dev/null +++ b/include/boost/geometry/strategies/spherical/point_in_point.hpp @@ -0,0 +1,172 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// 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. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_POINT_IN_POINT_HPP +#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_POINT_IN_POINT_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 within +{ + +class point_point_on_spheroid +{ +private: + template + struct are_same_points + { + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + typedef typename helper_geometry::type helper_point_type1; + typedef typename helper_geometry::type helper_point_type2; + + helper_point_type1 point1_normalized; + strategy::normalize::spherical_point::apply(point1, point1_normalized); + helper_point_type2 point2_normalized; + strategy::normalize::spherical_point::apply(point2, point2_normalized); + + return point_point_generic + < + 0, dimension::value + >::apply(point1_normalized, point2_normalized); + } + }; + + template + struct are_same_points // points have different units + { + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + typedef typename geometry::select_most_precise + < + typename fp_coordinate_type::type, + typename fp_coordinate_type::type + >::type calculation_type; + + typename helper_geometry + < + Point1, calculation_type, radian + >::type helper_point1, helper_point2; + + Point1 point1_normalized = return_normalized(point1); + Point2 point2_normalized = return_normalized(point2); + + geometry::transform(point1_normalized, helper_point1); + geometry::transform(point2_normalized, helper_point2); + + return point_point_generic + < + 0, dimension::value + >::apply(helper_point1, helper_point2); + } + }; + +public: + template + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + return are_same_points + < + Point1, + Point2, + boost::is_same + < + typename detail::cs_angular_units::type, + typename detail::cs_angular_units::type + >::value + >::apply(point1, point2); + } +}; + +}} // namespace detail::within +#endif // DOXYGEN_NO_DETAIL + + +namespace strategy { namespace within +{ + +struct spherical_point_point + : geometry::detail::within::point_point_on_spheroid +{}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template +struct default_strategy +{ + typedef strategy::within::spherical_point_point type; +}; + +} // namespace services +#endif + + +}} // namespace strategy::within + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace strategy { namespace covered_by { namespace services +{ + +template +struct default_strategy +{ + typedef strategy::within::spherical_point_point type; +}; + +}}} // namespace strategy::covered_by::services +#endif + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_POINT_IN_POINT_HPP diff --git a/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp b/include/boost/geometry/strategies/spherical/point_in_poly_winding.hpp index c942cbe46..c283b5333 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. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018. +// Modifications copyright (c) 2013-2018 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 @@ -27,8 +27,10 @@ #include #include +#include #include #include +#include #include #include @@ -63,7 +65,7 @@ class spherical_winding_base CalculationType >::type calculation_type; - 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; /*! subclass to keep state */ @@ -140,6 +142,20 @@ public: return m_side_strategy.get_disjoint_strategy(); } + typedef typename SideStrategy::equals_point_point_strategy_type equals_point_point_strategy_type; + inline equals_point_point_strategy_type get_equals_point_point_strategy() const + { + return m_side_strategy.get_equals_point_point_strategy(); + } + + typedef disjoint::spherical_box_box disjoint_box_box_strategy_type; + static inline disjoint_box_box_strategy_type get_disjoint_box_box_strategy() + { + return disjoint_box_box_strategy_type(); + } + + typedef covered_by::spherical_point_box disjoint_point_box_strategy_type; + spherical_winding_base() {} @@ -434,7 +450,7 @@ private: count_info const& ci) const { typedef typename coordinate_type::type scoord_t; - typedef typename coordinate_system::type::units units_t; + typedef typename geometry::detail::cs_angular_units::type units_t; if (math::equals(get<1>(point), get<1>(se))) { diff --git a/include/boost/geometry/strategies/spherical/ssf.hpp b/include/boost/geometry/strategies/spherical/ssf.hpp index 03f5428ed..18c547ced 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. -// Modifications copyright (c) 2016, Oracle and/or its affiliates. +// This file was modified by Oracle on 2016, 2018. +// Modifications copyright (c) 2016-2018, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -24,8 +24,9 @@ #include #include -#include +#include //#include +#include namespace boost { namespace geometry @@ -84,7 +85,7 @@ class spherical_side_formula { public : - typedef strategy::envelope::spherical_segment envelope_strategy_type; + typedef strategy::envelope::spherical envelope_strategy_type; static inline envelope_strategy_type get_envelope_strategy() { @@ -98,6 +99,12 @@ public : return disjoint_strategy_type(); } + typedef strategy::within::spherical_point_point equals_point_point_strategy_type; + static inline equals_point_point_strategy_type get_equals_point_point_strategy() + { + return equals_point_point_strategy_type(); + } + template static inline int apply(P1 const& p1, P2 const& p2, P const& p) { diff --git a/test/algorithms/detail/partition.cpp b/test/algorithms/detail/partition.cpp index fc899631d..9d63668d8 100644 --- a/test/algorithms/detail/partition.cpp +++ b/test/algorithms/detail/partition.cpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-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, 2018. +// Modifications copyright (c) 2017-2018 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, @@ -65,7 +65,12 @@ struct ovelaps_box template static inline bool apply(Box const& box, InputItem const& item) { - return ! bg::detail::disjoint::disjoint_box_box(box, item.box); + typename bg::strategy::disjoint::services::default_strategy + < + Box, Box + >::type strategy; + + return ! bg::detail::disjoint::disjoint_box_box(box, item.box, strategy); } }; diff --git a/test/algorithms/envelope_expand/envelope_on_spheroid.cpp b/test/algorithms/envelope_expand/envelope_on_spheroid.cpp index 6b26eeacb..dc0bd559d 100644 --- a/test/algorithms/envelope_expand/envelope_on_spheroid.cpp +++ b/test/algorithms/envelope_expand/envelope_on_spheroid.cpp @@ -1,7 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2015-2017, Oracle and/or its affiliates. +// Copyright (c) 2015-2018, 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 @@ -65,14 +65,29 @@ struct test_envelope static inline void apply(Geometry& geometry, Box& detected) { - bg::strategy::envelope::geographic_segment - < - FormulaPolicy, - bg::srs::spheroid, - double - > envelope_geographic_segment_strategy; + typedef bg::strategy::envelope::spherical_point point_strategy_t; + typedef bg::strategy::envelope::spherical_multipoint multi_point_strategy_t; + typedef bg::strategy::envelope::spherical_box box_strategy_t; + typedef bg::strategy::envelope::geographic, double> strategy_t; - bg::envelope(geometry, detected, envelope_geographic_segment_strategy); + typename boost::mpl::if_c + < + boost::is_same::type, bg::point_tag>::value, + point_strategy_t, + typename boost::mpl::if_c + < + boost::is_same::type, bg::multi_point_tag>::value, + multi_point_strategy_t, + typename boost::mpl::if_c + < + boost::is_same::type, bg::box_tag>::value, + box_strategy_t, + strategy_t + >::type + >::type + >::type strategy; + + bg::envelope(geometry, detected, strategy); } }; diff --git a/test/algorithms/is_valid.cpp b/test/algorithms/is_valid.cpp index 8efd1ef41..cc06a0164 100644 --- a/test/algorithms/is_valid.cpp +++ b/test/algorithms/is_valid.cpp @@ -1,7 +1,7 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2014-2015, Oracle and/or its affiliates. +// Copyright (c) 2014-2018, 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 @@ -874,6 +874,9 @@ inline void test_open_multipolygons() test::apply("mpg09", "MULTIPOLYGON(((0 0,10 0,10 10,0 10)),((0 0,9 1,9 2)))", false); + test::apply("mpg09_2", + "MULTIPOLYGON(((0 0,5 1,10 0,10 10,0 10)),((1 1,9 1,9 2)))", + false); // one polygon inside another and boundaries not touching test::apply("mpg10", diff --git a/test/algorithms/is_valid_failure.cpp b/test/algorithms/is_valid_failure.cpp index cbdd29180..96a2af0e6 100644 --- a/test/algorithms/is_valid_failure.cpp +++ b/test/algorithms/is_valid_failure.cpp @@ -1,9 +1,10 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test -// Copyright (c) 2015, Oracle and/or its affiliates. +// Copyright (c) 2015-2018, 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 @@ -851,6 +852,9 @@ void test_open_multipolygons() test::apply("mpg09", "MULTIPOLYGON(((0 0,10 0,10 10,0 10)),((0 0,9 1,9 2)))", bg::failure_intersecting_interiors); + test::apply("mpg09_2", + "MULTIPOLYGON(((0 0,5 1,10 0,10 10,0 10)),((1 1,9 1,9 2)))", + bg::failure_intersecting_interiors); // one polygon inside another and boundaries not touching test::apply("mpg10", diff --git a/test/algorithms/within/within.cpp b/test/algorithms/within/within.cpp index 07cea8d58..b095d1752 100644 --- a/test/algorithms/within/within.cpp +++ b/test/algorithms/within/within.cpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014, 2015, 2016. -// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2015, 2016, 2018. +// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -109,7 +109,7 @@ void test_strategy() box_type b0(point_type(0, 0), point_type(5, 0)); bool r = bg::within(p, b, - bg::strategy::within::point_in_box()); + bg::strategy::within::cartesian_point_box()); BOOST_CHECK_EQUAL(r, true); r = bg::within(b, b, @@ -121,7 +121,7 @@ void test_strategy() BOOST_CHECK_EQUAL(r, false); r = bg::within(p, b, - bg::strategy::within::point_in_box_by_side()); + bg::strategy::within::point_in_box_by_side<>()); BOOST_CHECK_EQUAL(r, true); } diff --git a/test/algorithms/within/within_sph_geo.cpp b/test/algorithms/within/within_sph_geo.cpp index 486fafb80..6b0fb1b2c 100644 --- a/test/algorithms/within/within_sph_geo.cpp +++ b/test/algorithms/within/within_sph_geo.cpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2016 Oracle and/or its affiliates. +// Copyright (c) 2016-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -19,7 +19,7 @@ void test_point_box_by_side() // Test spherical boxes // See also http://www.gcmap.com/mapui?P=1E45N-19E45N-19E55N-1E55N-1E45N,10E55.1N,10E45.1N typedef bg::model::box box_t; - bg::strategy::within::point_in_box_by_side by_side; + bg::strategy::within::point_in_box_by_side<> by_side; box_t box; bg::read_wkt("POLYGON((1 45,19 55))", box); BOOST_CHECK_EQUAL(bg::within(Point(10, 55.1), box, by_side), true); diff --git a/test/strategies/Jamfile.v2 b/test/strategies/Jamfile.v2 index 83026940a..10d281b38 100644 --- a/test/strategies/Jamfile.v2 +++ b/test/strategies/Jamfile.v2 @@ -4,8 +4,8 @@ # Copyright (c) 2008-2015 Bruno Lalande, Paris, France. # Copyright (c) 2009-2015 Mateusz Loskot, London, UK. # -# This file was modified by Oracle on 2014, 2015, 2016, 2017. -# Modifications copyright (c) 2014-2017, Oracle and/or its affiliates. +# This file was modified by Oracle on 2014, 2015, 2016, 2017, 2018. +# Modifications copyright (c) 2014-2018, 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 @@ -21,6 +21,7 @@ test-suite boost-geometry-strategies [ run crossings_multiply.cpp : : : : strategies_crossings_multiply ] [ run distance_default_result.cpp : : : : strategies_distance_default_result ] [ run douglas_peucker.cpp : : : : strategies_douglas_peucker ] + [ run envelope_segment.cpp : : : : strategies_envelope_segment ] [ run franklin.cpp : : : : strategies_franklin ] [ run haversine.cpp : : : : strategies_haversine ] [ run point_in_box.cpp : : : : strategies_point_in_box ] @@ -28,7 +29,6 @@ test-suite boost-geometry-strategies [ run projected_point_ax.cpp : : : : strategies_projected_point_ax ] [ run pythagoras.cpp : : : : strategies_pythagoras ] [ run pythagoras_point_box.cpp : : : : strategies_pythagoras_point_box ] - [ run segment_envelope.cpp : : : : strategies_segment_envelope ] [ run segment_intersection.cpp : : : : strategies_segment_intersection ] [ run segment_intersection_collinear.cpp : : : : strategies_segment_intersection_collinear ] [ run segment_intersection_geo.cpp : : : : strategies_segment_intersection_geo ] diff --git a/test/strategies/segment_envelope.cpp b/test/strategies/envelope_segment.cpp similarity index 96% rename from test/strategies/segment_envelope.cpp rename to test/strategies/envelope_segment.cpp index 7ece77686..09610e3c0 100644 --- a/test/strategies/segment_envelope.cpp +++ b/test/strategies/envelope_segment.cpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2016-2017 Oracle and/or its affiliates. +// Copyright (c) 2016-2018 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 @@ -41,9 +41,9 @@ void test_strategies_lat(P p1, P p2, CT expected_max, CT expected_min, BOOST_CHECK_CLOSE(p_max_degree_geo, expected_max, error); BOOST_CHECK_CLOSE(p_min_degree_geo, expected_min, error); - bg::strategy::envelope::spherical_segment strategy_sph; + typedef bg::strategy::envelope::spherical_segment strategy_sph_t; - strategy_sph.apply(p1, p2, box); + strategy_sph_t::apply(p1, p2, box); CT p_min_degree_sph = bg::get<0, 1>(box); CT p_max_degree_sph = bg::get<1, 1>(box); diff --git a/test/strategies/point_in_box.cpp b/test/strategies/point_in_box.cpp index 1c5e04879..50d5f65a3 100644 --- a/test/strategies/point_in_box.cpp +++ b/test/strategies/point_in_box.cpp @@ -34,8 +34,8 @@ void test_box_of(std::string const& wkt_point, std::string const& wkt_box, // Also test with the non-default agnostic side version namespace wi = bg::strategy::within; - wi::point_in_box_by_side within_strategy; - wi::point_in_box_by_side covered_by_strategy; + wi::point_in_box_by_side<> within_strategy; + wi::point_in_box_by_side covered_by_strategy; detected_within = bg::within(point, box, within_strategy); detected_covered_by = bg::covered_by(point, box, covered_by_strategy);