// Copyright (c) 2008-2016 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2016 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014, 2015, 2016.
+// This file was modified by Oracle on 2014-2017.
// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
typedef bg::srs::spheroid<rtype> stype;
typedef bg::strategy::distance::andoyer<stype> andoyer_type;
- typedef bg::detail::andoyer_inverse<rtype, true, false> andoyer_inverse_type;
+ typedef bg::formula::andoyer_inverse<rtype, true, false> andoyer_inverse_type;
BOOST_CONCEPT_ASSERT
(
return_type d_strategy = andoyer.apply(p1, p2);
return_type d_function = bg::distance(p1, p2, andoyer);
- return_type d_formula = andoyer_inverse_type::apply(to_rad(lon1), to_rad(lat1), to_rad(lon2), to_rad(lat2), stype()).distance;
+
+ double diff = bg::math::longitude_distance_signed<bg::degree>(lon1, lon2);
+ return_type d_formula;
+
+ // if the points lay on a meridian, distance strategy calls the special formula
+ // for meridian distance that returns different result than andoyer formula
+ // for nearly antipodal points
+ if (bg::math::equals(diff, 0.0)
+ || bg::math::equals(bg::math::abs(diff), 180.0))
+ {
+ d_formula = d_strategy;
+ }
+ else
+ {
+ d_formula = andoyer_inverse_type::apply(to_rad(lon1), to_rad(lat1),
+ to_rad(lon2), to_rad(lat2),
+ stype()).distance;
+ }
BOOST_CHECK_CLOSE(d_strategy / 1000.0, expected_km, 0.001);
BOOST_CHECK_CLOSE(d_function / 1000.0, expected_km, 0.001);
>::type rtype;
typedef bg::srs::spheroid<rtype> stype;
- typedef bg::detail::andoyer_inverse<rtype, false, true> andoyer_inverse_type;
+ typedef bg::formula::andoyer_inverse<rtype, false, true> andoyer_inverse_type;
rtype a_formula = andoyer_inverse_type::apply(to_rad(lon1), to_rad(lat1), to_rad(lon2), to_rad(lat2), stype()).azimuth;
}
template <typename P1, typename P2>
-void test_distazi(double lon1, double lat1, double lon2, double lat2, double expected_km, double expected_azimuth_deg)
+void test_distazi(double lon1, double lat1, double lon2, double lat2,
+ double expected_km, double expected_azimuth_deg)
{
test_distance<P1, P2>(lon1, lat1, lon2, lat2, expected_km);
test_azimuth<P1, P2>(lon1, lat1, lon2, lat2, expected_azimuth_deg);
// requires SW->NE
template <typename P1, typename P2>
-void test_distazi_symm(double lon1, double lat1, double lon2, double lat2, double expected_km, double expected_azimuth_deg)
+void test_distazi_symm(double lon1, double lat1, double lon2, double lat2,
+ double expected_km, double expected_azimuth_deg,
+ bool is_antipodal = false)
{
+ double d180 = is_antipodal ? 0 : 180;
test_distazi<P1, P2>(lon1, lat1, lon2, lat2, expected_km, expected_azimuth_deg);
test_distazi<P1, P2>(-lon1, lat1, -lon2, lat2, expected_km, -expected_azimuth_deg);
- test_distazi<P1, P2>(lon1, -lat1, lon2, -lat2, expected_km, 180 - expected_azimuth_deg);
- test_distazi<P1, P2>(-lon1, -lat1, -lon2, -lat2, expected_km, -180 + expected_azimuth_deg);
+ test_distazi<P1, P2>(lon1, -lat1, lon2, -lat2, expected_km, d180 - expected_azimuth_deg);
+ test_distazi<P1, P2>(-lon1, -lat1, -lon2, -lat2, expected_km, -d180 + expected_azimuth_deg);
}
template <typename P1, typename P2>
-void test_distazi_symmNS(double lon1, double lat1, double lon2, double lat2, double expected_km, double expected_azimuth_deg)
+void test_distazi_symmNS(double lon1, double lat1, double lon2, double lat2,
+ double expected_km, double expected_azimuth_deg)
{
test_distazi<P1, P2>(lon1, lat1, lon2, lat2, expected_km, expected_azimuth_deg);
test_distazi<P1, P2>(lon1, -lat1, lon2, -lat2, expected_km, 180 - expected_azimuth_deg);
// antipodal
// ok? in those cases shorter path would pass through a pole
// but 90 or -90 would be consistent with distance?
- test_distazi<P1, P2>(0, 0, 180, 0, 20037.5, 0.0);
- test_distazi<P1, P2>(0, 0, -180, 0, 20037.5, 0.0);
- test_distazi<P1, P2>(-90, 0, 90, 0, 20037.5, 0.0);
- test_distazi<P1, P2>(90, 0, -90, 0, 20037.5, 0.0);
+ test_distazi<P1, P2>(0, 0, 180, 0, 20003.9, 0.0);
+ test_distazi<P1, P2>(0, 0, -180, 0, 20003.9, 0.0);
+ test_distazi<P1, P2>(-90, 0, 90, 0, 20003.9, 0.0);
+ test_distazi<P1, P2>(90, 0, -90, 0, 20003.9, 0.0);
// 0, 45, 90 ...
for (int i = 0 ; i < 360 ; i += 45)
test_distazi_symm<P1, P2>(normlized_deg(l-44.99), -44.99, normlized_deg(l+135), 45, 20008.1, 0.0);
test_distazi_symm<P1, P2>(normlized_deg(l-44.999), -44.999, normlized_deg(l+135), 45, 20009.4, 0.0);
// antipodal
- test_distazi_symm<P1, P2>(normlized_deg(l-45), -45, normlized_deg(l+135), 45, 20020.7, 0.0);
+ test_distazi_symm<P1, P2>(normlized_deg(l-45), -45, normlized_deg(l+135), 45, 20003.92, 0.0, true);
}
/* SQL Server gives: