1 // Boost.Geometry (aka GGL, Generic Geometry Library)
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
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)
11 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
12 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
14 #include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
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>
24 namespace boost { namespace geometry
28 namespace strategy { namespace distance
31 struct generic_segment_box
37 typename SegmentPoint,
39 typename SegmentBoxStrategy,
40 typename AzimuthStrategy,
41 typename EnvelopeSegmentStrategy,
42 typename NormalizePointStrategy,
43 typename DisjointPointBoxStrategy,
44 typename DisjointBoxBoxStrategy
46 static inline ReturnType segment_below_of_box(
47 SegmentPoint const& p0,
48 SegmentPoint const& p1,
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)
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
66 boost::is_same<typename SegmentBoxStrategy::cs_tag, spherical_tag>::value,
67 typename boost::mpl::if_c
71 typename geometry::cs_tag<segment_type>::type,
74 spherical_polar_tag, spherical_equatorial_tag
76 typename SegmentBoxStrategy::cs_tag
78 typedef geometry::detail::disjoint::
79 disjoint_segment_box_sphere_or_spheroid<cs_tag>
81 typedef typename disjoint_sb::disjoint_info disjoint_info_type;
83 segment_type seg(p0, p1);
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));
97 disjoint_info_type disjoint_result = disjoint_sb::
98 apply(seg, input_box, p_max,
99 az_strategy, np_strategy, dpb_strategy, dbb_strategy);
101 if (disjoint_result == disjoint_info_type::intersect) //intersect
105 // disjoint but vertex not computed
106 if (disjoint_result == disjoint_info_type::disjoint_no_vertex)
108 typedef typename coordinate_type<SegmentPoint>::type CT;
110 geometry::model::box<SegmentPoint> mbr;
111 geometry::envelope(seg, mbr, es_strategy);
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);
120 std::swap(lon1, lon2);
121 std::swap(lat1, lat2);
125 CT lat_sum = lat1 + lat2;
128 vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(mbr);
130 vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(mbr);
134 az_strategy.apply(lon1, lat1, lon2, lat2, alp1);
135 CT vertex_lon = geometry::formula::vertex_longitude
139 >::apply(lon1, lat1, lon2, lat2,
140 vertex_lat, alp1, az_strategy);
142 geometry::set_from_radian<0>(p_max, vertex_lon);
143 geometry::set_from_radian<1>(p_max, vertex_lat);
145 //otherwise disjoint and vertex computed inside disjoint
147 if (less_equal(geometry::get_as_radian<0>(bottom_left),
148 geometry::get_as_radian<0>(p_max)))
150 result = boost::numeric_cast<ReturnType>(typename
151 SegmentBoxStrategy::distance_ps_strategy::type().apply(bottom_left, p0, p1));
155 result = geometry::detail::distance::segment_to_box_2D
161 >::template call_above_of_box
163 typename LessEqual::other
164 >(p1, p0, p_max, bottom_right, sb_strategy);
169 template <typename SPoint, typename BPoint>
170 static void mirror(SPoint& p0,
173 BPoint& bottom_right,
177 //if segment's vertex is the southest point then mirror geometries
178 if (geometry::get<1>(p0) + geometry::get<1>(p1) < 0)
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);
192 //===========================================================================
196 typename CalculationType = void,
197 typename Strategy = haversine<double, CalculationType>
199 struct spherical_segment_box
201 template <typename PointOfSegment, typename PointOfBox>
202 struct calculation_type
203 : promote_floating_point
205 typename strategy::distance::services::return_type
214 typedef spherical_tag cs_tag;
218 // point-point strategy getters
219 struct distance_pp_strategy
221 typedef Strategy type;
224 inline typename distance_pp_strategy::type get_distance_pp_strategy() const
226 return typename distance_pp_strategy::type();
228 // point-segment strategy getters
229 struct distance_ps_strategy
231 typedef cross_track<CalculationType, Strategy> type;
234 inline typename distance_ps_strategy::type get_distance_ps_strategy() const
236 return typename distance_ps_strategy::type();
239 struct distance_pb_strategy
241 typedef cross_track_point_box<CalculationType, Strategy> type;
244 inline typename distance_pb_strategy::type get_distance_pb_strategy() const
246 return typename distance_pb_strategy::type();
249 // TODO: why is the Radius not propagated above?
251 typedef side::spherical_side_formula<CalculationType> side_strategy_type;
253 static inline side_strategy_type get_side_strategy()
255 return side_strategy_type();
258 typedef within::spherical_point_point equals_point_point_strategy_type;
260 static inline equals_point_point_strategy_type get_equals_point_point_strategy()
262 return equals_point_point_strategy_type();
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
276 typedef typename azimuth::spherical<CalculationType> azimuth_strategy_type;
277 azimuth_strategy_type az_strategy;
279 typedef typename envelope::spherical_segment<CalculationType>
280 envelope_segment_strategy_type;
281 envelope_segment_strategy_type es_strategy;
283 return generic_segment_box::segment_below_of_box
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());
295 template <typename SPoint, typename BPoint>
296 static void mirror(SPoint& p0,
299 BPoint& bottom_right,
304 generic_segment_box::mirror(p0, p1,
305 bottom_left, bottom_right,
306 top_left, top_right);
311 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
315 template <typename CalculationType, typename Strategy>
316 struct tag<spherical_segment_box<CalculationType, Strategy> >
318 typedef strategy_tag_distance_segment_box type;
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>
326 template <typename CalculationType, typename Strategy>
327 struct comparable_type<spherical_segment_box<CalculationType, Strategy> >
329 // Define a cartesian_segment_box strategy with its underlying point-segment
330 // strategy being comparable
331 typedef spherical_segment_box
334 typename comparable_type<Strategy>::type
339 template <typename CalculationType, typename Strategy>
340 struct get_comparable<spherical_segment_box<CalculationType, Strategy> >
342 typedef typename comparable_type
344 spherical_segment_box<CalculationType, Strategy>
345 >::type comparable_type;
347 static inline comparable_type apply(spherical_segment_box<CalculationType, Strategy> const& )
349 return comparable_type();
353 template <typename CalculationType, typename Strategy, typename PS, typename PB>
354 struct result_from_distance<spherical_segment_box<CalculationType, Strategy>, PS, PB>
357 typedef typename return_type<
358 spherical_segment_box
367 template <typename T>
368 static inline return_type apply(spherical_segment_box<CalculationType,
373 return result_from_distance<Strategy, PS, PB>::apply(s, value);
377 template <typename Segment, typename Box>
378 struct default_strategy
380 segment_tag, box_tag, Segment, Box,
381 spherical_equatorial_tag, spherical_equatorial_tag
384 typedef spherical_segment_box<> type;
387 template <typename Box, typename Segment>
388 struct default_strategy
390 box_tag, segment_tag, Box, Segment,
391 spherical_equatorial_tag, spherical_equatorial_tag
394 typedef typename default_strategy
396 segment_tag, box_tag, Segment, Box,
397 spherical_equatorial_tag, spherical_equatorial_tag
404 }} // namespace strategy::distance
406 }} // namespace boost::geometry
407 #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP