File indexing completed on 2025-07-02 08:14:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
0012 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
0013
0014 #include <type_traits>
0015
0016 #include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
0017 #include <boost/geometry/algorithms/envelope.hpp>
0018
0019 #include <boost/geometry/strategies/distance.hpp>
0020 #include <boost/geometry/strategies/normalize.hpp>
0021 #include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
0022 #include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
0023 #include <boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp>
0024 #include <boost/geometry/strategies/spherical/point_in_point.hpp>
0025 #include <boost/geometry/strategies/cartesian/point_in_box.hpp> // spherical
0026 #include <boost/geometry/strategies/spherical/ssf.hpp>
0027
0028 #include <boost/geometry/util/numeric_cast.hpp>
0029
0030
0031 namespace boost { namespace geometry
0032 {
0033
0034
0035 namespace strategy { namespace distance
0036 {
0037
0038 struct generic_segment_box
0039 {
0040 template
0041 <
0042 typename LessEqual,
0043 typename ReturnType,
0044 typename SegmentPoint,
0045 typename BoxPoint,
0046 typename Strategies
0047 >
0048 static inline ReturnType segment_below_of_box(
0049 SegmentPoint const& p0,
0050 SegmentPoint const& p1,
0051 BoxPoint const&,
0052 BoxPoint const& top_right,
0053 BoxPoint const& bottom_left,
0054 BoxPoint const& bottom_right,
0055 Strategies const& strategies)
0056 {
0057 ReturnType result;
0058 typename LessEqual::other less_equal;
0059 typedef geometry::model::segment<SegmentPoint> segment_type;
0060
0061 typedef std::conditional_t
0062 <
0063 std::is_same<typename Strategies::cs_tag, spherical_tag>::value,
0064 std::conditional_t
0065 <
0066 std::is_same
0067 <
0068 typename geometry::cs_tag<segment_type>::type,
0069 spherical_polar_tag
0070 >::value,
0071 spherical_polar_tag, spherical_equatorial_tag
0072 >,
0073 typename Strategies::cs_tag
0074 > cs_tag;
0075 typedef geometry::detail::disjoint::
0076 disjoint_segment_box_sphere_or_spheroid<cs_tag>
0077 disjoint_sb;
0078 typedef typename disjoint_sb::disjoint_info disjoint_info_type;
0079
0080 segment_type seg(p0, p1);
0081
0082 geometry::model::box<BoxPoint> input_box;
0083 geometry::set_from_radian<geometry::min_corner, 0>
0084 (input_box, geometry::get_as_radian<0>(bottom_left));
0085 geometry::set_from_radian<geometry::min_corner, 1>
0086 (input_box, geometry::get_as_radian<1>(bottom_left));
0087 geometry::set_from_radian<geometry::max_corner, 0>
0088 (input_box, geometry::get_as_radian<0>(top_right));
0089 geometry::set_from_radian<geometry::max_corner, 1>
0090 (input_box, geometry::get_as_radian<1>(top_right));
0091
0092 SegmentPoint p_max;
0093
0094
0095
0096 disjoint_info_type disjoint_result = disjoint_sb::
0097 apply(seg, input_box, p_max,
0098 strategies.azimuth(),
0099 strategies.normalize(p0),
0100 strategies.covered_by(p0, input_box),
0101 strategies.disjoint(input_box, input_box));
0102
0103 if (disjoint_result == disjoint_info_type::intersect)
0104 {
0105 return 0;
0106 }
0107
0108 if (disjoint_result == disjoint_info_type::disjoint_no_vertex)
0109 {
0110 typedef typename coordinate_type<SegmentPoint>::type CT;
0111
0112 geometry::model::box<SegmentPoint> mbr;
0113 geometry::envelope(seg, mbr, strategies);
0114
0115 CT lon1 = geometry::get_as_radian<0>(p0);
0116 CT lat1 = geometry::get_as_radian<1>(p0);
0117 CT lon2 = geometry::get_as_radian<0>(p1);
0118 CT lat2 = geometry::get_as_radian<1>(p1);
0119
0120 if (lon1 > lon2)
0121 {
0122 std::swap(lon1, lon2);
0123 std::swap(lat1, lat2);
0124 }
0125
0126 CT vertex_lat;
0127 CT lat_sum = lat1 + lat2;
0128 if (lat_sum > CT(0))
0129 {
0130 vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(mbr);
0131 } else {
0132 vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(mbr);
0133 }
0134
0135 CT alp1;
0136 strategies.azimuth().apply(lon1, lat1, lon2, lat2, alp1);
0137
0138
0139 CT vertex_lon = geometry::formula::vertex_longitude
0140 <
0141 CT,
0142 cs_tag
0143 >::apply(lon1, lat1, lon2, lat2,
0144 vertex_lat, alp1, strategies.azimuth());
0145
0146 geometry::set_from_radian<0>(p_max, vertex_lon);
0147 geometry::set_from_radian<1>(p_max, vertex_lat);
0148 }
0149
0150
0151 if (less_equal(geometry::get_as_radian<0>(bottom_left),
0152 geometry::get_as_radian<0>(p_max)))
0153 {
0154 result = util::numeric_cast<ReturnType>(
0155 strategies.distance(bottom_left, seg).apply(bottom_left, p0, p1));
0156 }
0157 else
0158 {
0159
0160 result = geometry::detail::distance::segment_to_box_2D
0161 <
0162 ReturnType,
0163 SegmentPoint,
0164 BoxPoint,
0165 Strategies
0166 >::template call_above_of_box
0167 <
0168 typename LessEqual::other
0169 >(p1, p0, p_max, bottom_right, strategies);
0170 }
0171 return result;
0172 }
0173
0174 template <typename SPoint, typename BPoint>
0175 static void mirror(SPoint& p0,
0176 SPoint& p1,
0177 BPoint& bottom_left,
0178 BPoint& bottom_right,
0179 BPoint& top_left,
0180 BPoint& top_right)
0181 {
0182
0183 if (geometry::get<1>(p0) + geometry::get<1>(p1) < 0)
0184 {
0185 BPoint bl = bottom_left;
0186 BPoint br = bottom_right;
0187 geometry::set<1>(p0, geometry::get<1>(p0) * -1);
0188 geometry::set<1>(p1, geometry::get<1>(p1) * -1);
0189 geometry::set<1>(bottom_left, geometry::get<1>(top_left) * -1);
0190 geometry::set<1>(top_left, geometry::get<1>(bl) * -1);
0191 geometry::set<1>(bottom_right, geometry::get<1>(top_right) * -1);
0192 geometry::set<1>(top_right, geometry::get<1>(br) * -1);
0193 }
0194 }
0195 };
0196
0197
0198
0199 template
0200 <
0201 typename CalculationType = void,
0202 typename Strategy = haversine<double, CalculationType>
0203 >
0204 struct spherical_segment_box
0205 {
0206 template <typename PointOfSegment, typename PointOfBox>
0207 struct calculation_type
0208 : promote_floating_point
0209 <
0210 typename strategy::distance::services::return_type
0211 <
0212 Strategy,
0213 PointOfSegment,
0214 PointOfBox
0215 >::type
0216 >
0217 {};
0218
0219 typedef spherical_tag cs_tag;
0220
0221
0222
0223 inline spherical_segment_box()
0224 {}
0225
0226 explicit inline spherical_segment_box(typename Strategy::radius_type const& r)
0227 : m_strategy(r)
0228 {}
0229
0230 inline spherical_segment_box(Strategy const& s)
0231 : m_strategy(s)
0232 {}
0233
0234 typename Strategy::radius_type radius() const
0235 {
0236 return m_strategy.radius();
0237 }
0238
0239
0240
0241 template
0242 <
0243 typename LessEqual, typename ReturnType,
0244 typename SegmentPoint, typename BoxPoint,
0245 typename Strategies
0246 >
0247 inline ReturnType segment_below_of_box(SegmentPoint const& p0,
0248 SegmentPoint const& p1,
0249 BoxPoint const& top_left,
0250 BoxPoint const& top_right,
0251 BoxPoint const& bottom_left,
0252 BoxPoint const& bottom_right,
0253 Strategies const& strategies) const
0254 {
0255 return generic_segment_box::segment_below_of_box
0256 <
0257 LessEqual,
0258 ReturnType
0259 >(p0,p1,top_left,top_right,bottom_left,bottom_right,
0260 strategies);
0261 }
0262
0263 template <typename SPoint, typename BPoint>
0264 static void mirror(SPoint& p0,
0265 SPoint& p1,
0266 BPoint& bottom_left,
0267 BPoint& bottom_right,
0268 BPoint& top_left,
0269 BPoint& top_right)
0270 {
0271
0272 generic_segment_box::mirror(p0, p1,
0273 bottom_left, bottom_right,
0274 top_left, top_right);
0275 }
0276
0277 private:
0278 Strategy m_strategy;
0279 };
0280
0281 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0282 namespace services
0283 {
0284
0285 template <typename CalculationType, typename Strategy>
0286 struct tag<spherical_segment_box<CalculationType, Strategy> >
0287 {
0288 typedef strategy_tag_distance_segment_box type;
0289 };
0290
0291 template <typename CalculationType, typename Strategy, typename PS, typename PB>
0292 struct return_type<spherical_segment_box<CalculationType, Strategy>, PS, PB>
0293 : spherical_segment_box<CalculationType, Strategy>::template calculation_type<PS, PB>
0294 {};
0295
0296 template <typename CalculationType, typename Strategy>
0297 struct comparable_type<spherical_segment_box<CalculationType, Strategy> >
0298 {
0299
0300
0301 typedef spherical_segment_box
0302 <
0303 CalculationType,
0304 typename comparable_type<Strategy>::type
0305 > type;
0306 };
0307
0308
0309 template <typename CalculationType, typename Strategy>
0310 struct get_comparable<spherical_segment_box<CalculationType, Strategy> >
0311 {
0312 typedef typename comparable_type
0313 <
0314 spherical_segment_box<CalculationType, Strategy>
0315 >::type comparable_type;
0316 public :
0317 static inline comparable_type apply(spherical_segment_box<CalculationType, Strategy> const& )
0318 {
0319 return comparable_type();
0320 }
0321 };
0322
0323 template <typename CalculationType, typename Strategy, typename PS, typename PB>
0324 struct result_from_distance<spherical_segment_box<CalculationType, Strategy>, PS, PB>
0325 {
0326 private :
0327 typedef typename return_type<
0328 spherical_segment_box
0329 <
0330 CalculationType,
0331 Strategy
0332 >,
0333 PS,
0334 PB
0335 >::type return_type;
0336 public :
0337 template <typename T>
0338 static inline return_type apply(spherical_segment_box<CalculationType,
0339 Strategy> const& ,
0340 T const& value)
0341 {
0342 Strategy s;
0343 return result_from_distance<Strategy, PS, PB>::apply(s, value);
0344 }
0345 };
0346
0347 template <typename Segment, typename Box>
0348 struct default_strategy
0349 <
0350 segment_tag, box_tag, Segment, Box,
0351 spherical_equatorial_tag, spherical_equatorial_tag
0352 >
0353 {
0354 typedef spherical_segment_box<> type;
0355 };
0356
0357 template <typename Box, typename Segment>
0358 struct default_strategy
0359 <
0360 box_tag, segment_tag, Box, Segment,
0361 spherical_equatorial_tag, spherical_equatorial_tag
0362 >
0363 {
0364 typedef typename default_strategy
0365 <
0366 segment_tag, box_tag, Segment, Box,
0367 spherical_equatorial_tag, spherical_equatorial_tag
0368 >::type type;
0369 };
0370
0371 }
0372 #endif
0373
0374 }}
0375
0376 }}
0377 #endif