File indexing completed on 2025-09-16 08:34:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP
0023 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP
0024
0025 #include <cstddef>
0026
0027 #include <boost/geometry/core/tags.hpp>
0028 #include <boost/geometry/core/radian_access.hpp>
0029
0030 #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
0031 #include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
0032 #include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
0033 #include <boost/geometry/algorithms/detail/envelope/segment.hpp>
0034 #include <boost/geometry/algorithms/detail/normalize.hpp>
0035 #include <boost/geometry/algorithms/dispatch/disjoint.hpp>
0036
0037 #include <boost/geometry/formulas/vertex_longitude.hpp>
0038
0039 #include <boost/geometry/geometries/box.hpp>
0040
0041
0042 #include <boost/geometry/strategy/spherical/envelope_segment.hpp>
0043
0044 namespace boost { namespace geometry
0045 {
0046
0047
0048 #ifndef DOXYGEN_NO_DETAIL
0049 namespace detail { namespace disjoint
0050 {
0051
0052 template <typename CS_Tag>
0053 struct disjoint_segment_box_sphere_or_spheroid
0054 {
0055 struct disjoint_info
0056 {
0057 enum type
0058 {
0059 intersect,
0060 disjoint_no_vertex,
0061 disjoint_vertex
0062 };
0063 disjoint_info(type t) : m_(t){}
0064 operator type () const {return m_;}
0065 type m_;
0066 private :
0067
0068 template <typename T>
0069 operator T () const;
0070 };
0071
0072 template
0073 <
0074 typename Segment, typename Box,
0075 typename AzimuthStrategy,
0076 typename NormalizeStrategy,
0077 typename DisjointPointBoxStrategy,
0078 typename DisjointBoxBoxStrategy
0079 >
0080 static inline bool apply(Segment const& segment,
0081 Box const& box,
0082 AzimuthStrategy const& azimuth_strategy,
0083 NormalizeStrategy const& normalize_strategy,
0084 DisjointPointBoxStrategy const& disjoint_point_box_strategy,
0085 DisjointBoxBoxStrategy const& disjoint_box_box_strategy)
0086 {
0087 point_type_t<Segment> vertex;
0088 return apply(segment, box, vertex,
0089 azimuth_strategy,
0090 normalize_strategy,
0091 disjoint_point_box_strategy,
0092 disjoint_box_box_strategy) != disjoint_info::intersect;
0093 }
0094
0095 template
0096 <
0097 typename Segment, typename Box,
0098 typename P,
0099 typename AzimuthStrategy,
0100 typename NormalizeStrategy,
0101 typename DisjointPointBoxStrategy,
0102 typename DisjointBoxBoxStrategy
0103 >
0104 static inline disjoint_info apply(Segment const& segment,
0105 Box const& box,
0106 P& vertex,
0107 AzimuthStrategy const& azimuth_strategy,
0108 NormalizeStrategy const& ,
0109 DisjointPointBoxStrategy const& disjoint_point_box_strategy,
0110 DisjointBoxBoxStrategy const& disjoint_box_box_strategy)
0111 {
0112 assert_dimension_equal<Segment, Box>();
0113
0114 using segment_point_type = point_type_t<Segment>;
0115
0116 segment_point_type p0, p1;
0117 geometry::detail::assign_point_from_index<0>(segment, p0);
0118 geometry::detail::assign_point_from_index<1>(segment, p1);
0119
0120
0121 disjoint_info disjoint_return_value = disjoint_info::disjoint_no_vertex;
0122
0123
0124
0125
0126 if ( ! disjoint_point_box(p0, box, disjoint_point_box_strategy)
0127 || ! disjoint_point_box(p1, box, disjoint_point_box_strategy) )
0128 {
0129 return disjoint_info::intersect;
0130 }
0131
0132
0133
0134 using coor_t = coordinate_type_t<segment_point_type>;
0135
0136 segment_point_type p0_normalized;
0137 NormalizeStrategy::apply(p0, p0_normalized);
0138 segment_point_type p1_normalized;
0139 NormalizeStrategy::apply(p1, p1_normalized);
0140
0141 coor_t lon1 = geometry::get_as_radian<0>(p0_normalized);
0142 coor_t lat1 = geometry::get_as_radian<1>(p0_normalized);
0143 coor_t lon2 = geometry::get_as_radian<0>(p1_normalized);
0144 coor_t lat2 = geometry::get_as_radian<1>(p1_normalized);
0145
0146 if (lon1 > lon2)
0147 {
0148 std::swap(lon1, lon2);
0149 std::swap(lat1, lat2);
0150 }
0151
0152 geometry::model::box<segment_point_type> box_seg;
0153
0154 strategy::envelope::detail::envelope_segment_impl
0155 <
0156 CS_Tag
0157 >::template apply<geometry::radian>(lon1, lat1,
0158 lon2, lat2,
0159 box_seg,
0160 azimuth_strategy);
0161
0162 if (disjoint_box_box(box, box_seg, disjoint_box_box_strategy))
0163 {
0164 return disjoint_return_value;
0165 }
0166
0167
0168
0169 coor_t alp1, a_b0, a_b1, a_b2, a_b3;
0170
0171 coor_t b_lon_min = geometry::get_as_radian<geometry::min_corner, 0>(box);
0172 coor_t b_lat_min = geometry::get_as_radian<geometry::min_corner, 1>(box);
0173 coor_t b_lon_max = geometry::get_as_radian<geometry::max_corner, 0>(box);
0174 coor_t b_lat_max = geometry::get_as_radian<geometry::max_corner, 1>(box);
0175
0176 azimuth_strategy.apply(lon1, lat1, lon2, lat2, alp1);
0177 azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_min, a_b0);
0178 azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_min, a_b1);
0179 azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_max, a_b2);
0180 azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_max, a_b3);
0181
0182 int s0 = formula::azimuth_side_value(alp1, a_b0);
0183 int s1 = formula::azimuth_side_value(alp1, a_b1);
0184 int s2 = formula::azimuth_side_value(alp1, a_b2);
0185 int s3 = formula::azimuth_side_value(alp1, a_b3);
0186
0187 if (s0 == 0 || s1 == 0 || s2 == 0 || s3 == 0)
0188 {
0189 return disjoint_info::intersect;
0190 }
0191
0192 bool s0_positive = s0 > 0;
0193 bool s1_positive = s1 > 0;
0194 bool s2_positive = s2 > 0;
0195 bool s3_positive = s3 > 0;
0196
0197 bool all_positive = s0_positive && s1_positive && s2_positive && s3_positive;
0198 bool all_non_positive = !(s0_positive || s1_positive || s2_positive || s3_positive);
0199 bool vertex_north = lat1 + lat2 > 0;
0200
0201 if ((all_positive && vertex_north) || (all_non_positive && !vertex_north))
0202 {
0203 return disjoint_info::disjoint_no_vertex;
0204 }
0205
0206 if (!all_positive && !all_non_positive)
0207 {
0208 return disjoint_info::intersect;
0209 }
0210
0211
0212
0213
0214
0215 coor_t vertex_lat;
0216
0217 if ((lat1 < b_lat_min && vertex_north)
0218 || (lat1 > b_lat_max && !vertex_north))
0219 {
0220 coor_t b_lat_below;
0221
0222 if (vertex_north)
0223 {
0224 vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(box_seg);
0225 b_lat_below = b_lat_min;
0226 } else {
0227 vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(box_seg);
0228 b_lat_below = b_lat_max;
0229 }
0230
0231
0232
0233 coor_t vertex_lon = geometry::formula::vertex_longitude<coor_t, CS_Tag>
0234 ::apply(lon1, lat1,
0235 lon2, lat2,
0236 vertex_lat,
0237 alp1,
0238 azimuth_strategy);
0239
0240 geometry::set_from_radian<0>(vertex, vertex_lon);
0241 geometry::set_from_radian<1>(vertex, vertex_lat);
0242 disjoint_return_value = disjoint_info::disjoint_vertex;
0243
0244
0245
0246
0247
0248 if (vertex_lon >= b_lon_min && vertex_lon <= b_lon_max
0249 && std::abs(vertex_lat) > std::abs(b_lat_below))
0250 {
0251 return disjoint_info::intersect;
0252 }
0253 }
0254
0255 return disjoint_return_value;
0256 }
0257 };
0258
0259 struct disjoint_segment_box
0260 {
0261 template <typename Segment, typename Box, typename Strategy>
0262 static inline bool apply(Segment const& segment,
0263 Box const& box,
0264 Strategy const& strategy)
0265 {
0266 return strategy.disjoint(segment, box).apply(segment, box);
0267 }
0268 };
0269
0270 }}
0271 #endif
0272
0273
0274 #ifndef DOXYGEN_NO_DISPATCH
0275 namespace dispatch
0276 {
0277
0278
0279 template <typename Segment, typename Box, std::size_t DimensionCount>
0280 struct disjoint<Segment, Box, DimensionCount, segment_tag, box_tag, false>
0281 : detail::disjoint::disjoint_segment_box
0282 {};
0283
0284
0285 }
0286 #endif
0287
0288
0289 }}
0290
0291
0292 #endif