From d04acacc74b13c4f192b4585d035b5fd44ec0016 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 8 Mar 2016 04:38:48 +0100 Subject: [PATCH] [strategies] Support non-cartesian CSes in box_in_box strategy. --- .../strategies/cartesian/box_in_box.hpp | 163 +++++++++++++++++- 1 file changed, 159 insertions(+), 4 deletions(-) diff --git a/include/boost/geometry/strategies/cartesian/box_in_box.hpp b/include/boost/geometry/strategies/cartesian/box_in_box.hpp index 56aef9e4d..bc7c6580f 100644 --- a/include/boost/geometry/strategies/cartesian/box_in_box.hpp +++ b/include/boost/geometry/strategies/cartesian/box_in_box.hpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace boost { namespace geometry { namespace strategy @@ -34,6 +35,8 @@ namespace boost { namespace geometry { namespace strategy namespace within { + +template struct box_within_range { template @@ -48,6 +51,7 @@ struct box_within_range }; +template struct box_covered_by_range { template @@ -61,9 +65,103 @@ struct box_covered_by_range }; +// spherical_equatorial_tag and spherical_polar_tag is casted to spherical_tag +template +struct box_within_range +{ + template + 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::type::units units_t; + typedef math::detail::constants_on_spheroid constants; + + // min <= max <=> diff >= 0 + calc_t diff_ed = bed_max - bed_min; + calc_t diff_ing = bing_max - bing_min; + // if containing is smaller it cannot contain + // or interiors doesn't overlap (no interior in contained) + if (diff_ing < diff_ed || diff_ed == 0) + return false; + + // if containing covers the whole globe it contains all + if (!math::smaller(diff_ing, constants::period())) // >= period + return true; + + // calculate positive longitude translation with bing_min as origin + calc_t const c0 = 0; + calc_t diff_min = bed_min - bing_min; + math::normalize_longitude(diff_min); + if (diff_min < c0) // [-180, 180] -> [0, 360] + diff_min += constants::period(); + + return bing_min + diff_min + diff_ed <= bing_max; + } +}; + + +template +struct box_covered_by_range +{ + template + 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::type::units units_t; + typedef math::detail::constants_on_spheroid constants; + + // min <= max <=> diff >= 0 + calc_t diff_ed = bed_max - bed_min; + calc_t diff_ing = bing_max - bing_min; + // if containing is smaller it cannot contain + if (diff_ing < diff_ed) + return false; + + // if containing covers the whole globe it contains all + if (!math::smaller(diff_ing, constants::period())) // >= period + return true; + + // calculate positive longitude translation with bing_min as origin + calc_t const c0 = 0; + calc_t diff_min = bed_min - bing_min; + math::normalize_longitude(diff_min); + if (diff_min < c0) // [-180, 180] -> [0, 360] + diff_min += constants::period(); + + return bing_min + diff_min + diff_ed <= bing_max; + } +}; + + +template +struct box_within_range + : box_within_range +{}; + + +template +struct box_covered_by_range + : box_covered_by_range +{}; + + template < - typename SubStrategy, + template class SubStrategy, typename Box1, typename Box2, std::size_t Dimension, @@ -74,8 +172,9 @@ struct relate_box_box_loop static inline bool apply(Box1 const& b_contained, Box2 const& b_containing) { assert_dimension_equal(); + typedef typename tag_cast::type, spherical_tag>::type cs_tag_t; - if (! SubStrategy::apply( + if (! SubStrategy::apply( get(b_contained), get(b_contained), get(b_containing), @@ -97,7 +196,7 @@ struct relate_box_box_loop template < - typename SubStrategy, + template class SubStrategy, typename Box1, typename Box2, std::size_t DimensionCount @@ -114,7 +213,7 @@ template < typename Box1, typename Box2, - typename SubStrategy = box_within_range + template class SubStrategy = box_within_range > struct box_in_box { @@ -150,6 +249,30 @@ struct default_strategy typedef within::box_in_box type; }; +template +struct default_strategy + < + box_tag, box_tag, + box_tag, areal_tag, + spherical_tag, spherical_tag, + BoxContained, BoxContaining + > +{ + typedef within::box_in_box type; +}; + +template +struct default_strategy + < + box_tag, box_tag, + box_tag, areal_tag, + geographic_tag, geographic_tag, + BoxContained, BoxContaining + > +{ + typedef within::box_in_box type; +}; + }} // namespace within::services @@ -172,6 +295,38 @@ struct default_strategy > type; }; +template +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; +}; + +template +struct default_strategy + < + box_tag, box_tag, + box_tag, areal_tag, + geographic_tag, geographic_tag, + BoxContained, BoxContaining + > +{ + typedef within::box_in_box + < + BoxContained, BoxContaining, + within::box_covered_by_range + > type; +}; + }} // namespace covered_by::services