distance.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Boost.Geometry
  2. // Copyright (c) 2017 Oracle and/or its affiliates.
  3. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  4. // Use, modification and distribution is subject to the Boost Software License,
  5. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #include <geometry_test_common.hpp>
  8. #include <boost/concept_check.hpp>
  9. #include <boost/geometry/srs/srs.hpp>
  10. #include <boost/geometry/algorithms/assign.hpp>
  11. #include <boost/geometry/geometries/point.hpp>
  12. #include <boost/geometry/strategies/strategies.hpp>
  13. #include <test_common/test_point.hpp>
  14. #ifdef HAVE_TTMATH
  15. # include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
  16. #endif
  17. typedef bg::srs::spheroid<double> stype;
  18. typedef bg::strategy::andoyer andoyer_formula;
  19. typedef bg::strategy::thomas thomas_formula;
  20. typedef bg::strategy::vincenty vincenty_formula;
  21. template <typename P>
  22. bool non_precise_ct()
  23. {
  24. typedef typename bg::coordinate_type<P>::type ct;
  25. return boost::is_integral<ct>::value || boost::is_float<ct>::value;
  26. }
  27. template <typename P1, typename P2, typename FormulaPolicy>
  28. void test_distance(double lon1, double lat1, double lon2, double lat2)
  29. {
  30. typedef typename bg::promote_floating_point
  31. <
  32. typename bg::select_calculation_type<P1, P2, void>::type
  33. >::type calc_t;
  34. calc_t tolerance = non_precise_ct<P1>() || non_precise_ct<P2>() ?
  35. 5.0 : 0.001;
  36. P1 p1;
  37. P2 p2;
  38. bg::assign_values(p1, lon1, lat1);
  39. bg::assign_values(p2, lon2, lat2);
  40. // Test strategy that implements meridian distance against formula
  41. // that implements general distance
  42. // That may change in the future but in any case these calls must return
  43. // the same result
  44. calc_t dist_formula = FormulaPolicy::template inverse
  45. <
  46. double, true, false, false, false, false
  47. >::apply(lon1 * bg::math::d2r<double>(),
  48. lat1 * bg::math::d2r<double>(),
  49. lon2 * bg::math::d2r<double>(),
  50. lat2 * bg::math::d2r<double>(),
  51. stype()).distance;
  52. bg::strategy::distance::geographic<FormulaPolicy, stype> strategy;
  53. calc_t dist_strategy = strategy.apply(p1, p2);
  54. BOOST_CHECK_CLOSE(dist_formula, dist_strategy, tolerance);
  55. }
  56. template <typename P1, typename P2, typename FormulaPolicy>
  57. void test_distance_reverse(double lon1, double lat1,
  58. double lon2, double lat2)
  59. {
  60. test_distance<P1, P2, FormulaPolicy>(lon1, lat1, lon2, lat2);
  61. test_distance<P1, P2, FormulaPolicy>(lon2, lat2, lon1, lat1);
  62. }
  63. template <typename P1, typename P2, typename FormulaPolicy>
  64. void test_meridian()
  65. {
  66. test_distance_reverse<P1, P2, FormulaPolicy>(0., 70., 0., 80.);
  67. test_distance_reverse<P1, P2, FormulaPolicy>(0, 70, 0., -80.);
  68. test_distance_reverse<P1, P2, FormulaPolicy>(0., -70., 0., 80.);
  69. test_distance_reverse<P1, P2, FormulaPolicy>(0., -70., 0., -80.);
  70. test_distance_reverse<P1, P2, FormulaPolicy>(0., 70., 180., 80.);
  71. test_distance_reverse<P1, P2, FormulaPolicy>(0., 70., 180., -80.);
  72. test_distance_reverse<P1, P2, FormulaPolicy>(0., -70., 180., 80.);
  73. test_distance_reverse<P1, P2, FormulaPolicy>(0., -70., 180., -80.);
  74. test_distance_reverse<P1, P2, FormulaPolicy>(350., 70., 170., 80.);
  75. test_distance_reverse<P1, P2, FormulaPolicy>(350., 70., 170., -80.);
  76. test_distance_reverse<P1, P2, FormulaPolicy>(350., -70., 170., 80.);
  77. test_distance_reverse<P1, P2, FormulaPolicy>(350., -70., 170., -80.);
  78. }
  79. template <typename P>
  80. void test_all()
  81. {
  82. test_meridian<P, P, andoyer_formula>();
  83. test_meridian<P, P, thomas_formula>();
  84. test_meridian<P, P, vincenty_formula>();
  85. }
  86. int test_main(int, char* [])
  87. {
  88. test_all<bg::model::point<double, 2, bg::cs::geographic<bg::degree> > >();
  89. test_all<bg::model::point<float, 2, bg::cs::geographic<bg::degree> > >();
  90. test_all<bg::model::point<int, 2, bg::cs::geographic<bg::degree> > >();
  91. return 0;
  92. }