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