• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3 
4 // Copyright (c) 2010-2015 Barend Gehrels, Amsterdam, the Netherlands.
5 
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 
10 #include <iostream>
11 #include <string>
12 
13 #include "test_difference.hpp"
14 #include <algorithms/test_overlay.hpp>
15 #include <algorithms/overlay/multi_overlay_cases.hpp>
16 
17 #include <boost/geometry/algorithms/correct.hpp>
18 #include <boost/geometry/algorithms/intersection.hpp>
19 
20 #include <boost/geometry/geometries/point_xy.hpp>
21 #include <boost/geometry/geometries/multi_point.hpp>
22 #include <boost/geometry/geometries/multi_polygon.hpp>
23 
24 #include <boost/geometry/io/wkt/read.hpp>
25 
26 // Convenience macros (points are not checked)
27 #define TEST_DIFFERENCE(caseid, clips1, area1, clips2, area2, clips3) \
28     (test_one<Polygon, MultiPolygon, MultiPolygon>) \
29     ( #caseid, caseid[0], caseid[1], clips1, -1, area1, clips2, -1, area2, \
30                 clips3, -1, area1 + area2)
31 
32 #define TEST_DIFFERENCE_IGNORE(caseid, clips1, area1, clips2, area2, clips3) \
33     { ut_settings ignore_validity; ignore_validity.set_test_validity(false); \
34     (test_one<Polygon, MultiPolygon, MultiPolygon>) \
35     ( #caseid, caseid[0], caseid[1], clips1, -1, area1, clips2, -1, area2, \
36                 clips3, -1, area1 + area2, ignore_validity); }
37 
38 #define TEST_DIFFERENCE_WITH(index1, index2, caseid, clips1, area1, \
39                 clips2, area2, clips3) \
40     (test_one<Polygon, MultiPolygon, MultiPolygon>) \
41     ( #caseid "_" #index1 "_" #index2, caseid[index1], caseid[index2], \
42             clips1, -1, area1, \
43             clips2, -1, area2, \
44             clips3, -1, area1 + area2, settings)
45 
46 
47 template <typename Ring, typename Polygon, typename MultiPolygon>
test_areal()48 void test_areal()
49 {
50     test_one<Polygon, MultiPolygon, MultiPolygon>("simplex_multi",
51             case_multi_simplex[0], case_multi_simplex[1],
52             5, 21, 5.58, 4, 17, 2.58);
53 
54     test_one<Polygon, MultiPolygon, MultiPolygon>("case_multi_no_ip",
55             case_multi_no_ip[0], case_multi_no_ip[1],
56             2, 12, 24.0, 2, 12, 34.0);
57     test_one<Polygon, MultiPolygon, MultiPolygon>("case_multi_2",
58             case_multi_2[0], case_multi_2[1],
59             2, 15, 19.6, 2, 13, 33.6);
60 
61     test_one<Polygon, MultiPolygon, Polygon>("simplex_multi_mp_p",
62             case_multi_simplex[0], case_single_simplex,
63             5, 21, 5.58, 4, 17, 2.58);
64     test_one<Polygon, Ring, MultiPolygon>("simplex_multi_r_mp",
65             case_single_simplex, case_multi_simplex[0],
66             4, 17, 2.58, 5, 21, 5.58);
67     test_one<Polygon, MultiPolygon, Ring>("simplex_multi_mp_r",
68             case_multi_simplex[0], case_single_simplex,
69             5, 21, 5.58, 4, 17, 2.58);
70 
71     // Constructed cases for multi/touch/equal/etc
72     test_one<Polygon, MultiPolygon, MultiPolygon>("case_61_multi",
73             case_61_multi[0], case_61_multi[1],
74             2, 10, 2, 2, 10, 2, 1, 10, 4);
75     test_one<Polygon, MultiPolygon, MultiPolygon>("case_62_multi",
76             case_62_multi[0], case_62_multi[1],
77             0, 0, 0, 1, 5, 1);
78     test_one<Polygon, MultiPolygon, MultiPolygon>("case_63_multi",
79             case_63_multi[0], case_63_multi[1],
80             0, 0, 0, 1, 5, 1);
81     test_one<Polygon, MultiPolygon, MultiPolygon>("case_64_multi",
82         case_64_multi[0], case_64_multi[1],
83         1, 5, 1, 1, 5, 1, 1, 7, 2);
84     test_one<Polygon, MultiPolygon, MultiPolygon>("case_65_multi",
85         case_65_multi[0], case_65_multi[1],
86             0, 0, 0, 2, 10, 3);
87 
88     test_one<Polygon, MultiPolygon, MultiPolygon>("case_72_multi",
89         case_72_multi[0], case_72_multi[1],
90             3, 13, 1.65, 3, 17, 6.15);
91 
92     test_one<Polygon, MultiPolygon, MultiPolygon>("case_77_multi",
93         case_77_multi[0], case_77_multi[1],
94             6, 31, 7.0,
95             5, 33, 13.0,
96             5, 38, 7.0 + 13.0);
97 
98     test_one<Polygon, MultiPolygon, MultiPolygon>("case_78_multi",
99         case_78_multi[0], case_78_multi[1],
100             1, 5, 1.0, 1, 5, 1.0);
101 
102     TEST_DIFFERENCE(case_123_multi, 1, 0.25, 2, 0.625, 3);
103     TEST_DIFFERENCE(case_124_multi, 1, 0.25, 2, 0.4375, 3);
104     TEST_DIFFERENCE(case_125_multi, 1, 0.25, 2, 0.400, 3);
105 
106     // A should have 3 clips, B should have 5 clips
107     TEST_DIFFERENCE(case_126_multi, 4, 16.0, 5, 27.0, 9);
108 
109     {
110         ut_settings settings;
111 
112         settings.sym_difference = BG_IF_RESCALED(false, true);
113 
114         test_one<Polygon, MultiPolygon, MultiPolygon>("case_108_multi",
115             case_108_multi[0], case_108_multi[1],
116                 7, 32, 5.5,
117                 4, 24, 9.75,
118                 7, 45, 15.25,
119                 settings);
120     }
121 
122     // Ticket on GGL list 2011/10/25
123     // to mix polygon/multipolygon in call to difference
124     test_one<Polygon, Polygon, Polygon>("ggl_list_20111025_vd_pp",
125         ggl_list_20111025_vd[0], ggl_list_20111025_vd[1],
126             1, 4, 8.0, 1, 4, 12.5);
127     test_one<Polygon, Polygon, MultiPolygon>("ggl_list_20111025_vd_pm",
128         ggl_list_20111025_vd[0], ggl_list_20111025_vd[3],
129             1, 4, 8.0, 1, 4, 12.5);
130     test_one<Polygon, MultiPolygon, Polygon>("ggl_list_20111025_vd_mp",
131         ggl_list_20111025_vd[2], ggl_list_20111025_vd[1],
132             1, 4, 8.0, 1, 4, 12.5);
133     test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20111025_vd_mm",
134         ggl_list_20111025_vd[2], ggl_list_20111025_vd[3],
135             1, 4, 8.0, 1, 4, 12.5);
136 
137     test_one<Polygon, Polygon, MultiPolygon>("ggl_list_20111025_vd_2",
138         ggl_list_20111025_vd_2[0], ggl_list_20111025_vd_2[1],
139             1, 7, 10.0, 2, 10, 6.0);
140 
141     test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120915_h2_a",
142         ggl_list_20120915_h2[0], ggl_list_20120915_h2[1],
143             2, 13, 17.0, 0, 0, 0.0);
144     test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120915_h2_b",
145         ggl_list_20120915_h2[0], ggl_list_20120915_h2[2],
146             2, 13, 17.0, 0, 0, 0.0);
147 
148     {
149         ut_settings settings;
150         settings.percentage = 0.001;
151         settings.set_test_validity(BG_IF_RESCALED(true, false));
152         TEST_DIFFERENCE_WITH(0, 1, ggl_list_20120221_volker, 2, 7962.66, 2, 2775258.93, 4);
153     }
154 
155     {
156         // With rescaling, A is invalid (this is a robustness problem) and the other
157         // output is discarded because of zero area
158         // POSTGIS areas: 3.75893745345145, 2.5810000723917e-15
159         ut_settings settings;
160         settings.sym_difference = BG_IF_RESCALED(false, true);
161         settings.set_test_validity(BG_IF_RESCALED(false, true));
162 #if defined(BOOST_GEOMETRY_USE_RESCALING) || ! defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
163         // No output for B
164         TEST_DIFFERENCE_WITH(0, 1, bug_21155501, 1, 3.758937, 0, 0.0, 1);
165 #else
166         // Very small sliver for B, and sym difference is not considered valid
167         settings.set_test_validity(false);
168         TEST_DIFFERENCE_WITH(0, 1, bug_21155501, 1, 3.758937, 1, 1.7763568394002505e-15, 2);
169 #endif
170     }
171 
172 #if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES)
173     {
174         // With rescaling, it is complete but invalid
175         // Without rescaling, one ring is missing (for a and s)
176         ut_settings settings;
177         settings.percentage = 0.001;
178         settings.set_test_validity(BG_IF_RESCALED(false, true));
179         TEST_DIFFERENCE_WITH(0, 1, ticket_9081,
180                              2, 0.0907392476356186,
181                              4, 0.126018011439877,
182                              BG_IF_RESCALED(4, 3));
183     }
184 #endif
185 
186     TEST_DIFFERENCE(ticket_12503, 46, 920.625, 4, 7.625, 50);
187 
188     {
189         // Reported issues going wrong with rescaling (except for 630b)
190         ut_settings settings;
191         settings.percentage = 0.001;
192 
193 #if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES)
194         TEST_DIFFERENCE_WITH(0, 1, issue_630_a, 0, 0.0, 1, BG_IF_KRAMER(2.023326, 2.200326), 1);
195 #endif
196         TEST_DIFFERENCE_WITH(0, 1, issue_630_b, 1, 0.0056089, 2, 1.498976, 3);
197 #if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES)
198 
199 #if defined(BOOST_GEOMETRY_USE_KRAMER) || defined(BOOST_GEOMETRY_TEST_FAILURES)
200         // Only succeeds with Kramer rule and no rescaling
201         TEST_DIFFERENCE_WITH(0, 1, issue_630_c, 0, 0, 1, 1.493367, 1);
202 #endif
203 
204         TEST_DIFFERENCE_WITH(0, 1, issue_643, 1, 76.5385, BG_IF_KRAMER(1, 0), BG_IF_KRAMER(2.8634e-09, 0.0), 1);
205 #endif
206     }
207 
208     // Areas and #clips correspond with POSTGIS (except sym case)
209     test_one<Polygon, MultiPolygon, MultiPolygon>("case_101_multi",
210         case_101_multi[0], case_101_multi[1],
211             5, 23, 4.75,
212             5, 40, 12.75,
213             5, 48, 4.75 + 12.75);
214 
215     // Areas and #clips correspond with POSTGIS
216     test_one<Polygon, MultiPolygon, MultiPolygon>("case_102_multi",
217         case_102_multi[0], case_102_multi[1],
218             2, 8, 0.75,
219             6, 25, 3.75,
220             6, 27, 0.75 + 3.75);
221 
222     // Areas and #clips correspond with POSTGIS
223     test_one<Polygon, MultiPolygon, MultiPolygon>("case_107_multi",
224         case_107_multi[0], case_107_multi[1],
225             2, 11, 2.25,
226             3, 14, 3.0,
227             4, 21, 5.25);
228 
229     TEST_DIFFERENCE(case_133_multi, 3, 16.0, 2, 8.0, 5);
230     TEST_DIFFERENCE(case_134_multi, 3, 16.0, 2, 8.0, 5);
231     TEST_DIFFERENCE(case_135_multi, 2, 2.0, 2, 13.0, 2);
232     TEST_DIFFERENCE(case_136_multi, 2, 2.0, 3, 13.5, 3);
233     TEST_DIFFERENCE(case_137_multi, 2, 2.5, 2, 13.0, 2);
234     TEST_DIFFERENCE(case_138_multi, 5, 16.6, 3, 8.225, 8);
235     TEST_DIFFERENCE(case_139_multi, 4, 16.328125, 3, 8.078125, 7);
236     TEST_DIFFERENCE(case_140_multi, 4, 16.328125, 3, 8.078125, 7);
237     TEST_DIFFERENCE(case_141_multi, 5, 15.5, 5, 10.0, 10);
238 
239     // Areas correspond with POSTGIS,
240     // #clips in PostGIS is 11,11,5 but should most probably be be 12,12,6
241     TEST_DIFFERENCE(case_recursive_boxes_1, 12, 26.0, 12, 24.0, 6);
242 
243     // Areas and #clips correspond with POSTGIS
244     test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_2",
245         case_recursive_boxes_2[0], case_recursive_boxes_2[1],
246             3, 15, 3.0,
247             7, 33, 7.0,
248             10, 48, 10.0);
249 
250     // Areas and #clips by POSTGIS (except sym case)
251     test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_3",
252         case_recursive_boxes_3[0], case_recursive_boxes_3[1],
253             24, -1, 21.5,
254             25, -1, 22.5,
255             37, -1, 44.0);
256 
257     // 4, input is not valid
258 
259     TEST_DIFFERENCE(case_recursive_boxes_5, 16, 22.0, 12, 27.0, 10);
260     TEST_DIFFERENCE(case_recursive_boxes_6, 7, 3.5, 3, 1.5, 9);
261 
262     test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_7",
263         case_recursive_boxes_7[0], case_recursive_boxes_7[1],
264             3, 15, 2.75,
265             4, 19, 2.75,
266             3, 22, 5.5);
267 
268     test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_8",
269         case_recursive_boxes_8[0], case_recursive_boxes_8[1],
270             2, -1, 2.50,
271             4, -1, 5.75,
272             4, -1, 8.25);
273 
274     test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_9",
275         case_recursive_boxes_9[0], case_recursive_boxes_9[1],
276             3, -1, 1.5,
277             4, -1, 2.5,
278             6, -1, 4.0);
279 
280     test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_10",
281         case_recursive_boxes_10[0], case_recursive_boxes_10[1],
282             2, -1, 1.25,
283             2, -1, 0.75,
284             4, -1, 2.00);
285 
286     test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_11",
287         case_recursive_boxes_11[0], case_recursive_boxes_11[1],
288             3, -1, 2.5,
289             3, -1, 4.5,
290             3, -1, 7.0);
291 
292     TEST_DIFFERENCE(case_recursive_boxes_12, 4, 2.75, 3, 2.75, 6);
293     TEST_DIFFERENCE(case_recursive_boxes_13, 4, 4.75, 3, 5.5, 3);
294     TEST_DIFFERENCE(case_recursive_boxes_14, 3, 2.0, 4, 2.5, 5);
295     TEST_DIFFERENCE(case_recursive_boxes_15, 3, 3.0, 2, 2.5, 3);
296     TEST_DIFFERENCE(case_recursive_boxes_16, 8, 6.5, 3, 5.5, 9);
297     TEST_DIFFERENCE(case_recursive_boxes_17, 10, 7.75, 7, 5.5, 13);
298     TEST_DIFFERENCE(case_recursive_boxes_18, 2, 1.0, 1, 1.5, 3);
299     TEST_DIFFERENCE(case_recursive_boxes_19, 2, 1.0, 2, 1.5, 3);
300     TEST_DIFFERENCE(case_recursive_boxes_20, 2, 1.0, 0, 0.0, 2);
301 
302     TEST_DIFFERENCE(case_recursive_boxes_21, 2, 1.0, 1, 1.0, 1);
303     TEST_DIFFERENCE(case_recursive_boxes_22, 2, 1.25, 2, 2.0, 2);
304     TEST_DIFFERENCE(case_recursive_boxes_23, 2, 0.75, 1, 0.5, 3);
305     TEST_DIFFERENCE(case_recursive_boxes_24, 3, 2.5, 2, 2.0, 5);
306     TEST_DIFFERENCE(case_recursive_boxes_25, 2, 2.5, 3, 2.5, 2);
307     TEST_DIFFERENCE(case_recursive_boxes_26, 2, 1.5, 3, 2.0, 4);
308     TEST_DIFFERENCE(case_recursive_boxes_27, 1, 1.5, 3, 2.5, 3);
309     TEST_DIFFERENCE(case_recursive_boxes_28, 3, 2.5, 2, 3.0, 4);
310     TEST_DIFFERENCE(case_recursive_boxes_29, 5, 7.25, 5, 4.5, 5);
311     TEST_DIFFERENCE(case_recursive_boxes_30, 6, 4.25, 3, 7.25, 7);
312 
313     TEST_DIFFERENCE(case_recursive_boxes_31, 2, 2.0, 1, 0.5, 2);
314     TEST_DIFFERENCE(case_recursive_boxes_32, 2, 2.75, 2, 1.25, 2);
315     TEST_DIFFERENCE(case_recursive_boxes_33, 4, 3.0, 3, 6.0, 4);
316     TEST_DIFFERENCE(case_recursive_boxes_34, 7, 7.25, 1, 0.5, 8);
317     TEST_DIFFERENCE(case_recursive_boxes_35, 5, 1.75, 5, 2.75, 10);
318     TEST_DIFFERENCE(case_recursive_boxes_36, 2, 1.0, 2, 1.5, 3);
319     TEST_DIFFERENCE(case_recursive_boxes_37, 3, 2.5, 2, 4.25, 2);
320     TEST_DIFFERENCE(case_recursive_boxes_38, 5, 7.75, 4, 3.5, 3);
321     TEST_DIFFERENCE(case_recursive_boxes_39, 3, 6.0, 3, 3.0, 4);
322     TEST_DIFFERENCE(case_recursive_boxes_40, 11, 14.0, 9, 13.0, 11);
323 
324     TEST_DIFFERENCE(case_recursive_boxes_41, 1, 0.5, 1, 0.5, 2);
325     TEST_DIFFERENCE(case_recursive_boxes_42, 1, 1.0, 4, 4.0, 5);
326     TEST_DIFFERENCE(case_recursive_boxes_43, 1, 0.5, 3, 2.0, 4);
327     TEST_DIFFERENCE(case_recursive_boxes_44, 3, 5.0, 0, 0.0, 3);
328     TEST_DIFFERENCE(case_recursive_boxes_45, 6, 20.0, 7, 20.0, 3);
329     TEST_DIFFERENCE(case_recursive_boxes_46, 4, 14.0, 5, 12.0, 5);
330     TEST_DIFFERENCE(case_recursive_boxes_47, 4, 10.0, 7, 11.0, 1);
331     TEST_DIFFERENCE(case_recursive_boxes_48, 0, 0.0, 1, 9.0, 1);
332     TEST_DIFFERENCE(case_recursive_boxes_49, 10, 22.0, 10, 17.0, 11);
333     TEST_DIFFERENCE(case_recursive_boxes_50, 14, 21.0, 16, 21.0, 14);
334     TEST_DIFFERENCE(case_recursive_boxes_51, 14, 25.0, 12, 31.0, 7);
335     TEST_DIFFERENCE(case_recursive_boxes_52, 13, 30.0, 15, 25.0, 8);
336     TEST_DIFFERENCE(case_recursive_boxes_53, 6, 3.5, 4, 1.5, 9);
337     TEST_DIFFERENCE(case_recursive_boxes_54, 6, 6.5, 8, 6.0, 7);
338     TEST_DIFFERENCE(case_recursive_boxes_55, 4, 5.5, 6, 7.75, 4);
339     TEST_DIFFERENCE(case_recursive_boxes_56, 4, 4.5, 5, 2.75, 6);
340     TEST_DIFFERENCE(case_recursive_boxes_57, 5, 3.75, 9, 6.5, 10);
341     TEST_DIFFERENCE(case_recursive_boxes_58, 4, 2.25, 6, 3.75, 7);
342     TEST_DIFFERENCE(case_recursive_boxes_59, 8, 6.5, 7, 7.0, 12);
343     TEST_DIFFERENCE(case_recursive_boxes_60, 6, 5.25, 7, 5.25, 11);
344     TEST_DIFFERENCE(case_recursive_boxes_61, 2, 1.5, 6, 2.0, 7);
345 #if defined(BOOST_GEOMETRY_TEST_FAILURES)
346     // Misses one triangle, should be fixed in traversal.
347     // It is not related to rescaling.
348     TEST_DIFFERENCE(case_recursive_boxes_62, 5, 5.0, 11, 5.75, 12);
349 #endif
350 
351     TEST_DIFFERENCE(case_recursive_boxes_63, 9, 10.5, 5, 27.75, 4);
352     TEST_DIFFERENCE(case_recursive_boxes_64, 6, 2.75, 7, 4.5, 11);
353     TEST_DIFFERENCE(case_recursive_boxes_65, 6, 4.25, 7, 3.0, 13);
354     TEST_DIFFERENCE(case_recursive_boxes_66, 5, 4.75, 7, 4.0, 9);
355     TEST_DIFFERENCE(case_recursive_boxes_67, 7, 6.25, 9, 6.0, 10);
356     TEST_DIFFERENCE(case_recursive_boxes_68, 10, 6.5, 9, 6.5, 7);
357     TEST_DIFFERENCE(case_recursive_boxes_69, 5, 6.25, 5, 6.75, 8);
358     TEST_DIFFERENCE(case_recursive_boxes_70, 5, 2.0, 8, 4.5, 11);
359     TEST_DIFFERENCE(case_recursive_boxes_71, 7, 8.25, 7, 5.75, 8);
360     TEST_DIFFERENCE(case_recursive_boxes_72, 6, 6.5, 7, 4.0, 10);
361     TEST_DIFFERENCE(case_recursive_boxes_73, 4, 1.75, 5, 4.0, 8);
362     TEST_DIFFERENCE(case_recursive_boxes_74, 3, 3.00, 3, 1.5, 5);
363     TEST_DIFFERENCE(case_recursive_boxes_75, 7, 4.5, 4, 2.0, 11);
364     TEST_DIFFERENCE(case_recursive_boxes_76, 7, 3.75, 4, 2.5, 9);
365     TEST_DIFFERENCE(case_recursive_boxes_77, 4, 3.75, 7, 6.25, 8);
366     TEST_DIFFERENCE(case_recursive_boxes_78, 11, 5.5, 8, 4.5, 14);
367     TEST_DIFFERENCE(case_recursive_boxes_79, 2, 1.25, 6, 4.5, 8);
368 
369     // one polygon is divided into two, for same reason as union creates a small
370     // interior ring there
371     TEST_DIFFERENCE(case_recursive_boxes_80, 1, 0.5, 2, 0.75, BG_IF_RESCALED(3, 2));
372 
373     TEST_DIFFERENCE(case_recursive_boxes_81, 3, 5.0, 6, 6.75, 6);
374     TEST_DIFFERENCE(case_recursive_boxes_82, 5, 7.25, 7, 4.5, 8);
375     TEST_DIFFERENCE(case_recursive_boxes_83, 9, 5.25, 8, 5.25, 12);
376     TEST_DIFFERENCE(case_recursive_boxes_84, 4, 8.0, 7, 9.0, 4);
377 #if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES)
378     TEST_DIFFERENCE(case_recursive_boxes_85, 4, 4.0, 7, 3.75, 9);
379 #endif
380 
381     TEST_DIFFERENCE(case_recursive_boxes_86, 1, 1.5, 2, 1.5, 3);
382     TEST_DIFFERENCE(case_recursive_boxes_87, 4, 2.0, 4, 2.5, 8);
383     TEST_DIFFERENCE(case_recursive_boxes_88, 3, 4.75, 5, 6.75, 4);
384 
385     // Output of A can be 0 or 1 polygons (with a very small area)
386     TEST_DIFFERENCE(case_precision_m1, optional(), 0.0, 1, 57.0, count_set(1, 2));
387     // Output of A can be 1 or 2 polygons (one with a very small area)
388     TEST_DIFFERENCE(case_precision_m2, count_set(1, 2), 1.0, 1, 57.75, count_set(2, 3));
389 
390     {
391         ut_settings sym_settings;
392     #if ! defined(BOOST_GEOMETRY_USE_RESCALING)
393         sym_settings.sym_difference = false;
394     #endif
395         test_one<Polygon, MultiPolygon, MultiPolygon>("mysql_21965285_b",
396             mysql_21965285_b[0],
397             mysql_21965285_b[1],
398             2, -1, 183.71376870369406,
399             2, -1, 131.21376870369406,
400             sym_settings);
401     }
402 
403     TEST_DIFFERENCE(mysql_regression_1_65_2017_08_31,
404                     optional(), BG_IF_RESCALED(4.30697514e-7, 0),
405                     3, 152.0642, count_set(3, 4));
406 }
407 
408 
409 template <typename P>
test_all()410 void test_all()
411 {
412     typedef bg::model::ring<P> ring;
413     typedef bg::model::polygon<P> polygon;
414     typedef bg::model::multi_polygon<polygon> multi_polygon;
415     test_areal<ring, polygon, multi_polygon>();
416 }
417 
418 
419 // Test cases for integer coordinates / ccw / open
420 template <typename Polygon, typename MultiPolygon>
test_specific_areal()421 void test_specific_areal()
422 {
423     {
424         // Spikes in a-b and b-a, failure in symmetric difference
425         ut_settings settings;
426         settings.sym_difference = false;
427         settings.set_test_validity(false);
428 
429         TEST_DIFFERENCE_WITH(0, 1, ticket_11674,
430                              BG_IF_KRAMER(3, 4),
431                              BG_IF_KRAMER(9105781.5, 9105473.5),
432                              5,
433                              BG_IF_KRAMER(119059.5, 119423), ignore_count());
434     }
435 
436     {
437         // Ticket 12751 (Volker)
438         // Spikes in a-b and b-a, failure in symmetric difference
439 
440         ut_settings settings;
441         settings.remove_spikes = true;
442 
443         TEST_DIFFERENCE_WITH(0, 1, ticket_12751, 1,
444                              BG_IF_KRAMER(2781965.0, 2782114), 1,
445                              BG_IF_KRAMER(597.0, 598.0), 2);
446 
447 #if ! defined(BOOST_GEOMETRY_USE_KRAMER)
448         // Fails with general line form intersection, symmetric version misses one outcut
449         // TODO GENERAL FORM
450         settings.set_test_validity(false);
451         settings.sym_difference = false;
452 #endif
453 
454         TEST_DIFFERENCE_WITH(2, 3, ticket_12751,
455                              2, BG_IF_KRAMER(2537992.5, 2538305),
456                              2, BG_IF_KRAMER(294963.5, 294737),
457                              3);
458     }
459 
460     {
461         // Ticket 12752 (Volker)
462         // Spikes in a-b and b-a, failure in symmetric difference
463         ut_settings settings;
464         settings.remove_spikes = true;
465         settings.sym_difference = false;
466         TEST_DIFFERENCE_WITH(0, 1, ticket_12752,
467                              BG_IF_KRAMER(3, 2), BG_IF_KRAMER(2776692.0, 2776657),
468                              3, BG_IF_KRAMER(7893.0, 7710.5),
469                              2);
470     }
471 
472     {
473 #if defined(BOOST_GEOMETRY_USE_KRAMER) || defined(BOOST_GEOMETRY_TEST_FAILURES)
474         // Fails completely with general line form intersection
475         // There is something with scale.
476         // TODO GENERAL FORM
477         const std::string a_min_b =
478             TEST_DIFFERENCE(ticket_10661, 2, 1441632.5, 2, 13167454, 4);
479 
480         test_one<Polygon, MultiPolygon, MultiPolygon>("ticket_10661_2",
481             a_min_b, ticket_10661[2],
482             1, 8, 825192.0,
483             1, 10, BG_IF_KRAMER(27226370.5, 27842811),
484             1, -1, 825192.0 + 27226370.5);
485 #endif
486     }
487 
488     {
489         ut_settings settings;
490         settings.sym_difference = false;
491 
492 #if defined(BOOST_GEOMETRY_USE_KRAMER) || defined(BOOST_GEOMETRY_TEST_FAILURES)
493         // Fails with general line form intersection
494         // Misses one clip
495         // TODO GENERAL FORM
496         TEST_DIFFERENCE_WITH(0, 1, ticket_9942, 4, 7427727.5, 4,
497                              BG_IF_KRAMER(131506, 130083.5), 4);
498 #endif
499         TEST_DIFFERENCE_WITH(0, 1, ticket_9942a, 2,
500                              BG_IF_KRAMER(412676.5, 413183.5), 2,
501                              BG_IF_KRAMER(76779.5, 76924), 4);
502     }
503 }
504 
505 template <typename Point, bool ClockWise, bool Closed>
test_specific()506 void test_specific()
507 {
508     typedef bg::model::polygon<Point, ClockWise, Closed> polygon;
509     typedef bg::model::multi_polygon<polygon> multi_polygon;
510     test_specific_areal<polygon, multi_polygon>();
511 }
512 
513 
test_main(int,char * [])514 int test_main(int, char* [])
515 {
516     BoostGeometryWriteTestConfiguration();
517     test_all<bg::model::d2::point_xy<default_test_type> >();
518 
519     test_specific<bg::model::d2::point_xy<int>, false, false>();
520 
521 #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
522     test_all<bg::model::d2::point_xy<float> >();
523 
524 #if defined(HAVE_TTMATH)
525     std::cout << "Testing TTMATH" << std::endl;
526     test_all<bg::model::d2::point_xy<ttmath_big> >();
527 #endif
528 
529 #endif
530 
531 #if defined(BOOST_GEOMETRY_TEST_FAILURES)
532     BoostGeometryWriteExpectedFailures(23, 13);
533 #endif
534 
535     return 0;
536 }
537