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