]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/geometry/strategies/spherical/distance_segment_box.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / geometry / strategies / spherical / distance_segment_box.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2018-2019 Oracle and/or its affiliates.
4 // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
5 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
6
7 // Use, modification and distribution is subject to the Boost Software License,
8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10
11 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
12 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
13
14 #include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
15
16 #include <boost/geometry/strategies/distance.hpp>
17 #include <boost/geometry/strategies/normalize.hpp>
18 #include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
19 #include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
20 #include <boost/geometry/strategies/spherical/point_in_point.hpp>
21 #include <boost/geometry/strategies/cartesian/point_in_box.hpp> // spherical
22 #include <boost/geometry/strategies/spherical/ssf.hpp>
23
24 namespace boost { namespace geometry
25 {
26
27
28 namespace strategy { namespace distance
29 {
30
31 struct generic_segment_box
32 {
33 template
34 <
35 typename LessEqual,
36 typename ReturnType,
37 typename SegmentPoint,
38 typename BoxPoint,
39 typename SegmentBoxStrategy,
40 typename AzimuthStrategy,
41 typename EnvelopeSegmentStrategy,
42 typename NormalizePointStrategy,
43 typename DisjointPointBoxStrategy,
44 typename DisjointBoxBoxStrategy
45 >
46 static inline ReturnType segment_below_of_box(
47 SegmentPoint const& p0,
48 SegmentPoint const& p1,
49 BoxPoint const&,
50 BoxPoint const& top_right,
51 BoxPoint const& bottom_left,
52 BoxPoint const& bottom_right,
53 SegmentBoxStrategy const& sb_strategy,
54 AzimuthStrategy const& az_strategy,
55 EnvelopeSegmentStrategy const& es_strategy,
56 NormalizePointStrategy const& np_strategy,
57 DisjointPointBoxStrategy const& dpb_strategy,
58 DisjointBoxBoxStrategy const& dbb_strategy)
59 {
60 ReturnType result;
61 typename LessEqual::other less_equal;
62 typedef geometry::model::segment<SegmentPoint> segment_type;
63 // if cs_tag is spherical_tag check segment's cs_tag with spherical_equatorial_tag as default
64 typedef typename boost::mpl::if_c
65 <
66 boost::is_same<typename SegmentBoxStrategy::cs_tag, spherical_tag>::value,
67 typename boost::mpl::if_c
68 <
69 boost::is_same
70 <
71 typename geometry::cs_tag<segment_type>::type,
72 spherical_polar_tag
73 >::value,
74 spherical_polar_tag, spherical_equatorial_tag
75 >::type,
76 typename SegmentBoxStrategy::cs_tag
77 >::type cs_tag;
78 typedef geometry::detail::disjoint::
79 disjoint_segment_box_sphere_or_spheroid<cs_tag>
80 disjoint_sb;
81 typedef typename disjoint_sb::disjoint_info disjoint_info_type;
82
83 segment_type seg(p0, p1);
84
85 geometry::model::box<BoxPoint> input_box;
86 geometry::set_from_radian<geometry::min_corner, 0>
87 (input_box, geometry::get_as_radian<0>(bottom_left));
88 geometry::set_from_radian<geometry::min_corner, 1>
89 (input_box, geometry::get_as_radian<1>(bottom_left));
90 geometry::set_from_radian<geometry::max_corner, 0>
91 (input_box, geometry::get_as_radian<0>(top_right));
92 geometry::set_from_radian<geometry::max_corner, 1>
93 (input_box, geometry::get_as_radian<1>(top_right));
94
95 SegmentPoint p_max;
96
97 disjoint_info_type disjoint_result = disjoint_sb::
98 apply(seg, input_box, p_max,
99 az_strategy, np_strategy, dpb_strategy, dbb_strategy);
100
101 if (disjoint_result == disjoint_info_type::intersect) //intersect
102 {
103 return 0;
104 }
105 // disjoint but vertex not computed
106 if (disjoint_result == disjoint_info_type::disjoint_no_vertex)
107 {
108 typedef typename coordinate_type<SegmentPoint>::type CT;
109
110 geometry::model::box<SegmentPoint> mbr;
111 geometry::envelope(seg, mbr, es_strategy);
112
113 CT lon1 = geometry::get_as_radian<0>(p0);
114 CT lat1 = geometry::get_as_radian<1>(p0);
115 CT lon2 = geometry::get_as_radian<0>(p1);
116 CT lat2 = geometry::get_as_radian<1>(p1);
117
118 if (lon1 > lon2)
119 {
120 std::swap(lon1, lon2);
121 std::swap(lat1, lat2);
122 }
123
124 CT vertex_lat;
125 CT lat_sum = lat1 + lat2;
126 if (lat_sum > CT(0))
127 {
128 vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(mbr);
129 } else {
130 vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(mbr);
131 }
132
133 CT alp1;
134 az_strategy.apply(lon1, lat1, lon2, lat2, alp1);
135 CT vertex_lon = geometry::formula::vertex_longitude
136 <
137 CT,
138 cs_tag
139 >::apply(lon1, lat1, lon2, lat2,
140 vertex_lat, alp1, az_strategy);
141
142 geometry::set_from_radian<0>(p_max, vertex_lon);
143 geometry::set_from_radian<1>(p_max, vertex_lat);
144 }
145 //otherwise disjoint and vertex computed inside disjoint
146
147 if (less_equal(geometry::get_as_radian<0>(bottom_left),
148 geometry::get_as_radian<0>(p_max)))
149 {
150 result = boost::numeric_cast<ReturnType>(typename
151 SegmentBoxStrategy::distance_ps_strategy::type().apply(bottom_left, p0, p1));
152 }
153 else
154 {
155 result = geometry::detail::distance::segment_to_box_2D
156 <
157 ReturnType,
158 SegmentPoint,
159 BoxPoint,
160 SegmentBoxStrategy
161 >::template call_above_of_box
162 <
163 typename LessEqual::other
164 >(p1, p0, p_max, bottom_right, sb_strategy);
165 }
166 return result;
167 }
168
169 template <typename SPoint, typename BPoint>
170 static void mirror(SPoint& p0,
171 SPoint& p1,
172 BPoint& bottom_left,
173 BPoint& bottom_right,
174 BPoint& top_left,
175 BPoint& top_right)
176 {
177 //if segment's vertex is the southest point then mirror geometries
178 if (geometry::get<1>(p0) + geometry::get<1>(p1) < 0)
179 {
180 BPoint bl = bottom_left;
181 BPoint br = bottom_right;
182 geometry::set<1>(p0, geometry::get<1>(p0) * -1);
183 geometry::set<1>(p1, geometry::get<1>(p1) * -1);
184 geometry::set<1>(bottom_left, geometry::get<1>(top_left) * -1);
185 geometry::set<1>(top_left, geometry::get<1>(bl) * -1);
186 geometry::set<1>(bottom_right, geometry::get<1>(top_right) * -1);
187 geometry::set<1>(top_right, geometry::get<1>(br) * -1);
188 }
189 }
190 };
191
192 //===========================================================================
193
194 template
195 <
196 typename CalculationType = void,
197 typename Strategy = haversine<double, CalculationType>
198 >
199 struct spherical_segment_box
200 {
201 template <typename PointOfSegment, typename PointOfBox>
202 struct calculation_type
203 : promote_floating_point
204 <
205 typename strategy::distance::services::return_type
206 <
207 Strategy,
208 PointOfSegment,
209 PointOfBox
210 >::type
211 >
212 {};
213
214 typedef spherical_tag cs_tag;
215
216 // strategy getters
217
218 // point-point strategy getters
219 struct distance_pp_strategy
220 {
221 typedef Strategy type;
222 };
223
224 inline typename distance_pp_strategy::type get_distance_pp_strategy() const
225 {
226 return typename distance_pp_strategy::type();
227 }
228 // point-segment strategy getters
229 struct distance_ps_strategy
230 {
231 typedef cross_track<CalculationType, Strategy> type;
232 };
233
234 inline typename distance_ps_strategy::type get_distance_ps_strategy() const
235 {
236 return typename distance_ps_strategy::type();
237 }
238
239 struct distance_pb_strategy
240 {
241 typedef cross_track_point_box<CalculationType, Strategy> type;
242 };
243
244 inline typename distance_pb_strategy::type get_distance_pb_strategy() const
245 {
246 return typename distance_pb_strategy::type();
247 }
248
249 // TODO: why is the Radius not propagated above?
250
251 typedef side::spherical_side_formula<CalculationType> side_strategy_type;
252
253 static inline side_strategy_type get_side_strategy()
254 {
255 return side_strategy_type();
256 }
257
258 typedef within::spherical_point_point equals_point_point_strategy_type;
259
260 static inline equals_point_point_strategy_type get_equals_point_point_strategy()
261 {
262 return equals_point_point_strategy_type();
263 }
264
265 // methods
266
267 template <typename LessEqual, typename ReturnType,
268 typename SegmentPoint, typename BoxPoint>
269 inline ReturnType segment_below_of_box(SegmentPoint const& p0,
270 SegmentPoint const& p1,
271 BoxPoint const& top_left,
272 BoxPoint const& top_right,
273 BoxPoint const& bottom_left,
274 BoxPoint const& bottom_right) const
275 {
276 typedef typename azimuth::spherical<CalculationType> azimuth_strategy_type;
277 azimuth_strategy_type az_strategy;
278
279 typedef typename envelope::spherical_segment<CalculationType>
280 envelope_segment_strategy_type;
281 envelope_segment_strategy_type es_strategy;
282
283 return generic_segment_box::segment_below_of_box
284 <
285 LessEqual,
286 ReturnType
287 >(p0,p1,top_left,top_right,bottom_left,bottom_right,
288 spherical_segment_box<CalculationType>(),
289 az_strategy, es_strategy,
290 normalize::spherical_point(),
291 covered_by::spherical_point_box(),
292 disjoint::spherical_box_box());
293 }
294
295 template <typename SPoint, typename BPoint>
296 static void mirror(SPoint& p0,
297 SPoint& p1,
298 BPoint& bottom_left,
299 BPoint& bottom_right,
300 BPoint& top_left,
301 BPoint& top_right)
302 {
303
304 generic_segment_box::mirror(p0, p1,
305 bottom_left, bottom_right,
306 top_left, top_right);
307 }
308
309 };
310
311 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
312 namespace services
313 {
314
315 template <typename CalculationType, typename Strategy>
316 struct tag<spherical_segment_box<CalculationType, Strategy> >
317 {
318 typedef strategy_tag_distance_segment_box type;
319 };
320
321 template <typename CalculationType, typename Strategy, typename PS, typename PB>
322 struct return_type<spherical_segment_box<CalculationType, Strategy>, PS, PB>
323 : spherical_segment_box<CalculationType, Strategy>::template calculation_type<PS, PB>
324 {};
325
326 template <typename CalculationType, typename Strategy>
327 struct comparable_type<spherical_segment_box<CalculationType, Strategy> >
328 {
329 // Define a cartesian_segment_box strategy with its underlying point-segment
330 // strategy being comparable
331 typedef spherical_segment_box
332 <
333 CalculationType,
334 typename comparable_type<Strategy>::type
335 > type;
336 };
337
338
339 template <typename CalculationType, typename Strategy>
340 struct get_comparable<spherical_segment_box<CalculationType, Strategy> >
341 {
342 typedef typename comparable_type
343 <
344 spherical_segment_box<CalculationType, Strategy>
345 >::type comparable_type;
346 public :
347 static inline comparable_type apply(spherical_segment_box<CalculationType, Strategy> const& )
348 {
349 return comparable_type();
350 }
351 };
352
353 template <typename CalculationType, typename Strategy, typename PS, typename PB>
354 struct result_from_distance<spherical_segment_box<CalculationType, Strategy>, PS, PB>
355 {
356 private :
357 typedef typename return_type<
358 spherical_segment_box
359 <
360 CalculationType,
361 Strategy
362 >,
363 PS,
364 PB
365 >::type return_type;
366 public :
367 template <typename T>
368 static inline return_type apply(spherical_segment_box<CalculationType,
369 Strategy> const& ,
370 T const& value)
371 {
372 Strategy s;
373 return result_from_distance<Strategy, PS, PB>::apply(s, value);
374 }
375 };
376
377 template <typename Segment, typename Box>
378 struct default_strategy
379 <
380 segment_tag, box_tag, Segment, Box,
381 spherical_equatorial_tag, spherical_equatorial_tag
382 >
383 {
384 typedef spherical_segment_box<> type;
385 };
386
387 template <typename Box, typename Segment>
388 struct default_strategy
389 <
390 box_tag, segment_tag, Box, Segment,
391 spherical_equatorial_tag, spherical_equatorial_tag
392 >
393 {
394 typedef typename default_strategy
395 <
396 segment_tag, box_tag, Segment, Box,
397 spherical_equatorial_tag, spherical_equatorial_tag
398 >::type type;
399 };
400
401 }
402 #endif
403
404 }} // namespace strategy::distance
405
406 }} // namespace boost::geometry
407 #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP