File indexing completed on 2025-09-15 08:36:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_HPP
0016 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_HPP
0017
0018
0019 #include <type_traits>
0020
0021 #include <boost/geometry/core/access.hpp>
0022 #include <boost/geometry/core/coordinate_dimension.hpp>
0023 #include <boost/geometry/core/coordinate_system.hpp>
0024 #include <boost/geometry/core/coordinate_type.hpp>
0025 #include <boost/geometry/core/cs.hpp>
0026 #include <boost/geometry/core/radian_access.hpp>
0027 #include <boost/geometry/core/tags.hpp>
0028
0029 #include <boost/geometry/strategies/compare.hpp>
0030
0031 #include <boost/geometry/util/math.hpp>
0032 #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
0033
0034
0035 namespace boost { namespace geometry
0036 {
0037
0038
0039 namespace strategy { namespace compare
0040 {
0041
0042
0043 #ifndef DOXYGEN_NO_DETAIL
0044 namespace detail
0045 {
0046
0047 template <std::size_t I, typename P>
0048 static inline geometry::coordinate_type_t<P>
0049 get(P const& p, std::true_type )
0050 {
0051 return geometry::get<I>(p);
0052 }
0053
0054 template <std::size_t I, typename P>
0055 static inline geometry::coordinate_type_t<P>
0056 get(P const& p, std::false_type )
0057 {
0058 return geometry::get_as_radian<I>(p);
0059 }
0060
0061 template
0062 <
0063 typename ComparePolicy,
0064 typename EqualsPolicy,
0065 typename Point1,
0066 typename Point2,
0067 std::size_t DimensionCount
0068 >
0069 struct spherical_latitude
0070 {
0071 using coordinate1_type = geometry::coordinate_type_t<Point1>;
0072 using units1_type = typename geometry::detail::cs_angular_units<Point1>::type;
0073 using coordinate2_type = geometry::coordinate_type_t<Point2>;
0074 using units2_type = typename geometry::detail::cs_angular_units<Point2>::type;
0075 using same_units_type = std::is_same<units1_type, units2_type>;
0076
0077 template <typename T1, typename T2>
0078 static inline bool apply(Point1 const& left, Point2 const& right,
0079 T1 const& l1, T2 const& r1)
0080 {
0081
0082 if (EqualsPolicy::apply(l1, r1))
0083 {
0084 return compare::detail::compare_loop
0085 <
0086 ComparePolicy, EqualsPolicy, 2, DimensionCount
0087 >::apply(left, right);
0088 }
0089 else
0090 {
0091 return ComparePolicy::apply(l1, r1);
0092 }
0093 }
0094
0095 static inline bool apply(Point1 const& left, Point2 const& right)
0096 {
0097 coordinate1_type const& l1 = compare::detail::get<1>(left, same_units_type());
0098 coordinate2_type const& r1 = compare::detail::get<1>(right, same_units_type());
0099
0100 return apply(left, right, l1, r1);
0101 }
0102 };
0103
0104 template
0105 <
0106 typename ComparePolicy,
0107 typename EqualsPolicy,
0108 typename Point1,
0109 typename Point2
0110 >
0111 struct spherical_latitude<ComparePolicy, EqualsPolicy, Point1, Point2, 1>
0112 {
0113 template <typename T1, typename T2>
0114 static inline bool apply(Point1 const& left, Point2 const& right,
0115 T1 const& , T2 const& )
0116 {
0117 return apply(left, right);
0118 }
0119
0120 static inline bool apply(Point1 const& left, Point2 const& right)
0121 {
0122 return compare::detail::compare_loop
0123 <
0124 ComparePolicy, EqualsPolicy, 1, 1
0125 >::apply(left, right);
0126 }
0127 };
0128
0129 template
0130 <
0131 typename ComparePolicy,
0132 typename EqualsPolicy,
0133 typename Point1,
0134 typename Point2,
0135 std::size_t DimensionCount
0136 >
0137 struct spherical_longitude
0138 {
0139 using coordinate1_type = geometry::coordinate_type_t<Point1>;
0140 using units1_type = typename geometry::detail::cs_angular_units<Point1>::type;
0141 using coordinate2_type = geometry::coordinate_type_t<Point2>;
0142 using units2_type = typename geometry::detail::cs_angular_units<Point2>::type;
0143 using same_units_type = std::is_same<units1_type, units2_type>;
0144 using units_type = std::conditional_t<same_units_type::value, units1_type, geometry::radian>;
0145
0146 static const bool is_equatorial =
0147 ! std::is_same<geometry::cs_tag_t<Point1>, geometry::spherical_polar_tag>::value;
0148
0149 static inline bool are_both_at_antimeridian(coordinate1_type const& l0,
0150 coordinate2_type const& r0,
0151 bool & is_left_at,
0152 bool & is_right_at)
0153 {
0154 is_left_at = math::is_longitude_antimeridian<units_type>(l0);
0155 is_right_at = math::is_longitude_antimeridian<units_type>(r0);
0156 return is_left_at && is_right_at;
0157 }
0158
0159 static inline bool apply(Point1 const& left, Point2 const& right)
0160 {
0161
0162 coordinate1_type const& l0 = compare::detail::get<0>(left, same_units_type());
0163 coordinate2_type const& r0 = compare::detail::get<0>(right, same_units_type());
0164 coordinate1_type const& l1 = compare::detail::get<1>(left, same_units_type());
0165 coordinate2_type const& r1 = compare::detail::get<1>(right, same_units_type());
0166
0167 bool is_left_at_antimeridian = false;
0168 bool is_right_at_antimeridian = false;
0169
0170
0171 if (EqualsPolicy::apply(l0, r0)
0172
0173 || are_both_at_antimeridian(l0, r0, is_left_at_antimeridian, is_right_at_antimeridian)
0174
0175 || (EqualsPolicy::apply(l1, r1)
0176 && math::is_latitude_pole<units_type, is_equatorial>(l1)))
0177 {
0178 return spherical_latitude
0179 <
0180 ComparePolicy, EqualsPolicy, Point1, Point2, DimensionCount
0181 >::apply(left, right, l1, r1);
0182 }
0183
0184
0185 else if (is_left_at_antimeridian)
0186 {
0187
0188 return ComparePolicy::apply(1, 0);
0189 }
0190
0191
0192 else if (is_right_at_antimeridian)
0193 {
0194
0195 return ComparePolicy::apply(0, 1);
0196 }
0197 else
0198 {
0199 return ComparePolicy::apply(l0, r0);
0200 }
0201 }
0202 };
0203
0204
0205 }
0206 #endif
0207
0208
0209
0210
0211
0212
0213
0214
0215 template
0216 <
0217 typename ComparePolicy,
0218 typename EqualsPolicy,
0219 int Dimension = -1
0220 >
0221 struct spherical
0222 : cartesian<ComparePolicy, EqualsPolicy, Dimension>
0223 {};
0224
0225 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0226
0227 template <typename ComparePolicy, typename EqualsPolicy>
0228 struct spherical<ComparePolicy, EqualsPolicy, -1>
0229 {
0230 template <typename Point1, typename Point2>
0231 static inline bool apply(Point1 const& left, Point2 const& right)
0232 {
0233 return compare::detail::spherical_longitude
0234 <
0235 ComparePolicy,
0236 EqualsPolicy,
0237 Point1,
0238 Point2,
0239 std::conditional_t
0240 <
0241 (dimension<Point1>::value < dimension<Point2>::value),
0242 std::integral_constant<std::size_t, dimension<Point1>::value>,
0243 std::integral_constant<std::size_t, dimension<Point2>::value>
0244 >::value
0245 >::apply(left, right);
0246 }
0247 };
0248
0249
0250 template <typename ComparePolicy, typename EqualsPolicy>
0251 struct spherical<ComparePolicy, EqualsPolicy, 0>
0252 {
0253 template <typename Point1, typename Point2>
0254 static inline bool apply(Point1 const& left, Point2 const& right)
0255 {
0256 return compare::detail::spherical_longitude
0257 <
0258 ComparePolicy, EqualsPolicy, Point1, Point2, 1
0259 >::apply(left, right);
0260 }
0261 };
0262
0263
0264 template <typename ComparePolicy, typename EqualsPolicy>
0265 struct spherical<ComparePolicy, EqualsPolicy, 1>
0266 {
0267 template <typename Point1, typename Point2>
0268 static inline bool apply(Point1 const& left, Point2 const& right)
0269 {
0270 return compare::detail::spherical_latitude
0271 <
0272 ComparePolicy, EqualsPolicy, Point1, Point2, 2
0273 >::apply(left, right);
0274 }
0275 };
0276
0277 #endif
0278
0279
0280 namespace services
0281 {
0282
0283
0284 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0285 struct default_strategy
0286 <
0287 ComparePolicy, EqualsPolicy,
0288 Point1, Point2, Dimension,
0289 spherical_tag, spherical_tag
0290 >
0291 {
0292 typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0293 };
0294
0295 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0296 struct default_strategy
0297 <
0298 ComparePolicy, EqualsPolicy,
0299 Point1, Point2, Dimension,
0300 spherical_polar_tag, spherical_polar_tag
0301 >
0302 {
0303 typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0304 };
0305
0306 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0307 struct default_strategy
0308 <
0309 ComparePolicy, EqualsPolicy,
0310 Point1, Point2, Dimension,
0311 spherical_equatorial_tag, spherical_equatorial_tag
0312 >
0313 {
0314 typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0315 };
0316
0317 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0318 struct default_strategy
0319 <
0320 ComparePolicy, EqualsPolicy,
0321 Point1, Point2, Dimension,
0322 geographic_tag, geographic_tag
0323 >
0324 {
0325 typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0326 };
0327
0328
0329 }
0330
0331
0332 }}
0333
0334
0335 }}
0336
0337 #endif