From 52fc1f62b31a515b4fd692729beaeb8bc2b9dc12 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sun, 3 Mar 2024 22:35:49 +0000 Subject: [PATCH] [test] add cases for issues #1229 #1231 #1244 and some test refactoring --- test/algorithms/overlay/overlay_cases.hpp | 19 ++ .../set_operations/difference/difference.cpp | 227 +++++++++++------- .../intersection/intersection.cpp | 45 +++- .../algorithms/set_operations/union/union.cpp | 49 ++-- 4 files changed, 223 insertions(+), 117 deletions(-) diff --git a/test/algorithms/overlay/overlay_cases.hpp b/test/algorithms/overlay/overlay_cases.hpp index 48ebfcde11..ef477631e2 100644 --- a/test/algorithms/overlay/overlay_cases.hpp +++ b/test/algorithms/overlay/overlay_cases.hpp @@ -1176,6 +1176,25 @@ static std::string issue_1186[2] = "POLYGON((-13848.1446527556 6710443.1496919869,-13848.2559722463 6710440.2884572418,-13847.8106942832 6710440.1096301023,-13847.6993747924 6710443.1496919869,-13847.3654163201 6710442.9708647905,-13846.0295824308 6710442.9708647905,-13846.4748603939 6710435.1024718173,-13847.8106942832 6710435.1024718173,-13848.1446527556 6710435.1024718173,-13849.8144451172 6710443.1496919869,-13848.1446527556 6710443.1496919869),(-13847.4767358109 6710440.1096301023,-13847.8106942832 6710440.1096301023,-13847.9220137740 6710439.9308029665,-13847.5880553017 6710439.7519758362,-13847.4767358109 6710440.1096301023))" }; +// Triangle, nearly a line +static std::string issue_1229[2] = +{ + "POLYGON((38436.758 22765.61,930.538 -10523.68,925.121 -10507.965,38436.758 22765.61))", + "POLYGON((38436.758 22765.61,925.121 -10507.965,925.121 -10507.965,38436.758 22765.61))" +}; + +static std::string issue_1231[2] = +{ + "POLYGON((0 5,-6 -17,12 17,0 5),(4 6,5 5,0 1,4 6))", + "POLYGON((3 9,-15 -5,13 -11,3 9))" +}; + +static std::string issue_1244[2] = +{ + "POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1,1 3,2 2,1 1))", + "POLYGON((2 -1,5 2,2 5,2 -1))" +}; + static std::string ggl_list_20120229_volker[3] = { "POLYGON((1716 1554,2076 2250,2436 2352,2796 1248,3156 2484,3516 2688,3516 2688,3156 2484,2796 1248,2436 2352,2076 2250, 1716 1554))", diff --git a/test/algorithms/set_operations/difference/difference.cpp b/test/algorithms/set_operations/difference/difference.cpp index 1c36b8f650..7ba60d6f44 100644 --- a/test/algorithms/set_operations/difference/difference.cpp +++ b/test/algorithms/set_operations/difference/difference.cpp @@ -22,6 +22,8 @@ #include +#include + #include #include "test_difference.hpp" @@ -29,8 +31,33 @@ #include #include +namespace +{ + +// Change compiler defines to constexpr bools +// to make conditions more readable +// and to always compile all code. +#if defined(BOOST_GEOMETRY_TEST_FAILURES) +constexpr bool test_failures = true; +#else +constexpr bool test_failures = false; +#endif + +#if defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) +constexpr bool test_only_one_type = true; +#else +constexpr bool test_only_one_type = false; +#endif + +#if defined(BOOST_GEOMETRY_TEST_ONLY_ONE_ORDER) +constexpr bool test_only_one_order = true; +#else +constexpr bool test_only_one_order = false; +#endif + +} // namespace -// Convenience macros (points are not checked) +// Convenience macros (point counts are not checked) #define TEST_DIFFERENCE(caseid, clips1, area1, clips2, area2, clips3) \ (test_one) \ ( #caseid, caseid[0], caseid[1], clips1, -1, area1, clips2, -1, area2, \ @@ -41,10 +68,12 @@ ( #caseid, caseid[0], caseid[1], clips1, -1, area1, clips2, -1, area2, \ clips3, -1, area1 + area2, settings) -template +template void test_all() { - typedef bg::model::polygon

polygon; + using polygon = bg::model::polygon; + + constexpr bool is_ccw = ! ClockWise; test_one("simplex_normal", simplex_normal[0], simplex_normal[1], @@ -67,7 +96,7 @@ void test_all() 1, 5, 8.0); { - // Sym difference works, but expectations are different for rescaling + // It reports self-intersections for symmetric difference ut_settings settings; settings.sym_difference = false; test_one("star_comb_15", @@ -250,19 +279,17 @@ void test_all() TEST_DIFFERENCE(case_precision_9, optional(), optional_sliver(), 1, 59.0, count_set(1, 2)); TEST_DIFFERENCE_WITH(case_precision_10, optional(), optional_sliver(), 1, 59, count_set(1, 2), ut_settings(0.001)); -#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) - // Fails without rescaling - TEST_DIFFERENCE(case_precision_11, optional(), optional_sliver(), 1, 59.0, count_set(1, 2)); -#endif + if BOOST_GEOMETRY_CONSTEXPR(test_failures) + { + // Fails (since rescaling is turned off) + TEST_DIFFERENCE(case_precision_11, optional(), optional_sliver(), 1, 59.0, count_set(1, 2)); + } TEST_DIFFERENCE(case_precision_12, 1, 12.0, 0, 0.0, 1); TEST_DIFFERENCE_WITH(case_precision_13, 1, 12, 0, 0.0, 1, ut_settings(0.001)); TEST_DIFFERENCE(case_precision_14, 1, 14.0, 1, 8.0, 1); TEST_DIFFERENCE(case_precision_15, 0, 0.0, 1, 59.0, 1); -#if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) - // Fails if rescaling is used in combination with get_clusters TEST_DIFFERENCE(case_precision_16, optional(), optional_sliver(), 1, 59.0, 1); -#endif TEST_DIFFERENCE(case_precision_17, 0, 0.0, 1, 59.0, 1); TEST_DIFFERENCE(case_precision_18, 0, 0.0, 1, 59.0, 1); TEST_DIFFERENCE(case_precision_19, 1, expectation_limits(1.2e-6, 1.35e-5), 1, 59.0, 2); @@ -335,11 +362,8 @@ void test_all() settings); } -#if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) { ut_settings settings(0.1); - settings.set_test_validity(BG_IF_RESCALED(false, true)); - settings.validity_false_negative_sym = BG_IF_RESCALED(true, false); // SQL Server gives: 0.28937764436705 and 0.000786406897532288 with 44/35 rings // PostGIS gives: 0.30859375 and 0.033203125 with 35/35 rings @@ -348,7 +372,6 @@ void test_all() ignore_count(), expectation_limits(0.00060440758, 0.00076856), ignore_count(), settings); } -#endif { ut_settings settings; @@ -471,13 +494,14 @@ void test_all() count_set(1, 6), 20.096189, count_set(1, 6)); -#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) - // Without rescaling the "b" case produces no output. - test_one("ticket_10108_a", - ticket_10108_a[0], ticket_10108_a[1], - 1, 4, {0.0145036, 0.0145037}, - 1, 4, 0.029019232); -#endif + if BOOST_GEOMETRY_CONSTEXPR(test_failures) + { + // Without rescaling the second case (labeled "b") produces no output. + test_one("ticket_10108_a", + ticket_10108_a[0], ticket_10108_a[1], + 1, 4, {0.0145036, 0.0145037}, + 1, 4, 0.029019232); + } test_one("ticket_10108_b", ticket_10108_b[0], ticket_10108_b[1], @@ -498,66 +522,66 @@ void test_all() 2, 23, 62.25, 0, 0, 0.0); -#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) - typedef bg::model::box

box; - typedef bg::model::ring

ring; - - // Other combinations + if BOOST_GEOMETRY_CONSTEXPR(! test_only_one_type) { - test_one( - "star_ring_ring", example_star, example_ring, - 5, 22, 1.1901714, - 5, 27, 1.6701714); - - test_one( - "ring_star_ring", example_ring, example_star, - 5, 27, 1.6701714, - 5, 22, 1.1901714); - - static std::string const clip = "POLYGON((2.5 0.5,5.5 2.5))"; - - test_one("star_box", - clip, example_star, - 4, 20, 2.833333, 4, 16, 0.833333); - - test_one("box_star", - example_star, clip, - 4, 16, 0.833333, 4, 20, 2.833333); + using box = bg::model::box

; + using ring = bg::model::ring

; + { + // Other combinations + test_one( + "star_ring_ring", example_star, example_ring, + 5, 22, 1.1901714, + 5, 27, 1.6701714); + + test_one( + "ring_star_ring", example_ring, example_star, + 5, 27, 1.6701714, + 5, 22, 1.1901714); + + static std::string const clip = "POLYGON((2.5 0.5,5.5 2.5))"; + + test_one("star_box", + clip, example_star, + 4, 20, 2.833333, 4, 16, 0.833333); + + test_one("box_star", + example_star, clip, + 4, 16, 0.833333, 4, 20, 2.833333); + } + + // Combinations of clockwise and counter clockwise + { + using polygon_ccw = bg::model::polygon; + test_one( + "star_ring_ccw", example_star, example_ring, + 5, 22, 1.1901714, + 5, 27, 1.6701714); + test_one( + "star_ring_ccw1", example_star, example_ring, + 5, 22, 1.1901714, + 5, 27, 1.6701714); + test_one( + "star_ring_ccw2", example_star, example_ring, + 5, 22, 1.1901714, + 5, 27, 1.6701714); + } + + // Multi/box (should be moved to multi) + { + using mp = bg::model::multi_polygon; + + static std::string const clip = "POLYGON((2 2,4 4))"; + + test_one("simplex_multi_box_mp", + clip, case_multi_simplex[0], + 2, -1, 0.53333333333, 3, -1, 8.53333333333); + test_one("simplex_multi_mp_box", + case_multi_simplex[0], clip, + 3, -1, 8.53333333333, 2, -1, 0.53333333333); + + } } - // Counter clockwise - { - typedef bg::model::polygon polygon_ccw; - test_one( - "star_ring_ccw", example_star, example_ring, - 5, 22, 1.1901714, - 5, 27, 1.6701714); - test_one( - "star_ring_ccw1", example_star, example_ring, - 5, 22, 1.1901714, - 5, 27, 1.6701714); - test_one( - "star_ring_ccw2", example_star, example_ring, - 5, 22, 1.1901714, - 5, 27, 1.6701714); - } - - // Multi/box (should be moved to multi) - { - typedef bg::model::multi_polygon mp; - - static std::string const clip = "POLYGON((2 2,4 4))"; - - test_one("simplex_multi_box_mp", - clip, case_multi_simplex[0], - 2, -1, 0.53333333333, 3, -1, 8.53333333333); - test_one("simplex_multi_mp_box", - case_multi_simplex[0], clip, - 3, -1, 8.53333333333, 2, -1, 0.53333333333); - - } -#endif - // Rescaling generates a very small false polygon TEST_DIFFERENCE(issue_566_a, 1, expectation_limits(143.662), optional(), optional_sliver(1.0e-5), @@ -577,24 +601,42 @@ void test_all() settings); } - TEST_DIFFERENCE(issue_875, 1, 3468.77515, 1, 105.425816, 2); -#if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES) + { + // The symmetric difference is invalid for ccw + ut_settings settings; + settings.validity_of_sym = ! is_ccw; + TEST_DIFFERENCE_WITH(issue_875, 1, 3468.77515, 1, 105.425816, 2, settings); + } + TEST_DIFFERENCE(issue_876a, 1, 4728.89916, 1, 786.29563, 2); -#endif TEST_DIFFERENCE(issue_876b, 1, 6114.18234, 1, 4754.29449, count_set(1, 2)); TEST_DIFFERENCE(issue_1138, 1, 203161.751, 2, 1237551.0171, 1); + if BOOST_GEOMETRY_CONSTEXPR(test_failures) + { + // Fails for both clockwise and counter clockwise in detecting the difference + // of the interior ring, touching the outer ring. + TEST_DIFFERENCE(issue_1231, 1, 203161.751, 2, 1237551.0171, 1); + } + + if BOOST_GEOMETRY_CONSTEXPR(! is_ccw || test_failures) + { + // Case #1244 is wrong for ccw + TEST_DIFFERENCE(issue_1244, 3, 8, 3, 2, 6); + } + TEST_DIFFERENCE(mysql_21977775, 2, 160.856568913, 2, 92.3565689126, 4); TEST_DIFFERENCE(mysql_21965285, 1, 92.0, 1, 14.0, 1); TEST_DIFFERENCE(mysql_23023665_1, 1, 92.0, 1, 142.5, 2); TEST_DIFFERENCE(mysql_23023665_2, 1, 96.0, 1, 16.0, 2); TEST_DIFFERENCE(mysql_23023665_3, 1, 225.0, 1, 66.0, 2); TEST_DIFFERENCE(mysql_23023665_5, 2, 165.23735, 2, 105.73735, 4); + { - // Without rescaling it is invalid + // The symmetric difference is invalid for ccw ut_settings settings; - settings.set_test_validity(true); + settings.validity_of_sym = ! is_ccw; TEST_DIFFERENCE_WITH(mysql_23023665_6, 2, 105.68756, 3, 10.18756, 5, settings); } { @@ -609,7 +651,7 @@ void test_all() template void test_specific() { - typedef bg::model::polygon polygon; + using polygon = bg::model::polygon; test_one("ggl_list_20120717_volker", ggl_list_20120717_volker[0], ggl_list_20120717_volker[1], @@ -635,13 +677,18 @@ void test_specific() int test_main(int, char* []) { BoostGeometryWriteTestConfiguration(); - test_all >(); - test_specific, false, false>(); + test_all, true>(); -#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) - test_all >(); -#endif + if BOOST_GEOMETRY_CONSTEXPR(! test_only_one_order) + { + test_all, false>(); + } + + if BOOST_GEOMETRY_CONSTEXPR(! test_only_one_type) + { + test_all, true>(); + } #if defined(BOOST_GEOMETRY_TEST_FAILURES) // Not yet fully tested for float and long double. diff --git a/test/algorithms/set_operations/intersection/intersection.cpp b/test/algorithms/set_operations/intersection/intersection.cpp index 4ce0127604..7cabab29ef 100644 --- a/test/algorithms/set_operations/intersection/intersection.cpp +++ b/test/algorithms/set_operations/intersection/intersection.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include "test_intersection.hpp" @@ -64,6 +65,8 @@ BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::vector) template void test_areal() { + constexpr bool is_ccw = bg::point_order::value == bg::counterclockwise; + test_one("simplex_with_empty_1", simplex_normal[0], polygon_empty, 0, 0, 0.0); @@ -310,6 +313,17 @@ void test_areal() TEST_INTERSECTION(issue_861, 1, -1, 1.4715007684573677693e-10); #endif + TEST_INTERSECTION(issue_1229, 0, -1, 0); + + { + // For CCW this test case currently reports as invalid + ut_settings settings; + settings.set_test_validity(! is_ccw); + TEST_INTERSECTION_WITH(issue_1231, 0, 1, 1, -1, 54.701340543162516, settings); + } + + TEST_INTERSECTION(issue_1244, 1, -1, 7); + test_one("buffer_mp1", buffer_mp1[0], buffer_mp1[1], 1, 31, 2.271707796); test_one("buffer_mp2", buffer_mp2[0], buffer_mp2[1], @@ -341,7 +355,12 @@ void test_areal() case_104[0], case_104[1], 0, -1, 0.0); - TEST_INTERSECTION(case_105, 1, 34, 76.0); + { + // For CCW this test case currently reports as invalid + ut_settings settings; + settings.set_test_validity(! is_ccw); + TEST_INTERSECTION_WITH(case_105, 0, 1, 1, 34, 76.0, settings); + } TEST_INTERSECTION(case_106, 2, -1, 3.5); TEST_INTERSECTION(case_107, 3, -1, 3.0); @@ -414,15 +433,15 @@ void test_areal() TEST_INTERSECTION(mysql_23023665_6, 2, 0, 11.812440191387557); - // Formation of an interior ring is optional - test_one("mysql_23023665_10", - mysql_23023665_10[0], mysql_23023665_10[1], - 1, optional(), -1, 54.701340543162523); - // Formation of an interior ring is optional - test_one("mysql_23023665_11", - mysql_23023665_11[0], mysql_23023665_11[1], - 1, optional(), -1, 35.933385462482065); + { + // Formation of an interior ring is optional for these cases + // For CCW an invalidity is reported + ut_settings settings; + settings.set_test_validity(! is_ccw); + TEST_INTERSECTION_WITH(mysql_23023665_10, 0, 1, optional(), 1, 54.701340543162523, settings); + TEST_INTERSECTION_WITH(mysql_23023665_11, 0, 1, optional(), 1, 35.933385462482065, settings); + } // test_one( // "polygon_pseudo_line", @@ -686,9 +705,11 @@ void test_all() std::string clip = "box(2 2,8 8)"; test_areal_linear(); +#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_ORDER) + test_areal_linear(); +#endif #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) test_areal_linear(); - test_areal_linear(); test_areal_linear(); #endif @@ -697,8 +718,10 @@ void test_all() // Test polygons clockwise and counter clockwise test_areal(); -#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) +#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_ORDER) test_areal(); +#endif +#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) test_areal(); test_areal(); #endif diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index a009911cc1..3e47a12870 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -24,6 +24,7 @@ #include #include +#include #define TEST_UNION(caseid, clips, holes, points, area) \ @@ -44,6 +45,8 @@ void test_areal() { typedef typename bg::coordinate_type::type ct; + constexpr bool is_ccw = bg::point_order::value == bg::counterclockwise; + ut_settings ignore_validity_for_float; if (BOOST_GEOMETRY_CONDITION((std::is_same::value)) ) { @@ -471,12 +474,16 @@ void test_areal() TEST_UNION(issue_1186, 1, 1, -1, 21.6189); TEST_UNION_REV(issue_1186, 1, 1, -1, 21.6189); - { - // Rescaling produces an invalid result - ut_settings settings; - settings.set_test_validity(BG_IF_RESCALED(false, true)); - TEST_UNION_WITH(geos_1, 1, 0, -1, expectation_limits(3458.0, 3461.3203125)); - } + TEST_UNION(issue_1229, 1, 0, -1, 384869.166); + TEST_UNION_REV(issue_1229, 1, 0, -1, 384869.166); + + TEST_UNION(issue_1231, 1, 0, -1, 286.799); + TEST_UNION_REV(issue_1231, 1, 0, -1, 286.799); + + TEST_UNION(issue_1244, 1, 1, -1, 17); + TEST_UNION_REV(issue_1244, 1, 1, -1, 17); + + TEST_UNION(geos_1, 1, 0, -1, expectation_limits(3458.0, 3461.3203125)); TEST_UNION(geos_2, 1, 0, -1, expectation_limits(349.0625, 350.55102539)); TEST_UNION(geos_3, 1, 0, -1, 29391548.4998779); TEST_UNION(geos_4, 1, 0, -1, 2304.4163115); @@ -541,8 +548,14 @@ void test_areal() test_one("buffer_mp1", buffer_mp1[0], buffer_mp1[1], 1, 0, -1, 22.815); - test_one("buffer_mp2", buffer_mp2[0], buffer_mp2[1], - 1, -1, 217, 36.752837); + { + // Contains a self-intersection invalidity for ccw + ut_settings settings; + settings.set_test_validity(! is_ccw); + test_one("buffer_mp2", + buffer_mp2[0], buffer_mp2[1], + 1, -1, 217, 36.752837, settings); + } test_one("mysql_21964079_1", mysql_21964079_1[0], mysql_21964079_1[1], @@ -565,12 +578,12 @@ void test_areal() 1, 1, -1, 220.5); } -template +template void test_all() { - typedef bg::model::polygon

polygon; - typedef bg::model::ring

ring; - typedef bg::model::box

box; + using polygon = bg::model::polygon; + using ring = bg::model::ring

; + using box = bg::model::box

; test_areal(); @@ -626,12 +639,16 @@ void test_all() int test_main(int, char* []) { BoostGeometryWriteTestConfiguration(); - test_all>(); + test_all, true>(); + +#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_ORDER) + test_all, false>(); +#endif #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) - test_all>(); - test_all>(); - test_all>(); + test_all, true>(); + test_all, true>(); + test_all, true>(); #endif #if defined(BOOST_GEOMETRY_TEST_FAILURES)