File indexing completed on 2024-11-16 09:14:54
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 typename geometry::coordinate_type<P>::type
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 typename geometry::coordinate_type<P>::type
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 typedef typename geometry::coordinate_type<Point1>::type coordinate1_type;
0072 typedef typename geometry::detail::cs_angular_units<Point1>::type units1_type;
0073 typedef typename geometry::coordinate_type<Point2>::type coordinate2_type;
0074 typedef typename geometry::detail::cs_angular_units<Point2>::type units2_type;
0075 typedef std::is_same<units1_type, units2_type> same_units_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 typedef typename geometry::coordinate_type<Point1>::type coordinate1_type;
0140 typedef typename geometry::detail::cs_angular_units<Point1>::type units1_type;
0141 typedef typename geometry::coordinate_type<Point2>::type coordinate2_type;
0142 typedef typename geometry::detail::cs_angular_units<Point2>::type units2_type;
0143 typedef std::is_same<units1_type, units2_type> same_units_type;
0144 typedef std::conditional_t<same_units_type::value, units1_type, geometry::radian> units_type;
0145
0146 static const bool is_equatorial = ! std::is_same
0147 <
0148 typename geometry::cs_tag<Point1>::type,
0149 geometry::spherical_polar_tag
0150 >::value;
0151
0152 static inline bool are_both_at_antimeridian(coordinate1_type const& l0,
0153 coordinate2_type const& r0,
0154 bool & is_left_at,
0155 bool & is_right_at)
0156 {
0157 is_left_at = math::is_longitude_antimeridian<units_type>(l0);
0158 is_right_at = math::is_longitude_antimeridian<units_type>(r0);
0159 return is_left_at && is_right_at;
0160 }
0161
0162 static inline bool apply(Point1 const& left, Point2 const& right)
0163 {
0164
0165 coordinate1_type const& l0 = compare::detail::get<0>(left, same_units_type());
0166 coordinate2_type const& r0 = compare::detail::get<0>(right, same_units_type());
0167 coordinate1_type const& l1 = compare::detail::get<1>(left, same_units_type());
0168 coordinate2_type const& r1 = compare::detail::get<1>(right, same_units_type());
0169
0170 bool is_left_at_antimeridian = false;
0171 bool is_right_at_antimeridian = false;
0172
0173
0174 if (EqualsPolicy::apply(l0, r0)
0175
0176 || are_both_at_antimeridian(l0, r0, is_left_at_antimeridian, is_right_at_antimeridian)
0177
0178 || (EqualsPolicy::apply(l1, r1)
0179 && math::is_latitude_pole<units_type, is_equatorial>(l1)))
0180 {
0181 return spherical_latitude
0182 <
0183 ComparePolicy, EqualsPolicy, Point1, Point2, DimensionCount
0184 >::apply(left, right, l1, r1);
0185 }
0186
0187
0188 else if (is_left_at_antimeridian)
0189 {
0190
0191 return ComparePolicy::apply(1, 0);
0192 }
0193
0194
0195 else if (is_right_at_antimeridian)
0196 {
0197
0198 return ComparePolicy::apply(0, 1);
0199 }
0200 else
0201 {
0202 return ComparePolicy::apply(l0, r0);
0203 }
0204 }
0205 };
0206
0207
0208 }
0209 #endif
0210
0211
0212
0213
0214
0215
0216
0217
0218 template
0219 <
0220 typename ComparePolicy,
0221 typename EqualsPolicy,
0222 int Dimension = -1
0223 >
0224 struct spherical
0225 : cartesian<ComparePolicy, EqualsPolicy, Dimension>
0226 {};
0227
0228 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0229
0230 template <typename ComparePolicy, typename EqualsPolicy>
0231 struct spherical<ComparePolicy, EqualsPolicy, -1>
0232 {
0233 template <typename Point1, typename Point2>
0234 static inline bool apply(Point1 const& left, Point2 const& right)
0235 {
0236 return compare::detail::spherical_longitude
0237 <
0238 ComparePolicy,
0239 EqualsPolicy,
0240 Point1,
0241 Point2,
0242 std::conditional_t
0243 <
0244 (dimension<Point1>::value < dimension<Point2>::value),
0245 std::integral_constant<std::size_t, dimension<Point1>::value>,
0246 std::integral_constant<std::size_t, dimension<Point2>::value>
0247 >::value
0248 >::apply(left, right);
0249 }
0250 };
0251
0252
0253 template <typename ComparePolicy, typename EqualsPolicy>
0254 struct spherical<ComparePolicy, EqualsPolicy, 0>
0255 {
0256 template <typename Point1, typename Point2>
0257 static inline bool apply(Point1 const& left, Point2 const& right)
0258 {
0259 return compare::detail::spherical_longitude
0260 <
0261 ComparePolicy, EqualsPolicy, Point1, Point2, 1
0262 >::apply(left, right);
0263 }
0264 };
0265
0266
0267 template <typename ComparePolicy, typename EqualsPolicy>
0268 struct spherical<ComparePolicy, EqualsPolicy, 1>
0269 {
0270 template <typename Point1, typename Point2>
0271 static inline bool apply(Point1 const& left, Point2 const& right)
0272 {
0273 return compare::detail::spherical_latitude
0274 <
0275 ComparePolicy, EqualsPolicy, Point1, Point2, 2
0276 >::apply(left, right);
0277 }
0278 };
0279
0280 #endif
0281
0282
0283 namespace services
0284 {
0285
0286
0287 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0288 struct default_strategy
0289 <
0290 ComparePolicy, EqualsPolicy,
0291 Point1, Point2, Dimension,
0292 spherical_tag, spherical_tag
0293 >
0294 {
0295 typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0296 };
0297
0298 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0299 struct default_strategy
0300 <
0301 ComparePolicy, EqualsPolicy,
0302 Point1, Point2, Dimension,
0303 spherical_polar_tag, spherical_polar_tag
0304 >
0305 {
0306 typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0307 };
0308
0309 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0310 struct default_strategy
0311 <
0312 ComparePolicy, EqualsPolicy,
0313 Point1, Point2, Dimension,
0314 spherical_equatorial_tag, spherical_equatorial_tag
0315 >
0316 {
0317 typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0318 };
0319
0320 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0321 struct default_strategy
0322 <
0323 ComparePolicy, EqualsPolicy,
0324 Point1, Point2, Dimension,
0325 geographic_tag, geographic_tag
0326 >
0327 {
0328 typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0329 };
0330
0331
0332 }
0333
0334
0335 }}
0336
0337
0338 }}
0339
0340 #endif