File indexing completed on 2025-01-18 09:36:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_POINT_BOX_HPP
0019 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_POINT_BOX_HPP
0020
0021
0022 #include <type_traits>
0023
0024 #include <boost/config.hpp>
0025 #include <boost/concept_check.hpp>
0026
0027 #include <boost/geometry/core/access.hpp>
0028 #include <boost/geometry/core/assert.hpp>
0029 #include <boost/geometry/core/point_type.hpp>
0030 #include <boost/geometry/core/radian_access.hpp>
0031 #include <boost/geometry/core/tags.hpp>
0032
0033 #include <boost/geometry/strategies/distance.hpp>
0034 #include <boost/geometry/strategies/concepts/distance_concept.hpp>
0035 #include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
0036
0037 #include <boost/geometry/util/math.hpp>
0038 #include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
0039
0040
0041 namespace boost { namespace geometry
0042 {
0043
0044 namespace strategy { namespace distance
0045 {
0046
0047 namespace details
0048 {
0049
0050 template <typename ReturnType>
0051 class cross_track_point_box_generic
0052 {
0053 public :
0054
0055 template
0056 <
0057 typename Point,
0058 typename Box,
0059 typename Strategy
0060 >
0061 ReturnType static inline apply (Point const& point,
0062 Box const& box,
0063 Strategy ps_strategy)
0064 {
0065
0066
0067
0068 typedef typename point_type<Box>::type box_point_type;
0069
0070 box_point_type bottom_left, bottom_right, top_left, top_right;
0071 geometry::detail::assign_box_corners(box,
0072 bottom_left, bottom_right,
0073 top_left, top_right);
0074
0075 ReturnType const plon = geometry::get_as_radian<0>(point);
0076 ReturnType const plat = geometry::get_as_radian<1>(point);
0077
0078 ReturnType const lon_min = geometry::get_as_radian<0>(bottom_left);
0079 ReturnType const lat_min = geometry::get_as_radian<1>(bottom_left);
0080 ReturnType const lon_max = geometry::get_as_radian<0>(top_right);
0081 ReturnType const lat_max = geometry::get_as_radian<1>(top_right);
0082
0083 ReturnType const pi = math::pi<ReturnType>();
0084 ReturnType const two_pi = math::two_pi<ReturnType>();
0085
0086 typedef typename point_type<Box>::type box_point_type;
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 if ((plon >= lon_min && plon <= lon_max) || plon + two_pi <= lon_max)
0098 {
0099 if (plat > lat_max)
0100 {
0101 return geometry::strategy::distance::services::result_from_distance
0102 <
0103 Strategy, Point, box_point_type
0104 >::apply(ps_strategy, ps_strategy
0105 .vertical_or_meridian(plat, lat_max));
0106 }
0107 else if (plat < lat_min)
0108 {
0109 return geometry::strategy::distance::services::result_from_distance
0110 <
0111 Strategy, Point, box_point_type
0112 >::apply(ps_strategy, ps_strategy
0113 .vertical_or_meridian(lat_min, plat));
0114 }
0115 else
0116 {
0117 BOOST_GEOMETRY_ASSERT(plat >= lat_min && plat <= lat_max);
0118 return ReturnType(0);
0119 }
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 ReturnType const two = 2.0;
0131 bool use_left_segment;
0132 if (lon_max > pi)
0133 {
0134
0135
0136
0137 ReturnType const lon_midway = (lon_min - lon_max) / two + pi;
0138 BOOST_GEOMETRY_ASSERT(lon_midway >= -pi && lon_midway <= pi);
0139
0140 use_left_segment = plon > lon_midway;
0141 }
0142 else
0143 {
0144
0145
0146 ReturnType const lon_sum = lon_min + lon_max;
0147 if (math::equals(lon_sum, ReturnType(0)))
0148 {
0149
0150
0151
0152 use_left_segment = plon < lon_min;
0153 }
0154 else
0155 {
0156
0157 ReturnType lon_midway = (lon_min + lon_max) / two - pi;
0158
0159
0160 if (lon_midway > pi)
0161 {
0162 lon_midway -= two_pi;
0163 }
0164 else if (lon_midway < -pi)
0165 {
0166 lon_midway += two_pi;
0167 }
0168 BOOST_GEOMETRY_ASSERT(lon_midway >= -pi && lon_midway <= pi);
0169
0170
0171
0172 use_left_segment = lon_sum > 0
0173 ? (plon < lon_min && plon >= lon_midway)
0174 : (plon <= lon_max || plon > lon_midway);
0175 }
0176 }
0177
0178 return use_left_segment
0179 ? ps_strategy.apply(point, bottom_left, top_left)
0180 : ps_strategy.apply(point, bottom_right, top_right);
0181 }
0182 };
0183
0184 }
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 template
0199 <
0200 typename CalculationType = void,
0201 typename Strategy = haversine<double, CalculationType>
0202 >
0203 class cross_track_point_box
0204 {
0205 public:
0206 template <typename Point, typename Box>
0207 struct return_type
0208 : services::return_type<Strategy, Point, typename point_type<Box>::type>
0209 {};
0210
0211 typedef typename Strategy::radius_type radius_type;
0212
0213
0214
0215
0216 struct distance_ps_strategy
0217 {
0218 typedef cross_track<CalculationType, Strategy> type;
0219 };
0220
0221 typedef typename strategy::distance::services::comparable_type
0222 <
0223 Strategy
0224 >::type pp_comparable_strategy;
0225
0226 typedef std::conditional_t
0227 <
0228 std::is_same
0229 <
0230 pp_comparable_strategy,
0231 Strategy
0232 >::value,
0233 typename strategy::distance::services::comparable_type
0234 <
0235 typename distance_ps_strategy::type
0236 >::type,
0237 typename distance_ps_strategy::type
0238 > ps_strategy_type;
0239
0240
0241
0242 inline cross_track_point_box()
0243 {}
0244
0245 explicit inline cross_track_point_box(typename Strategy::radius_type const& r)
0246 : m_strategy(r)
0247 {}
0248
0249 inline cross_track_point_box(Strategy const& s)
0250 : m_strategy(s)
0251 {}
0252
0253
0254
0255
0256
0257
0258
0259
0260 template <typename Point, typename Box>
0261 inline typename return_type<Point, Box>::type
0262 apply(Point const& point, Box const& box) const
0263 {
0264 #if !defined(BOOST_MSVC)
0265 BOOST_CONCEPT_ASSERT
0266 (
0267 (concepts::PointDistanceStrategy
0268 <
0269 Strategy, Point, typename point_type<Box>::type
0270 >)
0271 );
0272 #endif
0273 typedef typename return_type<Point, Box>::type return_type;
0274 return details::cross_track_point_box_generic
0275 <return_type>::apply(point, box,
0276 ps_strategy_type(m_strategy));
0277 }
0278
0279 inline typename Strategy::radius_type radius() const
0280 {
0281 return m_strategy.radius();
0282 }
0283
0284 private:
0285 Strategy m_strategy;
0286 };
0287
0288
0289
0290 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0291 namespace services
0292 {
0293
0294 template <typename CalculationType, typename Strategy>
0295 struct tag<cross_track_point_box<CalculationType, Strategy> >
0296 {
0297 typedef strategy_tag_distance_point_box type;
0298 };
0299
0300
0301 template <typename CalculationType, typename Strategy, typename P, typename Box>
0302 struct return_type<cross_track_point_box<CalculationType, Strategy>, P, Box>
0303 : cross_track_point_box
0304 <
0305 CalculationType, Strategy
0306 >::template return_type<P, Box>
0307 {};
0308
0309
0310 template <typename CalculationType, typename Strategy>
0311 struct comparable_type<cross_track_point_box<CalculationType, Strategy> >
0312 {
0313 typedef cross_track_point_box
0314 <
0315 CalculationType, typename comparable_type<Strategy>::type
0316 > type;
0317 };
0318
0319
0320 template <typename CalculationType, typename Strategy>
0321 struct get_comparable<cross_track_point_box<CalculationType, Strategy> >
0322 {
0323 typedef cross_track_point_box<CalculationType, Strategy> this_strategy;
0324 typedef typename comparable_type<this_strategy>::type comparable_type;
0325
0326 public:
0327 static inline comparable_type apply(this_strategy const& strategy)
0328 {
0329 return comparable_type(strategy.radius());
0330 }
0331 };
0332
0333
0334 template <typename CalculationType, typename Strategy, typename P, typename Box>
0335 struct result_from_distance
0336 <
0337 cross_track_point_box<CalculationType, Strategy>, P, Box
0338 >
0339 {
0340 private:
0341 typedef cross_track_point_box<CalculationType, Strategy> this_strategy;
0342
0343 typedef typename this_strategy::template return_type
0344 <
0345 P, Box
0346 >::type return_type;
0347
0348 public:
0349 template <typename T>
0350 static inline return_type apply(this_strategy const& strategy,
0351 T const& distance)
0352 {
0353 Strategy s(strategy.radius());
0354
0355 return result_from_distance
0356 <
0357 Strategy, P, typename point_type<Box>::type
0358 >::apply(s, distance);
0359 }
0360 };
0361
0362
0363
0364
0365 template <typename Point, typename Box, typename Strategy>
0366 struct default_strategy
0367 <
0368 point_tag, box_tag, Point, Box,
0369 spherical_equatorial_tag, spherical_equatorial_tag,
0370 Strategy
0371 >
0372 {
0373 typedef cross_track_point_box
0374 <
0375 void,
0376 std::conditional_t
0377 <
0378 std::is_void<Strategy>::value,
0379 typename default_strategy
0380 <
0381 point_tag, point_tag,
0382 Point, typename point_type<Box>::type,
0383 spherical_equatorial_tag, spherical_equatorial_tag
0384 >::type,
0385 Strategy
0386 >
0387 > type;
0388 };
0389
0390
0391 template <typename Box, typename Point, typename Strategy>
0392 struct default_strategy
0393 <
0394 box_tag, point_tag, Box, Point,
0395 spherical_equatorial_tag, spherical_equatorial_tag,
0396 Strategy
0397 >
0398 {
0399 typedef typename default_strategy
0400 <
0401 point_tag, box_tag, Point, Box,
0402 spherical_equatorial_tag, spherical_equatorial_tag,
0403 Strategy
0404 >::type type;
0405 };
0406
0407
0408 }
0409 #endif
0410
0411
0412 }}
0413
0414
0415 }}
0416
0417
0418 #endif