From 825b835f8ae7814d28e0612d8cada8afce35865d Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Sat, 26 May 2012 21:05:01 +0000 Subject: [PATCH] [geometry] recent work on buffers (march/april) - unit tests - pending commit [SVN r78657] --- .../buffer/multi_polygon_buffer.cpp | 237 +++++++++++++++++- .../algorithms/buffer/polygon_buffer.cpp | 8 + .../algorithms/buffer/test_buffer.hpp | 9 +- 3 files changed, 239 insertions(+), 15 deletions(-) diff --git a/test_extensions/algorithms/buffer/multi_polygon_buffer.cpp b/test_extensions/algorithms/buffer/multi_polygon_buffer.cpp index 81631391d..ee5e88fb4 100644 --- a/test_extensions/algorithms/buffer/multi_polygon_buffer.cpp +++ b/test_extensions/algorithms/buffer/multi_polygon_buffer.cpp @@ -7,10 +7,14 @@ // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +//#define HAVE_TTMATH +#ifdef HAVE_TTMATH +#include +#endif + #include -#define BOOST_GEOMETRY_TEST_BUFFER_POLYGON #include #include // TODO: more specific @@ -28,6 +32,9 @@ static std::string const zonethru static std::string const wrapped = "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0),(2 2,8 2,8 8,2 8,2 2)),((4 4,4 6,6 6,6 4,4 4)))"; +static std::string const triangles + = "MULTIPOLYGON(((0 4,3 0,-2.5 -1,0 4)),((3 8,5.5 13,8 8,3 8)),((11 4,13.5 -1,8 0,11 4)))"; + // From robustness tests // Case with duplicate points (due to chained boxes) (round) @@ -50,13 +57,160 @@ static std::string const rt_d static std::string const rt_e = "MULTIPOLYGON(((0 6,0 7,1 6,0 6)),((3 7,3 8,4 8,4 7,3 7)),((4 6,4 7,5 7,4 6)),((3 6,3 7,4 6,3 6)),((1 9,2 10,2 9,1 9)),((1 9,1 8,0 8,0 9,1 9)),((3 5,3 4,2 4,2 5,2 6,3 5)))"; -// Extact of e (miter) +// Extract of e (miter) static std::string const rt_f = "MULTIPOLYGON(((0 6,0 7,1 6,0 6)),((1 9,1 8,0 8,0 9,1 9)))"; -static std::string const rt_g +// Robustness / turn problem (collinearity with turn after), solved in get_turn-info +static std::string const rt_g1 = "MULTIPOLYGON(((3 8,3 9,4 9,3 8)),((7 5,7 6,8 5,7 5)),((1 8,1 9,2 9,1 8)),((1 6,1 7,2 7,1 6)))"; +static std::string const rt_g2 + = "MULTIPOLYGON(((6 5,7 5,6 4,5 4,5 5,6 5)),((4 2,4 3,5 3,4 2)))"; + +static std::string const rt_g3 + = "MULTIPOLYGON(((4 2,5 3,5 2,4 2)),((2 0,3 1,3 0,2 0)))"; + + +// IP on match of 3 lines +static std::string const rt_h + = "MULTIPOLYGON(((4 7,4 8,5 7,4 7)),((4 8,5 9,5 8,4 8)),((9 1,10 2,10 1,9 1)),((4 1,4 2,5 2,4 1)),((2 9,2 10,3 10,2 9)),((7 7,8 8,8 7,7 7)),((3 4,4 4,3 3,2 3,2 4,3 4)))"; + +// r=1.16 (touching) +static std::string const rt_i + = "MULTIPOLYGON(((2 1,2 2,3 2,2 1)),((3 2,3 3,4 3,3 2)))"; + +// r=1.16 (touching in the middle) +static std::string const rt_j + = "MULTIPOLYGON(((2 4,2 5,3 5,2 4)),((5 3,5 4,6 4,5 3)),((9 4,9 5,10 5,10 4,9 4)),((0 2,0 3,1 3,0 2)))"; + +// Occupied (but not completely - due to duplicate point there) +static std::string const rt_k + = "MULTIPOLYGON(((3 7,3 8,4 8,3 7)),((0 4,0 5,1 5,0 4)),((3 5,3 6,4 6,4 5,3 5)),((2 6,3 7,3 6,2 6)),((3 2,3 1,2 1,2 2,3 3,3 2)),((0 9,1 10,1 9,1 8,0 8,0 9)))"; + +// Segment-intersection problem (nearly collinear not reported as collinear), fixed +static std::string const rt_l + = "MULTIPOLYGON(((2 5,2 6,3 5,2 5)),((6 1,6 2,7 1,6 1)))"; + +// Segment-intersection problem (missed touch because of robustness) (with 4), fixed +static std::string const rt_m1 + = "MULTIPOLYGON(((4 2,4 3,5 2,4 2)),((1 2,2 3,2 2,1 2)))"; + +// Same, with 2 +static std::string const rt_m2 + = "MULTIPOLYGON(((0 3,1 4,1 3,0 3)),((3 6,4 7,4 6,4 5,3 5,3 6)))"; + + +// Segment-intersection problem (disjoint nearly collinear segments were reported as intersecting), fixed. +static std::string const rt_n + = "MULTIPOLYGON(((0 0,1 1,1 0,0 0)),((3 3,4 4,4 3,3 3)))"; + +// Segment intersection of 3 pieces in one point, plus all intersection points are within the other piece (due to precision) +static std::string const rt_o1 + = "MULTIPOLYGON(((8 4,8 5,9 5,8 4)),((9 4,10 5,10 4,9 4)),((6 2,6 3,7 3,6 2)))"; + +static std::string const rt_o2 + = "MULTIPOLYGON(((8 4,8 5,9 5,8 4)),((6 5,7 4,6 4,6 5)),((9 4,10 5,10 4,9 4)),((6 2,6 3,7 3,6 2)))"; + +static std::string const rt_o3 + = "MULTIPOLYGON(((8 4,8 5,9 5,8 4)),((6.5 5,7.5 4,6.5 4,6.5 5)),((8.5 4,9.5 5,9.5 4,8.5 4)),((6 2,6 3,7 3,6 2)),((10 4,11 5,11 4,10 4)))"; + +static std::string const rt_o4 + = "MULTIPOLYGON(((8 4,8 5,9 5,8 4)),((6.5 5,7.5 4,6.5 4,6.5 5)),((8.5 4,9.5 5,9.5 4,8.5 4)),((6 2,6 3,7 3,6 2)),((10 4,11 5,11 4,10 4)),((10 3,11 3,11 2,10 3)))"; + +// Occupied - intersection +static std::string const rt_p1 + = "MULTIPOLYGON(((5 2,5 3,6 3,6 2,5 2)),((8 0,8 1,9 0,8 0)),((8 2,9 3,9 2,8 2)))"; + +static std::string const rt_p2 + = "MULTIPOLYGON(((9 3,9 4,10 3,9 3)),((9 4,9 5,10 5,9 4)),((8 6,9 7,9 6,8 6)))"; + +static std::string const rt_p3 + = "MULTIPOLYGON(((3 8,3 9,4 9,3 8)),((3 7,3 8,4 8,3 7)),((0 8,0 9,1 8,0 8)))"; + +// Occupation map: robustness, nearly collinear, both incoming +static std::string const rt_p4 + = "MULTIPOLYGON(((8 8,9 9,9 8,8 8)),((5 8,5 9,6 9,5 8)),((6 5,6 6,7 6,6 5)),((4 7,4 8,5 8,4 7)))"; + +// Occupation map: Two collinear segments intersecting one segment +static std::string const rt_p5 + = "MULTIPOLYGON(((3 2,4 3,4 2,3 2)),((2 2,2 3,3 3,3 2,2 2)),((4 3,5 4,5 3,4 3)))"; + +// Occupied map: only two pieces involved so leave early +static std::string const rt_p6 + = "MULTIPOLYGON(((7 3,7 4,8 3,7 3)),((7 6,8 7,8 6,7 6)))"; + +// Occupation map: needing relaxed_less for map +static std::string const rt_p7 + = "MULTIPOLYGON(((6 6,7 7,7 6,6 6)),((3 4,3 5,4 4,3 4)),((2 6,3 7,3 6,2 6)))"; + +// Occupation map: needing relaxed_less PLUS relaxed_equals for map +static std::string const rt_p8 + = "MULTIPOLYGON(((4 7,4 8,5 7,4 7)),((5 3,6 4,6 3,5 3)),((8 5,8 6,9 6,8 5)))"; + +// Occupation map: needing go back for extra outgoing vectors too +static std::string const rt_p9 + = "MULTIPOLYGON(((1 6,1 7,2 6,1 6)),((4 3,4 4,5 3,4 3)),((3 4,2 3,2 4,3 5,3 4)))"; + +static std::string const rt_p10 + = "MULTIPOLYGON(((6 6,7 7,7 6,6 6)),((4 6,5 7,5 6,4 6)),((8 8,9 9,9 8,8 8)))"; + +// Occupation map, multiple back/forward cases and combinations +static std::string const rt_p11 + = "MULTIPOLYGON(((0 8,0 9,1 9,1 8,0 8)),((2 8,2 9,3 9,3 8,2 8)),((3 8,4 9,4 8,3 8)),((4 1,4 2,5 2,4 1)))"; + +// Occupation map - incoming angle, non-zero +static std::string const rt_p12 + = "MULTIPOLYGON(((8 4,9 5,9 4,8 4)),((5 5,5 6,6 6,6 5,5 5)),((8 4,8 3,7 3,8 4)))"; + +// Occupation map - outgoing angle, 1 +static std::string const rt_p13 + = "MULTIPOLYGON(((5 2,6 3,6 2,5 2)),((3 0,4 1,4 0,3 0)),((3 1,3 2,4 2,4 1,3 1)))"; + +// Occupation map - touch which was originally in other segment-id +static std::string const rt_p14 + = "MULTIPOLYGON(((9 9,10 10,10 9,9 9)),((7 7,8 8,8 7,7 7)),((6 6,6 7,7 7,7 6,6 6)))"; + +// Occupation map - needing measuring sides from original point and not center point +static std::string const rt_p15 + = "MULTIPOLYGON(((5 2,5 3,6 3,6 2,5 2)),((4 1,5 2,5 1,4 1)),((8 5,9 6,9 5,8 5)))"; + +// Occupation map - needing other approach w.r.t. discarding (collinear) segments +static std::string const rt_p16 + = "MULTIPOLYGON(((5 7,5 8,6 7,5 7)),((9 3,9 4,10 3,9 3)),((6 7,7 8,7 7,6 7)))"; + +// Occupation map - outputting two valid turns (resulting in the wrong choice in the end) +static std::string const rt_p17 + = "MULTIPOLYGON(((4 8,5 9,5 8,4 8)),((1 8,2 9,2 8,1 8)),((2 6,3 7,3 6,2 6)))"; + +// Occupation map with a uu-turn +static std::string const rt_q1 + = "MULTIPOLYGON(((4 6,4 7,5 7,5 6,4 6)),((1 6,1 7,2 7,2 6,1 6)),((1 9,1 10,2 10,2 9,1 9)))"; + +// Occupation map with twice a uu-turn +static std::string const rt_q2 + = "MULTIPOLYGON(((0 6,0 7,1 6,0 6)),((2 6,2 7,3 6,2 6)),((4 5,3 5,3 6,4 6,5 6,5 5,4 4,4 5)))"; + +// Robustness issue related to collinear correction (meeting) and selecting the right axis (x/y) +static std::string const rt_r + = "MULTIPOLYGON(((3 1,2 0,1 1,2 2,3 1)),((5 3,4 2,3 2,4 4,5 3)))"; + +// Robustness - flagged by "meeting" +static std::string const rt_s1 + = "MULTIPOLYGON(((4 1,5 2,5 1,4 1)),((5 2,6 3,6 2,5 2)),((7 1,7 2,8 1,7 1)))"; + +// Robustness - flagged by "disjoint" +static std::string const rt_s2 + = "MULTIPOLYGON(((0 0,1 1,1 0,0 0)),((2 4,2 5,3 4,2 4)),((3.5 3.5,4 4,4 3,3 3,3 4,3.5 3.5)))"; + + +static std::string const rt_t1 + = "MULTIPOLYGON(((5 4,5 5,6 4,5 4)),((1 2,2 3,2 2,1 2)),((6 0,7 1,7 0,6 0)),((1 0,2 1,2 0,1 0)),((7 5,7 6,8 5,7 5)),((6 2,6 3,7 3,6 2)),((8 4,8 5,9 5,8 4)),((4 4,4 5,5 5,4 4)))"; +static std::string const rt_t2 + = "MULTIPOLYGON(((7 6,8 7,8 6,7 6)),((7 3,7 4,8 3,7 3)),((5 4,6 5,6 4,5 4)))"; + + + template @@ -66,6 +220,12 @@ void test_all() typedef bg::model::polygon

polygon_type; typedef bg::model::multi_polygon multi_polygon_type; + + test_one("triangles424", triangles, 'm', 417.910, 4.24); + test_one("triangles425", triangles, 'm', 418.918, 4.25); + test_one("triangles426", triangles, 'm', 419.927, 4.26); + test_one("zonethru_10", zonethru, 'm', 96.0000, 1.0); + test_one("multi_simplex_05", simplex, 'r', 23.7030, 0.5); test_one("multi_simplex_05", simplex, 'm', 24.5965, 0.5); test_one("multi_simplex_10", simplex, 'r', 34.2532, 1.0); @@ -88,7 +248,7 @@ void test_all() test_one("wrapped_15", wrapped, 'r', 167.066, 1.5); test_one("wrapped_15", wrapped, 'm', 169.000, 1.5); - test_one("rt_a", rt_a, 'r', 34.5344, 1.0); + test_one("rt_a", rt_a, 'r', 34.5381, 1.0); test_one("rt_a", rt_a, 'm', 36, 1.0); test_one("rt_b", rt_b, 'r', 31.4186, 1.0); test_one("rt_b", rt_b, 'm', 34, 1.0); @@ -98,21 +258,72 @@ void test_all() test_one("rt_d", rt_d, 'm', 19.8823, 0.3); test_one("rt_e", rt_e, 'r', 14.1866, 0.3); test_one("rt_e", rt_e, 'm', 15.1198, 0.3); - test_one("rt_f", rt_f, 'r', 4.28937, 0.3); + // This does not add anything: test_one("rt_f", rt_f, 'r', 4.28937, 0.3); test_one("rt_f", rt_f, 'm', 4.60853, 0.3); - test_one("rt_g", rt_g, 'r', 24.719, 1.0); - test_one("rt_g", rt_g, 'm', 30.3137, 1.0); + + test_one("rt_g1", rt_g1, 'r', 24.719, 1.0); + test_one("rt_g1", rt_g1, 'm', 30.3137, 1.0); + test_one("rt_g2", rt_g2, 'm', 18.5711, 1.0); + test_one("rt_g3", rt_g3, 'm', 16.5711, 1.0); + + test_one("rt_h", rt_h, 'r', 47.6012, 1.0); + test_one("rt_h", rt_h, 'm', 61.7058, 1.0); + test_one("rt_i", rt_i, 'r', 10.7528, 1.0); + test_one("rt_i", rt_i, 'm', 13.6569, 1.0); + test_one("rt_j", rt_j, 'r', 28.7309, 1.0); + test_one("rt_j", rt_j, 'm', 35.1421, 1.0); + test_one("rt_k", rt_k, 'r', 42.0092, 1.0); + test_one("rt_k", rt_k, 'm', 48.0563, 1.0); + // This does not add anything: test_one("rt_l", rt_l, 'r', 14.1074, 1.0); + test_one("rt_l", rt_l, 'm', 19.3995, 1.0); + test_one("rt_m1", rt_m1, 'r', 14.1074, 1.0); + test_one("rt_m1", rt_m1, 'm', 19.4853, 1.0); + test_one("rt_m2", rt_m2, 'm', 21.4853, 1.0); + + // This does not add anything: test_one("rt_n", rt_n, 'r', 14.1074, 1.0); + test_one("rt_n", rt_n, 'm', 18.4853, 1.0); + + test_one("rt_o1", rt_o1, 'r', 17.536, 1.0); + test_one("rt_o1", rt_o1, 'm', 20.9142, 1.0); + + test_one("rt_o2", rt_o2, 'm', 25.7426, 1.0); + test_one("rt_o3", rt_o3, 'm', 28.8247, 1.0); + test_one("rt_o4", rt_o4, 'm', 34.6532, 1.0); + + test_one("rt_p1", rt_p1, 'm', 24.8211, 1.0); + test_one("rt_p2", rt_p2, 'm', 21.4853, 1.0); + test_one("rt_p3", rt_p3, 'm', 22.3995, 1.0); + test_one("rt_p4", rt_p4, 'm', 33.0563, 1.0); + test_one("rt_p5", rt_p5, 'm', 17, 1.0); + test_one("rt_p6", rt_p6, 'm', 18.4853, 1.0); + test_one("rt_p7", rt_p7, 'm', 26.2279, 1.0); + test_one("rt_p8", rt_p8, 'm', 29.0563, 1.0); + test_one("rt_p9", rt_p9, 'm', 26.1421, 1.0); + test_one("rt_p10", rt_p10, 'm', 23.3995, 1.0); + test_one("rt_p11", rt_p11, 'm', 28.7426, 1.0); + test_one("rt_p12", rt_p12, 'm', 22.5711, 1.0); + test_one("rt_p13", rt_p13, 'm', 19.9142, 1.0); + test_one("rt_p14", rt_p14, 'm', 20.8284, 1.0); + test_one("rt_p15", rt_p15, 'm', 23.6569, 1.0); + test_one("rt_p16", rt_p16, 'm', 23.4853, 1.0); + test_one("rt_p17", rt_p17, 'm', 25.3137, 1.0); + + test_one("rt_q1", rt_q1, 'm', 27, 1.0); + test_one("rt_q2", rt_q2, 'm', 26.4853, 1.0); + + test_one("rt_r", rt_r, 'm', 21.0761, 1.0); + test_one("rt_s1", rt_s1, 'm', 20.4853, 1.0); + test_one("rt_s2", rt_s2, 'm', 24.6495, 1.0); + + //test_one("rt_t1", rt_t1, 'm', 99, 1.0); + //test_one("rt_t2", rt_t2, 'm', 99, 1.0); + } - -#ifdef HAVE_TTMATH -#include -#endif - int test_main(int, char* []) { test_all >(); - //test_all >(); + //test_all >(); return 0; } diff --git a/test_extensions/algorithms/buffer/polygon_buffer.cpp b/test_extensions/algorithms/buffer/polygon_buffer.cpp index 8df72b83e..ad80371b2 100644 --- a/test_extensions/algorithms/buffer/polygon_buffer.cpp +++ b/test_extensions/algorithms/buffer/polygon_buffer.cpp @@ -57,6 +57,10 @@ static std::string const saw static std::string const bowl = "POLYGON((1 2,1 7,2 7,3 5,5 4,7 5,8 7,9 7,9 2,1 2))"; +// Triangle with segmented sides, closing point at longest side +static std::string const triangle + = "POLYGON((4 5,5 4,4 4,3 4,3 5,3 6,4 5))"; + static std::string const county1 = "POLYGON((-111.700 41.200 ,-111.681388 41.181739 ,-111.682453 41.181506 ,-111.684052 41.180804 ,-111.685295 41.180538 ,-111.686318 41.180776 ,-111.687517 41.181416 ,-111.688982 41.181520 ,-111.690670 41.181523 ,-111.692135 41.181460 ,-111.693646 41.182034 ,-111.695156 41.182204 ,-111.696489 41.182274 ,-111.697775 41.182075 ,-111.698974 41.181539 ,-111.700485 41.182348 ,-111.701374 41.182955 ,-111.700 41.200))"; @@ -77,6 +81,9 @@ void test_all() test_one("L", letter_L, 'r', 13.7314, 0.5); test_one("L", letter_L, 'm', 14.0, 0.5); + test_one("chained_box", chained_box, 'm', 84, 1.0); + test_one("chained_box", chained_box, 'r', 83.1403, 1.0); + test_one("indentation4", indentation, 'm', 25.7741, 0.4); test_one("indentation4", indentation, 'r', 25.5695, 0.4); test_one("indentation5", indentation, 'm', 28.2426, 0.5); @@ -143,6 +150,7 @@ void test_all() test_one("fork_a1", fork_a, 'm', 88, 1); test_one("fork_b1", fork_b, 'm', 154, 1); test_one("fork_c1", fork_c, 'm', 152, 1); + test_one("triangle", triangle, 'm', 14.6569, 1.0); test_one("gammagate2", gammagate, 'm', 130, 2); diff --git a/test_extensions/algorithms/buffer/test_buffer.hpp b/test_extensions/algorithms/buffer/test_buffer.hpp index bd958ce95..e4463d0ee 100644 --- a/test_extensions/algorithms/buffer/test_buffer.hpp +++ b/test_extensions/algorithms/buffer/test_buffer.hpp @@ -151,7 +151,7 @@ void test_buffer(std::string const& caseid, Geometry const& geometry, #endif ); - double area = 0; + typename bg::default_area_result::type area = 0; BOOST_FOREACH(GeometryOut const& polygon, buffered) { area += bg::area(polygon); @@ -168,9 +168,14 @@ void test_buffer(std::string const& caseid, Geometry const& geometry, if (expected_area > -0.1) { + typename bg::default_area_result::type tolerance = 0.01; + if (join == 'r') + { + tolerance = 0.1; + } BOOST_CHECK_MESSAGE ( - std::abs(area - expected_area) < 0.11, + bg::math::abs(area - expected_area) < tolerance, complete.str() << " not as expected. " << " Expected: " << expected_area << " Detected: " << area