]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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-2016. | |
8 | // Modifications copyright (c) 2015-2016, 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/strategies/covered_by.hpp> | |
26 | #include <boost/geometry/strategies/within.hpp> | |
27 | #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp> | |
28 | ||
29 | ||
30 | namespace boost { namespace geometry { namespace strategy | |
31 | { | |
32 | ||
33 | namespace within | |
34 | { | |
35 | ||
36 | ||
37 | template <typename Geometry, std::size_t Dimension, typename CSTag> | |
38 | struct within_range | |
39 | { | |
40 | template <typename Value1, typename Value2> | |
41 | static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value) | |
42 | { | |
43 | return value > min_value && value < max_value; | |
44 | } | |
45 | }; | |
46 | ||
47 | ||
48 | template <typename Geometry, std::size_t Dimension, typename CSTag> | |
49 | struct covered_by_range | |
50 | { | |
51 | template <typename Value1, typename Value2> | |
52 | static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value) | |
53 | { | |
54 | return value >= min_value && value <= max_value; | |
55 | } | |
56 | }; | |
57 | ||
58 | ||
59 | // NOTE: the result would be the same if instead of structs defined below | |
60 | // the above xxx_range were used with the following arguments: | |
61 | // (min_value + diff_min, min_value, max_value) | |
62 | struct within_longitude_range | |
63 | { | |
64 | template <typename CalcT> | |
65 | static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value) | |
66 | { | |
67 | CalcT const c0 = 0; | |
68 | return diff_min > c0 && min_value + diff_min < max_value; | |
69 | } | |
70 | }; | |
71 | ||
72 | struct covered_by_longitude_range | |
73 | { | |
74 | template <typename CalcT> | |
75 | static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value) | |
76 | { | |
77 | return min_value + diff_min <= max_value; | |
78 | } | |
79 | }; | |
80 | ||
81 | ||
82 | template <typename Geometry, | |
83 | typename ResultCheck> | |
84 | struct longitude_range | |
85 | { | |
86 | template <typename Value1, typename Value2> | |
87 | static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value) | |
88 | { | |
89 | typedef typename select_most_precise | |
90 | < | |
91 | Value1, Value2 | |
92 | >::type calc_t; | |
93 | typedef typename coordinate_system<Geometry>::type::units units_t; | |
94 | typedef math::detail::constants_on_spheroid<calc_t, units_t> constants; | |
95 | ||
96 | // min <= max <=> diff >= 0 | |
97 | calc_t const diff_ing = max_value - min_value; | |
98 | ||
99 | // if containing covers the whole globe it contains all | |
100 | if (diff_ing >= constants::period()) | |
101 | { | |
102 | return true; | |
103 | } | |
104 | ||
105 | // calculate positive longitude translation with min_value as origin | |
106 | calc_t const diff_min = math::longitude_distance_unsigned<units_t, calc_t>(min_value, value); | |
107 | ||
108 | return ResultCheck::template apply<calc_t>(diff_min, min_value, max_value); | |
109 | } | |
110 | }; | |
111 | ||
112 | ||
113 | // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag | |
114 | template <typename Geometry> | |
115 | struct within_range<Geometry, 0, spherical_tag> | |
116 | : longitude_range<Geometry, within_longitude_range> | |
117 | {}; | |
118 | ||
119 | ||
120 | template <typename Geometry> | |
121 | struct covered_by_range<Geometry, 0, spherical_tag> | |
122 | : longitude_range<Geometry, covered_by_longitude_range> | |
123 | {}; | |
124 | ||
125 | ||
126 | template | |
127 | < | |
128 | template <typename, std::size_t, typename> class SubStrategy, | |
129 | typename Point, | |
130 | typename Box, | |
131 | std::size_t Dimension, | |
132 | std::size_t DimensionCount | |
133 | > | |
134 | struct relate_point_box_loop | |
135 | { | |
136 | static inline bool apply(Point const& point, Box const& box) | |
137 | { | |
138 | typedef typename tag_cast<typename cs_tag<Point>::type, spherical_tag>::type cs_tag_t; | |
139 | ||
140 | if (! SubStrategy<Point, Dimension, cs_tag_t>::apply(get<Dimension>(point), | |
141 | get<min_corner, Dimension>(box), | |
142 | get<max_corner, Dimension>(box)) | |
143 | ) | |
144 | { | |
145 | return false; | |
146 | } | |
147 | ||
148 | return relate_point_box_loop | |
149 | < | |
150 | SubStrategy, | |
151 | Point, Box, | |
152 | Dimension + 1, DimensionCount | |
153 | >::apply(point, box); | |
154 | } | |
155 | }; | |
156 | ||
157 | ||
158 | template | |
159 | < | |
160 | template <typename, std::size_t, typename> class SubStrategy, | |
161 | typename Point, | |
162 | typename Box, | |
163 | std::size_t DimensionCount | |
164 | > | |
165 | struct relate_point_box_loop<SubStrategy, Point, Box, DimensionCount, DimensionCount> | |
166 | { | |
167 | static inline bool apply(Point const& , Box const& ) | |
168 | { | |
169 | return true; | |
170 | } | |
171 | }; | |
172 | ||
173 | ||
174 | template | |
175 | < | |
176 | typename Point, | |
177 | typename Box, | |
178 | template <typename, std::size_t, typename> class SubStrategy = within_range | |
179 | > | |
180 | struct point_in_box | |
181 | { | |
182 | static inline bool apply(Point const& point, Box const& box) | |
183 | { | |
184 | return relate_point_box_loop | |
185 | < | |
186 | SubStrategy, | |
187 | Point, Box, | |
188 | 0, dimension<Point>::type::value | |
189 | >::apply(point, box); | |
190 | } | |
191 | }; | |
192 | ||
193 | ||
194 | } // namespace within | |
195 | ||
196 | ||
197 | #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS | |
198 | ||
199 | ||
200 | namespace within { namespace services | |
201 | { | |
202 | ||
203 | template <typename Point, typename Box> | |
204 | struct default_strategy | |
205 | < | |
206 | point_tag, box_tag, | |
207 | point_tag, areal_tag, | |
208 | cartesian_tag, cartesian_tag, | |
209 | Point, Box | |
210 | > | |
211 | { | |
212 | typedef within::point_in_box<Point, Box> type; | |
213 | }; | |
214 | ||
215 | // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag | |
216 | template <typename Point, typename Box> | |
217 | struct default_strategy | |
218 | < | |
219 | point_tag, box_tag, | |
220 | point_tag, areal_tag, | |
221 | spherical_tag, spherical_tag, | |
222 | Point, Box | |
223 | > | |
224 | { | |
225 | typedef within::point_in_box<Point, Box> type; | |
226 | }; | |
227 | ||
228 | ||
229 | }} // namespace within::services | |
230 | ||
231 | ||
232 | namespace covered_by { namespace services | |
233 | { | |
234 | ||
235 | ||
236 | template <typename Point, typename Box> | |
237 | struct default_strategy | |
238 | < | |
239 | point_tag, box_tag, | |
240 | point_tag, areal_tag, | |
241 | cartesian_tag, cartesian_tag, | |
242 | Point, Box | |
243 | > | |
244 | { | |
245 | typedef within::point_in_box | |
246 | < | |
247 | Point, Box, | |
248 | within::covered_by_range | |
249 | > type; | |
250 | }; | |
251 | ||
252 | // spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag | |
253 | template <typename Point, typename Box> | |
254 | struct default_strategy | |
255 | < | |
256 | point_tag, box_tag, | |
257 | point_tag, areal_tag, | |
258 | spherical_tag, spherical_tag, | |
259 | Point, Box | |
260 | > | |
261 | { | |
262 | typedef within::point_in_box | |
263 | < | |
264 | Point, Box, | |
265 | within::covered_by_range | |
266 | > type; | |
267 | }; | |
268 | ||
269 | ||
270 | }} // namespace covered_by::services | |
271 | ||
272 | ||
273 | #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS | |
274 | ||
275 | ||
276 | }}} // namespace boost::geometry::strategy | |
277 | ||
278 | ||
279 | #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP |