diff options
Diffstat (limited to 'boost/geometry/strategies/cartesian/box_in_box.hpp')
-rw-r--r-- | boost/geometry/strategies/cartesian/box_in_box.hpp | 123 |
1 files changed, 117 insertions, 6 deletions
diff --git a/boost/geometry/strategies/cartesian/box_in_box.hpp b/boost/geometry/strategies/cartesian/box_in_box.hpp index 56aef9e4df..fe77de9e2d 100644 --- a/boost/geometry/strategies/cartesian/box_in_box.hpp +++ b/boost/geometry/strategies/cartesian/box_in_box.hpp @@ -5,8 +5,8 @@ // Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2016, 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_dimension.hpp> #include <boost/geometry/strategies/covered_by.hpp> #include <boost/geometry/strategies/within.hpp> +#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> namespace boost { namespace geometry { namespace strategy @@ -34,6 +35,8 @@ namespace boost { namespace geometry { namespace strategy namespace within { + +template <typename Geometry, std::size_t Dimension, typename CSTag> struct box_within_range { template <typename BoxContainedValue, typename BoxContainingValue> @@ -48,6 +51,7 @@ struct box_within_range }; +template <typename Geometry, std::size_t Dimension, typename CSTag> struct box_covered_by_range { template <typename BoxContainedValue, typename BoxContainingValue> @@ -61,9 +65,84 @@ struct box_covered_by_range }; +struct box_within_longitude_check +{ + template <typename CalcT> + static inline bool apply(CalcT const& diff_ed) + { + return diff_ed > CalcT(0); + } +}; + +struct box_covered_by_longitude_check +{ + template <typename CalcT> + static inline bool apply(CalcT const&) + { + return true; + } +}; + +template <typename Geometry, + typename InteriorCheck> +struct box_longitude_range +{ + template <typename BoxContainedValue, typename BoxContainingValue> + static inline bool apply(BoxContainedValue const& bed_min, + BoxContainedValue const& bed_max, + BoxContainingValue const& bing_min, + BoxContainingValue const& bing_max) + { + typedef typename select_most_precise + < + BoxContainedValue, + BoxContainingValue + >::type calc_t; + typedef typename coordinate_system<Geometry>::type::units units_t; + typedef math::detail::constants_on_spheroid<calc_t, units_t> constants; + + // min <= max <=> diff >= 0 + calc_t const diff_ed = bed_max - bed_min; + calc_t const diff_ing = bing_max - bing_min; + + // if containing covers the whole globe it contains all + if (diff_ing >= constants::period()) + { + return true; + } + + // if containing is smaller it cannot contain + // and check interior (within vs covered_by) + if (diff_ing < diff_ed || ! InteriorCheck::apply(diff_ed)) + { + return false; + } + + // calculate positive longitude translation with bing_min as origin + calc_t const diff_min = math::longitude_distance_unsigned<units_t>(bing_min, bed_min); + + // max of contained translated into the containing origin must be lesser than max of containing + return bing_min + diff_min + diff_ed <= bing_max; + } +}; + + +// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag +template <typename Geometry> +struct box_within_range<Geometry, 0, spherical_tag> + : box_longitude_range<Geometry, box_within_longitude_check> +{}; + + +template <typename Geometry> +struct box_covered_by_range<Geometry, 0, spherical_tag> + : box_longitude_range<Geometry, box_covered_by_longitude_check> +{}; + + template < - typename SubStrategy, + template <typename, std::size_t, typename> class SubStrategy, typename Box1, typename Box2, std::size_t Dimension, @@ -74,8 +153,9 @@ struct relate_box_box_loop static inline bool apply(Box1 const& b_contained, Box2 const& b_containing) { assert_dimension_equal<Box1, Box2>(); + typedef typename tag_cast<typename cs_tag<Box1>::type, spherical_tag>::type cs_tag_t; - if (! SubStrategy::apply( + if (! SubStrategy<Box1, Dimension, cs_tag_t>::apply( get<min_corner, Dimension>(b_contained), get<max_corner, Dimension>(b_contained), get<min_corner, Dimension>(b_containing), @@ -97,7 +177,7 @@ struct relate_box_box_loop template < - typename SubStrategy, + template <typename, std::size_t, typename> class SubStrategy, typename Box1, typename Box2, std::size_t DimensionCount @@ -114,7 +194,7 @@ template < typename Box1, typename Box2, - typename SubStrategy = box_within_range + template <typename, std::size_t, typename> class SubStrategy = box_within_range > struct box_in_box { @@ -150,6 +230,19 @@ struct default_strategy typedef within::box_in_box<BoxContained, BoxContaining> type; }; +// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag +template <typename BoxContained, typename BoxContaining> +struct default_strategy + < + box_tag, box_tag, + box_tag, areal_tag, + spherical_tag, spherical_tag, + BoxContained, BoxContaining + > +{ + typedef within::box_in_box<BoxContained, BoxContaining> type; +}; + }} // namespace within::services @@ -172,6 +265,24 @@ struct default_strategy > type; }; +// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag +template <typename BoxContained, typename BoxContaining> +struct default_strategy + < + box_tag, box_tag, + box_tag, areal_tag, + spherical_tag, spherical_tag, + BoxContained, BoxContaining + > +{ + typedef within::box_in_box + < + BoxContained, BoxContaining, + within::box_covered_by_range + > type; +}; + + }} // namespace covered_by::services |