• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
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 
7 // This file was modified by Oracle on 2015-2018.
8 // Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
9 
10 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11 
12 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
13 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
14 
15 // Use, modification and distribution is subject to the Boost Software License,
16 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
17 // http://www.boost.org/LICENSE_1_0.txt)
18 
19 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP
20 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP
21 
22 
23 #include <boost/geometry/core/access.hpp>
24 #include <boost/geometry/core/coordinate_dimension.hpp>
25 #include <boost/geometry/core/cs.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>
29 
30 
31 namespace boost { namespace geometry { namespace strategy
32 {
33 
34 namespace within
35 {
36 
37 #ifndef DOXYGEN_NO_DETAIL
38 namespace detail
39 {
40 
41 struct within_coord
42 {
43     template <typename Value1, typename Value2>
applyboost::geometry::strategy::within::detail::within_coord44     static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
45     {
46         return value > min_value && value < max_value;
47     }
48 };
49 
50 struct covered_by_coord
51 {
52     template <typename Value1, typename Value2>
applyboost::geometry::strategy::within::detail::covered_by_coord53     static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
54     {
55         return value >= min_value && value <= max_value;
56     }
57 };
58 
59 template <typename Geometry, std::size_t Dimension, typename CSTag>
60 struct within_range
61     : within_coord
62 {};
63 
64 
65 template <typename Geometry, std::size_t Dimension, typename CSTag>
66 struct covered_by_range
67     : covered_by_coord
68 {};
69 
70 
71 // NOTE: the result would be the same if instead of structs defined below
72 // the above xxx_range were used with the following arguments:
73 // (min_value + diff_min, min_value, max_value)
74 struct within_longitude_diff
75 {
76     template <typename CalcT>
applyboost::geometry::strategy::within::detail::within_longitude_diff77     static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)
78     {
79         CalcT const c0 = 0;
80         return diff_min > c0
81             && (min_value + diff_min < max_value
82              /*|| max_value - diff_min > min_value*/);
83     }
84 };
85 
86 struct covered_by_longitude_diff
87 {
88     template <typename CalcT>
applyboost::geometry::strategy::within::detail::covered_by_longitude_diff89     static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)
90     {
91         return min_value + diff_min <= max_value
92             /*|| max_value - diff_min >= min_value*/;
93     }
94 };
95 
96 
97 template <typename Geometry,
98           typename CoordCheck,
99           typename DiffCheck>
100 struct longitude_range
101 {
102     template <typename Value1, typename Value2>
applyboost::geometry::strategy::within::detail::longitude_range103     static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
104     {
105         typedef typename select_most_precise
106             <
107                 Value1, Value2
108             >::type calc_t;
109         typedef typename geometry::detail::cs_angular_units<Geometry>::type units_t;
110         typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
111 
112         if (CoordCheck::apply(value, min_value, max_value))
113         {
114             return true;
115         }
116 
117         // min <= max <=> diff >= 0
118         calc_t const diff_ing = max_value - min_value;
119 
120         // if containing covers the whole globe it contains all
121         if (diff_ing >= constants::period())
122         {
123             return true;
124         }
125 
126         // calculate positive longitude translation with min_value as origin
127         calc_t const diff_min = math::longitude_distance_unsigned<units_t, calc_t>(min_value, value);
128 
129         return DiffCheck::template apply<calc_t>(diff_min, min_value, max_value);
130     }
131 };
132 
133 
134 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
135 template <typename Geometry>
136 struct within_range<Geometry, 0, spherical_tag>
137     : longitude_range<Geometry, within_coord, within_longitude_diff>
138 {};
139 
140 
141 template <typename Geometry>
142 struct covered_by_range<Geometry, 0, spherical_tag>
143     : longitude_range<Geometry, covered_by_coord, covered_by_longitude_diff>
144 {};
145 
146 
147 template
148 <
149     template <typename, std::size_t, typename> class SubStrategy,
150     typename CSTag, // cartesian_tag or spherical_tag
151     std::size_t Dimension,
152     std::size_t DimensionCount
153 >
154 struct relate_point_box_loop
155 {
156     template <typename Point, typename Box>
applyboost::geometry::strategy::within::detail::relate_point_box_loop157     static inline bool apply(Point const& point, Box const& box)
158     {
159         if (! SubStrategy<Point, Dimension, CSTag>::apply(get<Dimension>(point),
160                     get<min_corner, Dimension>(box),
161                     get<max_corner, Dimension>(box))
162             )
163         {
164             return false;
165         }
166 
167         return relate_point_box_loop
168             <
169                 SubStrategy,
170                 CSTag,
171                 Dimension + 1, DimensionCount
172             >::apply(point, box);
173     }
174 };
175 
176 
177 template
178 <
179     template <typename, std::size_t, typename> class SubStrategy,
180     typename CSTag,
181     std::size_t DimensionCount
182 >
183 struct relate_point_box_loop<SubStrategy, CSTag, DimensionCount, DimensionCount>
184 {
185     template <typename Point, typename Box>
applyboost::geometry::strategy::within::detail::relate_point_box_loop186     static inline bool apply(Point const& , Box const& )
187     {
188         return true;
189     }
190 };
191 
192 } // namespace detail
193 #endif // DOXYGEN_NO_DETAIL
194 
195 struct cartesian_point_box
196 {
197     template <typename Point, typename Box>
applyboost::geometry::strategy::within::cartesian_point_box198     static inline bool apply(Point const& point, Box const& box)
199     {
200         return detail::relate_point_box_loop
201             <
202                 detail::within_range,
203                 cartesian_tag,
204                 0, dimension<Point>::value
205             >::apply(point, box);
206     }
207 };
208 
209 struct spherical_point_box
210 {
211     template <typename Point, typename Box>
applyboost::geometry::strategy::within::spherical_point_box212     static inline bool apply(Point const& point, Box const& box)
213     {
214         return detail::relate_point_box_loop
215             <
216                 detail::within_range,
217                 spherical_tag,
218                 0, dimension<Point>::value
219             >::apply(point, box);
220     }
221 };
222 
223 
224 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
225 namespace services
226 {
227 
228 template <typename Point, typename Box>
229 struct default_strategy
230     <
231         Point, Box,
232         point_tag, box_tag,
233         pointlike_tag, areal_tag,
234         cartesian_tag, cartesian_tag
235     >
236 {
237     typedef within::cartesian_point_box type;
238 };
239 
240 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
241 template <typename Point, typename Box>
242 struct default_strategy
243     <
244         Point, Box,
245         point_tag, box_tag,
246         pointlike_tag, areal_tag,
247         spherical_tag, spherical_tag
248     >
249 {
250     typedef within::spherical_point_box type;
251 };
252 
253 
254 } // namespace services
255 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
256 
257 } // namespace within
258 
259 namespace covered_by
260 {
261 
262 struct cartesian_point_box
263 {
264     template <typename Point, typename Box>
applyboost::geometry::strategy::covered_by::cartesian_point_box265     static inline bool apply(Point const& point, Box const& box)
266     {
267         return within::detail::relate_point_box_loop
268             <
269                 within::detail::covered_by_range,
270                 cartesian_tag,
271                 0, dimension<Point>::value
272             >::apply(point, box);
273     }
274 };
275 
276 struct spherical_point_box
277 {
278     template <typename Point, typename Box>
applyboost::geometry::strategy::covered_by::spherical_point_box279     static inline bool apply(Point const& point, Box const& box)
280     {
281         return within::detail::relate_point_box_loop
282             <
283                 within::detail::covered_by_range,
284                 spherical_tag,
285                 0, dimension<Point>::value
286             >::apply(point, box);
287     }
288 };
289 
290 
291 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
292 namespace services
293 {
294 
295 
296 template <typename Point, typename Box>
297 struct default_strategy
298     <
299         Point, Box,
300         point_tag, box_tag,
301         pointlike_tag, areal_tag,
302         cartesian_tag, cartesian_tag
303     >
304 {
305     typedef covered_by::cartesian_point_box type;
306 };
307 
308 // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
309 template <typename Point, typename Box>
310 struct default_strategy
311     <
312         Point, Box,
313         point_tag, box_tag,
314         pointlike_tag, areal_tag,
315         spherical_tag, spherical_tag
316     >
317 {
318     typedef covered_by::spherical_point_box type;
319 };
320 
321 
322 } // namespace services
323 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
324 
325 
326 } // namespace covered_by
327 
328 
329 }}} // namespace boost::geometry::strategy
330 
331 
332 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP
333