1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
6 // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
8 // This file was modified by Oracle on 2015, 2016.
9 // Modifications copyright (c) 2016, Oracle and/or its affiliates.
11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16 // Use, modification and distribution is subject to the Boost Software License,
17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18 // http://www.boost.org/LICENSE_1_0.txt)
20 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
21 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
24 #include <boost/geometry/core/access.hpp>
25 #include <boost/geometry/core/coordinate_dimension.hpp>
26 #include <boost/geometry/strategies/covered_by.hpp>
27 #include <boost/geometry/strategies/within.hpp>
28 #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
31 namespace boost { namespace geometry { namespace strategy
39 template <typename Geometry, std::size_t Dimension, typename CSTag>
40 struct box_within_range
42 template <typename BoxContainedValue, typename BoxContainingValue>
43 static inline bool apply(BoxContainedValue const& bed_min,
44 BoxContainedValue const& bed_max,
45 BoxContainingValue const& bing_min,
46 BoxContainingValue const& bing_max)
48 return bing_min <= bed_min && bed_max <= bing_max // contained in containing
49 && bed_min < bed_max; // interiors overlap
54 template <typename Geometry, std::size_t Dimension, typename CSTag>
55 struct box_covered_by_range
57 template <typename BoxContainedValue, typename BoxContainingValue>
58 static inline bool apply(BoxContainedValue const& bed_min,
59 BoxContainedValue const& bed_max,
60 BoxContainingValue const& bing_min,
61 BoxContainingValue const& bing_max)
63 return bed_min >= bing_min && bed_max <= bing_max;
68 struct box_within_longitude_check
70 template <typename CalcT>
71 static inline bool apply(CalcT const& diff_ed)
73 return diff_ed > CalcT(0);
77 struct box_covered_by_longitude_check
79 template <typename CalcT>
80 static inline bool apply(CalcT const&)
86 template <typename Geometry,
87 typename InteriorCheck>
88 struct box_longitude_range
90 template <typename BoxContainedValue, typename BoxContainingValue>
91 static inline bool apply(BoxContainedValue const& bed_min,
92 BoxContainedValue const& bed_max,
93 BoxContainingValue const& bing_min,
94 BoxContainingValue const& bing_max)
96 typedef typename select_most_precise
101 typedef typename coordinate_system<Geometry>::type::units units_t;
102 typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
104 // min <= max <=> diff >= 0
105 calc_t const diff_ed = bed_max - bed_min;
106 calc_t const diff_ing = bing_max - bing_min;
108 // if containing covers the whole globe it contains all
109 if (diff_ing >= constants::period())
114 // if containing is smaller it cannot contain
115 // and check interior (within vs covered_by)
116 if (diff_ing < diff_ed || ! InteriorCheck::apply(diff_ed))
121 // calculate positive longitude translation with bing_min as origin
122 calc_t const diff_min = math::longitude_distance_unsigned<units_t>(bing_min, bed_min);
124 // max of contained translated into the containing origin must be lesser than max of containing
125 return bing_min + diff_min + diff_ed <= bing_max;
130 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
131 template <typename Geometry>
132 struct box_within_range<Geometry, 0, spherical_tag>
133 : box_longitude_range<Geometry, box_within_longitude_check>
137 template <typename Geometry>
138 struct box_covered_by_range<Geometry, 0, spherical_tag>
139 : box_longitude_range<Geometry, box_covered_by_longitude_check>
145 template <typename, std::size_t, typename> class SubStrategy,
148 std::size_t Dimension,
149 std::size_t DimensionCount
151 struct relate_box_box_loop
153 static inline bool apply(Box1 const& b_contained, Box2 const& b_containing)
155 assert_dimension_equal<Box1, Box2>();
156 typedef typename tag_cast<typename cs_tag<Box1>::type, spherical_tag>::type cs_tag_t;
158 if (! SubStrategy<Box1, Dimension, cs_tag_t>::apply(
159 get<min_corner, Dimension>(b_contained),
160 get<max_corner, Dimension>(b_contained),
161 get<min_corner, Dimension>(b_containing),
162 get<max_corner, Dimension>(b_containing)
169 return relate_box_box_loop
173 Dimension + 1, DimensionCount
174 >::apply(b_contained, b_containing);
180 template <typename, std::size_t, typename> class SubStrategy,
183 std::size_t DimensionCount
185 struct relate_box_box_loop<SubStrategy, Box1, Box2, DimensionCount, DimensionCount>
187 static inline bool apply(Box1 const& , Box2 const& )
197 template <typename, std::size_t, typename> class SubStrategy = box_within_range
201 static inline bool apply(Box1 const& box1, Box2 const& box2)
203 return relate_box_box_loop
206 Box1, Box2, 0, dimension<Box1>::type::value
207 >::apply(box1, box2);
212 } // namespace within
215 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
218 namespace within { namespace services
221 template <typename BoxContained, typename BoxContaining>
222 struct default_strategy
226 cartesian_tag, cartesian_tag,
227 BoxContained, BoxContaining
230 typedef within::box_in_box<BoxContained, BoxContaining> type;
233 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
234 template <typename BoxContained, typename BoxContaining>
235 struct default_strategy
239 spherical_tag, spherical_tag,
240 BoxContained, BoxContaining
243 typedef within::box_in_box<BoxContained, BoxContaining> type;
247 }} // namespace within::services
249 namespace covered_by { namespace services
252 template <typename BoxContained, typename BoxContaining>
253 struct default_strategy
257 cartesian_tag, cartesian_tag,
258 BoxContained, BoxContaining
261 typedef within::box_in_box
263 BoxContained, BoxContaining,
264 within::box_covered_by_range
268 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
269 template <typename BoxContained, typename BoxContaining>
270 struct default_strategy
274 spherical_tag, spherical_tag,
275 BoxContained, BoxContaining
278 typedef within::box_in_box
280 BoxContained, BoxContaining,
281 within::box_covered_by_range
286 }} // namespace covered_by::services
289 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
292 }}} // namespace boost::geometry::strategy
294 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP