union_aa_geo.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Boost.Geometry
  2. // Unit Test
  3. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
  4. // Copyright (c) 2017, Oracle and/or its affiliates.
  5. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  6. // Use, modification and distribution is subject to the Boost Software License,
  7. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. #include <iostream>
  10. #include <string>
  11. #include "test_union.hpp"
  12. #include <boost/geometry/geometries/point_xy.hpp>
  13. struct exterior_points_counter
  14. {
  15. exterior_points_counter() : count(0) {}
  16. template <typename Polygon>
  17. void operator()(Polygon const& poly)
  18. {
  19. count += boost::size(bg::exterior_ring(poly));
  20. }
  21. std::size_t count;
  22. };
  23. struct interiors_counter
  24. : exterior_points_counter
  25. {
  26. template <typename Polygon>
  27. void operator()(Polygon const& poly)
  28. {
  29. count += boost::size(bg::interior_rings(poly));
  30. }
  31. };
  32. void test_geographic_one(std::string const& wkt1, std::string const& wkt2,
  33. std::size_t count, std::size_t exterior_points_count, std::size_t interiors_count,
  34. double expected_area)
  35. {
  36. typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree> > point;
  37. typedef bg::model::polygon<point> polygon;
  38. typedef bg::model::multi_polygon<polygon> multipolygon;
  39. bg::srs::spheroid<double> sph(6378137.0000000000, 6356752.3142451793);
  40. bg::strategy::intersection::geographic_segments<> is(sph);
  41. bg::strategy::area::geographic<> as(sph);
  42. polygon p1, p2;
  43. boost::geometry::read_wkt(wkt1, p1);
  44. boost::geometry::read_wkt(wkt2, p2);
  45. multipolygon result;
  46. enum test_mode { expect_valid, expect_empty, expect_exception };
  47. #if defined(BOOST_GEOMETRY_UNION_THROW_INVALID_OUTPUT_EXCEPTION)
  48. test_mode mode = expected_area >= 0 ? expect_valid : expect_exception;
  49. #elif defined(BOOST_GEOMETRY_UNION_RETURN_INVALID)
  50. test_mode mode = expect_valid;
  51. #else
  52. // default
  53. test_mode mode = expected_area >= 0 ? expect_valid : expect_empty;
  54. #endif
  55. if (mode == expect_exception)
  56. {
  57. BOOST_CHECK_THROW(boost::geometry::union_(p1, p2, result, is),
  58. bg::invalid_output_exception);
  59. }
  60. else
  61. {
  62. boost::geometry::union_(p1, p2, result, is);
  63. double result_area = bg::area(result, as);
  64. std::size_t result_count = boost::size(result);
  65. std::size_t result_exterior_points = std::for_each(boost::begin(result),
  66. boost::end(result),
  67. exterior_points_counter()).count;
  68. std::size_t result_interiors = std::for_each(boost::begin(result),
  69. boost::end(result),
  70. interiors_counter()).count;
  71. if (mode == expect_valid)
  72. {
  73. BOOST_CHECK_EQUAL(result_count, count);
  74. BOOST_CHECK_EQUAL(result_exterior_points, exterior_points_count);
  75. BOOST_CHECK_EQUAL(result_interiors, interiors_count);
  76. BOOST_CHECK_CLOSE(result_area, expected_area, 0.001);
  77. }
  78. else
  79. {
  80. BOOST_CHECK_EQUAL(result_count, 0u);
  81. BOOST_CHECK_EQUAL(result_area, 0.0);
  82. }
  83. }
  84. }
  85. void test_geographic()
  86. {
  87. // input ok and the result is ok
  88. test_geographic_one("POLYGON((16 15,-132 10,-56 89,67 5,16 15))",
  89. "POLYGON((101 49,12 40,-164 10,117 0,101 49))",
  90. 1, 9, 0, 144265751613509.06);
  91. // input ok but the result is too big
  92. test_geographic_one("POLYGON((16 -15,-132 -22,-56 89,67 -29,16 -15))",
  93. "POLYGON((101 49,12 40,-164 -21,117 -61,101 49))",
  94. 1, 9, 0, -163427005620080.0);
  95. // the second polygon is reversed i.e. it covers more than half of the globe
  96. // so the result is also too big
  97. test_geographic_one("POLYGON((16 -15,-132 -22,-56 89,67 -29,16 -15))",
  98. "POLYGON((101 49,117 -61,-164 -21,12 40,101 49))",
  99. 1, 7, 0, -125258931656228.08);
  100. }
  101. int test_main(int, char* [])
  102. {
  103. test_geographic();
  104. return 0;
  105. }