File indexing completed on 2025-01-18 09:35:04
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 typedef typename point_type<Segment>::type segment_point;
0088 segment_point vertex;
0089 return apply(segment, box, vertex,
0090 azimuth_strategy,
0091 normalize_strategy,
0092 disjoint_point_box_strategy,
0093 disjoint_box_box_strategy) != disjoint_info::intersect;
0094 }
0095
0096 template
0097 <
0098 typename Segment, typename Box,
0099 typename P,
0100 typename AzimuthStrategy,
0101 typename NormalizeStrategy,
0102 typename DisjointPointBoxStrategy,
0103 typename DisjointBoxBoxStrategy
0104 >
0105 static inline disjoint_info apply(Segment const& segment,
0106 Box const& box,
0107 P& vertex,
0108 AzimuthStrategy const& azimuth_strategy,
0109 NormalizeStrategy const& ,
0110 DisjointPointBoxStrategy const& disjoint_point_box_strategy,
0111 DisjointBoxBoxStrategy const& disjoint_box_box_strategy)
0112 {
0113 assert_dimension_equal<Segment, Box>();
0114
0115 typedef typename point_type<Segment>::type segment_point_type;
0116
0117 segment_point_type p0, p1;
0118 geometry::detail::assign_point_from_index<0>(segment, p0);
0119 geometry::detail::assign_point_from_index<1>(segment, p1);
0120
0121
0122 disjoint_info disjoint_return_value = disjoint_info::disjoint_no_vertex;
0123
0124
0125
0126
0127 if ( ! disjoint_point_box(p0, box, disjoint_point_box_strategy)
0128 || ! disjoint_point_box(p1, box, disjoint_point_box_strategy) )
0129 {
0130 return disjoint_info::intersect;
0131 }
0132
0133
0134
0135 typedef typename coordinate_type<segment_point_type>::type CT;
0136
0137 segment_point_type p0_normalized;
0138 NormalizeStrategy::apply(p0, p0_normalized);
0139 segment_point_type p1_normalized;
0140 NormalizeStrategy::apply(p1, p1_normalized);
0141
0142 CT lon1 = geometry::get_as_radian<0>(p0_normalized);
0143 CT lat1 = geometry::get_as_radian<1>(p0_normalized);
0144 CT lon2 = geometry::get_as_radian<0>(p1_normalized);
0145 CT lat2 = geometry::get_as_radian<1>(p1_normalized);
0146
0147 if (lon1 > lon2)
0148 {
0149 std::swap(lon1, lon2);
0150 std::swap(lat1, lat2);
0151 }
0152
0153 geometry::model::box<segment_point_type> box_seg;
0154
0155 strategy::envelope::detail::envelope_segment_impl
0156 <
0157 CS_Tag
0158 >::template apply<geometry::radian>(lon1, lat1,
0159 lon2, lat2,
0160 box_seg,
0161 azimuth_strategy);
0162
0163 if (disjoint_box_box(box, box_seg, disjoint_box_box_strategy))
0164 {
0165 return disjoint_return_value;
0166 }
0167
0168
0169
0170 CT alp1, a_b0, a_b1, a_b2, a_b3;
0171
0172 CT b_lon_min = geometry::get_as_radian<geometry::min_corner, 0>(box);
0173 CT b_lat_min = geometry::get_as_radian<geometry::min_corner, 1>(box);
0174 CT b_lon_max = geometry::get_as_radian<geometry::max_corner, 0>(box);
0175 CT b_lat_max = geometry::get_as_radian<geometry::max_corner, 1>(box);
0176
0177 azimuth_strategy.apply(lon1, lat1, lon2, lat2, alp1);
0178 azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_min, a_b0);
0179 azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_min, a_b1);
0180 azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_max, a_b2);
0181 azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_max, a_b3);
0182
0183 int s0 = formula::azimuth_side_value(alp1, a_b0);
0184 int s1 = formula::azimuth_side_value(alp1, a_b1);
0185 int s2 = formula::azimuth_side_value(alp1, a_b2);
0186 int s3 = formula::azimuth_side_value(alp1, a_b3);
0187
0188 if (s0 == 0 || s1 == 0 || s2 == 0 || s3 == 0)
0189 {
0190 return disjoint_info::intersect;
0191 }
0192
0193 bool s0_positive = s0 > 0;
0194 bool s1_positive = s1 > 0;
0195 bool s2_positive = s2 > 0;
0196 bool s3_positive = s3 > 0;
0197
0198 bool all_positive = s0_positive && s1_positive && s2_positive && s3_positive;
0199 bool all_non_positive = !(s0_positive || s1_positive || s2_positive || s3_positive);
0200 bool vertex_north = lat1 + lat2 > 0;
0201
0202 if ((all_positive && vertex_north) || (all_non_positive && !vertex_north))
0203 {
0204 return disjoint_info::disjoint_no_vertex;
0205 }
0206
0207 if (!all_positive && !all_non_positive)
0208 {
0209 return disjoint_info::intersect;
0210 }
0211
0212
0213
0214
0215
0216 CT vertex_lat;
0217
0218 if ((lat1 < b_lat_min && vertex_north)
0219 || (lat1 > b_lat_max && !vertex_north))
0220 {
0221 CT b_lat_below;
0222
0223 if (vertex_north)
0224 {
0225 vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(box_seg);
0226 b_lat_below = b_lat_min;
0227 } else {
0228 vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(box_seg);
0229 b_lat_below = b_lat_max;
0230 }
0231
0232
0233
0234 CT vertex_lon = geometry::formula::vertex_longitude<CT, CS_Tag>
0235 ::apply(lon1, lat1,
0236 lon2, lat2,
0237 vertex_lat,
0238 alp1,
0239 azimuth_strategy);
0240
0241 geometry::set_from_radian<0>(vertex, vertex_lon);
0242 geometry::set_from_radian<1>(vertex, vertex_lat);
0243 disjoint_return_value = disjoint_info::disjoint_vertex;
0244
0245
0246
0247
0248
0249 if (vertex_lon >= b_lon_min && vertex_lon <= b_lon_max
0250 && std::abs(vertex_lat) > std::abs(b_lat_below))
0251 {
0252 return disjoint_info::intersect;
0253 }
0254 }
0255
0256 return disjoint_return_value;
0257 }
0258 };
0259
0260 struct disjoint_segment_box
0261 {
0262 template <typename Segment, typename Box, typename Strategy>
0263 static inline bool apply(Segment const& segment,
0264 Box const& box,
0265 Strategy const& strategy)
0266 {
0267 return strategy.disjoint(segment, box).apply(segment, box);
0268 }
0269 };
0270
0271 }}
0272 #endif
0273
0274
0275 #ifndef DOXYGEN_NO_DISPATCH
0276 namespace dispatch
0277 {
0278
0279
0280 template <typename Segment, typename Box, std::size_t DimensionCount>
0281 struct disjoint<Segment, Box, DimensionCount, segment_tag, box_tag, false>
0282 : detail::disjoint::disjoint_segment_box
0283 {};
0284
0285
0286 }
0287 #endif
0288
0289
0290 }}
0291
0292
0293 #endif