calculate_point_order.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Boost.Geometry
  2. // Unit Test
  3. // Copyright (c) 2019, Oracle and/or its affiliates.
  4. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  5. // Licensed under the Boost Software License version 1.0.
  6. // http://www.boost.org/users/license.html
  7. #include <geometry_test_common.hpp>
  8. #include <boost/geometry/algorithms/detail/calculate_point_order.hpp>
  9. #include <boost/geometry/geometries/point.hpp>
  10. #include <boost/geometry/geometries/ring.hpp>
  11. #include <boost/geometry/io/wkt/wkt.hpp>
  12. #include <boost/geometry/strategies/cartesian/point_order.hpp>
  13. #include <boost/geometry/strategies/geographic/point_order.hpp>
  14. #include <boost/geometry/strategies/spherical/point_order.hpp>
  15. inline const char * order_str(bg::order_selector o)
  16. {
  17. if (o == bg::clockwise)
  18. return "clockwise";
  19. else if (o == bg::counterclockwise)
  20. return "counterclockwise";
  21. else
  22. return "order_undetermined";
  23. }
  24. inline const char * cs_str(bg::cartesian_tag)
  25. {
  26. return "cartesian";
  27. }
  28. inline const char * cs_str(bg::spherical_equatorial_tag)
  29. {
  30. return "spherical_equatorial";
  31. }
  32. inline const char * cs_str(bg::geographic_tag)
  33. {
  34. return "geographic";
  35. }
  36. template <typename Ring>
  37. inline void test_one(Ring const& ring, bg::order_selector expected)
  38. {
  39. typedef typename bg::cs_tag<Ring>::type cs_tag;
  40. bg::order_selector result = bg::detail::calculate_point_order(ring);
  41. BOOST_CHECK_MESSAGE(result == expected, "Expected: " << order_str(expected) << " for " << bg::wkt(ring) << " in " << cs_str(cs_tag()));
  42. if (expected != bg::order_undetermined && result != bg::order_undetermined)
  43. {
  44. Ring ring_rev = ring;
  45. std::reverse(boost::begin(ring_rev), boost::end(ring_rev));
  46. bg::order_selector result_rev = bg::detail::calculate_point_order(ring_rev);
  47. BOOST_CHECK_MESSAGE(result != result_rev, "Invalid order of reversed: " << bg::wkt(ring) << " in " << cs_str(cs_tag()));
  48. }
  49. }
  50. template <typename P>
  51. inline void test_one(std::string const& ring_wkt, bg::order_selector expected)
  52. {
  53. //typedef typename bg::cs_tag<P>::type cs_tag;
  54. bg::model::ring<P> ring;
  55. bg::read_wkt(ring_wkt, ring);
  56. std::size_t n = boost::size(ring);
  57. for (size_t i = 1; i < n; ++i)
  58. {
  59. test_one(ring, expected);
  60. std::rotate(boost::begin(ring), boost::begin(ring) + 1, boost::end(ring));
  61. // it seems that area method doesn't work for invalid "opened" polygons
  62. //if (! boost::is_same<cs_tag, bg::geographic_tag>::value)
  63. {
  64. P p = bg::range::front(ring);
  65. bg::range::push_back(ring, p);
  66. }
  67. }
  68. }
  69. template <typename P>
  70. void test_all()
  71. {
  72. // From correct() test, rings rotated and reversed in test_one()
  73. test_one<P>("POLYGON((0 0,0 1,1 1,1 0,0 0))", bg::clockwise);
  74. test_one<P>("POLYGON((0 0,0 1,1 1,1 0))", bg::clockwise);
  75. test_one<P>("POLYGON((0 0,0 4,4 4,4 0,0 0))", bg::clockwise);
  76. test_one<P>("POLYGON((1 1,2 1,2 2,1 2,1 1))", bg::counterclockwise);
  77. test_one<P>("POLYGON((0 5, 5 5, 5 0, 0 0, 0 5))", bg::clockwise);
  78. test_one<P>("POLYGON((0 5, 0 5, 0 6, 0 6, 0 4, 0 5, 5 5, 5 0, 0 0, 0 6, 0 5))", bg::clockwise);
  79. test_one<P>("POLYGON((2 0, 2 1, 2 -1, 2 0, 1 0, 1 -1, 0 -1, 0 1, 1 1, 1 0, 2 0))", bg::clockwise);
  80. test_one<P>("POLYGON((2 0, 2 1, 2 -1, 2 0, 1 0, 1 -1, 0 -1, 0 1, 1 1, 1 0))", bg::clockwise);
  81. test_one<P>("POLYGON((2 0, 2 1, 3 1, 3 -1, 2 -1, 2 0, 1 0, 1 -1, 0 -1, 0 1, 1 1, 1 0, 2 0))", bg::clockwise);
  82. test_one<P>("POLYGON((0 85, 5 85, 5 84, 0 84, 0 85))", bg::clockwise);
  83. test_one<P>("POLYGON((0 2, 170 2, 170 0, 0 0, 0 2))", bg::clockwise);
  84. test_one<P>("POLYGON((0 2, 170 2, 170 1, 160 1, 10 1, 0 1, 0 2))", bg::clockwise);
  85. test_one<P>("POLYGON((0 2, 170 2, 170 -2, 0 -2, 0 2))", bg::clockwise);
  86. test_one<P>("POLYGON((5 5, 6 5, 6 6, 6 4, 6 5, 5 5, 5 4, 4 4, 4 6, 5 6, 5 5))", bg::clockwise);
  87. test_one<P>("POLYGON((5 5, 6 5, 6 6, 6 4, 6 5, 5 5, 5 6, 4 6, 4 4, 5 4, 5 5))", bg::counterclockwise);
  88. test_one<P>("POLYGON((5 5, 6 5, 6 5, 6 6, 6 5, 6 4, 6 5, 6 5, 5 5, 5 4, 4 4, 4 6, 5 6, 5 5))", bg::clockwise);
  89. // https://github.com/boostorg/geometry/pull/554
  90. test_one<P>("POLYGON((9.8591674311151110 54.602813224425063, 9.8591651519791412 54.602359676428932, 9.8584586199249316 54.602359676428932, 9.8591674311151110 54.602813224425063))",
  91. bg::clockwise);
  92. }
  93. template <typename P>
  94. void test_cartesian()
  95. {
  96. test_one<P>("POLYGON((0 5, 1 5, 1 6, 1 4, 2 4, 0 4, 0 3, 0 5))", bg::clockwise);
  97. }
  98. template <typename P>
  99. void test_spheroidal()
  100. {
  101. test_one<P>("POLYGON((0 5, 1 5, 1 6, 1 4, 0 4, 0 3, 0 5))", bg::clockwise);
  102. test_one<P>("POLYGON((0 45, 120 45, -120 45, 0 45))", bg::counterclockwise);
  103. }
  104. int test_main(int, char* [])
  105. {
  106. test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
  107. test_all<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > >();
  108. test_all<bg::model::point<double, 2, bg::cs::geographic<bg::degree> > >();
  109. test_cartesian<bg::model::point<double, 2, bg::cs::cartesian> >();
  110. test_spheroidal<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > >();
  111. test_spheroidal<bg::model::point<double, 2, bg::cs::geographic<bg::degree> > >();
  112. return 0;
  113. }