1 // Boost.Geometry (aka GGL, Generic Geometry Library)
4 // Copyright (c) 2010-2015 Barend Gehrels, Amsterdam, the Netherlands.
6 // This file was modified by Oracle on 2015, 2016.
7 // Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
8 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11 // Use, modification and distribution is subject to the Boost Software License,
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13 // http://www.boost.org/LICENSE_1_0.txt)
20 #include <boost/geometry/algorithms/correct.hpp>
21 #include <boost/geometry/algorithms/is_valid.hpp>
23 #include <boost/geometry/io/wkt/wkt.hpp>
25 #include <boost/geometry/geometries/point_xy.hpp>
27 #include "test_difference.hpp"
28 #include <algorithms/test_overlay.hpp>
29 #include <algorithms/overlay/overlay_cases.hpp>
30 #include <algorithms/overlay/multi_overlay_cases.hpp>
34 # include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
41 typedef bg::model::box
<P
> box
;
42 typedef bg::model::polygon
<P
> polygon
;
43 typedef bg::model::ring
<P
> ring
;
45 typedef typename
bg::coordinate_type
<P
>::type ct
;
47 ut_settings ignore_validity
;
48 ignore_validity
.test_validity
= false;
50 ut_settings sym_settings
;
51 #if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
52 sym_settings
.sym_difference
= false;
55 test_one
<polygon
, polygon
, polygon
>("simplex_normal",
56 simplex_normal
[0], simplex_normal
[1],
57 3, 12, 2.52636706856656,
58 3, 12, 3.52636706856656,
61 test_one
<polygon
, polygon
, polygon
>("simplex_with_empty",
62 simplex_normal
[0], polygon_empty
,
66 test_one
<polygon
, polygon
, polygon
>(
67 "star_ring", example_star
, example_ring
,
72 test_one
<polygon
, polygon
, polygon
>("two_bends",
73 two_bends
[0], two_bends
[1],
77 test_one
<polygon
, polygon
, polygon
>("star_comb_15",
78 star_comb_15
[0], star_comb_15
[1],
79 30, 160, 227.658275102812,
80 30, 198, 480.485775259312,
83 test_one
<polygon
, polygon
, polygon
>("new_hole",
84 new_hole
[0], new_hole
[1],
89 test_one
<polygon
, polygon
, polygon
>("crossed",
90 crossed
[0], crossed
[1],
94 test_one
<polygon
, polygon
, polygon
>("disjoint",
95 disjoint
[0], disjoint
[1],
99 // The too small one might be discarded (depending on point-type / compiler)
100 // We check area only
101 test_one
<polygon
, polygon
, polygon
>("distance_zero",
102 distance_zero
[0], distance_zero
[1],
107 test_one
<polygon
, polygon
, polygon
>("equal_holes_disjoint",
108 equal_holes_disjoint
[0], equal_holes_disjoint
[1],
112 test_one
<polygon
, polygon
, polygon
>("only_hole_intersections1",
113 only_hole_intersections
[0], only_hole_intersections
[1],
118 test_one
<polygon
, polygon
, polygon
>("only_hole_intersection2",
119 only_hole_intersections
[0], only_hole_intersections
[2],
124 test_one
<polygon
, polygon
, polygon
>("first_within_second",
125 first_within_second
[1], first_within_second
[0],
129 test_one
<polygon
, polygon
, polygon
>("fitting",
130 fitting
[0], fitting
[1],
135 test_one
<polygon
, polygon
, polygon
>("identical",
136 identical
[0], identical
[1],
140 test_one
<polygon
, polygon
, polygon
>("intersect_exterior_and_interiors_winded",
141 intersect_exterior_and_interiors_winded
[0], intersect_exterior_and_interiors_winded
[1],
145 test_one
<polygon
, polygon
, polygon
>("intersect_holes_intersect_and_disjoint",
146 intersect_holes_intersect_and_disjoint
[0], intersect_holes_intersect_and_disjoint
[1],
150 test_one
<polygon
, polygon
, polygon
>("intersect_holes_intersect_and_touch",
151 intersect_holes_intersect_and_touch
[0], intersect_holes_intersect_and_touch
[1],
156 ut_settings settings
= sym_settings
;
157 settings
.percentage
= 0.01;
158 test_one
<polygon
, polygon
, polygon
>("intersect_holes_new_ring",
159 intersect_holes_new_ring
[0], intersect_holes_new_ring
[1],
165 test_one
<polygon
, polygon
, polygon
>("first_within_hole_of_second",
166 first_within_hole_of_second
[0], first_within_hole_of_second
[1],
170 test_one
<polygon
, polygon
, polygon
>("intersect_holes_disjoint",
171 intersect_holes_disjoint
[0], intersect_holes_disjoint
[1],
175 test_one
<polygon
, polygon
, polygon
>("intersect_holes_intersect",
176 intersect_holes_intersect
[0], intersect_holes_intersect
[1],
180 test_one
<polygon
, polygon
, polygon
>(
181 "case4", case_4
[0], case_4
[1],
182 6, 28, 2.77878787878788,
183 4, 22, 4.77878787878788,
186 test_one
<polygon
, polygon
, polygon
>(
187 "case5", case_5
[0], case_5
[1],
188 8, 36, 2.43452380952381,
189 7, 33, 3.18452380952381);
191 #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS
192 // Fails, a-b is partly generated, b-a does not have any output
193 // It failed already in 1.59
194 test_one
<polygon
, polygon
, polygon
>("case_58_iet",
195 case_58
[0], case_58
[2],
197 1, -1, 11.1666666667);
200 test_one
<polygon
, polygon
, polygon
>("case_80",
201 case_80
[0], case_80
[1],
206 #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS
207 // Fails, holes are not subtracted
208 test_one
<polygon
, polygon
, polygon
>("case_81",
209 case_81
[0], case_81
[1],
215 test_one
<polygon
, polygon
, polygon
>("case_100",
216 case_100
[0], case_100
[1],
222 test_one
<polygon
, polygon
, polygon
>("winded",
223 winded
[0], winded
[1],
227 test_one
<polygon
, polygon
, polygon
>("within_holes_disjoint",
228 within_holes_disjoint
[0], within_holes_disjoint
[1],
232 test_one
<polygon
, polygon
, polygon
>("side_side",
233 side_side
[0], side_side
[1],
238 test_one
<polygon
, polygon
, polygon
>("buffer_mp1",
239 buffer_mp1
[0], buffer_mp1
[1],
243 #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
244 if ( BOOST_GEOMETRY_CONDITION((boost::is_same
<ct
, double>::value
)) )
246 test_one
<polygon
, polygon
, polygon
>("buffer_mp2",
247 buffer_mp2
[0], buffer_mp2
[1],
253 /*** TODO: self-tangencies for difference
254 test_one<polygon, polygon, polygon>("wrapped_a",
255 wrapped[0], wrapped[1],
259 test_one<polygon, polygon, polygon>("wrapped_b",
260 wrapped[0], wrapped[2],
266 ut_settings settings
;
267 #if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
268 settings
.percentage
= 0.1;
269 settings
.test_validity
= false;
271 settings
.percentage
= 0.001;
274 // Isovist - the # output polygons differ per compiler/pointtype, (very) small
275 // rings might be discarded. We check area only
276 test_one
<polygon
, polygon
, polygon
>("isovist",
277 isovist1
[0], isovist1
[1],
282 // SQL Server gives: 0.279121891701124 and 224.889211358929
283 // PostGIS gives: 0.279121991127244 and 224.889205853156
284 // No robustness gives: 0.279121991127106 and 224.825363749290
286 #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS
287 test_one
<polygon
, polygon
, polygon
>("geos_1",
288 geos_1
[0], geos_1
[1],
292 // Excluded this test in the normal suite, it is OK like this for many clang/gcc/msvc
293 // versions, but NOT OK for many other clang/gcc/msvc versions on other platforms
294 // It might depend on partition (order)
295 // 10, -1, 0.02148439); // change in partition might give these results
297 // SQL Server gives: 0.28937764436705 and 0.000786406897532288 with 44/35 rings
298 // PostGIS gives: 0.30859375 and 0.033203125 with 35/35 rings
302 // MSVC 14 expects 138.69214 and 211.85913: increase percentage
304 ut_settings settings
= sym_settings
;
305 settings
.percentage
= 0.01;
306 settings
.test_validity
= false;
308 test_one
<polygon
, polygon
, polygon
>("geos_2",
309 geos_2
[0], geos_2
[1],
315 test_one
<polygon
, polygon
, polygon
>("geos_3",
316 geos_3
[0], geos_3
[1],
319 1, -1, 16211128.5 + 13180420.0,
322 test_one
<polygon
, polygon
, polygon
>("geos_4",
323 geos_4
[0], geos_4
[1],
328 test_one
<polygon
, polygon
, polygon
>("ggl_list_20110306_javier",
329 ggl_list_20110306_javier
[0], ggl_list_20110306_javier
[1],
332 2, -1, 71495.3331 + 8960.49049);
334 test_one
<polygon
, polygon
, polygon
>("ggl_list_20110307_javier",
335 ggl_list_20110307_javier
[0], ggl_list_20110307_javier
[1],
336 1, if_typed
<ct
, float>(14, 13), 16815.6,
340 if ( BOOST_GEOMETRY_CONDITION((! boost::is_same
<ct
, float>::value
)) )
342 test_one
<polygon
, polygon
, polygon
>("ggl_list_20110716_enrico",
343 ggl_list_20110716_enrico
[0], ggl_list_20110716_enrico
[1],
344 3, -1, 35723.8506317139,
345 1, -1, 58456.4964294434,
346 1, -1, 35723.8506317139 + 58456.4964294434);
349 #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
350 test_one
<polygon
, polygon
, polygon
>("ggl_list_20110820_christophe",
351 ggl_list_20110820_christophe
[0], ggl_list_20110820_christophe
[1],
352 1, -1, 2.8570121719168924,
353 1, -1, 64.498061986388564);
356 test_one
<polygon
, polygon
, polygon
>("ggl_list_20120717_volker",
357 ggl_list_20120717_volker
[0], ggl_list_20120717_volker
[1],
358 1, 11, 3370866.2295081965,
359 1, 5, 384.2295081964694,
362 #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
363 // 2011-07-02 / 2014-06-19
364 // Interesting FP-precision case.
365 // sql server gives: 6.62295817619452E-05
366 // PostGIS gives: 0.0 (no output)
367 // Boost.Geometry gave results depending on FP-type, and compiler, and operating system.
368 // Since rescaling to integer results are equal w.r.t. compiler/FP type,
369 // however, some long spikes are still generated in the resulting difference
370 test_one
<polygon
, polygon
, polygon
>("ggl_list_20110627_phillip",
371 ggl_list_20110627_phillip
[0], ggl_list_20110627_phillip
[1],
372 if_typed_tt
<ct
>(1, 1), -1,
373 if_typed_tt
<ct
>(0.0000000000001105367, 0.000125137888971949),
374 1, -1, 3577.40960816756,
379 // Ticket 8310, one should be completely subtracted from the other.
380 test_one
<polygon
, polygon
, polygon
>("ticket_8310a",
381 ticket_8310a
[0], ticket_8310a
[1],
384 test_one
<polygon
, polygon
, polygon
>("ticket_8310b",
385 ticket_8310b
[0], ticket_8310b
[1],
388 test_one
<polygon
, polygon
, polygon
>("ticket_8310c",
389 ticket_8310c
[0], ticket_8310c
[1],
393 #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
394 test_one
<polygon
, polygon
, polygon
>("ticket_9081_15",
395 ticket_9081_15
[0], ticket_9081_15
[1],
396 2, 10, 0.0334529710902111,
397 1, 4, 5.3469555172380723e-010);
400 test_one
<polygon
, polygon
, polygon
>("ticket_9081_314",
401 ticket_9081_314
[0], ticket_9081_314
[1],
402 2, 12, 0.0451236449624935,
405 #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
406 test_one
<polygon
, polygon
, polygon
>("ticket_9563",
407 ticket_9563
[0], ticket_9563
[1],
412 test_one
<polygon
, polygon
, polygon
>("ticket_10108_a",
413 ticket_10108_a
[0], ticket_10108_a
[1],
418 #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
419 test_one
<polygon
, polygon
, polygon
>("ticket_10108_b",
420 ticket_10108_b
[0], ticket_10108_b
[1],
425 test_one
<polygon
, polygon
, polygon
>("ticket_11725",
426 ticket_11725
[0], ticket_11725
[1],
431 // From assemble-test, with a u/u case
432 test_one
<polygon
, polygon
, polygon
>("assemble_0210",
433 "POLYGON((0 0,0 10,10 10,10 0,0 0),(8.5 1,9.5 1,9.5 2,8.5 2,8.5 1))",
434 "POLYGON((2 0.5,0.5 2,0.5 8,2 9.5,6 9.5,8.5 8,8.5 2,7 0.5,2 0.5),(2 2,7 2,7 8,2 8,2 2))",
440 test_one
<polygon
, polygon
, ring
>(
441 "star_ring_ring", example_star
, example_ring
,
446 test_one
<polygon
, ring
, polygon
>(
447 "ring_star_ring", example_ring
, example_star
,
452 static std::string
const clip
= "POLYGON((2.5 0.5,5.5 2.5))";
454 test_one
<polygon
, box
, ring
>("star_box",
456 4, 20, 2.833333, 4, 16, 0.833333);
458 test_one
<polygon
, ring
, box
>("box_star",
460 4, 16, 0.833333, 4, 20, 2.833333);
465 typedef bg::model::polygon
<P
, false> polygon_ccw
;
466 test_one
<polygon
, polygon_ccw
, polygon_ccw
>(
467 "star_ring_ccw", example_star
, example_ring
,
471 test_one
<polygon
, polygon
, polygon_ccw
>(
472 "star_ring_ccw1", example_star
, example_ring
,
476 test_one
<polygon
, polygon_ccw
, polygon
>(
477 "star_ring_ccw2", example_star
, example_ring
,
483 // Multi/box (should be moved to multi)
485 typedef bg::model::multi_polygon
<polygon
> mp
;
487 static std::string
const clip
= "POLYGON((2 2,4 4))";
489 test_one
<polygon
, box
, mp
>("simplex_multi_box_mp",
490 clip
, case_multi_simplex
[0],
491 2, -1, 0.53333333333, 3, -1, 8.53333333333);
492 test_one
<polygon
, mp
, box
>("simplex_multi_mp_box",
493 case_multi_simplex
[0], clip
,
494 3, -1, 8.53333333333, 2, -1, 0.53333333333);
499 Experimental (cut), does not work:
500 test_one<polygon, polygon, polygon>(
501 "polygon_pseudo_line",
502 "POLYGON((0 0,0 4,4 4,4 0,0 0))",
503 "POLYGON((2 -2,2 -1,2 6,2 -2))",
508 // Should have 2 outputs
509 int const correction_for_invalidity
= 1; // should be 0
510 test_one
<polygon
, polygon
, polygon
>("mysql_21977775",
511 mysql_21977775
[0], mysql_21977775
[1],
512 2 - correction_for_invalidity
, -1, 160.856568913,
513 2, -1, 92.3565689126,
516 // also mysql_23023665
517 test_one
<polygon
, polygon
, polygon
>("mysql_21965285",
518 mysql_21965285
[0], mysql_21965285
[1],
519 1, 2 - correction_for_invalidity
, -1, 92.0,
521 1, 2, -1, 92.0 + 14.0,
524 test_one
<polygon
, polygon
, polygon
>("mysql_23023665_1",
525 mysql_23023665_1
[0], mysql_23023665_1
[1],
526 1, 2 - correction_for_invalidity
, -1, 92.0,
530 test_one
<polygon
, polygon
, polygon
>("mysql_23023665_2",
531 mysql_23023665_2
[0], mysql_23023665_2
[1],
532 1, 2 - correction_for_invalidity
, -1, 96.0,
536 test_one
<polygon
, polygon
, polygon
>("mysql_23023665_3",
537 mysql_23023665_3
[0], mysql_23023665_3
[1],
538 1, 2 - correction_for_invalidity
, -1, 225.0,
542 // Case mysql_23023665_4 is not yet included!
543 // test_one<polygon, polygon, polygon>("mysql_23023665_4",
544 // mysql_23023665_4[0], mysql_23023665_4[1],
547 // 1, 2, -1, 1.5 + 219.0);
549 test_one
<polygon
, polygon
, polygon
>("mysql_23023665_5",
550 mysql_23023665_5
[0], mysql_23023665_5
[1],
551 2 - correction_for_invalidity
, 2 - correction_for_invalidity
, -1, 165.23735,
554 test_one
<polygon
, polygon
, polygon
>("mysql_23023665_6",
555 mysql_23023665_6
[0], mysql_23023665_6
[1],
558 #if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
562 test_one
<polygon
, polygon
, polygon
>("mysql_23023665_13",
563 mysql_23023665_13
[0], mysql_23023665_13
[1],
564 3 - correction_for_invalidity
, 3 - correction_for_invalidity
, -1, 99.74526,
570 // Test cases for integer coordinates / ccw / open
571 template <typename Point
, bool ClockWise
, bool Closed
>
574 typedef bg::model::polygon
<Point
, ClockWise
, Closed
> polygon
;
576 test_one
<polygon
, polygon
, polygon
>("ggl_list_20120717_volker",
577 ggl_list_20120717_volker
[0], ggl_list_20120717_volker
[1],
580 1, 16, 3371540 + 385);
582 test_one
<polygon
, polygon
, polygon
>("ticket_10658",
583 ticket_10658
[0], ticket_10658
[1],
587 test_one
<polygon
, polygon
, polygon
>("ticket_11121",
588 ticket_11121
[0], ticket_11121
[1],
593 ut_settings settings
;
594 settings
.test_validity
= false;
595 #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS
596 settings
.test_validity
= true;
599 // Generates spikes, both a-b and b-a
600 test_one
<polygon
, polygon
, polygon
>("ticket_11676",
601 ticket_11676
[0], ticket_11676
[1],
604 2, -1, 2537992.5 + 294963.5,
610 int test_main(int, char* [])
612 test_all
<bg::model::d2::point_xy
<double> >();
614 test_specific
<bg::model::d2::point_xy
<int>, false, false>();
616 #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
617 test_all
<bg::model::d2::point_xy
<float> >();
620 std::cout
<< "Testing TTMATH" << std::endl
;
621 test_all
<bg::model::d2::point_xy
<ttmath_big
> >();