]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/geometry/algorithms/detail/expand/point.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / detail / expand / point.hpp
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 // Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
7
8 // This file was modified by Oracle on 2015, 2016, 2017.
9 // Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
10
11 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
12 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
13 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
14
15 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
16 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
17
18 // Distributed under the Boost Software License, Version 1.0.
19 // (See accompanying file LICENSE_1_0.txt or copy at
20 // http://www.boost.org/LICENSE_1_0.txt)
21
22 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
23 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
24
25 #include <cstddef>
26 #include <algorithm>
27 #include <functional>
28
29 #include <boost/mpl/assert.hpp>
30 #include <boost/type_traits/is_same.hpp>
31
32 #include <boost/geometry/core/access.hpp>
33 #include <boost/geometry/core/coordinate_dimension.hpp>
34 #include <boost/geometry/core/coordinate_system.hpp>
35 #include <boost/geometry/core/coordinate_type.hpp>
36 #include <boost/geometry/core/tags.hpp>
37
38 #include <boost/geometry/util/math.hpp>
39 #include <boost/geometry/util/select_coordinate_type.hpp>
40
41 #include <boost/geometry/algorithms/detail/normalize.hpp>
42 #include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
43
44 #include <boost/geometry/algorithms/dispatch/expand.hpp>
45
46
47 namespace boost { namespace geometry
48 {
49
50 #ifndef DOXYGEN_NO_DETAIL
51 namespace detail { namespace expand
52 {
53
54
55 template <std::size_t Dimension, std::size_t DimensionCount>
56 struct point_loop
57 {
58 template <typename Box, typename Point, typename Strategy>
59 static inline void apply(Box& box, Point const& source, Strategy const& strategy)
60 {
61 typedef typename select_coordinate_type
62 <
63 Point, Box
64 >::type coordinate_type;
65
66 std::less<coordinate_type> less;
67 std::greater<coordinate_type> greater;
68
69 coordinate_type const coord = get<Dimension>(source);
70
71 if (less(coord, get<min_corner, Dimension>(box)))
72 {
73 set<min_corner, Dimension>(box, coord);
74 }
75
76 if (greater(coord, get<max_corner, Dimension>(box)))
77 {
78 set<max_corner, Dimension>(box, coord);
79 }
80
81 point_loop<Dimension + 1, DimensionCount>::apply(box, source, strategy);
82 }
83 };
84
85
86 template <std::size_t DimensionCount>
87 struct point_loop<DimensionCount, DimensionCount>
88 {
89 template <typename Box, typename Point, typename Strategy>
90 static inline void apply(Box&, Point const&, Strategy const&) {}
91 };
92
93
94 // implementation for the spherical and geographic coordinate systems
95 template <std::size_t DimensionCount, bool IsEquatorial = true>
96 struct point_loop_on_spheroid
97 {
98 template <typename Box, typename Point, typename Strategy>
99 static inline void apply(Box& box,
100 Point const& point,
101 Strategy const& strategy)
102 {
103 typedef typename point_type<Box>::type box_point_type;
104 typedef typename coordinate_type<Box>::type box_coordinate_type;
105 typedef typename coordinate_system<Box>::type::units units_type;
106
107 typedef math::detail::constants_on_spheroid
108 <
109 box_coordinate_type,
110 units_type
111 > constants;
112
113 // normalize input point and input box
114 Point p_normalized = detail::return_normalized<Point>(point);
115 detail::normalize(box, box);
116
117 // transform input point to be of the same type as the box point
118 box_point_type box_point;
119 detail::envelope::transform_units(p_normalized, box_point);
120
121 box_coordinate_type p_lon = geometry::get<0>(box_point);
122 box_coordinate_type p_lat = geometry::get<1>(box_point);
123
124 typename coordinate_type<Box>::type
125 b_lon_min = geometry::get<min_corner, 0>(box),
126 b_lat_min = geometry::get<min_corner, 1>(box),
127 b_lon_max = geometry::get<max_corner, 0>(box),
128 b_lat_max = geometry::get<max_corner, 1>(box);
129
130 if (math::is_latitude_pole<units_type, IsEquatorial>(p_lat))
131 {
132 // the point of expansion is the either the north or the
133 // south pole; the only important coordinate here is the
134 // pole's latitude, as the longitude can be anything;
135 // we, thus, take into account the point's latitude only and return
136 geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
137 geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
138 return;
139 }
140
141 if (math::equals(b_lat_min, b_lat_max)
142 && math::is_latitude_pole<units_type, IsEquatorial>(b_lat_min))
143 {
144 // the box degenerates to either the north or the south pole;
145 // the only important coordinate here is the pole's latitude,
146 // as the longitude can be anything;
147 // we thus take into account the box's latitude only and return
148 geometry::set<min_corner, 0>(box, p_lon);
149 geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
150 geometry::set<max_corner, 0>(box, p_lon);
151 geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
152 return;
153 }
154
155 // update latitudes
156 b_lat_min = (std::min)(b_lat_min, p_lat);
157 b_lat_max = (std::max)(b_lat_max, p_lat);
158
159 // update longitudes
160 if (math::smaller(p_lon, b_lon_min))
161 {
162 box_coordinate_type p_lon_shifted = p_lon + constants::period();
163
164 if (math::larger(p_lon_shifted, b_lon_max))
165 {
166 // here we could check using: ! math::larger(.., ..)
167 if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max))
168 {
169 b_lon_min = p_lon;
170 }
171 else
172 {
173 b_lon_max = p_lon_shifted;
174 }
175 }
176 }
177 else if (math::larger(p_lon, b_lon_max))
178 {
179 // in this case, and since p_lon is normalized in the range
180 // (-180, 180], we must have that b_lon_max <= 180
181 if (b_lon_min < 0
182 && math::larger(p_lon - b_lon_max,
183 constants::period() - p_lon + b_lon_min))
184 {
185 b_lon_min = p_lon;
186 b_lon_max += constants::period();
187 }
188 else
189 {
190 b_lon_max = p_lon;
191 }
192 }
193
194 geometry::set<min_corner, 0>(box, b_lon_min);
195 geometry::set<min_corner, 1>(box, b_lat_min);
196 geometry::set<max_corner, 0>(box, b_lon_max);
197 geometry::set<max_corner, 1>(box, b_lat_max);
198
199 point_loop
200 <
201 2, DimensionCount
202 >::apply(box, point, strategy);
203 }
204 };
205
206
207 }} // namespace detail::expand
208 #endif // DOXYGEN_NO_DETAIL
209
210 #ifndef DOXYGEN_NO_DISPATCH
211 namespace dispatch
212 {
213
214
215 // Box + point -> new box containing also point
216 template
217 <
218 typename BoxOut, typename Point,
219 typename CSTagOut, typename CSTag
220 >
221 struct expand
222 <
223 BoxOut, Point,
224 box_tag, point_tag,
225 CSTagOut, CSTag
226 >
227 {
228 BOOST_MPL_ASSERT_MSG((false),
229 NOT_IMPLEMENTED_FOR_THESE_COORDINATE_SYSTEMS,
230 (types<CSTagOut, CSTag>()));
231 };
232
233
234 template <typename BoxOut, typename Point>
235 struct expand
236 <
237 BoxOut, Point,
238 box_tag, point_tag,
239 cartesian_tag, cartesian_tag
240 > : detail::expand::point_loop
241 <
242 0, dimension<Point>::value
243 >
244 {};
245
246 template <typename BoxOut, typename Point>
247 struct expand
248 <
249 BoxOut, Point,
250 box_tag, point_tag,
251 spherical_equatorial_tag, spherical_equatorial_tag
252 > : detail::expand::point_loop_on_spheroid
253 <
254 dimension<Point>::value
255 >
256 {};
257
258 template <typename BoxOut, typename Point>
259 struct expand
260 <
261 BoxOut, Point,
262 box_tag, point_tag,
263 spherical_polar_tag, spherical_polar_tag
264 > : detail::expand::point_loop_on_spheroid
265 <
266 dimension<Point>::value,
267 false
268 >
269 {};
270
271 template
272 <
273 typename BoxOut, typename Point
274 >
275 struct expand
276 <
277 BoxOut, Point,
278 box_tag, point_tag,
279 geographic_tag, geographic_tag
280 > : detail::expand::point_loop_on_spheroid
281 <
282 dimension<Point>::value
283 >
284 {};
285
286
287 } // namespace dispatch
288 #endif // DOXYGEN_NO_DISPATCH
289
290 }} // namespace boost::geometry
291
292 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP