diff options
Diffstat (limited to 'boost/geometry')
273 files changed, 9129 insertions, 4835 deletions
diff --git a/boost/geometry/algorithms/area.hpp b/boost/geometry/algorithms/area.hpp index 26ff5c5058..b5ec53392f 100644 --- a/boost/geometry/algorithms/area.hpp +++ b/boost/geometry/algorithms/area.hpp @@ -216,15 +216,20 @@ struct area<MultiGeometry, multi_polygon_tag> : detail::multi_sum namespace resolve_strategy { +template <typename Strategy> struct area { - template <typename Geometry, typename Strategy> + template <typename Geometry> static inline typename area_result<Geometry, Strategy>::type apply(Geometry const& geometry, Strategy const& strategy) { return dispatch::area<Geometry>::apply(geometry, strategy); } +}; +template <> +struct area<default_strategy> +{ template <typename Geometry> static inline typename area_result<Geometry>::type apply(Geometry const& geometry, default_strategy) @@ -252,7 +257,7 @@ struct area static inline typename area_result<Geometry, Strategy>::type apply(Geometry const& geometry, Strategy const& strategy) { - return resolve_strategy::area::apply(geometry, strategy); + return resolve_strategy::area<Strategy>::apply(geometry, strategy); } }; diff --git a/boost/geometry/algorithms/buffer.hpp b/boost/geometry/algorithms/buffer.hpp index fd6f0fbe6a..ec2f9c5aca 100644 --- a/boost/geometry/algorithms/buffer.hpp +++ b/boost/geometry/algorithms/buffer.hpp @@ -37,52 +37,12 @@ #include <boost/geometry/geometries/box.hpp> #include <boost/geometry/util/math.hpp> +#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp> #include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp> namespace boost { namespace geometry { - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace buffer -{ - -template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N> -struct box_loop -{ - typedef typename coordinate_type<BoxOut>::type coordinate_type; - - static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out) - { - coordinate_type d = distance; - set<C, D>(box_out, get<C, D>(box_in) + d); - box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out); - } -}; - -template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N> -struct box_loop<BoxIn, BoxOut, T, C, N, N> -{ - static inline void apply(BoxIn const&, T const&, BoxOut&) {} -}; - -// Extends a box with the same amount in all directions -template<typename BoxIn, typename BoxOut, typename T> -inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out) -{ - assert_dimension_equal<BoxIn, BoxOut>(); - - static const std::size_t N = dimension<BoxIn>::value; - - box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out); - box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, distance, box_out); -} - - - -}} // namespace detail::buffer -#endif // DOXYGEN_NO_DETAIL - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { diff --git a/boost/geometry/algorithms/densify.hpp b/boost/geometry/algorithms/densify.hpp index ed948b3464..3a6e27d6ae 100644 --- a/boost/geometry/algorithms/densify.hpp +++ b/boost/geometry/algorithms/densify.hpp @@ -15,6 +15,7 @@ #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> #include <boost/geometry/algorithms/not_implemented.hpp> #include <boost/geometry/core/closure.hpp> +#include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/exception.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/tag.hpp> @@ -370,6 +371,9 @@ struct densify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > [heading Example] [densify_strategy] [densify_strategy_output] + +[heading See also] +\* [link geometry.reference.algorithms.line_interpolate line_interpolate] } */ template <typename Geometry, typename Distance, typename Strategy> @@ -409,6 +413,9 @@ inline void densify(Geometry const& geometry, [heading Example] [densify] [densify_output] + +[heading See also] +\* [link geometry.reference.algorithms.line_interpolate line_interpolate] } */ template <typename Geometry, typename Distance> diff --git a/boost/geometry/algorithms/detail/buffer/buffer_box.hpp b/boost/geometry/algorithms/detail/buffer/buffer_box.hpp new file mode 100755 index 0000000000..f19a91d6ba --- /dev/null +++ b/boost/geometry/algorithms/detail/buffer/buffer_box.hpp @@ -0,0 +1,62 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2018-2019 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP + +#include <cstddef> + +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/access.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + +template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N> +struct box_loop +{ + typedef typename coordinate_type<BoxOut>::type coordinate_type; + + static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out) + { + coordinate_type d = distance; + set<C, D>(box_out, get<C, D>(box_in) + d); + box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out); + } +}; + +template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N> +struct box_loop<BoxIn, BoxOut, T, C, N, N> +{ + static inline void apply(BoxIn const&, T const&, BoxOut&) {} +}; + +// Extends a box with the same amount in all directions +template<typename BoxIn, typename BoxOut, typename T> +inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out) +{ + assert_dimension_equal<BoxIn, BoxOut>(); + + static const std::size_t N = dimension<BoxIn>::value; + + box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out); + box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, distance, box_out); +} + +}} // namespace detail::buffer +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP diff --git a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp index 0374b53a99..a37eabbe25 100644 --- a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp +++ b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2012-2014 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 // Use, modification and distribution is subject to the Boost Software License, @@ -13,10 +13,6 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) -# define BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION -#endif - #include <cstddef> #include <boost/range.hpp> @@ -26,6 +22,7 @@ #include <boost/geometry/algorithms/covered_by.hpp> #include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp> +#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> #include <boost/geometry/strategies/buffer.hpp> @@ -181,9 +178,7 @@ struct buffer_turn_info intersection_location_type location; -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) robust_point_type rob_pi, rob_pj, rob_qi, rob_qj; -#endif std::size_t count_within; @@ -193,9 +188,7 @@ struct buffer_turn_info std::size_t count_on_offsetted; std::size_t count_on_helper; -#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) std::size_t count_within_near_offsetted; -#endif bool remove_on_multi; @@ -212,9 +205,7 @@ struct buffer_turn_info , count_in_original(0) , count_on_offsetted(0) , count_on_helper(0) -#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) , count_within_near_offsetted(0) -#endif , remove_on_multi(false) , count_on_occupied(0) , count_on_multi(0) diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index ba824243cc..128f2beef3 100644 --- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/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, @@ -145,6 +145,8 @@ struct buffered_piece_collection >::type robust_comparable_radius_type; typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; + typedef typename IntersectionStrategy::envelope_strategy_type envelope_strategy_type; + typedef typename IntersectionStrategy::expand_strategy_type expand_strategy_type; typedef typename IntersectionStrategy::template area_strategy < @@ -165,6 +167,12 @@ struct buffered_piece_collection robust_point_type >::type robust_area_result_type; + typedef typename strategy::point_in_geometry::services::default_strategy + < + robust_point_type, + robust_ring_type + >::type point_in_geometry_strategy_type; + typedef typename geometry::rescale_policy_type < typename geometry::point_type<Ring>::type @@ -280,12 +288,14 @@ struct buffered_piece_collection {} inline robust_original(robust_ring_type const& ring, - bool is_interior, bool has_interiors) + bool is_interior, bool has_interiors, + envelope_strategy_type const& envelope_strategy, + expand_strategy_type const& expand_strategy) : m_ring(ring) , m_is_interior(is_interior) , m_has_interiors(has_interiors) { - geometry::envelope(m_ring, m_box); + geometry::envelope(m_ring, m_box, envelope_strategy); // create monotonic sections in x-dimension // The dimension is critical because the direction is later used @@ -293,7 +303,8 @@ struct buffered_piece_collection // and this strategy is scanning in x direction. typedef boost::mpl::vector_c<std::size_t, 0> dimensions; geometry::sectionalize<false, dimensions>(m_ring, - detail::no_rescale_policy(), m_sections); + detail::no_rescale_policy(), m_sections, + envelope_strategy, expand_strategy); } robust_ring_type m_ring; @@ -335,6 +346,9 @@ struct buffered_piece_collection IntersectionStrategy m_intersection_strategy; side_strategy_type m_side_strategy; area_strategy_type m_area_strategy; + envelope_strategy_type m_envelope_strategy; + expand_strategy_type m_expand_strategy; + robust_area_strategy_type m_robust_area_strategy; RobustPolicy const& m_robust_policy; @@ -354,6 +368,8 @@ struct buffered_piece_collection , m_intersection_strategy(intersection_strategy) , m_side_strategy(intersection_strategy.get_side_strategy()) , m_area_strategy(intersection_strategy.template get_area_strategy<point_type>()) + , m_envelope_strategy(intersection_strategy.get_envelope_strategy()) + , m_expand_strategy(intersection_strategy.get_expand_strategy()) , m_robust_area_strategy(intersection_strategy.template get_area_strategy<robust_point_type>()) , m_robust_policy(robust_policy) {} @@ -529,7 +545,6 @@ struct buffered_piece_collection { it->location = inside_buffer; } -#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) if (it->count_within_near_offsetted > 0) { // Within can have in rare cases a rounding issue. We don't discard this @@ -538,7 +553,6 @@ struct buffered_piece_collection it->operations[0].enriched.startable = false; it->operations[1].enriched.startable = false; } -#endif } } @@ -635,6 +649,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<turn_vector_type> visitor(m_turns); geometry::partition < @@ -642,8 +665,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(); @@ -727,46 +750,47 @@ struct buffered_piece_collection } } -#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - // Insert all rescaled turn-points into these rings, to form a - // reliable integer-based ring. All turns can be compared (inside) to this - // rings to see if they are inside. - - for (typename boost::range_iterator<piece_vector_type>::type - it = boost::begin(m_pieces); it != boost::end(m_pieces); ++it) + if (! use_side_of_intersection<typename geometry::cs_tag<point_type>::type>::value) { - piece& pc = *it; - signed_size_type piece_segment_index = pc.first_seg_id.segment_index; - if (! pc.robust_turns.empty()) + // Insert all rescaled turn-points into these rings, to form a + // reliable integer-based ring. All turns can be compared (inside) to this + // rings to see if they are inside. + + for (typename boost::range_iterator<piece_vector_type>::type + it = boost::begin(m_pieces); it != boost::end(m_pieces); ++it) { - if (pc.robust_turns.size() > 1u) + piece& pc = *it; + signed_size_type piece_segment_index = pc.first_seg_id.segment_index; + if (! pc.robust_turns.empty()) { - std::sort(pc.robust_turns.begin(), pc.robust_turns.end(), buffer_operation_less()); - } - // Walk through them, in reverse to insert at right index - signed_size_type index_offset = static_cast<signed_size_type>(pc.robust_turns.size()) - 1; - for (typename boost::range_reverse_iterator<const std::vector<robust_turn> >::type - rit = boost::const_rbegin(pc.robust_turns); - rit != boost::const_rend(pc.robust_turns); - ++rit, --index_offset) - { - signed_size_type const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index; - BOOST_GEOMETRY_ASSERT - ( - index_in_vector > 0 - && index_in_vector < pc.offsetted_count - ); + if (pc.robust_turns.size() > 1u) + { + std::sort(pc.robust_turns.begin(), pc.robust_turns.end(), buffer_operation_less()); + } + // Walk through them, in reverse to insert at right index + signed_size_type index_offset = static_cast<signed_size_type>(pc.robust_turns.size()) - 1; + for (typename boost::range_reverse_iterator<const std::vector<robust_turn> >::type + rit = boost::const_rbegin(pc.robust_turns); + rit != boost::const_rend(pc.robust_turns); + ++rit, --index_offset) + { + signed_size_type const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index; + BOOST_GEOMETRY_ASSERT + ( + index_in_vector > 0 + && index_in_vector < pc.offsetted_count + ); - pc.robust_ring.insert(boost::begin(pc.robust_ring) + index_in_vector, rit->point); - pc.offsetted_count++; + pc.robust_ring.insert(boost::begin(pc.robust_ring) + index_in_vector, rit->point); + pc.offsetted_count++; - m_turns[rit->turn_index].operations[rit->operation_index].index_in_robust_ring = index_in_vector + index_offset; + m_turns[rit->turn_index].operations[rit->operation_index].index_in_robust_ring = index_in_vector + index_offset; + } } } - } - BOOST_GEOMETRY_ASSERT(assert_indices_in_robust_rings()); -#endif + BOOST_GEOMETRY_ASSERT(assert_indices_in_robust_rings()); + } } template <std::size_t Dimension> @@ -842,7 +866,8 @@ struct buffered_piece_collection // create monotonic sections in y-dimension typedef boost::mpl::vector_c<std::size_t, 1> dimensions; geometry::sectionalize<false, dimensions>(pc.robust_ring, - detail::no_rescale_policy(), pc.sections); + detail::no_rescale_policy(), pc.sections, + m_envelope_strategy, m_expand_strategy); // Determine min/max radius typedef geometry::model::referring_segment<robust_point_type const> @@ -906,12 +931,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(); @@ -926,15 +960,26 @@ struct buffered_piece_collection // Check if it is inside any of the pieces turn_in_piece_visitor < - turn_vector_type, piece_vector_type - > visitor(m_turns, m_pieces); + typename geometry::cs_tag<point_type>::type, + turn_vector_type, piece_vector_type, + point_in_geometry_strategy_type + > visitor(m_turns, m_pieces, point_in_geometry_strategy_type()); + + 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()); } } @@ -1057,7 +1102,7 @@ struct buffered_piece_collection robust_originals.push_back( robust_original(current_robust_ring, - is_interior, has_interiors)); + is_interior, has_interiors, m_envelope_strategy, m_expand_strategy)); } } @@ -1174,7 +1219,7 @@ struct buffered_piece_collection return; } - geometry::envelope(pc.robust_ring, pc.robust_envelope); + geometry::envelope(pc.robust_ring, pc.robust_envelope, m_envelope_strategy); geometry::assign_inverse(pc.robust_offsetted_envelope); for (signed_size_type i = 0; i < pc.offsetted_count; i++) @@ -1400,6 +1445,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,14 +1463,15 @@ 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; } int const geometry_code = detail::within::point_in_geometry(any_point, - original.m_ring); + original.m_ring, point_in_geometry_strategy_type()); if (geometry_code == -1) { diff --git a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp index 506ff58474..b2af001be2 100644 --- a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp +++ b/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, @@ -17,6 +17,7 @@ #include <boost/core/ignore_unused.hpp> #include <boost/range.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/algorithms/equals.hpp> #include <boost/geometry/algorithms/expand.hpp> #include <boost/geometry/algorithms/detail/disjoint/box_box.hpp> @@ -34,34 +35,81 @@ namespace boost { namespace geometry namespace detail { namespace buffer { - -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) -struct buffer_assign_turn +// Implements a unique_sub_range for a buffered piece, +// the range can return subsequent points +// known as "i", "j" and "k" (and further), indexed as 0,1,2,3 +template <typename Ring> +struct unique_sub_range_from_piece { - static bool const include_no_turn = false; - static bool const include_degenerate = false; - static bool const include_opposite = false; - - template - < - typename Info, - typename Point1, - typename Point2, - typename IntersectionInfo - > - static inline void apply(Info& info, - Point1 const& /*p1*/, - Point2 const& /*p2*/, - IntersectionInfo const& iinfo) + typedef typename boost::range_iterator<Ring const>::type iterator_type; + typedef typename geometry::point_type<Ring const>::type point_type; + + unique_sub_range_from_piece(Ring const& ring, + iterator_type iterator_at_i, iterator_type iterator_at_j) + : m_ring(ring) + , m_iterator_at_i(iterator_at_i) + , m_iterator_at_j(iterator_at_j) + , m_point_retrieved(false) + {} + + static inline bool is_first_segment() { return false; } + static inline bool is_last_segment() { return false; } + + static inline std::size_t size() { return 3u; } + + inline point_type const& at(std::size_t index) const { - info.rob_pi = iinfo.rpi(); - info.rob_pj = iinfo.rpj(); - info.rob_qi = iinfo.rqi(); - info.rob_qj = iinfo.rqj(); + BOOST_GEOMETRY_ASSERT(index < size()); + switch (index) + { + case 0 : return *m_iterator_at_i; + case 1 : return *m_iterator_at_j; + case 2 : return get_point_k(); + default : return *m_iterator_at_i; + } + } + +private : + + inline point_type const& get_point_k() const + { + if (! m_point_retrieved) + { + m_iterator_at_k = advance_one(m_iterator_at_j); + m_point_retrieved = true; + } + return *m_iterator_at_k; + } + + inline void circular_advance_one(iterator_type& next) const + { + ++next; + if (next == boost::end(m_ring)) + { + next = boost::begin(m_ring) + 1; + } } + inline iterator_type advance_one(iterator_type it) const + { + iterator_type result = it; + circular_advance_one(result); + + // TODO: we could also use piece-boundaries + // to check if the point equals the last one + while (geometry::equals(*it, *result)) + { + circular_advance_one(result); + } + return result; + } + + Ring const& m_ring; + iterator_type m_iterator_at_i; + iterator_type m_iterator_at_j; + mutable iterator_type m_iterator_at_k; + mutable bool m_point_retrieved; }; -#endif template < @@ -102,29 +150,6 @@ class piece_turn_visitor return ! m_rings[piece1.first_seg_id.multi_index].has_concave; } - template <typename Range, typename Iterator> - inline void move_to_next_point(Range const& range, Iterator& next) const - { - ++next; - if (next == boost::end(range)) - { - next = boost::begin(range) + 1; - } - } - - template <typename Range, typename Iterator> - inline Iterator next_point(Range const& range, Iterator it) const - { - Iterator result = it; - move_to_next_point(range, result); - // TODO: we could use either piece-boundaries, or comparison with - // robust points, to check if the point equals the last one - while(geometry::equals(*it, *result)) - { - move_to_next_point(range, result); - } - return result; - } template <std::size_t Dimension, typename Iterator, typename Box> inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond, @@ -229,15 +254,19 @@ class piece_turn_visitor the_model.operations[1].piece_index = piece2.index; the_model.operations[1].seg_id = piece2.first_seg_id; the_model.operations[1].seg_id.segment_index = index2; // override + geometry::recalculate(the_model.rob_pi, *prev1, m_robust_policy); + geometry::recalculate(the_model.rob_pj, *it1, m_robust_policy); - iterator next1 = next_point(ring1, it1); + unique_sub_range_from_piece<ring_type> unique_sub_range1(ring1, prev1, it1); iterator it2 = it2_first; for (iterator prev2 = it2++; it2 != it2_beyond; prev2 = it2++, the_model.operations[1].seg_id.segment_index++) { - iterator next2 = next_point(ring2, it2); + unique_sub_range_from_piece<ring_type> unique_sub_range2(ring2, prev2, it2); + geometry::recalculate(the_model.rob_qi, *prev2, m_robust_policy); + geometry::recalculate(the_model.rob_qj, *it2, m_robust_policy); // TODO: internally get_turn_info calculates robust points. // But they are already calculated. @@ -246,20 +275,14 @@ class piece_turn_visitor // and iterating in sync with them... typedef detail::overlay::get_turn_info < -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - buffer_assign_turn -#else detail::overlay::assign_null_policy -#endif > turn_policy; - turn_policy::apply(*prev1, *it1, *next1, - *prev2, *it2, *next2, - false, false, false, false, - the_model, - m_intersection_strategy, - m_robust_policy, - std::back_inserter(m_turns)); + turn_policy::apply(unique_sub_range1, unique_sub_range2, + the_model, + m_intersection_strategy, + m_robust_policy, + std::back_inserter(m_turns)); } } } @@ -292,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/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp index 70053536fb..5236da1da8 100644 --- a/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp +++ b/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, @@ -16,6 +16,7 @@ #include <boost/core/ignore_unused.hpp> +#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp> #include <boost/geometry/algorithms/expand.hpp> #include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp> #include <boost/geometry/strategies/buffer.hpp> @@ -38,12 +39,14 @@ struct original_get_box } }; +template <typename DisjointBoxBoxStrategy> struct original_ovelaps_box { template <typename Box, typename Original> 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 +59,7 @@ struct include_turn_policy } }; +template <typename DisjointPointBoxStrategy> struct turn_in_original_ovelaps_box { template <typename Box, typename Turn> @@ -68,7 +72,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/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp index e066c27f36..5e2258dfce 100644 --- a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp +++ b/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, @@ -20,6 +20,7 @@ #include <boost/range.hpp> #include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/config.hpp> #include <boost/geometry/arithmetic/dot_product.hpp> #include <boost/geometry/algorithms/assign.hpp> @@ -34,11 +35,8 @@ #include <boost/geometry/strategies/buffer.hpp> #include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp> -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) #include <boost/geometry/strategies/cartesian/side_of_intersection.hpp> -#else #include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp> -#endif namespace boost { namespace geometry @@ -58,6 +56,7 @@ struct piece_get_box } }; +template <typename DisjointBoxBoxStrategy> struct piece_ovelaps_box { template <typename Box, typename Piece> @@ -73,7 +72,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()); } }; @@ -86,12 +86,14 @@ struct turn_get_box } }; +template <typename DisjointPointBoxStrategy> struct turn_ovelaps_box { template <typename Box, typename Turn> 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()); } }; @@ -103,10 +105,8 @@ enum analyse_result analyse_disjoint, analyse_within, analyse_on_original_boundary, - analyse_on_offsetted -#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - , analyse_near_offsetted -#endif + analyse_on_offsetted, + analyse_near_offsetted }; template <typename Point> @@ -123,85 +123,115 @@ inline bool in_box(Point const& previous, return geometry::covered_by(point, box); } -template <typename Point, typename Turn> -inline analyse_result check_segment(Point const& previous, - Point const& current, Turn const& turn, - bool from_monotonic) -{ +// meta-programming-structure defining if to use side-of-intersection +// (only for cartesian / only necessary with rescaling) +template <typename Tag> +struct use_side_of_intersection {}; -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - typedef geometry::model::referring_segment<Point const> segment_type; - segment_type const p(turn.rob_pi, turn.rob_pj); - segment_type const q(turn.rob_qi, turn.rob_qj); - segment_type const r(previous, current); - int const side = strategy::side::side_of_intersection::apply(p, q, r, - turn.robust_point); +#if defined(BOOST_GEOMETRY_USE_RESCALING) +// With rescaling, let Cartesian use side-of-intersection +template <> +struct use_side_of_intersection<cartesian_tag> { static bool const value = true; }; +#else +template <> +struct use_side_of_intersection<cartesian_tag> { static bool const value = false; }; +#endif - if (side == 0) - { - return analyse_on_offsetted; - } - if (side == -1 && from_monotonic) - { - return analyse_within; - } - if (side == 1 && from_monotonic) - { - return analyse_disjoint; - } - return analyse_continue; +template <> +struct use_side_of_intersection<spherical_tag> { static bool const value = false; }; -#else +template <> +struct use_side_of_intersection<geographic_tag> { static bool const value = false; }; - typedef typename strategy::side::services::default_strategy - < - typename cs_tag<Point>::type - >::type side_strategy; - typedef typename geometry::coordinate_type<Point>::type coordinate_type; - coordinate_type const twice_area - = side_strategy::template side_value - < - coordinate_type, - coordinate_type - >(previous, current, turn.robust_point); +template <bool UseSideOfIntersection> +struct check_segment {}; - if (twice_area == 0) +// Implementation using side-of-intersection +template <> +struct check_segment<true> +{ + template <typename Point, typename Turn> + static inline analyse_result apply(Point const& previous, + Point const& current, Turn const& turn, + bool from_monotonic) { - // Collinear, only on segment if it is covered by its bbox - if (in_box(previous, current, turn.robust_point)) + typedef geometry::model::referring_segment<Point const> segment_type; + segment_type const p(turn.rob_pi, turn.rob_pj); + segment_type const q(turn.rob_qi, turn.rob_qj); + segment_type const r(previous, current); + int const side = strategy::side::side_of_intersection::apply(p, q, r, + turn.robust_point); + + if (side == 0) { return analyse_on_offsetted; } + if (side == -1 && from_monotonic) + { + return analyse_within; + } + if (side == 1 && from_monotonic) + { + return analyse_disjoint; + } + return analyse_continue; } - else if (twice_area < 0) +}; + +template <> +struct check_segment<false> +{ + template <typename Point, typename Turn> + static inline analyse_result apply(Point const& previous, + Point const& current, Turn const& turn, + bool from_monotonic) { - // It is in the triangle right-of the segment where the - // segment is the hypothenusa. Check if it is close - // (within rounding-area) - if (twice_area * twice_area < geometry::comparable_distance(previous, current) - && in_box(previous, current, turn.robust_point)) + typedef typename strategy::side::services::default_strategy + < + typename cs_tag<Point>::type + >::type side_strategy; + + int const side = side_strategy::apply(previous, current, turn.robust_point); + + if (side == 0) + { + // Collinear, only on segment if it is covered by its bbox + if (in_box(previous, current, turn.robust_point)) + { + return analyse_on_offsetted; + } + } + else if (side == -1) { - return analyse_near_offsetted; + // It is in the triangle right-of the segment where the + // segment is the hypothenusa. Check if it is close + // (within rounding-area) + if (in_box(previous, current, turn.robust_point)) + { + return analyse_near_offsetted; + } + else if (from_monotonic) + { + return analyse_within; + } } else if (from_monotonic) { - return analyse_within; + // Left of segment + return analyse_disjoint; } - } - else if (twice_area > 0 && from_monotonic) - { - // Left of segment - return analyse_disjoint; - } - // Not monotonic, on left or right side: continue analysing - return analyse_continue; -#endif -} + // Not monotonic, on left or right side: continue analysing + return analyse_continue; + } +}; +template <bool UseSideOfIntersection> +class analyse_turn_wrt_point_piece {}; -class analyse_turn_wrt_point_piece +template <> +class analyse_turn_wrt_point_piece<true> { public : template <typename Turn, typename Piece> @@ -211,17 +241,9 @@ public : typedef typename Turn::robust_point_type point_type; typedef typename geometry::coordinate_type<point_type>::type coordinate_type; -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) typedef geometry::model::referring_segment<point_type const> segment_type; segment_type const p(turn.rob_pi, turn.rob_pj); segment_type const q(turn.rob_qi, turn.rob_qj); -#else - typedef strategy::within::winding<point_type> strategy_type; - - typename strategy_type::state_type state; - strategy_type strategy; - boost::ignore_unused(strategy); -#endif BOOST_GEOMETRY_ASSERT(! piece.sections.empty()); @@ -241,7 +263,6 @@ public : point_type const& previous = piece.robust_ring[i - 1]; point_type const& current = piece.robust_ring[i]; -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) // First check if it is in range - if it is not, the // expensive side_of_intersection does not need to be @@ -272,8 +293,51 @@ public : return analyse_on_offsetted; } } -#else - analyse_result code = check_segment(previous, current, turn, false); + } + } + } + + // It is nowhere outside, and not on segment, so it is within + return analyse_within; + } + +}; + +template <> +class analyse_turn_wrt_point_piece<false> +{ +public : + template <typename Turn, typename Piece> + static inline analyse_result apply(Turn const& turn, Piece const& piece) + { + typedef typename Piece::section_type section_type; + typedef typename Turn::robust_point_type point_type; + typedef typename geometry::coordinate_type<point_type>::type coordinate_type; + + typedef strategy::within::winding<point_type> strategy_type; + + typename strategy_type::state_type state; + strategy_type strategy; + + BOOST_GEOMETRY_ASSERT(! piece.sections.empty()); + + coordinate_type const point_x = geometry::get<0>(turn.robust_point); + + for (std::size_t s = 0; s < piece.sections.size(); s++) + { + section_type const& section = piece.sections[s]; + // If point within horizontal range of monotonic section: + if (! section.duplicate + && section.begin_index < section.end_index + && point_x >= geometry::get<min_corner, 0>(section.bounding_box) - 1 + && point_x <= geometry::get<max_corner, 0>(section.bounding_box) + 1) + { + for (signed_size_type i = section.begin_index + 1; i <= section.end_index; i++) + { + point_type const& previous = piece.robust_ring[i - 1]; + point_type const& current = piece.robust_ring[i]; + + analyse_result code = check_segment<false>::apply(previous, current, turn, false); if (code != analyse_continue) { return code; @@ -282,15 +346,10 @@ public : // Get the state (to determine it is within), we don't have // to cover the on-segment case (covered above) strategy.apply(turn.robust_point, previous, current, state); -#endif } } } -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - // It is nowhere outside, and not on segment, so it is within - return analyse_within; -#else int const code = strategy.result(state); if (code == 1) { @@ -303,25 +362,24 @@ public : // Should normally not occur - on-segment is covered return analyse_unknown; -#endif } }; -class analyse_turn_wrt_piece +template <bool UseSideOfIntersection> +struct check_helper_segment {}; + +template <> +struct check_helper_segment<true> { template <typename Point, typename Turn> - static inline analyse_result check_helper_segment(Point const& s1, + static inline analyse_result apply(Point const& s1, Point const& s2, Turn const& turn, -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - bool , // is on original, to be reused -#else bool is_original, -#endif Point const& offsetted) { boost::ignore_unused(offsetted); -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + boost::ignore_unused(is_original); typedef geometry::model::referring_segment<Point const> segment_type; segment_type const p(turn.rob_pi, turn.rob_pj); segment_type const q(turn.rob_qi, turn.rob_qj); @@ -360,7 +418,20 @@ class analyse_turn_wrt_piece // right of segment return analyse_continue; -#else + } + +}; + +template <> +struct check_helper_segment<false> +{ + template <typename Point, typename Turn> + static inline analyse_result apply(Point const& s1, + Point const& s2, Turn const& turn, + bool is_original, + Point const& offsetted) + { + boost::ignore_unused(offsetted); typedef typename strategy::side::services::default_strategy < typename cs_tag<Point>::type @@ -409,9 +480,12 @@ class analyse_turn_wrt_piece // right of segment return analyse_continue; -#endif } +}; +template <bool UseSideOfIntersection> +class analyse_turn_wrt_piece +{ template <typename Turn, typename Piece> static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece) { @@ -471,7 +545,7 @@ class analyse_turn_wrt_piece // Right side of the piece analyse_result result - = check_helper_segment(points[0], points[1], turn, + = check_helper_segment<UseSideOfIntersection>::apply(points[0], points[1], turn, false, points[0]); if (result != analyse_continue) { @@ -479,7 +553,7 @@ class analyse_turn_wrt_piece } // Left side of the piece - result = check_helper_segment(points[2], points[3], turn, + result = check_helper_segment<UseSideOfIntersection>::apply(points[2], points[3], turn, false, points[3]); if (result != analyse_continue) { @@ -489,7 +563,7 @@ class analyse_turn_wrt_piece if (! comparator(points[1], points[2])) { // Side of the piece at side of original geometry - result = check_helper_segment(points[1], points[2], turn, + result = check_helper_segment<UseSideOfIntersection>::apply(points[1], points[2], turn, true, point); if (result != analyse_continue) { @@ -536,7 +610,7 @@ class analyse_turn_wrt_piece // w.r.t. specified direction, and prev points to a point smaller // We now know if it is inside/outside it_type prev = it - 1; - return check_segment(*prev, *it, turn, true); + return check_segment<UseSideOfIntersection>::apply(*prev, *it, turn, true); } return analyse_continue; } @@ -593,7 +667,7 @@ public : // (on which any side or side-value would return 0) if (! comparator(previous, current)) { - code = check_segment(previous, current, turn, false); + code = check_segment<UseSideOfIntersection>::apply(previous, current, turn, false); if (code != analyse_continue) { return code; @@ -606,45 +680,17 @@ public : }; +// Helper Structure, of which the apply method returns a side value in {-1, 0, 1} +template <bool UseSideOfIntersection> +struct turn_in_piece {}; -template <typename Turns, typename Pieces> -class turn_in_piece_visitor +template <> +struct turn_in_piece<true> { - Turns& m_turns; // because partition is currently operating on const input only - Pieces const& m_pieces; // to check for piece-type - template <typename Operation, typename Piece> - inline bool skip(Operation const& op, Piece const& piece) const - { - if (op.piece_index == piece.index) - { - return true; - } - Piece const& pc = m_pieces[op.piece_index]; - if (pc.left_index == piece.index || pc.right_index == piece.index) - { - if (pc.type == strategy::buffer::buffered_flat_end) - { - // If it is a flat end, don't compare against its neighbor: - // it will always be located on one of the helper segments - return true; - } - if (pc.type == strategy::buffer::buffered_concave) - { - // If it is concave, the same applies: the IP will be - // located on one of the helper segments - return true; - } - } - - return false; - } - -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - // NOTE: this function returns a side value in {-1, 0, 1} +private : template <typename Turn, typename Piece> - static inline int turn_in_convex_piece(Turn const& turn, - Piece const& piece) + static inline int in_convex_piece(Turn const& turn, Piece const& piece) { typedef typename Turn::robust_point_type point_type; typedef typename Piece::piece_robust_ring_type ring_type; @@ -693,14 +739,90 @@ class turn_in_piece_visitor } return 1; // inside } -#endif + +public : + + template <typename Turn, typename Piece, typename Strategy> + static inline int apply(Turn const& turn, Piece const& piece, + Strategy const& strategy) + { + if (piece.is_convex) + { + return in_convex_piece(turn, piece); + } + else + { + // side-of-intersection only supported for convex pieces + // Call point_in_geometry, a performance-bottleneck + // TODO: might be replaced by extending analysing piece + return detail::within::point_in_geometry(turn.robust_point, + piece.robust_ring, strategy); + } + } +}; + +template <> +struct turn_in_piece<false> +{ +public : + + template <typename Turn, typename Piece, typename Strategy> + static inline int apply(Turn const& turn, Piece const& piece, + Strategy const& strategy) + { + return detail::within::point_in_geometry(turn.robust_point, + piece.robust_ring, strategy); + } +}; + +template +< + typename CsTag, + typename Turns, + typename Pieces, + typename PointInGeometryStrategy +> +class turn_in_piece_visitor +{ + Turns& m_turns; // because partition is currently operating on const input only + Pieces const& m_pieces; // to check for piece-type + PointInGeometryStrategy const& m_point_in_geometry_strategy; + + template <typename Operation, typename Piece> + inline bool skip(Operation const& op, Piece const& piece) const + { + if (op.piece_index == piece.index) + { + return true; + } + Piece const& pc = m_pieces[op.piece_index]; + if (pc.left_index == piece.index || pc.right_index == piece.index) + { + if (pc.type == strategy::buffer::buffered_flat_end) + { + // If it is a flat end, don't compare against its neighbor: + // it will always be located on one of the helper segments + return true; + } + if (pc.type == strategy::buffer::buffered_concave) + { + // If it is concave, the same applies: the IP will be + // located on one of the helper segments + return true; + } + } + + return false; + } public: - inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces) + inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces, + PointInGeometryStrategy const& strategy) : m_turns(turns) , m_pieces(pieces) + , m_point_in_geometry_strategy(strategy) {} template <typename Turn, typename Piece> @@ -759,10 +881,13 @@ public: } } + static const bool use_soi = use_side_of_intersection<CsTag>::value; + boost::ignore_unused(use_soi); + analyse_result analyse_code = piece.type == geometry::strategy::buffer::buffered_point - ? analyse_turn_wrt_point_piece::apply(turn, piece) - : analyse_turn_wrt_piece::apply(turn, piece); + ? analyse_turn_wrt_point_piece<use_soi>::apply(turn, piece) + : analyse_turn_wrt_piece<use_soi>::apply(turn, piece); switch(analyse_code) { @@ -777,32 +902,15 @@ public: case analyse_within : mutable_turn.count_within++; return true; -#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) case analyse_near_offsetted : mutable_turn.count_within_near_offsetted++; return true; -#endif default : break; } -#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) - // We don't know (yet) - int geometry_code = 0; - if (piece.is_convex) - { - geometry_code = turn_in_convex_piece(turn, piece); - } - else - { - - // TODO: this point_in_geometry is a performance-bottleneck here and - // will be replaced completely by extending analyse_piece functionality - geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring); - } -#else - int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring); -#endif + int const geometry_code = turn_in_piece<use_soi>::apply(turn, piece, + m_point_in_geometry_strategy); if (geometry_code == 1) { diff --git a/boost/geometry/algorithms/detail/covered_by/implementation.hpp b/boost/geometry/algorithms/detail/covered_by/implementation.hpp index c5a02b9761..b180a3d5a3 100644 --- a/boost/geometry/algorithms/detail/covered_by/implementation.hpp +++ b/boost/geometry/algorithms/detail/covered_by/implementation.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013, 2014, 2017. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2017, 2019. +// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -36,7 +36,7 @@ struct use_point_in_geometry template <typename Geometry1, typename Geometry2, typename Strategy> static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { - return detail::within::point_in_geometry(geometry1, geometry2, strategy) >= 0; + return detail::within::covered_by_point_geometry(geometry1, geometry2, strategy); } }; diff --git a/boost/geometry/algorithms/detail/covered_by/interface.hpp b/boost/geometry/algorithms/detail/covered_by/interface.hpp index 6599078210..bdc92db43b 100644 --- a/boost/geometry/algorithms/detail/covered_by/interface.hpp +++ b/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<Geometry1>::type, - typename tag<Geometry2>::type, - typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type, - Strategy - >(); + concepts::within::check<Geometry1, Geometry2, Strategy>(); concepts::check<Geometry1 const>(); concepts::check<Geometry2 const>(); assert_dimension_equal<Geometry1, Geometry2>(); diff --git a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp b/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp index 664c995384..3fccc74d22 100644 --- a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp +++ b/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2013-2017. -// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2013-2019. +// Modifications copyright (c) 2013-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -28,6 +28,9 @@ #include <boost/geometry/algorithms/detail/point_on_border.hpp> #include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp> +#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp> + +#include <boost/geometry/iterators/segment_iterator.hpp> namespace boost { namespace geometry @@ -38,30 +41,15 @@ namespace boost { namespace geometry namespace detail { namespace disjoint { - -template <typename Geometry, typename Tag = typename tag<Geometry>::type> -struct check_each_ring_for_within_call_covered_by +template <typename Geometry1, typename Geometry2, typename Strategy> +inline bool point_on_border_covered_by(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { - /*! - \tparam Strategy point_in_geometry strategy - */ - template <typename Point, typename Strategy> - static inline bool apply(Point const& p, Geometry const& g, Strategy const& strategy) - { - return geometry::covered_by(p, g, strategy); - } -}; - -template <typename Geometry> -struct check_each_ring_for_within_call_covered_by<Geometry, box_tag> -{ - template <typename Point, typename Strategy> - static inline bool apply(Point const& p, Geometry const& g, Strategy const& ) - { - return geometry::covered_by(p, g); - } -}; - + typename geometry::point_type<Geometry1>::type pt; + return geometry::point_on_border(pt, geometry1) + && geometry::covered_by(pt, geometry2, strategy); +} /*! \tparam Strategy point_in_geometry strategy @@ -83,13 +71,8 @@ struct check_each_ring_for_within template <typename Range> inline void apply(Range const& range) { - typename point_type<Range>::type pt; not_disjoint = not_disjoint - || ( geometry::point_on_border(pt, range) - && check_each_ring_for_within_call_covered_by - < - Geometry - >::apply(pt, m_geometry, m_strategy) ); + || point_on_border_covered_by(range, m_geometry, m_strategy); } }; @@ -113,7 +96,7 @@ inline bool rings_containing(FirstGeometry const& geometry1, template <typename Geometry1, typename Geometry2> -struct general_areal +struct areal_areal { /*! \tparam Strategy relate (segments intersection) strategy @@ -147,6 +130,56 @@ struct general_areal }; +template <typename Areal, typename Box> +struct areal_box +{ + /*! + \tparam Strategy relate (segments intersection) strategy + */ + template <typename Strategy> + static inline bool apply(Areal const& areal, + Box const& box, + Strategy const& strategy) + { + if ( ! for_each_segment(geometry::segments_begin(areal), + geometry::segments_end(areal), + box, + strategy.get_disjoint_segment_box_strategy()) ) + { + return false; + } + + // If there is no intersection of any segment and box, + // the box might be located inside areal geometry + + if ( point_on_border_covered_by(box, areal, + strategy.template get_point_in_geometry_strategy<Box, Areal>()) ) + { + return false; + } + + return true; + } + +private: + template <typename SegIter, typename Strategy> + static inline bool for_each_segment(SegIter first, + SegIter last, + Box const& box, + Strategy const& strategy) + { + for ( ; first != last ; ++first) + { + if (! disjoint_segment_box::apply(*first, box, strategy)) + { + return false; + } + } + return true; + } +}; + + }} // namespace detail::disjoint #endif // DOXYGEN_NO_DETAIL @@ -160,13 +193,13 @@ namespace dispatch template <typename Areal1, typename Areal2> struct disjoint<Areal1, Areal2, 2, areal_tag, areal_tag, false> - : detail::disjoint::general_areal<Areal1, Areal2> + : detail::disjoint::areal_areal<Areal1, Areal2> {}; template <typename Areal, typename Box> struct disjoint<Areal, Box, 2, areal_tag, box_tag, false> - : detail::disjoint::general_areal<Areal, Box> + : detail::disjoint::areal_box<Areal, Box> {}; diff --git a/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/boost/geometry/algorithms/detail/disjoint/box_box.hpp index 87618939b8..67f0633218 100644 --- a/boost/geometry/algorithms/detail/disjoint/box_box.hpp +++ b/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 <cstddef> -#include <boost/geometry/core/access.hpp> -#include <boost/geometry/core/tags.hpp> - #include <boost/geometry/algorithms/dispatch/disjoint.hpp> -#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> -#include <boost/geometry/util/select_most_precise.hpp> - +// For backward compatibility +#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp> +#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp> 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<Box1>::value, - typename CSTag = typename tag_cast - < - typename cs_tag<Box1>::type, - spherical_tag - >::type -> -struct box_box -{ - template <typename Strategy> - 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<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2)) - { - return true; - } - if (get<min_corner, Dimension>(box1) > get<max_corner, Dimension>(box2)) - { - return true; - } - return box_box - < - Box1, Box2, - Dimension + 1, DimensionCount - >::apply(box1, box2); - } -}; - - -template <typename Box1, typename Box2, std::size_t DimensionCount, typename CSTag> -struct box_box<Box1, Box2, DimensionCount, DimensionCount, CSTag> -{ - static inline bool apply(Box1 const& , Box2 const& ) - { - return false; - } -}; - - -template <typename Box1, typename Box2, std::size_t DimensionCount> -struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag> -{ - template <typename Strategy> - 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<Box1>::type, - typename coordinate_type<Box2>::type - >::type calc_t; - typedef typename coordinate_system<Box1>::type::units units_t; - typedef math::detail::constants_on_spheroid<calc_t, units_t> constants; - - calc_t const b1_min = get<min_corner, 0>(box1); - calc_t const b1_max = get<max_corner, 0>(box1); - calc_t const b2_min = get<min_corner, 0>(box2); - calc_t const b2_max = get<max_corner, 0>(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<units_t>(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 <typename Box1, typename Box2> -inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2) +template <typename Box1, typename Box2, typename Strategy> +inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const&) { - return box_box<Box1, Box2>::apply(box1, box2); + return Strategy::apply(box1, box2); } @@ -170,8 +61,13 @@ namespace dispatch template <typename Box1, typename Box2, std::size_t DimensionCount> struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, false> - : detail::disjoint::box_box<Box1, Box2, 0, DimensionCount> -{}; +{ + template <typename Strategy> + static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&) + { + return Strategy::apply(box1, box2); + } +}; } // namespace dispatch diff --git a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp index e6077d3e7f..55e3fe07fd 100644 --- a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp +++ b/boost/geometry/algorithms/detail/disjoint/linear_areal.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 Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -41,8 +41,9 @@ #include <boost/geometry/algorithms/detail/check_iterator_range.hpp> #include <boost/geometry/algorithms/detail/point_on_border.hpp> -#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp> +#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp> #include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp> +#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp> #include <boost/geometry/algorithms/detail/disjoint/point_box.hpp> #include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp> diff --git a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp index 989b8df247..7b830f7d1f 100644 --- a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp +++ b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp @@ -93,18 +93,6 @@ struct assign_disjoint_policy static bool const include_no_turn = true; static bool const include_degenerate = true; static bool const include_opposite = true; - - // We don't assign extra info: - template - < - typename Info, - typename Point1, - typename Point2, - typename IntersectionInfo - > - static inline void apply(Info& , Point1 const& , Point2 const&, - IntersectionInfo const&) - {} }; diff --git a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp index d7aa9089e3..029d68be5b 100644 --- a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp +++ b/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 <typename DisjointPointBoxStrategy> struct overlaps_box_point { template <typename Box, typename Point> 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<typename point_type<MultiPoint>::type> >::apply(multipoint, segment_range(linear), visitor, expand_box_point(), - overlaps_box_point(), + overlaps_box_point<disjoint_pb_strategy_type>(), expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()), overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy())); @@ -256,8 +259,12 @@ class multi_point_single_geometry { public: template <typename Strategy> - 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<MultiPoint>::type point1_type; typedef typename point_type<SingleGeometry>::type point2_type; typedef model::box<point2_type> 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<point1_type, SingleGeometry>::apply(*it, single_geometry, strategy)) { return false; @@ -310,23 +317,27 @@ private: } }; + template <typename DisjointPointBoxStrategy> struct overlaps_box_point { template <typename Box, typename Point> 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 <typename DisjointBoxBoxStrategy> struct overlaps_box_box_pair { template <typename Box, typename BoxPair> 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 <typename Point, typename BoxPair> 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<MultiGeometry>::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<Point, single_type>::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy)) { m_intersection_found = true; @@ -390,14 +403,23 @@ public: item_visitor_type<Strategy> 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/boost/geometry/algorithms/detail/disjoint/point_box.hpp b/boost/geometry/algorithms/detail/disjoint/point_box.hpp index 2e6773d221..b4c4026467 100644 --- a/boost/geometry/algorithms/detail/disjoint/point_box.hpp +++ b/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 <typename Point, typename Box> -inline bool disjoint_point_box(Point const& point, Box const& box) +template <typename Point, typename Box, typename Strategy> +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/boost/geometry/algorithms/detail/disjoint/point_point.hpp b/boost/geometry/algorithms/detail/disjoint/point_point.hpp index 13ac34d718..f91712934b 100644 --- a/boost/geometry/algorithms/detail/disjoint/point_point.hpp +++ b/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 <cstddef> -#include <boost/type_traits/is_same.hpp> - -#include <boost/geometry/core/access.hpp> -#include <boost/geometry/core/radian_access.hpp> -#include <boost/geometry/core/coordinate_dimension.hpp> -#include <boost/geometry/core/coordinate_system.hpp> -#include <boost/geometry/core/coordinate_type.hpp> -#include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/util/math.hpp> -#include <boost/geometry/util/select_most_precise.hpp> - -#include <boost/geometry/strategies/strategy_transform.hpp> - -#include <boost/geometry/geometries/helper_geometry.hpp> - -#include <boost/geometry/algorithms/transform.hpp> - -#include <boost/geometry/algorithms/detail/normalize.hpp> - #include <boost/geometry/algorithms/dispatch/disjoint.hpp> +// For backward compatibility +#include <boost/geometry/strategies/disjoint.hpp> +#include <boost/geometry/strategies/cartesian/point_in_point.hpp> +#include <boost/geometry/strategies/spherical/point_in_point.hpp> + namespace boost { namespace geometry { @@ -56,169 +42,15 @@ namespace detail { namespace disjoint { -template <std::size_t Dimension, std::size_t DimensionCount> -struct point_point_generic -{ - template <typename Point1, typename Point2, typename Strategy> - static inline bool apply(Point1 const& p1, Point2 const& p2, Strategy const& ) - { - return apply(p1, p2); - } - - template <typename Point1, typename Point2> - static inline bool apply(Point1 const& p1, Point2 const& p2) - { - if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2))) - { - return true; - } - return - point_point_generic<Dimension + 1, DimensionCount>::apply(p1, p2); - } -}; - -template <std::size_t DimensionCount> -struct point_point_generic<DimensionCount, DimensionCount> -{ - template <typename Point1, typename Point2> - static inline bool apply(Point1 const&, Point2 const& ) - { - return false; - } -}; - - -class point_point_on_spheroid -{ -private: - template <typename Point1, typename Point2, bool SameUnits> - struct are_same_points - { - static inline bool apply(Point1 const& point1, Point2 const& point2) - { - typedef typename helper_geometry<Point1>::type helper_point_type1; - typedef typename helper_geometry<Point2>::type helper_point_type2; - - helper_point_type1 point1_normalized - = return_normalized<helper_point_type1>(point1); - helper_point_type2 point2_normalized - = return_normalized<helper_point_type2>(point2); - - return point_point_generic - < - 0, dimension<Point1>::value - >::apply(point1_normalized, point2_normalized); - } - }; - - template <typename Point1, typename Point2> - struct are_same_points<Point1, Point2, false> // points have different units - { - static inline bool apply(Point1 const& point1, Point2 const& point2) - { - typedef typename geometry::select_most_precise - < - typename fp_coordinate_type<Point1>::type, - typename fp_coordinate_type<Point2>::type - >::type calculation_type; - - typename helper_geometry - < - Point1, calculation_type, radian - >::type helper_point1, helper_point2; - - Point1 point1_normalized = return_normalized<Point1>(point1); - Point2 point2_normalized = return_normalized<Point2>(point2); - - geometry::transform(point1_normalized, helper_point1); - geometry::transform(point2_normalized, helper_point2); - - return point_point_generic - < - 0, dimension<Point1>::value - >::apply(helper_point1, helper_point2); - } - }; - -public: - template <typename Point1, typename Point2, typename Strategy> - static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& ) - { - return apply(point1, point2); - } - - template <typename Point1, typename Point2> - static inline bool apply(Point1 const& point1, Point2 const& point2) - { - return are_same_points - < - Point1, - Point2, - boost::is_same - < - typename coordinate_system<Point1>::type::units, - typename coordinate_system<Point2>::type::units - >::value - >::apply(point1, point2); - } -}; - - -template -< - typename Point1, typename Point2, - std::size_t Dimension, std::size_t DimensionCount, - typename CSTag1 = typename cs_tag<Point1>::type, - typename CSTag2 = CSTag1 -> -struct point_point - : point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag> -{}; - -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<Point1, Point2, Dimension, DimensionCount, cartesian_tag> - : point_point_generic<Dimension, DimensionCount> -{}; - - /*! \brief Internal utility function to detect of points are disjoint \note To avoid circular references */ -template <typename Point1, typename Point2> -inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2) +template <typename Point1, typename Point2, typename Strategy> +inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2, + Strategy const& ) { - return point_point - < - Point1, Point2, - 0, dimension<Point1>::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 <typename Point1, typename Point2, std::size_t DimensionCount> struct disjoint<Point1, Point2, DimensionCount, point_tag, point_tag, false> - : detail::disjoint::point_point<Point1, Point2, 0, DimensionCount> -{}; +{ + template <typename Strategy> + static inline bool apply(Point1 const& point1, Point2 const& point2, + Strategy const& ) + { + return ! Strategy::apply(point1, point2); + } +}; } // namespace dispatch diff --git a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp index baa4cf83dd..ea51f6be7a 100644 --- a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp +++ b/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-2019. +// Modifications copyright (c) 2013-2019, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -39,6 +39,9 @@ #include <boost/geometry/geometries/box.hpp> +// Temporary, for envelope_segment_impl +#include <boost/geometry/strategies/spherical/envelope_segment.hpp> + namespace boost { namespace geometry { @@ -50,21 +53,6 @@ namespace detail { namespace disjoint template <typename CS_Tag> struct disjoint_segment_box_sphere_or_spheroid { -private: - - template <typename CT> - 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,26 +70,50 @@ public: operator T () const; }; - template <typename Segment, typename Box, typename Strategy> + 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<Segment>::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 <typename Segment, typename Box, typename Strategy, typename P> + 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<Segment, Box>(); typedef typename point_type<Segment>::type segment_point_type; - typedef typename cs_tag<Segment>::type segment_cs_type; segment_point_type p0, p1; geometry::detail::assign_point_from_index<0>(segment, p0); @@ -113,7 +125,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 +135,10 @@ public: typedef typename coordinate_type<segment_point_type>::type CT; - segment_point_type p0_normalized = - geometry::detail::return_normalized<segment_point_type>(p0); - segment_point_type p1_normalized = - geometry::detail::return_normalized<segment_point_type>(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,38 +147,35 @@ 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 - //in order for it to be used later in the algorithm - CT alp1; - - azimuth_strategy.apply(lon1, lat1, lon2, lat2, alp1); - geometry::model::box<segment_point_type> box_seg; - geometry::detail::envelope::envelope_segment_impl<segment_cs_type> - ::template apply<geometry::radian>(lon1, lat1, - lon2, lat2, - box_seg, - azimuth_strategy, - alp1); + strategy::envelope::detail::envelope_segment_impl + < + CS_Tag + >::template apply<geometry::radian>(lon1, lat1, + lon2, lat2, + box_seg, + azimuth_strategy); - if (disjoint_box_box(box, box_seg)) + if (disjoint_box_box(box, box_seg, disjoint_box_box_strategy)) { return disjoint_return_value; } // Case 3: test intersection by comparing angles - CT a_b0, a_b1, a_b2, a_b3; + CT alp1, a_b0, a_b1, a_b2, a_b3; CT b_lon_min = geometry::get_as_radian<geometry::min_corner, 0>(box); CT b_lat_min = geometry::get_as_radian<geometry::min_corner, 1>(box); CT b_lon_max = geometry::get_as_radian<geometry::max_corner, 0>(box); CT b_lat_max = geometry::get_as_radian<geometry::max_corner, 1>(box); + azimuth_strategy.apply(lon1, lat1, lon2, lat2, alp1); azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_min, a_b0); azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_min, a_b1); azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_max, a_b2); diff --git a/boost/geometry/algorithms/detail/distance/interface.hpp b/boost/geometry/algorithms/detail/distance/interface.hpp index 4122ecfe17..2338abbeb5 100644 --- a/boost/geometry/algorithms/detail/distance/interface.hpp +++ b/boost/geometry/algorithms/detail/distance/interface.hpp @@ -95,9 +95,10 @@ struct distance namespace resolve_strategy { +template <typename Strategy> struct distance { - template <typename Geometry1, typename Geometry2, typename Strategy> + template <typename Geometry1, typename Geometry2> static inline typename distance_result<Geometry1, Geometry2, Strategy>::type apply(Geometry1 const& geometry1, Geometry2 const& geometry2, @@ -108,7 +109,11 @@ struct distance Geometry1, Geometry2, Strategy >::apply(geometry1, geometry2, strategy); } +}; +template <> +struct distance<default_strategy> +{ template <typename Geometry1, typename Geometry2> static inline typename distance_result<Geometry1, Geometry2, default_strategy>::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/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp b/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp index 9596799cb2..f41cf5c764 100644 --- a/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp +++ b/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp @@ -5,10 +5,11 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014. -// Modifications copyright (c) 2014, Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2019. +// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -39,13 +40,12 @@ #include <boost/geometry/strategies/tags.hpp> #include <boost/geometry/algorithms/assign.hpp> -#include <boost/geometry/algorithms/covered_by.hpp> -#include <boost/geometry/algorithms/within.hpp> #include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp> #include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp> #include <boost/geometry/algorithms/detail/distance/is_comparable.hpp> #include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp> +#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp> #include <boost/geometry/algorithms/dispatch/distance.hpp> @@ -160,7 +160,8 @@ struct point_to_ring Ring const& ring, Strategy const& strategy) { - if (geometry::within(point, ring)) + // TODO: pass strategy + if (within::within_point_geometry(point, ring)) { return return_type(0); } @@ -204,7 +205,8 @@ private: { for (InteriorRingIterator it = first; it != last; ++it) { - if (geometry::within(point, *it)) + // TODO: pass strategy + if (within::within_point_geometry(point, *it)) { // the point is inside a polygon hole, so its distance // to the polygon its distance to the polygon's @@ -233,7 +235,8 @@ public: Polygon const& polygon, Strategy const& strategy) { - if (!geometry::covered_by(point, exterior_ring(polygon))) + // TODO: pass strategy + if (! within::covered_by_point_geometry(point, exterior_ring(polygon))) { // the point is outside the exterior ring, so its distance // to the polygon is its distance to the polygon's exterior ring @@ -330,7 +333,8 @@ struct point_to_multigeometry<Point, MultiPolygon, Strategy, true> MultiPolygon const& multipolygon, Strategy const& strategy) { - if (geometry::covered_by(point, multipolygon)) + // TODO: pass strategy + if (within::covered_by_point_geometry(point, multipolygon)) { return 0; } diff --git a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp index bfe52c7b1b..d88a6699c8 100644 --- a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp +++ b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp @@ -1,15 +1,17 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-2018 Oracle and/or its affiliates. +// Copyright (c) 2014-2019 Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP + #include <cstddef> #include <functional> @@ -27,26 +29,27 @@ #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/tags.hpp> +#include <boost/geometry/algorithms/detail/assign_box_corners.hpp> +#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp> +#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp> +#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp> +#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp> +#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp> +#include <boost/geometry/algorithms/detail/equals/point_point.hpp> +#include <boost/geometry/algorithms/dispatch/distance.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> + +#include <boost/geometry/policies/compare.hpp> + #include <boost/geometry/util/calculation_type.hpp> #include <boost/geometry/util/condition.hpp> +#include <boost/geometry/util/has_nan_coordinate.hpp> #include <boost/geometry/util/math.hpp> +#include <boost/geometry/strategies/disjoint.hpp> #include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/strategies/tags.hpp> -#include <boost/geometry/policies/compare.hpp> - -#include <boost/geometry/algorithms/equals.hpp> -#include <boost/geometry/algorithms/intersects.hpp> -#include <boost/geometry/algorithms/not_implemented.hpp> - -#include <boost/geometry/algorithms/detail/assign_box_corners.hpp> -#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp> -#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp> -#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp> - -#include <boost/geometry/algorithms/dispatch/distance.hpp> - namespace boost { namespace geometry { @@ -57,6 +60,20 @@ namespace detail { namespace distance { +// TODO: Take strategy +template <typename Segment, typename Box> +inline bool intersects_segment_box(Segment const& segment, Box const& box) +{ + typedef typename strategy::disjoint::services::default_strategy + < + Segment, Box + >::type strategy_type; + + return ! detail::disjoint::disjoint_segment_box::apply(segment, box, + strategy_type()); +} + + template < typename Segment, @@ -99,7 +116,7 @@ public: Strategy const& strategy, bool check_intersection = true) { - if (check_intersection && geometry::intersects(segment, box)) + if (check_intersection && intersects_segment_box(segment, box)) { return 0; } @@ -214,7 +231,7 @@ public: Strategy const& strategy, bool check_intersection = true) { - if (check_intersection && geometry::intersects(segment, box)) + if (check_intersection && intersects_segment_box(segment, box)) { return 0; } @@ -753,7 +770,8 @@ public: detail::assign_point_from_index<0>(segment, p[0]); detail::assign_point_from_index<1>(segment, p[1]); - if (geometry::equals(p[0], p[1])) + if (detail::equals::equals_point_point(p[0], p[1], + sb_strategy.get_equals_point_point_strategy())) { typedef typename boost::mpl::if_ < diff --git a/boost/geometry/algorithms/detail/envelope/areal.hpp b/boost/geometry/algorithms/detail/envelope/areal.hpp index 034a98c0ae..3c9b5c576c 100644 --- a/boost/geometry/algorithms/detail/envelope/areal.hpp +++ b/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 <typename EnvelopePolicy> struct envelope_polygon { template <typename Polygon, typename Box, typename Strategy> @@ -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 <typename Ring, typename CS_Tag> -struct envelope<Ring, ring_tag, CS_Tag> - : detail::envelope::envelope_range -{}; - template <typename Ring> -struct envelope<Ring, ring_tag, spherical_equatorial_tag> - : detail::envelope::envelope_linestring_or_ring_on_spheroid -{}; - -template <typename Ring> -struct envelope<Ring, ring_tag, geographic_tag> - : detail::envelope::envelope_linestring_or_ring_on_spheroid -{}; - - -template <typename Polygon, typename CS_Tag> -struct envelope<Polygon, polygon_tag, CS_Tag> - : detail::envelope::envelope_polygon - < - detail::envelope::envelope_range - > -{}; - -template <typename Polygon> -struct envelope<Polygon, polygon_tag, spherical_equatorial_tag> - : detail::envelope::envelope_polygon - < - detail::envelope::envelope_linestring_or_ring_on_spheroid - > +struct envelope<Ring, ring_tag> + : detail::envelope::envelope_range {}; template <typename Polygon> -struct envelope<Polygon, polygon_tag, geographic_tag> +struct envelope<Polygon, polygon_tag> : detail::envelope::envelope_polygon - < - detail::envelope::envelope_linestring_or_ring_on_spheroid - > -{}; - - -template <typename MultiPolygon, typename CS_Tag> -struct envelope<MultiPolygon, multi_polygon_tag, CS_Tag> - : detail::envelope::envelope_multi_range - < - detail::envelope::envelope_polygon - < - detail::envelope::envelope_range - > - > -{}; - -template <typename MultiPolygon> -struct envelope<MultiPolygon, multi_polygon_tag, spherical_equatorial_tag> - : detail::envelope::envelope_multi_range - < - detail::envelope::envelope_polygon - < - detail::envelope::envelope_linestring_or_ring_on_spheroid - > - > {}; template <typename MultiPolygon> -struct envelope<MultiPolygon, multi_polygon_tag, geographic_tag> +struct envelope<MultiPolygon, multi_polygon_tag> : detail::envelope::envelope_multi_range < detail::envelope::envelope_polygon - < - detail::envelope::envelope_linestring_or_ring_on_spheroid - > > {}; diff --git a/boost/geometry/algorithms/detail/envelope/box.hpp b/boost/geometry/algorithms/detail/envelope/box.hpp index cf039a292a..b085a14b9d 100644 --- a/boost/geometry/algorithms/detail/envelope/box.hpp +++ b/boost/geometry/algorithms/detail/envelope/box.hpp @@ -18,164 +18,34 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP -#include <cstddef> -#include <boost/geometry/core/cs.hpp> -#include <boost/geometry/core/coordinate_dimension.hpp> -#include <boost/geometry/core/coordinate_system.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/views/detail/indexed_point_view.hpp> - -#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> -#include <boost/geometry/algorithms/detail/normalize.hpp> -#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> - -#include <boost/geometry/algorithms/dispatch/envelope.hpp> +// For backward compatibility +#include <boost/geometry/strategies/cartesian/envelope_box.hpp> +#include <boost/geometry/strategies/spherical/envelope_box.hpp> 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 <typename BoxIn, typename BoxOut> - static inline void apply(BoxIn const& box_in, BoxOut& mbr) - { - detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in); - detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr); - - detail::conversion::point_to_point - < - detail::indexed_point_view<BoxIn const, Index>, - detail::indexed_point_view<BoxOut, Index>, - Dimension, - DimensionCount - >::apply(box_in_corner, mbr_corner); - } -}; -template -< - std::size_t Index, - std::size_t DimensionCount -> -struct envelope_indexed_box_on_spheroid +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch { - template <typename BoxIn, typename BoxOut> - 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<BoxIn const, Index> box_in_corner(box_in); - detail::indexed_point_view<BoxOut, Index> 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<BoxIn const, Index>, - detail::indexed_point_view<BoxOut, Index>, - 2, - DimensionCount - >::apply(box_in_corner, mbr_corner); - } -}; -struct envelope_box +template <typename Box> +struct envelope<Box, box_tag> { template<typename BoxIn, typename BoxOut, typename Strategy> - static inline void apply(BoxIn const& box_in, - BoxOut& mbr, - Strategy const&) + static inline void apply(BoxIn const& box_in, BoxOut& mbr, Strategy const& ) { - envelope_indexed_box - < - min_corner, 0, dimension<BoxIn>::value - >::apply(box_in, mbr); - - envelope_indexed_box - < - max_corner, 0, dimension<BoxIn>::value - >::apply(box_in, mbr); + Strategy::apply(box_in, mbr); } }; -struct envelope_box_on_spheroid -{ - template <typename BoxIn, typename BoxOut, typename Strategy> - 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<BoxIn>(box_in); - } - - envelope_indexed_box_on_spheroid - < - min_corner, dimension<BoxIn>::value - >::apply(box_in_normalized, mbr); - - envelope_indexed_box_on_spheroid - < - max_corner, dimension<BoxIn>::value - >::apply(box_in_normalized, mbr); - } -}; - - -}} // namespace detail::envelope -#endif // DOXYGEN_NO_DETAIL - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - - -template <typename Box> -struct envelope<Box, box_tag, cartesian_tag> - : detail::envelope::envelope_box -{}; - - -template <typename Box> -struct envelope<Box, box_tag, spherical_polar_tag> - : detail::envelope::envelope_box_on_spheroid -{}; - - -template <typename Box> -struct envelope<Box, box_tag, spherical_equatorial_tag> - : detail::envelope::envelope_box_on_spheroid -{}; - - -template <typename Box> -struct envelope<Box, box_tag, geographic_tag> - : detail::envelope::envelope_box_on_spheroid -{}; - - } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/boost/geometry/algorithms/detail/envelope/interface.hpp b/boost/geometry/algorithms/detail/envelope/interface.hpp index 8e9c35b395..28c815f4c2 100644 --- a/boost/geometry/algorithms/detail/envelope/interface.hpp +++ b/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 <boost/variant/apply_visitor.hpp> #include <boost/variant/static_visitor.hpp> #include <boost/variant/variant_fwd.hpp> -#include <boost/geometry/geometries/concepts/check.hpp> - #include <boost/geometry/algorithms/dispatch/envelope.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/tag.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/geometries/concepts/check.hpp> + #include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/envelope.hpp> -#include <boost/geometry/strategies/cartesian/envelope_segment.hpp> -#include <boost/geometry/strategies/spherical/envelope_segment.hpp> -#include <boost/geometry/strategies/geographic/envelope_segment.hpp> + +#include <boost/geometry/util/select_most_precise.hpp> + namespace boost { namespace geometry { @@ -57,13 +62,15 @@ struct envelope Box& box, default_strategy) { - typedef typename point_type<Geometry>::type point_type; - typedef typename coordinate_type<point_type>::type coordinate_type; - typedef typename strategy::envelope::services::default_strategy < - typename cs_tag<point_type>::type, - coordinate_type + typename tag<Geometry>::type, + typename cs_tag<Geometry>::type, + typename select_most_precise + < + typename coordinate_type<Geometry>::type, + typename coordinate_type<Box>::type + >::type >::type strategy_type; dispatch::envelope<Geometry>::apply(geometry, box, strategy_type()); diff --git a/boost/geometry/algorithms/detail/envelope/linear.hpp b/boost/geometry/algorithms/detail/envelope/linear.hpp index 7fa788b738..e2f05f2e3a 100644 --- a/boost/geometry/algorithms/detail/envelope/linear.hpp +++ b/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 <boost/geometry/core/cs.hpp> -#include <boost/geometry/core/tags.hpp> -#include <boost/geometry/iterators/segment_iterator.hpp> +#include <boost/geometry/core/tags.hpp> #include <boost/geometry/algorithms/detail/envelope/range.hpp> #include <boost/geometry/algorithms/dispatch/envelope.hpp> +// For backward compatibility +#include <boost/geometry/strategies/cartesian/envelope.hpp> +#include <boost/geometry/strategies/spherical/envelope.hpp> +#include <boost/geometry/strategies/geographic/envelope.hpp> namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace envelope -{ - -struct envelope_linestring_or_ring_on_spheroid -{ - template <typename LinestringRing, typename Box, typename Strategy> - 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 <typename Linestring, typename CS_Tag> -struct envelope<Linestring, linestring_tag, CS_Tag> - : detail::envelope::envelope_range -{}; - -template <typename Linestring> -struct envelope<Linestring, linestring_tag, spherical_equatorial_tag> - : detail::envelope::envelope_linestring_or_ring_on_spheroid -{}; - template <typename Linestring> -struct envelope<Linestring, linestring_tag, geographic_tag> - : detail::envelope::envelope_linestring_or_ring_on_spheroid +struct envelope<Linestring, linestring_tag> + : detail::envelope::envelope_range {}; -template <typename MultiLinestring, typename CS_Tag> -struct envelope - < - MultiLinestring, multi_linestring_tag, CS_Tag - > : detail::envelope::envelope_multi_range - < - detail::envelope::envelope_range - > -{}; - template <typename MultiLinestring> -struct envelope - < - MultiLinestring, multi_linestring_tag, spherical_equatorial_tag - > : detail::envelope::envelope_multi_range_on_spheroid +struct envelope<MultiLinestring, multi_linestring_tag> + : detail::envelope::envelope_multi_range < - detail::envelope::envelope_linestring_or_ring_on_spheroid + detail::envelope::envelope_range > {}; -template <typename MultiLinestring> -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/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/boost/geometry/algorithms/detail/envelope/multipoint.hpp index eef7563796..ce112e4d78 100644 --- a/boost/geometry/algorithms/detail/envelope/multipoint.hpp +++ b/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 <cstddef> -#include <algorithm> -#include <utility> -#include <vector> - -#include <boost/algorithm/minmax_element.hpp> -#include <boost/range.hpp> - -#include <boost/geometry/core/access.hpp> -#include <boost/geometry/core/assert.hpp> -#include <boost/geometry/core/coordinate_system.hpp> -#include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/util/math.hpp> -#include <boost/geometry/util/range.hpp> - -#include <boost/geometry/geometries/helper_geometry.hpp> - -#include <boost/geometry/algorithms/detail/normalize.hpp> - -#include <boost/geometry/algorithms/detail/envelope/box.hpp> -#include <boost/geometry/algorithms/detail/envelope/initialize.hpp> -#include <boost/geometry/algorithms/detail/envelope/range.hpp> -#include <boost/geometry/algorithms/detail/expand/point.hpp> - #include <boost/geometry/algorithms/dispatch/envelope.hpp> +// For backward compatibility +#include <boost/geometry/strategies/cartesian/envelope_multipoint.hpp> +#include <boost/geometry/strategies/spherical/envelope_multipoint.hpp> namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace envelope -{ - - -class envelope_multipoint_on_spheroid -{ -private: - template <std::size_t Dim> - struct coordinate_less - { - template <typename Point> - inline bool operator()(Point const& point1, Point const& point2) const - { - return math::smaller(geometry::get<Dim>(point1), - geometry::get<Dim>(point2)); - } - }; - - template <typename Constants, typename MultiPoint, typename OutputIterator> - static inline void analyze_point_coordinates(MultiPoint const& multipoint, - bool& has_south_pole, - bool& has_north_pole, - OutputIterator oit) - { - typedef typename boost::range_value<MultiPoint>::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<point_type>(*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 <typename SortedRange, typename Value> - 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<iterator_type, iterator_type> 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<Iterator, Iterator> 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 <typename MultiPoint, typename Box, typename Strategy> - static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& strategy) - { - typedef typename point_type<MultiPoint>::type point_type; - typedef typename coordinate_type<MultiPoint>::type coordinate_type; - typedef typename boost::range_iterator - < - MultiPoint const - >::type iterator_type; - - typedef math::detail::constants_on_spheroid - < - coordinate_type, - typename coordinate_system<MultiPoint>::type::units - > constants; - - if (boost::empty(multipoint)) - { - initialize<Box, 0, dimension<Box>::value>::apply(mbr); - return; - } - - initialize<Box, 0, 2>::apply(mbr); - - if (boost::size(multipoint) == 1) - { - return dispatch::envelope - < - typename boost::range_value<MultiPoint>::type - >::apply(range::front(multipoint), mbr, strategy); - } - - // analyze the points and put the non-pole ones in the - // points vector - std::vector<point_type> points; - bool has_north_pole = false, has_south_pole = false; - - analyze_point_coordinates<constants>(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<constants>(points, - coordinate_less<0>(), - lon_min, - lon_max); - - get_min_max_latitudes<constants>(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<MultiPoint>::type::units - >::type helper_box_type; - - helper_box_type helper_mbr; - - geometry::set<min_corner, 0>(helper_mbr, lon_min); - geometry::set<min_corner, 1>(helper_mbr, lat_min); - geometry::set<max_corner, 0>(helper_mbr, lon_max); - geometry::set<max_corner, 1>(helper_mbr, lat_max); - - // now transform to output MBR (per index) - envelope_indexed_box_on_spheroid<min_corner, 2>::apply(helper_mbr, mbr); - envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr); - - // compute envelope for higher coordinates - iterator_type it = boost::begin(multipoint); - envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr, strategy); - - for (++it; it != boost::end(multipoint); ++it) - { - detail::expand::point_loop - < - 2, dimension<Box>::value - >::apply(mbr, *it, strategy); - } - } -}; - - -}} // namespace detail::envelope -#endif // DOXYGEN_NO_DETAIL - - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { -template <typename MultiPoint, typename CSTag> -struct envelope<MultiPoint, multi_point_tag, CSTag> - : detail::envelope::envelope_range -{}; - -template <typename MultiPoint> -struct envelope<MultiPoint, multi_point_tag, spherical_equatorial_tag> - : detail::envelope::envelope_multipoint_on_spheroid -{}; - template <typename MultiPoint> -struct envelope<MultiPoint, multi_point_tag, geographic_tag> - : detail::envelope::envelope_multipoint_on_spheroid -{}; +struct envelope<MultiPoint, multi_point_tag> +{ + template <typename Box, typename Strategy> + static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& ) + { + Strategy::apply(multipoint, mbr); + } +}; } // namespace dispatch diff --git a/boost/geometry/algorithms/detail/envelope/point.hpp b/boost/geometry/algorithms/detail/envelope/point.hpp index 86e73f3aa3..164274a280 100644 --- a/boost/geometry/algorithms/detail/envelope/point.hpp +++ b/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 <cstddef> - -#include <boost/geometry/core/access.hpp> -#include <boost/geometry/core/cs.hpp> -#include <boost/geometry/core/coordinate_dimension.hpp> -#include <boost/geometry/core/coordinate_system.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/views/detail/indexed_point_view.hpp> - -#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> -#include <boost/geometry/algorithms/detail/normalize.hpp> - -#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> - #include <boost/geometry/algorithms/dispatch/envelope.hpp> +// For backward compatibility +#include <boost/geometry/strategies/cartesian/envelope_point.hpp> +#include <boost/geometry/strategies/spherical/envelope_point.hpp> + namespace boost { namespace geometry { @@ -44,53 +35,12 @@ namespace detail { namespace envelope { -template <std::size_t Dimension, std::size_t DimensionCount> -struct envelope_one_point +struct envelope_point { - template <std::size_t Index, typename Point, typename Box> - static inline void apply(Point const& point, Box& mbr) - { - detail::indexed_point_view<Box, Index> box_corner(mbr); - detail::conversion::point_to_point - < - Point, - detail::indexed_point_view<Box, Index>, - Dimension, - DimensionCount - >::apply(point, box_corner); - } - template <typename Point, typename Box, typename Strategy> - static inline void apply(Point const& point, Box& mbr, Strategy const&) + static inline void apply(Point const& point, Box& mbr, Strategy const& ) { - apply<min_corner>(point, mbr); - apply<max_corner>(point, mbr); - } -}; - - -struct envelope_point_on_spheroid -{ - template<typename Point, typename Box, typename Strategy> - static inline void apply(Point const& point, Box& mbr, Strategy const& strategy) - { - Point normalized_point = detail::return_normalized<Point>(point); - - typename point_type<Box>::type box_point; - - // transform units of input point to units of a box point - transform_units(normalized_point, box_point); - - geometry::set<min_corner, 0>(mbr, geometry::get<0>(box_point)); - geometry::set<min_corner, 1>(mbr, geometry::get<1>(box_point)); - - geometry::set<max_corner, 0>(mbr, geometry::get<0>(box_point)); - geometry::set<max_corner, 1>(mbr, geometry::get<1>(box_point)); - - envelope_one_point - < - 2, dimension<Point>::value - >::apply(normalized_point, mbr, strategy); + Strategy::apply(point, mbr); } }; @@ -104,26 +54,8 @@ namespace dispatch template <typename Point> -struct envelope<Point, point_tag, cartesian_tag> - : detail::envelope::envelope_one_point<0, dimension<Point>::value> -{}; - - -template <typename Point> -struct envelope<Point, point_tag, spherical_polar_tag> - : detail::envelope::envelope_point_on_spheroid -{}; - - -template <typename Point> -struct envelope<Point, point_tag, spherical_equatorial_tag> - : detail::envelope::envelope_point_on_spheroid -{}; - - -template <typename Point> -struct envelope<Point, point_tag, geographic_tag> - : detail::envelope::envelope_point_on_spheroid +struct envelope<Point, point_tag> + : detail::envelope::envelope_point {}; diff --git a/boost/geometry/algorithms/detail/envelope/range.hpp b/boost/geometry/algorithms/detail/envelope/range.hpp index b5591f61ab..2d33600d0f 100644 --- a/boost/geometry/algorithms/detail/envelope/range.hpp +++ b/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 <iterator> #include <vector> -#include <boost/range.hpp> - -#include <boost/geometry/core/coordinate_dimension.hpp> - -#include <boost/geometry/util/range.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> #include <boost/geometry/algorithms/is_empty.hpp> #include <boost/geometry/algorithms/detail/envelope/initialize.hpp> -#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp> - #include <boost/geometry/algorithms/detail/expand/box.hpp> #include <boost/geometry/algorithms/detail/expand/point.hpp> #include <boost/geometry/algorithms/detail/expand/segment.hpp> -#include <boost/geometry/algorithms/dispatch/envelope.hpp> - +#include <boost/geometry/core/coordinate_dimension.hpp> namespace boost { namespace geometry { @@ -53,7 +48,7 @@ namespace detail { namespace envelope struct envelope_range { template <typename Iterator, typename Box, typename Strategy> - 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<Box, 0, dimension<Box>::value>::apply(mbr); - Iterator it = first; if (it != last) { // initialize box with first element in range - dispatch::envelope<value_type>::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<Box, value_type>::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 <typename Range, typename Box, typename Strategy> 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<Box, Box>::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<Box, 0, dimension<Box>::value>::apply(mbr); - } + apply(boost::begin(multirange), boost::end(multirange), mbr, strategy); } -}; - -// implementation for multi-range on a spheroid (longitude is periodic) -template <typename EnvelopePolicy> -struct envelope_multi_range_on_spheroid -{ - template <typename MultiRange, typename Box, typename Strategy> - static inline void apply(MultiRange const& multirange, + template <typename Iter, typename Box, typename Strategy> + 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<Box> boxes; - for (iterator_type it = boost::begin(multirange); - it != boost::end(multirange); - ++it) + typename Strategy::template multi_state<Box> 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<Box, 0, dimension<Box>::value>::apply(mbr); - } - + state.result(mbr); } }; diff --git a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp index 92d1fe3959..28e76c4458 100644 --- a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp +++ b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp @@ -20,17 +20,20 @@ #include <boost/range.hpp> +#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> +#include <boost/geometry/algorithms/detail/max_interval_gap.hpp> +#include <boost/geometry/algorithms/detail/expand/indexed.hpp> + #include <boost/geometry/core/access.hpp> #include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/coordinate_system.hpp> #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/util/math.hpp> +#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> #include <boost/geometry/util/range.hpp> -#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> -#include <boost/geometry/algorithms/detail/max_interval_gap.hpp> -#include <boost/geometry/algorithms/detail/expand/indexed.hpp> +#include <boost/geometry/views/detail/indexed_point_view.hpp> namespace boost { namespace geometry @@ -151,10 +154,8 @@ struct envelope_range_of_longitudes template <std::size_t Dimension, std::size_t DimensionCount> struct envelope_range_of_boxes_by_expansion { - template <typename RangeOfBoxes, typename Box, typename Strategy> - static inline void apply(RangeOfBoxes const& range_of_boxes, - Box& mbr, - Strategy const& strategy) + template <typename RangeOfBoxes, typename Box> + static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr) { typedef typename boost::range_value<RangeOfBoxes>::type box_type; @@ -198,14 +199,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 +226,14 @@ struct envelope_range_of_boxes } }; - template <typename RangeOfBoxes, typename Box, typename Strategy> - static inline void apply(RangeOfBoxes const& range_of_boxes, - Box& mbr, - Strategy const& strategy) + template <typename RangeOfBoxes, typename Box> + 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<RangeOfBoxes>::type box_type; typedef typename coordinate_type<box_type>::type coordinate_type; - typedef typename coordinate_system<box_type>::type::units units_type; + typedef typename detail::cs_angular_units<box_type>::type units_type; typedef typename boost::range_iterator < RangeOfBoxes const @@ -326,7 +325,7 @@ struct envelope_range_of_boxes envelope_range_of_boxes_by_expansion < 2, dimension<Box>::value - >::apply(range_of_boxes, mbr, strategy); + >::apply(range_of_boxes, mbr); } }; diff --git a/boost/geometry/algorithms/detail/envelope/segment.hpp b/boost/geometry/algorithms/detail/envelope/segment.hpp index cfa139a087..af79f34508 100644 --- a/boost/geometry/algorithms/detail/envelope/segment.hpp +++ b/boost/geometry/algorithms/detail/envelope/segment.hpp @@ -19,33 +19,17 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP #include <cstddef> -#include <utility> -#include <boost/core/ignore_unused.hpp> -#include <boost/numeric/conversion/cast.hpp> - -#include <boost/geometry/core/assert.hpp> -#include <boost/geometry/core/coordinate_system.hpp> -#include <boost/geometry/core/coordinate_type.hpp> -#include <boost/geometry/core/cs.hpp> -#include <boost/geometry/core/point_type.hpp> -#include <boost/geometry/core/radian_access.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/util/math.hpp> - -#include <boost/geometry/geometries/helper_geometry.hpp> - -#include <boost/geometry/formulas/meridian_segment.hpp> -#include <boost/geometry/formulas/vertex_latitude.hpp> - #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp> -#include <boost/geometry/algorithms/detail/envelope/point.hpp> -#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> -#include <boost/geometry/algorithms/detail/expand/point.hpp> - #include <boost/geometry/algorithms/dispatch/envelope.hpp> +// For backward compatibility +#include <boost/geometry/strategies/cartesian/envelope_segment.hpp> +#include <boost/geometry/strategies/spherical/envelope_segment.hpp> +#include <boost/geometry/strategies/geographic/envelope_segment.hpp> + namespace boost { namespace geometry { @@ -53,385 +37,6 @@ namespace boost { namespace geometry namespace detail { namespace envelope { -template <typename CalculationType, typename CS_Tag> -struct envelope_segment_call_vertex_latitude -{ - template <typename T1, typename T2, typename Strategy> - static inline CalculationType apply(T1 const& lat1, - T2 const& alp1, - Strategy const& ) - { - return geometry::formula::vertex_latitude<CalculationType, CS_Tag> - ::apply(lat1, alp1); - } -}; - -template <typename CalculationType> -struct envelope_segment_call_vertex_latitude<CalculationType, geographic_tag> -{ - template <typename T1, typename T2, typename Strategy> - static inline CalculationType apply(T1 const& lat1, - T2 const& alp1, - Strategy const& strategy) - { - return geometry::formula::vertex_latitude<CalculationType, geographic_tag> - ::apply(lat1, alp1, strategy.model()); - } -}; - -template <typename Units, typename CS_Tag> -struct envelope_segment_convert_polar -{ - template <typename T> - static inline void pre(T & , T & ) {} - - template <typename T> - static inline void post(T & , T & ) {} -}; - -template <typename Units> -struct envelope_segment_convert_polar<Units, spherical_polar_tag> -{ - template <typename T> - static inline void pre(T & lat1, T & lat2) - { - lat1 = math::latitude_convert_ep<Units>(lat1); - lat2 = math::latitude_convert_ep<Units>(lat2); - } - - template <typename T> - static inline void post(T & lat1, T & lat2) - { - lat1 = math::latitude_convert_ep<Units>(lat1); - lat2 = math::latitude_convert_ep<Units>(lat2); - std::swap(lat1, lat2); - } -}; - -template <typename CS_Tag> -class envelope_segment_impl -{ -private: - - // degrees or radians - template <typename CalculationType> - static inline void swap(CalculationType& lon1, - CalculationType& lat1, - CalculationType& lon2, - CalculationType& lat2) - { - std::swap(lon1, lon2); - std::swap(lat1, lat2); - } - - // radians - template <typename CalculationType> - 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<CalculationType>(); - - return (a1 < a2) - ? (a1 < pi_half && pi_half < a2) - : (a1 > pi_half && pi_half > a2); - } - - // radians or degrees - template <typename Units, typename CoordinateType> - 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 <typename Units, typename CalculationType, typename Strategy> - 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<Units>(lat1); - CalculationType lat2_rad = math::as_radian<Units>(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 - <CalculationType, CS_Tag>::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<Units>(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<Units>(lat_max_rad); - - if (lat2 < lat_max) - { - lat2 = lat_max; - } - } - } - } - - template <typename Units, typename CalculationType> - 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<Units>(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<Box>::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<box_coordinate_type>(lon1)); - - geometry::set - < - min_corner, 1 - >(helper_mbr, boost::numeric_cast<box_coordinate_type>(lat1)); - - geometry::set - < - max_corner, 0 - >(helper_mbr, boost::numeric_cast<box_coordinate_type>(lon2)); - - geometry::set - < - max_corner, 1 - >(helper_mbr, boost::numeric_cast<box_coordinate_type>(lat2)); - - transform_units(helper_mbr, mbr); - } - - - template <typename Units, typename CalculationType, typename Strategy> - static inline void apply(CalculationType& lon1, - CalculationType& lat1, - CalculationType& lon2, - CalculationType& lat2, - Strategy const& strategy) - { - special_cases<Units>(lon1, lat1, lon2, lat2); - - CalculationType lon1_rad = math::as_radian<Units>(lon1); - CalculationType lat1_rad = math::as_radian<Units>(lat1); - CalculationType lon2_rad = math::as_radian<Units>(lon2); - CalculationType lat2_rad = math::as_radian<Units>(lat2); - CalculationType alp1, alp2; - strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, alp1, alp2); - - compute_box_corners<Units>(lon1, lat1, lon2, lat2, alp1, alp2, strategy); - } - - template <typename Units, typename CalculationType, typename Strategy> - static inline void apply(CalculationType& lon1, - CalculationType& lat1, - CalculationType& lon2, - CalculationType& lat2, - Strategy const& strategy, - CalculationType alp1) - { - special_cases<Units>(lon1, lat1, lon2, lat2); - - CalculationType lon1_rad = math::as_radian<Units>(lon1); - CalculationType lat1_rad = math::as_radian<Units>(lat1); - CalculationType lon2_rad = math::as_radian<Units>(lon2); - CalculationType lat2_rad = math::as_radian<Units>(lat2); - CalculationType alp2; - strategy.apply_reverse(lon1_rad, lat1_rad, lon2_rad, lat2_rad, alp2); - - compute_box_corners<Units>(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<Units, typename cs_tag<Box>::type> convert_polar; - - convert_polar::pre(lat1, lat2); - - apply<Units>(lon1, lat1, lon2, lat2, strategy); - - convert_polar::post(lat1, lat2); - - create_box<Units>(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<Units, typename cs_tag<Box>::type> convert_polar; - - convert_polar::pre(lat1, lat2); - - apply<Units>(lon1, lat1, lon2, lat2, strategy, alp1); - - convert_polar::post(lat1, lat2); - - create_box<Units>(lon1, lat1, lon2, lat2, mbr); - } -}; - -template <std::size_t Dimension, std::size_t DimensionCount> -struct envelope_one_segment -{ - template<typename Point, typename Box, typename Strategy> - static inline void apply(Point const& p1, - Point const& p2, - Box& mbr, - Strategy const& strategy) - { - envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr, strategy); - detail::expand::point_loop - < - Dimension, - DimensionCount - >::apply(mbr, p2, strategy); - } -}; - - template <std::size_t DimensionCount> 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 <typename Segment, typename Box, typename Strategy> diff --git a/boost/geometry/algorithms/detail/equals/implementation.hpp b/boost/geometry/algorithms/detail/equals/implementation.hpp index 310059a427..f39ae0b8b7 100644 --- a/boost/geometry/algorithms/detail/equals/implementation.hpp +++ b/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 <typename Point1, typename Point2, typename Strategy> - 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<DimensionCount, DimensionCount> struct segment_segment { template <typename Segment1, typename Segment2, typename Strategy> - 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 const, 0>(segment1), - indexed_point_view<Segment2 const, 0>(segment2) ) + indexed_point_view<Segment2 const, 0>(segment2), + pt_pt_strategy) ? equals::equals_point_point( indexed_point_view<Segment1 const, 1>(segment1), - indexed_point_view<Segment2 const, 1>(segment2) ) + indexed_point_view<Segment2 const, 1>(segment2), + pt_pt_strategy) : ( equals::equals_point_point( indexed_point_view<Segment1 const, 0>(segment1), - indexed_point_view<Segment2 const, 1>(segment2) ) + indexed_point_view<Segment2 const, 1>(segment2), + pt_pt_strategy) && equals::equals_point_point( indexed_point_view<Segment1 const, 1>(segment1), - indexed_point_view<Segment2 const, 0>(segment2) ) + indexed_point_view<Segment2 const, 0>(segment2), + pt_pt_strategy) ); } }; diff --git a/boost/geometry/algorithms/detail/equals/point_point.hpp b/boost/geometry/algorithms/detail/equals/point_point.hpp index 12daa85e9d..06a784284e 100644 --- a/boost/geometry/algorithms/detail/equals/point_point.hpp +++ b/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 <boost/geometry/algorithms/detail/disjoint/point_point.hpp> - 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 <typename Point1, typename Point2> -inline bool equals_point_point(Point1 const& point1, Point2 const& point2) +template <typename Point1, typename Point2, typename Strategy> +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/boost/geometry/algorithms/detail/expand/box.hpp b/boost/geometry/algorithms/detail/expand/box.hpp index 485f4d25e6..41571dba6a 100644 --- a/boost/geometry/algorithms/detail/expand/box.hpp +++ b/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 <cstddef> -#include <algorithm> -#include <boost/mpl/assert.hpp> -#include <boost/type_traits/is_same.hpp> +#include <boost/geometry/algorithms/dispatch/expand.hpp> -#include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/algorithms/detail/envelope/box.hpp> -#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp> - -#include <boost/geometry/algorithms/detail/expand/indexed.hpp> - -#include <boost/geometry/algorithms/dispatch/expand.hpp> +// For backward compatibility +#include <boost/geometry/strategies/cartesian/expand_box.hpp> +#include <boost/geometry/strategies/spherical/expand_box.hpp> namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace expand -{ - - -struct box_on_spheroid -{ - template <typename BoxOut, typename BoxIn, typename Strategy> - 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<CSTagOut, CSTag>())); + template <typename Strategy> + static inline void apply(BoxOut& box_out, + BoxIn const& box_in, + Strategy const& ) + { + Strategy::apply(box_out, box_in); + } }; -template <typename BoxOut, typename BoxIn> -struct expand - < - BoxOut, BoxIn, - box_tag, box_tag, - cartesian_tag, cartesian_tag - > : detail::expand::expand_indexed - < - 0, dimension<BoxIn>::value - > -{}; - -template <typename BoxOut, typename BoxIn> -struct expand - < - BoxOut, BoxIn, - box_tag, box_tag, - spherical_equatorial_tag, spherical_equatorial_tag - > : detail::expand::box_on_spheroid -{}; - -template <typename BoxOut, typename BoxIn> -struct expand - < - BoxOut, BoxIn, - box_tag, box_tag, - spherical_polar_tag, spherical_polar_tag - > : detail::expand::box_on_spheroid -{}; - -template <typename BoxOut, typename BoxIn> -struct expand - < - BoxOut, BoxIn, - box_tag, box_tag, - geographic_tag, geographic_tag - > : detail::expand::box_on_spheroid -{}; } // namespace dispatch diff --git a/boost/geometry/algorithms/detail/expand/indexed.hpp b/boost/geometry/algorithms/detail/expand/indexed.hpp index fe7ee4f781..08463689de 100644 --- a/boost/geometry/algorithms/detail/expand/indexed.hpp +++ b/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 <typename Box, typename Geometry, typename Strategy> - static inline void apply(Box& box, Geometry const& source, Strategy const& strategy) + template <typename Box, typename Geometry> + 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 <typename Box, typename Geometry, typename Strategy> - static inline void apply(Box&, Geometry const&, Strategy const&) {} + template <typename Box, typename Geometry> + static inline void apply(Box&, Geometry const&) {} }; @@ -96,20 +96,18 @@ struct indexed_loop template <std::size_t Dimension, std::size_t DimensionCount> struct expand_indexed { - template <typename Box, typename Geometry, typename Strategy> - static inline void apply(Box& box, - Geometry const& geometry, - Strategy const& strategy) + template <typename Box, typename Geometry> + 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/boost/geometry/algorithms/detail/expand/interface.hpp b/boost/geometry/algorithms/detail/expand/interface.hpp index 5aacd8e72a..28241b379b 100644 --- a/boost/geometry/algorithms/detail/expand/interface.hpp +++ b/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 <boost/variant/static_visitor.hpp> #include <boost/variant/variant_fwd.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/tag.hpp> +#include <boost/geometry/core/tags.hpp> + #include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/algorithms/dispatch/expand.hpp> #include <boost/geometry/strategies/default_strategy.hpp> +#include <boost/geometry/strategies/expand.hpp> -#include <boost/geometry/strategies/envelope.hpp> -#include <boost/geometry/strategies/cartesian/envelope_segment.hpp> -#include <boost/geometry/strategies/spherical/envelope_segment.hpp> -#include <boost/geometry/strategies/geographic/envelope_segment.hpp> namespace boost { namespace geometry { @@ -58,14 +60,11 @@ struct expand Geometry const& geometry, default_strategy) { - typedef typename point_type<Geometry>::type point_type; - typedef typename coordinate_type<point_type>::type coordinate_type; - - typedef typename strategy::envelope::services::default_strategy - < - typename cs_tag<point_type>::type, - coordinate_type - >::type strategy_type; + typedef typename strategy::expand::services::default_strategy + < + typename tag<Geometry>::type, + typename cs_tag<Geometry>::type + >::type strategy_type; dispatch::expand<Box, Geometry>::apply(box, geometry, strategy_type()); } diff --git a/boost/geometry/algorithms/detail/expand/point.hpp b/boost/geometry/algorithms/detail/expand/point.hpp index 88ebe75db7..d4a9097cb3 100644 --- a/boost/geometry/algorithms/detail/expand/point.hpp +++ b/boost/geometry/algorithms/detail/expand/point.hpp @@ -22,202 +22,19 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP -#include <cstddef> -#include <algorithm> -#include <functional> -#include <boost/mpl/assert.hpp> -#include <boost/type_traits/is_same.hpp> +#include <boost/geometry/algorithms/dispatch/expand.hpp> -#include <boost/geometry/core/access.hpp> -#include <boost/geometry/core/coordinate_dimension.hpp> -#include <boost/geometry/core/coordinate_system.hpp> -#include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/util/is_inverse_spheroidal_coordinates.hpp> -#include <boost/geometry/util/math.hpp> -#include <boost/geometry/util/select_coordinate_type.hpp> - -#include <boost/geometry/algorithms/detail/normalize.hpp> -#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> +// For backward compatibility +#include <boost/geometry/strategies/cartesian/expand_point.hpp> +#include <boost/geometry/strategies/spherical/expand_point.hpp> -#include <boost/geometry/algorithms/dispatch/expand.hpp> namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace expand -{ - - -template <std::size_t Dimension, std::size_t DimensionCount> -struct point_loop -{ - template <typename Box, typename Point, typename Strategy> - static inline void apply(Box& box, Point const& source, Strategy const& strategy) - { - typedef typename select_coordinate_type - < - Point, Box - >::type coordinate_type; - - std::less<coordinate_type> less; - std::greater<coordinate_type> greater; - - coordinate_type const coord = get<Dimension>(source); - - if (less(coord, get<min_corner, Dimension>(box))) - { - set<min_corner, Dimension>(box, coord); - } - - if (greater(coord, get<max_corner, Dimension>(box))) - { - set<max_corner, Dimension>(box, coord); - } - - point_loop<Dimension + 1, DimensionCount>::apply(box, source, strategy); - } -}; - - -template <std::size_t DimensionCount> -struct point_loop<DimensionCount, DimensionCount> -{ - template <typename Box, typename Point, typename Strategy> - static inline void apply(Box&, Point const&, Strategy const&) {} -}; - - -// implementation for the spherical and geographic coordinate systems -template <std::size_t DimensionCount, bool IsEquatorial = true> -struct point_loop_on_spheroid -{ - template <typename Box, typename Point, typename Strategy> - static inline void apply(Box& box, - Point const& point, - Strategy const& strategy) - { - typedef typename point_type<Box>::type box_point_type; - typedef typename coordinate_type<Box>::type box_coordinate_type; - typedef typename coordinate_system<Box>::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>(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<min_corner, 0>(box, geometry::get_as_radian<0>(p_normalized)); - geometry::set_from_radian<min_corner, 1>(box, geometry::get_as_radian<1>(p_normalized)); - geometry::set_from_radian<max_corner, 0>(box, geometry::get_as_radian<0>(p_normalized)); - geometry::set_from_radian<max_corner, 1>(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<Box>::type - b_lon_min = geometry::get<min_corner, 0>(box), - b_lat_min = geometry::get<min_corner, 1>(box), - b_lon_max = geometry::get<max_corner, 0>(box), - b_lat_max = geometry::get<max_corner, 1>(box); - - if (math::is_latitude_pole<units_type, IsEquatorial>(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<min_corner, 1>(box, (std::min)(p_lat, b_lat_min)); - geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max)); - return; - } - - if (math::equals(b_lat_min, b_lat_max) - && math::is_latitude_pole<units_type, IsEquatorial>(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<min_corner, 0>(box, p_lon); - geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min)); - geometry::set<max_corner, 0>(box, p_lon); - geometry::set<max_corner, 1>(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<min_corner, 0>(box, b_lon_min); - geometry::set<min_corner, 1>(box, b_lat_min); - geometry::set<max_corner, 0>(box, b_lon_max); - geometry::set<max_corner, 1>(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 { @@ -226,74 +43,24 @@ namespace dispatch // Box + point -> new box containing also point template < - typename BoxOut, typename Point, - typename CSTagOut, typename CSTag + typename BoxOut, typename Point > struct expand < BoxOut, Point, - box_tag, point_tag, - CSTagOut, CSTag + box_tag, point_tag > { - BOOST_MPL_ASSERT_MSG((false), - NOT_IMPLEMENTED_FOR_THESE_COORDINATE_SYSTEMS, - (types<CSTagOut, CSTag>())); + template <typename Strategy> + static inline void apply(BoxOut& box, + Point const& point, + Strategy const& ) + { + Strategy::apply(box, point); + } }; -template <typename BoxOut, typename Point> -struct expand - < - BoxOut, Point, - box_tag, point_tag, - cartesian_tag, cartesian_tag - > : detail::expand::point_loop - < - 0, dimension<Point>::value - > -{}; - -template <typename BoxOut, typename Point> -struct expand - < - BoxOut, Point, - box_tag, point_tag, - spherical_equatorial_tag, spherical_equatorial_tag - > : detail::expand::point_loop_on_spheroid - < - dimension<Point>::value - > -{}; - -template <typename BoxOut, typename Point> -struct expand - < - BoxOut, Point, - box_tag, point_tag, - spherical_polar_tag, spherical_polar_tag - > : detail::expand::point_loop_on_spheroid - < - dimension<Point>::value, - false - > -{}; - -template -< - typename BoxOut, typename Point -> -struct expand - < - BoxOut, Point, - box_tag, point_tag, - geographic_tag, geographic_tag - > : detail::expand::point_loop_on_spheroid - < - dimension<Point>::value - > -{}; - } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/boost/geometry/algorithms/detail/expand/segment.hpp b/boost/geometry/algorithms/detail/expand/segment.hpp index dddd3d2c7a..3f6f196026 100644 --- a/boost/geometry/algorithms/detail/expand/segment.hpp +++ b/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,57 +19,21 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP -#include <boost/mpl/assert.hpp> -#include <boost/type_traits/is_same.hpp> -#include <boost/geometry/core/coordinate_dimension.hpp> -#include <boost/geometry/core/tags.hpp> - -#include <boost/geometry/algorithms/detail/envelope/box.hpp> -#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp> -#include <boost/geometry/algorithms/detail/envelope/segment.hpp> - -#include <boost/geometry/algorithms/detail/expand/indexed.hpp> +#include <boost/core/ignore_unused.hpp> #include <boost/geometry/algorithms/dispatch/expand.hpp> +#include <boost/geometry/core/tags.hpp> -namespace boost { namespace geometry -{ +// For backward compatibility +#include <boost/geometry/strategies/cartesian/expand_segment.hpp> +#include <boost/geometry/strategies/geographic/expand_segment.hpp> +#include <boost/geometry/strategies/spherical/expand_segment.hpp> -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace expand -{ -struct segment +namespace boost { namespace geometry { - template <typename Box, typename Segment, typename Strategy> - static inline void apply(Box& box, - Segment const& segment, - Strategy const& strategy) - { - Box mbrs[2]; - - // compute the envelope of the segment - typename point_type<Segment>::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<Segment>::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 @@ -77,62 +41,24 @@ namespace dispatch template < - typename Box, typename Segment, - typename CSTagOut, typename CSTag + typename Box, typename Segment > struct expand < Box, Segment, - box_tag, segment_tag, - CSTagOut, CSTag + box_tag, segment_tag > { - BOOST_MPL_ASSERT_MSG((false), - NOT_IMPLEMENTED_FOR_THESE_COORDINATE_SYSTEMS, - (types<CSTagOut, CSTag>())); + template <typename Strategy> + static inline void apply(Box& box, + Segment const& segment, + Strategy const& strategy) + { + boost::ignore_unused(strategy); + strategy.apply(box, segment); + } }; -template -< - typename Box, typename Segment -> -struct expand - < - Box, Segment, - box_tag, segment_tag, - cartesian_tag, cartesian_tag - > : detail::expand::expand_indexed - < - 0, dimension<Segment>::value - > -{}; - -template <typename Box, typename Segment> -struct expand - < - Box, Segment, - box_tag, segment_tag, - spherical_polar_tag, spherical_polar_tag - > : detail::expand::segment -{}; - -template <typename Box, typename Segment> -struct expand - < - Box, Segment, - box_tag, segment_tag, - spherical_equatorial_tag, spherical_equatorial_tag - > : detail::expand::segment -{}; - -template <typename Box, typename Segment> -struct expand - < - Box, Segment, - box_tag, segment_tag, - geographic_tag, geographic_tag - > : detail::expand::segment -{}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH diff --git a/boost/geometry/algorithms/detail/extreme_points.hpp b/boost/geometry/algorithms/detail/extreme_points.hpp index 607997813c..842c441f41 100644 --- a/boost/geometry/algorithms/detail/extreme_points.hpp +++ b/boost/geometry/algorithms/detail/extreme_points.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2013 Mateusz Loskot, London, UK. // Copyright (c) 2013-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 @@ -25,6 +25,7 @@ #include <boost/geometry/algorithms/detail/interior_iterator.hpp> #include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/point_order.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/ring_type.hpp> #include <boost/geometry/core/tags.hpp> diff --git a/boost/geometry/algorithms/detail/get_left_turns.hpp b/boost/geometry/algorithms/detail/get_left_turns.hpp index e9f6a50859..1fec47a01f 100644 --- a/boost/geometry/algorithms/detail/get_left_turns.hpp +++ b/boost/geometry/algorithms/detail/get_left_turns.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2012-2014 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 @@ -14,11 +14,14 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP +#include <set> +#include <vector> + #include <boost/geometry/core/assert.hpp> -#include <boost/geometry/arithmetic/arithmetic.hpp> #include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> +#include <boost/geometry/arithmetic/arithmetic.hpp> #include <boost/geometry/iterators/closing_iterator.hpp> #include <boost/geometry/iterators/ever_circling_iterator.hpp> #include <boost/geometry/strategies/side.hpp> diff --git a/boost/geometry/algorithms/detail/get_max_size.hpp b/boost/geometry/algorithms/detail/get_max_size.hpp index 8ac43e78b8..f4741824a7 100644 --- a/boost/geometry/algorithms/detail/get_max_size.hpp +++ b/boost/geometry/algorithms/detail/get_max_size.hpp @@ -5,6 +5,11 @@ // Copyright (c) 2014 Mateusz Loskot, London, UK. // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. +// 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) @@ -12,10 +17,10 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP - #include <cstddef> #include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/util/math.hpp> namespace boost { namespace geometry diff --git a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp index f08e70242c..1d3bda191a 100644 --- a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp +++ b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp @@ -1,8 +1,9 @@ // 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 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 @@ -19,6 +20,7 @@ #include <boost/core/addressof.hpp> +#include <boost/geometry/algorithms/detail/signed_size_type.hpp> #include <boost/geometry/core/assert.hpp> #include <boost/geometry/policies/compare.hpp> @@ -221,9 +223,11 @@ public: return false; } +#ifdef BOOST_GEOMETRY_TEST_DEBUG template <typename OStream, typename TP> friend inline void debug_print_complement_graph(OStream&, complement_graph<TP> const&); +#endif // BOOST_GEOMETRY_TEST_DEBUG private: std::size_t m_num_rings, m_num_turns; diff --git a/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp b/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp index 60f597e296..749dd3fc25 100644 --- a/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp +++ b/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp @@ -1,8 +1,9 @@ // 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 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 @@ -14,6 +15,8 @@ #include <iostream> #endif +#include <boost/geometry/algorithms/detail/is_valid/complement_graph.hpp> + namespace boost { namespace geometry { diff --git a/boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp b/boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp index a10e0fe596..b072f7ad43 100644 --- a/boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp +++ b/boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp @@ -1,8 +1,9 @@ // 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 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 @@ -12,11 +13,10 @@ #ifdef GEOMETRY_TEST_DEBUG #include <iostream> +#endif #include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tags.hpp> -#endif - namespace boost { namespace geometry { diff --git a/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp b/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp index 6e6823d62f..cf3a41069a 100644 --- a/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp +++ b/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// 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 @@ -15,15 +15,17 @@ #include <boost/type_traits/is_floating_point.hpp> +#include <boost/geometry/algorithms/detail/check_iterator_range.hpp> +#include <boost/geometry/algorithms/validity_failure_type.hpp> + #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/point_type.hpp> -#include <boost/geometry/util/has_non_finite_coordinate.hpp> - #include <boost/geometry/iterators/point_iterator.hpp> + #include <boost/geometry/views/detail/indexed_point_view.hpp> -#include <boost/geometry/algorithms/detail/check_iterator_range.hpp> +#include <boost/geometry/util/has_non_finite_coordinate.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp index b36e9f38b7..82818b0990 100644 --- a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp +++ b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp @@ -1,6 +1,6 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2014-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 @@ -16,6 +16,12 @@ #include <boost/core/ignore_unused.hpp> #include <boost/range.hpp> +#include <boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp> +#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp> +#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> +#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp> +#include <boost/geometry/algorithms/validity_failure_type.hpp> + #include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/point_type.hpp> @@ -23,12 +29,6 @@ #include <boost/geometry/policies/robustness/segment_ratio_type.hpp> #include <boost/geometry/policies/robustness/get_rescale_policy.hpp> -#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp> -#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> -#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp> - -#include <boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp> - namespace boost { namespace geometry { diff --git a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp index ed24b13810..8fe5803323 100644 --- a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp +++ b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp @@ -116,19 +116,12 @@ private: } // prepare strategies - typedef typename std::iterator_traits<PolygonIterator>::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<polygon_type, polygon_type>(); 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<within_strategy_type> item_visitor(within_strategy); + typename base::template item_visitor_type<Strategy> item_visitor(strategy); geometry::partition < diff --git a/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/boost/geometry/algorithms/detail/is_valid/polygon.hpp index 5c6229b793..834ce5af2c 100644 --- a/boost/geometry/algorithms/detail/is_valid/polygon.hpp +++ b/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 <typename Item> - inline bool is_within(Item const& first, Item const& second) - { - typename point_type<Polygon>::type point; - typedef detail::point_on_border::point_on_range<true> 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 <typename Iterator, typename Box> inline bool apply(partition_item<Iterator, Box> const& item1, partition_item<Iterator, Box> 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<inter_ring_type, inter_ring_type>(); 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<in_interior_strategy_type> item_visitor(in_interior_strategy); + item_visitor_type<Strategy> item_visitor(strategy); geometry::partition < diff --git a/boost/geometry/algorithms/detail/is_valid/ring.hpp b/boost/geometry/algorithms/detail/is_valid/ring.hpp index 40698155b5..5a55d998e4 100644 --- a/boost/geometry/algorithms/detail/is_valid/ring.hpp +++ b/boost/geometry/algorithms/detail/is_valid/ring.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 @@ -20,6 +20,7 @@ #include <boost/geometry/core/closure.hpp> #include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/point_order.hpp> +#include <boost/geometry/core/tags.hpp> #include <boost/geometry/util/order_as_direction.hpp> #include <boost/geometry/util/range.hpp> @@ -36,6 +37,7 @@ #include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp> #include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp> #include <boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp> +#include <boost/geometry/algorithms/dispatch/is_valid.hpp> #include <boost/geometry/strategies/area.hpp> diff --git a/boost/geometry/algorithms/detail/normalize.hpp b/boost/geometry/algorithms/detail/normalize.hpp index 7a761d42bb..b53243f08f 100644 --- a/boost/geometry/algorithms/detail/normalize.hpp +++ b/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 <cstddef> -#include <boost/numeric/conversion/cast.hpp> - -#include <boost/geometry/core/access.hpp> -#include <boost/geometry/core/coordinate_system.hpp> -#include <boost/geometry/core/coordinate_type.hpp> -#include <boost/geometry/core/cs.hpp> -#include <boost/geometry/core/tag.hpp> -#include <boost/geometry/core/tags.hpp> - -#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> -#include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp> - -#include <boost/geometry/views/detail/indexed_point_view.hpp> +// For backward compatibility +#include <boost/geometry/strategies/normalize.hpp> namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace normalization -{ - - -struct do_nothing -{ - template <typename GeometryIn, typename GeometryOut> - static inline void apply(GeometryIn const&, GeometryOut&) - { - } -}; - - -template <std::size_t Dimension, std::size_t DimensionCount> -struct assign_loop -{ - template <typename CoordinateType, typename PointIn, typename PointOut> - static inline void apply(CoordinateType const& longitude, - CoordinateType const& latitude, - PointIn const& point_in, - PointOut& point_out) - { - geometry::set<Dimension>(point_out, boost::numeric_cast - < - typename coordinate_type<PointOut>::type - >(geometry::get<Dimension>(point_in))); - - assign_loop - < - Dimension + 1, DimensionCount - >::apply(longitude, latitude, point_in, point_out); - } -}; - -template <std::size_t DimensionCount> -struct assign_loop<DimensionCount, DimensionCount> -{ - template <typename CoordinateType, typename PointIn, typename PointOut> - static inline void apply(CoordinateType const&, - CoordinateType const&, - PointIn const&, - PointOut&) - { - } -}; - -template <std::size_t DimensionCount> -struct assign_loop<0, DimensionCount> -{ - template <typename CoordinateType, typename PointIn, typename PointOut> - 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<PointOut>::type - >(longitude)); - - assign_loop - < - 1, DimensionCount - >::apply(longitude, latitude, point_in, point_out); - } -}; - -template <std::size_t DimensionCount> -struct assign_loop<1, DimensionCount> -{ - template <typename CoordinateType, typename PointIn, typename PointOut> - 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<PointOut>::type - >(latitude)); - - assign_loop - < - 2, DimensionCount - >::apply(longitude, latitude, point_in, point_out); - } -}; - - -template <typename PointIn, typename PointOut, bool IsEquatorial = true> -struct normalize_point -{ - static inline void apply(PointIn const& point_in, PointOut& point_out) - { - typedef typename coordinate_type<PointIn>::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<PointIn>::type::units, - IsEquatorial, - in_coordinate_type - >(longitude, latitude); - - assign_loop - < - 0, dimension<PointIn>::value - >::apply(longitude, latitude, point_in, point_out); - } -}; - - -template <typename BoxIn, typename BoxOut, bool IsEquatorial = true> -class normalize_box -{ - template <typename UnitsIn, typename UnitsOut, typename CoordinateInType> - 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<BoxOut, min_corner> p_min_out(box_out); - assign_loop - < - 0, dimension<BoxIn>::value - >::apply(lon_min, - lat_min, - detail::indexed_point_view - < - BoxIn const, min_corner - >(box_in), - p_min_out); - - detail::indexed_point_view<BoxOut, max_corner> p_max_out(box_out); - assign_loop - < - 0, dimension<BoxIn>::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<BoxIn>::type in_coordinate_type; - - in_coordinate_type lon_min = geometry::get<min_corner, 0>(box_in); - in_coordinate_type lat_min = geometry::get<min_corner, 1>(box_in); - in_coordinate_type lon_max = geometry::get<max_corner, 0>(box_in); - in_coordinate_type lat_max = geometry::get<max_corner, 1>(box_in); - - math::normalize_spheroidal_box_coordinates - < - typename coordinate_system<BoxIn>::type::units, - IsEquatorial, - in_coordinate_type - >(lon_min, lat_min, lon_max, lat_max); - - apply_to_coordinates - < - typename coordinate_system<BoxIn>::type::units, - typename coordinate_system<BoxOut>::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<GeometryIn>::type, - typename TagOut = typename tag<GeometryOut>::type, - typename CSTagIn = typename cs_tag<GeometryIn>::type, - typename CSTagOut = typename cs_tag<GeometryOut>::type -> -struct normalize : detail::normalization::do_nothing -{}; - - -template <typename PointIn, typename PointOut> -struct normalize - < - PointIn, PointOut, point_tag, point_tag, - spherical_equatorial_tag, spherical_equatorial_tag - > : detail::normalization::normalize_point<PointIn, PointOut> -{}; - - -template <typename PointIn, typename PointOut> -struct normalize - < - PointIn, PointOut, point_tag, point_tag, - spherical_polar_tag, spherical_polar_tag - > : detail::normalization::normalize_point<PointIn, PointOut, false> -{}; - - -template <typename PointIn, typename PointOut> -struct normalize - < - PointIn, PointOut, point_tag, point_tag, geographic_tag, geographic_tag - > : detail::normalization::normalize_point<PointIn, PointOut> -{}; - - -template <typename BoxIn, typename BoxOut> -struct normalize - < - BoxIn, BoxOut, box_tag, box_tag, - spherical_equatorial_tag, spherical_equatorial_tag - > : detail::normalization::normalize_box<BoxIn, BoxOut> -{}; - - -template <typename BoxIn, typename BoxOut> -struct normalize - < - BoxIn, BoxOut, box_tag, box_tag, - spherical_polar_tag, spherical_polar_tag - > : detail::normalization::normalize_box<BoxIn, BoxOut, false> -{}; - - -template <typename BoxIn, typename BoxOut> -struct normalize - < - BoxIn, BoxOut, box_tag, box_tag, geographic_tag, geographic_tag - > : detail::normalization::normalize_box<BoxIn, BoxOut> -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - #ifndef DOXYGEN_NO_DETAIL namespace detail { -template <typename GeometryIn, typename GeometryOut> -inline void normalize(GeometryIn const& geometry_in, GeometryOut& geometry_out) +template <typename GeometryIn, typename GeometryOut, typename Strategy> +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 <typename GeometryOut, typename GeometryIn> -inline GeometryOut return_normalized(GeometryIn const& geometry_in) +template <typename GeometryOut, typename GeometryIn, typename Strategy> +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/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp b/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp index 0fd1fe4de9..34e9fc79c7 100644 --- a/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp +++ b/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 <boost/range.hpp> - #include <boost/geometry/algorithms/append.hpp> #include <boost/geometry/algorithms/detail/equals/point_point.hpp> +#include <boost/geometry/util/range.hpp> namespace boost { namespace geometry @@ -26,11 +30,24 @@ namespace detail { namespace overlay { template <typename Range, typename Point> -inline void append_no_duplicates(Range& range, Point const& point, bool force = false) +inline void append_with_duplicates(Range& range, Point const& 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 <typename Range, typename Point, typename EqPPStrategy> +inline void append_no_duplicates(Range& range, Point const& point, + EqPPStrategy const& strategy) { - if (boost::size(range) == 0 - || force - || ! geometry::detail::equals::equals_point_point(*(boost::end(range)-1), point)) + 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/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp b/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp index 724996ae33..aac39df141 100644 --- a/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp +++ b/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,11 +15,14 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPS_OR_SPIKES_HPP #include <boost/range.hpp> +#include <boost/static_assert.hpp> #include <boost/geometry/algorithms/append.hpp> #include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp> #include <boost/geometry/algorithms/detail/equals/point_point.hpp> +#include <boost/geometry/core/closure.hpp> + #include <boost/geometry/util/condition.hpp> #include <boost/geometry/util/range.hpp> @@ -33,12 +36,13 @@ namespace detail { namespace overlay { // TODO: move this / rename this -template <typename Point1, typename Point2, typename RobustPolicy> +template <typename Point1, typename Point2, typename EqualsStrategy, typename RobustPolicy> 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 +63,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<Point1>::type, + typename geometry::cs_tag<robust_point_type>::type + >::value)); + + return detail::equals::equals_point_point(point1_rob, point2_rob, strategy); } @@ -76,8 +87,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 +126,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/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index 3be5393486..6d3c602ff2 100644 --- a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/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, @@ -16,7 +16,6 @@ #include <boost/range.hpp> -#include <boost/geometry/algorithms/area.hpp> #include <boost/geometry/algorithms/envelope.hpp> #include <boost/geometry/algorithms/expand.hpp> #include <boost/geometry/algorithms/detail/partition.hpp> @@ -135,12 +134,14 @@ struct ring_info_helper_get_box } }; +template <typename DisjointBoxBoxStrategy> struct ring_info_helper_ovelaps_box { template <typename Box, typename InputItem> 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()); } }; @@ -328,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/boost/geometry/algorithms/detail/overlay/check_enrich.hpp b/boost/geometry/algorithms/detail/overlay/check_enrich.hpp index 25e442982b..e07e056c33 100644 --- a/boost/geometry/algorithms/detail/overlay/check_enrich.hpp +++ b/boost/geometry/algorithms/detail/overlay/check_enrich.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) @@ -9,11 +14,18 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH +#include <iostream> +#endif // BOOST_GEOMETRY_DEBUG_ENRICH #include <cstddef> +#include <vector> -#include <boost/range.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/value_type.hpp> +#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp> #include <boost/geometry/algorithms/detail/ring_identifier.hpp> @@ -42,7 +54,7 @@ struct meta_turn template <typename MetaTurn> -inline void display(MetaTurn const& meta_turn, std::string const& reason = "") +inline void display(MetaTurn const& meta_turn, const char* reason = "") { #ifdef BOOST_GEOMETRY_DEBUG_ENRICH std::cout << meta_turn.index diff --git a/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp index 8cb37d6954..ead9e7014a 100644 --- a/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp +++ b/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 <boost/geometry/util/select_coordinate_type.hpp> #include <boost/geometry/geometries/segment.hpp> +#include <boost/geometry/strategies/cartesian/point_in_point.hpp> + 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<Box, Point>::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/boost/geometry/algorithms/detail/overlay/convert_ring.hpp b/boost/geometry/algorithms/detail/overlay/convert_ring.hpp index 51955b515d..e2b3cfe069 100644 --- a/boost/geometry/algorithms/detail/overlay/convert_ring.hpp +++ b/boost/geometry/algorithms/detail/overlay/convert_ring.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) @@ -9,18 +14,16 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP - #include <boost/mpl/assert.hpp> -#include <boost/range.hpp> #include <boost/range/algorithm/reverse.hpp> +#include <boost/geometry/algorithms/convert.hpp> +#include <boost/geometry/algorithms/detail/ring_identifier.hpp> +#include <boost/geometry/algorithms/num_points.hpp> + #include <boost/geometry/core/tags.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> -#include <boost/geometry/algorithms/detail/ring_identifier.hpp> - -#include <boost/geometry/algorithms/convert.hpp> - namespace boost { namespace geometry { diff --git a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp index c6f540a978..d5bdf7eb82 100644 --- a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp +++ b/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 @@ -23,23 +23,27 @@ #include <boost/range.hpp> #include <boost/type_traits/integral_constant.hpp> +#include <boost/geometry/algorithms/detail/assign_box_corners.hpp> +#include <boost/geometry/algorithms/detail/signed_size_type.hpp> +#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp> +#include <boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> + #include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> #include <boost/geometry/core/ring_type.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/algorithms/not_implemented.hpp> + #include <boost/geometry/geometries/concepts/check.hpp> -#include <boost/geometry/iterators/ever_circling_iterator.hpp> -#include <boost/geometry/views/closeable_view.hpp> -#include <boost/geometry/views/reversible_view.hpp> -#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp> -#include <boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp> -#include <boost/geometry/algorithms/detail/signed_size_type.hpp> +#include <boost/geometry/iterators/ever_circling_iterator.hpp> #include <boost/geometry/util/range.hpp> +#include <boost/geometry/views/closeable_view.hpp> +#include <boost/geometry/views/reversible_view.hpp> + namespace boost { namespace geometry { @@ -137,11 +141,11 @@ private: template <typename RangeOut, typename Point, typename SideStrategy, typename RobustPolicy> 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/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp index a35be052a0..287a06b081 100644 --- a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -441,18 +441,21 @@ inline void enrich_intersection_points(Turns& turns, if (turn.both(detail::overlay::operation_none) || turn.both(opposite_operation) + || turn.both(detail::overlay::operation_blocked) || (detail::overlay::is_self_turn<OverlayType>(turn) && ! turn.is_clustered() && ! turn.both(target_operation))) { + // For all operations, discard xx and none/none // For intersections, remove uu to avoid the need to travel // a union (during intersection) in uu/cc clusters (e.g. #31,#32,#33) + // The ux is necessary to indicate impossible paths + // (especially if rescaling is removed) - // Similarly, for union, discard ii + // Similarly, for union, discard ii and ix - // Only keep self-uu-turns or self-ii-turns + // For self-turns, only keep uu / ii - // Blocked (or combination with blocked is still needed for difference) turn.discarded = true; turn.cluster_id = -1; continue; diff --git a/boost/geometry/algorithms/detail/overlay/follow.hpp b/boost/geometry/algorithms/detail/overlay/follow.hpp index d948c4f670..5d62e0c476 100644 --- a/boost/geometry/algorithms/detail/overlay/follow.hpp +++ b/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<overlay_intersection, RemoveSpikes> 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<overlay_intersection, RemoveSpikes> 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<overlay_intersection, RemoveSpikes> 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<overlay_intersection, RemoveSpikes> 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<overlay_intersection, RemoveSpikes> < 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<overlay_difference, RemoveSpikes> 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<overlay_difference, RemoveSpikes> 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<overlay_difference, RemoveSpikes> 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<overlay_difference, RemoveSpikes> 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/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp index 94667d0ed0..5a3360375a 100644 --- a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp @@ -44,12 +44,16 @@ template > struct get_turn_without_info { - template <typename Strategy, typename RobustPolicy, typename OutputIterator> - static inline OutputIterator apply( - Point1 const& pi, Point1 const& pj, Point1 const& /*pk*/, - Point2 const& qi, Point2 const& qj, Point2 const& /*qk*/, - bool /*is_p_first*/, bool /*is_p_last*/, - bool /*is_q_first*/, bool /*is_q_last*/, + template + < + typename UniqueSubRange1, + typename UniqueSubRange2, + typename Strategy, + typename RobustPolicy, + typename OutputIterator + > + static inline OutputIterator apply(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, TurnInfo const& , Strategy const& strategy, RobustPolicy const& robust_policy, @@ -71,6 +75,10 @@ struct get_turn_without_info typedef model::referring_segment<Point1 const> segment_type1; typedef model::referring_segment<Point2 const> segment_type2; + Point1 const& pi = range_p.at(0); + Point1 const& pj = range_p.at(1); + Point2 const& qi = range_q.at(0); + Point2 const& qj = range_q.at(1); segment_type1 p1(pi, pj); segment_type2 q1(qi, qj); diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 895952c8fc..6d92b1bd3c 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2015, 2017. -// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2017, 2018, 2019. +// Modifications copyright (c) 2015-2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -21,6 +21,7 @@ #include <boost/geometry/core/access.hpp> #include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/exception.hpp> #include <boost/geometry/algorithms/convert.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> @@ -84,7 +85,7 @@ struct base_turn_handler return side1 * side2 == 1; } - // Both continue + // Both get the same operation template <typename TurnInfo> static inline void both(TurnInfo& ti, operation_type const op) { @@ -130,6 +131,17 @@ struct base_turn_handler ? 1 : 0; } + template <typename Point1, typename Point2> + static inline typename geometry::coordinate_type<Point1>::type + distance_measure(Point1 const& a, Point2 const& b) + { + // TODO: use comparable distance for point-point instead - but that + // causes currently cycling include problems + typedef typename geometry::coordinate_type<Point1>::type ctype; + ctype const dx = get<0>(a) - get<0>(b); + ctype const dy = get<1>(a) - get<1>(b); + return dx * dx + dy * dy; + } }; @@ -143,15 +155,14 @@ struct touch_interior : public base_turn_handler template < unsigned int Index, - typename Point1, - typename Point2, + typename UniqueSubRange1, + typename UniqueSubRange2, typename IntersectionInfo, typename DirInfo, typename SidePolicy > - static inline void apply( - Point1 const& , Point1 const& , Point1 const& , - Point2 const& , Point2 const& , Point2 const& , + static inline void apply(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, TurnInfo& ti, IntersectionInfo const& intersection_info, DirInfo const& dir_info, @@ -169,8 +180,10 @@ struct touch_interior : public base_turn_handler static unsigned int const index_p = Index; static unsigned int const index_q = 1 - Index; + bool const has_pk = ! range_p.is_last_segment(); + bool const has_qk = ! range_q.is_last_segment(); int const side_qi_p = dir_info.sides.template get<index_q, 0>(); - int const side_qk_p = side.qk_wrt_p1(); + int const side_qk_p = has_qk ? side.qk_wrt_p1() : 0; if (side_qi_p == -side_qk_p) { @@ -183,7 +196,10 @@ struct touch_interior : public base_turn_handler return; } - int const side_qk_q = side.qk_wrt_q1(); + int const side_qk_q = has_qk ? side.qk_wrt_q1() : 0; + + // Only necessary if rescaling is turned off: + int const side_pj_q2 = has_qk ? side.pj_wrt_q2() : 0; if (side_qi_p == -1 && side_qk_p == -1 && side_qk_q == 1) { @@ -194,10 +210,21 @@ struct touch_interior : public base_turn_handler } else if (side_qi_p == 1 && side_qk_p == 1 && side_qk_q == -1) { - // Q turns right on the left side of P (test "ML3") - // Union: take both operation - // Intersection: skip - both(ti, operation_union); + if (has_qk && side_pj_q2 == -1) + { + // Q turns right on the left side of P (test "ML3") + // Union: take both operations + // Intersection: skip + both(ti, operation_union); + } + else + { + // q2 is collinear with p1, so it does not turn back. This + // can happen in floating point precision. In this case, + // block one of the operations to avoid taking that path. + ti.operations[index_p].operation = operation_union; + ti.operations[index_q].operation = operation_blocked; + } ti.touch_only = true; } else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q) @@ -207,6 +234,29 @@ struct touch_interior : public base_turn_handler // Union: take left turn (Q if Q turns left, P if Q turns right) // Intersection: other turn unsigned int index = side_qk_q == 1 ? index_q : index_p; + if (has_qk && side_pj_q2 == 0) + { + // Even though sides xk w.r.t. 1 are distinct, pj is collinear + // with q. Therefore swap the path + index = 1 - index; + } + + if (has_pk && has_qk && opposite(side_pj_q2, side_qi_p)) + { + // Without rescaling, floating point requires extra measures + int const side_qj_p1 = side.qj_wrt_p1(); + int const side_qj_p2 = side.qj_wrt_p2(); + + if (same(side_qj_p1, side_qj_p2)) + { + int const side_pj_q1 = side.pj_wrt_q1(); + if (opposite(side_pj_q1, side_pj_q2)) + { + index = 1 - index; + } + } + } + ti.operations[index].operation = operation_union; ti.operations[1 - index].operation = operation_intersection; ti.touch_only = true; @@ -219,10 +269,16 @@ struct touch_interior : public base_turn_handler // Collinearly in the same direction // (Q comes from left of P and turns left, // OR Q comes from right of P and turns right) - // Omit intersection point. + // Omit second intersection point. // Union: just continue // Intersection: just continue both(ti, operation_continue); + + // Calculate remaining distance. + // Q arrives at p, at point qj, so use qk for q + // and use pj for p + ti.operations[index_p].remaining_distance = distance_measure(ti.point, range_p.at(1)); + ti.operations[index_q].remaining_distance = distance_measure(ti.point, range_q.at(2)); } else { @@ -266,15 +322,14 @@ struct touch : public base_turn_handler template < - typename Point1, - typename Point2, + typename UniqueSubRange1, + typename UniqueSubRange2, typename IntersectionInfo, typename DirInfo, typename SidePolicy > - static inline void apply( - Point1 const& , Point1 const& , Point1 const& , - Point2 const& , Point2 const& , Point2 const& , + static inline void apply(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, TurnInfo& ti, IntersectionInfo const& intersection_info, DirInfo const& dir_info, @@ -282,17 +337,20 @@ struct touch : public base_turn_handler { assign_point(ti, method_touch, intersection_info, 0); + bool const has_pk = ! range_p.is_last_segment(); + bool const has_qk = ! range_q.is_last_segment(); + int const side_qi_p1 = dir_info.sides.template get<1, 0>(); - int const side_qk_p1 = side.qk_wrt_p1(); + int const side_qk_p1 = has_qk ? side.qk_wrt_p1() : 0; // If Qi and Qk are both at same side of Pi-Pj, // or collinear (so: not opposite sides) if (! opposite(side_qi_p1, side_qk_p1)) { - int const side_pk_q2 = side.pk_wrt_q2(); - int const side_pk_p = side.pk_wrt_p1(); - int const side_qk_q = side.qk_wrt_q1(); + int const side_pk_q2 = has_pk && has_qk ? side.pk_wrt_q2() : 0; + int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0; + int const side_qk_q = has_qk ? side.qk_wrt_q1() : 0; bool const q_turns_left = side_qk_q == 1; bool const block_q = side_qk_p1 == 0 @@ -315,7 +373,7 @@ struct touch : public base_turn_handler return; } - int const side_pk_q1 = side.pk_wrt_q1(); + int const side_pk_q1 = has_pk && has_qk ? side.pk_wrt_q1() : 0; // Collinear opposite case -> block P @@ -392,13 +450,13 @@ struct touch : public base_turn_handler else { // From left to right or from right to left - int const side_pk_p = side.pk_wrt_p1(); + int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0; bool const right_to_left = side_qk_p1 == 1; // If p turns into direction of qi (1,2) if (side_pk_p == side_qi_p1) { - int const side_pk_q1 = side.pk_wrt_q1(); + int const side_pk_q1 = has_pk ? side.pk_wrt_q1() : 0; // Collinear opposite case -> block P if (side_pk_q1 == 0) @@ -420,7 +478,7 @@ struct touch : public base_turn_handler // If p turns into direction of qk (4,5) if (side_pk_p == side_qk_p1) { - int const side_pk_q2 = side.pk_wrt_q2(); + int const side_pk_q2 = has_pk ? side.pk_wrt_q2() : 0; // Collinear case -> lines join, continue if (side_pk_q2 == 0) @@ -439,21 +497,6 @@ struct touch : public base_turn_handler ui_else_iu(! right_to_left, ti); return; } - -#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS - // Normally a robustness issue. - // TODO: more research if still occuring - std::cout << "Not yet handled" << std::endl - << "pi " << get<0>(pi) << " , " << get<1>(pi) - << " pj " << get<0>(pj) << " , " << get<1>(pj) - << " pk " << get<0>(pk) << " , " << get<1>(pk) - << std::endl - << "qi " << get<0>(qi) << " , " << get<1>(qi) - << " qj " << get<0>(qj) << " , " << get<1>(qj) - << " qk " << get<0>(qk) << " , " << get<1>(qk) - << std::endl; -#endif - } }; @@ -466,15 +509,14 @@ struct equal : public base_turn_handler { template < - typename Point1, - typename Point2, + typename UniqueSubRange1, + typename UniqueSubRange2, typename IntersectionInfo, typename DirInfo, typename SidePolicy > - static inline void apply( - Point1 const& , Point1 const& , Point1 const& , - Point2 const& , Point2 const& , Point2 const& , + static inline void apply(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, TurnInfo& ti, IntersectionInfo const& info, DirInfo const& , @@ -483,10 +525,12 @@ struct equal : public base_turn_handler // Copy the intersection point in TO direction assign_point(ti, method_equal, info, non_opposite_to_index(info)); - int const side_pk_q2 = side.pk_wrt_q2(); - int const side_pk_p = side.pk_wrt_p1(); - int const side_qk_p = side.qk_wrt_p1(); + bool const has_pk = ! range_p.is_last_segment(); + bool const has_qk = ! range_q.is_last_segment(); + int const side_pk_q2 = has_pk && has_qk ? side.pk_wrt_q2() : 0; + int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0; + int const side_qk_p = has_qk ? side.qk_wrt_p1() : 0; // If pk is collinear with qj-qk, they continue collinearly. // This can be on either side of p1 (== q1), or collinear @@ -525,12 +569,14 @@ struct equal_opposite : public base_turn_handler { template < - typename Point1, - typename Point2, + typename UniqueSubRange1, + typename UniqueSubRange2, typename OutputIterator, typename IntersectionInfo > - static inline void apply(Point1 const& pi, Point2 const& qi, + static inline void apply( + UniqueSubRange1 const& /*range_p*/, + UniqueSubRange2 const& /*range_q*/, /* by value: */ TurnInfo tp, OutputIterator& out, IntersectionInfo const& intersection_info) @@ -546,7 +592,6 @@ struct equal_opposite : public base_turn_handler for (unsigned int i = 0; i < intersection_info.i_info().count; i++) { assign_point(tp, method_none, intersection_info.i_info(), i); - AssignPolicy::apply(tp, pi, qi, intersection_info); *out++ = tp; } } @@ -593,15 +638,15 @@ struct collinear : public base_turn_handler */ template < - typename Point1, - typename Point2, + typename UniqueSubRange1, + typename UniqueSubRange2, typename IntersectionInfo, typename DirInfo, typename SidePolicy > static inline void apply( - Point1 const& , Point1 const& pj, Point1 const& pk, - Point2 const& , Point2 const& qj, Point2 const& qk, + UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, TurnInfo& ti, IntersectionInfo const& info, DirInfo const& dir_info, @@ -614,8 +659,10 @@ struct collinear : public base_turn_handler // Should not be 0, this is checked before BOOST_GEOMETRY_ASSERT(arrival != 0); - int const side_p = side.pk_wrt_p1(); - int const side_q = side.qk_wrt_q1(); + bool const has_pk = ! range_p.is_last_segment(); + bool const has_qk = ! range_q.is_last_segment(); + int const side_p = has_pk ? side.pk_wrt_p1() : 0; + int const side_q = has_qk ? side.qk_wrt_q1() : 0; // If p arrives, use p, else use q int const side_p_or_q = arrival == 1 @@ -642,25 +689,13 @@ struct collinear : public base_turn_handler // Calculate remaining distance. If it continues collinearly it is // measured until the end of the next segment ti.operations[0].remaining_distance - = side_p == 0 - ? distance_measure(ti.point, pk) - : distance_measure(ti.point, pj); + = side_p == 0 && has_pk + ? distance_measure(ti.point, range_p.at(2)) + : distance_measure(ti.point, range_p.at(1)); ti.operations[1].remaining_distance - = side_q == 0 - ? distance_measure(ti.point, qk) - : distance_measure(ti.point, qj); - } - - template <typename Point1, typename Point2> - static inline typename geometry::coordinate_type<Point1>::type - distance_measure(Point1 const& a, Point2 const& b) - { - // TODO: use comparable distance for point-point instead - but that - // causes currently cycling include problems - typedef typename geometry::coordinate_type<Point1>::type ctype; - ctype const dx = get<0>(a) - get<0>(b); - ctype const dy = get<1>(a) - get<1>(b); - return dx * dx + dy * dy; + = side_q == 0 && has_qk + ? distance_measure(ti.point, range_q.at(2)) + : distance_measure(ti.point, range_q.at(1)); } }; @@ -699,13 +734,10 @@ private : template < unsigned int Index, - typename Point1, - typename Point2, typename IntersectionInfo > - static inline bool set_tp(Point1 const& , Point1 const& , Point1 const& , int side_rk_r, - bool const handle_robustness, - Point2 const& , Point2 const& , int side_rk_s, + static inline bool set_tp(int side_rk_r, bool handle_robustness, + int side_rk_s, TurnInfo& tp, IntersectionInfo const& intersection_info) { BOOST_STATIC_ASSERT(Index <= 1); @@ -757,15 +789,15 @@ public: template < - typename Point1, - typename Point2, + typename UniqueSubRange1, + typename UniqueSubRange2, typename OutputIterator, typename IntersectionInfo, typename SidePolicy > static inline void apply( - Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, + UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, // Opposite collinear can deliver 2 intersection points, TurnInfo const& tp_model, @@ -774,22 +806,24 @@ public: IntersectionInfo const& intersection_info, SidePolicy const& side) { - apply(pi, pj, pk, qi, qj, qk, tp_model, out, intersection_info, side, empty_transformer); + apply(range_p, range_q, + tp_model, out, intersection_info, side, empty_transformer); } public: + template < - typename Point1, - typename Point2, + typename UniqueSubRange1, + typename UniqueSubRange2, typename OutputIterator, typename IntersectionInfo, typename SidePolicy, typename TurnTransformer > static inline void apply( - Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, + UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, // Opposite collinear can deliver 2 intersection points, TurnInfo const& tp_model, @@ -797,8 +831,7 @@ public: IntersectionInfo const& info, SidePolicy const& side, - TurnTransformer turn_transformer, - bool const is_pk_valid = true, bool const is_qk_valid = true) + TurnTransformer turn_transformer) { TurnInfo tp = tp_model; @@ -807,23 +840,21 @@ public: // If P arrives within Q, there is a turn dependent on P if ( p_arrival == 1 - && is_pk_valid - && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, info.i_info()) ) + && ! range_p.is_last_segment() + && set_tp<0>(side.pk_wrt_p1(), true, side.pk_wrt_q1(), tp, info.i_info()) ) { turn_transformer(tp); - AssignPolicy::apply(tp, pi, qi, info); *out++ = tp; } // If Q arrives within P, there is a turn dependent on Q if ( q_arrival == 1 - && is_qk_valid - && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, info.i_info()) ) + && ! range_q.is_last_segment() + && set_tp<1>(side.qk_wrt_q1(), false, side.qk_wrt_p1(), tp, info.i_info()) ) { turn_transformer(tp); - AssignPolicy::apply(tp, pi, qi, info); *out++ = tp; } @@ -840,7 +871,6 @@ public: for (unsigned int i = 0; i < info.i_info().count; i++) { assign_point(tp, method_collinear, info.i_info(), i); - AssignPolicy::apply(tp, pi, qi, info); *out++ = tp; } } @@ -856,23 +886,14 @@ template > struct crosses : public base_turn_handler { - template - < - typename Point1, - typename Point2, - typename IntersectionInfo, - typename DirInfo - > - static inline void apply( - Point1 const& , Point1 const& , Point1 const& , - Point2 const& , Point2 const& , Point2 const& , - TurnInfo& ti, + template <typename IntersectionInfo, typename DirInfo> + static inline void apply(TurnInfo& ti, IntersectionInfo const& intersection_info, DirInfo const& dir_info) { assign_point(ti, method_crosses, intersection_info, 0); - // In all casees: + // In all cases: // If Q crosses P from left to right // Union: take P // Intersection: take Q @@ -897,37 +918,21 @@ struct only_convert : public base_turn_handler /*! \brief Policy doing nothing -\details get_turn_info can have an optional policy to get/assign some - extra information. By default it does not, and this class - is that default. +\details get_turn_info can have an optional policy include extra + truns. By default it does not, and this class is that default. */ struct assign_null_policy { static bool const include_no_turn = false; static bool const include_degenerate = false; static bool const include_opposite = false; - - template - < - typename Info, - typename Point1, - typename Point2, - typename IntersectionInfo - > - static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&) - {} - }; - /*! \brief Turn information: intersection point, method, and turn information \details Information necessary for traversal phase (a phase of the overlay process). The information is gathered during the get_turns (segment intersection) phase. - \tparam Point1 point type of first segment - \tparam Point2 point type of second segment - \tparam TurnInfo type of class getting intersection and turn info \tparam AssignPolicy policy to assign extra info, e.g. to calculate distance from segment's first points to intersection points. @@ -937,23 +942,21 @@ struct assign_null_policy template<typename AssignPolicy> struct get_turn_info { - // Intersect pi-pj with qi-qj - // The points pk and qk are used do determine more information - // about the turn (turn left/right) + // Intersect a segment p with a segment q + // Both p and q are modelled as sub_ranges to provide more points + // to be able to give more information about the turn (left/right) template < - typename Point1, - typename Point2, + typename UniqueSubRange1, + typename UniqueSubRange2, typename TurnInfo, typename IntersectionStrategy, typename RobustPolicy, typename OutputIterator > static inline OutputIterator apply( - Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, - bool /*is_p_first*/, bool /*is_p_last*/, - bool /*is_q_first*/, bool /*is_q_last*/, + UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, TurnInfo const& tp_model, IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, @@ -961,13 +964,14 @@ struct get_turn_info { typedef intersection_info < - Point1, Point2, + UniqueSubRange1, UniqueSubRange2, typename TurnInfo::point_type, IntersectionStrategy, RobustPolicy > inters_info; - inters_info inters(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy); + inters_info inters(range_p, range_q, + intersection_strategy, robust_policy); char const method = inters.d_info().how; @@ -984,7 +988,6 @@ struct get_turn_info && inters.i_info().count > 0) { only_convert::apply(tp, inters.i_info()); - AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; @@ -1002,45 +1005,28 @@ struct get_turn_info // If Q (1) arrives (1) if ( inters.d_info().arrival[1] == 1 ) { - policy::template apply<0>(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), + policy::template apply<0>(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides()); } else { // Swap p/q - side_calculator - < - typename inters_info::cs_tag, - typename inters_info::robust_point2_type, - typename inters_info::robust_point1_type, - typename inters_info::side_strategy_type - > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), - inters.rpi(), inters.rpj(), inters.rpk(), - inters.get_side_strategy()); - - policy::template apply<1>(qi, qj, qk, pi, pj, pk, - tp, inters.i_info(), inters.d_info(), - swapped_side_calc); + policy::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), + inters.get_swapped_sides()); } - AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; case 'i' : { - crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info()); - AssignPolicy::apply(tp, pi, qi, inters); + crosses<TurnInfo>::apply(tp, inters.i_info(), inters.d_info()); *out++ = tp; } break; case 't' : { // Both touch (both arrive there) - touch<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), inters.sides()); - AssignPolicy::apply(tp, pi, qi, inters); + touch<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides()); *out++ = tp; } break; @@ -1050,9 +1036,7 @@ struct get_turn_info { // Both equal // or collinear-and-ending at intersection point - equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), inters.sides()); - AssignPolicy::apply(tp, pi, qi, inters); + equal<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides()); *out++ = tp; } else @@ -1061,8 +1045,7 @@ struct get_turn_info < TurnInfo, AssignPolicy - >::apply(pi, qi, - tp, out, inters); + >::apply(range_p, range_q, tp, out, inters); } } break; @@ -1075,19 +1058,18 @@ struct get_turn_info if ( inters.d_info().arrival[0] == 0 ) { // Collinear, but similar thus handled as equal - equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), inters.sides()); + equal<TurnInfo>::apply(range_p, range_q, tp, + inters.i_info(), inters.d_info(), inters.sides()); // override assigned method tp.method = method_collinear; } else { - collinear<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), inters.sides()); + collinear<TurnInfo>::apply(range_p, range_q, tp, + inters.i_info(), inters.d_info(), inters.sides()); } - AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } else @@ -1096,7 +1078,7 @@ struct get_turn_info < TurnInfo, AssignPolicy - >::apply(pi, pj, pk, qi, qj, qk, + >::apply(range_p, range_q, tp, out, inters, inters.sides()); } } @@ -1107,7 +1089,6 @@ struct get_turn_info if (AssignPolicy::include_degenerate) { only_convert::apply(tp, inters.i_info()); - AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } } diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index f9b4dee2cd..521744df88 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/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 @@ -15,8 +15,10 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP #include <boost/core/ignore_unused.hpp> -#include <boost/geometry/core/assert.hpp> + +#include <boost/geometry/algorithms/detail/equals/point_point.hpp> #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/policies/robustness/no_rescale_policy.hpp> namespace boost { namespace geometry { @@ -109,11 +111,12 @@ namespace detail { namespace overlay { class linear_intersections { public: - template <typename Point1, typename Point2, typename IntersectionResult> + template <typename Point1, typename Point2, typename IntersectionResult, typename EqPPStrategy> 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 +136,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; } @@ -222,39 +225,53 @@ private: ip_info ips[2]; }; -template <typename AssignPolicy, bool EnableFirst, bool EnableLast> +template <bool EnableFirst, bool EnableLast> struct get_turn_info_for_endpoint { + typedef std::pair<operation_type, operation_type> operations_pair; + BOOST_STATIC_ASSERT(EnableFirst || EnableLast); - template<typename Point1, - typename Point2, + template<typename UniqueSubRange1, + typename UniqueSubRange2, typename TurnInfo, typename IntersectionInfo, - typename OutputIterator + typename OutputIterator, + typename EqPPStrategy > - static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, - bool is_p_first, bool is_p_last, - bool is_q_first, bool is_q_last, + 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 - if ( ip_count == 0 ) + if (ip_count == 0) + { return false; + } - if ( !is_p_first && !is_p_last && !is_q_first && !is_q_last ) + if (! range_p.is_first_segment() + && ! range_q.is_first_segment() + && ! range_p.is_last_segment() + && ! range_q.is_last_segment()) + { + // Not an end-point from segment p or q return false; + } - linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last); + linear_intersections intersections(range_p.at(0), + range_q.at(0), + inters.result(), + range_p.is_last_segment(), + range_q.is_last_segment(), + strategy); bool append0_last - = analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, + = analyse_segment_and_assign_ip(range_p, range_q, intersections.template get<0>(), tp_model, inters, 0, out); @@ -268,8 +285,7 @@ struct get_turn_info_for_endpoint return result_ignore_ip0; bool append1_last - = analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, + = analyse_segment_and_assign_ip(range_p, range_q, intersections.template get<1>(), tp_model, inters, 1, out); @@ -279,37 +295,25 @@ struct get_turn_info_for_endpoint return result_ignore_ip0 || result_ignore_ip1; } - template <typename Point1, - typename Point2, + template <typename UniqueSubRange1, + typename UniqueSubRange2, typename TurnInfo, typename IntersectionInfo, typename OutputIterator> static inline - bool analyse_segment_and_assign_ip(Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, - bool is_p_first, bool is_p_last, - bool is_q_first, bool is_q_last, + bool analyse_segment_and_assign_ip(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, linear_intersections::ip_info const& ip_info, TurnInfo const& tp_model, IntersectionInfo const& inters, unsigned int ip_index, OutputIterator out) { -#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR - // may this give false positives for INTs? - typename IntersectionResult::point_type const& - inters_pt = result.template get<0>().intersections[ip_index]; - BOOST_GEOMETRY_ASSERT(ip_info.is_pi == equals::equals_point_point(pi, inters_pt)); - BOOST_GEOMETRY_ASSERT(ip_info.is_qi == equals::equals_point_point(qi, inters_pt)); - BOOST_GEOMETRY_ASSERT(ip_info.is_pj == equals::equals_point_point(pj, inters_pt)); - BOOST_GEOMETRY_ASSERT(ip_info.is_qj == equals::equals_point_point(qj, inters_pt)); -#endif - // TODO - calculate first/last only if needed - bool is_p_first_ip = is_p_first && ip_info.is_pi; - bool is_p_last_ip = is_p_last && ip_info.is_pj; - bool is_q_first_ip = is_q_first && ip_info.is_qi; - bool is_q_last_ip = is_q_last && ip_info.is_qj; + bool is_p_first_ip = range_p.is_first_segment() && ip_info.is_pi; + bool is_p_last_ip = range_p.is_last_segment() && ip_info.is_pj; + bool is_q_first_ip = range_q.is_first_segment() && ip_info.is_qi; + bool is_q_last_ip = range_q.is_last_segment() && ip_info.is_qj; bool append_first = EnableFirst && (is_p_first_ip || is_q_first_ip); bool append_last = EnableLast && (is_p_last_ip || is_q_last_ip); @@ -318,9 +322,7 @@ struct get_turn_info_for_endpoint if ( append_first || append_last ) { - bool handled = handle_internal<0>(pi, pj, pk, qi, qj, qk, - inters.rpi(), inters.rpj(), inters.rpk(), - inters.rqi(), inters.rqj(), inters.rqk(), + bool handled = handle_internal<0>(range_p, range_q, is_p_first_ip, is_p_last_ip, is_q_first_ip, is_q_last_ip, ip_info.is_qi, ip_info.is_qj, @@ -328,9 +330,8 @@ struct get_turn_info_for_endpoint p_operation, q_operation); if ( !handled ) { - handle_internal<1>(qi, qj, qk, pi, pj, pk, - inters.rqi(), inters.rqj(), inters.rqk(), - inters.rpi(), inters.rpj(), inters.rpk(), + // Reverse p/q + handle_internal<1>(range_q, range_p, is_q_first_ip, is_q_last_ip, is_p_first_ip, is_p_last_ip, ip_info.is_pi, ip_info.is_pj, @@ -348,31 +349,29 @@ struct get_turn_info_for_endpoint // handle spikes // P is spike and should be handled - if ( !is_p_last - && ip_info.is_pj // this check is redundant (also in is_spike_p) but faster + if (ip_info.is_pj // this check is redundant (also in is_spike_p) but faster && inters.i_info().count == 2 && inters.is_spike_p() ) { - assign(pi, qi, inters.result(), ip_index, method, operation_blocked, q_operation, + assign(inters.result(), ip_index, method, operation_blocked, q_operation, p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out); - assign(pi, qi, inters.result(), ip_index, method, operation_intersection, q_operation, + assign(inters.result(), ip_index, method, operation_intersection, q_operation, p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out); } // Q is spike and should be handled - else if ( !is_q_last - && ip_info.is_qj // this check is redundant (also in is_spike_q) but faster + else if (ip_info.is_qj // this check is redundant (also in is_spike_q) but faster && inters.i_info().count == 2 && inters.is_spike_q() ) { - assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_blocked, + assign(inters.result(), ip_index, method, p_operation, operation_blocked, p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out); - assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_intersection, + assign(inters.result(), ip_index, method, p_operation, operation_intersection, p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out); } // no spikes else { - assign(pi, qi, inters.result(), ip_index, method, p_operation, q_operation, + assign(inters.result(), ip_index, method, p_operation, q_operation, p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, false, tp_model, out); } } @@ -385,25 +384,22 @@ struct get_turn_info_for_endpoint // however now it's lazily calculated and then it would be always calculated template<std::size_t G1Index, - typename Point1, - typename Point2, - typename RobustPoint1, - typename RobustPoint2, + typename UniqueRange1, + typename UniqueRange2, typename TurnInfo, typename IntersectionInfo > - static inline bool handle_internal(Point1 const& /*i1*/, Point1 const& /*j1*/, Point1 const& /*k1*/, - Point2 const& i2, Point2 const& j2, Point2 const& /*k2*/, - RobustPoint1 const& ri1, RobustPoint1 const& rj1, RobustPoint1 const& /*rk1*/, - RobustPoint2 const& ri2, RobustPoint2 const& rj2, RobustPoint2 const& rk2, + static inline bool handle_internal(UniqueRange1 const& range1, + UniqueRange2 const& range2, bool first1, bool last1, bool first2, bool last2, bool ip_i2, bool ip_j2, TurnInfo const& tp_model, IntersectionInfo const& inters, unsigned int ip_index, operation_type & op1, operation_type & op2) { - typedef typename cs_tag<typename TurnInfo::point_type>::type cs_tag; + boost::ignore_unused(ip_index, tp_model); - boost::ignore_unused(i2, j2, ip_index, tp_model); + typename IntersectionInfo::side_strategy_type const& sides + = inters.get_side_strategy(); if ( !first2 && !last2 ) { @@ -425,14 +421,11 @@ struct get_turn_info_for_endpoint } else if ( ip_j2 ) { - side_calculator<cs_tag, - RobustPoint1, RobustPoint2, - typename IntersectionInfo::side_strategy_type, - RobustPoint2> - side_calc(ri2, ri1, rj1, ri2, rj2, rk2, inters.get_side_strategy()); + int const side_pj_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(1)); + int const side_pj_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(1)); + int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2)); - std::pair<operation_type, operation_type> - operations = operations_of_equal(side_calc); + operations_pair operations = operations_of_equal(side_pj_q2, side_pj_q1, side_qk_q1); // TODO: must the above be calculated? // wouldn't it be enough to check if segments are collinear? @@ -479,13 +472,11 @@ struct get_turn_info_for_endpoint } else if ( ip_j2 ) { - side_calculator<cs_tag, RobustPoint1, RobustPoint2, - typename IntersectionInfo::side_strategy_type, - RobustPoint2> - side_calc(ri2, rj1, ri1, ri2, rj2, rk2, inters.get_side_strategy()); - - std::pair<operation_type, operation_type> - operations = operations_of_equal(side_calc); + int const side_pi_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(0)); + int const side_pi_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(0)); + int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2)); + + operations_pair operations = operations_of_equal(side_pi_q2, side_pi_q1, side_qk_q1); // TODO: must the above be calculated? // wouldn't it be enough to check if segments are collinear? @@ -534,13 +525,10 @@ struct get_turn_info_for_endpoint ( is_ip_last_j ? position_back : position_middle ); } - template <typename Point1, - typename Point2, - typename IntersectionResult, + template <typename IntersectionResult, typename TurnInfo, typename OutputIterator> - static inline void assign(Point1 const& pi, Point2 const& qi, - IntersectionResult const& result, + static inline void assign(IntersectionResult const& result, unsigned int ip_index, method_type method, operation_type op0, operation_type op1, @@ -591,33 +579,27 @@ struct get_turn_info_for_endpoint } } - // TODO: this should get an intersection_info, which is unavailable here - // Because the assign_null policy accepts any structure, we pass the result instead for now - AssignPolicy::apply(tp, pi, qi, result); *out++ = tp; } - template <typename SidePolicy> - static inline std::pair<operation_type, operation_type> operations_of_equal(SidePolicy const& side) + static inline operations_pair operations_of_equal(int side_px_q2, + int side_px_q1, + int side_qk_q1) { - int const side_pk_q2 = side.pk_wrt_q2(); - int const side_pk_p = side.pk_wrt_p1(); - int const side_qk_p = side.qk_wrt_p1(); - - // If pk is collinear with qj-qk, they continue collinearly. - // This can be on either side of p1 (== q1), or collinear + // If px (pi or pj) is collinear with qj-qk (q2), they continue collinearly. + // This can be on either side of q1, or collinear // The second condition checks if they do not continue // oppositely - if ( side_pk_q2 == 0 && side_pk_p == side_qk_p ) + if (side_px_q2 == 0 && side_px_q1 == side_qk_q1) { return std::make_pair(operation_continue, operation_continue); } // If they turn to same side (not opposite sides) - if ( ! base_turn_handler::opposite(side_pk_p, side_qk_p) ) + if ( ! base_turn_handler::opposite(side_px_q1, side_qk_q1) ) { - // If pk is left of q2 or collinear: p: union, q: intersection - if ( side_pk_q2 != -1 ) + // If px is left of q2 or collinear: p: union, q: intersection + if (side_px_q2 != -1 ) { return std::make_pair(operation_union, operation_intersection); } @@ -630,7 +612,7 @@ struct get_turn_info_for_endpoint { // They turn opposite sides. If p turns left (or collinear), // p: union, q: intersection - if ( side_pk_p != -1 ) + if (side_px_q1 != -1 ) { return std::make_pair(operation_union, operation_intersection); } @@ -641,16 +623,15 @@ struct get_turn_info_for_endpoint } } - static inline bool operations_both( - std::pair<operation_type, operation_type> const& operations, - operation_type const op) + static inline bool operations_both(operations_pair const& operations, + operation_type const op) { return operations.first == op && operations.second == op; } - static inline bool operations_combination( - std::pair<operation_type, operation_type> const& operations, - operation_type const op1, operation_type const op2) + static inline bool operations_combination(operations_pair const& operations, + operation_type const op1, + operation_type const op2) { return ( operations.first == op1 && operations.second == op2 ) || ( operations.first == op2 && operations.second == op1 ); diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp index f8247cd240..087ca80602 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp +++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015, 2017. -// 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 @@ -14,7 +14,16 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP +#include <boost/geometry/algorithms/detail/direction_code.hpp> +#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> +#include <boost/geometry/algorithms/detail/recalculate.hpp> +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/geometries/segment.hpp> // referring_segment +#include <boost/geometry/policies/relate/direction.hpp> +#include <boost/geometry/policies/relate/intersection_points.hpp> +#include <boost/geometry/policies/relate/tupled.hpp> #include <boost/geometry/policies/robustness/no_rescale_policy.hpp> +#include <boost/geometry/strategies/intersection_result.hpp> namespace boost { namespace geometry { @@ -36,183 +45,324 @@ struct turn_operation_linear bool is_collinear; // valid only for Linear geometry }; -template <typename TurnPointCSTag, typename PointP, typename PointQ, - typename SideStrategy, - typename Pi = PointP, typename Pj = PointP, typename Pk = PointP, - typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ +template +< + typename TurnPointCSTag, + typename UniqueSubRange1, + typename UniqueSubRange2, + typename SideStrategy > struct side_calculator { - inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk, - Qi const& qi, Qj const& qj, Qk const& qk, + typedef typename UniqueSubRange1::point_type point1_type; + typedef typename UniqueSubRange2::point_type point2_type; + + inline side_calculator(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, SideStrategy const& side_strategy) - : m_pi(pi), m_pj(pj), m_pk(pk) - , m_qi(qi), m_qj(qj), m_qk(qk) - , m_side_strategy(side_strategy) + : m_side_strategy(side_strategy) + , m_range_p(range_p) + , m_range_q(range_q) {} - inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); } - inline int pk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_pk); } - inline int qk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_qk); } - inline int qk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_qk); } + inline int pk_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_pk()); } + inline int pk_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pk()); } + inline int qk_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_qk()); } + inline int qk_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_qk()); } - inline int pk_wrt_q2() const { return m_side_strategy.apply(m_qj, m_qk, m_pk); } - inline int qk_wrt_p2() const { return m_side_strategy.apply(m_pj, m_pk, m_qk); } + inline int pk_wrt_q2() const { return m_side_strategy.apply(get_qj(), get_qk(), get_pk()); } + inline int qk_wrt_p2() const { return m_side_strategy.apply(get_pj(), get_pk(), get_qk()); } - Pi const& m_pi; - Pj const& m_pj; - Pk const& m_pk; - Qi const& m_qi; - Qj const& m_qj; - Qk const& m_qk; + // Necessary when rescaling turns off: + inline int qj_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_qj()); } + inline int qj_wrt_p2() const { return m_side_strategy.apply(get_pj(), get_pk(), get_qj()); } + inline int pj_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pj()); } + inline int pj_wrt_q2() const { return m_side_strategy.apply(get_qj(), get_qk(), get_pj()); } + inline point1_type const& get_pi() const { return m_range_p.at(0); } + inline point1_type const& get_pj() const { return m_range_p.at(1); } + inline point1_type const& get_pk() const { return m_range_p.at(2); } + + inline point2_type const& get_qi() const { return m_range_q.at(0); } + inline point2_type const& get_qj() const { return m_range_q.at(1); } + inline point2_type const& get_qk() const { return m_range_q.at(2); } + + // Used side-strategy, owned by the calculator, + // created from .get_side_strategy() SideStrategy m_side_strategy; + + // Used ranges - owned by get_turns or (for robust points) by intersection_info_base + UniqueSubRange1 const& m_range_p; + UniqueSubRange2 const& m_range_q; }; -template <typename Point1, typename Point2, typename RobustPolicy> +template<typename Point, typename UniqueSubRange, typename RobustPolicy> +struct robust_subrange_adapter +{ + typedef Point point_type; + + robust_subrange_adapter(UniqueSubRange const& unique_sub_range, + Point const& robust_point_i, Point const& robust_point_j, + RobustPolicy const& robust_policy) + + : m_unique_sub_range(unique_sub_range) + , m_robust_policy(robust_policy) + , m_robust_point_i(robust_point_i) + , m_robust_point_j(robust_point_j) + , m_k_retrieved(false) + {} + + std::size_t size() const { return m_unique_sub_range.size(); } + + //! Get precalculated point + Point const& at(std::size_t index) const + { + BOOST_GEOMETRY_ASSERT(index < size()); + switch (index) + { + case 0 : return m_robust_point_i; + case 1 : return m_robust_point_j; + case 2 : return get_point_k(); + default : return m_robust_point_i; + } + } + +private : + Point const& get_point_k() const + { + if (! m_k_retrieved) + { + geometry::recalculate(m_robust_point_k, m_unique_sub_range.at(2), m_robust_policy); + m_k_retrieved = true; + } + return m_robust_point_k; + } + + UniqueSubRange const& m_unique_sub_range; + RobustPolicy const& m_robust_policy; + + Point const& m_robust_point_i; + Point const& m_robust_point_j; + mutable Point m_robust_point_k; + + mutable bool m_k_retrieved; +}; + +template +< + typename UniqueSubRange1, typename UniqueSubRange2, + typename RobustPolicy +> struct robust_points { typedef typename geometry::robust_point_type < - Point1, RobustPolicy + typename UniqueSubRange1::point_type, RobustPolicy >::type robust_point1_type; - // TODO: define robust_point2_type using Point2? typedef robust_point1_type robust_point2_type; - inline robust_points(Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, + inline robust_points(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, RobustPolicy const& robust_policy) + : m_robust_policy(robust_policy) + , m_range_p(range_p) + , m_range_q(range_q) + , m_pk_retrieved(false) + , m_qk_retrieved(false) + { + // Calculate pi,pj and qi,qj which are almost always necessary + // But don't calculate pk/qk yet, which is retrieved (taking + // more time) and not always necessary. + geometry::recalculate(m_rpi, range_p.at(0), robust_policy); + geometry::recalculate(m_rpj, range_p.at(1), robust_policy); + geometry::recalculate(m_rqi, range_q.at(0), robust_policy); + geometry::recalculate(m_rqj, range_q.at(1), robust_policy); + } + + inline robust_point1_type const& get_rpk() const { - geometry::recalculate(m_rpi, pi, robust_policy); - geometry::recalculate(m_rpj, pj, robust_policy); - geometry::recalculate(m_rpk, pk, robust_policy); - geometry::recalculate(m_rqi, qi, robust_policy); - geometry::recalculate(m_rqj, qj, robust_policy); - geometry::recalculate(m_rqk, qk, robust_policy); + if (! m_pk_retrieved) + { + geometry::recalculate(m_rpk, m_range_p.at(2), m_robust_policy); + m_pk_retrieved = true; + } + return m_rpk; } + inline robust_point2_type const& get_rqk() const + { + if (! m_qk_retrieved) + { + geometry::recalculate(m_rqk, m_range_q.at(2), m_robust_policy); + m_qk_retrieved = true; + } + return m_rqk; + } + + robust_point1_type m_rpi, m_rpj; + robust_point2_type m_rqi, m_rqj; - robust_point1_type m_rpi, m_rpj, m_rpk; - robust_point2_type m_rqi, m_rqj, m_rqk; +private : + RobustPolicy const& m_robust_policy; + UniqueSubRange1 const& m_range_p; + UniqueSubRange2 const& m_range_q; + + // On retrieval + mutable robust_point1_type m_rpk; + mutable robust_point2_type m_rqk; + mutable bool m_pk_retrieved; + mutable bool m_qk_retrieved; }; -template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy, typename RobustPolicy> +template +< + typename UniqueSubRange1, typename UniqueSubRange2, + typename TurnPoint, typename IntersectionStrategy, typename RobustPolicy> class intersection_info_base - : private robust_points<Point1, Point2, RobustPolicy> + : private robust_points<UniqueSubRange1, UniqueSubRange2, RobustPolicy> { - typedef robust_points<Point1, Point2, RobustPolicy> base; + typedef robust_points<UniqueSubRange1, UniqueSubRange2, RobustPolicy> base; public: - typedef Point1 point1_type; - typedef Point2 point2_type; - typedef typename base::robust_point1_type robust_point1_type; typedef typename base::robust_point2_type robust_point2_type; + typedef robust_subrange_adapter<robust_point1_type, UniqueSubRange1, RobustPolicy> robust_subrange1; + typedef robust_subrange_adapter<robust_point2_type, UniqueSubRange2, RobustPolicy> robust_subrange2; + typedef typename cs_tag<TurnPoint>::type cs_tag; typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; - typedef side_calculator<cs_tag, robust_point1_type, robust_point2_type, side_strategy_type> side_calculator_type; - - intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, + typedef side_calculator<cs_tag, robust_subrange1, robust_subrange2, + side_strategy_type> side_calculator_type; + + typedef side_calculator + < + cs_tag, robust_subrange2, robust_subrange1, + side_strategy_type + > robust_swapped_side_calculator_type; + + intersection_info_base(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy) - : base(pi, pj, pk, qi, qj, qk, robust_policy) - , m_side_calc(base::m_rpi, base::m_rpj, base::m_rpk, - base::m_rqi, base::m_rqj, base::m_rqk, + : base(range_p, range_q, robust_policy) + , m_range_p(range_p) + , m_range_q(range_q) + , m_robust_range_p(range_p, base::m_rpi, base::m_rpj, robust_policy) + , m_robust_range_q(range_q, base::m_rqi, base::m_rqj, robust_policy) + , m_side_calc(m_robust_range_p, m_robust_range_q, intersection_strategy.get_side_strategy()) - , m_pi(pi), m_pj(pj), m_pk(pk) - , m_qi(qi), m_qj(qj), m_qk(qk) {} - inline Point1 const& pi() const { return m_pi; } - inline Point1 const& pj() const { return m_pj; } - inline Point1 const& pk() const { return m_pk; } - - inline Point2 const& qi() const { return m_qi; } - inline Point2 const& qj() const { return m_qj; } - inline Point2 const& qk() const { return m_qk; } + inline typename UniqueSubRange1::point_type const& pi() const { return m_range_p.at(0); } + inline typename UniqueSubRange2::point_type const& qi() const { return m_range_q.at(0); } inline robust_point1_type const& rpi() const { return base::m_rpi; } inline robust_point1_type const& rpj() const { return base::m_rpj; } - inline robust_point1_type const& rpk() const { return base::m_rpk; } + inline robust_point1_type const& rpk() const { return base::get_rpk(); } inline robust_point2_type const& rqi() const { return base::m_rqi; } inline robust_point2_type const& rqj() const { return base::m_rqj; } - inline robust_point2_type const& rqk() const { return base::m_rqk; } + inline robust_point2_type const& rqk() const { return base::get_rqk(); } inline side_calculator_type const& sides() const { return m_side_calc; } -private: - side_calculator_type m_side_calc; + robust_swapped_side_calculator_type get_swapped_sides() const + { + robust_swapped_side_calculator_type result( + m_robust_range_q, m_robust_range_p, + m_side_calc.m_side_strategy); + return result; + } - point1_type const& m_pi; - point1_type const& m_pj; - point1_type const& m_pk; - point2_type const& m_qi; - point2_type const& m_qj; - point2_type const& m_qk; + // Owned by get_turns + UniqueSubRange1 const& m_range_p; + UniqueSubRange2 const& m_range_q; +private : + // Owned by this class + robust_subrange1 m_robust_range_p; + robust_subrange2 m_robust_range_q; + side_calculator_type m_side_calc; }; -template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy> -class intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, detail::no_rescale_policy> +template +< + typename UniqueSubRange1, typename UniqueSubRange2, + typename TurnPoint, typename IntersectionStrategy +> +class intersection_info_base<UniqueSubRange1, UniqueSubRange2, + TurnPoint, IntersectionStrategy, detail::no_rescale_policy> { public: - typedef Point1 point1_type; - typedef Point2 point2_type; + typedef typename UniqueSubRange1::point_type point1_type; + typedef typename UniqueSubRange2::point_type point2_type; - typedef Point1 robust_point1_type; - typedef Point2 robust_point2_type; + typedef typename UniqueSubRange1::point_type robust_point1_type; + typedef typename UniqueSubRange2::point_type robust_point2_type; typedef typename cs_tag<TurnPoint>::type cs_tag; typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; - typedef side_calculator<cs_tag, Point1, Point2, side_strategy_type> side_calculator_type; + typedef side_calculator<cs_tag, UniqueSubRange1, UniqueSubRange2, side_strategy_type> side_calculator_type; + + typedef side_calculator + < + cs_tag, UniqueSubRange2, UniqueSubRange1, + side_strategy_type + > swapped_side_calculator_type; - intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, + intersection_info_base(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, IntersectionStrategy const& intersection_strategy, no_rescale_policy const& /*robust_policy*/) - : m_side_calc(pi, pj, pk, qi, qj, qk, + : m_range_p(range_p) + , m_range_q(range_q) + , m_side_calc(range_p, range_q, intersection_strategy.get_side_strategy()) {} - inline Point1 const& pi() const { return m_side_calc.m_pi; } - inline Point1 const& pj() const { return m_side_calc.m_pj; } - inline Point1 const& pk() const { return m_side_calc.m_pk; } + inline point1_type const& rpi() const { return m_side_calc.get_pi(); } + inline point1_type const& rpj() const { return m_side_calc.get_pj(); } + inline point1_type const& rpk() const { return m_side_calc.get_pk(); } - inline Point2 const& qi() const { return m_side_calc.m_qi; } - inline Point2 const& qj() const { return m_side_calc.m_qj; } - inline Point2 const& qk() const { return m_side_calc.m_qk; } + inline point2_type const& rqi() const { return m_side_calc.get_qi(); } + inline point2_type const& rqj() const { return m_side_calc.get_qj(); } + inline point2_type const& rqk() const { return m_side_calc.get_qk(); } - inline Point1 const& rpi() const { return pi(); } - inline Point1 const& rpj() const { return pj(); } - inline Point1 const& rpk() const { return pk(); } + inline side_calculator_type const& sides() const { return m_side_calc; } - inline Point2 const& rqi() const { return qi(); } - inline Point2 const& rqj() const { return qj(); } - inline Point2 const& rqk() const { return qk(); } + swapped_side_calculator_type get_swapped_sides() const + { + swapped_side_calculator_type result( + m_range_q, m_range_p, + m_side_calc.m_side_strategy); + return result; + } - inline side_calculator_type const& sides() const { return m_side_calc; } - -private: +protected : + // Owned by get_turns + UniqueSubRange1 const& m_range_p; + UniqueSubRange2 const& m_range_q; +private : + // Owned here, passed by .get_side_strategy() side_calculator_type m_side_calc; }; template < - typename Point1, - typename Point2, + typename UniqueSubRange1, typename UniqueSubRange2, typename TurnPoint, typename IntersectionStrategy, typename RobustPolicy > class intersection_info - : public intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy> + : public intersection_info_base<UniqueSubRange1, UniqueSubRange2, + TurnPoint, IntersectionStrategy, RobustPolicy> { - typedef intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy> base; + typedef intersection_info_base<UniqueSubRange1, UniqueSubRange2, + TurnPoint, IntersectionStrategy, RobustPolicy> base; public: typedef segment_intersection_points @@ -224,6 +374,9 @@ public: >::type > intersection_point_type; + typedef typename UniqueSubRange1::point_type point1_type; + typedef typename UniqueSubRange2::point_type point2_type; + // NOTE: formerly defined in intersection_strategies typedef policies::relate::segments_tupled < @@ -237,22 +390,23 @@ public: typedef IntersectionStrategy intersection_strategy_type; typedef typename IntersectionStrategy::side_strategy_type side_strategy_type; - typedef model::referring_segment<Point1 const> segment_type1; - typedef model::referring_segment<Point2 const> segment_type2; + typedef model::referring_segment<point1_type const> segment_type1; + typedef model::referring_segment<point2_type const> segment_type2; typedef typename base::side_calculator_type side_calculator_type; typedef typename intersection_policy_type::return_type result_type; typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info - intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, + intersection_info(UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy) - : base(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy) + : base(range_p, range_q, + intersection_strategy, robust_policy) , m_result(intersection_strategy.apply( - segment_type1(pi, pj), - segment_type2(qi, qj), + segment_type1(range_p.at(0), range_p.at(1)), + segment_type2(range_q.at(0), range_q.at(1)), intersection_policy_type(), robust_policy, base::rpi(), base::rpj(), @@ -265,11 +419,6 @@ public: inline i_info_type const& i_info() const { return m_result.template get<0>(); } inline d_info_type const& d_info() const { return m_result.template get<1>(); } - inline intersection_strategy_type const& get_intersection_strategy() const - { - return m_intersection_strategy; - } - inline side_strategy_type get_side_strategy() const { return m_intersection_strategy.get_side_strategy(); @@ -278,24 +427,36 @@ public: // TODO: it's more like is_spike_ip_p inline bool is_spike_p() const { + if (base::m_range_p.is_last_segment()) + { + return false; + } if (base::sides().pk_wrt_p1() == 0) { + // p: pi--------pj--------pk + // or: pi----pk==pj + if (! is_ip_j<0>()) { return false; } - int const qk_p1 = base::sides().qk_wrt_p1(); - int const qk_p2 = base::sides().qk_wrt_p2(); - + // TODO: why is q used to determine spike property in p? + bool const has_qk = ! base::m_range_q.is_last_segment(); + int const qk_p1 = has_qk ? base::sides().qk_wrt_p1() : 0; + int const qk_p2 = has_qk ? base::sides().qk_wrt_p2() : 0; + if (qk_p1 == -qk_p2) { if (qk_p1 == 0) { - return is_spike_of_collinear(base::pi(), base::pj(), - base::pk()); + // qk is collinear with both p1 and p2, + // verify if pk goes backwards w.r.t. pi/pj + return direction_code(base::rpi(), base::rpj(), base::rpk()) == -1; } - + + // qk is at opposite side of p1/p2, therefore + // p1/p2 (collinear) are opposite and form a spike return true; } } @@ -303,9 +464,14 @@ public: return false; } - // TODO: it's more like is_spike_ip_q inline bool is_spike_q() const { + if (base::m_range_q.is_last_segment()) + { + return false; + } + + // See comments at is_spike_p if (base::sides().qk_wrt_q1() == 0) { if (! is_ip_j<1>()) @@ -313,15 +479,16 @@ public: return false; } - int const pk_q1 = base::sides().pk_wrt_q1(); - int const pk_q2 = base::sides().pk_wrt_q2(); + // TODO: why is p used to determine spike property in q? + bool const has_pk = ! base::m_range_p.is_last_segment(); + int const pk_q1 = has_pk ? base::sides().pk_wrt_q1() : 0; + int const pk_q2 = has_pk ? base::sides().pk_wrt_q2() : 0; if (pk_q1 == -pk_q2) { if (pk_q1 == 0) { - return is_spike_of_collinear(base::qi(), base::qj(), - base::qk()); + return direction_code(base::rqi(), base::rqj(), base::rqk()) == -1; } return true; @@ -332,26 +499,6 @@ public: } private: - template <typename Point> - inline bool is_spike_of_collinear(Point const& i, Point const& j, - Point const& k) const - { - typedef model::referring_segment<Point const> seg; - - // no need to calcualte direction info - typedef policies::relate::segments_intersection_points - < - intersection_point_type - > policy_type; - - typename policy_type::return_type const result - = m_intersection_strategy.apply(seg(i, j), seg(j, k), - policy_type(), - m_robust_policy); - - return result.count == 2; - } - template <std::size_t OpId> bool is_ip_j() const { diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp index 46c1305cd7..f8272794bd 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp +++ b/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 @@ -41,32 +41,30 @@ struct get_turn_info_linear_areal template < - typename Point1, - typename Point2, + typename UniqueSubRange1, + typename UniqueSubRange2, typename TurnInfo, typename IntersectionStrategy, typename RobustPolicy, typename OutputIterator > static inline OutputIterator apply( - Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, - bool is_p_first, bool is_p_last, - bool is_q_first, bool is_q_last, + 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) { typedef intersection_info < - Point1, Point2, + UniqueSubRange1, UniqueSubRange2, typename TurnInfo::point_type, IntersectionStrategy, RobustPolicy > inters_info; - inters_info inters(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy); + inters_info inters(range_p, range_q, strategy, robust_policy); char const method = inters.d_info().how; @@ -79,10 +77,9 @@ struct get_turn_info_linear_areal case 'a' : // collinear, "at" case 'f' : // collinear, "from" case 's' : // starts from the middle - get_turn_info_for_endpoint<true, true>( - pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters, method_none, out); + get_turn_info_for_endpoint<true, true>(range_p, range_q, + tp_model, inters, method_none, out, + strategy.get_point_in_point_strategy()); break; case 'd' : // disjoint: never do anything @@ -90,10 +87,9 @@ struct get_turn_info_linear_areal case 'm' : { - if ( get_turn_info_for_endpoint<false, true>( - pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters, method_touch_interior, out) ) + if ( get_turn_info_for_endpoint<false, true>(range_p, range_q, + tp_model, inters, method_touch_interior, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -107,25 +103,16 @@ struct get_turn_info_linear_areal // If Q (1) arrives (1) if ( inters.d_info().arrival[1] == 1 ) { - policy::template apply<0>(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), + policy::template apply<0>(range_p, range_q, tp, + inters.i_info(), inters.d_info(), inters.sides()); } else { // Swap p/q - side_calculator - < - typename inters_info::cs_tag, - typename inters_info::robust_point2_type, - typename inters_info::robust_point1_type, - typename inters_info::side_strategy_type - > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), - inters.rpi(), inters.rpj(), inters.rpk(), - inters.get_side_strategy()); - policy::template apply<1>(qi, qj, qk, pi, pj, pk, + policy::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(), - swapped_side_calc); + inters.get_swapped_sides()); } if ( tp.operations[1].operation == operation_blocked ) @@ -139,39 +126,35 @@ 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, is_p_last); + inters, + strategy.get_point_in_point_strategy()); - AssignPolicy::apply(tp, pi, qi, inters); - *out++ = tp; } } break; case 'i' : { - crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info()); + crosses<TurnInfo>::apply(tp, inters.i_info(), inters.d_info()); replace_operations_i(tp.operations[0].operation, tp.operations[1].operation); - AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; case 't' : { // Both touch (both arrive there) - if ( get_turn_info_for_endpoint<false, true>( - pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters, method_touch, out) ) + if ( get_turn_info_for_endpoint<false, true>(range_p, range_q, + tp_model, inters, method_touch, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } else { - touch<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), inters.sides()); + touch<TurnInfo>::apply(range_p, range_q, tp, + inters.i_info(), inters.d_info(), inters.sides()); if ( tp.operations[1].operation == operation_blocked ) { @@ -236,15 +219,13 @@ struct get_turn_info_linear_areal bool ignore_spike = calculate_spike_operation(tp.operations[0].operation, - inters, is_p_last); - -// TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters); + inters, + strategy.get_point_in_point_strategy()); if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) || ignore_spike || ! append_opposite_spikes<append_touches>( // for 'i' or 'c' i??? - tp, inters, is_p_last, is_q_last, out) ) + tp, inters, out) ) { *out++ = tp; } @@ -253,10 +234,9 @@ struct get_turn_info_linear_areal break; case 'e': { - if ( get_turn_info_for_endpoint<true, true>( - pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters, method_equal, out) ) + if ( get_turn_info_for_endpoint<true, true>(range_p, range_q, + tp_model, inters, method_equal, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -268,18 +248,15 @@ struct get_turn_info_linear_areal { // Both equal // or collinear-and-ending at intersection point - equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), inters.sides()); + equal<TurnInfo>::apply(range_p, range_q, tp, + inters.i_info(), inters.d_info(), inters.sides()); turn_transformer_ec<false> transformer(method_touch); transformer(tp); - -// TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters); - + // conditionally handle spikes if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) - || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, + || ! append_collinear_spikes(tp, inters, method_touch, append_equal, out) ) { *out++ = tp; // no spikes @@ -291,7 +268,7 @@ struct get_turn_info_linear_areal < TurnInfo, AssignPolicy - >::apply(pi, qi, + >::apply(range_p, range_q, tp, out, inters); } } @@ -301,9 +278,9 @@ struct get_turn_info_linear_areal { // Collinear if ( get_turn_info_for_endpoint<true, true>( - pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters, method_collinear, out) ) + range_p, range_q, + tp_model, inters, method_collinear, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -319,16 +296,16 @@ struct get_turn_info_linear_areal if ( inters.d_info().arrival[0] == 0 ) { // Collinear, but similar thus handled as equal - equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), inters.sides()); + equal<TurnInfo>::apply(range_p, range_q, tp, + inters.i_info(), inters.d_info(), inters.sides()); method_replace = method_touch; version = append_equal; } else { - collinear<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), inters.sides()); + collinear<TurnInfo>::apply(range_p, range_q, tp, + inters.i_info(), inters.d_info(), inters.sides()); //method_replace = method_touch_interior; //version = append_collinear; @@ -337,12 +314,9 @@ struct get_turn_info_linear_areal turn_transformer_ec<false> transformer(method_replace); transformer(tp); -// TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters); - // conditionally handle spikes if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) - || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, + || ! append_collinear_spikes(tp, inters, method_replace, version, out) ) { // no spikes @@ -358,7 +332,7 @@ struct get_turn_info_linear_areal if ( BOOST_GEOMETRY_CONDITION(handle_spikes) ) { append_opposite_spikes<append_collinear_opposite>( - tp, inters, is_p_last, is_q_last, out); + tp, inters, out); } // TODO: ignore for spikes? @@ -369,10 +343,9 @@ struct get_turn_info_linear_areal < TurnInfo, AssignPolicy - >::apply(pi, pj, pk, qi, qj, qk, + >::apply(range_p, range_q, tp, out, inters, - inters.sides(), transformer, - !is_p_last, true); // qk is always valid + inters.sides(), transformer); } } } @@ -384,19 +357,20 @@ struct get_turn_info_linear_areal { only_convert::apply(tp, inters.i_info()); - if ( is_p_first - && equals::equals_point_point(pi, tp.point) ) + if ( range_p.is_first_segment() + && equals::equals_point_point(range_p.at(0), tp.point, + strategy.get_point_in_point_strategy()) ) { tp.operations[0].position = position_front; } - else if ( is_p_last - && equals::equals_point_point(pj, tp.point) ) + else if ( range_p.is_last_segment() + && equals::equals_point_point(range_p.at(1), tp.point, + strategy.get_point_in_point_strategy()) ) { tp.operations[0].position = position_back; } // tp.operations[1].position = position_middle; - AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } } @@ -417,13 +391,13 @@ struct get_turn_info_linear_areal } template <typename Operation, - typename IntersectionInfo> + typename IntersectionInfo, + typename EqPPStrategy> static inline bool calculate_spike_operation(Operation & op, IntersectionInfo const& inters, - bool is_p_last) + EqPPStrategy const& strategy) { bool is_p_spike = ( op == operation_union || op == operation_intersection ) - && ! is_p_last && inters.is_spike_p(); if ( is_p_spike ) @@ -441,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 @@ -453,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 @@ -483,7 +457,6 @@ struct get_turn_info_linear_areal typename OutIt> static inline bool append_collinear_spikes(TurnInfo & tp, IntersectionInfo const& inters, - bool is_p_last, bool /*is_q_last*/, method_type method, append_version_c version, OutIt out) { @@ -494,7 +467,6 @@ struct get_turn_info_linear_areal ( tp.operations[0].operation == operation_union || tp.operations[0].operation == operation_intersection ) : tp.operations[0].operation == operation_continue ) - && ! is_p_last && inters.is_spike_p(); // TODO: throw an exception for spike in Areal? @@ -543,7 +515,6 @@ struct get_turn_info_linear_areal typename OutIt> static inline bool append_opposite_spikes(TurnInfo & tp, IntersectionInfo const& inters, - bool is_p_last, bool /*is_q_last*/, OutIt out) { static const bool is_version_touches = (Version == append_touches); @@ -552,7 +523,6 @@ struct get_turn_info_linear_areal ( tp.operations[0].operation == operation_continue || tp.operations[0].operation == operation_intersection ) : // i ??? true ) - && ! is_p_last && inters.is_spike_p(); // TODO: throw an exception for spike in Areal? @@ -586,8 +556,6 @@ struct get_turn_info_linear_areal BOOST_GEOMETRY_ASSERT(inters.i_info().count > 1); base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); - - AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); } tp.operations[0].operation = operation_blocked; @@ -706,35 +674,46 @@ struct get_turn_info_linear_areal template <bool EnableFirst, bool EnableLast, - typename Point1, - typename Point2, + typename UniqueSubRange1, + typename UniqueSubRange2, typename TurnInfo, typename IntersectionInfo, - typename OutputIterator> + typename OutputIterator, + typename EqPPStrategy> static inline bool get_turn_info_for_endpoint( - Point1 const& pi, Point1 const& /*pj*/, Point1 const& /*pk*/, - Point2 const& qi, Point2 const& /*qj*/, Point2 const& /*qk*/, - bool is_p_first, bool is_p_last, - bool /*is_q_first*/, bool is_q_last, + 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<AssignPolicy, EnableFirst, EnableLast> get_info_e; + typedef ov::get_turn_info_for_endpoint<EnableFirst, EnableLast> get_info_e; const std::size_t ip_count = inters.i_info().count; // no intersection points - if ( ip_count == 0 ) + if (ip_count == 0) + { return false; + } - if ( !is_p_first && !is_p_last ) + if (! range_p.is_first_segment() && ! range_p.is_last_segment()) + { + // P sub-range has no end-points return false; + } -// TODO: is_q_last could probably be replaced by false and removed from parameters + typename IntersectionInfo::side_strategy_type const& sides + = inters.get_side_strategy(); - linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last); + linear_intersections intersections(range_p.at(0), + range_q.at(0), + inters.result(), + range_p.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>(); @@ -745,7 +724,7 @@ struct get_turn_info_linear_areal // IP on the first point of Linear Geometry bool was_first_point_handled = false; if ( BOOST_GEOMETRY_CONDITION(EnableFirst) - && is_p_first && ip0.is_pi && !ip0.is_qi ) // !q0i prevents duplication + && range_p.is_first_segment() && ip0.is_pi && !ip0.is_qi ) // !q0i prevents duplication { TurnInfo tp = tp_model; tp.operations[0].position = position_front; @@ -759,51 +738,40 @@ struct get_turn_info_linear_areal } else { - typedef typename IntersectionInfo::robust_point1_type rp1_type; - typedef typename IntersectionInfo::robust_point2_type rp2_type; - - method_type replaced_method = method_touch_interior; - + // 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 + // x: qi-qj, y: qj-qk, qz: qk + // 2. pi in the middle of q1: qi-pi-pj and qi-pi-qj + // x: qi-pi, y: pi-qj, qz: qj + // qi-pi, side the same as WRT q1 + // pi-qj, side the same as WRT q1 + // qj WRT q1 is 0 + method_type replaced_method = method_none; + int side_pj_y = 0, side_pj_x = 0, side_qz_x = 0; + // 1. ip0 or pi at qj if ( ip0.is_qj ) { - side_calculator - < - typename IntersectionInfo::cs_tag, - rp1_type, rp2_type, - typename IntersectionInfo::side_strategy_type, - rp2_type - > side_calc(inters.rqi(), inters.rpi(), inters.rpj(), - inters.rqi(), inters.rqj(), inters.rqk(), - inters.get_side_strategy()); - - std::pair<operation_type, operation_type> - operations = get_info_e::operations_of_equal(side_calc); - - tp.operations[0].operation = operations.first; - tp.operations[1].operation = operations.second; - replaced_method = method_touch; + side_pj_y = sides.apply(range_q.at(1), range_q.at(2), range_p.at(1)); // pj wrt q2 + side_pj_x = sides.apply(range_q.at(0), range_q.at(1), range_p.at(1)); // pj wrt q1 + side_qz_x = sides.apply(range_q.at(0), range_q.at(1), range_q.at(2)); // qk wrt q1 } + // 2. ip0 or pi in the middle of q1 else { - side_calculator - < - typename IntersectionInfo::cs_tag, - rp1_type, rp2_type, - typename IntersectionInfo::side_strategy_type, - rp2_type, rp1_type, rp1_type, - rp2_type, rp1_type, rp2_type - > side_calc(inters.rqi(), inters.rpi(), inters.rpj(), - inters.rqi(), inters.rpi(), inters.rqj(), - inters.get_side_strategy()); - - std::pair<operation_type, operation_type> - operations = get_info_e::operations_of_equal(side_calc); - - tp.operations[0].operation = operations.first; - tp.operations[1].operation = operations.second; + replaced_method = method_touch_interior; + side_pj_y = sides.apply(range_q.at(0), range_q.at(1), range_p.at(1)); // pj wrt q1 + side_pj_x = side_pj_y; // pj wrt q1 + side_qz_x = 0; // qj wrt q1 } + std::pair<operation_type, operation_type> operations + = get_info_e::operations_of_equal(side_pj_y, side_pj_x, side_qz_x); + + tp.operations[0].operation = operations.first; + tp.operations[1].operation = operations.second; + turn_transformer_ec<true> transformer(replaced_method); transformer(tp); } @@ -817,7 +785,6 @@ struct get_turn_info_linear_areal // here is_p_first_ip == true tp.operations[0].is_collinear = false; - AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; was_first_point_handled = true; @@ -827,7 +794,7 @@ struct get_turn_info_linear_areal // IP on the last point of Linear Geometry if ( BOOST_GEOMETRY_CONDITION(EnableLast) - && is_p_last + && range_p.is_last_segment() && ( ip_count > 1 ? (ip1.is_pj && !ip1.is_qi) : (ip0.is_pj && !ip0.is_qi) ) ) // prevents duplication { TurnInfo tp = tp_model; @@ -840,19 +807,33 @@ struct get_turn_info_linear_areal } else //if ( result.template get<0>().count == 1 ) { - side_calculator - < - typename IntersectionInfo::cs_tag, - typename IntersectionInfo::robust_point1_type, - typename IntersectionInfo::robust_point2_type, - typename IntersectionInfo::side_strategy_type, - typename IntersectionInfo::robust_point2_type - > side_calc(inters.rqi(), inters.rpj(), inters.rpi(), - inters.rqi(), inters.rqj(), inters.rqk(), - inters.get_side_strategy()); - - std::pair<operation_type, operation_type> - operations = get_info_e::operations_of_equal(side_calc); + // pj is the intersection point at qj or in the middle of q1 + // so consider segments + // 1. pj at qj: qi-qj-pi and qi-qj-qk + // x: qi-qj, y: qj-qk, qz: qk + // 2. pj in the middle of q1: qi-pj-pi and qi-pj-qj + // x: qi-pj, y: pj-qj, qz: qj + // qi-pj, the side is the same as WRT q1 + // pj-qj, the side is the same as WRT q1 + // side of qj WRT q1 is 0 + int side_pi_y = 0, side_pi_x = 0, side_qz_x = 0; + // 1. ip0 or pj at qj + if ( ip0.is_qj ) + { + side_pi_y = sides.apply(range_q.at(1), range_q.at(2), range_p.at(0)); // pi wrt q2 + side_pi_x = sides.apply(range_q.at(0), range_q.at(1), range_p.at(0)); // pi wrt q1 + side_qz_x = sides.apply(range_q.at(0), range_q.at(1), range_q.at(2)); // qk wrt q1 + } + // 2. ip0 or pj in the middle of q1 + else + { + side_pi_y = sides.apply(range_q.at(0), range_q.at(1), range_p.at(0)); // pi wrt q1 + side_pi_x = side_pi_y; // pi wrt q1 + side_qz_x = 0; // qj wrt q1 + } + + std::pair<operation_type, operation_type> operations + = get_info_e::operations_of_equal(side_pi_y, side_pi_x, side_qz_x); tp.operations[0].operation = operations.first; tp.operations[1].operation = operations.second; @@ -873,7 +854,6 @@ struct get_turn_info_linear_areal unsigned int ip_index = ip_count > 1 ? 1 : 0; base_turn_handler::assign_point(tp, tp.method, inters.i_info(), ip_index); - AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; // don't ignore the first IP if the segment is opposite @@ -883,6 +863,14 @@ struct get_turn_info_linear_areal // don't ignore anything for now return false; } + + template <typename Point1, typename Point2, typename IntersectionStrategy> + 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/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp index 58fd4bb5c7..217f4a340b 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp +++ b/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 @@ -36,18 +36,16 @@ struct get_turn_info_linear_linear template < - typename Point1, - typename Point2, + typename UniqueSubRange1, + typename UniqueSubRange2, typename TurnInfo, typename IntersectionStrategy, typename RobustPolicy, typename OutputIterator > static inline OutputIterator apply( - Point1 const& pi, Point1 const& pj, Point1 const& pk, - Point2 const& qi, Point2 const& qj, Point2 const& qk, - bool is_p_first, bool is_p_last, - bool is_q_first, bool is_q_last, + UniqueSubRange1 const& range_p, + UniqueSubRange2 const& range_q, TurnInfo const& tp_model, IntersectionStrategy const& strategy, RobustPolicy const& robust_policy, @@ -55,13 +53,13 @@ struct get_turn_info_linear_linear { typedef intersection_info < - Point1, Point2, + UniqueSubRange1, UniqueSubRange2, typename TurnInfo::point_type, IntersectionStrategy, RobustPolicy > inters_info; - inters_info inters(pi, pj, pk, qi, qj, qk, strategy, robust_policy); + inters_info inters(range_p, range_q, strategy, robust_policy); char const method = inters.d_info().how; @@ -74,10 +72,10 @@ struct get_turn_info_linear_linear case 'a' : // collinear, "at" case 'f' : // collinear, "from" case 's' : // starts from the middle - get_turn_info_for_endpoint<AssignPolicy, true, true> - ::apply(pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters, method_none, out); + get_turn_info_for_endpoint<true, true> + ::apply(range_p, range_q, + tp_model, inters, method_none, out, + strategy.get_point_in_point_strategy()); break; case 'd' : // disjoint: never do anything @@ -85,10 +83,10 @@ struct get_turn_info_linear_linear case 'm' : { - if ( get_turn_info_for_endpoint<AssignPolicy, false, true> - ::apply(pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters, method_touch_interior, out) ) + if ( get_turn_info_for_endpoint<false, true> + ::apply(range_p, range_q, + tp_model, inters, method_touch_interior, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -102,26 +100,16 @@ struct get_turn_info_linear_linear // If Q (1) arrives (1) if ( inters.d_info().arrival[1] == 1) { - policy::template apply<0>(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), + policy::template apply<0>(range_p, range_q, tp, + inters.i_info(), inters.d_info(), inters.sides()); } else { // Swap p/q - side_calculator - < - typename inters_info::cs_tag, - typename inters_info::robust_point2_type, - typename inters_info::robust_point1_type, - typename inters_info::side_strategy_type - > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), - inters.rpi(), inters.rpj(), inters.rpk(), - inters.get_side_strategy()); - - policy::template apply<1>(qi, qj, qk, pi, pj, pk, - tp, inters.i_info(), inters.d_info(), - swapped_side_calc); + policy::template apply<1>(range_q, range_p, tp, + inters.i_info(), inters.d_info(), + inters.get_swapped_sides()); } if ( tp.operations[0].operation == operation_blocked ) @@ -137,36 +125,33 @@ struct get_turn_info_linear_linear tp.operations[0].operation, tp.operations[1].operation); - AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } } break; case 'i' : { - crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info()); + crosses<TurnInfo>::apply(tp, inters.i_info(), inters.d_info()); replace_operations_i(tp.operations[0].operation, tp.operations[1].operation); - AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } break; case 't' : { // Both touch (both arrive there) - if ( get_turn_info_for_endpoint<AssignPolicy, false, true> - ::apply(pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters, method_touch, out) ) + if ( get_turn_info_for_endpoint<false, true> + ::apply(range_p, range_q, + tp_model, inters, method_touch, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } else { - touch<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), inters.sides()); + touch<TurnInfo>::apply(range_p, range_q, tp, + inters.i_info(), inters.d_info(), inters.sides()); // workarounds for touch<> not taking spikes into account starts here // those was discovered empirically @@ -276,13 +261,8 @@ struct get_turn_info_linear_linear tp.operations[0].operation, tp.operations[1].operation); -// TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters); - if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) - || ! append_opposite_spikes<append_touches>(tp, inters, - is_p_last, is_q_last, - out) ) + || ! append_opposite_spikes<append_touches>(tp, inters, out) ) { *out++ = tp; } @@ -291,10 +271,10 @@ struct get_turn_info_linear_linear break; case 'e': { - if ( get_turn_info_for_endpoint<AssignPolicy, true, true> - ::apply(pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters, method_equal, out) ) + if ( get_turn_info_for_endpoint<true, true> + ::apply(range_p, range_q, + tp_model, inters, method_equal, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -307,8 +287,8 @@ struct get_turn_info_linear_linear { // Both equal // or collinear-and-ending at intersection point - equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), inters.sides()); + equal<TurnInfo>::apply(range_p, range_q, tp, + inters.i_info(), inters.d_info(), inters.sides()); operation_type spike_op = ( tp.operations[0].operation != operation_continue @@ -320,13 +300,9 @@ struct get_turn_info_linear_linear turn_transformer_ec transformer(method_touch); transformer(tp); -// TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters); - // conditionally handle spikes if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) || ! append_collinear_spikes(tp, inters, - is_p_last, is_q_last, method_touch, spike_op, out) ) { @@ -341,7 +317,7 @@ struct get_turn_info_linear_linear < TurnInfo, AssignPolicy - >::apply(pi, qi, tp, out, inters); + >::apply(range_p, range_q, tp, out, inters); } } } @@ -349,10 +325,10 @@ struct get_turn_info_linear_linear case 'c' : { // Collinear - if ( get_turn_info_for_endpoint<AssignPolicy, true, true> - ::apply(pi, pj, pk, qi, qj, qk, - is_p_first, is_p_last, is_q_first, is_q_last, - tp_model, inters, method_collinear, out) ) + if ( get_turn_info_for_endpoint<true, true> + ::apply(range_p, range_q, + tp_model, inters, method_collinear, out, + strategy.get_point_in_point_strategy()) ) { // do nothing } @@ -370,8 +346,8 @@ struct get_turn_info_linear_linear if ( inters.d_info().arrival[0] == 0 ) { // Collinear, but similar thus handled as equal - equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, - tp, inters.i_info(), inters.d_info(), inters.sides()); + equal<TurnInfo>::apply(range_p, range_q, tp, + inters.i_info(), inters.d_info(), inters.sides()); method_replace = method_touch; if ( tp.operations[0].operation != operation_continue @@ -382,7 +358,7 @@ struct get_turn_info_linear_linear } else { - collinear<TurnInfo>::apply(pi, pj, pk, qi, qj, qk, + collinear<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides()); //method_replace = method_touch_interior; @@ -393,13 +369,9 @@ struct get_turn_info_linear_linear turn_transformer_ec transformer(method_replace); transformer(tp); -// TODO: move this into the append_xxx and call for each turn? - AssignPolicy::apply(tp, pi, qi, inters); - // conditionally handle spikes if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) || ! append_collinear_spikes(tp, inters, - is_p_last, is_q_last, method_replace, spike_op, out) ) { @@ -415,9 +387,7 @@ struct get_turn_info_linear_linear // conditionally handle spikes if ( BOOST_GEOMETRY_CONDITION(handle_spikes) ) { - append_opposite_spikes<append_collinear_opposite>(tp, inters, - is_p_last, is_q_last, - out); + append_opposite_spikes<append_collinear_opposite>(tp, inters, out); } // TODO: ignore for spikes? @@ -428,9 +398,9 @@ struct get_turn_info_linear_linear < TurnInfo, AssignPolicy - >::apply(pi, pj, pk, qi, qj, qk, + >::apply(range_p, range_q, tp, out, inters, inters.sides(), - transformer, !is_p_last, !is_q_last); + transformer); } } } @@ -440,31 +410,33 @@ 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 ( is_p_first - && equals::equals_point_point(pi, tp.point) ) + if ( range_p.is_first_segment() + && equals::equals_point_point(range_p.at(0), tp.point, equals_strategy_type()) ) { tp.operations[0].position = position_front; } - else if ( is_p_last - && equals::equals_point_point(pj, tp.point) ) + else if ( range_p.is_last_segment() + && equals::equals_point_point(range_p.at(1), tp.point, equals_strategy_type()) ) { tp.operations[0].position = position_back; } - else if ( is_q_first - && equals::equals_point_point(qi, tp.point) ) + else if ( range_q.is_first_segment() + && equals::equals_point_point(range_q.at(0), tp.point, equals_strategy_type()) ) { tp.operations[1].position = position_front; } - else if ( is_q_last - && equals::equals_point_point(qj, tp.point) ) + else if ( range_q.is_last_segment() + && equals::equals_point_point(range_q.at(1), tp.point, equals_strategy_type()) ) { tp.operations[1].position = position_back; } - AssignPolicy::apply(tp, pi, qi, inters); *out++ = tp; } } @@ -489,7 +461,6 @@ struct get_turn_info_linear_linear typename OutIt> static inline bool append_collinear_spikes(TurnInfo & tp, IntersectionInfo const& inters_info, - bool is_p_last, bool is_q_last, method_type method, operation_type spike_op, OutIt out) { @@ -497,10 +468,8 @@ struct get_turn_info_linear_linear // both position == middle bool is_p_spike = tp.operations[0].operation == spike_op - && ! is_p_last && inters_info.is_spike_p(); bool is_q_spike = tp.operations[1].operation == spike_op - && ! is_q_last && inters_info.is_spike_q(); if ( is_p_spike && is_q_spike ) @@ -559,7 +528,6 @@ struct get_turn_info_linear_linear typename OutIt> static inline bool append_opposite_spikes(TurnInfo & tp, IntersectionInfo const& inters, - bool is_p_last, bool is_q_last, OutIt out) { static const bool is_version_touches = (Version == append_touches); @@ -568,13 +536,11 @@ struct get_turn_info_linear_linear ( tp.operations[0].operation == operation_continue || tp.operations[0].operation == operation_intersection ) : true ) - && ! is_p_last && inters.is_spike_p(); bool is_q_spike = ( is_version_touches ? ( tp.operations[1].operation == operation_continue || tp.operations[1].operation == operation_intersection ) : true ) - && ! is_q_last && inters.is_spike_q(); bool res = false; @@ -598,8 +564,6 @@ struct get_turn_info_linear_linear base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); - - AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); } tp.operations[0].operation = operation_blocked; @@ -630,8 +594,6 @@ struct get_turn_info_linear_linear BOOST_GEOMETRY_ASSERT(inters.i_info().count > 0); base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0); - - AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); } tp.operations[0].operation = operation_intersection; diff --git a/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/algorithms/detail/overlay/get_turns.hpp index 042e65b4e1..886f8b683f 100644 --- a/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/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 @@ -27,6 +27,7 @@ #include <boost/range.hpp> #include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> @@ -101,6 +102,113 @@ struct no_interrupt_policy } }; +template +< + bool IsAreal, + typename Section, + typename Point, + typename CircularIterator, + typename IntersectionStrategy, + typename RobustPolicy +> +struct unique_sub_range_from_section +{ + typedef Point point_type; + + unique_sub_range_from_section(Section const& section, signed_size_type index, + CircularIterator circular_iterator, + Point const& previous, Point const& current, + RobustPolicy const& robust_policy) + : m_section(section) + , m_index(index) + , m_previous_point(previous) + , m_current_point(current) + , m_circular_iterator(circular_iterator) + , m_point_retrieved(false) + , m_robust_policy(robust_policy) + { + } + + inline bool is_first_segment() const + { + return !IsAreal && m_section.is_non_duplicate_first && m_index == m_section.begin_index; + } + inline bool is_last_segment() const + { + return size() == 2u; + } + + inline std::size_t size() const + { + return IsAreal ? 3 + : m_section.is_non_duplicate_last && m_index + 1 >= m_section.end_index ? 2 : 3; + } + + inline Point const& at(std::size_t index) const + { + BOOST_GEOMETRY_ASSERT(index < size()); + switch (index) + { + case 0 : return m_previous_point; + case 1 : return m_current_point; + case 2 : return get_next_point(); + default : return m_previous_point; + } + } + +private : + inline Point const& get_next_point() const + { + if (! m_point_retrieved) + { + advance_to_non_duplicate_next(m_current_point, m_circular_iterator); + m_point = *m_circular_iterator; + m_point_retrieved = true; + } + return m_point; + } + + 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<Point, RobustPolicy>::type robust_point_type; + robust_point_type current_robust_point; + robust_point_type next_robust_point; + geometry::recalculate(current_robust_point, current, m_robust_policy); + geometry::recalculate(next_robust_point, *circular_iterator, m_robust_policy); + + // To see where the next segments bend to, in case of touch/intersections + // on end points, we need (in case of degenerate/duplicate points) an extra + // iterator which moves to the REAL next point, so non duplicate. + // This needs an extra comparison (disjoint). + // (Note that within sections, non duplicate points are already asserted, + // by the sectionalize process). + + // So advance to the "non duplicate next" + // (the check is defensive, to avoid endless loops) + std::size_t check = 0; + while(! detail::disjoint::disjoint_point_point + ( + current_robust_point, next_robust_point, + disjoint_strategy_type() + ) + && check++ < m_section.range_count) + { + circular_iterator++; + geometry::recalculate(next_robust_point, *circular_iterator, m_robust_policy); + } + } + + Section const& m_section; + signed_size_type m_index; + Point const& m_previous_point; + Point const& m_current_point; + mutable CircularIterator m_circular_iterator; + mutable Point m_point; + mutable bool m_point_retrieved; + RobustPolicy m_robust_policy; +}; + template < @@ -143,6 +251,8 @@ class get_turns_in_sections view_type2 const >::type range2_iterator; + typedef ever_circling_iterator<range1_iterator> circular1_iterator; + typedef ever_circling_iterator<range2_iterator> circular2_iterator; template <typename Geometry, typename Section> static inline bool adjacent(Section const& section, @@ -187,6 +297,18 @@ public : { boost::ignore_unused(interrupt_policy); + static bool const areal1 = boost::is_same + < + typename tag_cast<typename tag<Geometry1>::type, areal_tag>::type, + areal_tag + >::type::value; + static bool const areal2 = boost::is_same + < + typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type, + areal_tag + >::type::value; + + if ((sec1.duplicate && (sec1.count + 1) < sec1.range_count) || (sec2.duplicate && (sec2.count + 1) < sec2.range_count)) { @@ -230,9 +352,14 @@ public : it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec1.bounding_box, sec2.bounding_box, robust_policy); ++prev1, ++it1, ++index1, ++next1, ++ndi1) { - ever_circling_iterator<range1_iterator> nd_next1( - begin_range_1, end_range_1, next1, true); - advance_to_non_duplicate_next(nd_next1, it1, sec1, 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; @@ -278,10 +405,14 @@ public : if (! skip) { - // Move to the "non duplicate next" - ever_circling_iterator<range2_iterator> nd_next2( - begin_range_2, end_range_2, next2, true); - advance_to_non_duplicate_next(nd_next2, it2, sec2, 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<Turns>::type turn_info; @@ -295,13 +426,7 @@ public : std::size_t const size_before = boost::size(turns); - bool const is_1_first = sec1.is_non_duplicate_first && index1 == sec1.begin_index; - bool const is_1_last = sec1.is_non_duplicate_last && index1+1 >= sec1.end_index; - bool const is_2_first = sec2.is_non_duplicate_first && index2 == sec2.begin_index; - bool const is_2_last = sec2.is_non_duplicate_last && index2+1 >= sec2.end_index; - - TurnPolicy::apply(*prev1, *it1, *nd_next1, *prev2, *it2, *nd_next2, - is_1_first, is_1_last, is_2_first, is_2_last, + TurnPolicy::apply(unique_sub_range1, unique_sub_range2, ti, intersection_strategy, robust_policy, std::back_inserter(turns)); @@ -327,37 +452,6 @@ private : typedef typename model::referring_segment<point1_type const> segment1_type; typedef typename model::referring_segment<point2_type const> segment2_type; - template <typename Iterator, typename RangeIterator, typename Section, typename RobustPolicy> - static inline void advance_to_non_duplicate_next(Iterator& next, - RangeIterator const& it, Section const& section, RobustPolicy const& robust_policy) - { - typedef typename robust_point_type<point1_type, RobustPolicy>::type robust_point_type; - robust_point_type robust_point_from_it; - robust_point_type robust_point_from_next; - geometry::recalculate(robust_point_from_it, *it, robust_policy); - geometry::recalculate(robust_point_from_next, *next, robust_policy); - - // To see where the next segments bend to, in case of touch/intersections - // on end points, we need (in case of degenerate/duplicate points) an extra - // iterator which moves to the REAL next point, so non duplicate. - // This needs an extra comparison (disjoint). - // (Note that within sections, non duplicate points are already asserted, - // by the sectionalize process). - - // So advance to the "non duplicate next" - // (the check is defensive, to avoid endless loops) - std::size_t check = 0; - while(! detail::disjoint::disjoint_point_point - ( - robust_point_from_it, robust_point_from_next - ) - && check++ < section.range_count) - { - next++; - geometry::recalculate(robust_point_from_next, *next, robust_policy); - } - } - // It is NOT possible to have section-iterators here // because of the logistics of "index" (the section-iterator automatically // skips to the begin-point, we loose the index or have to recalculate it) @@ -423,7 +517,9 @@ struct section_visitor template <typename Section> 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 @@ -482,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<Reverse1, dimensions>(geometry1, robust_policy, - sec1, envelope_strategy, 0); + sec1, envelope_strategy, expand_strategy, 0); geometry::sectionalize<Reverse2, dimensions>(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 @@ -500,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()); } }; @@ -519,8 +626,9 @@ template > struct get_turns_cs { - typedef typename geometry::point_type<Range>::type point_type; + typedef typename geometry::point_type<Range>::type range_point_type; typedef typename geometry::point_type<Box>::type box_point_type; + typedef boost::array<box_point_type, 4> box_array; typedef typename closeable_view < @@ -539,6 +647,70 @@ struct get_turns_cs view_type const >::type iterator_type; + struct unique_sub_range_from_box_policy + { + typedef box_point_type point_type; + + unique_sub_range_from_box_policy(box_array const& box) + : m_box(box) + , m_index(0) + {} + + static inline bool is_first_segment() { return false; } + static inline bool is_last_segment() { return false; } + static inline std::size_t size() { return 4; } + + inline box_point_type const& at(std::size_t index) const + { + BOOST_GEOMETRY_ASSERT(index < size()); + return m_box[(m_index + index) % 4]; + } + + inline void next() + { + m_index++; + } + + private : + box_array const& m_box; + std::size_t m_index; + }; + + struct unique_sub_range_from_view_policy + { + typedef range_point_type point_type; + + unique_sub_range_from_view_policy(view_type const& view, point_type const& pi, point_type const& pj, iterator_type it) + : m_view(view) + , m_pi(pi) + , m_pj(pj) + , m_circular_iterator(boost::begin(view), boost::end(view), it, true) + { + ++m_circular_iterator; + } + + static inline bool is_first_segment() { return false; } + static inline bool is_last_segment() { return false; } + static inline std::size_t size() { return 3; } + + inline point_type const& at(std::size_t index) const + { + BOOST_GEOMETRY_ASSERT(index < size()); + switch (index) + { + case 0 : return m_pi; + case 1 : return m_pj; + case 2 : return *m_circular_iterator; + default : return m_pi; + } + } + + private : + view_type const& m_view; + point_type const& m_pi; + point_type const& m_pj; + ever_circling_iterator<iterator_type> m_circular_iterator; + }; template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> static inline void apply( @@ -556,22 +728,16 @@ struct get_turns_cs return; } - boost::array<box_point_type,4> bp; - assign_box_corners_oriented<ReverseBox>(box, bp); + box_array box_points; + assign_box_corners_oriented<ReverseBox>(box, box_points); cview_type cview(range); view_type view(cview); - typedef typename boost::range_size<view_type>::type size_type; - size_type segments_count1 = boost::size(view) - 1; - + // TODO: in this code, possible duplicate points are not yet taken + // into account (not in the iterator, nor in the retrieve policy) iterator_type it = boost::begin(view); - ever_circling_iterator<iterator_type> next( - boost::begin(view), boost::end(view), it, true); - next++; - next++; - //bool first = true; //char previous_side[2] = {0, 0}; @@ -580,11 +746,13 @@ struct get_turns_cs for (iterator_type prev = it++; it != boost::end(view); - prev = it++, next++, index++) + prev = it++, index++) { segment_identifier seg_id(source_id1, multi_index, ring_index, index); + unique_sub_range_from_view_policy view_unique_sub_range(view, *prev, *it, it); + /*if (first) { previous_side[0] = get_side<0>(box, *prev); @@ -611,11 +779,8 @@ struct get_turns_cs if (true) { get_turns_with_box(seg_id, source_id2, - *prev, *it, *next, - bp[0], bp[1], bp[2], bp[3], - // NOTE: some dummy values could be passed below since this would be called only for Polygons and Boxes - index == 0, - size_type(index) == segments_count1, + view_unique_sub_range, + box_points, intersection_strategy, robust_policy, turns, @@ -647,19 +812,16 @@ private: else return 0; } - template <typename IntersectionStrategy, typename RobustPolicy, typename Turns, typename InterruptPolicy> + template + < + typename IntersectionStrategy, + typename Turns, + typename InterruptPolicy, + typename RobustPolicy + > static inline void get_turns_with_box(segment_identifier const& seg_id, int source_id2, - // Points from a range: - point_type const& rp0, - point_type const& rp1, - point_type const& rp2, - // Points from the box - box_point_type const& bp0, - box_point_type const& bp1, - box_point_type const& bp2, - box_point_type const& bp3, - bool const is_range_first, - bool const is_range_last, + unique_sub_range_from_view_policy const& range_unique_sub_range, + box_array const& box, IntersectionStrategy const& intersection_strategy, RobustPolicy const& robust_policy, // Output @@ -675,31 +837,27 @@ private: turn_info ti; ti.operations[0].seg_id = seg_id; + unique_sub_range_from_box_policy box_unique_sub_range(box); ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 0); - TurnPolicy::apply(rp0, rp1, rp2, bp0, bp1, bp2, - is_range_first, is_range_last, - true, false, + TurnPolicy::apply(range_unique_sub_range, box_unique_sub_range, ti, intersection_strategy, robust_policy, std::back_inserter(turns)); ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 1); - TurnPolicy::apply(rp0, rp1, rp2, bp1, bp2, bp3, - is_range_first, is_range_last, - false, false, + box_unique_sub_range.next(); + TurnPolicy::apply(range_unique_sub_range, box_unique_sub_range, ti, intersection_strategy, robust_policy, std::back_inserter(turns)); ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 2); - TurnPolicy::apply(rp0, rp1, rp2, bp2, bp3, bp0, - is_range_first, is_range_last, - false, false, + box_unique_sub_range.next(); + TurnPolicy::apply(range_unique_sub_range, box_unique_sub_range, ti, intersection_strategy, robust_policy, std::back_inserter(turns)); ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3); - TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1, - is_range_first, is_range_last, - false, true, + box_unique_sub_range.next(); + TurnPolicy::apply(range_unique_sub_range, box_unique_sub_range, ti, intersection_strategy, robust_policy, std::back_inserter(turns)); diff --git a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp index 21d079d95c..f0a7d6a7a8 100644 --- a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp +++ b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp @@ -139,18 +139,6 @@ protected: static bool const include_no_turn = false; static bool const include_degenerate = EnableDegenerateTurns; static bool const include_opposite = false; - - template - < - typename Info, - typename Point1, - typename Point2, - typename IntersectionInfo - > - static inline void apply(Info& , Point1 const& , Point2 const& , - IntersectionInfo const& ) - { - } }; diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp index 5094c6c96c..8a8561c136 100644 --- a/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -125,6 +125,12 @@ inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns, C bool cluster_checked = false; bool has_blocked = false; + if (is_self_turn<OverlayType>(turn) && turn.discarded) + { + // Discarded self-turns don't count as traversed + continue; + } + for (typename boost::range_iterator<container_type const>::type op_it = boost::begin(turn.operations); op_it != boost::end(turn.operations); diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp index 88aedecf86..afe8f680be 100644 --- a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp +++ b/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<PointOut, OverlayType> 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/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/boost/geometry/algorithms/detail/overlay/select_rings.hpp index 262ba748ab..9b88ddf8b4 100644 --- a/boost/geometry/algorithms/detail/overlay/select_rings.hpp +++ b/boost/geometry/algorithms/detail/overlay/select_rings.hpp @@ -21,7 +21,6 @@ #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/algorithms/area.hpp> #include <boost/geometry/algorithms/covered_by.hpp> #include <boost/geometry/algorithms/detail/interior_iterator.hpp> #include <boost/geometry/algorithms/detail/ring_identifier.hpp> diff --git a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp index 3cc98d3b7e..261d2c4b03 100644 --- a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp +++ b/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 <typename Section> 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<Reverse, dimensions>(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; } @@ -324,6 +336,8 @@ inline void self_turns(Geometry const& geometry, \param turns container which will contain intersection points \param interrupt_policy policy determining if process is stopped when intersection is found + \param source_index source index for generated turns + \param skip_adjacent indicates if adjacent turns should be skipped */ template < diff --git a/boost/geometry/algorithms/detail/overlay/stream_info.hpp b/boost/geometry/algorithms/detail/overlay/stream_info.hpp index 51fd1b3dca..307d9ff805 100644 --- a/boost/geometry/algorithms/detail/overlay/stream_info.hpp +++ b/boost/geometry/algorithms/detail/overlay/stream_info.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) @@ -12,7 +17,7 @@ #include <string> -#include <boost/array.hpp> +#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> namespace boost { namespace geometry @@ -32,8 +37,8 @@ namespace detail { namespace overlay return h == 0 ? "-" : (h == 1 ? "A" : "D"); } - template <typename P> - std::ostream& operator<<(std::ostream &os, turn_info<P> const& info) + template <typename P, typename SR, typename O, typename C> + std::ostream& operator<<(std::ostream &os, turn_info<P, SR, O, C> const& info) { os << "\t" << " src " << info.seg_id.source_index @@ -46,10 +51,10 @@ namespace detail { namespace overlay << (info.opposite ? " o" : "") << "]" << " sd " - << dir(info.sides.get<0,0>()) - << dir(info.sides.get<0,1>()) - << dir(info.sides.get<1,0>()) - << dir(info.sides.get<1,1>()) + << dir(info.sides.template get<0,0>()) + << dir(info.sides.template get<0,1>()) + << dir(info.sides.template get<1,0>()) + << dir(info.sides.template get<1,1>()) << " nxt seg " << info.travels_to_vertex_index << " , ip " << info.travels_to_ip_index << " , or " << info.next_ip_index diff --git a/boost/geometry/algorithms/detail/overlay/traversal.hpp b/boost/geometry/algorithms/detail/overlay/traversal.hpp index 90ee240138..3a7d82ce0a 100644 --- a/boost/geometry/algorithms/detail/overlay/traversal.hpp +++ b/boost/geometry/algorithms/detail/overlay/traversal.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017. -// Modifications copyright (c) 2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018. +// Modifications copyright (c) 2017-2018 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -15,9 +15,11 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_HPP #include <cstddef> +#include <set> #include <boost/range.hpp> +#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp> #include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp> #include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> @@ -103,6 +105,23 @@ template > struct traversal { +private : + struct linked_turn_op_info + { + explicit linked_turn_op_info(signed_size_type ti = -1, int oi = -1, + signed_size_type nti = -1) + : turn_index(ti) + , op_index(oi) + , next_turn_index(nti) + , rank_index(-1) + {} + + signed_size_type turn_index; + int op_index; + signed_size_type next_turn_index; + signed_size_type rank_index; + }; + static const operation_type target_operation = operation_from_overlay<OverlayType>::value; typedef typename side_compare<target_operation>::type side_compare_type; @@ -116,6 +135,7 @@ struct traversal point_type, SideStrategy, side_compare_type > sbs_type; +public : inline traversal(Geometry1 const& geometry1, Geometry2 const& geometry2, Turns& turns, Clusters const& clusters, RobustPolicy const& robust_policy, SideStrategy const& strategy, @@ -352,35 +372,72 @@ struct traversal // If both are valid candidates, take the one with minimal remaining // distance (important for #mysql_23023665 in buffer). - // Initialize with 0, automatically assigned on first result + signed_size_type next[2] = {0}; + bool possible[2] = {0}; + bool close[2] = {0}; + + for (int i = 0; i < 2; i++) + { + next[i] = turn.operations[i].enriched.get_next_turn_index(); + possible[i] = traverse_possible(next[i]); + close[i] = possible[i] && next[i] == start_turn_index; + } + + if (close[0] != close[1]) + { + // One of the operations will finish the ring. Take that one. + selected_op_index = close[0] ? 0 : 1; + debug_traverse(turn, turn.operations[selected_op_index], "Candidate cc closing"); + return true; + } + + if (OverlayType == overlay_buffer && possible[0] && possible[1]) + { + // Buffers sometimes have multiple overlapping pieces, where remaining + // distance could lead to the wrong choice. Take the matching operation. + + bool is_target[2] = {0}; + for (int i = 0; i < 2; i++) + { + turn_operation_type const& next_op = m_turns[next[i]].operations[i]; + is_target[i] = next_op.operation == target_operation; + } + + if (is_target[0] != is_target[1]) + { + // Take the matching operation + selected_op_index = is_target[0] ? 0 : 1; + debug_traverse(turn, turn.operations[selected_op_index], "Candidate cc target"); + return true; + } + } + + static bool const is_union = target_operation == operation_union; + typename turn_operation_type::comparable_distance_type - min_remaining_distance = 0; + best_remaining_distance = 0; bool result = false; for (int i = 0; i < 2; i++) { - turn_operation_type const& op = turn.operations[i]; - - signed_size_type const next_turn_index = op.enriched.get_next_turn_index(); - - if (! traverse_possible(next_turn_index)) + if (!possible[i]) { continue; } + turn_operation_type const& op = turn.operations[i]; + if (! result - || next_turn_index == start_turn_index - || op.remaining_distance < min_remaining_distance) + || (is_union && op.remaining_distance > best_remaining_distance) + || (!is_union && op.remaining_distance < best_remaining_distance)) { debug_traverse(turn, op, "First candidate cc", ! result); - debug_traverse(turn, op, "Candidate cc override (start)", - result && next_turn_index == start_turn_index); debug_traverse(turn, op, "Candidate cc override (remaining)", - result && op.remaining_distance < min_remaining_distance); + result && op.remaining_distance < best_remaining_distance); selected_op_index = i; - min_remaining_distance = op.remaining_distance; + best_remaining_distance = op.remaining_distance; result = true; } } @@ -710,24 +767,163 @@ struct traversal return false; } - inline bool select_turn_from_cluster(signed_size_type& turn_index, + inline signed_size_type get_rank(sbs_type const& sbs, + linked_turn_op_info const& info) const + { + for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++) + { + typename sbs_type::rp const& rp = sbs.m_ranked_points[i]; + if (rp.turn_index == info.turn_index + && rp.operation_index == info.op_index + && rp.direction == sort_by_side::dir_to) + { + return rp.rank; + } + } + return -1; + } + + // Function checks simple cases, such as a cluster with two turns, + // arriving at the first turn, first turn points to second turn, + // second turn points further. + inline bool select_turn_from_cluster_linked(signed_size_type& turn_index, int& op_index, - signed_size_type start_turn_index, int start_op_index, + std::set<signed_size_type> const& ids, segment_identifier const& previous_seg_id) const { - bool const is_union = target_operation == operation_union; + typedef typename std::set<signed_size_type>::const_iterator sit_type; - turn_type const& turn = m_turns[turn_index]; - BOOST_ASSERT(turn.is_clustered()); + std::vector<linked_turn_op_info> possibilities; + std::vector<linked_turn_op_info> blocked; + for (sit_type it = ids.begin(); it != ids.end(); ++it) + { + signed_size_type cluster_turn_index = *it; + turn_type const& cluster_turn = m_turns[cluster_turn_index]; + if (cluster_turn.discarded) + { + continue; + } + if (is_self_turn<OverlayType>(cluster_turn) + || cluster_turn.both(target_operation)) + { + // Not (yet) supported, can be cluster of u/u turns + return false; + } + for (int i = 0; i < 2; i++) + { + turn_operation_type const& op = cluster_turn.operations[i]; + turn_operation_type const& other_op = cluster_turn.operations[1 - i]; + signed_size_type const ni = op.enriched.get_next_turn_index(); + if (op.operation == target_operation + || op.operation == operation_continue) + { + if (ni == cluster_turn_index) + { + // Not (yet) supported, traveling to itself, can be + // hole + return false; + } + possibilities.push_back( + linked_turn_op_info(cluster_turn_index, i, ni)); + } + else if (op.operation == operation_blocked + && ! (ni == other_op.enriched.get_next_turn_index()) + && ids.count(ni) == 0) + { + // Points to turn, not part of this cluster, + // and that way is blocked. But if the other operation + // points at the same turn, it is still fine. + blocked.push_back( + linked_turn_op_info(cluster_turn_index, i, ni)); + } + } + } - typename Clusters::const_iterator mit = m_clusters.find(turn.cluster_id); - BOOST_ASSERT(mit != m_clusters.end()); + typedef typename std::vector<linked_turn_op_info>::const_iterator const_it_type; - cluster_info const& cinfo = mit->second; - std::set<signed_size_type> const& ids = cinfo.turn_indices; + if (! blocked.empty()) + { + sbs_type sbs(m_strategy); - sbs_type sbs(m_strategy); + if (! fill_sbs(sbs, turn_index, ids, previous_seg_id)) + { + return false; + } + + for (typename std::vector<linked_turn_op_info>::iterator it = possibilities.begin(); + it != possibilities.end(); ++it) + { + linked_turn_op_info& info = *it; + info.rank_index = get_rank(sbs, info); + } + for (typename std::vector<linked_turn_op_info>::iterator it = blocked.begin(); + it != blocked.end(); ++it) + { + linked_turn_op_info& info = *it; + info.rank_index = get_rank(sbs, info); + } + + + for (const_it_type it = possibilities.begin(); + it != possibilities.end(); ++it) + { + linked_turn_op_info const& lti = *it; + for (const_it_type bit = blocked.begin(); + bit != blocked.end(); ++bit) + { + linked_turn_op_info const& blti = *bit; + if (blti.next_turn_index == lti.next_turn_index + && blti.rank_index == lti.rank_index) + { + return false; + } + } + } + } + + // Traversal can either enter the cluster in the first turn, + // or it can start halfway. + // If there is one (and only one) possibility pointing outside + // the cluster, take that one. + linked_turn_op_info target; + for (const_it_type it = possibilities.begin(); + it != possibilities.end(); ++it) + { + linked_turn_op_info const& lti = *it; + if (ids.count(lti.next_turn_index) == 0) + { + if (target.turn_index >= 0 + && target.next_turn_index != lti.next_turn_index) + { + // Points to different target + return false; + } + if (OverlayType == overlay_buffer && target.turn_index > 0) + { + // Target already assigned, so there are more targets + // or more ways to the same target + return false; + } + + target = lti; + } + } + if (target.turn_index < 0) + { + return false; + } + + turn_index = target.turn_index; + op_index = target.op_index; + return true; + } + + inline bool fill_sbs(sbs_type& sbs, + signed_size_type turn_index, + std::set<signed_size_type> const& ids, + segment_identifier const& previous_seg_id) const + { for (typename std::set<signed_size_type>::const_iterator sit = ids.begin(); sit != ids.end(); ++sit) { @@ -753,7 +949,39 @@ struct traversal { return false; } + turn_type const& turn = m_turns[turn_index]; sbs.apply(turn.point); + return true; + } + + + inline bool select_turn_from_cluster(signed_size_type& turn_index, + int& op_index, + signed_size_type start_turn_index, int start_op_index, + segment_identifier const& previous_seg_id) const + { + bool const is_union = target_operation == operation_union; + + turn_type const& turn = m_turns[turn_index]; + BOOST_ASSERT(turn.is_clustered()); + + typename Clusters::const_iterator mit = m_clusters.find(turn.cluster_id); + BOOST_ASSERT(mit != m_clusters.end()); + + cluster_info const& cinfo = mit->second; + std::set<signed_size_type> const& ids = cinfo.turn_indices; + + if (select_turn_from_cluster_linked(turn_index, op_index, ids, previous_seg_id)) + { + return true; + } + + sbs_type sbs(m_strategy); + + if (! fill_sbs(sbs, turn_index, ids, previous_seg_id)) + { + return false; + } bool result = false; diff --git a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp index 7f80c8313a..99b2834f15 100644 --- a/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp +++ b/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017. -// Modifications copyright (c) 2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 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, @@ -17,6 +17,7 @@ #include <boost/range.hpp> +#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp> #include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp> #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> #include <boost/geometry/algorithms/detail/overlay/traversal.hpp> @@ -208,10 +209,11 @@ struct traversal_ring_creator if (start_turn.is_clustered()) { - turn_type const& turn = m_turns[current_turn_index]; - if (turn.cluster_id == start_turn.cluster_id) + turn_type& turn = m_turns[current_turn_index]; + turn_operation_type& op = turn.operations[current_op_index]; + if (turn.cluster_id == start_turn.cluster_id + && op.enriched.get_next_turn_index() == start_turn_index) { - turn_operation_type& op = m_turns[start_turn_index].operations[current_op_index]; op.visited.set_finished(); m_visitor.visit_traverse(m_turns, m_turns[current_turn_index], start_op, "Early finish (cluster)"); return traverse_error_none; @@ -306,6 +308,23 @@ struct traversal_ring_creator } } + int get_operation_index(turn_type const& turn) const + { + // When starting with a continue operation, the one + // with the smallest (for intersection) or largest (for union) + // remaining distance (#8310b) + // Also to avoid skipping a turn in between, which can happen + // in rare cases (e.g. #130) + static const bool is_union + = operation_from_overlay<OverlayType>::value == operation_union; + + turn_operation_type const& op0 = turn.operations[0]; + turn_operation_type const& op1 = turn.operations[1]; + return op0.remaining_distance <= op1.remaining_distance + ? (is_union ? 1 : 0) + : (is_union ? 0 : 1); + } + template <typename Rings> void iterate(Rings& rings, std::size_t& finalized_ring_size, typename Backtrack::state_type& state) @@ -322,15 +341,8 @@ struct traversal_ring_creator if (turn.both(operation_continue)) { - // Traverse only one turn, the one with the SMALLEST remaining distance - // to avoid skipping a turn in between, which can happen in rare cases - // (e.g. #130) - turn_operation_type const& op0 = turn.operations[0]; - turn_operation_type const& op1 = turn.operations[1]; - int const op_index - = op0.remaining_distance <= op1.remaining_distance ? 0 : 1; - - traverse_with_operation(turn, turn_index, op_index, + traverse_with_operation(turn, turn_index, + get_operation_index(turn), rings, finalized_ring_size, state); } else @@ -373,13 +385,8 @@ struct traversal_ring_creator if (turn.both(operation_continue)) { - // Traverse only one turn, the one with the SMALLEST remaining distance - // to avoid skipping a turn in between, which can happen in rare cases - // (e.g. #130) - int const op_index - = op0.remaining_distance <= op1.remaining_distance ? 0 : 1; - - traverse_with_operation(turn, turn_index, op_index, + traverse_with_operation(turn, turn_index, + get_operation_index(turn), rings, finalized_ring_size, state); } else diff --git a/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp b/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp index 8bdb03df5d..2732531324 100644 --- a/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp +++ b/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp @@ -2,6 +2,11 @@ // Copyright (c) 2015-2016 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,6 +15,7 @@ #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_SWITCH_DETECTOR_HPP #include <cstddef> +#include <map> #include <boost/range.hpp> diff --git a/boost/geometry/algorithms/detail/point_on_border.hpp b/boost/geometry/algorithms/detail/point_on_border.hpp index 831081aa69..b3e14fecbd 100644 --- a/boost/geometry/algorithms/detail/point_on_border.hpp +++ b/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<typename Point, std::size_t Dimension, std::size_t DimensionCount> -struct midpoint_helper -{ - template <typename InputPoint> - static inline bool apply(Point& p, InputPoint const& p1, InputPoint const& p2) - { - typename coordinate_type<Point>::type const two = 2; - set<Dimension>(p, - (get<Dimension>(p1) + get<Dimension>(p2)) / two); - return midpoint_helper<Point, Dimension + 1, DimensionCount>::apply(p, p1, p2); - } -}; - -template <typename Point, std::size_t DimensionCount> -struct midpoint_helper<Point, DimensionCount, DimensionCount> -{ - template <typename InputPoint> - static inline bool apply(Point& , InputPoint const& , InputPoint const& ) - { - return true; - } -}; - - -template <bool Midpoint> struct point_on_range { // Version with iterator template<typename Point, typename Iterator> 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<Point>::value - >::apply(point, *prev, *it); - } - return false; + geometry::detail::conversion::convert_point_to_point(*begin, point); + return true; } // Version with range template<typename Point, typename Range> static inline bool apply(Point& point, Range const& range) { - typedef typename geometry::cs_tag<Point>::type cs_tag; - BOOST_STATIC_ASSERT((! Midpoint || boost::is_same<cs_tag, cartesian_tag>::value)); - return apply(point, boost::begin(range), boost::end(range)); } }; -template <bool Midpoint> struct point_on_polygon { template<typename Point, typename Polygon> 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 <bool Midpoint> struct point_on_box { template<typename Point, typename Box> static inline bool apply(Point& point, Box const& box) { - if (BOOST_GEOMETRY_CONDITION(Midpoint)) - { - Point p1, p2; - detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, p1); - detail::assign::assign_box_2d_corner<max_corner, min_corner>(box, p2); - midpoint_helper - < - Point, - 0, dimension<Point>::value - >::apply(point, p1, p2); - } - else - { - detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point); - } - + detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point); return true; } }; @@ -206,60 +136,50 @@ namespace dispatch { -template -< - typename GeometryTag, - bool Midpoint - -> +template <typename GeometryTag> struct point_on_border {}; - -template <bool Midpoint> -struct point_on_border<point_tag, Midpoint> +template <> +struct point_on_border<point_tag> : detail::point_on_border::get_point {}; - -template <bool Midpoint> -struct point_on_border<linestring_tag, Midpoint> - : detail::point_on_border::point_on_range<Midpoint> +template <> +struct point_on_border<linestring_tag> + : detail::point_on_border::point_on_range {}; - -template <bool Midpoint> -struct point_on_border<ring_tag, Midpoint> - : detail::point_on_border::point_on_range<Midpoint> +template <> +struct point_on_border<ring_tag> + : detail::point_on_border::point_on_range {}; - -template <bool Midpoint> -struct point_on_border<polygon_tag, Midpoint> - : detail::point_on_border::point_on_polygon<Midpoint> +template <> +struct point_on_border<polygon_tag> + : detail::point_on_border::point_on_polygon {}; - -template <bool Midpoint> -struct point_on_border<box_tag, Midpoint> - : detail::point_on_border::point_on_box<Midpoint> +template <> +struct point_on_border<box_tag> + : detail::point_on_border::point_on_box {}; -template <bool Midpoint> -struct point_on_border<multi_polygon_tag, Midpoint> +template <> +struct point_on_border<multi_polygon_tag> : detail::point_on_border::point_on_multi < - detail::point_on_border::point_on_polygon<Midpoint> + detail::point_on_border::point_on_polygon > {}; -template <bool Midpoint> -struct point_on_border<multi_linestring_tag, Midpoint> +template <> +struct point_on_border<multi_linestring_tag> : detail::point_on_border::point_on_multi < - detail::point_on_border::point_on_range<Midpoint> + 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<Geometry>::type, - false + typename tag<Geometry>::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 <bool Midpoint, typename Point, typename Geometry> -inline bool point_on_border(Point& point, Geometry const& geometry) -{ - concepts::check<Point>(); - concepts::check<Geometry const>(); - - return dispatch::point_on_border - < - typename tag<Geometry>::type, - Midpoint - >::apply(point, geometry); -} -*/ - }} // namespace boost::geometry diff --git a/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/boost/geometry/algorithms/detail/relate/areal_areal.hpp index 800fbb2e96..fa0ab1ea0f 100644 --- a/boost/geometry/algorithms/detail/relate/areal_areal.hpp +++ b/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<turn_type, 0> 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<turn_type, 1> 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 <typename Result, - typename TurnIt> - void apply(Result & result, TurnIt it) + template <typename Result, typename TurnIt, typename EqPPStrategy> + 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<op_id>(*m_previous_turn_ptr, *it) ) + || ! turn_on_the_same_ip<op_id>(*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<op_id>(*m_previous_turn_ptr, *it) ) + || ! turn_on_the_same_ip<op_id>(*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 <typename Result, - typename Analyser, - typename TurnIt> + 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/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp index 99385e06f9..dc927d9026 100644 --- a/boost/geometry/algorithms/detail/relate/boundary_checker.hpp +++ b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp @@ -1,24 +1,26 @@ // 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 <boost/core/ignore_unused.hpp> -#include <boost/geometry/util/range.hpp> -#include <boost/geometry/algorithms/num_points.hpp> -#include <boost/geometry/algorithms/detail/sub_range.hpp> #include <boost/geometry/algorithms/detail/equals/point_point.hpp> +#include <boost/geometry/algorithms/detail/sub_range.hpp> +#include <boost/geometry/algorithms/num_points.hpp> + +#include <boost/geometry/policies/compare.hpp> #include <boost/geometry/util/has_nan_coordinate.hpp> +#include <boost/geometry/util/range.hpp> namespace boost { namespace geometry { @@ -29,19 +31,26 @@ namespace detail { namespace relate { enum boundary_query { boundary_front, boundary_back, boundary_any }; template <typename Geometry, + typename WithinStrategy, // Point/Point equals (within) strategy typename Tag = typename geometry::tag<Geometry>::type> class boundary_checker {}; -template <typename Geometry> -class boundary_checker<Geometry, linestring_tag> +template <typename Geometry, typename WithinStrategy> +class boundary_checker<Geometry, WithinStrategy, linestring_tag> { typedef typename point_type<Geometry>::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 <boundary_query BoundaryQuery> @@ -51,24 +60,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 <typename Geometry> -class boundary_checker<Geometry, multi_linestring_tag> +template <typename Geometry, typename WithinStrategy> +class boundary_checker<Geometry, WithinStrategy, multi_linestring_tag> { typedef typename point_type<Geometry>::type point_type; public: + typedef WithinStrategy equals_strategy_type; + boundary_checker(Geometry const& g) : is_filled(false), geometry(g) {} @@ -111,7 +124,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/boost/geometry/algorithms/detail/relate/follow_helpers.hpp b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp index 11e95a0b35..139664cc7c 100644 --- a/boost/geometry/algorithms/detail/relate/follow_helpers.hpp +++ b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp @@ -2,25 +2,33 @@ // 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. + +// 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_FOLLOW_HELPERS_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP +#include <vector> + #include <boost/core/ignore_unused.hpp> +#include <boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp> +#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp> +#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp> +#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> + #include <boost/geometry/core/assert.hpp> #include <boost/geometry/util/condition.hpp> #include <boost/geometry/util/range.hpp> -//#include <boost/geometry/algorithms/detail/sub_range.hpp> namespace boost { namespace geometry { @@ -333,8 +341,9 @@ private: std::vector<point_info> m_other_entry_points; // TODO: use map here or sorted vector? }; -template <std::size_t OpId, typename Turn> -inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn) +template <std::size_t OpId, typename Turn, typename EqPPStrategy> +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 +363,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 <boundary_query BoundaryQuery, diff --git a/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/boost/geometry/algorithms/detail/relate/linear_areal.hpp index ddbd7d615a..81fc9e5b3b 100644 --- a/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2013, 2014, 2015, 2017. -// 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 @@ -262,13 +262,22 @@ struct linear_areal typedef typename IntersectionStrategy::template point_in_geometry_strategy<Geometry1, Geometry2>::type within_strategy_type; within_strategy_type const within_strategy = intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>(); - boundary_checker<Geometry1> 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<Geometry1>, + 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<turn_type> 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; } @@ -621,6 +632,37 @@ struct linear_areal static const std::size_t op_id = 0; static const std::size_t other_op_id = 1; + template <typename TurnPointCSTag, typename PointP, typename PointQ, + typename SideStrategy, + typename Pi = PointP, typename Pj = PointP, typename Pk = PointP, + typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ + > + struct la_side_calculator + { + inline la_side_calculator(Pi const& pi, Pj const& pj, Pk const& pk, + Qi const& qi, Qj const& qj, Qk const& qk, + SideStrategy const& side_strategy) + : m_pi(pi), m_pj(pj), m_pk(pk) + , m_qi(qi), m_qj(qj), m_qk(qk) + , m_side_strategy(side_strategy) + {} + + inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); } + inline int qk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_qk); } + inline int pk_wrt_q2() const { return m_side_strategy.apply(m_qj, m_qk, m_pk); } + + private : + Pi const& m_pi; + Pj const& m_pj; + Pk const& m_pk; + Qi const& m_qi; + Qj const& m_qj; + Qk const& m_qk; + + SideStrategy m_side_strategy; + }; + + public: turns_analyser() : m_previous_turn_ptr(NULL) @@ -670,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<op_id>(m_exit_watcher.get_exit_turn(), *it) ) + if ( ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it, + side_strategy.get_equals_point_point_strategy()) ) { m_exit_watcher.reset_detected_exit(); @@ -712,7 +755,8 @@ struct linear_areal if ( ( op == overlay::operation_intersection || op == overlay::operation_continue ) - && turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) ) + && turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it, + side_strategy.get_equals_point_point_strategy()) ) { fake_enter_detected = true; } @@ -732,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<op_id>(*m_previous_turn_ptr, *it) ) + && ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it, + side_strategy.get_equals_point_point_strategy()) ) ) { update<interior, exterior, '1', TransposeResult>(res); @@ -764,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<op_id>(*m_previous_turn_ptr, *it) ) + if ( ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it, + side_strategy.get_equals_point_point_strategy()) ) { update<interior, interior, '1', TransposeResult>(res); m_interior_detected = false; @@ -1203,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)); @@ -1217,10 +1263,11 @@ 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? - overlay::side_calculator<cs_tag, point1_type, point2_type, SideStrategy> + la_side_calculator<cs_tag, point1_type, point2_type, SideStrategy> side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, side_strategy); return calculate_from_inside_sides(side_calc); @@ -1230,15 +1277,16 @@ struct linear_areal point2_type new_qj; geometry::convert(turn.point, new_qj); - overlay::side_calculator<cs_tag, point1_type, point2_type, SideStrategy> + la_side_calculator<cs_tag, point1_type, point2_type, SideStrategy> side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, side_strategy); return calculate_from_inside_sides(side_calc); } } - template <typename It> - static inline It find_next_non_duplicated(It first, It current, It last) + template <typename It, typename EqPPStrategy> + static inline It find_next_non_duplicated(It first, It current, It last, + EqPPStrategy const& strategy) { BOOST_GEOMETRY_ASSERT( current != last ); @@ -1246,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; } @@ -1396,8 +1444,9 @@ struct linear_areal , m_previous_turn_ptr(NULL) {} - template <typename TurnIt> - bool apply(TurnIt /*first*/, TurnIt it, TurnIt last) + template <typename TurnIt, typename EqPPStrategy> + bool apply(TurnIt /*first*/, TurnIt it, TurnIt last, + EqPPStrategy const& strategy) { overlay::operation_type op = it->operations[1].operation; @@ -1412,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/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/boost/geometry/algorithms/detail/relate/linear_linear.hpp index 520f2bd775..6c5d82fdea 100644 --- a/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/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 <typename Result, typename BoundaryChecker, bool TransposeResult> 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<interior, exterior, '0', TransposeResult>(m_result); } @@ -145,14 +148,24 @@ struct linear_linear if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) return; - boundary_checker<Geometry1> boundary_checker1(geometry1); - disjoint_linestring_pred<Result, boundary_checker<Geometry1>, 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<Result, boundary_checker1_type, false> 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<Geometry2> boundary_checker2(geometry2); - disjoint_linestring_pred<Result, boundary_checker<Geometry2>, 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<Result, boundary_checker2_type, true> 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<op_id>(m_exit_watcher.get_exit_turn(), *it) ) + if ( ! turn_on_the_same_ip<op_id>(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<op_id>(m_exit_watcher.get_exit_turn(), *it) ) + && turn_on_the_same_ip<op_id>(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<Geometry const>::type ls1_ref = detail::single_geometry(geometry, turn.operations[op_id].seg_id); typename detail::single_geometry_return_type<OtherGeometry const>::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/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp b/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp index 8d5f21555c..8dec5ccdaf 100644 --- a/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp +++ b/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 @@ -17,6 +17,7 @@ #include <boost/geometry/algorithms/detail/disjoint/box_box.hpp> #include <boost/geometry/algorithms/detail/disjoint/point_box.hpp> #include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp> +#include <boost/geometry/algorithms/detail/partition.hpp> #include <boost/geometry/algorithms/detail/relate/result.hpp> #include <boost/geometry/algorithms/detail/relate/topology_check.hpp> #include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp> @@ -40,20 +41,21 @@ namespace detail { namespace relate template < typename Geometry, + typename EqPPStrategy, typename Tag = typename tag<Geometry>::type > struct multi_point_geometry_eb { template <typename MultiPoint> static inline bool apply(MultiPoint const& , - detail::relate::topology_check<Geometry> const& ) + detail::relate::topology_check<Geometry, EqPPStrategy> const& ) { return true; } }; -template <typename Geometry> -struct multi_point_geometry_eb<Geometry, linestring_tag> +template <typename Geometry, typename EqPPStrategy> +struct multi_point_geometry_eb<Geometry, EqPPStrategy, linestring_tag> { template <typename Points> struct boundary_visitor @@ -73,7 +75,7 @@ struct multi_point_geometry_eb<Geometry, linestring_tag> template <typename Pt> 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 +101,7 @@ struct multi_point_geometry_eb<Geometry, linestring_tag> template <typename MultiPoint> static inline bool apply(MultiPoint const& multi_point, - detail::relate::topology_check<Geometry> const& tc) + detail::relate::topology_check<Geometry, EqPPStrategy> const& tc) { boundary_visitor<MultiPoint> visitor(multi_point); tc.for_each_boundary_point(visitor); @@ -107,9 +109,12 @@ struct multi_point_geometry_eb<Geometry, linestring_tag> } }; -template <typename Geometry> -struct multi_point_geometry_eb<Geometry, multi_linestring_tag> +template <typename Geometry, typename EqPPStrategy> +struct multi_point_geometry_eb<Geometry, EqPPStrategy, multi_linestring_tag> { + // TODO: CS-specific less compare strategy derived from EqPPStrategy + typedef geometry::less<> less_type; + template <typename Points> struct boundary_visitor { @@ -121,7 +126,7 @@ struct multi_point_geometry_eb<Geometry, multi_linestring_tag> template <typename Point> 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 +143,12 @@ struct multi_point_geometry_eb<Geometry, multi_linestring_tag> template <typename MultiPoint> static inline bool apply(MultiPoint const& multi_point, - detail::relate::topology_check<Geometry> const& tc) + detail::relate::topology_check<Geometry, EqPPStrategy> const& tc) { typedef typename boost::range_value<MultiPoint>::type point_type; typedef std::vector<point_type> 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<points_type> visitor(points); tc.for_each_boundary_point(visitor); @@ -165,6 +170,8 @@ struct multi_point_single_geometry { typedef typename point_type<SingleGeometry>::type point2_type; typedef model::box<point2_type> 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 +188,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<interior, exterior, '0', Transpose>(result); } @@ -209,7 +216,10 @@ struct multi_point_single_geometry } } - typedef detail::relate::topology_check<SingleGeometry> tc_t; + typedef detail::relate::topology_check + < + SingleGeometry, eq_pp_strategy_type + > tc_t; if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result) || relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) ) { @@ -226,8 +236,13 @@ struct multi_point_single_geometry if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) && tc.has_boundary() ) { - if (multi_point_geometry_eb<SingleGeometry>::apply(multi_point, tc)) + if (multi_point_geometry_eb + < + SingleGeometry, eq_pp_strategy_type + >::apply(multi_point, tc)) + { relate::set<exterior, boundary, tc_t::boundary, Transpose>(result); + } } } @@ -260,32 +275,40 @@ class multi_point_multi_geometry_ii_ib } }; + template <typename DisjointPointBoxStrategy> struct overlaps_box_point { template <typename Box, typename Point> 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 <typename DisjointBoxBoxStrategy> struct overlaps_box_box_pair { template <typename Box, typename BoxPair> 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 <typename Result, typename PtSegStrategy> 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<MultiGeometry, pp_strategy_type> topology_check_type; + public: item_visitor_type(MultiGeometry const& multi_geometry, - detail::relate::topology_check<MultiGeometry> const& tc, + topology_check_type const& tc, Result & result, PtSegStrategy const& strategy) : m_multi_geometry(multi_geometry) @@ -298,7 +321,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<MultiGeometry>::type const& single = range::at(m_multi_geometry, box_pair.second); @@ -335,7 +358,7 @@ class multi_point_multi_geometry_ii_ib private: MultiGeometry const& m_multi_geometry; - detail::relate::topology_check<MultiGeometry> const& m_tc; + topology_check_type const& m_tc; Result & m_result; PtSegStrategy const& m_strategy; }; @@ -351,20 +374,33 @@ public: static inline void apply(MultiPoint const& multi_point, MultiGeometry const& multi_geometry, std::vector<box_pair_type> const& boxes, - detail::relate::topology_check<MultiGeometry> const& tc, + detail::relate::topology_check + < + MultiGeometry, + typename Strategy::equals_point_point_strategy_type + > const& tc, Result & result, Strategy const& strategy) { item_visitor_type<Result, Strategy> 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 +423,11 @@ struct multi_point_multi_geometry_ii_ib_ie static inline void apply(MultiPoint const& multi_point, MultiGeometry const& multi_geometry, std::vector<box_pair_type> const& boxes, - detail::relate::topology_check<MultiGeometry> const& tc, + detail::relate::topology_check + < + MultiGeometry, + typename Strategy::equals_point_point_strategy_type + > const& tc, Result & result, Strategy const& strategy) { @@ -461,6 +501,8 @@ struct multi_point_multi_geometry typedef model::box<point2_type> box2_type; typedef std::pair<box2_type, std::size_t> 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 +515,7 @@ struct multi_point_multi_geometry boxes[i].second = i; } - typedef detail::relate::topology_check<MultiGeometry> tc_t; + typedef detail::relate::topology_check<MultiGeometry, eq_pp_strategy_type> tc_t; tc_t tc(multi_geometry); if ( relate::may_update<interior, interior, '0', Transpose>(result) @@ -512,8 +554,13 @@ struct multi_point_multi_geometry if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) && tc.has_boundary() ) { - if (multi_point_geometry_eb<MultiGeometry>::apply(multi_point, tc)) + if (multi_point_geometry_eb + < + MultiGeometry, eq_pp_strategy_type + >::apply(multi_point, tc)) + { relate::set<exterior, boundary, tc_t::boundary, Transpose>(result); + } } } diff --git a/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/boost/geometry/algorithms/detail/relate/point_geometry.hpp index e78a404b21..7b1726abeb 100644 --- a/boost/geometry/algorithms/detail/relate/point_geometry.hpp +++ b/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<Geometry> tc_t; + typedef detail::relate::topology_check + < + Geometry, + typename Strategy::equals_point_point_strategy_type + > tc_t; if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result) || relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) ) { diff --git a/boost/geometry/algorithms/detail/relate/point_point.hpp b/boost/geometry/algorithms/detail/relate/point_point.hpp index e0bed72ba3..d2a373f3c1 100644 --- a/boost/geometry/algorithms/detail/relate/point_point.hpp +++ b/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 <typename Result, typename Strategy> 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<interior, interior, '0'>(result); @@ -56,8 +56,10 @@ struct point_point } }; -template <typename Point, typename MultiPoint> -std::pair<bool, bool> point_multipoint_check(Point const& point, MultiPoint const& multi_point) +template <typename Point, typename MultiPoint, typename EqPPStrategy> +std::pair<bool, bool> 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<bool, bool> 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 <typename Result, typename Strategy> 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<bool, bool> rel = point_multipoint_check(point, multi_point); + std::pair<bool, bool> rel = point_multipoint_check(point, multi_point, strategy); if ( rel.first ) // some point of MP is equal to P { diff --git a/boost/geometry/algorithms/detail/relate/result.hpp b/boost/geometry/algorithms/detail/relate/result.hpp index 92bc160a6c..43592b9815 100644 --- a/boost/geometry/algorithms/detail/relate/result.hpp +++ b/boost/geometry/algorithms/detail/relate/result.hpp @@ -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 2013-2016. -// Modifications copyright (c) 2013-2016 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 @@ -25,6 +25,7 @@ #include <boost/mpl/end.hpp> #include <boost/mpl/is_sequence.hpp> #include <boost/mpl/next.hpp> +#include <boost/mpl/size.hpp> #include <boost/static_assert.hpp> #include <boost/throw_exception.hpp> #include <boost/tuple/tuple.hpp> diff --git a/boost/geometry/algorithms/detail/relate/topology_check.hpp b/boost/geometry/algorithms/detail/relate/topology_check.hpp index 810466ec05..a12acaf42b 100644 --- a/boost/geometry/algorithms/detail/relate/topology_check.hpp +++ b/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 @@ -13,6 +13,7 @@ #include <boost/geometry/algorithms/detail/equals/point_point.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> #include <boost/geometry/policies/compare.hpp> @@ -28,6 +29,7 @@ namespace detail { namespace relate { // TODO: change the name for e.g. something with the word "exterior" template <typename Geometry, + typename EqPPStrategy, typename Tag = typename geometry::tag<Geometry>::type> struct topology_check : not_implemented<Tag> @@ -47,8 +49,8 @@ struct topology_check // topology_check(Point const&, IgnoreBoundaryPoint const&) {} //}; -template <typename Linestring> -struct topology_check<Linestring, linestring_tag> +template <typename Linestring, typename EqPPStrategy> +struct topology_check<Linestring, EqPPStrategy, linestring_tag> { static const char interior = '1'; static const char boundary = '0'; @@ -100,7 +102,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 +116,8 @@ private: mutable bool m_has_boundary; }; -template <typename MultiLinestring> -struct topology_check<MultiLinestring, multi_linestring_tag> +template <typename MultiLinestring, typename EqPPStrategy> +struct topology_check<MultiLinestring, EqPPStrategy, multi_linestring_tag> { static const char interior = '1'; static const char boundary = '0'; @@ -159,6 +163,9 @@ struct topology_check<MultiLinestring, multi_linestring_tag> } private: +// TODO: CS-specific less derived from EqPPStrategy + typedef geometry::less<> less_type; + void init() const { if (m_is_initialized) @@ -192,7 +199,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 +222,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 +232,7 @@ private: template <typename It, typename Point> static inline std::size_t count_equal(It first, It last, Point const& point) { - std::pair<It, It> rng = std::equal_range(first, last, point, geometry::less<>()); + std::pair<It, It> rng = std::equal_range(first, last, point, less_type()); return (std::size_t)std::distance(rng.first, rng.second); } @@ -261,7 +268,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 +305,35 @@ private: mutable std::vector<point_type> m_endpoints; }; -template <typename Ring> -struct topology_check<Ring, ring_tag> +struct topology_check_areal { static const char interior = '2'; static const char boundary = '1'; - topology_check(Ring const&) {} - static bool has_interior() { return true; } static bool has_boundary() { return true; } }; -template <typename Polygon> -struct topology_check<Polygon, polygon_tag> +template <typename Ring, typename EqPPStrategy> +struct topology_check<Ring, EqPPStrategy, ring_tag> + : topology_check_areal { - static const char interior = '2'; - static const char boundary = '1'; - - topology_check(Polygon const&) {} + topology_check(Ring const&) {} +}; - static bool has_interior() { return true; } - static bool has_boundary() { return true; } +template <typename Polygon, typename EqPPStrategy> +struct topology_check<Polygon, EqPPStrategy, polygon_tag> + : topology_check_areal +{ + topology_check(Polygon const&) {} }; -template <typename MultiPolygon> -struct topology_check<MultiPolygon, multi_polygon_tag> +template <typename MultiPolygon, typename EqPPStrategy> +struct topology_check<MultiPolygon, EqPPStrategy, multi_polygon_tag> + : 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 <typename Point> static bool check_boundary_point(Point const& ) { return true; } }; diff --git a/boost/geometry/algorithms/detail/relate/turns.hpp b/boost/geometry/algorithms/detail/relate/turns.hpp index 6fa05eaf21..01c4304fa4 100644 --- a/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/boost/geometry/algorithms/detail/relate/turns.hpp @@ -48,7 +48,11 @@ template < Geometry1, Geometry2, assign_policy<> >, - typename RobustPolicy = detail::no_rescale_policy + typename RobustPolicy = typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2 + >::type > struct get_turns { diff --git a/boost/geometry/algorithms/detail/sections/section_box_policies.hpp b/boost/geometry/algorithms/detail/sections/section_box_policies.hpp index cf06700306..e6342ff709 100644 --- a/boost/geometry/algorithms/detail/sections/section_box_policies.hpp +++ b/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 <typename ExpandBoxStrategy> struct get_section_box { template <typename Box, typename Section> static inline void apply(Box& total, Section const& section) { - geometry::expand(total, section.bounding_box); + geometry::expand(total, section.bounding_box, + ExpandBoxStrategy()); } }; +template <typename DisjointBoxBoxStrategy> struct overlaps_section_box { template <typename Box, typename Section> 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/boost/geometry/algorithms/detail/sections/section_functions.hpp b/boost/geometry/algorithms/detail/sections/section_functions.hpp index d283784e2c..bd72ff48a0 100644 --- a/boost/geometry/algorithms/detail/sections/section_functions.hpp +++ b/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 @@ -22,6 +22,8 @@ // For spherical/geographic longitudes covered_by point/box #include <boost/geometry/strategies/cartesian/point_in_box.hpp> +#include <boost/geometry/util/select_coordinate_type.hpp> + namespace boost { namespace geometry { @@ -30,6 +32,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 +72,7 @@ struct preceding_check<0, Geometry, spherical_tag> calc_t const other_min = get<min_corner, 0>(other_box); calc_t const other_max = get<max_corner, 0>(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/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/boost/geometry/algorithms/detail/sections/sectionalize.hpp index 7a8638f5c8..6ece756cd4 100644 --- a/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/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 <boost/geometry/algorithms/detail/expand_by_epsilon.hpp> #include <boost/geometry/strategies/envelope.hpp> +#include <boost/geometry/strategies/expand.hpp> namespace boost { namespace geometry { @@ -330,9 +331,9 @@ struct assign_loop<T, Count, Count> template <typename CSTag> struct box_first_in_section { - template <typename Box, typename Point, typename Strategy> + template <typename Box, typename Point, typename EnvelopeStrategy> static inline void apply(Box & box, Point const& prev, Point const& curr, - Strategy const& strategy) + EnvelopeStrategy const& strategy) { geometry::model::referring_segment<Point const> seg(prev, curr); geometry::envelope(seg, box, strategy); @@ -342,9 +343,9 @@ struct box_first_in_section template <> struct box_first_in_section<cartesian_tag> { - template <typename Box, typename Point, typename Strategy> + template <typename Box, typename Point, typename ExpandStrategy> 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<typename Sections::box_type>::type >::type envelope_strategy_type; + typedef typename strategy::expand::services::default_strategy + < + segment_tag, + typename cs_tag<typename Sections::box_type>::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<typename cs_tag<robust_point_type>::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<typename cs_tag<robust_point_type>::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<Point, DimensionVector>::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<Polygon const>::type @@ -663,7 +681,8 @@ struct sectionalize_polygon for (typename detail::interior_iterator<Polygon const>::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<Box>::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); } } }; @@ -903,6 +928,8 @@ struct sectionalize<multi_linestring_tag, MultiLinestring, Reverse, DimensionVec \param geometry geometry to create sections from \param robust_policy policy to handle robustness issues \param sections structure with sections + \param envelope_strategy strategy for envelope calculation + \param expand_strategy strategy for partitions \param source_index index to assign to the ring_identifiers \param max_count maximal number of points per section (defaults to 10, this seems to give the fastest results) @@ -915,12 +942,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 +988,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 +1012,27 @@ inline void sectionalize(Geometry const& geometry, { typedef typename strategy::envelope::services::default_strategy < + typename tag<Geometry>::type, typename cs_tag<Geometry>::type >::type envelope_strategy_type; + typedef typename strategy::expand::services::default_strategy + < + typename boost::mpl::if_c + < + boost::is_same<typename tag<Geometry>::type, box_tag>::value, + box_tag, + segment_tag + >::type, + typename cs_tag<Geometry>::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/boost/geometry/algorithms/detail/sub_range.hpp b/boost/geometry/algorithms/detail/sub_range.hpp index 29edc94e6c..099de426ab 100644 --- a/boost/geometry/algorithms/detail/sub_range.hpp +++ b/boost/geometry/algorithms/detail/sub_range.hpp @@ -2,21 +2,29 @@ // 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. + +// 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_SUB_RANGE_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP #include <boost/mpl/if.hpp> +#include <boost/type_traits/is_base_of.hpp> + +#include <boost/geometry/algorithms/not_implemented.hpp> #include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/exterior_ring.hpp> +#include <boost/geometry/core/interior_rings.hpp> +#include <boost/geometry/core/tag.hpp> +#include <boost/geometry/core/tags.hpp> + #include <boost/geometry/util/range.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/algorithms/detail/within/implementation.hpp b/boost/geometry/algorithms/detail/within/implementation.hpp index a1fae421e5..163092b2cb 100644 --- a/boost/geometry/algorithms/detail/within/implementation.hpp +++ b/boost/geometry/algorithms/detail/within/implementation.hpp @@ -4,8 +4,8 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// This file was modified by Oracle on 2013, 2014, 2017. -// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates. +// This file was modified by Oracle on 2013, 2014, 2017, 2019. +// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -61,7 +61,7 @@ struct use_point_in_geometry template <typename Geometry1, typename Geometry2, typename Strategy> static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { - return detail::within::point_in_geometry(geometry1, geometry2, strategy) == 1; + return detail::within::within_point_geometry(geometry1, geometry2, strategy); } }; diff --git a/boost/geometry/algorithms/detail/within/interface.hpp b/boost/geometry/algorithms/detail/within/interface.hpp index 23263604c2..048cc01f7a 100644 --- a/boost/geometry/algorithms/detail/within/interface.hpp +++ b/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<Geometry1>::type, - typename tag<Geometry2>::type, - typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type, - Strategy - >(); + concepts::within::check<Geometry1, Geometry2, Strategy>(); return dispatch::within<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy); } diff --git a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp index a24f4d21e2..45449eb194 100644 --- a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp +++ b/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, 2019. +// Modifications copyright (c) 2013-2019, 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 <typename Point1, typename Point2, typename Strategy> +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<Segment, segment_tag> 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<Linestring, linestring_tag> 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<Geometry, multi_linestring_tag> 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 <typename Point, typename Geometry, typename Strategy> inline int point_in_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy) { - concepts::within::check - < - typename tag<Point>::type, - typename tag<Geometry>::type, - typename tag_cast<typename tag<Geometry>::type, areal_tag>::type, - Strategy - >(); + concepts::within::check<Point, Geometry, Strategy>(); return detail_dispatch::within::point_in_geometry<Geometry>::apply(point, geometry, strategy); } @@ -383,6 +382,30 @@ inline int point_in_geometry(Point const& point, Geometry const& geometry) return point_in_geometry(point, geometry, strategy_type()); } +template <typename Point, typename Geometry, typename Strategy> +inline bool within_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy) +{ + return point_in_geometry(point, geometry, strategy) > 0; +} + +template <typename Point, typename Geometry> +inline bool within_point_geometry(Point const& point, Geometry const& geometry) +{ + return point_in_geometry(point, geometry) > 0; +} + +template <typename Point, typename Geometry, typename Strategy> +inline bool covered_by_point_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy) +{ + return point_in_geometry(point, geometry, strategy) >= 0; +} + +template <typename Point, typename Geometry> +inline bool covered_by_point_geometry(Point const& point, Geometry const& geometry) +{ + return point_in_geometry(point, geometry) >= 0; +} + }} // namespace detail::within #endif // DOXYGEN_NO_DETAIL diff --git a/boost/geometry/algorithms/discrete_frechet_distance.hpp b/boost/geometry/algorithms/discrete_frechet_distance.hpp index de8a5286e0..70a0c1d11d 100644 --- a/boost/geometry/algorithms/discrete_frechet_distance.hpp +++ b/boost/geometry/algorithms/discrete_frechet_distance.hpp @@ -1,8 +1,12 @@ // Boost.Geometry // Copyright (c) 2018 Yaghyavardhan Singh Khangarot, Hyderabad, India. +// Contributed and/or modified by Yaghyavardhan Singh Khangarot, +// as part of Google Summer of Code 2018 program. -// Contributed and/or modified by Yaghyavardhan Singh Khangarot, as part of Google Summer of Code 2018 program. +// 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 @@ -22,13 +26,15 @@ #include <vector> #include <limits> -#include <boost/geometry/geometry.hpp> -#include <boost/geometry/geometries/linestring.hpp> -#include <boost/geometry/geometries/point_xy.hpp> -#include <boost/geometry/geometries/polygon.hpp> -#include <boost/range.hpp> -#include <boost/mpl/assert.hpp> +#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> +#include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/tag.hpp> +#include <boost/geometry/core/tags.hpp> +#include <boost/geometry/core/point_type.hpp> +#include <boost/geometry/strategies/distance.hpp> +#include <boost/geometry/strategies/distance_result.hpp> +#include <boost/geometry/util/range.hpp> namespace boost { namespace geometry @@ -48,7 +54,7 @@ public: result_type & operator()(size_type1 i, size_type2 j) { - BOOST_ASSERT(i < m_width && j < m_height); + BOOST_GEOMETRY_ASSERT(i < m_width && j < m_height); return m_data[j * m_width + i]; } @@ -86,28 +92,31 @@ struct linestring_linestring //Coupling Matrix CoupMat(a,b,-1); - coup_mat<size_type1,size_type2,result_type> coup_matrix(a,b); + coup_mat<size_type1,size_type2,result_type> coup_matrix(a,b); result_type const not_feasible = -100; //findin the Coupling Measure - for(size_type1 i=0;i<a;i++) + for (size_type1 i = 0 ; i < a ; i++ ) { for(size_type2 j=0;j<b;j++) { - result_type dis = geometry::distance(range::at(ls1,i),range::at(ls2,j),strategy); + result_type dis = strategy.apply(range::at(ls1,i), range::at(ls2,j)); if(i==0 && j==0) - coup_matrix(i,j)= dis; + coup_matrix(i,j) = dis; else if(i==0 && j>0) - coup_matrix(i,j)= - (std::max)(coup_matrix(i,j-1),dis); + coup_matrix(i,j) = + (std::max)(coup_matrix(i,j-1), dis); else if(i>0 && j==0) - coup_matrix(i,j)= - (std::max)(coup_matrix(i-1,j),dis); + coup_matrix(i,j) = + (std::max)(coup_matrix(i-1,j), dis); else if(i>0 && j>0) - coup_matrix(i,j)= - (std::max)((std::min)(coup_matrix(i,j-1),(std::min)(coup_matrix(i-1,j),coup_matrix(i-1,j-1))),dis); + coup_matrix(i,j) = + (std::max)((std::min)(coup_matrix(i,j-1), + (std::min)(coup_matrix(i-1,j), + coup_matrix(i-1,j-1))), + dis); else - coup_matrix(i,j)=not_feasible; + coup_matrix(i,j) = not_feasible; } } @@ -140,8 +149,15 @@ template > struct discrete_frechet_distance : not_implemented<Tag1, Tag2> {}; + template <typename Linestring1, typename Linestring2> -struct discrete_frechet_distance<Linestring1,Linestring2,linestring_tag,linestring_tag> +struct discrete_frechet_distance + < + Linestring1, + Linestring2, + linestring_tag, + linestring_tag + > : detail::discrete_frechet_distance::linestring_linestring {}; @@ -151,7 +167,7 @@ struct discrete_frechet_distance<Linestring1,Linestring2,linestring_tag,linestri /*! \brief Calculate discrete Frechet distance between two geometries (currently - works for LineString-LineString) using specified strategy. + works for LineString-LineString) using specified strategy. \ingroup discrete_frechet_distance \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry @@ -181,16 +197,21 @@ inline typename distance_result typename point_type<Geometry2>::type, Strategy >::type -discrete_frechet_distance(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) +discrete_frechet_distance(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) { - return dispatch::discrete_frechet_distance<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy); + return dispatch::discrete_frechet_distance + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, strategy); } // Algorithm overload using default Pt-Pt distance strategy /*! \brief Calculate discrete Frechet distance between two geometries (currently - work for LineString-LineString). + work for LineString-LineString). \ingroup discrete_frechet_distance \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry diff --git a/boost/geometry/algorithms/discrete_hausdorff_distance.hpp b/boost/geometry/algorithms/discrete_hausdorff_distance.hpp index f9daefe62b..6b954737bf 100644 --- a/boost/geometry/algorithms/discrete_hausdorff_distance.hpp +++ b/boost/geometry/algorithms/discrete_hausdorff_distance.hpp @@ -26,16 +26,18 @@ #include <vector> #include <limits> -#include <boost/geometry/geometry.hpp> -#include <boost/geometry/geometries/linestring.hpp> -#include <boost/geometry/geometries/point_xy.hpp> -#include <boost/geometry/geometries/polygon.hpp> -#include <boost/range.hpp> -#include <boost/mpl/assert.hpp> +#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> +#include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/tag.hpp> -#include <boost/geometry/index/rtree.hpp> +#include <boost/geometry/core/tags.hpp> +#include <boost/geometry/strategies/distance.hpp> +#include <boost/geometry/strategies/distance_result.hpp> +#include <boost/geometry/util/range.hpp> -namespace bgi = boost::geometry::index; +#ifdef BOOST_GEOMETRY_ENABLE_SIMILARITY_RTREE +#include <boost/geometry/index/rtree.hpp> +#endif // BOOST_GEOMETRY_ENABLE_SIMILARITY_RTREE namespace boost { namespace geometry { @@ -70,7 +72,7 @@ struct point_range for (size_type i = 0 ; i < n ; i++) { - result_type dis_temp = geometry::distance(pnt, range::at(rng, i), strategy); + result_type dis_temp = strategy.apply(pnt, range::at(rng, i)); if (! is_dis_min_set || dis_temp < dis_min) { dis_min = dis_temp; @@ -110,6 +112,7 @@ struct range_range result_type dis_max = 0; #ifdef BOOST_GEOMETRY_ENABLE_SIMILARITY_RTREE + namespace bgi = boost::geometry::index; typedef typename point_type<Range1>::type point_t; typedef bgi::rtree<point_t, bgi::linear<4> > rtree_type; rtree_type rtree(boost::begin(r2), boost::end(r2)); @@ -120,7 +123,7 @@ struct range_range { #ifdef BOOST_GEOMETRY_ENABLE_SIMILARITY_RTREE size_type found = rtree.query(bgi::nearest(range::at(r1, i), 1), &res); - result_type dis_min = geometry::distance(range::at(r1,i), res); + result_type dis_min = strategy.apply(range::at(r1,i), res); #else result_type dis_min = point_range::apply(range::at(r1, i), r2, strategy); #endif @@ -246,15 +249,15 @@ struct discrete_hausdorff_distance<MultiPoint1, MultiPoint2, multi_point_tag, mu : detail::discrete_hausdorff_distance::range_range {}; -// Specialization for linestring and multi_linestring -template <typename linestring, typename multi_linestring> -struct discrete_hausdorff_distance<linestring, multi_linestring, linestring_tag, multi_linestring_tag> +// Specialization for Linestring and MultiLinestring +template <typename Linestring, typename MultiLinestring> +struct discrete_hausdorff_distance<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag> : detail::discrete_hausdorff_distance::range_multi_range {}; -// Specialization for multi_linestring and multi_linestring -template <typename multi_linestring1, typename multi_linestring2> -struct discrete_hausdorff_distance<multi_linestring1, multi_linestring2, multi_linestring_tag, multi_linestring_tag> +// Specialization for MultiLinestring and MultiLinestring +template <typename MultiLinestring1, typename MultiLinestring2> +struct discrete_hausdorff_distance<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag> : detail::discrete_hausdorff_distance::multi_range_multi_range {}; diff --git a/boost/geometry/algorithms/dispatch/disjoint.hpp b/boost/geometry/algorithms/dispatch/disjoint.hpp index 78015f1a55..ef74991883 100644 --- a/boost/geometry/algorithms/dispatch/disjoint.hpp +++ b/boost/geometry/algorithms/dispatch/disjoint.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 Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -23,6 +23,7 @@ #include <cstddef> +#include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tag_cast.hpp> #include <boost/geometry/core/tags.hpp> diff --git a/boost/geometry/algorithms/dispatch/distance.hpp b/boost/geometry/algorithms/dispatch/distance.hpp index cae3ebd0c9..b12fc0ce9d 100644 --- a/boost/geometry/algorithms/dispatch/distance.hpp +++ b/boost/geometry/algorithms/dispatch/distance.hpp @@ -5,10 +5,11 @@ // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. -// 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. @@ -25,8 +26,9 @@ #include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tag_cast.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/strategies/distance.hpp> +#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp> #include <boost/geometry/algorithms/not_implemented.hpp> +#include <boost/geometry/strategies/distance.hpp> namespace boost { namespace geometry diff --git a/boost/geometry/algorithms/dispatch/envelope.hpp b/boost/geometry/algorithms/dispatch/envelope.hpp index bb8a99f5a8..bfe0f0d447 100644 --- a/boost/geometry/algorithms/dispatch/envelope.hpp +++ b/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<Geometry>::type, - typename CS_Tag = typename cs_tag<Geometry>::type + typename Tag = typename tag<Geometry>::type > struct envelope : not_implemented<Tag> {}; diff --git a/boost/geometry/algorithms/dispatch/expand.hpp b/boost/geometry/algorithms/dispatch/expand.hpp index c7a7696480..204bbc6ce3 100644 --- a/boost/geometry/algorithms/dispatch/expand.hpp +++ b/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<GeometryOut>::type, - typename Tag = typename tag<Geometry>::type, - typename CSTagOut = typename cs_tag<GeometryOut>::type, - typename CSTag = typename cs_tag<Geometry>::type + typename Tag = typename tag<Geometry>::type > struct expand : not_implemented<TagOut, Tag> {}; diff --git a/boost/geometry/algorithms/is_convex.hpp b/boost/geometry/algorithms/is_convex.hpp index 4a9251b270..1df778d1b5 100644 --- a/boost/geometry/algorithms/is_convex.hpp +++ b/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 <typename Ring, typename SideStrategy> 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/boost/geometry/algorithms/line_interpolate.hpp b/boost/geometry/algorithms/line_interpolate.hpp new file mode 100644 index 0000000000..1de92a0b62 --- /dev/null +++ b/boost/geometry/algorithms/line_interpolate.hpp @@ -0,0 +1,411 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2018, 2019 Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP + +#include <iterator> + +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <boost/range/value_type.hpp> + +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/closure.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/geometries/concepts/check.hpp> + +#include <boost/geometry/algorithms/assign.hpp> +#include <boost/geometry/algorithms/length.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> +#include <boost/geometry/strategies/line_interpolate.hpp> + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace line_interpolate +{ + +struct convert_and_push_back +{ + template <typename Range, typename Point> + inline void apply(Point const& p, Range& range) + { + typename boost::range_value<Range>::type p2; + geometry::detail::conversion::convert_point_to_point(p, p2); + range::push_back(range, p2); + } +}; + +struct convert_and_assign +{ + template <typename Point1, typename Point2> + inline void apply(Point1 const& p1, Point2& p2) + { + geometry::detail::conversion::convert_point_to_point(p1, p2); + } + +}; + + +/*! +\brief Internal, calculates interpolation point of a linestring using iterator pairs and + specified strategy +*/ +template <typename Policy> +struct interpolate_range +{ + template + < + typename Range, + typename Distance, + typename PointLike, + typename Strategy + > + static inline void apply(Range const& range, + Distance const& max_distance, + PointLike & pointlike, + Strategy const& strategy) + { + Policy policy; + + typedef typename boost::range_iterator<Range const>::type iterator_t; + typedef typename boost::range_value<Range const>::type point_t; + + iterator_t it = boost::begin(range); + iterator_t end = boost::end(range); + + if (it == end) // empty(range) + { + BOOST_THROW_EXCEPTION(empty_input_exception()); + return; + } + if (max_distance <= 0) //non positive distance + { + policy.apply(*it, pointlike); + return; + } + + iterator_t prev = it++; + Distance repeated_distance = max_distance; + Distance prev_distance = 0; + Distance current_distance = 0; + point_t start_p = *prev; + + for ( ; it != end ; ++it) + { + Distance dist = strategy.get_distance_pp_strategy().apply(*prev, *it); + current_distance = prev_distance + dist; + + while (current_distance >= repeated_distance) + { + point_t p; + Distance diff_distance = current_distance - prev_distance; + BOOST_ASSERT(diff_distance != Distance(0)); + strategy.apply(start_p, *it, + (repeated_distance - prev_distance)/diff_distance, + p, + diff_distance); + policy.apply(p, pointlike); + if (boost::is_same<PointLike, point_t>::value) + { + return; + } + start_p = p; + prev_distance = repeated_distance; + repeated_distance += max_distance; + } + prev_distance = current_distance; + prev = it; + start_p = *prev; + } + + // case when max_distance is larger than linestring's length + // return the last point in range (range is not empty) + if (repeated_distance == max_distance) + { + policy.apply(*(end-1), pointlike); + } + } +}; + +template <typename Policy> +struct interpolate_segment +{ + template <typename Segment, typename Distance, typename Pointlike, typename Strategy> + static inline void apply(Segment const& segment, + Distance const& max_distance, + Pointlike & point, + Strategy const& strategy) + { + interpolate_range<Policy>().apply(segment_view<Segment>(segment), + max_distance, point, strategy); + } +}; + +}} // namespace detail::line_interpolate +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Geometry, + typename Pointlike, + typename Tag1 = typename tag<Geometry>::type, + typename Tag2 = typename tag<Pointlike>::type +> +struct line_interpolate +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE + , (types<Geometry>) + ); +}; + + +template <typename Geometry, typename Pointlike> +struct line_interpolate<Geometry, Pointlike, linestring_tag, point_tag> + : detail::line_interpolate::interpolate_range + < + detail::line_interpolate::convert_and_assign + > +{}; + +template <typename Geometry, typename Pointlike> +struct line_interpolate<Geometry, Pointlike, linestring_tag, multi_point_tag> + : detail::line_interpolate::interpolate_range + < + detail::line_interpolate::convert_and_push_back + > +{}; + +template <typename Geometry, typename Pointlike> +struct line_interpolate<Geometry, Pointlike, segment_tag, point_tag> + : detail::line_interpolate::interpolate_segment + < + detail::line_interpolate::convert_and_assign + > +{}; + +template <typename Geometry, typename Pointlike> +struct line_interpolate<Geometry, Pointlike, segment_tag, multi_point_tag> + : detail::line_interpolate::interpolate_segment + < + detail::line_interpolate::convert_and_push_back + > +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_strategy { + +struct line_interpolate +{ + template + < + typename Geometry, + typename Distance, + typename Pointlike, + typename Strategy + > + static inline void apply(Geometry const& geometry, + Distance const& max_distance, + Pointlike & pointlike, + Strategy const& strategy) + { + dispatch::line_interpolate<Geometry, Pointlike>::apply(geometry, + max_distance, + pointlike, + strategy); + } + + template <typename Geometry, typename Distance, typename Pointlike> + static inline void apply(Geometry const& geometry, + Distance const& max_distance, + Pointlike & pointlike, + default_strategy) + { + typedef typename strategy::line_interpolate::services::default_strategy + < + typename cs_tag<Geometry>::type + >::type strategy_type; + + dispatch::line_interpolate<Geometry, Pointlike>::apply(geometry, + max_distance, + pointlike, + strategy_type()); + } +}; + +} // namespace resolve_strategy + + +namespace resolve_variant { + +template <typename Geometry> +struct line_interpolate +{ + template <typename Distance, typename Pointlike, typename Strategy> + static inline void apply(Geometry const& geometry, + Distance const& max_distance, + Pointlike & pointlike, + Strategy const& strategy) + { + return resolve_strategy::line_interpolate::apply(geometry, + max_distance, + pointlike, + strategy); + } +}; + +template <BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct line_interpolate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename Pointlike, typename Strategy> + struct visitor: boost::static_visitor<void> + { + Pointlike const& m_pointlike; + Strategy const& m_strategy; + + visitor(Pointlike const& pointlike, Strategy const& strategy) + : m_pointlike(pointlike) + , m_strategy(strategy) + {} + + template <typename Geometry, typename Distance> + void operator()(Geometry const& geometry, Distance const& max_distance) const + { + line_interpolate<Geometry>::apply(geometry, max_distance, + m_pointlike, m_strategy); + } + }; + + template <typename Distance, typename Pointlike, typename Strategy> + static inline void + apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry, + double const& max_distance, + Pointlike & pointlike, + Strategy const& strategy) + { + boost::apply_visitor( + visitor<Pointlike, Strategy>(pointlike, strategy), + geometry, + max_distance + ); + } +}; + +} // namespace resolve_variant + +/*! +\brief Returns one or more points interpolated along a LineString \brief_strategy +\ingroup line_interpolate +\tparam Geometry Any type fulfilling a LineString concept +\tparam Distance A numerical distance measure +\tparam Pointlike Any type fulfilling Point or Multipoint concept +\tparam Strategy A type fulfilling a LineInterpolatePointStrategy concept +\param geometry Input geometry +\param max_distance Distance threshold (in units depending on coordinate system) +representing the spacing between the points +\param pointlike Output: either a Point (exactly one point will be constructed) or +a MultiPoint (depending on the max_distance one or more points will be constructed) +\param strategy line_interpolate strategy to be used for interpolation of +points + +\qbk{[include reference/algorithms/line_interpolate.qbk]} + +\qbk{distinguish,with strategy} + +\qbk{ +[heading Available Strategies] +\* [link geometry.reference.strategies.strategy_line_interpolate_cartesian Cartesian] +\* [link geometry.reference.strategies.strategy_line_interpolate_spherical Spherical] +\* [link geometry.reference.strategies.strategy_line_interpolate_geographic Geographic] + +[heading Example] +[line_interpolate_strategy] +[line_interpolate_strategy_output] + +[heading See also] +\* [link geometry.reference.algorithms.densify densify] +} + */ +template +< + typename Geometry, + typename Distance, + typename Pointlike, + typename Strategy +> +inline void line_interpolate(Geometry const& geometry, + Distance const& max_distance, + Pointlike & pointlike, + Strategy const& strategy) +{ + concepts::check<Geometry const>(); + + // detail::throw_on_empty_input(geometry); + + return resolve_variant::line_interpolate<Geometry> + ::apply(geometry, max_distance, pointlike, strategy); +} + + +/*! +\brief Returns one or more points interpolated along a LineString. +\ingroup line_interpolate +\tparam Geometry Any type fulfilling a LineString concept +\tparam Distance A numerical distance measure +\tparam Pointlike Any type fulfilling Point or Multipoint concept +\param geometry Input geometry +\param max_distance Distance threshold (in units depending on coordinate system) +representing the spacing between the points +\param pointlike Output: either a Point (exactly one point will be constructed) or +a MultiPoint (depending on the max_distance one or more points will be constructed) + +\qbk{[include reference/algorithms/line_interpolate.qbk] + +[heading Example] +[line_interpolate] +[line_interpolate_output] + +[heading See also] +\* [link geometry.reference.algorithms.densify densify] +} + */ +template<typename Geometry, typename Distance, typename Pointlike> +inline void line_interpolate(Geometry const& geometry, + Distance const& max_distance, + Pointlike & pointlike) +{ + concepts::check<Geometry const>(); + + // detail::throw_on_empty_input(geometry); + + return resolve_variant::line_interpolate<Geometry> + ::apply(geometry, max_distance, pointlike, default_strategy()); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP diff --git a/boost/geometry/algorithms/simplify.hpp b/boost/geometry/algorithms/simplify.hpp index 298f9c640a..b5276878ef 100644 --- a/boost/geometry/algorithms/simplify.hpp +++ b/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. @@ -15,6 +20,7 @@ #define BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP #include <cstddef> +#include <set> #include <boost/core/ignore_unused.hpp> #include <boost/range.hpp> @@ -53,12 +59,13 @@ namespace boost { namespace geometry namespace detail { namespace simplify { -template <typename Range> -inline bool is_degenerate(Range const& range) +template <typename Range, typename EqualsStrategy> +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 +74,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 +117,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 +139,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/boost/geometry/algorithms/union.hpp b/boost/geometry/algorithms/union.hpp index d3a2daf66e..d1d04d4045 100644 --- a/boost/geometry/algorithms/union.hpp +++ b/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<Collection>::type geometry_out; - typedef typename strategy::intersection::services::default_strategy + typedef typename strategy::relate::services::default_strategy < - typename cs_tag<geometry_out>::type + Geometry1, + Geometry2 >::type strategy_type; dispatch::union_insert diff --git a/boost/geometry/core/config.hpp b/boost/geometry/core/config.hpp new file mode 100644 index 0000000000..c068e98cc7 --- /dev/null +++ b/boost/geometry/core/config.hpp @@ -0,0 +1,26 @@ +// 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_CORE_CONFIG_HPP +#define BOOST_GEOMETRY_CORE_CONFIG_HPP + +#include <boost/config.hpp> + +// NOTE: workaround for VC++ 12 (aka 2013): cannot specify explicit initializer for arrays +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && (!defined(_MSC_VER) || (_MSC_VER >= 1900)) +#define BOOST_GEOMETRY_CXX11_ARRAY_UNIFIED_INITIALIZATION +#endif + +// Rescaling is turned on, unless NO_ROBUSTNESS is defined +// In future versions of Boost.Geometry, it will be turned off by default +#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) +#define BOOST_GEOMETRY_USE_RESCALING +#endif + +#endif // BOOST_GEOMETRY_CORE_CONFIG_HPP diff --git a/boost/geometry/core/cs.hpp b/boost/geometry/core/cs.hpp index 301fb6b76f..c39eec3d4d 100644 --- a/boost/geometry/core/cs.hpp +++ b/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 <cstddef> #include <boost/mpl/assert.hpp> -#include <boost/type_traits/integral_constant.hpp> #include <boost/geometry/core/coordinate_system.hpp> #include <boost/geometry/core/tags.hpp> @@ -56,7 +56,7 @@ namespace core_detail { template <typename DegreeOrRadian> -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<geometry::degree> +struct define_angular_units<geometry::degree> { typedef geometry::degree units; }; template <> -struct coordinate_system_units<geometry::radian> +struct define_angular_units<geometry::radian> { typedef geometry::radian units; }; @@ -107,12 +107,8 @@ known as lat,long or lo,la or phi,lambda */ template<typename DegreeOrRadian> struct geographic -{ - typedef typename core_detail::coordinate_system_units - < - DegreeOrRadian - >::units units; -}; + : core_detail::define_angular_units<DegreeOrRadian> +{}; @@ -136,12 +132,8 @@ struct geographic */ template<typename DegreeOrRadian> struct spherical -{ - typedef typename core_detail::coordinate_system_units - < - DegreeOrRadian - >::units units; -}; + : core_detail::define_angular_units<DegreeOrRadian> +{}; /*! @@ -156,12 +148,8 @@ struct spherical */ template<typename DegreeOrRadian> struct spherical_equatorial -{ - typedef typename core_detail::coordinate_system_units - < - DegreeOrRadian - >::units units; -}; + : core_detail::define_angular_units<DegreeOrRadian> +{}; @@ -174,12 +162,15 @@ struct spherical_equatorial */ template<typename DegreeOrRadian> struct polar -{ - typedef typename core_detail::coordinate_system_units - < - DegreeOrRadian - >::units units; -}; + : core_detail::define_angular_units<DegreeOrRadian> +{}; + + +/*! +\brief Undefined coordinate system +\ingroup cs +*/ +struct undefined {}; } // namespace cs @@ -227,9 +218,18 @@ struct cs_tag<cs::cartesian> }; +template <> +struct cs_tag<cs::undefined> +{ + 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 -*/ +namespace traits +{ + +// cartesian or undefined template <typename CoordinateSystem> -struct is_radian : boost::true_type {}; +struct cs_angular_units +{ + typedef geometry::radian type; +}; + +#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS + +template<typename DegreeOrRadian> +struct cs_angular_units<cs::geographic<DegreeOrRadian> > +{ + typedef DegreeOrRadian type; +}; + +template<typename DegreeOrRadian> +struct cs_angular_units<cs::spherical<DegreeOrRadian> > +{ + typedef DegreeOrRadian type; +}; + +template<typename DegreeOrRadian> +struct cs_angular_units<cs::spherical_equatorial<DegreeOrRadian> > +{ + typedef DegreeOrRadian type; +}; + +#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS + +} // namespace traits -#ifndef DOXYGEN_NO_SPECIALIZATIONS -// Specialization for any degree coordinate systems -template <template<typename> class CoordinateSystem> -struct is_radian< CoordinateSystem<degree> > : boost::false_type +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template <typename Geometry> +struct cs_angular_units { + typedef typename traits::cs_angular_units + < + typename geometry::coordinate_system<Geometry>::type + >::type type; }; -#endif // DOXYGEN_NO_SPECIALIZATIONS + +template <typename Units, typename CsTag> +struct cs_tag_to_coordinate_system +{ + BOOST_MPL_ASSERT_MSG((false), + NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM, + (types<CsTag>)); +}; + +template <typename Units> +struct cs_tag_to_coordinate_system<Units, cs_undefined_tag> +{ + typedef cs::undefined type; +}; + +template <typename Units> +struct cs_tag_to_coordinate_system<Units, cartesian_tag> +{ + typedef cs::cartesian type; +}; + +template <typename Units> +struct cs_tag_to_coordinate_system<Units, spherical_equatorial_tag> +{ + typedef cs::spherical_equatorial<Units> type; +}; + +template <typename Units> +struct cs_tag_to_coordinate_system<Units, spherical_polar_tag> +{ + typedef cs::spherical<Units> type; +}; + +template <typename Units> +struct cs_tag_to_coordinate_system<Units, geographic_tag> +{ + typedef cs::geographic<Units> type; +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + }} // namespace boost::geometry diff --git a/boost/geometry/core/tags.hpp b/boost/geometry/core/tags.hpp index 5d6acb1878..f5bebbacb1 100644 --- a/boost/geometry/core/tags.hpp +++ b/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/boost/geometry/formulas/area_formulas.hpp b/boost/geometry/formulas/area_formulas.hpp index 66d90a7256..c670f831a6 100644 --- a/boost/geometry/formulas/area_formulas.hpp +++ b/boost/geometry/formulas/area_formulas.hpp @@ -12,6 +12,7 @@ #ifndef BOOST_GEOMETRY_FORMULAS_AREA_FORMULAS_HPP #define BOOST_GEOMETRY_FORMULAS_AREA_FORMULAS_HPP +#include <boost/geometry/core/radian_access.hpp> #include <boost/geometry/formulas/flattening.hpp> #include <boost/geometry/util/math.hpp> #include <boost/math/special_functions/hypot.hpp> diff --git a/boost/geometry/formulas/differential_quantities.hpp b/boost/geometry/formulas/differential_quantities.hpp index ff2ec539db..6d4c223286 100644 --- a/boost/geometry/formulas/differential_quantities.hpp +++ b/boost/geometry/formulas/differential_quantities.hpp @@ -1,6 +1,6 @@ // Boost.Geometry -// Copyright (c) 2016-2017 Oracle and/or its affiliates. +// Copyright (c) 2016-2019 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -70,10 +70,11 @@ public: // equator if (math::equals(sin_bet1, c0) && math::equals(sin_bet2, c0)) { - CT const sig_12 = math::abs(dlon) / one_minus_f; + CT const sig_12 = dlon / one_minus_f; if (BOOST_GEOMETRY_CONDITION(EnableReducedLength)) { - CT m12 = sin(sig_12) * b; + int azi_sign = math::sign(azimuth) >= 0 ? 1 : -1; // for antipodal + CT m12 = azi_sign * sin(sig_12) * b; reduced_length = m12; } diff --git a/boost/geometry/formulas/eccentricity_sqr.hpp b/boost/geometry/formulas/eccentricity_sqr.hpp index 01a9beacb9..1608a85707 100644 --- a/boost/geometry/formulas/eccentricity_sqr.hpp +++ b/boost/geometry/formulas/eccentricity_sqr.hpp @@ -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 @@ -11,11 +11,13 @@ #ifndef BOOST_GEOMETRY_FORMULAS_ECCENCRICITY_SQR_HPP #define BOOST_GEOMETRY_FORMULAS_ECCENCRICITY_SQR_HPP +#include <boost/geometry/algorithms/not_implemented.hpp> + #include <boost/geometry/core/radius.hpp> #include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/algorithms/not_implemented.hpp> +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/formulas/interpolate_point_spherical.hpp b/boost/geometry/formulas/interpolate_point_spherical.hpp new file mode 100644 index 0000000000..7141a5a9f6 --- /dev/null +++ b/boost/geometry/formulas/interpolate_point_spherical.hpp @@ -0,0 +1,107 @@ +// Boost.Geometry + +// Copyright (c) 2019 Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_FORMULAS_INTERPOLATE_POINT_SPHERICAL_HPP +#define BOOST_GEOMETRY_FORMULAS_INTERPOLATE_POINT_SPHERICAL_HPP + +namespace boost { namespace geometry { namespace formula +{ + +template <typename CalculationType> +class interpolate_point_spherical +{ + typedef model::point<CalculationType, 3, cs::cartesian> point3d_t; + +public : + + template <typename Point> + void compute_angle(Point const& p0, + Point const& p1, + CalculationType& angle01) + { + m_xyz0 = formula::sph_to_cart3d<point3d_t>(p0); + m_xyz1 = formula::sph_to_cart3d<point3d_t>(p1); + CalculationType const dot01 = geometry::dot_product(m_xyz0, m_xyz1); + angle01 = acos(dot01); + } + + template <typename Point> + void compute_axis(Point const& p0, + CalculationType const& angle01) + { + CalculationType const c0 = 0, c1 = 1; + CalculationType const pi = math::pi<CalculationType>(); + + if (! math::equals(angle01, pi)) + { + m_axis = geometry::cross_product(m_xyz0, m_xyz1); + geometry::detail::vec_normalize(m_axis); + } + else // antipodal + { + CalculationType const half_pi = math::half_pi<CalculationType>(); + CalculationType const lat = geometry::get_as_radian<1>(p0); + + if (math::equals(lat, half_pi)) + { + // pointing east, segment lies on prime meridian, going south + m_axis = point3d_t(c0, c1, c0); + } + else if (math::equals(lat, -half_pi)) + { + // pointing west, segment lies on prime meridian, going north + m_axis = point3d_t(c0, -c1, c0); + } + else + { + // lon rotated west by pi/2 at equator + CalculationType const lon = geometry::get_as_radian<0>(p0); + m_axis = point3d_t(sin(lon), -cos(lon), c0); + } + } + } + + template <typename Point> + void compute_point(CalculationType const& a, Point& p) + { + CalculationType const c1 = 1; + + // Axis-Angle rotation + // see: https://en.wikipedia.org/wiki/Axis-angle_representation + CalculationType const cos_a = cos(a); + CalculationType const sin_a = sin(a); + // cos_a * v + point3d_t s1 = m_xyz0; + geometry::multiply_value(s1, cos_a); + // sin_a * (n x v) + point3d_t s2 = geometry::cross_product(m_axis, m_xyz0); + geometry::multiply_value(s2, sin_a); + // (1 - cos_a)(n.v) * n + point3d_t s3 = m_axis; + geometry::multiply_value(s3, (c1 - cos_a) * + geometry::dot_product(m_axis, m_xyz0)); + // v_rot = cos_a * v + sin_a * (n x v) + (1 - cos_a)(n.v) * e + point3d_t v_rot = s1; + geometry::add_point(v_rot, s2); + geometry::add_point(v_rot, s3); + + p = formula::cart3d_to_sph<Point>(v_rot); + } + +private : + point3d_t m_xyz0; + point3d_t m_xyz1; + point3d_t m_axis; +}; + +}}} // namespace boost::geometry::formula + +#endif // BOOST_GEOMETRY_FORMULAS_INTERPOLATE_POINT_SPHERICAL_HPP diff --git a/boost/geometry/formulas/karney_direct.hpp b/boost/geometry/formulas/karney_direct.hpp index 1e6add7d49..7a89061fd6 100644 --- a/boost/geometry/formulas/karney_direct.hpp +++ b/boost/geometry/formulas/karney_direct.hpp @@ -2,7 +2,12 @@ // Copyright (c) 2018 Adeel Ahmad, Islamabad, Pakistan. -// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program. +// Contributed and/or modified by Adeel Ahmad, +// as part of Google Summer of Code 2018 program. + +// 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 @@ -30,13 +35,14 @@ #include <boost/math/constants/constants.hpp> #include <boost/math/special_functions/hypot.hpp> -#include <boost/geometry/util/math.hpp> -#include <boost/geometry/util/series_expansion.hpp> -#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> - #include <boost/geometry/formulas/flattening.hpp> #include <boost/geometry/formulas/result_direct.hpp> +#include <boost/geometry/util/condition.hpp> +#include <boost/geometry/util/math.hpp> +#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> +#include <boost/geometry/util/series_expansion.hpp> + namespace boost { namespace geometry { namespace formula { @@ -82,15 +88,6 @@ public: Azi azi12 = azimuth12; math::normalize_azimuth<degree, Azi>(azi12); - Dist const dist_c0 = 0; - - if (math::equals(distance, dist_c0) || distance < dist_c0) - { - result.lon2 = lon1; - result.lat2 = lat1; - return result; - } - CT const c0 = 0; CT const c1 = 1; CT const c2 = 2; diff --git a/boost/geometry/formulas/meridian_direct.hpp b/boost/geometry/formulas/meridian_direct.hpp index e55b35e88f..f8e73f57c6 100644 --- a/boost/geometry/formulas/meridian_direct.hpp +++ b/boost/geometry/formulas/meridian_direct.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 @@ -15,14 +16,15 @@ #include <boost/geometry/core/radius.hpp> -#include <boost/geometry/util/condition.hpp> -#include <boost/geometry/util/math.hpp> - -#include <boost/geometry/formulas/meridian_inverse.hpp> +#include <boost/geometry/formulas/differential_quantities.hpp> #include <boost/geometry/formulas/flattening.hpp> +#include <boost/geometry/formulas/meridian_inverse.hpp> #include <boost/geometry/formulas/quarter_meridian.hpp> #include <boost/geometry/formulas/result_direct.hpp> +#include <boost/geometry/util/condition.hpp> +#include <boost/geometry/util/math.hpp> + namespace boost { namespace geometry { namespace formula { diff --git a/boost/geometry/formulas/meridian_segment.hpp b/boost/geometry/formulas/meridian_segment.hpp index 535e31e3db..0aa7542f91 100644 --- a/boost/geometry/formulas/meridian_segment.hpp +++ b/boost/geometry/formulas/meridian_segment.hpp @@ -1,8 +1,9 @@ // 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 // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -14,7 +15,6 @@ #include <boost/math/constants/constants.hpp> #include <boost/geometry/core/radius.hpp> -#include <boost/geometry/srs/srs.hpp> #include <boost/geometry/util/condition.hpp> #include <boost/geometry/util/math.hpp> diff --git a/boost/geometry/formulas/quarter_meridian.hpp b/boost/geometry/formulas/quarter_meridian.hpp index 2f93f53cf6..5aa10cc870 100644 --- a/boost/geometry/formulas/quarter_meridian.hpp +++ b/boost/geometry/formulas/quarter_meridian.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 @@ -11,11 +12,15 @@ #ifndef BOOST_GEOMETRY_FORMULAS_QUARTER_MERIDIAN_HPP #define BOOST_GEOMETRY_FORMULAS_QUARTER_MERIDIAN_HPP +#include <boost/geometry/algorithms/not_implemented.hpp> + #include <boost/geometry/core/radius.hpp> #include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tags.hpp> -#include <boost/geometry/algorithms/not_implemented.hpp> +#include <boost/geometry/formulas/flattening.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/formulas/spherical.hpp b/boost/geometry/formulas/spherical.hpp index 5599cd6e81..964e2de302 100644 --- a/boost/geometry/formulas/spherical.hpp +++ b/boost/geometry/formulas/spherical.hpp @@ -13,6 +13,7 @@ #include <boost/geometry/core/coordinate_system.hpp> #include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/access.hpp> #include <boost/geometry/core/radian_access.hpp> #include <boost/geometry/core/radius.hpp> @@ -98,7 +99,7 @@ static inline PointSph cart3d_to_sph(Point3d const& point_3d) math::normalize_spheroidal_coordinates < - typename coordinate_system<PointSph>::type::units, + typename detail::cs_angular_units<PointSph>::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 <typename T> 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>(); T const two_pi = math::two_pi<T>(); @@ -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/boost/geometry/formulas/thomas_direct.hpp b/boost/geometry/formulas/thomas_direct.hpp index 830f256a6e..7b61616af6 100644 --- a/boost/geometry/formulas/thomas_direct.hpp +++ b/boost/geometry/formulas/thomas_direct.hpp @@ -67,13 +67,6 @@ public: CT const lon1 = lo1; CT const lat1 = la1; - if ( math::equals(distance, Dist(0)) || distance < Dist(0) ) - { - result.lon2 = lon1; - result.lat2 = lat1; - return result; - } - CT const c0 = 0; CT const c1 = 1; CT const c2 = 2; diff --git a/boost/geometry/formulas/vincenty_direct.hpp b/boost/geometry/formulas/vincenty_direct.hpp index b72379defe..2806de04cd 100644 --- a/boost/geometry/formulas/vincenty_direct.hpp +++ b/boost/geometry/formulas/vincenty_direct.hpp @@ -74,13 +74,6 @@ public: CT const lon1 = lo1; CT const lat1 = la1; - if ( math::equals(distance, Dist(0)) || distance < Dist(0) ) - { - result.lon2 = lon1; - result.lat2 = lat1; - return result; - } - CT const radius_a = CT(get_radius<0>(spheroid)); CT const radius_b = CT(get_radius<2>(spheroid)); CT const flattening = formula::flattening<CT>(spheroid); diff --git a/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp b/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp index 84f72aadcb..ca54ec6afe 100644 --- a/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp +++ b/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp @@ -2,6 +2,11 @@ // Copyright (c) 2010-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) @@ -14,9 +19,11 @@ // pair{begin_points, end_points} -> ring_proxy #include <boost/polygon/polygon.hpp> -#include <boost/range.hpp> - +#include <boost/range/const_iterator.hpp> +#include <boost/range/mutable_iterator.hpp> +#include <boost/geometry/core/mutable_range.hpp> +#include <boost/geometry/core/tag.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/geometries/adapted/boost_tuple.hpp b/boost/geometry/geometries/adapted/boost_tuple.hpp index 58065fe9af..88d1af37b8 100644 --- a/boost/geometry/geometries/adapted/boost_tuple.hpp +++ b/boost/geometry/geometries/adapted/boost_tuple.hpp @@ -4,6 +4,11 @@ // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. // 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. @@ -19,6 +24,7 @@ #include <boost/tuple/tuple.hpp> +#include <boost/geometry/core/access.hpp> #include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/point_type.hpp> diff --git a/boost/geometry/geometries/adapted/std_array.hpp b/boost/geometry/geometries/adapted/std_array.hpp index 4f5cbe0d32..ede9fe9974 100644 --- a/boost/geometry/geometries/adapted/std_array.hpp +++ b/boost/geometry/geometries/adapted/std_array.hpp @@ -12,6 +12,12 @@ #define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_ARRAY_HPP +#include <boost/config.hpp> + + +#ifndef BOOST_NO_CXX11_HDR_ARRAY + + #define BOOST_GEOMETRY_ADAPTED_STD_ARRAY_TAG_DEFINED @@ -111,5 +117,14 @@ struct access<std::array<CoordinateType, DimensionCount>, Dimension> }}} +#else + + +#warning "This file requires compiler and library support for the ISO C++ 2011 standard." + + +#endif // BOOST_NO_CXX11_HDR_ARRAY + + #endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_ARRAY_HPP diff --git a/boost/geometry/geometries/concepts/multi_point_concept.hpp b/boost/geometry/geometries/concepts/multi_point_concept.hpp index 9e205f1635..9dffdb1c41 100644 --- a/boost/geometry/geometries/concepts/multi_point_concept.hpp +++ b/boost/geometry/geometries/concepts/multi_point_concept.hpp @@ -20,6 +20,7 @@ #include <boost/range/concepts.hpp> #include <boost/range/metafunctions.hpp> +#include <boost/geometry/core/mutable_range.hpp> #include <boost/geometry/geometries/concepts/point_concept.hpp> diff --git a/boost/geometry/geometries/helper_geometry.hpp b/boost/geometry/geometries/helper_geometry.hpp index f3102fee93..e110dd2b1b 100644 --- a/boost/geometry/geometries/helper_geometry.hpp +++ b/boost/geometry/geometries/helper_geometry.hpp @@ -32,60 +32,6 @@ namespace boost { namespace geometry namespace detail { namespace helper_geometries { -template <typename Geometry, typename CS_Tag = typename cs_tag<Geometry>::type> -struct default_units -{ - typedef typename coordinate_system<Geometry>::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 <typename Geometry> -struct default_units<Geometry, cartesian_tag> -{ - typedef radian type; -}; - - -template <typename Units, typename CS_Tag> -struct cs_tag_to_coordinate_system -{ - BOOST_MPL_ASSERT_MSG((false), - NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM, - (types<CS_Tag>)); -}; - -template <typename Units> -struct cs_tag_to_coordinate_system<Units, cartesian_tag> -{ - typedef cs::cartesian type; -}; - -template <typename Units> -struct cs_tag_to_coordinate_system<Units, spherical_equatorial_tag> -{ - typedef cs::spherical_equatorial<Units> type; -}; - -template <typename Units> -struct cs_tag_to_coordinate_system<Units, spherical_polar_tag> -{ - typedef cs::spherical<Units> type; -}; - -template <typename Units> -struct cs_tag_to_coordinate_system<Units, geographic_tag> -{ - typedef cs::geographic<Units> type; -}; - - template < typename Point, @@ -154,10 +100,7 @@ template < typename Geometry, typename NewCoordinateType = typename coordinate_type<Geometry>::type, - typename NewUnits = typename detail::helper_geometries::default_units - < - Geometry - >::type + typename NewUnits = typename detail::cs_angular_units<Geometry>::type > struct helper_geometry { diff --git a/boost/geometry/geometries/variant.hpp b/boost/geometry/geometries/variant.hpp index 881eab9c8b..6b19c113d2 100644 --- a/boost/geometry/geometries/variant.hpp +++ b/boost/geometry/geometries/variant.hpp @@ -4,6 +4,11 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // 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. @@ -15,8 +20,10 @@ #define BOOST_GEOMETRY_GEOMETRIES_VARIANT_GEOMETRY_HPP -#include <boost/variant/variant_fwd.hpp> #include <boost/mpl/front.hpp> +#include <boost/variant/variant_fwd.hpp> + +#include <boost/geometry/core/point_type.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/geometry.hpp b/boost/geometry/geometry.hpp index 0957d48a29..5c2c58e4cb 100644 --- a/boost/geometry/geometry.hpp +++ b/boost/geometry/geometry.hpp @@ -76,6 +76,7 @@ #include <boost/geometry/algorithms/is_simple.hpp> #include <boost/geometry/algorithms/is_valid.hpp> #include <boost/geometry/algorithms/length.hpp> +#include <boost/geometry/algorithms/line_interpolate.hpp> #include <boost/geometry/algorithms/make.hpp> #include <boost/geometry/algorithms/num_geometries.hpp> #include <boost/geometry/algorithms/num_interior_rings.hpp> diff --git a/boost/geometry/index/detail/algorithms/intersection_content.hpp b/boost/geometry/index/detail/algorithms/intersection_content.hpp index 437f90b46c..b8ef9e7163 100644 --- a/boost/geometry/index/detail/algorithms/intersection_content.hpp +++ b/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 <typename Box> inline typename default_content_result<Box>::type intersection_content(Box const& box1, Box const& box2) { - bool const intersects = ! geometry::detail::disjoint::box_box<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/boost/geometry/index/detail/meta.hpp b/boost/geometry/index/detail/meta.hpp index bec1380b06..10118ade7c 100644 --- a/boost/geometry/index/detail/meta.hpp +++ b/boost/geometry/index/detail/meta.hpp @@ -1,6 +1,6 @@ // Boost.Geometry Index // -// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2019 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 @@ -10,7 +10,8 @@ #include <boost/mpl/aux_/has_type.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/and.hpp> -//#include <boost/type_traits/is_convertible.hpp> +#include <boost/type_traits/is_convertible.hpp> +#include <boost/type_traits/is_same.hpp> #ifndef BOOST_GEOMETRY_INDEX_DETAIL_META_HPP #define BOOST_GEOMETRY_INDEX_DETAIL_META_HPP @@ -37,6 +38,68 @@ struct is_range // : is_range_of_convertible_values_impl<T, V, is_range<T>::value> //{}; +// Implemented this way in order to prevent instantiation of all type traits at +// once because some of them are causing problems with gcc 4.6 namely +// is_convertible<bg::model::segment<>, std::pair<bg::model::segment<>, T> > +// because segment<> is derived from pair<> and pair<> has copy ctor taking +// other pair<> of any types the compiler tries to instantiate ctor of +// pair<segment, T> taking pair<point, point> which results in instantiation of +// segment's ctor taking a point which results in compilation error. +// This is probably compiler's bug. +template <typename T, typename Value, typename Indexable, typename ResultType, int Ver> +struct convertible_type_impl +{ + typedef ResultType type; +}; + +template <typename T, typename Value, typename Indexable> +struct convertible_type_impl<T, Value, Indexable, void, 0> +{ + typedef typename boost::mpl::if_c + < + boost::is_convertible<T, Indexable>::value, + Indexable, + void + >::type result_type; + + typedef typename convertible_type_impl + < + T, Value, Indexable, result_type, 1 + >::type type; +}; + +template <typename T, typename Value, typename Indexable> +struct convertible_type_impl<T, Value, Indexable, void, 1> +{ + typedef typename boost::mpl::if_c + < + boost::is_convertible<T, Value>::value, + Value, + void + >::type type; +}; + +template <typename T, typename Value, typename Indexable> +struct convertible_type +{ + typedef typename boost::mpl::if_c + < + boost::is_same<T, Value>::value, + Value, + typename boost::mpl::if_c + < + boost::is_same<T, Indexable>::value, + Indexable, + void + >::type + >::type result_type; + + typedef typename convertible_type_impl + < + T, Value, Indexable, result_type, 0 + >::type type; +}; + }}}} // namespace boost::geometry::index::detail #endif // BOOST_GEOMETRY_INDEX_DETAIL_META_HPP diff --git a/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp b/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp index e07926ffed..2ac6eb27c9 100644 --- a/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp +++ b/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp @@ -2,7 +2,7 @@ // // R-tree R*-tree next node choosing algorithm implementation // -// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2019 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 @@ -65,6 +65,20 @@ public: } private: + struct child_contents + { + content_type content_diff; + content_type content; + size_t i; + + void set(size_t i_, content_type const& content_, content_type const& content_diff_) + { + i = i_; + content = content_; + content_diff = content_diff_; + } + }; + template <typename Indexable> static inline size_t choose_by_minimum_overlap_cost(children_type const& children, Indexable const& indexable, @@ -77,10 +91,8 @@ private: size_t choosen_index = 0; // create container of children sorted by content enlargement needed to include the new value - typedef boost::tuple<size_t, content_type, content_type> child_contents; - - typename rtree::container_from_elements_type<children_type, child_contents>::type children_contents; - children_contents.resize(children_count); + typename rtree::container_from_elements_type<children_type, child_contents>::type + children_contents(children_count); for ( size_t i = 0 ; i < children_count ; ++i ) { @@ -94,7 +106,7 @@ private: content_type content = index::detail::content(box_exp); content_type content_diff = content - index::detail::content(ch_i.first); - children_contents[i] = boost::make_tuple(i, content_diff, content); + children_contents[i].set(i, content, content_diff); if ( content_diff < min_content_diff || (content_diff == min_content_diff && content < min_content) ) @@ -125,10 +137,10 @@ private: return choosen_index; } - static inline bool content_diff_less(boost::tuple<size_t, content_type, content_type> const& p1, boost::tuple<size_t, content_type, content_type> const& p2) + static inline bool content_diff_less(child_contents const& p1, child_contents const& p2) { - return boost::get<1>(p1) < boost::get<1>(p2) || - (boost::get<1>(p1) == boost::get<1>(p2) && boost::get<2>(p1) < boost::get<2>(p2)); + return p1.content_diff < p2.content_diff + || (p1.content_diff == p2.content_diff && (p1.content) < (p2.content)); } template <typename Indexable, typename ChildrenContents> @@ -148,8 +160,12 @@ private: content_type smallest_content = (std::numeric_limits<content_type>::max)(); // for each child node - for (size_t i = 0 ; i < first_n_children_count ; ++i ) + for (size_t first_i = 0 ; first_i < first_n_children_count ; ++first_i) { + size_t i = children_contents[first_i].i; + content_type const& content = children_contents[first_i].content; + content_type const& content_diff = children_contents[first_i].content_diff; + child_type const& ch_i = children[i]; Box box_exp(ch_i.first); @@ -173,9 +189,6 @@ private: } } - content_type content = boost::get<2>(children_contents[i]); - content_type content_diff = boost::get<1>(children_contents[i]); - // update result if ( overlap_diff < smallest_overlap_diff || ( overlap_diff == smallest_overlap_diff && ( content_diff < smallest_content_diff || diff --git a/boost/geometry/index/indexable.hpp b/boost/geometry/index/indexable.hpp index 831e17f6dd..eee4e1d211 100644 --- a/boost/geometry/index/indexable.hpp +++ b/boost/geometry/index/indexable.hpp @@ -1,6 +1,6 @@ // Boost.Geometry Index // -// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2019 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 @@ -11,11 +11,43 @@ #include <boost/mpl/assert.hpp> #include <boost/tuple/tuple.hpp> +#include <boost/type_traits/is_reference.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/remove_const.hpp> +#include <boost/type_traits/remove_reference.hpp> #include <boost/geometry/index/detail/is_indexable.hpp> namespace boost { namespace geometry { namespace index { namespace detail { +template <typename T> +struct remove_cr + : boost::remove_const + < + typename boost::remove_reference<T>::type + > +{}; + +template <typename From, typename To> +struct is_referencable + : boost::is_same + < + typename remove_cr<From>::type, + typename remove_cr<To>::type + > +{}; + +template <typename Indexable, typename V> +inline Indexable const& indexable_prevent_any_type(V const& ) +{ + BOOST_MPL_ASSERT_MSG( + (false), + UNEXPECTED_TYPE, + (V) + ); + return Indexable(); +} + /*! \brief The function object extracting Indexable from Value. @@ -48,6 +80,15 @@ struct indexable { return v; } + + /*! + \brief Prevent reference to temporary for types convertible to Value. + */ + template <typename V> + inline result_type operator()(V const& v) const + { + return indexable_prevent_any_type<Value>(v); + } }; /*! @@ -56,11 +97,13 @@ struct indexable This specialization translates from std::pair<Indexable, T2>. \tparam Indexable The Indexable type. -\tparam T2 The second type. +\tparam Second The second type. */ -template <typename Indexable, typename T2> -struct indexable<std::pair<Indexable, T2>, false> +template <typename Indexable, typename Second> +struct indexable<std::pair<Indexable, Second>, false> { + typedef std::pair<Indexable, Second> value_type; + BOOST_MPL_ASSERT_MSG( (detail::is_indexable<Indexable>::value), NOT_VALID_INDEXABLE_TYPE, @@ -76,24 +119,51 @@ struct indexable<std::pair<Indexable, T2>, false> \param v The value. \return The indexable. */ - inline result_type operator()(std::pair<Indexable, T2> const& v) const + inline result_type operator()(value_type const& v) const { return v.first; } + + /*! + \brief Return indexable extracted from compatible type different than value_type. + + \param v The value. + \return The indexable. + */ + template <typename I, typename S> + inline result_type operator()(std::pair<I, S> const& v) const + { + BOOST_MPL_ASSERT_MSG( + (is_referencable<I, result_type>::value), + UNEXPECTED_TYPE, + (std::pair<I, S>) + ); + return v.first; + } + + /*! + \brief Prevent reference to temporary for types convertible to Value. + */ + template <typename V> + inline result_type operator()(V const& v) const + { + return indexable_prevent_any_type<Indexable>(v); + } }; /*! \brief The function object extracting Indexable from Value. -This specialization translates from boost::tuple<Indexable, ...>. +This specialization translates from boost::tuple<Indexable, ...> + or boost::tuples::cons<Indexable, ...>. +\tparam Value The Value type. \tparam Indexable The Indexable type. */ -template <typename Indexable, typename T1, typename T2, typename T3, typename T4, - typename T5, typename T6, typename T7, typename T8, typename T9> -struct indexable<boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9>, false> +template <typename Value, typename Indexable> +struct indexable_boost_tuple { - typedef boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9> value_type; + typedef Value value_type; BOOST_MPL_ASSERT_MSG( (detail::is_indexable<Indexable>::value), @@ -114,8 +184,85 @@ struct indexable<boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9>, fa { return boost::get<0>(v); } + + /*! + \brief Return indexable extracted from compatible type different than value_type. + + \param v The value. + \return The indexable. + */ + template <typename I, typename U1, typename U2, typename U3, typename U4, + typename U5, typename U6, typename U7, typename U8, typename U9> + inline result_type operator()(boost::tuple<I, U1, U2, U3, U4, U5, U6, U7, U8, U9> const& v) const + { + BOOST_MPL_ASSERT_MSG( + (is_referencable<I, result_type>::value), + UNEXPECTED_TYPE, + (boost::tuple<I, U1, U2, U3, U4, U5, U6, U7, U8, U9>) + ); + return boost::get<0>(v); + } + + /*! + \brief Return indexable extracted from compatible type different than value_type. + + \param v The value. + \return The indexable. + */ + template <typename I, typename T> + inline result_type operator()(boost::tuples::cons<I, T> const& v) const + { + BOOST_MPL_ASSERT_MSG( + (is_referencable<I, result_type>::value), + UNEXPECTED_TYPE, + (boost::tuples::cons<I, T>) + ); + return boost::get<0>(v); + } + + /*! + \brief Prevent reference to temporary for types convertible to Value. + */ + template <typename V> + inline result_type operator()(V const& v) const + { + return indexable_prevent_any_type<Indexable>(v); + } }; +/*! +\brief The function object extracting Indexable from Value. + +This specialization translates from boost::tuple<Indexable, ...>. + +\tparam Indexable The Indexable type. +*/ +template <typename Indexable, typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7, typename T8, typename T9> +struct indexable<boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9>, false> + : indexable_boost_tuple + < + boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9>, + Indexable + > +{}; + +/*! +\brief The function object extracting Indexable from Value. + +This specialization translates from boost::tuples::cons<Indexable, ...>. + +\tparam Indexable The Indexable type. +*/ +template <typename Indexable, typename Tail> +struct indexable<boost::tuples::cons<Indexable, Tail>, false> + : indexable_boost_tuple + < + boost::tuples::cons<Indexable, Tail>, + Indexable + > +{}; + }}}} // namespace boost::geometry::index::detail #if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) @@ -156,6 +303,32 @@ struct indexable<std::tuple<Indexable, Args...>, false> { return std::get<0>(v); } + + /*! + \brief Return indexable extracted from compatible type different than value_type. + + \param v The value. + \return The indexable. + */ + template <typename I, typename ...A> + inline result_type operator()(std::tuple<I, A...> const& v) const + { + BOOST_MPL_ASSERT_MSG( + (is_referencable<I, result_type>::value), + UNEXPECTED_TYPE, + (std::tuple<I, A...>) + ); + return std::get<0>(v); + } + + /*! + \brief Prevent reference to temporary for types convertible to Value. + */ + template <typename V> + inline result_type operator()(V const& v) const + { + return indexable_prevent_any_type<Indexable>(v); + } }; }}}} // namespace boost::geometry::index::detail @@ -190,6 +363,20 @@ struct indexable { return detail::indexable<Value>::operator()(v); } + + /*! + \brief Return indexable extracted from the value. Overload for types + compatible with Value but different yet holding referencable + Indexable, e.g. tuple containing a reference. + + \param v The value. + \return The indexable. + */ + template <typename V> + inline result_type operator()(V const& v) const + { + return detail::indexable<Value>::operator()(v); + } }; }}} // namespace boost::geometry::index diff --git a/boost/geometry/index/rtree.hpp b/boost/geometry/index/rtree.hpp index 53c2661669..1a8be031dc 100644 --- a/boost/geometry/index/rtree.hpp +++ b/boost/geometry/index/rtree.hpp @@ -3,7 +3,7 @@ // R-tree implementation // // Copyright (c) 2008 Federico J. Fernandez. -// Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2011-2019 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 @@ -1296,32 +1296,18 @@ public: return 0; // the input should be convertible to Value or Indexable type - - enum { as_val = 0, as_ind, dont_know }; - typedef boost::mpl::int_ - < - boost::is_same<ValueOrIndexable, value_type>::value ? - as_val : - boost::is_same<ValueOrIndexable, indexable_type>::value ? - as_ind : - boost::is_convertible<ValueOrIndexable, indexable_type>::value ? - as_ind : - boost::is_convertible<ValueOrIndexable, value_type>::value ? - as_val : - dont_know - > variant; - - BOOST_MPL_ASSERT_MSG((variant::value != dont_know), - PASSED_OBJECT_NOT_CONVERTIBLE_TO_VALUE_NOR_INDEXABLE_TYPE, - (ValueOrIndexable)); - - typedef typename boost::mpl::if_c + typedef typename index::detail::convertible_type < - variant::value == as_val, + ValueOrIndexable, value_type, indexable_type >::type value_or_indexable; + static const bool is_void = boost::is_same<value_or_indexable, void>::value; + BOOST_MPL_ASSERT_MSG((! is_void), + PASSED_OBJECT_NOT_CONVERTIBLE_TO_VALUE_NOR_INDEXABLE_TYPE, + (ValueOrIndexable)); + // NOTE: If an object of convertible but not the same type is passed // into the function, here a temporary will be created. return this->template raw_count<value_or_indexable>(vori); diff --git a/boost/geometry/io/wkt/read.hpp b/boost/geometry/io/wkt/read.hpp index 9caa36cb47..414024b461 100644 --- a/boost/geometry/io/wkt/read.hpp +++ b/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 <boost/geometry/algorithms/assign.hpp> #include <boost/geometry/algorithms/append.hpp> #include <boost/geometry/algorithms/clear.hpp> -#include <boost/geometry/algorithms/detail/equals/point_point.hpp> +#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp> #include <boost/geometry/core/access.hpp> #include <boost/geometry/core/coordinate_dimension.hpp> @@ -295,7 +295,7 @@ struct stateful_range_appender<Geometry, open> should_append = is_next_expected || pt_index < core_detail::closure::minimum_ring_size<open>::value - || !detail::equals::equals_point_point(point, first_point); + || disjoint(point, first_point); } ++pt_index; @@ -306,6 +306,17 @@ struct stateful_range_appender<Geometry, open> } 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/boost/geometry/io/wkt/write.hpp b/boost/geometry/io/wkt/write.hpp index 34af432fc6..62d1d6cb44 100644 --- a/boost/geometry/io/wkt/write.hpp +++ b/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<Range>::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/boost/geometry/iterators/detail/point_iterator/iterator_type.hpp b/boost/geometry/iterators/detail/point_iterator/iterator_type.hpp index a7805b127b..92c0c093c9 100644 --- a/boost/geometry/iterators/detail/point_iterator/iterator_type.hpp +++ b/boost/geometry/iterators/detail/point_iterator/iterator_type.hpp @@ -1,8 +1,9 @@ // 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 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 @@ -12,6 +13,7 @@ #include <boost/range.hpp> +#include <boost/geometry/core/interior_type.hpp> #include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tags.hpp> diff --git a/boost/geometry/policies/robustness/get_rescale_policy.hpp b/boost/geometry/policies/robustness/get_rescale_policy.hpp index daf32d3057..9bb3f885a7 100644 --- a/boost/geometry/policies/robustness/get_rescale_policy.hpp +++ b/boost/geometry/policies/robustness/get_rescale_policy.hpp @@ -25,6 +25,7 @@ #include <boost/type_traits/is_same.hpp> #include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/config.hpp> #include <boost/geometry/core/tag_cast.hpp> #include <boost/geometry/algorithms/envelope.hpp> @@ -249,9 +250,7 @@ struct rescale_policy_type : public detail::get_rescale_policy::rescale_policy_type < Point, -#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) - false -#else +#if defined(BOOST_GEOMETRY_USE_RESCALING) boost::is_floating_point < typename geometry::coordinate_type<Point>::type @@ -262,6 +261,8 @@ struct rescale_policy_type typename geometry::coordinate_system<Point>::type, geometry::cs::cartesian >::value +#else + false #endif > { diff --git a/boost/geometry/policies/robustness/rescale_policy.hpp b/boost/geometry/policies/robustness/rescale_policy.hpp index b92f6e1ec7..e4a9090567 100644 --- a/boost/geometry/policies/robustness/rescale_policy.hpp +++ b/boost/geometry/policies/robustness/rescale_policy.hpp @@ -5,7 +5,8 @@ // Copyright (c) 2014-2015 Mateusz Loskot, London, UK. // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. -// 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 Adam Wulkiewicz, on behalf of Oracle @@ -18,6 +19,8 @@ #include <cstddef> +#include <boost/geometry/core/coordinate_type.hpp> + #include <boost/geometry/policies/robustness/segment_ratio.hpp> #include <boost/geometry/policies/robustness/segment_ratio_type.hpp> #include <boost/geometry/policies/robustness/robust_point_type.hpp> diff --git a/boost/geometry/srs/projections/dpar.hpp b/boost/geometry/srs/projections/dpar.hpp index 641a4fc6e9..0cfb2e2103 100644 --- a/boost/geometry/srs/projections/dpar.hpp +++ b/boost/geometry/srs/projections/dpar.hpp @@ -22,11 +22,16 @@ #include <boost/mpl/assert.hpp> #include <boost/mpl/if.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/size.hpp> +#include <boost/range/value_type.hpp> #include <boost/tuple/tuple.hpp> -#include <boost/variant/variant.hpp> #include <boost/type_traits/integral_constant.hpp> +#include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_void.hpp> +#include <boost/variant/variant.hpp> #include <string> #include <vector> diff --git a/boost/geometry/srs/projections/impl/aasincos.hpp b/boost/geometry/srs/projections/impl/aasincos.hpp index de064f6a01..b12b5f65ba 100644 --- a/boost/geometry/srs/projections/impl/aasincos.hpp +++ b/boost/geometry/srs/projections/impl/aasincos.hpp @@ -42,6 +42,8 @@ #include <cmath> +#include <boost/geometry/srs/projections/exception.hpp> +#include <boost/geometry/srs/projections/impl/pj_strerrno.hpp> #include <boost/geometry/util/math.hpp> diff --git a/boost/geometry/srs/projections/impl/dms_parser.hpp b/boost/geometry/srs/projections/impl/dms_parser.hpp index fabc558f61..ee9c8db3d1 100644 --- a/boost/geometry/srs/projections/impl/dms_parser.hpp +++ b/boost/geometry/srs/projections/impl/dms_parser.hpp @@ -42,9 +42,9 @@ #include <string> #include <boost/algorithm/string.hpp> -#include <boost/config.hpp> #include <boost/static_assert.hpp> +#include <boost/geometry/core/config.hpp> #include <boost/geometry/core/cs.hpp> #include <boost/geometry/srs/projections/str_cast.hpp> #include <boost/geometry/util/math.hpp> @@ -123,7 +123,7 @@ struct dms_parser bool has_dms[3]; dms_value() -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && (!defined(_MSC_VER) || (_MSC_VER >= 1900)) // workaround for VC++ 12 (aka 2013) +#ifdef BOOST_GEOMETRY_CXX11_ARRAY_UNIFIED_INITIALIZATION : dms{0, 0, 0} , has_dms{false, false, false} {} diff --git a/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp b/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp index ee3aa6ed23..e56fecc8b2 100644 --- a/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp +++ b/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp @@ -1,8 +1,8 @@ // Boost.Geometry // This file is manually converted from PROJ4 -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2018, 2019. +// Modifications copyright (c) 2018-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -44,8 +44,12 @@ #include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/radian_access.hpp> +#include <boost/geometry/srs/projections/impl/adjlon.hpp> +#include <boost/geometry/srs/projections/impl/function_overloads.hpp> #include <boost/geometry/srs/projections/impl/pj_gridlist.hpp> +#include <boost/geometry/util/range.hpp> + namespace boost { namespace geometry { namespace projections { @@ -388,7 +392,7 @@ inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy, /************************************************************************/ template <bool Inverse, typename Par, typename Range, typename ProjGrids> -inline bool pj_apply_gridshift_2(Par const& defn, Range & range, ProjGrids const& grids) +inline bool pj_apply_gridshift_2(Par const& /*defn*/, Range & range, ProjGrids const& grids) { /*if( defn->catalog_name != NULL ) return pj_gc_apply_gridshift( defn, inverse, point_count, point_offset, diff --git a/boost/geometry/srs/projections/impl/pj_apply_gridshift_shared.hpp b/boost/geometry/srs/projections/impl/pj_apply_gridshift_shared.hpp index 2f0d63169e..c83c1bc515 100644 --- a/boost/geometry/srs/projections/impl/pj_apply_gridshift_shared.hpp +++ b/boost/geometry/srs/projections/impl/pj_apply_gridshift_shared.hpp @@ -1,8 +1,8 @@ // Boost.Geometry // This file is manually converted from PROJ4 -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2018, 2019. +// Modifications copyright (c) 2018-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -57,7 +57,7 @@ namespace detail template <bool Inverse, typename CalcT, typename StreamPolicy, typename Range> inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy, Range & range, - srs::shared_grids & grids, + shared_grids & grids, std::vector<std::size_t> const& gridindexes) { typedef typename boost::range_size<Range>::type size_type; diff --git a/boost/geometry/srs/projections/impl/pj_datum_set.hpp b/boost/geometry/srs/projections/impl/pj_datum_set.hpp index fee5eca906..1b651d0826 100644 --- a/boost/geometry/srs/projections/impl/pj_datum_set.hpp +++ b/boost/geometry/srs/projections/impl/pj_datum_set.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -135,7 +135,7 @@ template struct pj_datum_find_datum_static { template <typename T> - static const pj_datums_type<T>* apply(Params const& params) + static const pj_datums_type<T>* apply(Params const& ) { const pj_datums_type<T>* pj_datums = pj_get_datums<T>().first; const int n = pj_get_datums<T>().second; @@ -225,7 +225,7 @@ struct pj_datum_find_nadgrids_static { static void apply(Params const& params, srs::detail::nadgrids & out) { - out = boost::tuples::get<I>(); + out = boost::tuples::get<I>(params); } }; template <typename Params, int N> @@ -322,7 +322,7 @@ struct pj_datum_find_towgs84_static static void apply(Params const& params, srs::detail::towgs84<T> & out) { typename boost::tuples::element<I, Params>::type const& - towgs84 = boost::tuples::get<I>(); + towgs84 = boost::tuples::get<I>(params); std::size_t n = (std::min<std::size_t>)(towgs84.size(), 7u); std::size_t z = n <= 3 ? 3 : 7; diff --git a/boost/geometry/srs/projections/impl/pj_ellps.hpp b/boost/geometry/srs/projections/impl/pj_ellps.hpp index ae6c55457d..1a6f824eec 100644 --- a/boost/geometry/srs/projections/impl/pj_ellps.hpp +++ b/boost/geometry/srs/projections/impl/pj_ellps.hpp @@ -39,8 +39,6 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_IMPL_PJ_ELLPS_HPP #define BOOST_GEOMETRY_PROJECTIONS_IMPL_PJ_ELLPS_HPP -#include <boost/geometry/srs/projections/impl/projects.hpp> - #include <string> namespace boost { namespace geometry { namespace projections { diff --git a/boost/geometry/srs/projections/impl/pj_gauss.hpp b/boost/geometry/srs/projections/impl/pj_gauss.hpp index 94b8f89862..54d1778226 100644 --- a/boost/geometry/srs/projections/impl/pj_gauss.hpp +++ b/boost/geometry/srs/projections/impl/pj_gauss.hpp @@ -40,7 +40,8 @@ #define BOOST_GEOMETRY_PROJECTIONS_IMPL_PJ_GAUSS_HPP -#include <boost/geometry/util/math.hpp> +#include <boost/geometry/srs/projections/constants.hpp> +#include <boost/geometry/srs/projections/exception.hpp> namespace boost { namespace geometry { namespace projections { diff --git a/boost/geometry/srs/projections/impl/pj_gridinfo.hpp b/boost/geometry/srs/projections/impl/pj_gridinfo.hpp index 8f244dc3c6..0d297b1cb8 100644 --- a/boost/geometry/srs/projections/impl/pj_gridinfo.hpp +++ b/boost/geometry/srs/projections/impl/pj_gridinfo.hpp @@ -1,8 +1,8 @@ // Boost.Geometry // This file is manually converted from PROJ4 -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2018, 2019. +// Modifications copyright (c) 2018-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -44,6 +44,7 @@ #include <boost/algorithm/string.hpp> #include <boost/geometry/core/assert.hpp> +#include <boost/geometry/util/math.hpp> #include <boost/cstdint.hpp> @@ -204,7 +205,7 @@ bool pj_gridinfo_load_ctable(IStream & is, pj_gi_load & gi) std::size_t ch_size = sizeof(pj_ctable::flp_t) * a_size; is.read(reinterpret_cast<char*>(&ct.cvs[0]), ch_size); - if (is.fail() || is.gcount() != ch_size) + if (is.fail() || std::size_t(is.gcount()) != ch_size) { ct.cvs.clear(); //ctable loading failed on fread() - binary incompatible? @@ -235,7 +236,7 @@ bool pj_gridinfo_load_ctable2(IStream & is, pj_gi_load & gi) std::size_t ch_size = sizeof(pj_ctable::flp_t) * a_size; is.read(reinterpret_cast<char*>(&ct.cvs[0]), ch_size); - if (is.fail() || is.gcount() != ch_size) + if (is.fail() || std::size_t(is.gcount()) != ch_size) { //ctable2 loading failed on fread() - binary incompatible? ct.cvs.clear(); @@ -278,7 +279,7 @@ inline bool pj_gridinfo_load_ntv1(IStream & is, pj_gi_load & gi) { is.read(reinterpret_cast<char*>(&row_buf[0]), ch_size); - if (is.fail() || is.gcount() != ch_size) + if (is.fail() || std::size_t(is.gcount()) != ch_size) { gi.ct.cvs.clear(); return false; @@ -328,7 +329,7 @@ inline bool pj_gridinfo_load_ntv2(IStream & is, pj_gi_load & gi) { is.read(reinterpret_cast<char*>(&row_buf[0]), ch_size); - if (is.fail() || is.gcount() != ch_size) + if (is.fail() || std::size_t(is.gcount()) != ch_size) { gi.ct.cvs.clear(); return false; @@ -375,7 +376,7 @@ inline bool pj_gridinfo_load_gtx(IStream & is, pj_gi_load & gi) is.read(reinterpret_cast<char*>(&gi.ct.cvs[0]), ch_size); - if (is.fail() || is.gcount() != ch_size) + if (is.fail() || std::size_t(is.gcount()) != ch_size) { gi.ct.cvs.clear(); return false; diff --git a/boost/geometry/srs/projections/impl/pj_gridlist.hpp b/boost/geometry/srs/projections/impl/pj_gridlist.hpp index 18a215b507..deccdd39fb 100644 --- a/boost/geometry/srs/projections/impl/pj_gridlist.hpp +++ b/boost/geometry/srs/projections/impl/pj_gridlist.hpp @@ -41,8 +41,11 @@ #define BOOST_GEOMETRY_SRS_PROJECTIONS_IMPL_PJ_GRIDLIST_HPP +#include <boost/geometry/srs/projections/exception.hpp> #include <boost/geometry/srs/projections/grids.hpp> #include <boost/geometry/srs/projections/impl/pj_gridinfo.hpp> +#include <boost/geometry/srs/projections/impl/pj_strerrno.hpp> +#include <boost/geometry/srs/projections/par_data.hpp> namespace boost { namespace geometry { namespace projections diff --git a/boost/geometry/srs/projections/impl/pj_gridlist_shared.hpp b/boost/geometry/srs/projections/impl/pj_gridlist_shared.hpp index 88753d034d..de8640a01f 100644 --- a/boost/geometry/srs/projections/impl/pj_gridlist_shared.hpp +++ b/boost/geometry/srs/projections/impl/pj_gridlist_shared.hpp @@ -1,8 +1,8 @@ // Boost.Geometry // This file is manually converted from PROJ4 -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2018, 2019. +// Modifications copyright (c) 2018-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -43,6 +43,7 @@ #include <boost/geometry/srs/projections/shared_grids.hpp> #include <boost/geometry/srs/projections/impl/pj_gridinfo.hpp> +#include <boost/geometry/srs/projections/impl/pj_gridlist.hpp> namespace boost { namespace geometry { namespace projections @@ -63,7 +64,7 @@ namespace detail template <typename StreamPolicy> inline bool pj_gridlist_merge_gridfile(std::string const& gridname, StreamPolicy const& stream_policy, - srs::shared_grids & grids, + shared_grids & grids, std::vector<std::size_t> & gridindexes) { // Try to find in the existing list of loaded grids. Add all diff --git a/boost/geometry/srs/projections/impl/pj_mlfn.hpp b/boost/geometry/srs/projections/impl/pj_mlfn.hpp index 04f0d19442..92621875bb 100644 --- a/boost/geometry/srs/projections/impl/pj_mlfn.hpp +++ b/boost/geometry/srs/projections/impl/pj_mlfn.hpp @@ -48,6 +48,8 @@ #include <cstdlib> +#include <boost/geometry/srs/projections/exception.hpp> +#include <boost/geometry/srs/projections/impl/pj_strerrno.hpp> #include <boost/geometry/util/math.hpp> diff --git a/boost/geometry/srs/projections/impl/pj_phi2.hpp b/boost/geometry/srs/projections/impl/pj_phi2.hpp index 868a8c659b..dacd4e16d0 100644 --- a/boost/geometry/srs/projections/impl/pj_phi2.hpp +++ b/boost/geometry/srs/projections/impl/pj_phi2.hpp @@ -39,6 +39,8 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_PHI2_HPP #define BOOST_GEOMETRY_PROJECTIONS_PHI2_HPP +#include <boost/geometry/srs/projections/exception.hpp> +#include <boost/geometry/srs/projections/impl/pj_strerrno.hpp> #include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { namespace projections { diff --git a/boost/geometry/srs/projections/impl/pj_transform.hpp b/boost/geometry/srs/projections/impl/pj_transform.hpp index 1be984556b..02291649e0 100644 --- a/boost/geometry/srs/projections/impl/pj_transform.hpp +++ b/boost/geometry/srs/projections/impl/pj_transform.hpp @@ -41,6 +41,7 @@ #include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/core/radian_access.hpp> #include <boost/geometry/srs/projections/impl/geocent.hpp> diff --git a/boost/geometry/srs/projections/impl/proj_mdist.hpp b/boost/geometry/srs/projections/impl/proj_mdist.hpp index 5f67546f54..65fc41a4cc 100644 --- a/boost/geometry/srs/projections/impl/proj_mdist.hpp +++ b/boost/geometry/srs/projections/impl/proj_mdist.hpp @@ -40,6 +40,8 @@ #define BOOST_GEOMETRY_PROJECTIONS_PROJ_MDIST_HPP +#include <boost/geometry/srs/projections/exception.hpp> +#include <boost/geometry/srs/projections/impl/pj_strerrno.hpp> #include <boost/geometry/util/math.hpp> diff --git a/boost/geometry/srs/projections/par_data.hpp b/boost/geometry/srs/projections/par_data.hpp index 17644e2157..c867676128 100644 --- a/boost/geometry/srs/projections/par_data.hpp +++ b/boost/geometry/srs/projections/par_data.hpp @@ -10,10 +10,12 @@ #ifndef BOOST_GEOMETRY_SRS_PROJECTIONS_PAR_DATA_HPP #define BOOST_GEOMETRY_SRS_PROJECTIONS_PAR_DATA_HPP -#include <boost/config.hpp> #include <string> #include <vector> +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/config.hpp> + namespace boost { namespace geometry { namespace srs { @@ -86,14 +88,14 @@ struct towgs84 towgs84() : m_size(0) -#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +#ifdef BOOST_GEOMETRY_CXX11_ARRAY_UNIFIED_INITIALIZATION , m_data{0, 0, 0, 0, 0, 0, 0} -#endif + {} +#else { -#ifdef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX std::fill(m_data, m_data + 7, T(0)); -#endif } +#endif template <typename It> towgs84(It first, It last) diff --git a/boost/geometry/srs/projections/proj/aeqd.hpp b/boost/geometry/srs/projections/proj/aeqd.hpp index b45146eac4..73ce9aac47 100644 --- a/boost/geometry/srs/projections/proj/aeqd.hpp +++ b/boost/geometry/srs/projections/proj/aeqd.hpp @@ -45,17 +45,21 @@ #define BOOST_GEOMETRY_PROJECTIONS_AEQD_HPP #include <boost/config.hpp> + #include <boost/geometry/formulas/vincenty_direct.hpp> #include <boost/geometry/formulas/vincenty_inverse.hpp> -#include <boost/geometry/util/math.hpp> -#include <boost/math/special_functions/hypot.hpp> +#include <boost/geometry/srs/projections/impl/aasincos.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> -#include <boost/geometry/srs/projections/impl/aasincos.hpp> #include <boost/geometry/srs/projections/impl/pj_mlfn.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> + +#include <boost/math/special_functions/hypot.hpp> #include <boost/type_traits/is_same.hpp> diff --git a/boost/geometry/srs/projections/proj/airy.hpp b/boost/geometry/srs/projections/proj/airy.hpp index 235a120d0e..fc2ea57de1 100644 --- a/boost/geometry/srs/projections/proj/airy.hpp +++ b/boost/geometry/srs/projections/proj/airy.hpp @@ -45,12 +45,13 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_AIRY_HPP #define BOOST_GEOMETRY_PROJECTIONS_AIRY_HPP -#include <boost/geometry/util/math.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/aitoff.hpp b/boost/geometry/srs/projections/proj/aitoff.hpp index 6d64ea3588..a7ad3b086d 100644 --- a/boost/geometry/srs/projections/proj/aitoff.hpp +++ b/boost/geometry/srs/projections/proj/aitoff.hpp @@ -47,14 +47,15 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_AITOFF_HPP #define BOOST_GEOMETRY_PROJECTIONS_AITOFF_HPP - #include <boost/core/ignore_unused.hpp> -#include <boost/geometry/util/math.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/bipc.hpp b/boost/geometry/srs/projections/proj/bipc.hpp index 647a07ad3f..9d531f87a8 100644 --- a/boost/geometry/srs/projections/proj/bipc.hpp +++ b/boost/geometry/srs/projections/proj/bipc.hpp @@ -40,13 +40,15 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_BIPC_HPP #define BOOST_GEOMETRY_PROJECTIONS_BIPC_HPP -#include <boost/geometry/util/math.hpp> -#include <boost/math/special_functions/hypot.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> + +#include <boost/math/special_functions/hypot.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/bonne.hpp b/boost/geometry/srs/projections/proj/bonne.hpp index 4016d03229..70bdc87fd2 100644 --- a/boost/geometry/srs/projections/proj/bonne.hpp +++ b/boost/geometry/srs/projections/proj/bonne.hpp @@ -40,14 +40,16 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_BONNE_HPP #define BOOST_GEOMETRY_PROJECTIONS_BONNE_HPP -#include <boost/geometry/util/math.hpp> -#include <boost/math/special_functions/hypot.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> #include <boost/geometry/srs/projections/impl/pj_mlfn.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> + +#include <boost/math/special_functions/hypot.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/cea.hpp b/boost/geometry/srs/projections/proj/cea.hpp index a440ec3f8a..467330e568 100644 --- a/boost/geometry/srs/projections/proj/cea.hpp +++ b/boost/geometry/srs/projections/proj/cea.hpp @@ -40,14 +40,15 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_CEA_HPP #define BOOST_GEOMETRY_PROJECTIONS_CEA_HPP -#include <boost/geometry/util/math.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> #include <boost/geometry/srs/projections/impl/pj_auth.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> #include <boost/geometry/srs/projections/impl/pj_qsfn.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/chamb.hpp b/boost/geometry/srs/projections/proj/chamb.hpp index 1f397b33c4..0200a565cf 100644 --- a/boost/geometry/srs/projections/proj/chamb.hpp +++ b/boost/geometry/srs/projections/proj/chamb.hpp @@ -40,14 +40,16 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_CHAMB_HPP #define BOOST_GEOMETRY_PROJECTIONS_CHAMB_HPP -#include <boost/geometry/util/math.hpp> #include <cstdio> +#include <boost/geometry/srs/projections/impl/aasincos.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> -#include <boost/geometry/srs/projections/impl/aasincos.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/eqc.hpp b/boost/geometry/srs/projections/proj/eqc.hpp index 21b655d2db..5a19f39ec7 100644 --- a/boost/geometry/srs/projections/proj/eqc.hpp +++ b/boost/geometry/srs/projections/proj/eqc.hpp @@ -42,8 +42,9 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/eqdc.hpp b/boost/geometry/srs/projections/proj/eqdc.hpp index d5aa8f2e11..986e258e2b 100644 --- a/boost/geometry/srs/projections/proj/eqdc.hpp +++ b/boost/geometry/srs/projections/proj/eqdc.hpp @@ -40,15 +40,17 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_EQDC_HPP #define BOOST_GEOMETRY_PROJECTIONS_EQDC_HPP -#include <boost/geometry/util/math.hpp> -#include <boost/math/special_functions/hypot.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> #include <boost/geometry/srs/projections/impl/pj_mlfn.hpp> #include <boost/geometry/srs/projections/impl/pj_msfn.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> + +#include <boost/math/special_functions/hypot.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/etmerc.hpp b/boost/geometry/srs/projections/proj/etmerc.hpp index 0bedbf247d..86e2a506fb 100644 --- a/boost/geometry/srs/projections/proj/etmerc.hpp +++ b/boost/geometry/srs/projections/proj/etmerc.hpp @@ -54,13 +54,14 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_ETMERC_HPP #define BOOST_GEOMETRY_PROJECTIONS_ETMERC_HPP -#include <boost/math/special_functions/hypot.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> #include <boost/geometry/srs/projections/impl/function_overloads.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/math/special_functions/hypot.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/fouc_s.hpp b/boost/geometry/srs/projections/proj/fouc_s.hpp index 10a252ec27..f6a8c5ed4b 100644 --- a/boost/geometry/srs/projections/proj/fouc_s.hpp +++ b/boost/geometry/srs/projections/proj/fouc_s.hpp @@ -40,13 +40,14 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_FOUC_S_HPP #define BOOST_GEOMETRY_PROJECTIONS_FOUC_S_HPP -#include <boost/geometry/util/math.hpp> - +#include <boost/geometry/srs/projections/impl/aasincos.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> -#include <boost/geometry/srs/projections/impl/aasincos.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/gn_sinu.hpp b/boost/geometry/srs/projections/proj/gn_sinu.hpp index b4218cc839..2ef7df5099 100644 --- a/boost/geometry/srs/projections/proj/gn_sinu.hpp +++ b/boost/geometry/srs/projections/proj/gn_sinu.hpp @@ -40,14 +40,15 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_GN_SINU_HPP #define BOOST_GEOMETRY_PROJECTIONS_GN_SINU_HPP -#include <boost/geometry/util/math.hpp> - +#include <boost/geometry/srs/projections/impl/aasincos.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> -#include <boost/geometry/srs/projections/impl/aasincos.hpp> #include <boost/geometry/srs/projections/impl/pj_mlfn.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/hammer.hpp b/boost/geometry/srs/projections/proj/hammer.hpp index 6518fd8245..f9e1ae4e72 100644 --- a/boost/geometry/srs/projections/proj/hammer.hpp +++ b/boost/geometry/srs/projections/proj/hammer.hpp @@ -42,8 +42,9 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/healpix.hpp b/boost/geometry/srs/projections/proj/healpix.hpp index 414935c040..2084ae82f8 100644 --- a/boost/geometry/srs/projections/proj/healpix.hpp +++ b/boost/geometry/srs/projections/proj/healpix.hpp @@ -49,14 +49,15 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_HEALPIX_HPP #define BOOST_GEOMETRY_PROJECTIONS_HEALPIX_HPP -#include <boost/geometry/util/math.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> #include <boost/geometry/srs/projections/impl/pj_auth.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> #include <boost/geometry/srs/projections/impl/pj_qsfn.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/imw_p.hpp b/boost/geometry/srs/projections/proj/imw_p.hpp index f5f662406f..d86c3c8f74 100644 --- a/boost/geometry/srs/projections/proj/imw_p.hpp +++ b/boost/geometry/srs/projections/proj/imw_p.hpp @@ -40,13 +40,14 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_IMW_P_HPP #define BOOST_GEOMETRY_PROJECTIONS_IMW_P_HPP -#include <boost/geometry/util/math.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> #include <boost/geometry/srs/projections/impl/pj_mlfn.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/isea.hpp b/boost/geometry/srs/projections/proj/isea.hpp index d3f53a7754..d8a48041d2 100644 --- a/boost/geometry/srs/projections/proj/isea.hpp +++ b/boost/geometry/srs/projections/proj/isea.hpp @@ -48,12 +48,14 @@ #include <boost/core/ignore_unused.hpp> #include <boost/geometry/core/assert.hpp> -#include <boost/geometry/util/math.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/krovak.hpp b/boost/geometry/srs/projections/proj/krovak.hpp index 5e4d08a844..75771b49e1 100644 --- a/boost/geometry/srs/projections/proj/krovak.hpp +++ b/boost/geometry/srs/projections/proj/krovak.hpp @@ -47,8 +47,9 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/labrd.hpp b/boost/geometry/srs/projections/proj/labrd.hpp index a66d0c63a2..1b86fe74ec 100644 --- a/boost/geometry/srs/projections/proj/labrd.hpp +++ b/boost/geometry/srs/projections/proj/labrd.hpp @@ -42,8 +42,9 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/lagrng.hpp b/boost/geometry/srs/projections/proj/lagrng.hpp index 6f40bb2804..6df4459624 100644 --- a/boost/geometry/srs/projections/proj/lagrng.hpp +++ b/boost/geometry/srs/projections/proj/lagrng.hpp @@ -40,12 +40,13 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_LAGRNG_HPP #define BOOST_GEOMETRY_PROJECTIONS_LAGRNG_HPP -#include <boost/geometry/util/math.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/lcc.hpp b/boost/geometry/srs/projections/proj/lcc.hpp index 1b261cb70b..ebd9c3bb6e 100644 --- a/boost/geometry/srs/projections/proj/lcc.hpp +++ b/boost/geometry/srs/projections/proj/lcc.hpp @@ -40,17 +40,18 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_LCC_HPP #define BOOST_GEOMETRY_PROJECTIONS_LCC_HPP -#include <boost/geometry/util/math.hpp> -#include <boost/math/special_functions/hypot.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> #include <boost/geometry/srs/projections/impl/pj_msfn.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> #include <boost/geometry/srs/projections/impl/pj_phi2.hpp> #include <boost/geometry/srs/projections/impl/pj_tsfn.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> +#include <boost/math/special_functions/hypot.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/loxim.hpp b/boost/geometry/srs/projections/proj/loxim.hpp index 3736a11cf2..927cab1574 100644 --- a/boost/geometry/srs/projections/proj/loxim.hpp +++ b/boost/geometry/srs/projections/proj/loxim.hpp @@ -40,12 +40,13 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_LOXIM_HPP #define BOOST_GEOMETRY_PROJECTIONS_LOXIM_HPP -#include <boost/geometry/util/math.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/lsat.hpp b/boost/geometry/srs/projections/proj/lsat.hpp index 65dbe97f6d..3a20d96cb7 100644 --- a/boost/geometry/srs/projections/proj/lsat.hpp +++ b/boost/geometry/srs/projections/proj/lsat.hpp @@ -40,13 +40,14 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_LSAT_HPP #define BOOST_GEOMETRY_PROJECTIONS_LSAT_HPP -#include <boost/geometry/util/math.hpp> - +#include <boost/geometry/srs/projections/impl/aasincos.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> -#include <boost/geometry/srs/projections/impl/aasincos.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/merc.hpp b/boost/geometry/srs/projections/proj/merc.hpp index e2fba50720..5ec1e1f84c 100644 --- a/boost/geometry/srs/projections/proj/merc.hpp +++ b/boost/geometry/srs/projections/proj/merc.hpp @@ -40,15 +40,16 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_MERC_HPP #define BOOST_GEOMETRY_PROJECTIONS_MERC_HPP -#include <boost/geometry/util/math.hpp> - #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> #include <boost/geometry/srs/projections/impl/pj_msfn.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> #include <boost/geometry/srs/projections/impl/pj_phi2.hpp> #include <boost/geometry/srs/projections/impl/pj_tsfn.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/nsper.hpp b/boost/geometry/srs/projections/proj/nsper.hpp index 89dc6a8a15..6366e100dd 100644 --- a/boost/geometry/srs/projections/proj/nsper.hpp +++ b/boost/geometry/srs/projections/proj/nsper.hpp @@ -41,13 +41,16 @@ #define BOOST_GEOMETRY_PROJECTIONS_NSPER_HPP #include <boost/config.hpp> -#include <boost/geometry/util/math.hpp> -#include <boost/math/special_functions/hypot.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> + +#include <boost/geometry/util/math.hpp> + +#include <boost/math/special_functions/hypot.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/ob_tran.hpp b/boost/geometry/srs/projections/proj/ob_tran.hpp index f5709228f5..99a7b82b1a 100644 --- a/boost/geometry/srs/projections/proj/ob_tran.hpp +++ b/boost/geometry/srs/projections/proj/ob_tran.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -128,7 +128,7 @@ namespace projections } template <BOOST_GEOMETRY_PROJECTIONS_DETAIL_TYPENAME_PX, typename Parameters> - inline Parameters o_proj_parameters(srs::spar::parameters<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> const& params, + inline Parameters o_proj_parameters(srs::spar::parameters<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> const& /*params*/, Parameters const& par) { /* copy existing header into new */ @@ -292,7 +292,7 @@ namespace projections // General Oblique Transformation template <typename T, typename Params, typename Parameters, typename ProjParameters> - inline T setup_ob_tran(Params const& params, Parameters & par, ProjParameters& proj_parm) + inline T setup_ob_tran(Params const& params, Parameters & /*par*/, ProjParameters& proj_parm) { static const T half_pi = detail::half_pi<T>(); diff --git a/boost/geometry/srs/projections/proj/ocea.hpp b/boost/geometry/srs/projections/proj/ocea.hpp index af8be1ca08..c7f531745c 100644 --- a/boost/geometry/srs/projections/proj/ocea.hpp +++ b/boost/geometry/srs/projections/proj/ocea.hpp @@ -44,8 +44,9 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/oea.hpp b/boost/geometry/srs/projections/proj/oea.hpp index f78037d2cb..10399ec1a8 100644 --- a/boost/geometry/srs/projections/proj/oea.hpp +++ b/boost/geometry/srs/projections/proj/oea.hpp @@ -42,11 +42,12 @@ #include <boost/math/special_functions/hypot.hpp> +#include <boost/geometry/srs/projections/impl/aasincos.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> -#include <boost/geometry/srs/projections/impl/aasincos.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/omerc.hpp b/boost/geometry/srs/projections/proj/omerc.hpp index 1e041e2ac0..0bec0cacca 100644 --- a/boost/geometry/srs/projections/proj/omerc.hpp +++ b/boost/geometry/srs/projections/proj/omerc.hpp @@ -46,10 +46,11 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> #include <boost/geometry/srs/projections/impl/pj_phi2.hpp> #include <boost/geometry/srs/projections/impl/pj_tsfn.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/rpoly.hpp b/boost/geometry/srs/projections/proj/rpoly.hpp index 87a5d482ba..fc59a0397b 100644 --- a/boost/geometry/srs/projections/proj/rpoly.hpp +++ b/boost/geometry/srs/projections/proj/rpoly.hpp @@ -42,8 +42,9 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/sconics.hpp b/boost/geometry/srs/projections/proj/sconics.hpp index 5499f1a7c0..44d606cab4 100644 --- a/boost/geometry/srs/projections/proj/sconics.hpp +++ b/boost/geometry/srs/projections/proj/sconics.hpp @@ -46,8 +46,9 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/stere.hpp b/boost/geometry/srs/projections/proj/stere.hpp index 7b287383f1..7c2de3fcc7 100644 --- a/boost/geometry/srs/projections/proj/stere.hpp +++ b/boost/geometry/srs/projections/proj/stere.hpp @@ -46,9 +46,10 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> #include <boost/geometry/srs/projections/impl/pj_tsfn.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/tpeqd.hpp b/boost/geometry/srs/projections/proj/tpeqd.hpp index 9b9687fae3..06f9cc0a03 100644 --- a/boost/geometry/srs/projections/proj/tpeqd.hpp +++ b/boost/geometry/srs/projections/proj/tpeqd.hpp @@ -43,11 +43,12 @@ #include <boost/geometry/util/math.hpp> #include <boost/math/special_functions/hypot.hpp> +#include <boost/geometry/srs/projections/impl/aasincos.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> -#include <boost/geometry/srs/projections/impl/aasincos.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/urm5.hpp b/boost/geometry/srs/projections/proj/urm5.hpp index 4cec4cdd1e..b1682332aa 100644 --- a/boost/geometry/srs/projections/proj/urm5.hpp +++ b/boost/geometry/srs/projections/proj/urm5.hpp @@ -40,11 +40,12 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_URM5_HPP #define BOOST_GEOMETRY_PROJECTIONS_URM5_HPP +#include <boost/geometry/srs/projections/impl/aasincos.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> -#include <boost/geometry/srs/projections/impl/aasincos.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/urmfps.hpp b/boost/geometry/srs/projections/proj/urmfps.hpp index aa7982758a..8f608619a5 100644 --- a/boost/geometry/srs/projections/proj/urmfps.hpp +++ b/boost/geometry/srs/projections/proj/urmfps.hpp @@ -40,11 +40,12 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_URMFPS_HPP #define BOOST_GEOMETRY_PROJECTIONS_URMFPS_HPP +#include <boost/geometry/srs/projections/impl/aasincos.hpp> #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> -#include <boost/geometry/srs/projections/impl/aasincos.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/wag3.hpp b/boost/geometry/srs/projections/proj/wag3.hpp index 825ead3533..c69eca7b75 100644 --- a/boost/geometry/srs/projections/proj/wag3.hpp +++ b/boost/geometry/srs/projections/proj/wag3.hpp @@ -42,8 +42,9 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/wink1.hpp b/boost/geometry/srs/projections/proj/wink1.hpp index b920daa97f..d05f9458f8 100644 --- a/boost/geometry/srs/projections/proj/wink1.hpp +++ b/boost/geometry/srs/projections/proj/wink1.hpp @@ -42,8 +42,9 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/proj/wink2.hpp b/boost/geometry/srs/projections/proj/wink2.hpp index 06f0770365..71bc147abc 100644 --- a/boost/geometry/srs/projections/proj/wink2.hpp +++ b/boost/geometry/srs/projections/proj/wink2.hpp @@ -44,8 +44,9 @@ #include <boost/geometry/srs/projections/impl/base_static.hpp> #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> -#include <boost/geometry/srs/projections/impl/projects.hpp> #include <boost/geometry/srs/projections/impl/factory_entry.hpp> +#include <boost/geometry/srs/projections/impl/pj_param.hpp> +#include <boost/geometry/srs/projections/impl/projects.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/srs/projections/shared_grids.hpp b/boost/geometry/srs/projections/shared_grids.hpp index 54191808cb..d4a27e4b10 100644 --- a/boost/geometry/srs/projections/shared_grids.hpp +++ b/boost/geometry/srs/projections/shared_grids.hpp @@ -23,35 +23,24 @@ namespace boost { namespace geometry { -// Forward declarations -namespace srs +namespace projections { namespace detail { // Forward declaration for functions declarations below class shared_grids; -} // namespace srs -namespace projections { namespace detail -{ - // Forward declaratios of shared_grids friends template <typename StreamPolicy> inline bool pj_gridlist_merge_gridfile(std::string const& gridname, StreamPolicy const& stream_policy, - srs::shared_grids & grids, + shared_grids & grids, std::vector<std::size_t> & gridindexes); template <bool Inverse, typename CalcT, typename StreamPolicy, typename Range> inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy, Range & range, - srs::shared_grids & grids, + shared_grids & grids, std::vector<std::size_t> const& gridindexes); -}} // namespace projections::detail - - -namespace srs -{ - class shared_grids { @@ -73,21 +62,21 @@ private: friend inline bool projections::detail::pj_gridlist_merge_gridfile( std::string const& gridname, StreamPolicy const& stream_policy, - srs::shared_grids & grids, + shared_grids & grids, std::vector<std::size_t> & gridindexes); template <bool Inverse, typename CalcT, typename StreamPolicy, typename Range> friend inline bool projections::detail::pj_apply_gridshift_3( StreamPolicy const& stream_policy, Range & range, - srs::shared_grids & grids, + shared_grids & grids, std::vector<std::size_t> const& gridindexes); projections::detail::pj_gridinfo gridinfo; mutable boost::shared_mutex mutex; }; +}} // namespace projections::detail -} // namespace srs }} // namespace boost::geometry diff --git a/boost/geometry/srs/shared_grids.hpp b/boost/geometry/srs/shared_grids.hpp index 9eb61717ba..bc9528bd27 100644 --- a/boost/geometry/srs/shared_grids.hpp +++ b/boost/geometry/srs/shared_grids.hpp @@ -16,5 +16,11 @@ #include <boost/geometry/srs/projections/impl/pj_gridlist_shared.hpp> #include <boost/geometry/srs/projections/shared_grids.hpp> +namespace boost { namespace geometry { namespace srs +{ + +using geometry::projections::detail::shared_grids; + +}}} // namespace boost::geometry::srs #endif // BOOST_GEOMETRY_SRS_SHARED_GRIDS_HPP diff --git a/boost/geometry/srs/transformation.hpp b/boost/geometry/srs/transformation.hpp index 38e6ce04c6..b8ab4e0775 100644 --- a/boost/geometry/srs/transformation.hpp +++ b/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<PtIn>::type - >::type::value - == - geometry::is_radian - < - typename geometry::coordinate_system<PtOut>::type - >::type::value + typename geometry::detail::cs_angular_units<PtIn>::type, + typename geometry::detail::cs_angular_units<PtOut>::type + >::value > struct transform_geometry_point_coordinates { diff --git a/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp b/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp index 0cd0cdc4db..f86dcbdd91 100644 --- a/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp +++ b/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2014. -// Modifications copyright (c) 2014 Oracle and/or its affiliates. +// 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 @@ -22,18 +22,17 @@ #include <algorithm> #include <vector> -#include <boost/range.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/geometry/algorithms/detail/for_each_range.hpp> #include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/point_type.hpp> +#include <boost/geometry/policies/compare.hpp> #include <boost/geometry/strategies/convex_hull.hpp> - +#include <boost/geometry/strategies/side.hpp> #include <boost/geometry/views/detail/range_type.hpp> - -#include <boost/geometry/policies/compare.hpp> - -#include <boost/geometry/algorithms/detail/for_each_range.hpp> #include <boost/geometry/views/reversible_view.hpp> @@ -193,9 +192,6 @@ static inline void sort(Range& range) /*! \brief Graham scan strategy to calculate convex hull \ingroup strategies -\note Completely reworked version inspired on the sources listed below -\see http://www.ddj.com/architect/201806315 -\see http://marknelson.us/2007/08/22/convex */ template <typename InputGeometry, typename OutputPoint> class graham_andrew diff --git a/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp b/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp index 8493b57c35..f87656dbce 100644 --- a/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp +++ b/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. @@ -20,6 +24,7 @@ #include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/algorithms/assign.hpp> #include <boost/geometry/strategies/covered_by.hpp> +#include <boost/geometry/strategies/side.hpp> #include <boost/geometry/strategies/within.hpp> @@ -60,16 +65,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 <typename Point, typename Box, typename Decide = decide_within> +template <typename Decide = decide_within> struct point_in_box_by_side { - typedef typename strategy::side::services::default_strategy - < - typename cs_tag<Box>::type - >::type side_strategy_type; - + template <typename Point, typename Box> static inline bool apply(Point const& point, Box const& box) { + typedef typename strategy::side::services::default_strategy + < + typename cs_tag<Box>::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/boost/geometry/strategies/agnostic/point_in_point.hpp b/boost/geometry/strategies/agnostic/point_in_point.hpp index d4692766c5..051b87f401 100644 --- a/boost/geometry/strategies/agnostic/point_in_point.hpp +++ b/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 <boost/geometry/algorithms/detail/equals/point_point.hpp> -#include <boost/geometry/strategies/covered_by.hpp> -#include <boost/geometry/strategies/within.hpp> +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/strategies/cartesian/point_in_point.hpp> +#include <boost/geometry/strategies/spherical/point_in_point.hpp> 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<Point1>::type > struct point_in_point -{ - static inline bool apply(Point1 const& point1, Point2 const& point2) - { - return geometry::detail::equals::equals_point_point(point1, point2); - } -}; - - -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + : strategy::within::cartesian_point_point +{}; -namespace services -{ - -template <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2, typename AnyCS1, typename AnyCS2> -struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, AnyCS1, AnyCS2> -{ - typedef strategy::within::point_in_point - < - typename point_type<PointLike1>::type, - typename point_type<PointLike2>::type - > type; -}; +template <typename Point1, typename Point2> +struct point_in_point<Point1, Point2, spherical_equatorial_tag> + : strategy::within::spherical_point_point +{}; +template <typename Point1, typename Point2> +struct point_in_point<Point1, Point2, spherical_polar_tag> + : strategy::within::spherical_point_point +{}; -} // namespace services - -#endif +template <typename Point1, typename Point2> +struct point_in_point<Point1, Point2, geographic_tag> + : strategy::within::spherical_point_point +{}; }} // namespace strategy::within -#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS -namespace strategy { namespace covered_by { namespace services -{ - -template <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2, typename AnyCS1, typename AnyCS2> -struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, AnyCS1, AnyCS2> -{ - typedef strategy::within::point_in_point - < - typename point_type<PointLike1>::type, - typename point_type<PointLike2>::type - > type; -}; - -}}} // namespace strategy::covered_by::services -#endif - - }} // namespace boost::geometry diff --git a/boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp b/boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp index 423948fff3..35aae192a3 100644 --- a/boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp +++ b/boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp @@ -36,8 +36,6 @@ namespace strategy { namespace within \tparam PointOfSegment \tparam_segment_point \tparam CalculationType \tparam_calculation \author Barend Gehrels -\note The implementation is inspired by terralib http://www.terralib.org (LGPL) -\note but totally revised afterwards, especially for cases on segments \note Only dependant on "side", -> agnostic, suitable for spherical/latlong \qbk{ diff --git a/boost/geometry/strategies/cartesian/area.hpp b/boost/geometry/strategies/cartesian/area.hpp index 27708424c2..070e8f56b0 100644 --- a/boost/geometry/strategies/cartesian/area.hpp +++ b/boost/geometry/strategies/cartesian/area.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 2016, 2017. -// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2016, 2017, 2018. +// Modifications copyright (c) 2016-2018, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -24,6 +24,7 @@ #include <boost/mpl/if.hpp> //#include <boost/geometry/arithmetic/determinant.hpp> +#include <boost/geometry/core/access.hpp> #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/strategies/area.hpp> diff --git a/boost/geometry/strategies/cartesian/azimuth.hpp b/boost/geometry/strategies/cartesian/azimuth.hpp index 62f804e8f5..2ff16e9458 100644 --- a/boost/geometry/strategies/cartesian/azimuth.hpp +++ b/boost/geometry/strategies/cartesian/azimuth.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 @@ -13,6 +13,8 @@ #include <boost/geometry/core/tags.hpp> +#include <boost/geometry/strategies/azimuth.hpp> + namespace boost { namespace geometry { diff --git a/boost/geometry/strategies/cartesian/buffer_end_flat.hpp b/boost/geometry/strategies/cartesian/buffer_end_flat.hpp index c01cf4df85..dfbc19e98d 100644 --- a/boost/geometry/strategies/cartesian/buffer_end_flat.hpp +++ b/boost/geometry/strategies/cartesian/buffer_end_flat.hpp @@ -2,6 +2,11 @@ // Copyright (c) 2012-2014 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) @@ -9,16 +14,13 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP -#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/strategies/buffer.hpp> #include <boost/geometry/strategies/tags.hpp> #include <boost/geometry/strategies/side.hpp> #include <boost/geometry/util/math.hpp> #include <boost/geometry/util/select_most_precise.hpp> -#include <boost/geometry/strategies/buffer.hpp> - - - namespace boost { namespace geometry { diff --git a/boost/geometry/strategies/cartesian/buffer_point_circle.hpp b/boost/geometry/strategies/cartesian/buffer_point_circle.hpp index f289857177..c341e3ca3b 100644 --- a/boost/geometry/strategies/cartesian/buffer_point_circle.hpp +++ b/boost/geometry/strategies/cartesian/buffer_point_circle.hpp @@ -2,10 +2,11 @@ // Copyright (c) 2012-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 @@ -16,12 +17,15 @@ #include <cstddef> -#include <boost/range.hpp> +#include <boost/range/value_type.hpp> -#include <boost/geometry/util/math.hpp> +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/strategies/buffer.hpp> +#include <boost/geometry/util/math.hpp> +#include <boost/geometry/util/select_most_precise.hpp> namespace boost { namespace geometry { @@ -46,6 +50,7 @@ namespace strategy { namespace buffer [heading See also] \* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)] \* [link geometry.reference.strategies.strategy_buffer_point_square point_square] +\* [link geometry.reference.strategies.strategy_buffer_geographic_point_circle geographic_point_circle] } */ class point_circle diff --git a/boost/geometry/strategies/cartesian/buffer_point_square.hpp b/boost/geometry/strategies/cartesian/buffer_point_square.hpp index 37a90c013f..12b4bd8eb4 100644 --- a/boost/geometry/strategies/cartesian/buffer_point_square.hpp +++ b/boost/geometry/strategies/cartesian/buffer_point_square.hpp @@ -1,5 +1,12 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) + // Copyright (c) 2012-2014 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) @@ -9,12 +16,11 @@ #include <cstddef> -#include <boost/range.hpp> - -#include <boost/geometry/util/math.hpp> +#include <boost/range/value_type.hpp> +#include <boost/geometry/core/access.hpp> #include <boost/geometry/strategies/buffer.hpp> - +#include <boost/geometry/util/math.hpp> namespace boost { namespace geometry { @@ -39,6 +45,7 @@ namespace strategy { namespace buffer [heading See also] \* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)] \* [link geometry.reference.strategies.strategy_buffer_point_circle point_circle] +\* [link geometry.reference.strategies.strategy_buffer_geographic_point_circle geographic_point_circle] } */ class point_square diff --git a/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp b/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp index d081173a3e..edb2c8a712 100644 --- a/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp +++ b/boost/geometry/strategies/cartesian/centroid_bashein_detmer.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. -// 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 Adam Wulkiewicz, on behalf of Oracle @@ -31,6 +31,7 @@ #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/point_type.hpp> #include <boost/geometry/strategies/centroid.hpp> +#include <boost/geometry/util/math.hpp> #include <boost/geometry/util/select_coordinate_type.hpp> diff --git a/boost/geometry/strategies/cartesian/densify.hpp b/boost/geometry/strategies/cartesian/densify.hpp index 23651637b9..9e6dd39b56 100644 --- a/boost/geometry/strategies/cartesian/densify.hpp +++ b/boost/geometry/strategies/cartesian/densify.hpp @@ -18,6 +18,7 @@ #include <boost/geometry/core/assert.hpp> #include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/geometries/point.hpp> #include <boost/geometry/strategies/densify.hpp> #include <boost/geometry/util/math.hpp> #include <boost/geometry/util/select_most_precise.hpp> diff --git a/boost/geometry/strategies/cartesian/disjoint_box_box.hpp b/boost/geometry/strategies/cartesian/disjoint_box_box.hpp new file mode 100644 index 0000000000..706c93ec79 --- /dev/null +++ b/boost/geometry/strategies/cartesian/disjoint_box_box.hpp @@ -0,0 +1,112 @@ +// 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 <cstddef> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/strategies/disjoint.hpp> + + +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<Box1>::value +> +struct box_box +{ + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2)) + { + return true; + } + if (get<min_corner, Dimension>(box1) > get<max_corner, Dimension>(box2)) + { + return true; + } + return box_box + < + Box1, Box2, + Dimension + 1, DimensionCount + >::apply(box1, box2); + } +}; + + +template <typename Box1, typename Box2, std::size_t DimensionCount> +struct box_box<Box1, Box2, DimensionCount, DimensionCount> +{ + static inline bool apply(Box1 const& , Box2 const& ) + { + return false; + } +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +struct cartesian_box_box +{ + template <typename Box1, typename Box2> + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + return detail::box_box<Box1, Box2>::apply(box1, box2); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +namespace services +{ + +template <typename Box1, typename Box2, int TopDim1, int TopDim2> +struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, cartesian_tag, cartesian_tag> +{ + 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/boost/geometry/strategies/cartesian/distance_projected_point.hpp b/boost/geometry/strategies/cartesian/distance_projected_point.hpp index 84f1c948c1..bd4f7130ca 100644 --- a/boost/geometry/strategies/cartesian/distance_projected_point.hpp +++ b/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 <boost/geometry/strategies/distance.hpp> #include <boost/geometry/strategies/default_distance_result.hpp> #include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp> +#include <boost/geometry/strategies/cartesian/point_in_point.hpp> #include <boost/geometry/util/select_coordinate_type.hpp> @@ -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/boost/geometry/strategies/cartesian/distance_pythagoras.hpp b/boost/geometry/strategies/cartesian/distance_pythagoras.hpp index 8a8889dc99..8d8b954362 100644 --- a/boost/geometry/strategies/cartesian/distance_pythagoras.hpp +++ b/boost/geometry/strategies/cartesian/distance_pythagoras.hpp @@ -4,6 +4,11 @@ // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. // 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. @@ -17,6 +22,8 @@ #include <boost/geometry/core/access.hpp> +#include <boost/geometry/geometries/concepts/point_concept.hpp> + #include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/util/math.hpp> diff --git a/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp b/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp index 4c1b6539be..85ee4b78f3 100644 --- a/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp +++ b/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.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. @@ -21,6 +22,9 @@ #include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/point_type.hpp> + +#include <boost/geometry/geometries/concepts/point_concept.hpp> #include <boost/geometry/strategies/distance.hpp> @@ -29,7 +33,6 @@ - namespace boost { namespace geometry { diff --git a/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp b/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp index 8423d16a63..d5f62c9ef8 100644 --- a/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp +++ b/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.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. @@ -21,6 +22,9 @@ #include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/point_type.hpp> + +#include <boost/geometry/geometries/concepts/point_concept.hpp> #include <boost/geometry/strategies/distance.hpp> diff --git a/boost/geometry/strategies/cartesian/distance_segment_box.hpp b/boost/geometry/strategies/cartesian/distance_segment_box.hpp index 80f5094a59..b623822eca 100644 --- a/boost/geometry/strategies/cartesian/distance_segment_box.hpp +++ b/boost/geometry/strategies/cartesian/distance_segment_box.hpp @@ -1,7 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2018 Oracle and/or its affiliates. +// Copyright (c) 2018-2019 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,9 @@ #include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp> +#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp> +#include <boost/geometry/strategies/cartesian/point_in_point.hpp> + namespace boost { namespace geometry { @@ -60,6 +64,13 @@ struct cartesian_segment_box return typename distance_ps_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(); + } + template <typename LessEqual, typename ReturnType, typename SegmentPoint, typename BoxPoint> inline ReturnType segment_below_of_box(SegmentPoint const& p0, diff --git a/boost/geometry/strategies/cartesian/envelope.hpp b/boost/geometry/strategies/cartesian/envelope.hpp new file mode 100644 index 0000000000..2a11dc5a52 --- /dev/null +++ b/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 <boost/range/begin.hpp> +#include <boost/range/end.hpp> + +#include <boost/geometry/algorithms/detail/envelope/initialize.hpp> + +#include <boost/geometry/strategies/cartesian/envelope_box.hpp> +#include <boost/geometry/strategies/cartesian/envelope_segment.hpp> +#include <boost/geometry/strategies/cartesian/expand_box.hpp> +#include <boost/geometry/strategies/cartesian/expand_segment.hpp> + +namespace boost { namespace geometry +{ + +namespace strategy { namespace envelope +{ + +template <typename CalculationType = void> +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 <typename Range> + static inline typename boost::range_iterator<Range const>::type begin(Range const& range) + { + return boost::begin(range); + } + + template <typename Range> + static inline typename boost::range_iterator<Range const>::type end(Range const& range) + { + return boost::end(range); + } + + // MultiLinestring, MultiPolygon + + template <typename Box> + 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<Box, 0, dimension<Box>::value>::apply(box); + } + } + + private: + bool m_initialized; + Box m_box; + }; + + // Segment + + template <typename Point1, typename Point2, typename Box> + static inline void apply(Point1 const& point1, Point2 const& point2, + Box& box) + { + cartesian_segment<CalculationType>::apply(point1, point2, box); + } + + // Box + + template <typename BoxIn, typename Box> + static inline void apply(BoxIn const& box_in, Box& box) + { + cartesian_box::apply(box_in, box); + } +}; + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename Tag, typename CalculationType> +struct default_strategy<Tag, cartesian_tag, CalculationType> +{ + typedef strategy::envelope::cartesian<CalculationType> type; +}; + +} // namespace services + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + +}} //namepsace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_HPP diff --git a/boost/geometry/strategies/cartesian/envelope_box.hpp b/boost/geometry/strategies/cartesian/envelope_box.hpp new file mode 100644 index 0000000000..c6dd218354 --- /dev/null +++ b/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 <cstddef> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/views/detail/indexed_point_view.hpp> + +#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> +#include <boost/geometry/algorithms/detail/normalize.hpp> +#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> + +#include <boost/geometry/algorithms/dispatch/envelope.hpp> + +#include <boost/geometry/strategies/envelope.hpp> + + +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 <typename BoxIn, typename BoxOut> + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in); + detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr); + + detail::conversion::point_to_point + < + detail::indexed_point_view<BoxIn const, Index>, + detail::indexed_point_view<BoxOut, Index>, + Dimension, + DimensionCount + >::apply(box_in_corner, mbr_corner); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +namespace strategy { namespace envelope +{ + + +struct cartesian_box +{ + template<typename BoxIn, typename BoxOut> + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + geometry::detail::envelope::envelope_indexed_box + < + min_corner, 0, dimension<BoxIn>::value + >::apply(box_in, mbr); + + geometry::detail::envelope::envelope_indexed_box + < + max_corner, 0, dimension<BoxIn>::value + >::apply(box_in, mbr); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename CalculationType> +struct default_strategy<box_tag, cartesian_tag, CalculationType> +{ + 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/boost/geometry/strategies/cartesian/envelope_multipoint.hpp b/boost/geometry/strategies/cartesian/envelope_multipoint.hpp new file mode 100644 index 0000000000..28c2374ce8 --- /dev/null +++ b/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 <boost/geometry/core/tags.hpp> + +#include <boost/geometry/algorithms/detail/envelope/range.hpp> + +#include <boost/geometry/strategies/cartesian/envelope.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace envelope +{ + +class cartesian_multipoint +{ +public: + template <typename MultiPoint, typename Box> + 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 <typename CalculationType> +struct default_strategy<multi_point_tag, cartesian_tag, CalculationType> +{ + 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/boost/geometry/strategies/cartesian/envelope_point.hpp b/boost/geometry/strategies/cartesian/envelope_point.hpp new file mode 100644 index 0000000000..3f900c7184 --- /dev/null +++ b/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 <cstddef> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/views/detail/indexed_point_view.hpp> + +#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> + +#include <boost/geometry/strategies/envelope.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + +template <std::size_t Dimension, std::size_t DimensionCount> +struct envelope_one_point +{ + template <std::size_t Index, typename Point, typename Box> + static inline void apply(Point const& point, Box& mbr) + { + detail::indexed_point_view<Box, Index> box_corner(mbr); + detail::conversion::point_to_point + < + Point, + detail::indexed_point_view<Box, Index>, + Dimension, + DimensionCount + >::apply(point, box_corner); + } + + template <typename Point, typename Box> + static inline void apply(Point const& point, Box& mbr) + { + apply<min_corner>(point, mbr); + apply<max_corner>(point, mbr); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +namespace strategy { namespace envelope +{ + +struct cartesian_point +{ + template <typename Point, typename Box> + static inline void apply(Point const& point, Box& mbr) + { + geometry::detail::envelope::envelope_one_point + < + 0, dimension<Point>::value + >::apply(point, mbr); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename CalculationType> +struct default_strategy<point_tag, cartesian_tag, CalculationType> +{ + 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/boost/geometry/strategies/cartesian/envelope_segment.hpp b/boost/geometry/strategies/cartesian/envelope_segment.hpp index a591996b84..cd52775da5 100644 --- a/boost/geometry/strategies/cartesian/envelope_segment.hpp +++ b/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,18 +11,45 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP +#include <cstddef> -#include <boost/geometry/algorithms/detail/envelope/segment.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> #include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/strategies/cartesian/envelope_point.hpp> +#include <boost/geometry/strategies/cartesian/expand_point.hpp> #include <boost/geometry/strategies/envelope.hpp> -#include <boost/geometry/util/select_calculation_type.hpp> +namespace boost { namespace geometry { namespace strategy { namespace envelope +{ -namespace boost { namespace geometry +#ifndef DOXYGEN_NO_DETAIL +namespace detail { -namespace strategy { namespace envelope +template <std::size_t Dimension, std::size_t DimensionCount> +struct envelope_one_segment { + template<typename Point, typename Box> + 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 < @@ -30,21 +57,15 @@ template > class cartesian_segment { -public : - - template <typename Point1, typename Point2, typename Box> - inline void - apply(Point1 const& point1, Point2 const& point2, Box& box) const +public: + template <typename Point, typename Box> + static inline void apply(Point const& point1, Point const& point2, Box& box) { - geometry::detail::envelope::envelope_one_segment - < - 0, - dimension<Point1>::value - > - ::apply(point1, - point2, - box, - strategy::envelope::cartesian_segment<CalculationType>()); + strategy::envelope::detail::envelope_one_segment + < + 0, + dimension<Point>::value + >::apply(point1, point2, box); } }; @@ -55,7 +76,7 @@ namespace services { template <typename CalculationType> -struct default_strategy<cartesian_tag, CalculationType> +struct default_strategy<segment_tag, cartesian_tag, CalculationType> { typedef strategy::envelope::cartesian_segment<CalculationType> type; }; diff --git a/boost/geometry/strategies/cartesian/expand_box.hpp b/boost/geometry/strategies/cartesian/expand_box.hpp new file mode 100644 index 0000000000..68b8824f81 --- /dev/null +++ b/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 <boost/geometry/core/tags.hpp> + +#include <boost/geometry/algorithms/detail/expand/indexed.hpp> + +#include <boost/geometry/strategies/expand.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +struct cartesian_box +{ + template <typename BoxOut, typename BoxIn> + static void apply(BoxOut & box_out, BoxIn const& box_in) + { + geometry::detail::expand::expand_indexed + < + 0, dimension<BoxIn>::value + >::apply(box_out, box_in); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename CalculationType> +struct default_strategy<box_tag, cartesian_tag, CalculationType> +{ + 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/boost/geometry/strategies/cartesian/expand_point.hpp b/boost/geometry/strategies/cartesian/expand_point.hpp new file mode 100644 index 0000000000..87d82dca08 --- /dev/null +++ b/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 <cstddef> +#include <functional> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/util/select_coordinate_type.hpp> + +#include <boost/geometry/strategies/expand.hpp> + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template <std::size_t Dimension, std::size_t DimensionCount> +struct point_loop +{ + template <typename Box, typename Point> + static inline void apply(Box& box, Point const& source) + { + typedef typename select_coordinate_type + < + Point, Box + >::type coordinate_type; + + std::less<coordinate_type> less; + std::greater<coordinate_type> greater; + + coordinate_type const coord = get<Dimension>(source); + + if (less(coord, get<min_corner, Dimension>(box))) + { + set<min_corner, Dimension>(box, coord); + } + + if (greater(coord, get<max_corner, Dimension>(box))) + { + set<max_corner, Dimension>(box, coord); + } + + point_loop<Dimension + 1, DimensionCount>::apply(box, source); + } +}; + + +template <std::size_t DimensionCount> +struct point_loop<DimensionCount, DimensionCount> +{ + template <typename Box, typename Point> + static inline void apply(Box&, Point const&) {} +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +struct cartesian_point +{ + template <typename Box, typename Point> + static void apply(Box & box, Point const& point) + { + expand::detail::point_loop + < + 0, dimension<Point>::value + >::apply(box, point); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename CalculationType> +struct default_strategy<point_tag, cartesian_tag, CalculationType> +{ + 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/boost/geometry/strategies/cartesian/expand_segment.hpp b/boost/geometry/strategies/cartesian/expand_segment.hpp new file mode 100644 index 0000000000..18fd9c9a78 --- /dev/null +++ b/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 <boost/geometry/core/tags.hpp> + +#include <boost/geometry/algorithms/detail/expand/indexed.hpp> + +#include <boost/geometry/strategies/expand.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +class cartesian_segment +{ +public: + template <typename Box, typename Segment> + static void apply(Box & box, Segment const& segment) + { + geometry::detail::expand::expand_indexed + < + 0, dimension<Segment>::value + >::apply(box, segment); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename CalculationType> +struct default_strategy<segment_tag, cartesian_tag, CalculationType> +{ + 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/boost/geometry/strategies/cartesian/intersection.hpp b/boost/geometry/strategies/cartesian/intersection.hpp index 10fd73ba54..01d1c9433a 100644 --- a/boost/geometry/strategies/cartesian/intersection.hpp +++ b/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, 2019. +// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -34,8 +34,13 @@ #include <boost/geometry/util/select_calculation_type.hpp> #include <boost/geometry/strategies/cartesian/area.hpp> +#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp> +#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp> #include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp> -#include <boost/geometry/strategies/cartesian/envelope_segment.hpp> +#include <boost/geometry/strategies/cartesian/envelope.hpp> +#include <boost/geometry/strategies/cartesian/expand_box.hpp> +#include <boost/geometry/strategies/cartesian/expand_segment.hpp> +#include <boost/geometry/strategies/cartesian/point_in_point.hpp> #include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp> #include <boost/geometry/strategies/cartesian/side_by_triangle.hpp> #include <boost/geometry/strategies/covered_by.hpp> @@ -132,14 +137,51 @@ struct cartesian_segments return strategy_type(); } - typedef envelope::cartesian_segment<CalculationType> - envelope_strategy_type; + typedef envelope::cartesian<CalculationType> 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 disjoint::segment_box disjoint_segment_box_strategy_type; + + static inline disjoint_segment_box_strategy_type get_disjoint_segment_box_strategy() + { + return disjoint_segment_box_strategy_type(); + } + + typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type; + typedef expand::cartesian_box expand_box_strategy_type; + template <typename CoordinateType, typename SegmentRatio> struct segment_intersection_info { @@ -314,12 +356,12 @@ struct cartesian_segments BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) ); 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/boost/geometry/strategies/cartesian/line_interpolate.hpp b/boost/geometry/strategies/cartesian/line_interpolate.hpp new file mode 100644 index 0000000000..ffad476ee4 --- /dev/null +++ b/boost/geometry/strategies/cartesian/line_interpolate.hpp @@ -0,0 +1,129 @@ +// Boost.Geometry + +// Copyright (c) 2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_LINE_INTERPOLATE_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_LINE_INTERPOLATE_HPP + +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/strategies/line_interpolate.hpp> +#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp> +#include <boost/geometry/util/select_calculation_type.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace line_interpolate +{ + + +/*! +\brief Interpolate point on a cartesian segment. +\ingroup strategies +\tparam CalculationType \tparam_calculation +\tparam DistanceStrategy The underlying point-point distance strategy + +\qbk{ +[heading See also] +\* [link geometry.reference.algorithms.line_interpolate.line_interpolate_4_with_strategy line_interpolate (with strategy)] +} + +*/ +template +< + typename CalculationType = void, + typename DistanceStrategy = distance::pythagoras<CalculationType> +> +class cartesian +{ +public: + + // point-point strategy getters + struct distance_pp_strategy + { + typedef DistanceStrategy type; + }; + + inline typename distance_pp_strategy::type get_distance_pp_strategy() const + { + typedef typename distance_pp_strategy::type distance_type; + return distance_type(); + } + + template <typename Point, typename Fraction, typename Distance> + inline void apply(Point const& p0, + Point const& p1, + Fraction const& fraction, + Point & p, + Distance const&) const + { + typedef typename select_calculation_type_alt + < + CalculationType, + Point + >::type calc_t; + + typedef model::point + < + calc_t, + geometry::dimension<Point>::value, + cs::cartesian + > calc_point_t; + + calc_point_t cp0, cp1; + geometry::detail::conversion::convert_point_to_point(p0, cp0); + geometry::detail::conversion::convert_point_to_point(p1, cp1); + + //segment convex combination: p0*fraction + p1*(1-fraction) + Fraction const one_minus_fraction = 1-fraction; + for_each_coordinate(cp1, detail::value_operation + < + Fraction, + std::multiplies + >(fraction)); + for_each_coordinate(cp0, detail::value_operation + < + Fraction, + std::multiplies + >(one_minus_fraction)); + for_each_coordinate(cp1, detail::point_operation + < + calc_point_t, + std::plus + >(cp0)); + + assert_dimension_equal<calc_point_t, Point>(); + geometry::detail::conversion::convert_point_to_point(cp1, p); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template <> +struct default_strategy<cartesian_tag> +{ + typedef strategy::line_interpolate::cartesian<> type; +}; + + +} // namespace services +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::line_interpolate + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_LINE_INTERPOLATE_HPP diff --git a/boost/geometry/strategies/cartesian/point_in_box.hpp b/boost/geometry/strategies/cartesian/point_in_box.hpp index 1c14125a6d..468e167c60 100644 --- a/boost/geometry/strategies/cartesian/point_in_box.hpp +++ b/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 <boost/geometry/core/access.hpp> #include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/cs.hpp> #include <boost/geometry/strategies/covered_by.hpp> #include <boost/geometry/strategies/within.hpp> #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> @@ -33,6 +34,10 @@ namespace boost { namespace geometry { namespace strategy namespace within { +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + struct within_coord { template <typename Value1, typename Value2> @@ -101,7 +106,7 @@ struct longitude_range < Value1, Value2 >::type calc_t; - typedef typename coordinate_system<Geometry>::type::units units_t; + typedef typename geometry::detail::cs_angular_units<Geometry>::type units_t; typedef math::detail::constants_on_spheroid<calc_t, units_t> constants; if (CoordCheck::apply(value, min_value, max_value)) @@ -142,18 +147,16 @@ struct covered_by_range<Geometry, 0, spherical_tag> template < template <typename, std::size_t, typename> 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 <typename Point, typename Box> static inline bool apply(Point const& point, Box const& box) { - typedef typename tag_cast<typename cs_tag<Point>::type, spherical_tag>::type cs_tag_t; - - if (! SubStrategy<Point, Dimension, cs_tag_t>::apply(get<Dimension>(point), + if (! SubStrategy<Point, Dimension, CSTag>::apply(get<Dimension>(point), get<min_corner, Dimension>(box), get<max_corner, Dimension>(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,46 +177,52 @@ struct relate_point_box_loop template < template <typename, std::size_t, typename> class SubStrategy, - typename Point, - typename Box, + typename CSTag, std::size_t DimensionCount > -struct relate_point_box_loop<SubStrategy, Point, Box, DimensionCount, DimensionCount> +struct relate_point_box_loop<SubStrategy, CSTag, DimensionCount, DimensionCount> { + template <typename Point, typename Box> static inline bool apply(Point const& , Box const& ) { return true; } }; +} // namespace detail +#endif // DOXYGEN_NO_DETAIL -template -< - typename Point, - typename Box, - template <typename, std::size_t, typename> class SubStrategy = within_range -> -struct point_in_box +struct cartesian_point_box { + template <typename Point, typename Box> 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<Point>::type::value + detail::within_range, + cartesian_tag, + 0, dimension<Point>::value >::apply(point, box); } }; - -} // namespace within +struct spherical_point_box +{ + template <typename Point, typename Box> + static inline bool apply(Point const& point, Box const& box) + { + return detail::relate_point_box_loop + < + detail::within_range, + spherical_tag, + 0, dimension<Point>::value + >::apply(point, box); + } +}; #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS - - -namespace within { namespace services +namespace services { template <typename Point, typename Box> @@ -225,7 +234,7 @@ struct default_strategy cartesian_tag, cartesian_tag > { - typedef within::point_in_box<Point, Box> type; + typedef within::cartesian_point_box type; }; // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag @@ -238,14 +247,49 @@ struct default_strategy spherical_tag, spherical_tag > { - typedef within::point_in_box<Point, Box> type; + typedef within::spherical_point_box type; }; -}} // namespace within::services +} // namespace services +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +} // namespace within -namespace covered_by { namespace services +namespace covered_by +{ + +struct cartesian_point_box +{ + template <typename Point, typename Box> + 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<Point>::value + >::apply(point, box); + } +}; + +struct spherical_point_box +{ + template <typename Point, typename Box> + 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<Point>::value + >::apply(point, box); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +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,18 +315,15 @@ 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 -#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +} // namespace covered_by }}} // namespace boost::geometry::strategy diff --git a/boost/geometry/strategies/cartesian/point_in_point.hpp b/boost/geometry/strategies/cartesian/point_in_point.hpp new file mode 100644 index 0000000000..fc849dcd48 --- /dev/null +++ b/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 <cstddef> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/util/math.hpp> + +#include <boost/geometry/strategies/covered_by.hpp> +#include <boost/geometry/strategies/within.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace within +{ + + +template <std::size_t Dimension, std::size_t DimensionCount> +struct point_point_generic +{ + template <typename Point1, typename Point2> + static inline bool apply(Point1 const& p1, Point2 const& p2) + { + if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2))) + { + return false; + } + return + point_point_generic<Dimension + 1, DimensionCount>::apply(p1, p2); + } +}; + +template <std::size_t DimensionCount> +struct point_point_generic<DimensionCount, DimensionCount> +{ + template <typename Point1, typename Point2> + 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 <typename Point1, typename Point2> + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + return geometry::detail::within::point_point_generic + < + 0, dimension<Point1>::type::value + >::apply(point1, point2); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2> +struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, cartesian_tag, cartesian_tag> +{ + 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 <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2> +struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, cartesian_tag, cartesian_tag> +{ + 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/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp b/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp index 94da5cc677..a8e0de7b7a 100644 --- a/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp +++ b/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp @@ -4,6 +4,11 @@ // 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. @@ -15,6 +20,7 @@ #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP +#include <boost/geometry/core/access.hpp> #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/util/select_calculation_type.hpp> diff --git a/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp b/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp index a774d3c52d..16e7987472 100644 --- a/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp +++ b/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp @@ -4,6 +4,11 @@ // 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. @@ -15,6 +20,7 @@ #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP +#include <boost/geometry/core/access.hpp> #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/util/select_calculation_type.hpp> diff --git a/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp b/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp index c41bc9b83d..696a86c984 100644 --- a/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp +++ b/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 <boost/geometry/util/math.hpp> #include <boost/geometry/util/select_calculation_type.hpp> +#include <boost/geometry/strategies/cartesian/point_in_box.hpp> +#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp> #include <boost/geometry/strategies/cartesian/side_by_triangle.hpp> #include <boost/geometry/strategies/covered_by.hpp> #include <boost/geometry/strategies/within.hpp> @@ -42,8 +44,6 @@ namespace strategy { namespace within \tparam PointOfSegment \tparam_segment_point \tparam CalculationType \tparam_calculation \author Barend Gehrels -\note The implementation is inspired by terralib http://www.terralib.org (LGPL) -\note but totally revised afterwards, especially for cases on segments \qbk{ [heading See also] @@ -103,6 +103,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/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/boost/geometry/strategies/cartesian/side_by_triangle.hpp index 91bbee7bb2..9760f560c7 100644 --- a/boost/geometry/strategies/cartesian/side_by_triangle.hpp +++ b/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 <boost/geometry/util/select_coordinate_type.hpp> #include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp> -#include <boost/geometry/strategies/cartesian/envelope_segment.hpp> +#include <boost/geometry/strategies/cartesian/envelope.hpp> +#include <boost/geometry/strategies/cartesian/point_in_point.hpp> #include <boost/geometry/strategies/compare.hpp> #include <boost/geometry/strategies/side.hpp> @@ -70,7 +71,7 @@ class side_by_triangle }; public : - typedef strategy::envelope::cartesian_segment<CalculationType> envelope_strategy_type; + typedef strategy::envelope::cartesian<CalculationType> 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 <typename P1, typename P2> + 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/boost/geometry/strategies/cartesian/side_of_intersection.hpp b/boost/geometry/strategies/cartesian/side_of_intersection.hpp index db57644ad5..9c0a5f0d3b 100644 --- a/boost/geometry/strategies/cartesian/side_of_intersection.hpp +++ b/boost/geometry/strategies/cartesian/side_of_intersection.hpp @@ -2,8 +2,8 @@ // Copyright (c) 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, 2019. +// Modifications copyright (c) 2015-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -118,6 +118,7 @@ struct multiplicable_integral return b < a; } +#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG template <typename CmpVal> void check_value(CmpVal const& cmp_val) const { @@ -125,6 +126,7 @@ struct multiplicable_integral CmpVal val = CmpVal(m_sign) * (CmpVal(m_ms) * CmpVal(b) + CmpVal(m_ls)); BOOST_GEOMETRY_ASSERT(cmp_val == val); } +#endif // BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG }; } // namespace detail diff --git a/boost/geometry/strategies/concepts/area_concept.hpp b/boost/geometry/strategies/concepts/area_concept.hpp index 6edc516f92..da983bac57 100644 --- a/boost/geometry/strategies/concepts/area_concept.hpp +++ b/boost/geometry/strategies/concepts/area_concept.hpp @@ -5,6 +5,10 @@ // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. +// 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. @@ -19,6 +23,9 @@ #include <boost/concept_check.hpp> #include <boost/core/ignore_unused.hpp> +#include <boost/geometry/geometries/point.hpp> + + namespace boost { namespace geometry { namespace concepts { diff --git a/boost/geometry/strategies/concepts/distance_concept.hpp b/boost/geometry/strategies/concepts/distance_concept.hpp index 0064d438d5..ea811d921b 100644 --- a/boost/geometry/strategies/concepts/distance_concept.hpp +++ b/boost/geometry/strategies/concepts/distance_concept.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. @@ -33,6 +34,7 @@ #include <boost/geometry/geometries/segment.hpp> #include <boost/geometry/geometries/point.hpp> +#include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/strategies/tags.hpp> diff --git a/boost/geometry/strategies/concepts/within_concept.hpp b/boost/geometry/strategies/concepts/within_concept.hpp index c02d0dc50f..e8b0b767ac 100644 --- a/boost/geometry/strategies/concepts/within_concept.hpp +++ b/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,13 @@ #include <boost/core/ignore_unused.hpp> #include <boost/function_types/result_type.hpp> +#include <boost/geometry/core/tag.hpp> +#include <boost/geometry/core/tag_cast.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/geometries/concepts/box_concept.hpp> +#include <boost/geometry/geometries/concepts/point_concept.hpp> + #include <boost/geometry/util/parameter_type_of.hpp> @@ -107,7 +118,7 @@ public : #endif }; -template <typename Strategy> +template <typename Point, typename Box, typename Strategy> class WithinStrategyPointBox { #ifndef DOXYGEN_NO_CONCEPT_MEMBERS @@ -165,7 +176,7 @@ class WithinStrategyPointBox public : BOOST_CONCEPT_USAGE(WithinStrategyPointBox) { - checker::apply(&Strategy::apply); + checker::apply(&Strategy::template apply<Point, Box>); } #endif }; @@ -241,26 +252,36 @@ namespace within namespace dispatch { -template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy> +template +< + typename Geometry1, typename Geometry2, + typename FirstTag, typename SecondTag, typename CastedTag, + typename Strategy +> struct check_within {}; -template <typename AnyTag, typename Strategy> -struct check_within<point_tag, AnyTag, areal_tag, Strategy> +template +< + typename Geometry1, typename Geometry2, + typename AnyTag, + typename Strategy +> +struct check_within<Geometry1, Geometry2, point_tag, AnyTag, areal_tag, Strategy> { BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal<Strategy>) ); }; -template <typename Strategy> -struct check_within<point_tag, box_tag, areal_tag, Strategy> +template <typename Geometry1, typename Geometry2, typename Strategy> +struct check_within<Geometry1, Geometry2, point_tag, box_tag, areal_tag, Strategy> { - BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox<Strategy>) ); + BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox<Geometry1, Geometry2, Strategy>) ); }; -template <typename Strategy> -struct check_within<box_tag, box_tag, areal_tag, Strategy> +template <typename Geometry1, typename Geometry2, typename Strategy> +struct check_within<Geometry1, Geometry2, box_tag, box_tag, areal_tag, Strategy> { BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox<Strategy>) ); }; @@ -274,10 +295,18 @@ struct check_within<box_tag, box_tag, areal_tag, Strategy> \brief Checks, in compile-time, the concept of any within-strategy \ingroup concepts */ -template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy> +template <typename Geometry1, typename Geometry2, typename Strategy> inline void check() { - dispatch::check_within<FirstTag, SecondTag, CastedTag, Strategy> c; + dispatch::check_within + < + Geometry1, + Geometry2, + typename tag<Geometry1>::type, + typename tag<Geometry2>::type, + typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type, + Strategy + > c; boost::ignore_unused(c); } diff --git a/boost/geometry/strategies/convex_hull.hpp b/boost/geometry/strategies/convex_hull.hpp index f4edc5ba3f..8208a4eb9f 100644 --- a/boost/geometry/strategies/convex_hull.hpp +++ b/boost/geometry/strategies/convex_hull.hpp @@ -4,6 +4,11 @@ // 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. @@ -14,6 +19,7 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP #define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP +#include <boost/geometry/core/cs.hpp> #include <boost/geometry/strategies/tags.hpp> diff --git a/boost/geometry/strategies/disjoint.hpp b/boost/geometry/strategies/disjoint.hpp index 23d2cede49..c111d2b8f5 100644 --- a/boost/geometry/strategies/disjoint.hpp +++ b/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<Box, MultiPoint, box_tag, multi_point_tag, 2, 0> > {}; -template <typename Box1, typename Box2> -struct default_strategy<Box1, Box2, box_tag, box_tag, 2, 2> -{ - // dummy strategy which will be ignored - typedef geometry::default_strategy type; -}; - } // namespace services #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS diff --git a/boost/geometry/strategies/envelope.hpp b/boost/geometry/strategies/envelope.hpp index fde9c858a6..050ed4658c 100644 --- a/boost/geometry/strategies/envelope.hpp +++ b/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 <typename CSTag, typename CalculationType = void> +template <typename Tag, typename CSTag, typename CalculationType = void> struct default_strategy { BOOST_MPL_ASSERT_MSG ( false, NOT_IMPLEMENTED_FOR_THIS_TYPE - , (types<CSTag>) + , (types<Tag, CSTag>) ); }; diff --git a/boost/geometry/strategies/expand.hpp b/boost/geometry/strategies/expand.hpp new file mode 100644 index 0000000000..39d4145144 --- /dev/null +++ b/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 <boost/mpl/assert.hpp> + +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 <typename Tag, typename CSTag, typename CalculationType = void> +struct default_strategy +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_TYPE + , (types<Tag, CSTag>) + ); +}; + +}}} // namespace strategy::expand::services + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_EXPAND_HPP + diff --git a/boost/geometry/strategies/geographic/area.hpp b/boost/geometry/strategies/geographic/area.hpp index ac7d933ce7..d40a30cf22 100644 --- a/boost/geometry/strategies/geographic/area.hpp +++ b/boost/geometry/strategies/geographic/area.hpp @@ -20,6 +20,7 @@ #include <boost/geometry/formulas/authalic_radius_sqr.hpp> #include <boost/geometry/formulas/eccentricity_sqr.hpp> +#include <boost/geometry/strategies/area.hpp> #include <boost/geometry/strategies/geographic/parameters.hpp> diff --git a/boost/geometry/strategies/geographic/buffer_point_circle.hpp b/boost/geometry/strategies/geographic/buffer_point_circle.hpp new file mode 100644 index 0000000000..7e7c8fe81d --- /dev/null +++ b/boost/geometry/strategies/geographic/buffer_point_circle.hpp @@ -0,0 +1,127 @@ +// Boost.Geometry + +// Copyright (c) 2018-2019 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_POINT_CIRCLE_HPP +#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_POINT_CIRCLE_HPP + +#include <cstddef> + +#include <boost/range.hpp> + +#include <boost/geometry/util/math.hpp> + +#include <boost/geometry/strategies/buffer.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace buffer +{ + +/*! +\brief Create a circular buffer around a point, on the Earth +\ingroup strategies +\details This strategy can be used as PointStrategy for the buffer algorithm. + It creates a circular buffer around a point, on the Earth. It can be applied + for points and multi_points. + +\qbk{ +[heading Example] +[buffer_geographic_point_circle] +[buffer_geographic_point_circle_output] +[heading See also] +\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)] +\* [link geometry.reference.strategies.strategy_buffer_point_circle point_circle] +\* [link geometry.reference.strategies.strategy_buffer_point_square point_square] +} + */ +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid<double>, + typename CalculationType = void +> +class geographic_point_circle +{ +public : + //! \brief Constructs the strategy + //! \param count number of points for the created circle (if count + //! is smaller than 3, count is internally set to 3) + explicit geographic_point_circle(std::size_t count = 90) + : m_count((count < 3u) ? 3u : count) + {} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + //! Fills output_range with a circle around point using distance_strategy + template + < + typename Point, + typename OutputRange, + typename DistanceStrategy + > + inline void apply(Point const& point, + DistanceStrategy const& distance_strategy, + OutputRange& output_range) const + { + typedef typename boost::range_value<OutputRange>::type output_point_type; + + typedef typename select_most_precise + < + typename geometry::coordinate_type<Point>::type, + typename geometry::coordinate_type<output_point_type>::type, + CalculationType + //double + >::type calculation_type; + + calculation_type const buffer_distance = distance_strategy.apply(point, point, + strategy::buffer::buffer_side_left); + + typedef typename FormulaPolicy::template direct + < + calculation_type, true, false, false, false + > direct_t; + + calculation_type const two_pi = geometry::math::two_pi<calculation_type>(); + + calculation_type const diff = two_pi / calculation_type(m_count); + // TODO: after calculation of some angles is corrected, + // we can start at 0.0 + calculation_type angle = 0.001; + + for (std::size_t i = 0; i < m_count; i++, angle += diff) + { + typename direct_t::result_type + dir_r = direct_t::apply(get_as_radian<0>(point), get_as_radian<1>(point), + buffer_distance, angle, + m_spheroid); + output_point_type p; + set_from_radian<0>(p, dir_r.lon2); + set_from_radian<1>(p, dir_r.lat2); + output_range.push_back(p); + } + + { + // Close the range + const output_point_type p = output_range.front(); + output_range.push_back(p); + } + } +#endif // DOXYGEN_SHOULD_SKIP_THIS + +private : + std::size_t m_count; + Spheroid m_spheroid; +}; + + +}} // namespace strategy::buffer + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_POINT_CIRCLE_HPP diff --git a/boost/geometry/strategies/geographic/disjoint_segment_box.hpp b/boost/geometry/strategies/geographic/disjoint_segment_box.hpp index afc9d66775..49c80a5e78 100644 --- a/boost/geometry/strategies/geographic/disjoint_segment_box.hpp +++ b/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 <boost/geometry/algorithms/detail/assign_indexed_point.hpp> #include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp> +#include <boost/geometry/srs/spheroid.hpp> + #include <boost/geometry/strategies/disjoint.hpp> #include <boost/geometry/strategies/geographic/azimuth.hpp> #include <boost/geometry/strategies/geographic/parameters.hpp> +#include <boost/geometry/strategies/normalize.hpp> +#include <boost/geometry/strategies/cartesian/point_in_box.hpp> +#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp> 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 - <geographic_tag>::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/boost/geometry/strategies/geographic/distance_cross_track.hpp b/boost/geometry/strategies/geographic/distance_cross_track.hpp index f84bb4134f..53942529bf 100644 --- a/boost/geometry/strategies/geographic/distance_cross_track.hpp +++ b/boost/geometry/strategies/geographic/distance_cross_track.hpp @@ -1,8 +1,9 @@ // 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 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 @@ -27,7 +28,9 @@ #include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/strategies/concepts/distance_concept.hpp> +#include <boost/geometry/strategies/spherical/distance_cross_track.hpp> #include <boost/geometry/strategies/spherical/distance_haversine.hpp> +#include <boost/geometry/strategies/spherical/point_in_point.hpp> #include <boost/geometry/strategies/geographic/azimuth.hpp> #include <boost/geometry/strategies/geographic/distance.hpp> #include <boost/geometry/strategies/geographic/parameters.hpp> @@ -84,6 +87,8 @@ template class geographic_cross_track { public : + typedef within::spherical_point_point equals_point_point_strategy_type; + template <typename Point, typename PointOfSegment> struct return_type : promote_floating_point @@ -105,7 +110,7 @@ public : inline typename return_type<Point, PointOfSegment>::type apply(Point const& p, PointOfSegment const& sp1, PointOfSegment const& sp2) const { - typedef typename coordinate_system<Point>::type::units units_type; + typedef typename geometry::detail::cs_angular_units<Point>::type units_type; return (apply<units_type>(get<0>(sp1), get<1>(sp1), get<0>(sp2), get<1>(sp2), @@ -404,7 +409,7 @@ private : return non_iterative_case(lon2, lat2, lon3, lat3, spheroid); } - // Guess s14 (SPHERICAL) + // Guess s14 (SPHERICAL) aka along-track distance typedef geometry::model::point < CT, 2, @@ -420,7 +425,12 @@ private : geometry::strategy::distance::haversine<CT> str(earth_radius); CT s13 = str.apply(p1, p3); - CT s14 = acos( cos(s13/earth_radius) / cos(s34/earth_radius) ) * earth_radius; + + //CT s14 = acos( cos(s13/earth_radius) / cos(s34/earth_radius) ) * earth_radius; + CT cos_frac = cos(s13/earth_radius) / cos(s34/earth_radius); + CT s14 = cos_frac >= 1 ? CT(0) + : cos_frac <= -1 ? pi * earth_radius + : acos(cos_frac) * earth_radius; #ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK std::cout << "s34=" << s34 << std::endl; @@ -638,15 +648,11 @@ template > struct get_comparable<geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> > { - typedef typename comparable_type - < - geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> - >::type comparable_type; public : - static inline comparable_type - apply(geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> const& ) + static inline geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> + apply(geographic_cross_track<FormulaPolicy, Spheroid, CalculationType> const& strategy) { - return comparable_type(); + return strategy; } }; diff --git a/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp b/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp index 8e48fbf19a..2bc33096ad 100644 --- a/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp +++ b/boost/geometry/strategies/geographic/distance_cross_track_box_box.hpp @@ -25,6 +25,8 @@ #include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/strategies/concepts/distance_concept.hpp> +#include <boost/geometry/strategies/geographic/distance.hpp> +#include <boost/geometry/strategies/geographic/distance_cross_track.hpp> #include <boost/geometry/strategies/spherical/distance_cross_track.hpp> #include <boost/geometry/strategies/spherical/distance_cross_track_box_box.hpp> @@ -171,13 +173,11 @@ struct comparable_type<geographic_cross_track_box_box<Strategy, Spheroid, Calcul template <typename Strategy, typename Spheroid, typename CalculationType> struct get_comparable<geographic_cross_track_box_box<Strategy, Spheroid, CalculationType> > { - typedef geographic_cross_track_box_box<Strategy, Spheroid, CalculationType> this_strategy; - typedef typename comparable_type<this_strategy>::type comparable_type; - public: - static inline comparable_type apply(this_strategy const& /*strategy*/) + static inline geographic_cross_track_box_box<Strategy, Spheroid, CalculationType> + apply(geographic_cross_track_box_box<Strategy, Spheroid, CalculationType> const& str) { - return comparable_type(); + return str; } }; diff --git a/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp b/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp index 4508d5acb5..b6694b4e02 100644 --- a/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp +++ b/boost/geometry/strategies/geographic/distance_cross_track_point_box.hpp @@ -157,13 +157,11 @@ struct comparable_type<geographic_cross_track_point_box<Strategy, Spheroid, Calc template <typename Strategy, typename Spheroid, typename CalculationType> struct get_comparable<geographic_cross_track_point_box<Strategy, Spheroid, CalculationType> > { - typedef geographic_cross_track_point_box<Strategy, Spheroid, CalculationType> this_strategy; - typedef typename comparable_type<this_strategy>::type comparable_type; - public: - static inline comparable_type apply(this_strategy const&) + static inline geographic_cross_track_point_box<Strategy, Spheroid, CalculationType> + apply(geographic_cross_track_point_box<Strategy, Spheroid, CalculationType> const& str) { - return comparable_type(); + return str; } }; diff --git a/boost/geometry/strategies/geographic/distance_segment_box.hpp b/boost/geometry/strategies/geographic/distance_segment_box.hpp index 6bde78ca27..615f938739 100644 --- a/boost/geometry/strategies/geographic/distance_segment_box.hpp +++ b/boost/geometry/strategies/geographic/distance_segment_box.hpp @@ -1,7 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2018 Oracle and/or its affiliates. +// Copyright (c) 2018-2019 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,22 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_SEGMENT_BOX_HPP #define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_SEGMENT_BOX_HPP +#include <boost/geometry/srs/spheroid.hpp> + #include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp> +#include <boost/geometry/strategies/distance.hpp> +#include <boost/geometry/strategies/geographic/parameters.hpp> +#include <boost/geometry/strategies/geographic/azimuth.hpp> +#include <boost/geometry/strategies/geographic/distance_cross_track.hpp> +#include <boost/geometry/strategies/normalize.hpp> +#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp> +#include <boost/geometry/strategies/spherical/distance_segment_box.hpp> +#include <boost/geometry/strategies/spherical/point_in_point.hpp> + +#include <boost/geometry/util/promote_floating_point.hpp> +#include <boost/geometry/util/select_calculation_type.hpp> + namespace boost { namespace geometry { @@ -68,6 +83,13 @@ struct geographic_segment_box return distance_type(m_spheroid); } + typedef within::spherical_point_point equals_point_point_strategy_type; + + static inline equals_point_point_strategy_type get_equals_point_point_strategy() + { + return equals_point_point_strategy_type(); + } + //constructor explicit geographic_segment_box(Spheroid const& spheroid = Spheroid()) @@ -107,7 +129,10 @@ struct geographic_segment_box ReturnType >(p0,p1,top_left,top_right,bottom_left,bottom_right, geographic_segment_box<FormulaPolicy, Spheroid, CalculationType>(), - az_strategy, es_strategy); + az_strategy, es_strategy, + normalize::spherical_point(), + covered_by::spherical_point_box(), + disjoint::spherical_box_box()); } template <typename SPoint, typename BPoint> diff --git a/boost/geometry/strategies/geographic/envelope.hpp b/boost/geometry/strategies/geographic/envelope.hpp new file mode 100644 index 0000000000..4623f1a6cd --- /dev/null +++ b/boost/geometry/strategies/geographic/envelope.hpp @@ -0,0 +1,116 @@ +// 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, 2019. +// Modifications copyright (c) 2015-2019, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// 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 <boost/geometry/srs/spheroid.hpp> + +#include <boost/geometry/strategies/geographic/envelope_segment.hpp> +#include <boost/geometry/strategies/geographic/expand_segment.hpp> +#include <boost/geometry/strategies/geographic/parameters.hpp> +#include <boost/geometry/strategies/spherical/envelope.hpp> + +namespace boost { namespace geometry +{ + +namespace strategy { namespace envelope +{ + + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = geometry::srs::spheroid<double>, + typename CalculationType = void +> +class geographic + : public spherical<CalculationType> +{ +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 <typename Point1, typename Point2, typename Box> + 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 <typename Tag, typename CalculationType> +struct default_strategy<Tag, geographic_tag, CalculationType> +{ + typedef strategy::envelope::geographic + < + strategy::andoyer, + geometry::srs::spheroid<double>, + CalculationType + > type; +}; + +} + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + +}} //namepsace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ENVELOPE_HPP diff --git a/boost/geometry/strategies/geographic/envelope_segment.hpp b/boost/geometry/strategies/geographic/envelope_segment.hpp index 5bada63f63..fda7868af2 100644 --- a/boost/geometry/strategies/geographic/envelope_segment.hpp +++ b/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 <boost/geometry/algorithms/detail/envelope/segment.hpp> -#include <boost/geometry/algorithms/detail/normalize.hpp> - #include <boost/geometry/srs/spheroid.hpp> +#include <boost/geometry/strategies/cartesian/envelope_segment.hpp> #include <boost/geometry/strategies/envelope.hpp> #include <boost/geometry/strategies/geographic/azimuth.hpp> #include <boost/geometry/strategies/geographic/parameters.hpp> - +#include <boost/geometry/strategies/normalize.hpp> +#include <boost/geometry/strategies/spherical/envelope_segment.hpp> +#include <boost/geometry/strategies/spherical/expand_box.hpp> namespace boost { namespace geometry { @@ -47,11 +47,18 @@ public: : m_spheroid(spheroid) {} - template <typename Point1, typename Point2, typename Box> - 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>(point1); - Point2 p2_normalized = detail::return_normalized<Point2>(point2); + return box_expand_strategy_type(); + } + + template <typename Point, typename Box> + 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<Point1>::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<units_type>(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<Point>::value + >::apply(point1, point2, box); } private: @@ -84,7 +101,7 @@ namespace services { template <typename CalculationType> -struct default_strategy<geographic_tag, CalculationType> +struct default_strategy<segment_tag, geographic_tag, CalculationType> { typedef strategy::envelope::geographic_segment < diff --git a/boost/geometry/strategies/geographic/expand_segment.hpp b/boost/geometry/strategies/geographic/expand_segment.hpp new file mode 100644 index 0000000000..66779c1099 --- /dev/null +++ b/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 <cstddef> +#include <functional> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/algorithms/detail/envelope/box.hpp> +#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp> +#include <boost/geometry/algorithms/detail/envelope/segment.hpp> + +#include <boost/geometry/srs/spheroid.hpp> + +#include <boost/geometry/strategies/expand.hpp> +#include <boost/geometry/strategies/geographic/envelope_segment.hpp> +#include <boost/geometry/strategies/geographic/parameters.hpp> +#include <boost/geometry/strategies/spherical/expand_segment.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = geometry::srs::spheroid<double>, + 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 <typename Box, typename Segment> + 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 <typename CalculationType> +struct default_strategy<segment_tag, geographic_tag, CalculationType> +{ + typedef geographic_segment + < + strategy::andoyer, + geometry::srs::spheroid<double>, + 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/boost/geometry/strategies/geographic/intersection.hpp b/boost/geometry/strategies/geographic/intersection.hpp index b095f8aefb..37f79e5895 100644 --- a/boost/geometry/strategies/geographic/intersection.hpp +++ b/boost/geometry/strategies/geographic/intersection.hpp @@ -2,7 +2,7 @@ // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// Copyright (c) 2016-2018, Oracle and/or its affiliates. +// Copyright (c) 2016-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -37,11 +37,15 @@ #include <boost/geometry/srs/spheroid.hpp> #include <boost/geometry/strategies/geographic/area.hpp> +#include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp> #include <boost/geometry/strategies/geographic/distance.hpp> -#include <boost/geometry/strategies/geographic/envelope_segment.hpp> +#include <boost/geometry/strategies/geographic/envelope.hpp> #include <boost/geometry/strategies/geographic/parameters.hpp> #include <boost/geometry/strategies/geographic/point_in_poly_winding.hpp> #include <boost/geometry/strategies/geographic/side.hpp> +#include <boost/geometry/strategies/spherical/expand_box.hpp> +#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp> +#include <boost/geometry/strategies/spherical/point_in_point.hpp> #include <boost/geometry/strategies/intersection.hpp> #include <boost/geometry/strategies/intersection_result.hpp> #include <boost/geometry/strategies/side_info.hpp> @@ -141,7 +145,7 @@ struct geographic_segments return strategy_type(m_spheroid); } - typedef envelope::geographic_segment<FormulaPolicy, Spheroid, CalculationType> + typedef envelope::geographic<FormulaPolicy, Spheroid, CalculationType> envelope_strategy_type; inline envelope_strategy_type get_envelope_strategy() const @@ -149,6 +153,48 @@ struct geographic_segments return envelope_strategy_type(m_spheroid); } + typedef expand::geographic_segment<FormulaPolicy, Spheroid, CalculationType> + 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 disjoint::segment_box_geographic + < + FormulaPolicy, Spheroid, CalculationType + > disjoint_segment_box_strategy_type; + + inline disjoint_segment_box_strategy_type get_disjoint_segment_box_strategy() const + { + return disjoint_segment_box_strategy_type(m_spheroid); + } + + 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 <typename CoordinateType, typename SegmentRatio> @@ -285,7 +331,6 @@ private: spheroid_type spheroid = formula::unit_spheroid<spheroid_type>(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); @@ -615,7 +660,7 @@ private: // in order to make this independent from is_near() template <typename Point1, typename Point2, typename ResultInverse, typename CalcT> static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2, // in - Point2 const& b1, Point2 const& b2, // in + Point2 const& b1, Point2 const& /*b2*/, // in ResultInverse const& res_a1_a2, // in ResultInverse const& res_a1_b1, // in ResultInverse const& res_a1_b2, // in @@ -688,7 +733,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 +932,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 +991,13 @@ private: ip_flag; } + template <typename Point1, typename Point2> + 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/boost/geometry/strategies/geographic/line_interpolate.hpp b/boost/geometry/strategies/geographic/line_interpolate.hpp new file mode 100644 index 0000000000..d5f0e04c93 --- /dev/null +++ b/boost/geometry/strategies/geographic/line_interpolate.hpp @@ -0,0 +1,129 @@ +// Boost.Geometry + +// Copyright (c) 2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_LINE_INTERPOLATE_HPP +#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_LINE_INTERPOLATE_HPP + +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/radian_access.hpp> +#include <boost/geometry/srs/spheroid.hpp> +#include <boost/geometry/strategies/line_interpolate.hpp> +#include <boost/geometry/strategies/geographic/parameters.hpp> +#include <boost/geometry/util/select_calculation_type.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace line_interpolate +{ + + +/*! +\brief Interpolate point on a geographic segment. +\ingroup strategies +\tparam FormulaPolicy The geodesic formulas used internally. +\tparam Spheroid The spheroid model. +\tparam CalculationType \tparam_calculation + +\qbk{ +[heading See also] +\* [link geometry.reference.algorithms.line_interpolate.line_interpolate_4_with_strategy line_interpolate (with strategy)] +\* [link geometry.reference.srs.srs_spheroid srs::spheroid] +} + */ +template +< + typename FormulaPolicy = strategy::andoyer, + typename Spheroid = srs::spheroid<double>, + typename CalculationType = void +> +class geographic +{ +public: + geographic() + : m_spheroid() + {} + + explicit geographic(Spheroid const& spheroid) + : m_spheroid(spheroid) + {} + + // point-point strategy getters + struct distance_pp_strategy + { + typedef distance::geographic<FormulaPolicy, Spheroid, CalculationType> type; + }; + + inline typename distance_pp_strategy::type get_distance_pp_strategy() const + { + typedef typename distance_pp_strategy::type distance_type; + return distance_type(m_spheroid); + } + + template <typename Point, typename Fraction, typename Distance> + inline void apply(Point const& p0, + Point const& p1, + Fraction const& fraction, //fraction of segment + Point & p, + Distance const& distance) const + { + typedef typename select_calculation_type_alt + < + CalculationType, + Point + >::type calc_t; + + typedef typename FormulaPolicy::template inverse + <calc_t, false, true, false, false, false> inverse_t; + + calc_t azimuth = inverse_t::apply(get_as_radian<0>(p0), get_as_radian<1>(p0), + get_as_radian<0>(p1), get_as_radian<1>(p1), + m_spheroid).azimuth; + + typedef typename FormulaPolicy::template direct + <calc_t, true, false, false, false> direct_t; + + typename direct_t::result_type + dir_r = direct_t::apply(get_as_radian<0>(p0), get_as_radian<1>(p0), + distance * fraction, azimuth, + m_spheroid); + + set_from_radian<0>(p, dir_r.lon2); + set_from_radian<1>(p, dir_r.lat2); + } + +private: + Spheroid m_spheroid; +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template <> +struct default_strategy<geographic_tag> +{ + typedef strategy::line_interpolate::geographic<> type; +}; + + +} // namespace services +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::line_interpolate + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_LINE_INTERPOLATE_HPP diff --git a/boost/geometry/strategies/geographic/side.hpp b/boost/geometry/strategies/geographic/side.hpp index 1201dc2f6d..e22718f32b 100644 --- a/boost/geometry/strategies/geographic/side.hpp +++ b/boost/geometry/strategies/geographic/side.hpp @@ -28,9 +28,10 @@ #include <boost/geometry/util/select_calculation_type.hpp> #include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp> -#include <boost/geometry/strategies/geographic/envelope_segment.hpp> +#include <boost/geometry/strategies/geographic/envelope.hpp> #include <boost/geometry/strategies/geographic/parameters.hpp> #include <boost/geometry/strategies/side.hpp> +#include <boost/geometry/strategies/spherical/point_in_point.hpp> //#include <boost/geometry/strategies/concepts/side_concept.hpp> @@ -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/boost/geometry/strategies/line_interpolate.hpp b/boost/geometry/strategies/line_interpolate.hpp new file mode 100644 index 0000000000..43d4250c0c --- /dev/null +++ b/boost/geometry/strategies/line_interpolate.hpp @@ -0,0 +1,42 @@ +// Boost.Geometry + +// Copyright (c) 2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_HPP +#define BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_HPP + + +#include <boost/mpl/assert.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace line_interpolate +{ + +namespace services +{ + +template <typename CSTag> +struct default_strategy +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_IMPLEMENTED_FOR_THIS_CS + , (types<CSTag>) + ); +}; + +} // namespace services + +}} // namespace strategy::line_interpolate + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_LINE_INTERPOLATE_HPP diff --git a/boost/geometry/strategies/normalize.hpp b/boost/geometry/strategies/normalize.hpp new file mode 100644 index 0000000000..1887c1e63b --- /dev/null +++ b/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 <cstddef> + +#include <boost/numeric/conversion/cast.hpp> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/tag.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> +#include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp> + +#include <boost/geometry/views/detail/indexed_point_view.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace normalize +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +struct do_nothing +{ + template <typename GeometryIn, typename GeometryOut> + static inline void apply(GeometryIn const&, GeometryOut&) + { + } +}; + + +template <std::size_t Dimension, std::size_t DimensionCount> +struct assign_loop +{ + template <typename CoordinateType, typename PointIn, typename PointOut> + static inline void apply(CoordinateType const& longitude, + CoordinateType const& latitude, + PointIn const& point_in, + PointOut& point_out) + { + geometry::set<Dimension>(point_out, boost::numeric_cast + < + typename coordinate_type<PointOut>::type + >(geometry::get<Dimension>(point_in))); + + assign_loop + < + Dimension + 1, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + +template <std::size_t DimensionCount> +struct assign_loop<DimensionCount, DimensionCount> +{ + template <typename CoordinateType, typename PointIn, typename PointOut> + static inline void apply(CoordinateType const&, + CoordinateType const&, + PointIn const&, + PointOut&) + { + } +}; + +template <std::size_t DimensionCount> +struct assign_loop<0, DimensionCount> +{ + template <typename CoordinateType, typename PointIn, typename PointOut> + 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<PointOut>::type + >(longitude)); + + assign_loop + < + 1, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + +template <std::size_t DimensionCount> +struct assign_loop<1, DimensionCount> +{ + template <typename CoordinateType, typename PointIn, typename PointOut> + 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<PointOut>::type + >(latitude)); + + assign_loop + < + 2, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + + +template <typename PointIn, typename PointOut, bool IsEquatorial = true> +struct normalize_point +{ + static inline void apply(PointIn const& point_in, PointOut& point_out) + { + typedef typename coordinate_type<PointIn>::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<PointIn>::type, + IsEquatorial, + in_coordinate_type + >(longitude, latitude); + + assign_loop + < + 0, dimension<PointIn>::value + >::apply(longitude, latitude, point_in, point_out); + } +}; + + +template <typename BoxIn, typename BoxOut, bool IsEquatorial = true> +class normalize_box +{ + template <typename UnitsIn, typename UnitsOut, typename CoordinateInType> + 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<BoxOut, min_corner> p_min_out(box_out); + assign_loop + < + 0, dimension<BoxIn>::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<BoxOut, max_corner> p_max_out(box_out); + assign_loop + < + 0, dimension<BoxIn>::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<BoxIn>::type in_coordinate_type; + + in_coordinate_type lon_min = geometry::get<min_corner, 0>(box_in); + in_coordinate_type lat_min = geometry::get<min_corner, 1>(box_in); + in_coordinate_type lon_max = geometry::get<max_corner, 0>(box_in); + in_coordinate_type lat_max = geometry::get<max_corner, 1>(box_in); + + math::normalize_spheroidal_box_coordinates + < + typename geometry::detail::cs_angular_units<BoxIn>::type, + IsEquatorial, + in_coordinate_type + >(lon_min, lat_min, lon_max, lat_max); + + apply_to_coordinates + < + typename geometry::detail::cs_angular_units<BoxIn>::type, + typename geometry::detail::cs_angular_units<BoxOut>::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 <typename PointIn, typename PointOut> + 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<PointIn>::type, + spherical_polar_tag + > + >::value + >::apply(point_in, point_out); + } +}; + +struct spherical_box +{ + template <typename BoxIn, typename BoxOut> + 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<BoxIn>::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/boost/geometry/strategies/side.hpp b/boost/geometry/strategies/side.hpp index 9aaa2bdddc..ea8e5fd226 100644 --- a/boost/geometry/strategies/side.hpp +++ b/boost/geometry/strategies/side.hpp @@ -4,6 +4,11 @@ // 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. @@ -15,6 +20,8 @@ #define BOOST_GEOMETRY_STRATEGIES_SIDE_HPP +#include <boost/mpl/assert.hpp> + #include <boost/geometry/strategies/tags.hpp> diff --git a/boost/geometry/strategies/spherical/compare.hpp b/boost/geometry/strategies/spherical/compare.hpp index 26163f7406..bf28fe75a8 100644 --- a/boost/geometry/strategies/spherical/compare.hpp +++ b/boost/geometry/strategies/spherical/compare.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017. -// 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 @@ -25,6 +25,7 @@ #include <boost/geometry/core/coordinate_system.hpp> #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/radian_access.hpp> #include <boost/geometry/core/tags.hpp> #include <boost/geometry/strategies/compare.hpp> diff --git a/boost/geometry/strategies/spherical/densify.hpp b/boost/geometry/strategies/spherical/densify.hpp index 97f4605a98..11eb866c1a 100644 --- a/boost/geometry/strategies/spherical/densify.hpp +++ b/boost/geometry/strategies/spherical/densify.hpp @@ -1,7 +1,8 @@ // Boost.Geometry -// Copyright (c) 2017-2018, Oracle and/or its affiliates. +// Copyright (c) 2017-2019, Oracle and/or its affiliates. +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Licensed under the Boost Software License version 1.0. @@ -22,6 +23,8 @@ #include <boost/geometry/core/coordinate_type.hpp> #include <boost/geometry/core/radian_access.hpp> #include <boost/geometry/formulas/spherical.hpp> +#include <boost/geometry/formulas/interpolate_point_spherical.hpp> +#include <boost/geometry/geometries/point.hpp> #include <boost/geometry/srs/sphere.hpp> #include <boost/geometry/strategies/densify.hpp> #include <boost/geometry/strategies/spherical/get_radius.hpp> @@ -79,15 +82,10 @@ public: CalculationType >::type calc_t; - calc_t const c0 = 0; - calc_t const c1 = 1; - calc_t const pi = math::pi<calc_t>(); + calc_t angle01; - typedef model::point<calc_t, 3, cs::cartesian> point3d_t; - point3d_t const xyz0 = formula::sph_to_cart3d<point3d_t>(p0); - point3d_t const xyz1 = formula::sph_to_cart3d<point3d_t>(p1); - calc_t const dot01 = geometry::dot_product(xyz0, xyz1); - calc_t const angle01 = acos(dot01); + formula::interpolate_point_spherical<calc_t> formula; + formula.compute_angle(p0, p1, angle01); BOOST_GEOMETRY_ASSERT(length_threshold > T(0)); @@ -95,59 +93,16 @@ public: if (n <= 0) return; - point3d_t axis; - if (! math::equals(angle01, pi)) - { - axis = geometry::cross_product(xyz0, xyz1); - geometry::detail::vec_normalize(axis); - } - else // antipodal - { - calc_t const half_pi = math::half_pi<calc_t>(); - calc_t const lat = geometry::get_as_radian<1>(p0); - - if (math::equals(lat, half_pi)) - { - // pointing east, segment lies on prime meridian, going south - axis = point3d_t(c0, c1, c0); - } - else if (math::equals(lat, -half_pi)) - { - // pointing west, segment lies on prime meridian, going north - axis = point3d_t(c0, -c1, c0); - } - else - { - // lon rotated west by pi/2 at equator - calc_t const lon = geometry::get_as_radian<0>(p0); - axis = point3d_t(sin(lon), -cos(lon), c0); - } - } + formula.compute_axis(p0, angle01); calc_t step = angle01 / (n + 1); calc_t a = step; for (signed_size_type i = 0 ; i < n ; ++i, a += step) { - // Axis-Angle rotation - // see: https://en.wikipedia.org/wiki/Axis-angle_representation - calc_t const cos_a = cos(a); - calc_t const sin_a = sin(a); - // cos_a * v - point3d_t s1 = xyz0; - geometry::multiply_value(s1, cos_a); - // sin_a * (n x v) - point3d_t s2 = geometry::cross_product(axis, xyz0); - geometry::multiply_value(s2, sin_a); - // (1 - cos_a)(n.v) * n - point3d_t s3 = axis; - geometry::multiply_value(s3, (c1 - cos_a) * geometry::dot_product(axis, xyz0)); - // v_rot = cos_a * v + sin_a * (n x v) + (1 - cos_a)(n.v) * e - point3d_t v_rot = s1; - geometry::add_point(v_rot, s2); - geometry::add_point(v_rot, s3); - - out_point_t p = formula::cart3d_to_sph<out_point_t>(v_rot); + out_point_t p; + formula.compute_point(a, p); + geometry::detail::conversion::point_to_point < Point, out_point_t, diff --git a/boost/geometry/strategies/spherical/disjoint_box_box.hpp b/boost/geometry/strategies/spherical/disjoint_box_box.hpp new file mode 100644 index 0000000000..f0504a8b17 --- /dev/null +++ b/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 <cstddef> + +#include <boost/geometry/core/cs.hpp> + +#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp> +#include <boost/geometry/strategies/disjoint.hpp> + +#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> +#include <boost/geometry/util/select_most_precise.hpp> + + +namespace boost { namespace geometry { namespace strategy { namespace disjoint +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +struct box_box_on_spheroid +{ + template <typename Box1, typename Box2> + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + typedef typename geometry::select_most_precise + < + typename coordinate_type<Box1>::type, + typename coordinate_type<Box2>::type + >::type calc_t; + typedef typename geometry::detail::cs_angular_units<Box1>::type units_t; + typedef math::detail::constants_on_spheroid<calc_t, units_t> constants; + + calc_t const b1_min = get<min_corner, 0>(box1); + calc_t const b1_max = get<max_corner, 0>(box1); + calc_t const b2_min = get<min_corner, 0>(box2); + calc_t const b2_max = get<max_corner, 0>(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<units_t>(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 <typename Box1, typename Box2> + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + return detail::box_box_on_spheroid::apply(box1, box2); + } +}; + + +namespace services +{ + +template <typename Box1, typename Box2, int TopDim1, int TopDim2> +struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, spherical_equatorial_tag, spherical_equatorial_tag> +{ + typedef disjoint::spherical_box_box type; +}; + +template <typename Box1, typename Box2, int TopDim1, int TopDim2> +struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, spherical_polar_tag, spherical_polar_tag> +{ + typedef disjoint::spherical_box_box type; +}; + +template <typename Box1, typename Box2, int TopDim1, int TopDim2> +struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, geographic_tag, geographic_tag> +{ + 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/boost/geometry/strategies/spherical/disjoint_segment_box.hpp b/boost/geometry/strategies/spherical/disjoint_segment_box.hpp index bda62a77fc..9c6711dea6 100644 --- a/boost/geometry/strategies/spherical/disjoint_segment_box.hpp +++ b/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 <boost/geometry/algorithms/detail/assign_indexed_point.hpp> #include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp> -#include <boost/geometry/strategies/spherical/azimuth.hpp> +// TODO: spherical_point_box currently defined in the same file as cartesian +#include <boost/geometry/strategies/cartesian/point_in_box.hpp> #include <boost/geometry/strategies/disjoint.hpp> +#include <boost/geometry/strategies/normalize.hpp> +#include <boost/geometry/strategies/spherical/azimuth.hpp> +#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp> + namespace boost { namespace geometry { namespace strategy { namespace disjoint { @@ -67,7 +72,13 @@ struct segment_box_spherical geometry::strategy::azimuth::spherical<CT> azimuth_strategy; return geometry::detail::disjoint::disjoint_segment_box_sphere_or_spheroid - <spherical_equatorial_tag>::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/boost/geometry/strategies/spherical/distance_cross_track.hpp b/boost/geometry/strategies/spherical/distance_cross_track.hpp index 97a36b8b27..280bf76b43 100644 --- a/boost/geometry/strategies/spherical/distance_cross_track.hpp +++ b/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 @@ -27,9 +28,12 @@ #include <boost/geometry/core/radian_access.hpp> #include <boost/geometry/core/tags.hpp> +#include <boost/geometry/formulas/spherical.hpp> + #include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/strategies/concepts/distance_concept.hpp> #include <boost/geometry/strategies/spherical/distance_haversine.hpp> +#include <boost/geometry/strategies/spherical/point_in_point.hpp> #include <boost/geometry/util/math.hpp> #include <boost/geometry/util/promote_floating_point.hpp> @@ -326,6 +330,8 @@ template class cross_track { public : + typedef within::spherical_point_point equals_point_point_strategy_type; + template <typename Point, typename PointOfSegment> struct return_type : promote_floating_point @@ -505,6 +511,8 @@ template class cross_track { public : + typedef within::spherical_point_point equals_point_point_strategy_type; + template <typename Point, typename PointOfSegment> struct return_type : promote_floating_point diff --git a/boost/geometry/strategies/spherical/distance_segment_box.hpp b/boost/geometry/strategies/spherical/distance_segment_box.hpp index d5647182a8..bb622ec52d 100644 --- a/boost/geometry/strategies/spherical/distance_segment_box.hpp +++ b/boost/geometry/strategies/spherical/distance_segment_box.hpp @@ -1,7 +1,8 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2018 Oracle and/or its affiliates. +// Copyright (c) 2018-2019 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,13 @@ #include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp> +#include <boost/geometry/strategies/distance.hpp> +#include <boost/geometry/strategies/normalize.hpp> +#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp> +#include <boost/geometry/strategies/spherical/distance_cross_track.hpp> +#include <boost/geometry/strategies/spherical/point_in_point.hpp> +#include <boost/geometry/strategies/cartesian/point_in_box.hpp> // spherical + namespace boost { namespace geometry { @@ -29,7 +37,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 +50,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 +80,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 { @@ -85,6 +100,12 @@ struct generic_segment_box CT lon2 = geometry::get_as_radian<0>(p1); CT lat2 = geometry::get_as_radian<1>(p1); + if (lon1 > lon2) + { + std::swap(lon1, lon2); + std::swap(lat1, lat2); + } + CT vertex_lat; CT lat_sum = lat1 + lat2; if (lat_sum > CT(0)) @@ -198,6 +219,13 @@ struct spherical_segment_box return typename distance_ps_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(); + } + // methods template <typename LessEqual, typename ReturnType, @@ -222,7 +250,10 @@ struct spherical_segment_box ReturnType >(p0,p1,top_left,top_right,bottom_left,bottom_right, spherical_segment_box<CalculationType>(), - az_strategy, es_strategy); + az_strategy, es_strategy, + normalize::spherical_point(), + covered_by::spherical_point_box(), + disjoint::spherical_box_box()); } template <typename SPoint, typename BPoint> diff --git a/boost/geometry/strategies/spherical/envelope.hpp b/boost/geometry/strategies/spherical/envelope.hpp new file mode 100644 index 0000000000..4353f0180b --- /dev/null +++ b/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 <boost/geometry/algorithms/detail/envelope/initialize.hpp> +#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp> + +#include <boost/geometry/iterators/segment_iterator.hpp> + +#include <boost/geometry/strategies/spherical/envelope_box.hpp> +#include <boost/geometry/strategies/spherical/envelope_segment.hpp> +#include <boost/geometry/strategies/spherical/expand_box.hpp> +#include <boost/geometry/strategies/spherical/expand_segment.hpp> + +namespace boost { namespace geometry +{ + +namespace strategy { namespace envelope +{ + +template <typename CalculationType = void> +class spherical +{ +public: + typedef spherical_segment<CalculationType> element_envelope_strategy_type; + static inline element_envelope_strategy_type get_element_envelope_strategy() + { + return element_envelope_strategy_type(); + } + + typedef expand::spherical_segment<CalculationType> 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 <typename Range> + static inline geometry::segment_iterator<Range const> begin(Range const& range) + { + return geometry::segments_begin(range); + } + + template <typename Range> + static inline geometry::segment_iterator<Range const> end(Range const& range) + { + return geometry::segments_end(range); + } + + // MultiLinestring, MultiPolygon + + template <typename Box> + 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<Box, 0, dimension<Box>::value>::apply(box); + } + } + + private: + std::vector<Box> m_boxes; + }; + + // Segment + + template <typename Point1, typename Point2, typename Box> + static inline void apply(Point1 const& point1, Point2 const& point2, + Box& box) + { + spherical_segment<CalculationType>::apply(point1, point2, box); + } + + // Box + + template <typename BoxIn, typename Box> + static inline void apply(BoxIn const& box_in, Box& box) + { + spherical_box::apply(box_in, box); + } +}; + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename Tag, typename CalculationType> +struct default_strategy<Tag, spherical_equatorial_tag, CalculationType> +{ + typedef strategy::envelope::spherical<CalculationType> type; +}; + +template <typename Tag, typename CalculationType> +struct default_strategy<Tag, spherical_polar_tag, CalculationType> +{ + typedef strategy::envelope::spherical<CalculationType> type; +}; + +} + +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::envelope + +}} //namepsace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_HPP diff --git a/boost/geometry/strategies/spherical/envelope_box.hpp b/boost/geometry/strategies/spherical/envelope_box.hpp new file mode 100644 index 0000000000..0a9436d123 --- /dev/null +++ b/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 <cstddef> + +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/views/detail/indexed_point_view.hpp> + +#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> +#include <boost/geometry/algorithms/detail/normalize.hpp> +#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> + +#include <boost/geometry/algorithms/dispatch/envelope.hpp> + +#include <boost/geometry/strategies/envelope.hpp> + + +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 <typename BoxIn, typename BoxOut> + 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<BoxIn const, Index> box_in_corner(box_in); + detail::indexed_point_view<BoxOut, Index> 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<BoxIn const, Index>, + detail::indexed_point_view<BoxOut, Index>, + 2, + DimensionCount + >::apply(box_in_corner, mbr_corner); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +namespace strategy { namespace envelope +{ + + +struct spherical_box +{ + template <typename BoxIn, typename BoxOut> + 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<BoxIn>::value + >::apply(box_in_normalized, mbr); + + geometry::detail::envelope::envelope_indexed_box_on_spheroid + < + max_corner, dimension<BoxIn>::value + >::apply(box_in_normalized, mbr); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename CalculationType> +struct default_strategy<box_tag, spherical_equatorial_tag, CalculationType> +{ + typedef strategy::envelope::spherical_box type; +}; + +template <typename CalculationType> +struct default_strategy<box_tag, spherical_polar_tag, CalculationType> +{ + typedef strategy::envelope::spherical_box type; +}; + +template <typename CalculationType> +struct default_strategy<box_tag, geographic_tag, CalculationType> +{ + 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/boost/geometry/strategies/spherical/envelope_multipoint.hpp b/boost/geometry/strategies/spherical/envelope_multipoint.hpp new file mode 100644 index 0000000000..e7817370f1 --- /dev/null +++ b/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 <cstddef> +#include <algorithm> +#include <utility> +#include <vector> + +#include <boost/algorithm/minmax_element.hpp> +#include <boost/range.hpp> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/util/math.hpp> +#include <boost/geometry/util/range.hpp> + +#include <boost/geometry/geometries/helper_geometry.hpp> + +#include <boost/geometry/algorithms/detail/envelope/box.hpp> +#include <boost/geometry/algorithms/detail/envelope/initialize.hpp> +#include <boost/geometry/algorithms/detail/envelope/range.hpp> +#include <boost/geometry/algorithms/detail/expand/point.hpp> + +#include <boost/geometry/strategies/cartesian/envelope_point.hpp> +#include <boost/geometry/strategies/normalize.hpp> +#include <boost/geometry/strategies/spherical/envelope_box.hpp> +#include <boost/geometry/strategies/spherical/envelope_point.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace envelope +{ + +class spherical_multipoint +{ +private: + template <std::size_t Dim> + struct coordinate_less + { + template <typename Point> + inline bool operator()(Point const& point1, Point const& point2) const + { + return math::smaller(geometry::get<Dim>(point1), + geometry::get<Dim>(point2)); + } + }; + + template <typename Constants, typename MultiPoint, typename OutputIterator> + static inline void analyze_point_coordinates(MultiPoint const& multipoint, + bool& has_south_pole, + bool& has_north_pole, + OutputIterator oit) + { + typedef typename boost::range_value<MultiPoint>::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 <typename SortedRange, typename Value> + 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<iterator_type, iterator_type> 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<Iterator, Iterator> 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 <typename MultiPoint, typename Box> + static inline void apply(MultiPoint const& multipoint, Box& mbr) + { + typedef typename point_type<MultiPoint>::type point_type; + typedef typename coordinate_type<MultiPoint>::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<MultiPoint>::type + > constants; + + if (boost::empty(multipoint)) + { + geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(mbr); + return; + } + + geometry::detail::envelope::initialize<Box, 0, 2>::apply(mbr); + + if (boost::size(multipoint) == 1) + { + return dispatch::envelope + < + typename boost::range_value<MultiPoint>::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<point_type> points; + bool has_north_pole = false, has_south_pole = false; + + analyze_point_coordinates<constants>(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<constants>(points, + coordinate_less<0>(), + lon_min, + lon_max); + + get_min_max_latitudes<constants>(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<MultiPoint>::type + >::type helper_box_type; + + helper_box_type helper_mbr; + + geometry::set<min_corner, 0>(helper_mbr, lon_min); + geometry::set<min_corner, 1>(helper_mbr, lat_min); + geometry::set<max_corner, 0>(helper_mbr, lon_max); + geometry::set<max_corner, 1>(helper_mbr, lat_max); + + // now transform to output MBR (per index) + geometry::detail::envelope::envelope_indexed_box_on_spheroid<min_corner, 2>::apply(helper_mbr, mbr); + geometry::detail::envelope::envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr); + + // compute envelope for higher coordinates + iterator_type it = boost::begin(multipoint); + geometry::detail::envelope::envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr); + + for (++it; it != boost::end(multipoint); ++it) + { + strategy::expand::detail::point_loop + < + 2, dimension<Box>::value + >::apply(mbr, *it); + } + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename CalculationType> +struct default_strategy<multi_point_tag, spherical_equatorial_tag, CalculationType> +{ + typedef strategy::envelope::spherical_multipoint type; +}; + +template <typename CalculationType> +struct default_strategy<multi_point_tag, spherical_polar_tag, CalculationType> +{ + typedef strategy::envelope::spherical_multipoint type; +}; + +template <typename CalculationType> +struct default_strategy<multi_point_tag, geographic_tag, CalculationType> +{ + 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/boost/geometry/strategies/spherical/envelope_point.hpp b/boost/geometry/strategies/spherical/envelope_point.hpp new file mode 100644 index 0000000000..8302d7e56f --- /dev/null +++ b/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 <cstddef> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/views/detail/indexed_point_view.hpp> + +#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> +#include <boost/geometry/algorithms/detail/normalize.hpp> + +#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> + +#include <boost/geometry/strategies/cartesian/envelope_point.hpp> + +#include <boost/geometry/strategies/envelope.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace envelope +{ + +struct spherical_point +{ + template<typename Point, typename Box> + static inline void apply(Point const& point, Box& mbr) + { + Point normalized_point; + strategy::normalize::spherical_point::apply(point, normalized_point); + + typename point_type<Box>::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<min_corner, 0>(mbr, geometry::get<0>(box_point)); + geometry::set<min_corner, 1>(mbr, geometry::get<1>(box_point)); + + geometry::set<max_corner, 0>(mbr, geometry::get<0>(box_point)); + geometry::set<max_corner, 1>(mbr, geometry::get<1>(box_point)); + + typedef geometry::detail::envelope::envelope_one_point + < + 2, dimension<Point>::value + > per_corner; + per_corner::template apply<min_corner>(normalized_point, mbr); + per_corner::template apply<max_corner>(normalized_point, mbr); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename CalculationType> +struct default_strategy<point_tag, spherical_equatorial_tag, CalculationType> +{ + typedef strategy::envelope::spherical_point type; +}; + +template <typename CalculationType> +struct default_strategy<point_tag, spherical_polar_tag, CalculationType> +{ + typedef strategy::envelope::spherical_point type; +}; + +template <typename CalculationType> +struct default_strategy<point_tag, geographic_tag, CalculationType> +{ + 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/boost/geometry/strategies/spherical/envelope_segment.hpp b/boost/geometry/strategies/spherical/envelope_segment.hpp index 98f085fe73..646d6695e1 100644 --- a/boost/geometry/strategies/spherical/envelope_segment.hpp +++ b/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,406 @@ #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_SEGMENT_HPP #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_ENVELOPE_SEGMENT_HPP -#include <boost/geometry/algorithms/detail/envelope/segment.hpp> -#include <boost/geometry/algorithms/detail/normalize.hpp> + +#include <cstddef> +#include <utility> + +#include <boost/core/ignore_unused.hpp> +#include <boost/mpl/if.hpp> +#include <boost/numeric/conversion/cast.hpp> +#include <boost/type_traits/is_same.hpp> + +#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> + +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/point_type.hpp> +#include <boost/geometry/core/radian_access.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/formulas/meridian_segment.hpp> +#include <boost/geometry/formulas/vertex_latitude.hpp> + +#include <boost/geometry/geometries/helper_geometry.hpp> + +#include <boost/geometry/strategies/cartesian/envelope_segment.hpp> #include <boost/geometry/strategies/envelope.hpp> +#include <boost/geometry/strategies/normalize.hpp> #include <boost/geometry/strategies/spherical/azimuth.hpp> +#include <boost/geometry/strategies/spherical/expand_box.hpp> + +#include <boost/geometry/util/math.hpp> -namespace boost { namespace geometry +namespace boost { namespace geometry { namespace strategy { namespace envelope { -namespace strategy { namespace envelope +#ifndef DOXYGEN_NO_DETAIL +namespace detail { +template <typename CalculationType, typename CS_Tag> +struct envelope_segment_call_vertex_latitude +{ + template <typename T1, typename T2, typename Strategy> + static inline CalculationType apply(T1 const& lat1, + T2 const& alp1, + Strategy const& ) + { + return geometry::formula::vertex_latitude<CalculationType, CS_Tag> + ::apply(lat1, alp1); + } +}; + +template <typename CalculationType> +struct envelope_segment_call_vertex_latitude<CalculationType, geographic_tag> +{ + template <typename T1, typename T2, typename Strategy> + static inline CalculationType apply(T1 const& lat1, + T2 const& alp1, + Strategy const& strategy) + { + return geometry::formula::vertex_latitude<CalculationType, geographic_tag> + ::apply(lat1, alp1, strategy.model()); + } +}; + +template <typename Units, typename CS_Tag> +struct envelope_segment_convert_polar +{ + template <typename T> + static inline void pre(T & , T & ) {} + + template <typename T> + static inline void post(T & , T & ) {} +}; + +template <typename Units> +struct envelope_segment_convert_polar<Units, spherical_polar_tag> +{ + template <typename T> + static inline void pre(T & lat1, T & lat2) + { + lat1 = math::latitude_convert_ep<Units>(lat1); + lat2 = math::latitude_convert_ep<Units>(lat2); + } + + template <typename T> + static inline void post(T & lat1, T & lat2) + { + lat1 = math::latitude_convert_ep<Units>(lat1); + lat2 = math::latitude_convert_ep<Units>(lat2); + std::swap(lat1, lat2); + } +}; + +template <typename CS_Tag> +class envelope_segment_impl +{ +private: + + // degrees or radians + template <typename CalculationType> + static inline void swap(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2) + { + std::swap(lon1, lon2); + std::swap(lat1, lat2); + } + + // radians + template <typename CalculationType> + 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<CalculationType>(); + + return (a1 < a2) + ? (a1 < pi_half && pi_half < a2) + : (a1 > pi_half && pi_half > a2); + } + + // radians or degrees + template <typename Units, typename CoordinateType> + 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 <typename Units, typename CalculationType, typename Strategy> + 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<Units>(lat1); + CalculationType lat2_rad = math::as_radian<Units>(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 + <CalculationType, CS_Tag>::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<Units>(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<Units>(lat_max_rad); + + if (lat2 < lat_max) + { + lat2 = lat_max; + } + } + } + } + + template <typename Units, typename CalculationType> + 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<Units>(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<Box>::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<box_coordinate_type>(lon1)); + + geometry::set + < + min_corner, 1 + >(helper_mbr, boost::numeric_cast<box_coordinate_type>(lat1)); + + geometry::set + < + max_corner, 0 + >(helper_mbr, boost::numeric_cast<box_coordinate_type>(lon2)); + + geometry::set + < + max_corner, 1 + >(helper_mbr, boost::numeric_cast<box_coordinate_type>(lat2)); + + geometry::detail::envelope::transform_units(helper_mbr, mbr); + } + + + template <typename Units, typename CalculationType, typename Strategy> + static inline void apply(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2, + Strategy const& strategy) + { + special_cases<Units>(lon1, lat1, lon2, lat2); + + CalculationType lon1_rad = math::as_radian<Units>(lon1); + CalculationType lat1_rad = math::as_radian<Units>(lat1); + CalculationType lon2_rad = math::as_radian<Units>(lon2); + CalculationType lat2_rad = math::as_radian<Units>(lat2); + CalculationType alp1, alp2; + strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, alp1, alp2); + + compute_box_corners<Units>(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<Units, typename cs_tag<Box>::type> convert_polar; + + convert_polar::pre(lat1, lat2); + + apply<Units>(lon1, lat1, lon2, lat2, strategy); + + convert_polar::post(lat1, lat2); + + create_box<Units>(lon1, lat1, lon2, lat2, mbr); + } + +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + template < typename CalculationType = void > class spherical_segment { -public : - - inline spherical_segment() - {} +public: + typedef strategy::expand::spherical_box box_expand_strategy_type; + static inline box_expand_strategy_type get_box_expand_strategy() + { + return box_expand_strategy_type(); + } - template <typename Point1, typename Point2, typename Box> - inline void - apply(Point1 const& point1, Point2 const& point2, Box& box) const + template <typename Point, typename Box> + static inline void apply(Point const& point1, Point const& point2, + Box& box) { - Point1 p1_normalized = detail::return_normalized<Point1>(point1); - Point2 p2_normalized = detail::return_normalized<Point2>(point2); + 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<CalculationType> azimuth_spherical; - typedef typename coordinate_system<Point1>::type::units units_type; + typedef typename geometry::detail::cs_angular_units<Point>::type units_type; - geometry::detail::envelope::envelope_segment_impl<spherical_equatorial_tag> - ::template apply<units_type>(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<units_type>(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<Point>::value + >::apply(point1, point2, box); } }; @@ -61,14 +420,14 @@ namespace services { template <typename CalculationType> -struct default_strategy<spherical_equatorial_tag, CalculationType> +struct default_strategy<segment_tag, spherical_equatorial_tag, CalculationType> { typedef strategy::envelope::spherical_segment<CalculationType> type; }; template <typename CalculationType> -struct default_strategy<spherical_polar_tag, CalculationType> +struct default_strategy<segment_tag, spherical_polar_tag, CalculationType> { typedef strategy::envelope::spherical_segment<CalculationType> type; }; diff --git a/boost/geometry/strategies/spherical/expand_box.hpp b/boost/geometry/strategies/spherical/expand_box.hpp new file mode 100644 index 0000000000..e3801861b2 --- /dev/null +++ b/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 <cstddef> +#include <algorithm> + +#include <boost/geometry/algorithms/detail/envelope/box.hpp> +#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp> + +#include <boost/geometry/strategies/expand.hpp> +#include <boost/geometry/strategies/spherical/envelope_box.hpp> + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +struct box_on_spheroid +{ + template <typename BoxOut, typename BoxIn> + 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 <typename CalculationType> +struct default_strategy<box_tag, spherical_equatorial_tag, CalculationType> +{ + typedef spherical_box type; +}; + +template <typename CalculationType> +struct default_strategy<box_tag, spherical_polar_tag, CalculationType> +{ + typedef spherical_box type; +}; + +template <typename CalculationType> +struct default_strategy<box_tag, geographic_tag, CalculationType> +{ + 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/boost/geometry/strategies/spherical/expand_point.hpp b/boost/geometry/strategies/spherical/expand_point.hpp new file mode 100644 index 0000000000..b2cff013ae --- /dev/null +++ b/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 <cstddef> +#include <algorithm> +#include <functional> + +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_same.hpp> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/util/is_inverse_spheroidal_coordinates.hpp> +#include <boost/geometry/util/math.hpp> +#include <boost/geometry/util/select_coordinate_type.hpp> + +#include <boost/geometry/algorithms/detail/normalize.hpp> +#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp> + +#include <boost/geometry/strategies/expand.hpp> +#include <boost/geometry/strategies/cartesian/expand_point.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +// implementation for the spherical and geographic coordinate systems +template <std::size_t DimensionCount, bool IsEquatorial> +struct point_loop_on_spheroid +{ + template <typename Box, typename Point> + static inline void apply(Box& box, Point const& point) + { + typedef typename point_type<Box>::type box_point_type; + typedef typename coordinate_type<Box>::type box_coordinate_type; + typedef typename geometry::detail::cs_angular_units<Box>::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<min_corner, 0>(box, geometry::get_as_radian<0>(p_normalized)); + geometry::set_from_radian<min_corner, 1>(box, geometry::get_as_radian<1>(p_normalized)); + geometry::set_from_radian<max_corner, 0>(box, geometry::get_as_radian<0>(p_normalized)); + geometry::set_from_radian<max_corner, 1>(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<Box>::type + b_lon_min = geometry::get<min_corner, 0>(box), + b_lat_min = geometry::get<min_corner, 1>(box), + b_lon_max = geometry::get<max_corner, 0>(box), + b_lat_max = geometry::get<max_corner, 1>(box); + + if (math::is_latitude_pole<units_type, IsEquatorial>(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<min_corner, 1>(box, (std::min)(p_lat, b_lat_min)); + geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max)); + return; + } + + if (math::equals(b_lat_min, b_lat_max) + && math::is_latitude_pole<units_type, IsEquatorial>(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<min_corner, 0>(box, p_lon); + geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min)); + geometry::set<max_corner, 0>(box, p_lon); + geometry::set<max_corner, 1>(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<min_corner, 0>(box, b_lon_min); + geometry::set<min_corner, 1>(box, b_lat_min); + geometry::set<max_corner, 0>(box, b_lon_max); + geometry::set<max_corner, 1>(box, b_lat_max); + } + + point_loop + < + 2, DimensionCount + >::apply(box, point); + } +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +struct spherical_point +{ + template <typename Box, typename Point> + static void apply(Box & box, Point const& point) + { + expand::detail::point_loop_on_spheroid + < + dimension<Point>::value, + ! boost::is_same<typename cs_tag<Point>::type, spherical_polar_tag>::value + >::apply(box, point); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename CalculationType> +struct default_strategy<point_tag, spherical_equatorial_tag, CalculationType> +{ + typedef spherical_point type; +}; + +template <typename CalculationType> +struct default_strategy<point_tag, spherical_polar_tag, CalculationType> +{ + typedef spherical_point type; +}; + +template <typename CalculationType> +struct default_strategy<point_tag, geographic_tag, CalculationType> +{ + 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/boost/geometry/strategies/spherical/expand_segment.hpp b/boost/geometry/strategies/spherical/expand_segment.hpp new file mode 100644 index 0000000000..75f4698ff0 --- /dev/null +++ b/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 <cstddef> +#include <functional> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/util/select_coordinate_type.hpp> + +#include <boost/geometry/algorithms/detail/envelope/box.hpp> +#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp> +#include <boost/geometry/algorithms/detail/envelope/segment.hpp> + +#include <boost/geometry/strategies/expand.hpp> +#include <boost/geometry/strategies/spherical/envelope_segment.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace expand +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +struct segment_on_spheroid +{ + template <typename Box, typename Segment, typename EnvelopeStrategy> + static inline void apply(Box& box, Segment const& segment, EnvelopeStrategy const& strategy) + { + Box mbrs[2]; + + // compute the envelope of the segment + typename point_type<Segment>::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<Segment>::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 <typename Box, typename Segment> + static inline void apply(Box& box, Segment const& segment) + { + detail::segment_on_spheroid::apply(box, segment, + strategy::envelope::spherical_segment<CalculationType>()); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + +namespace services +{ + +template <typename CalculationType> +struct default_strategy<segment_tag, spherical_equatorial_tag, CalculationType> +{ + typedef spherical_segment<CalculationType> type; +}; + +template <typename CalculationType> +struct default_strategy<segment_tag, spherical_polar_tag, CalculationType> +{ + typedef spherical_segment<CalculationType> 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/boost/geometry/strategies/spherical/intersection.hpp b/boost/geometry/strategies/spherical/intersection.hpp index 2bdc8b51ab..4cf4fca113 100644 --- a/boost/geometry/strategies/spherical/intersection.hpp +++ b/boost/geometry/strategies/spherical/intersection.hpp @@ -2,7 +2,7 @@ // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// Copyright (c) 2016-2018, Oracle and/or its affiliates. +// Copyright (c) 2016-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -41,8 +41,12 @@ #include <boost/geometry/strategies/side.hpp> #include <boost/geometry/strategies/side_info.hpp> #include <boost/geometry/strategies/spherical/area.hpp> +#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp> +#include <boost/geometry/strategies/spherical/disjoint_segment_box.hpp> #include <boost/geometry/strategies/spherical/distance_haversine.hpp> -#include <boost/geometry/strategies/spherical/envelope_segment.hpp> +#include <boost/geometry/strategies/spherical/envelope.hpp> +#include <boost/geometry/strategies/spherical/expand_box.hpp> +#include <boost/geometry/strategies/spherical/point_in_point.hpp> #include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp> #include <boost/geometry/strategies/spherical/ssf.hpp> #include <boost/geometry/strategies/within.hpp> @@ -149,7 +153,7 @@ struct ecef_segments return strategy_type(); } - typedef envelope::spherical_segment<CalculationType> + typedef envelope::spherical<CalculationType> envelope_strategy_type; static inline envelope_strategy_type get_envelope_strategy() @@ -157,6 +161,45 @@ struct ecef_segments return envelope_strategy_type(); } + typedef expand::spherical_segment<CalculationType> + 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 disjoint::segment_box_spherical disjoint_segment_box_strategy_type; + + static inline disjoint_segment_box_strategy_type get_disjoint_segment_box_strategy() + { + return disjoint_segment_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 +295,6 @@ struct ecef_segments BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) ); // 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 +687,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 +863,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 +890,13 @@ private: : ca1 < cb2 ? 4 : 2 ); } + + template <typename Point1, typename Point2> + 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 +968,7 @@ struct spherical_segments_calc_policy multiply_value(ip2, coord_t(-1)); return true; - } + } }; diff --git a/boost/geometry/strategies/spherical/line_interpolate.hpp b/boost/geometry/strategies/spherical/line_interpolate.hpp new file mode 100644 index 0000000000..2d602c0e06 --- /dev/null +++ b/boost/geometry/strategies/spherical/line_interpolate.hpp @@ -0,0 +1,123 @@ +// Boost.Geometry + +// Copyright (c) 2018, Oracle and/or its affiliates. + +// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_LINE_INTERPOLATE_HPP +#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_LINE_INTERPOLATE_HPP + +#include <boost/geometry/core/assert.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/radian_access.hpp> +#include <boost/geometry/formulas/interpolate_point_spherical.hpp> +#include <boost/geometry/srs/spheroid.hpp> +#include <boost/geometry/strategies/line_interpolate.hpp> +#include <boost/geometry/strategies/spherical/distance_haversine.hpp> +#include <boost/geometry/util/select_calculation_type.hpp> + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace line_interpolate +{ + + +/*! +\brief Interpolate point on a spherical segment. +\ingroup strategies +\tparam CalculationType \tparam_calculation +\tparam DistanceStrategy The underlying point-point distance strategy + +\qbk{ +[heading See also] +\* [link geometry.reference.algorithms.line_interpolate.line_interpolate_4_with_strategy line_interpolate (with strategy)] +} + + */ +template +< + typename CalculationType = void, + typename DistanceStrategy = distance::haversine<double, CalculationType> +> +class spherical +{ +public: + + typedef typename DistanceStrategy::radius_type radius_type; + + inline spherical() + {} + + explicit inline spherical(typename DistanceStrategy::radius_type const& r) + : m_strategy(r) + {} + + inline spherical(DistanceStrategy const& s) + : m_strategy(s) + {} + + // point-point strategy getters + struct distance_pp_strategy + { + typedef DistanceStrategy type; + }; + + inline typename distance_pp_strategy::type get_distance_pp_strategy() const + { + return m_strategy; + } + + template <typename Point, typename Fraction, typename Distance> + inline void apply(Point const& p0, + Point const& p1, + Fraction const& fraction, + Point & p, + Distance const&) const + { + typedef typename select_calculation_type_alt + < + CalculationType, + Point + >::type calc_t; + + formula::interpolate_point_spherical<calc_t> formula; + + calc_t angle01; + formula.compute_angle(p0, p1, angle01); + formula.compute_axis(p0, angle01); + + calc_t a = angle01 * fraction; + formula.compute_point(a, p); + } +private : + DistanceStrategy m_strategy; +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template <> +struct default_strategy<spherical_equatorial_tag> +{ + typedef strategy::line_interpolate::spherical<> type; +}; + + +} // namespace services +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::line_interpolate + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_LINE_INTERPOLATE_HPP diff --git a/boost/geometry/strategies/spherical/point_in_point.hpp b/boost/geometry/strategies/spherical/point_in_point.hpp new file mode 100644 index 0000000000..372e9cfaca --- /dev/null +++ b/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 <cstddef> + +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/radian_access.hpp> +#include <boost/geometry/core/coordinate_dimension.hpp> +#include <boost/geometry/core/coordinate_system.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/tags.hpp> + +#include <boost/geometry/algorithms/detail/normalize.hpp> +#include <boost/geometry/algorithms/dispatch/disjoint.hpp> +#include <boost/geometry/algorithms/transform.hpp> + +#include <boost/geometry/geometries/helper_geometry.hpp> + +#include <boost/geometry/strategies/cartesian/point_in_point.hpp> +#include <boost/geometry/strategies/covered_by.hpp> +#include <boost/geometry/strategies/strategy_transform.hpp> +#include <boost/geometry/strategies/within.hpp> + +#include <boost/geometry/util/math.hpp> +#include <boost/geometry/util/select_most_precise.hpp> + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace within +{ + +class point_point_on_spheroid +{ +private: + template <typename Point1, typename Point2, bool SameUnits> + struct are_same_points + { + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + typedef typename helper_geometry<Point1>::type helper_point_type1; + typedef typename helper_geometry<Point2>::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<Point1>::value + >::apply(point1_normalized, point2_normalized); + } + }; + + template <typename Point1, typename Point2> + struct are_same_points<Point1, Point2, false> // points have different units + { + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + typedef typename geometry::select_most_precise + < + typename fp_coordinate_type<Point1>::type, + typename fp_coordinate_type<Point2>::type + >::type calculation_type; + + typename helper_geometry + < + Point1, calculation_type, radian + >::type helper_point1, helper_point2; + + Point1 point1_normalized = return_normalized<Point1>(point1); + Point2 point2_normalized = return_normalized<Point2>(point2); + + geometry::transform(point1_normalized, helper_point1); + geometry::transform(point2_normalized, helper_point2); + + return point_point_generic + < + 0, dimension<Point1>::value + >::apply(helper_point1, helper_point2); + } + }; + +public: + template <typename Point1, typename Point2> + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + return are_same_points + < + Point1, + Point2, + boost::is_same + < + typename detail::cs_angular_units<Point1>::type, + typename detail::cs_angular_units<Point2>::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 <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2> +struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, spherical_tag, spherical_tag> +{ + 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 <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2> +struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, spherical_tag, spherical_tag> +{ + 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/boost/geometry/strategies/spherical/point_in_poly_winding.hpp b/boost/geometry/strategies/spherical/point_in_poly_winding.hpp index c942cbe460..c283b53335 100644 --- a/boost/geometry/strategies/spherical/point_in_poly_winding.hpp +++ b/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 <boost/geometry/util/select_calculation_type.hpp> #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> +#include <boost/geometry/strategies/cartesian/point_in_box.hpp> #include <boost/geometry/strategies/covered_by.hpp> #include <boost/geometry/strategies/side.hpp> +#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp> #include <boost/geometry/strategies/spherical/ssf.hpp> #include <boost/geometry/strategies/within.hpp> @@ -63,7 +65,7 @@ class spherical_winding_base CalculationType >::type calculation_type; - typedef typename coordinate_system<Point>::type::units units_t; + typedef typename geometry::detail::cs_angular_units<Point>::type units_t; typedef math::detail::constants_on_spheroid<calculation_type, units_t> 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<PointOfSegment>::type scoord_t; - typedef typename coordinate_system<PointOfSegment>::type::units units_t; + typedef typename geometry::detail::cs_angular_units<PointOfSegment>::type units_t; if (math::equals(get<1>(point), get<1>(se))) { diff --git a/boost/geometry/strategies/spherical/ssf.hpp b/boost/geometry/strategies/spherical/ssf.hpp index 03f5428ede..18c547ced8 100644 --- a/boost/geometry/strategies/spherical/ssf.hpp +++ b/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 <boost/geometry/strategies/side.hpp> #include <boost/geometry/strategies/spherical/disjoint_segment_box.hpp> -#include <boost/geometry/strategies/spherical/envelope_segment.hpp> +#include <boost/geometry/strategies/spherical/envelope.hpp> //#include <boost/geometry/strategies/concepts/side_concept.hpp> +#include <boost/geometry/strategies/spherical/point_in_point.hpp> namespace boost { namespace geometry @@ -84,7 +85,7 @@ class spherical_side_formula { public : - typedef strategy::envelope::spherical_segment<CalculationType> envelope_strategy_type; + typedef strategy::envelope::spherical<CalculationType> 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 <typename P1, typename P2, typename P> static inline int apply(P1 const& p1, P2 const& p2, P const& p) { diff --git a/boost/geometry/strategies/strategies.hpp b/boost/geometry/strategies/strategies.hpp index b6430692f4..026214173f 100644 --- a/boost/geometry/strategies/strategies.hpp +++ b/boost/geometry/strategies/strategies.hpp @@ -70,6 +70,7 @@ #include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp> #include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp> #include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp> +#include <boost/geometry/strategies/cartesian/line_interpolate.hpp> #include <boost/geometry/strategies/cartesian/side_by_triangle.hpp> #include <boost/geometry/strategies/spherical/area.hpp> @@ -85,10 +86,12 @@ #include <boost/geometry/strategies/spherical/envelope_segment.hpp> #include <boost/geometry/strategies/spherical/intersection.hpp> #include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp> +#include <boost/geometry/strategies/spherical/line_interpolate.hpp> #include <boost/geometry/strategies/spherical/ssf.hpp> #include <boost/geometry/strategies/geographic/area.hpp> #include <boost/geometry/strategies/geographic/azimuth.hpp> +#include <boost/geometry/strategies/geographic/buffer_point_circle.hpp> #include <boost/geometry/strategies/geographic/densify.hpp> #include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp> #include <boost/geometry/strategies/geographic/distance.hpp> @@ -103,6 +106,7 @@ #include <boost/geometry/strategies/geographic/intersection.hpp> //#include <boost/geometry/strategies/geographic/intersection_elliptic.hpp> #include <boost/geometry/strategies/geographic/point_in_poly_winding.hpp> +#include <boost/geometry/strategies/geographic/line_interpolate.hpp> #include <boost/geometry/strategies/geographic/side.hpp> #include <boost/geometry/strategies/geographic/side_andoyer.hpp> #include <boost/geometry/strategies/geographic/side_thomas.hpp> diff --git a/boost/geometry/util/calculation_type.hpp b/boost/geometry/util/calculation_type.hpp index 18eac4fbb7..cff4b9421e 100644 --- a/boost/geometry/util/calculation_type.hpp +++ b/boost/geometry/util/calculation_type.hpp @@ -4,6 +4,11 @@ // Copyright (c) 2012 Bruno Lalande, Paris, France. // Copyright (c) 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 + // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -13,6 +18,7 @@ #include <boost/config.hpp> #include <boost/mpl/if.hpp> +#include <boost/static_assert.hpp> #include <boost/type_traits/is_floating_point.hpp> #include <boost/type_traits/is_fundamental.hpp> #include <boost/type_traits/is_void.hpp> diff --git a/boost/geometry/util/combine_if.hpp b/boost/geometry/util/combine_if.hpp index 5d94c34461..11050e4e55 100644 --- a/boost/geometry/util/combine_if.hpp +++ b/boost/geometry/util/combine_if.hpp @@ -2,10 +2,11 @@ // Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. -// 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. @@ -17,13 +18,13 @@ #ifndef BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP #define BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP +#include <boost/mpl/bind.hpp> #include <boost/mpl/fold.hpp> #include <boost/mpl/if.hpp> -#include <boost/mpl/bind.hpp> -#include <boost/mpl/set.hpp> #include <boost/mpl/insert.hpp> +#include <boost/mpl/pair.hpp> #include <boost/mpl/placeholders.hpp> - +#include <boost/mpl/set.hpp> namespace boost { namespace geometry { diff --git a/boost/geometry/util/is_inverse_spheroidal_coordinates.hpp b/boost/geometry/util/is_inverse_spheroidal_coordinates.hpp index d67251254d..59746653a6 100644 --- a/boost/geometry/util/is_inverse_spheroidal_coordinates.hpp +++ b/boost/geometry/util/is_inverse_spheroidal_coordinates.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 @@ -11,6 +12,10 @@ #ifndef BOOST_GEOMETRY_UTIL_IS_INVERSE_SPHEROIDAL_COORDINATES_HPP #define BOOST_GEOMETRY_UTIL_IS_INVERSE_SPHEROIDAL_COORDINATES_HPP +#include <boost/geometry/core/access.hpp> +#include <boost/geometry/core/coordinate_type.hpp> +#include <boost/geometry/core/point_type.hpp> + #include <boost/geometry/util/math.hpp> namespace boost { namespace geometry diff --git a/boost/geometry/util/series_expansion.hpp b/boost/geometry/util/series_expansion.hpp index d0b5e36567..d279e218b4 100644 --- a/boost/geometry/util/series_expansion.hpp +++ b/boost/geometry/util/series_expansion.hpp @@ -633,18 +633,19 @@ namespace boost { namespace geometry { namespace series_expansion { inline void evaluate_coeffs_C3(Coeffs1 &coeffs1, Coeffs2 &coeffs2, CT const& eps) { CT mult = 1; - int offset = 1; + int offset = 0; // l is the index of C3[l]. for (size_t l = 1; l < Coeffs1::static_size; ++l) { // Order of polynomial in eps. - int m = Coeffs1::static_size - l - 1; + int m = Coeffs1::static_size - l; mult *= eps; - coeffs1[l] = mult * math::polyval(coeffs2.begin(), coeffs2.begin() + offset, eps); + coeffs1[l] = mult * math::horner_evaluate(eps, coeffs2.begin() + offset, + coeffs2.begin() + offset + m); - offset += m + 1; + offset += m; } // Post condition: offset == coeffs_C3_size } diff --git a/boost/geometry/views/detail/boundary_view/implementation.hpp b/boost/geometry/views/detail/boundary_view/implementation.hpp index 971a6fe002..fb5c119fbd 100644 --- a/boost/geometry/views/detail/boundary_view/implementation.hpp +++ b/boost/geometry/views/detail/boundary_view/implementation.hpp @@ -1,8 +1,9 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// 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 @@ -23,7 +24,6 @@ #include <boost/iterator/iterator_categories.hpp> #include <boost/mpl/assert.hpp> #include <boost/mpl/if.hpp> -#include <boost/range.hpp> #include <boost/type_traits/is_const.hpp> #include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/remove_reference.hpp> @@ -40,6 +40,7 @@ #include <boost/geometry/util/range.hpp> #include <boost/geometry/views/closeable_view.hpp> +#include <boost/geometry/views/detail/boundary_view/interface.hpp> #include <boost/geometry/algorithms/num_interior_rings.hpp> |