summaryrefslogtreecommitdiff
path: root/boost/geometry/strategies/cartesian/box_in_box.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/strategies/cartesian/box_in_box.hpp')
-rw-r--r--boost/geometry/strategies/cartesian/box_in_box.hpp123
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