]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/test/algorithms/overlay/traverse.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / geometry / test / algorithms / overlay / traverse.cpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3
4 // Copyright (c) 2010-2015 Barend Gehrels, Amsterdam, the Netherlands.
5
6 // This file was modified by Oracle on 2021.
7 // Modifications copyright (c) 2021, Oracle and/or its affiliates.
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
9
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13
14 #define BOOST_GEOMETRY_DEFINE_STREAM_OPERATOR_SEGMENT_RATIO
15
16 #include <iostream>
17 #include <iomanip>
18 #include <fstream>
19 #include <sstream>
20 #include <string>
21
22 #include <geometry_test_common.hpp>
23
24
25 // #define BOOST_GEOMETRY_DEBUG_ENRICH
26 //#define BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
27
28 // #define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
29
30
31 #define BOOST_GEOMETRY_TEST_OVERLAY_NOT_EXCHANGED
32
33 #ifdef BOOST_GEOMETRY_DEBUG_ENRICH
34 # define BOOST_GEOMETRY_DEBUG_IDENTIFIER
35 #endif
36
37 #include <boost/geometry/algorithms/area.hpp>
38 #include <boost/geometry/algorithms/correct.hpp>
39 #include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
40 #include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
41 #include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
42 #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
43 #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
44 #include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
45 #include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
46 #include <boost/geometry/algorithms/detail/overlay/traverse.hpp>
47 #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
48
49 #include <boost/geometry/geometries/geometries.hpp>
50
51 #include <boost/geometry/io/wkt/wkt.hpp>
52
53 #if defined(TEST_WITH_SVG)
54 # include <boost/geometry/io/svg/svg_mapper.hpp>
55 #endif
56
57 #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
58
59 #include <boost/geometry/strategies/strategies.hpp>
60
61 #include <algorithms/overlay/overlay_cases.hpp>
62
63 template <bg::overlay_type Op>
64 static inline std::string operation()
65 {
66 switch(Op)
67 {
68 case bg::overlay_union : return "union";
69 case bg::overlay_intersection : return "intersection";
70 case bg::overlay_difference : return "difference";
71 }
72 return "unknown";
73 }
74
75
76 namespace detail
77 {
78
79 template
80 <
81 typename G1, typename G2,
82 bg::overlay_type OverlayType,
83 bool Reverse1, bool Reverse2
84 >
85 struct test_traverse
86 {
87
88 static void apply(std::string const& id,
89 std::size_t expected_count, double expected_area,
90 G1 const& g1, G2 const& g2,
91 double precision)
92 {
93 // DEBUG ONE or FEW CASE(S) ONLY
94 //if (! boost::contains(id, "36") || Direction != 1) return;
95 //if (! boost::contains(id, "iet_") || boost::contains(id, "st")) return;
96 //if (! boost::contains(id, "66") || Direction != 1) return;
97 //if (! boost::contains(id, "92") && ! boost::contains(id, "96") ) return;
98 //if (! (boost::contains(id, "58_st") || boost::contains(id, "59_st") || boost::contains(id, "60_st") || boost::contains(id, "83")) ) return;
99 //if (! (boost::contains(id, "81") || boost::contains(id, "82") || boost::contains(id, "84") || boost::contains(id, "85") || boost::contains(id, "68")) ) return;
100 //if (! (boost::contains(id, "81") || boost::contains(id, "86") || boost::contains(id, "88")) ) return;
101 //if (! boost::contains(id, "58_") || Direction != 1) return;
102 //if (! boost::contains(id, "55") || Direction != 1) return;
103 //if (! boost::contains(id, "55_iet_iet") || Direction != 1) return;
104 //if (! boost::contains(id, "55_st_iet") || Direction != 1) return;
105 //if (! boost::contains(id, "55_iet_st") || Direction != 1) return;
106 //if (! boost::contains(id, "54_st_st") || Direction != 1) return;
107 //if (! boost::contains(id, "54_iet_st") || Direction != 1) return;
108 //if (! (boost::contains(id, "54_") || boost::contains(id, "55_")) || Direction != 1) return;
109 //if (Direction != 1) return;
110 // END DEBUG ONE ...
111
112
113 /*** FOR REVERSING ONLY
114 {
115 // If one or both are invalid (e.g. ccw),
116 // they can be corrected by uncommenting this section
117 G1 cg1 = g1;
118 G2 cg2 = g2;
119 bg::correct(cg1);
120 bg::correct(cg2);
121 std::cout << std::setprecision(12)
122 << bg::wkt(cg1) << std::endl
123 << bg::wkt(cg2) << std::endl;
124 }
125 ***/
126
127 #if defined(BOOST_GEOMETRY_DEBUG_OVERLAY) || defined(BOOST_GEOMETRY_DEBUG_ENRICH)
128 bool const ccw =
129 bg::point_order<G1>::value == bg::counterclockwise
130 || bg::point_order<G2>::value == bg::counterclockwise;
131
132 std::cout << std::endl
133 << "TRAVERSE"
134 << " " << id
135 << (ccw ? "_ccw" : "")
136 << " " << string_from_type<typename bg::coordinate_type<G1>::type>::name()
137 << "(" << OverlayType << ")" << std::endl;
138
139 //std::cout << bg::area(g1) << " " << bg::area(g2) << std::endl;
140 #endif
141
142 typename bg::strategy::intersection::services::default_strategy
143 <
144 typename bg::cs_tag<G1>::type
145 >::type strategy;
146
147 typedef typename bg::point_type<G2>::type point_type;
148 typedef typename bg::rescale_policy_type<point_type>::type
149 rescale_policy_type;
150
151 rescale_policy_type rescale_policy
152 = bg::get_rescale_policy<rescale_policy_type>(g1, g2);
153
154 typedef bg::detail::overlay::traversal_turn_info
155 <
156 point_type,
157 typename bg::detail::segment_ratio_type<point_type, rescale_policy_type>::type
158 > turn_info;
159 std::vector<turn_info> turns;
160
161 std::map<bg::signed_size_type, bg::detail::overlay::cluster_info> clusters;
162
163 bg::detail::get_turns::no_interrupt_policy policy;
164 bg::get_turns<Reverse1, Reverse2, bg::detail::overlay::assign_null_policy>(g1, g2, strategy, rescale_policy, turns, policy);
165 bg::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns, clusters, g1, g2, rescale_policy, strategy);
166
167 typedef bg::model::ring<typename bg::point_type<G2>::type> ring_type;
168 typedef std::vector<ring_type> out_vector;
169 out_vector v;
170
171 bg::detail::overlay::overlay_null_visitor visitor;
172
173 // TODO: this function requires additional arguments
174 bg::detail::overlay::traverse
175 <
176 Reverse1, Reverse2,
177 G1, G2,
178 OverlayType
179 >::apply(g1, g2, strategy, rescale_policy, turns, v, visitor);
180
181 // Check number of resulting rings
182 BOOST_CHECK_MESSAGE(expected_count == boost::size(v),
183 "traverse: " << id
184 << " (" << operation<OverlayType>() << ")"
185 << " #shapes expected: " << expected_count
186 << " detected: " << boost::size(v)
187 << " type: " << string_from_type
188 <typename bg::coordinate_type<G1>::type>::name()
189 );
190
191 // Check total area of resulting rings
192 typename bg::default_area_result<G1>::type total_area = 0;
193 for (ring_type const& ring : v)
194 {
195 total_area += bg::area(ring);
196 //std::cout << bg::wkt(ring) << std::endl;
197 }
198
199 BOOST_CHECK_CLOSE(expected_area, total_area, precision);
200
201 #if defined(TEST_WITH_SVG)
202 {
203 std::ostringstream filename;
204 filename << "traverse_" << operation<OverlayType>()
205 << "_" << id
206 << "_" << string_from_type<typename bg::coordinate_type<G1>::type>::name()
207 << ".svg";
208
209 std::ofstream svg(filename.str().c_str());
210
211 bg::svg_mapper<typename bg::point_type<G2>::type> mapper(svg, 500, 500);
212 mapper.add(g1);
213 mapper.add(g2);
214
215 // Input shapes in green (src=0) / blue (src=1)
216 mapper.map(g1, "fill-opacity:0.5;fill:rgb(153,204,0);"
217 "stroke:rgb(153,204,0);stroke-width:3");
218 mapper.map(g2, "fill-opacity:0.3;fill:rgb(51,51,153);"
219 "stroke:rgb(51,51,153);stroke-width:3");
220
221 // Traversal rings in magenta outline/red fill -> over blue/green this gives brown
222 for (ring_type const& ring : v)
223 {
224 mapper.map(ring, "fill-opacity:0.2;stroke-opacity:0.4;fill:rgb(255,0,0);"
225 "stroke:rgb(255,0,255);stroke-width:8");
226 }
227
228 // turn points in orange, + enrichment/traversal info
229 typedef typename bg::coordinate_type<G1>::type coordinate_type;
230
231 // Simple map to avoid two texts at same place (note that can still overlap!)
232 std::map<std::pair<int, int>, int> offsets;
233 int index = 0;
234 int const margin = 5;
235
236 for (turn_info const& turn : turns)
237 {
238 int lineheight = 8;
239 mapper.map(turn.point, "fill:rgb(255,128,0);"
240 "stroke:rgb(0,0,0);stroke-width:1", 3);
241
242 {
243 coordinate_type half = 0.5;
244 coordinate_type ten = 10;
245 // Map characteristics
246 // Create a rounded off point
247 std::pair<int, int> p
248 = std::make_pair(
249 boost::numeric_cast<int>(half
250 + ten * bg::get<0>(turn.point)),
251 boost::numeric_cast<int>(half
252 + ten * bg::get<1>(turn.point))
253 );
254 std::string style = "fill:rgb(0,0,0);font-family:Arial;font-size:8px";
255
256 if (turn.colocated)
257 {
258 style = "fill:rgb(255,0,0);font-family:Arial;font-size:8px";
259 }
260 else if (turn.discarded)
261 {
262 style = "fill:rgb(92,92,92);font-family:Arial;font-size:6px";
263 lineheight = 6;
264 }
265
266 //if (! turn.is_discarded() && ! turn.blocked() && ! turn.both(bg::detail::overlay::operation_union))
267 //if (! turn.discarded)
268 {
269 std::ostringstream out;
270 out << index
271 << ": " << bg::method_char(turn.method)
272 << std::endl
273 << "op: " << bg::operation_char(turn.operations[0].operation)
274 << " / " << bg::operation_char(turn.operations[1].operation)
275 //<< (turn.is_discarded() ? " (discarded) " : turn.blocked() ? " (blocked)" : "")
276 << std::endl;
277
278 out << "r: " << turn.operations[0].fraction
279 << " ; " << turn.operations[1].fraction
280 << std::endl;
281 if (turn.operations[0].enriched.next_ip_index != -1)
282 {
283 out << "ip: " << turn.operations[0].enriched.next_ip_index;
284 }
285 else
286 {
287 out << "vx: " << turn.operations[0].enriched.travels_to_vertex_index
288 << " -> ip: " << turn.operations[0].enriched.travels_to_ip_index;
289 }
290 out << " / ";
291 if (turn.operations[1].enriched.next_ip_index != -1)
292 {
293 out << "ip: " << turn.operations[1].enriched.next_ip_index;
294 }
295 else
296 {
297 out << "vx: " << turn.operations[1].enriched.travels_to_vertex_index
298 << " -> ip: " << turn.operations[1].enriched.travels_to_ip_index;
299 }
300
301 out << std::endl;
302
303 /*out
304
305 << std::setprecision(3)
306 << "dist: " << boost::numeric_cast<double>(turn.operations[0].enriched.distance)
307 << " / " << boost::numeric_cast<double>(turn.operations[1].enriched.distance)
308 << std::endl
309 << "vis: " << bg::visited_char(turn.operations[0].visited)
310 << " / " << bg::visited_char(turn.operations[1].visited);
311 */
312
313 /*
314 out << index
315 << ": " << bg::operation_char(turn.operations[0].operation)
316 << " " << bg::operation_char(turn.operations[1].operation)
317 << " (" << bg::method_char(turn.method) << ")"
318 << (turn.ignore() ? " (ignore) " : " ")
319 << std::endl
320
321 << "ip: " << turn.operations[0].enriched.travels_to_ip_index
322 << "/" << turn.operations[1].enriched.travels_to_ip_index;
323
324 if (turn.operations[0].enriched.next_ip_index != -1
325 || turn.operations[1].enriched.next_ip_index != -1)
326 {
327 out << " [" << turn.operations[0].enriched.next_ip_index
328 << "/" << turn.operations[1].enriched.next_ip_index
329 << "]"
330 ;
331 }
332 out << std::endl;
333
334
335 out
336 << "vx:" << turn.operations[0].enriched.travels_to_vertex_index
337 << "/" << turn.operations[1].enriched.travels_to_vertex_index
338 << std::endl
339
340 << std::setprecision(3)
341 << "dist: " << turn.operations[0].fraction
342 << " / " << turn.operations[1].fraction
343 << std::endl;
344 */
345
346
347
348 offsets[p] += lineheight;
349 int offset = offsets[p];
350 offsets[p] += lineheight * 3;
351 mapper.text(turn.point, out.str(), style, margin, offset, lineheight);
352 }
353 index++;
354 }
355 }
356 }
357 #endif
358 }
359 };
360 }
361
362 template
363 <
364 typename G1, typename G2,
365 bg::overlay_type OverlayType,
366 bool Reverse1 = false,
367 bool Reverse2 = false
368 >
369 struct test_traverse
370 {
371 typedef detail::test_traverse
372 <
373 G1, G2, OverlayType, Reverse1, Reverse2
374 > detail_test_traverse;
375
376 inline static void apply(std::string const& id, std::size_t expected_count, double expected_area,
377 std::string const& wkt1, std::string const& wkt2,
378 double precision = 0.001)
379 {
380 if (wkt1.empty() || wkt2.empty())
381 {
382 return;
383 }
384
385 G1 g1;
386 bg::read_wkt(wkt1, g1);
387
388 G2 g2;
389 bg::read_wkt(wkt2, g2);
390
391 bg::correct(g1);
392 bg::correct(g2);
393
394 //std::cout << bg::wkt(g1) << std::endl;
395 //std::cout << bg::wkt(g2) << std::endl;
396
397 // Try the overlay-function in both ways
398 std::string caseid = id;
399 //goto case_reversed;
400
401 #ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
402 std::cout << std::endl << std::endl << "# " << caseid << std::endl;
403 #endif
404 detail_test_traverse::apply(caseid, expected_count, expected_area, g1, g2, precision);
405
406 #ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
407 return;
408 #endif
409
410 //case_reversed:
411 #if ! defined(BOOST_GEOMETRY_TEST_OVERLAY_NOT_EXCHANGED)
412 caseid = id + "_rev";
413 #ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
414 std::cout << std::endl << std::endl << "# " << caseid << std::endl;
415 #endif
416
417 detail_test_traverse::apply(caseid, expected_count, expected_area, g2, g1, precision);
418 #endif
419 }
420 };
421
422 #if ! defined(BOOST_GEOMETRY_TEST_MULTI)
423 template <typename T>
424 void test_all(bool test_self_tangencies = true, bool test_mixed = false)
425 {
426 typedef bg::model::point<T, 2, bg::cs::cartesian> P;
427 typedef bg::model::polygon<P> polygon;
428 //typedef bg::model::box<P> box;
429
430 typedef test_traverse
431 <
432 polygon, polygon, bg::overlay_intersection
433 > test_traverse_intersection;
434 typedef test_traverse
435 <
436 polygon, polygon, bg::overlay_union
437 > test_traverse_union;
438
439 // 1-6
440 test_traverse_intersection::apply("1", 1, 5.4736, case_1[0], case_1[1]);
441 test_traverse_intersection::apply("2", 1, 12.0545, case_2[0], case_2[1]);
442 test_traverse_intersection::apply("3", 1, 5, case_3[0], case_3[1]);
443 test_traverse_intersection::apply("4", 1, 10.2212, case_4[0], case_4[1]);
444 test_traverse_intersection::apply("5", 2, 12.8155, case_5[0], case_5[1]);
445 test_traverse_intersection::apply("6", 1, 4.5, case_6[0], case_6[1]);
446
447 // 7-12
448 test_traverse_intersection::apply("7", 0, 0, case_7[0], case_7[1]);
449 test_traverse_intersection::apply("8", 0, 0, case_8[0], case_8[1]);
450 test_traverse_intersection::apply("9", 0, 0, case_9[0], case_9[1]);
451 test_traverse_intersection::apply("10", 0, 0, case_10[0], case_10[1]);
452 test_traverse_intersection::apply("11", 1, 1, case_11[0], case_11[1]);
453 test_traverse_intersection::apply("12", 2, 0.63333, case_12[0], case_12[1]);
454
455 // 13-18
456 test_traverse_intersection::apply("13", 0, 0, case_13[0], case_13[1]);
457 test_traverse_intersection::apply("14", 0, 0, case_14[0], case_14[1]);
458 test_traverse_intersection::apply("15", 0, 0, case_15[0], case_15[1]);
459 test_traverse_intersection::apply("16", 0, 0, case_16[0], case_16[1]);
460 test_traverse_intersection::apply("17", 1, 2, case_17[0], case_17[1]);
461 test_traverse_intersection::apply("18", 1, 2, case_18[0], case_18[1]);
462
463 // 19-24
464 test_traverse_intersection::apply("19", 0, 0, case_19[0], case_19[1]);
465 test_traverse_intersection::apply("20", 1, 5.5, case_20[0], case_20[1]);
466 test_traverse_intersection::apply("21", 0, 0, case_21[0], case_21[1]);
467 test_traverse_intersection::apply("22", 0, 0, case_22[0], case_22[1]);
468 test_traverse_intersection::apply("23", 1, 1.4, case_23[0], case_23[1]);
469 test_traverse_intersection::apply("24", 1, 1.0, case_24[0], case_24[1]);
470
471 // 25-30
472 test_traverse_intersection::apply("25", 0, 0, case_25[0], case_25[1]);
473 test_traverse_intersection::apply("26", 0, 0, case_26[0], case_26[1]);
474 test_traverse_intersection::apply("27", 1, 0.9545454, case_27[0], case_27[1]);
475 test_traverse_intersection::apply("28", 1, 0.9545454, case_28[0], case_28[1]);
476 test_traverse_intersection::apply("29", 1, 1.4, case_29[0], case_29[1]);
477 test_traverse_intersection::apply("30", 1, 0.5, case_30[0], case_30[1]);
478
479 // 31-36
480 test_traverse_intersection::apply("31", 0, 0, case_31[0], case_31[1]);
481 test_traverse_intersection::apply("32", 0, 0, case_32[0], case_32[1]);
482 test_traverse_intersection::apply("33", 0, 0, case_33[0], case_33[1]);
483 test_traverse_intersection::apply("34", 1, 0.5, case_34[0], case_34[1]);
484 test_traverse_intersection::apply("35", 1, 1.0, case_35[0], case_35[1]);
485 test_traverse_intersection::apply("36", 1, 1.625, case_36[0], case_36[1]);
486
487 // 37-42
488 test_traverse_intersection::apply("37", 2, 0.666666, case_37[0], case_37[1]);
489 test_traverse_intersection::apply("38", 2, 0.971429, case_38[0], case_38[1]);
490 test_traverse_intersection::apply("39", 1, 24, case_39[0], case_39[1]);
491 test_traverse_intersection::apply("40", 0, 0, case_40[0], case_40[1]);
492 test_traverse_intersection::apply("41", 1, 5, case_41[0], case_41[1]);
493 test_traverse_intersection::apply("42", 1, 5, case_42[0], case_42[1]);
494
495 // 43-48 - invalid polygons
496 //test_traverse_intersection::apply("43", 2, 0.75, case_43[0], case_43[1]);
497 //test_traverse_intersection::apply("44", 1, 44, case_44[0], case_44[1]);
498 //test_traverse_intersection::apply("45", 1, 45, case_45[0], case_45[1]);
499 //test_traverse_intersection::apply("46", 1, 46, case_46[0], case_46[1]);
500 //test_traverse_intersection::apply("47", 1, 47, case_47[0], case_47[1]);
501
502 // 49-54
503
504 test_traverse_intersection::apply("50", 0, 0, case_50[0], case_50[1]);
505 test_traverse_intersection::apply("51", 0, 0, case_51[0], case_51[1]);
506 test_traverse_intersection::apply("52", 1, 10.5, case_52[0], case_52[1]);
507 if (test_self_tangencies)
508 {
509 test_traverse_intersection::apply("53_st", 0, 0, case_53[0], case_53[1]);
510 }
511 test_traverse_intersection::apply("53_iet", 0, 0, case_53[0], case_53[2]);
512
513 test_traverse_intersection::apply("54_iet_iet", 1, 2, case_54[1], case_54[3]);
514 if (test_self_tangencies)
515 {
516 test_traverse_intersection::apply("54_st_iet", 1, 2, case_54[0], case_54[3]);
517 test_traverse_intersection::apply("54_iet_st", 1, 2, case_54[1], case_54[2]);
518 test_traverse_intersection::apply("54_st_st", 1, 2, case_54[0], case_54[2]);
519 }
520
521 if (test_self_tangencies)
522 {
523 // 55-60
524 test_traverse_intersection::apply("55_st_st", 1, 2, case_55[0], case_55[2]);
525 }
526
527 test_traverse_intersection::apply("55_st_iet", 1, 2, case_55[0], case_55[3]);
528 test_traverse_intersection::apply("55_iet_st", 1, 2, case_55[1], case_55[2]);
529 if (test_self_tangencies)
530 {
531 test_traverse_intersection::apply("56", 2, 4.5, case_56[0], case_56[1]);
532 }
533 test_traverse_intersection::apply("55_iet_iet", 1, 2, case_55[1], case_55[3]);
534 test_traverse_intersection::apply("57", 2, 5.9705882, case_57[0], case_57[1]);
535
536 if (test_self_tangencies)
537 {
538 test_traverse_intersection::apply("58_st",
539 2, 0.333333, case_58[0], case_58[1]);
540 test_traverse_intersection::apply("59_st",
541 2, 1.5416667, case_59[0], case_59[1]);
542 test_traverse_intersection::apply("60_st",
543 3, 2, case_60[0], case_60[1]);
544 }
545 test_traverse_intersection::apply("58_iet",
546 2, 0.333333, case_58[0], case_58[2]);
547 test_traverse_intersection::apply("59_iet",
548 2, 1.5416667, case_59[0], case_59[2]);
549 test_traverse_intersection::apply("60_iet",
550 3, 2, case_60[0], case_60[2]);
551 test_traverse_intersection::apply("61_st",
552 0, 0, case_61[0], case_61[1]);
553
554 test_traverse_intersection::apply("70",
555 2, 4, case_70[0], case_70[1]);
556 test_traverse_intersection::apply("71",
557 2, 2, case_71[0], case_71[1]);
558 test_traverse_intersection::apply("72",
559 3, 2.85, case_72[0], case_72[1]);
560 test_traverse_intersection::apply("79",
561 2, 20, case_79[0], case_79[1]);
562
563 // Should be 3 shapes
564 test_traverse_intersection::apply("82a",
565 2, 2.0, case_82[0], case_82[1]);
566 // Should be 3 shapes
567 test_traverse_intersection::apply("82b",
568 2, 2.0, case_82[0], case_82[2]);
569 // other
570
571 #ifdef BOOST_GEOMETRY_TEST_FAILURES
572 // simplified version of 82, area should be different
573 // missing IP at (1.5 3.5) from (1 4,1.5 3.5,2 4)x(2 4,1 3)
574 test_traverse_intersection::apply("83",
575 1, 0.0, case_83[0], case_83[1]);
576 #endif
577
578 // pies (went wrong when not all cases where implemented, especially some collinear (opposite) cases
579 test_traverse_intersection::apply("pie_16_4_12",
580 1, 491866.5, pie_16_4_12[0], pie_16_4_12[1]);
581 test_traverse_intersection::apply("pie_23_21_12_500",
582 2, 2363199.3313, pie_23_21_12_500[0], pie_23_21_12_500[1]);
583 test_traverse_intersection::apply("pie_23_23_3_2000",
584 2, 1867779.9349, pie_23_23_3_2000[0], pie_23_23_3_2000[1]);
585 test_traverse_intersection::apply("pie_23_16_16",
586 2, 2128893.9555, pie_23_16_16[0], pie_23_16_16[1]);
587 test_traverse_intersection::apply("pie_16_2_15_0",
588 0, 0, pie_16_2_15_0[0], pie_16_2_15_0[1]);
589 test_traverse_intersection::apply("pie_4_13_15",
590 1, 490887.06678, pie_4_13_15[0], pie_4_13_15[1]);
591 test_traverse_intersection::apply("pie_20_20_7_100",
592 2, 2183372.2718, pie_20_20_7_100[0], pie_20_20_7_100[1]);
593
594
595
596 // 1-6
597 test_traverse_union::apply("1", 1, 11.5264, case_1[0], case_1[1]);
598 test_traverse_union::apply("2", 1, 17.9455, case_2[0], case_2[1]);
599 test_traverse_union::apply("3", 1, 9, case_3[0], case_3[1]);
600 test_traverse_union::apply("4", 3, 17.7788, case_4[0], case_4[1]);
601 test_traverse_union::apply("5", 2, 18.4345, case_5[0], case_5[1]);
602 test_traverse_union::apply("6", 1, 9, case_6[0], case_6[1]);
603
604 // 7-12
605 test_traverse_union::apply("7", 1, 9, case_7[0], case_7[1]);
606 test_traverse_union::apply("8", 1, 12, case_8[0], case_8[1]);
607 test_traverse_union::apply("9", 0, 0 /*UU 2, 11*/, case_9[0], case_9[1]);
608 test_traverse_union::apply("10", 1, 9, case_10[0], case_10[1]);
609 test_traverse_union::apply("11", 1, 8, case_11[0], case_11[1]);
610 test_traverse_union::apply("12", 2, 8.36667, case_12[0], case_12[1]);
611
612 // 13-18
613 test_traverse_union::apply("13", 1, 4, case_13[0], case_13[1]);
614 test_traverse_union::apply("14", 1, 12, case_14[0], case_14[1]);
615 test_traverse_union::apply("15", 1, 12, case_15[0], case_15[1]);
616 test_traverse_union::apply("16", 1, 9, case_16[0], case_16[1]);
617 test_traverse_union::apply("17", 1, 8, case_17[0], case_17[1]);
618 test_traverse_union::apply("18", 1, 8, case_18[0], case_18[1]);
619
620 // 19-24
621 test_traverse_union::apply("19", 1, 10, case_19[0], case_19[1]);
622 test_traverse_union::apply("20", 1, 5.5, case_20[0], case_20[1]);
623 test_traverse_union::apply("21", 0, 0, case_21[0], case_21[1]);
624 test_traverse_union::apply("22", 0, 0 /*UU 2, 9.5*/, case_22[0], case_22[1]);
625 test_traverse_union::apply("23", 1, 6.1, case_23[0], case_23[1]);
626 test_traverse_union::apply("24", 1, 5.5, case_24[0], case_24[1]);
627
628 // 25-30
629 test_traverse_union::apply("25", 0, 0 /*UU 2, 7*/, case_25[0], case_25[1]);
630 test_traverse_union::apply("26", 0, 0 /*UU 2, 7.5 */, case_26[0], case_26[1]);
631 test_traverse_union::apply("27", 1, 8.04545, case_27[0], case_27[1]);
632 test_traverse_union::apply("28", 1, 10.04545, case_28[0], case_28[1]);
633 test_traverse_union::apply("29", 1, 8.1, case_29[0], case_29[1]);
634 test_traverse_union::apply("30", 1, 6.5, case_30[0], case_30[1]);
635
636 // 31-36
637 test_traverse_union::apply("31", 0, 0 /*UU 2, 4.5 */, case_31[0], case_31[1]);
638 test_traverse_union::apply("32", 0, 0 /*UU 2, 4.5 */, case_32[0], case_32[1]);
639 test_traverse_union::apply("33", 0, 0 /*UU 2, 4.5 */, case_33[0], case_33[1]);
640 test_traverse_union::apply("34", 1, 6.0, case_34[0], case_34[1]);
641 test_traverse_union::apply("35", 1, 10.5, case_35[0], case_35[1]);
642 test_traverse_union::apply("36", 1 /*UU 2*/, 14.375, case_36[0], case_36[1]);
643
644 // 37-42
645 test_traverse_union::apply("37", 1, 7.33333, case_37[0], case_37[1]);
646 test_traverse_union::apply("38", 1, 9.52857, case_38[0], case_38[1]);
647 test_traverse_union::apply("39", 1, 40.0, case_39[0], case_39[1]);
648 test_traverse_union::apply("40", 0, 0 /*UU 2, 11 */, case_40[0], case_40[1]);
649 test_traverse_union::apply("41", 1, 5, case_41[0], case_41[1]);
650 test_traverse_union::apply("42", 1, 5, case_42[0], case_42[1]);
651
652 // 43-48
653 //test_traverse_union::apply("43", 3, 8.1875, case_43[0], case_43[1]);
654 //test_traverse_union::apply("44", 1, 44, case_44[0], case_44[1]);
655 //test_traverse_union::apply("45", 1, 45, case_45[0], case_45[1]);
656 //test_traverse_union::apply("46", 1, 46, case_46[0], case_46[1]);
657 //test_traverse_union::apply("47", 1, 47, case_47[0], case_47[1]);
658
659 // 49-54
660
661 test_traverse_union::apply("50", 1, 25, case_50[0], case_50[1]);
662 test_traverse_union::apply("51", 0, 0, case_51[0], case_51[1]);
663 test_traverse_union::apply("52", 1, 15.5, case_52[0], case_52[1]);
664 if (test_self_tangencies)
665 {
666 test_traverse_union::apply("53_st", 2, 16, case_53[0], case_53[1]);
667 }
668 test_traverse_union::apply("53_iet",
669 2, 16, case_53[0], case_53[2]);
670 if (test_self_tangencies)
671 {
672 test_traverse_union::apply("54_st_st", 2, 20, case_54[0], case_54[2]);
673 test_traverse_union::apply("54_st_iet", 2, 20, case_54[0], case_54[3]);
674 test_traverse_union::apply("54_iet_st", 2, 20, case_54[1], case_54[2]);
675 }
676 test_traverse_union::apply("54_iet_iet", 2, 20, case_54[1], case_54[3]);
677
678 if (test_mixed)
679 {
680 test_traverse_union::apply("55_st_iet", 2, 18, case_55[0], case_55[3]);
681 test_traverse_union::apply("55_iet_st", 2, 18, case_55[1], case_55[2]);
682 // moved to mixed
683 test_traverse_union::apply("55_iet_iet", 3, 18, case_55[1], case_55[3]);
684 }
685
686 // 55-60
687 if (test_self_tangencies)
688 {
689 // 55 with both input polygons having self tangencies (st_st) generates 1 correct shape
690 test_traverse_union::apply("55_st_st", 1, 18, case_55[0], case_55[2]);
691 // 55 with one of them self-tangency, other int/ext ring tangency generate 2 correct shapes
692
693 test_traverse_union::apply("56", 2, 14, case_56[0], case_56[1]);
694 }
695 test_traverse_union::apply("57", 1, 14.029412, case_57[0], case_57[1]);
696
697 if (test_self_tangencies)
698 {
699 test_traverse_union::apply("58_st",
700 4, 12.16666, case_58[0], case_58[1]);
701 test_traverse_union::apply("59_st",
702 2, 17.208333, case_59[0], case_59[1]);
703 test_traverse_union::apply("60_st",
704 3, 19, case_60[0], case_60[1]);
705 }
706 test_traverse_union::apply("58_iet",
707 4, 12.16666, case_58[0], case_58[2]);
708 test_traverse_union::apply("59_iet",
709 1, -3.791666, // 2, 17.208333), outer ring (ii/ix) is done by ASSEMBLE
710 case_59[0], case_59[2]);
711 test_traverse_union::apply("60_iet",
712 3, 19, case_60[0], case_60[2]);
713 test_traverse_union::apply("61_st",
714 1, 4, case_61[0], case_61[1]);
715
716 test_traverse_union::apply("70",
717 1, 9, case_70[0], case_70[1]);
718 test_traverse_union::apply("71",
719 2, 9, case_71[0], case_71[1]);
720 test_traverse_union::apply("72",
721 1, 10.65, case_72[0], case_72[1]);
722
723 // other
724 test_traverse_union::apply("box_poly5",
725 2, 4.7191,
726 "POLYGON((1.5 1.5, 1.5 2.5, 4.5 2.5, 4.5 1.5, 1.5 1.5))",
727 "POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 2.5,4.5 2.5,4.5 2.3,5.0 2.3,5.0 2.1,4.5 2.1,4.5 1.9,4.0 1.9,4.5 1.2,4.9 0.8,2.9 0.7,2 1.3))");
728
729 test_traverse_intersection::apply("collinear_overlaps",
730 1, 24,
731 collinear_overlaps[0], collinear_overlaps[1]);
732 test_traverse_union::apply("collinear_overlaps",
733 1, 50,
734 collinear_overlaps[0], collinear_overlaps[1]);
735
736 test_traverse_intersection::apply("many_situations", 1, 184, case_many_situations[0], case_many_situations[1]);
737 test_traverse_union::apply("many_situations",
738 1, 207, case_many_situations[0], case_many_situations[1]);
739
740
741 // From "intersection piets", robustness test.
742 // This all went wrong in the past
743 // (when not all cases (get_turns) where implemented,
744 // especially important are some collinear (opposite) cases)
745 test_traverse_union::apply("pie_16_4_12",
746 1, 3669665.5, pie_16_4_12[0], pie_16_4_12[1]);
747 test_traverse_union::apply("pie_23_21_12_500",
748 1, 6295516.7185, pie_23_21_12_500[0], pie_23_21_12_500[1]);
749 test_traverse_union::apply("pie_23_23_3_2000",
750 1, 7118735.0530, pie_23_23_3_2000[0], pie_23_23_3_2000[1]);
751 test_traverse_union::apply("pie_23_16_16",
752 1, 5710474.5406, pie_23_16_16[0], pie_23_16_16[1]);
753 test_traverse_union::apply("pie_16_2_15_0",
754 1, 3833641.5, pie_16_2_15_0[0], pie_16_2_15_0[1]);
755 test_traverse_union::apply("pie_4_13_15",
756 1, 2208122.43322, pie_4_13_15[0], pie_4_13_15[1]);
757 test_traverse_union::apply("pie_20_20_7_100",
758 1, 5577158.72823, pie_20_20_7_100[0], pie_20_20_7_100[1]);
759
760 /*
761 if (test_not_valid)
762 {
763 test_traverse_union::apply("pie_5_12_12_0_7s",
764 1, 3271710.48516, pie_5_12_12_0_7s[0], pie_5_12_12_0_7s[1]);
765 }
766 */
767
768 static const bool is_float = std::is_same<T, float>::value;
769
770 static const double float_might_deviate_more = is_float ? 0.1 : 0.001; // In some cases up to 1 promille permitted
771
772 // GCC: does not everywhere handle float correctly (in our algorithms)
773 static bool const is_float_on_non_msvc =
774 #if defined(_MSC_VER)
775 false;
776 #else
777 is_float;
778 #endif
779
780
781
782 // From "Random Ellipse Stars", robustness test.
783 // This all went wrong in the past
784 // when using Determinant/ra/rb and comparing with 0/1
785 // Solved now by avoiding determinant / using sides
786 // ("hv" means "high volume")
787 {
788 double deviation = is_float ? 0.01 : 0.001;
789 test_traverse_union::apply("hv1", 1, 1624.508688461573, hv_1[0], hv_1[1], deviation);
790 test_traverse_intersection::apply("hv1", 1, 1622.7200125123809, hv_1[0], hv_1[1], deviation);
791
792 test_traverse_union::apply("hv2", 1, 1622.9193392726836, hv_2[0], hv_2[1], deviation);
793 test_traverse_intersection::apply("hv2", 1, 1622.1733591429329, hv_2[0], hv_2[1], deviation);
794
795 test_traverse_union::apply("hv3", 1, 1624.22079205664, hv_3[0], hv_3[1], deviation);
796 test_traverse_intersection::apply("hv3", 1, 1623.8265057282042, hv_3[0], hv_3[1], deviation);
797
798
799 if ( BOOST_GEOMETRY_CONDITION(! is_float) )
800 {
801 test_traverse_union::apply("hv4", 1, 1626.5146964146334, hv_4[0], hv_4[1], deviation);
802 test_traverse_intersection::apply("hv4", 1, 1626.2580370864305, hv_4[0], hv_4[1], deviation);
803 test_traverse_union::apply("hv5", 1, 1624.2158307261871, hv_5[0], hv_5[1], deviation);
804 test_traverse_intersection::apply("hv5", 1, 1623.4506071521519, hv_5[0], hv_5[1], deviation);
805
806 // Case 2009-12-07
807 test_traverse_intersection::apply("hv6", 1, 1604.6318757402121, hv_6[0], hv_6[1], deviation);
808 test_traverse_union::apply("hv6", 1, 1790.091872401327, hv_6[0], hv_6[1], deviation);
809
810 // Case 2009-12-08, needing sorting on side in enrich_intersection_points
811 test_traverse_union::apply("hv7", 1, 1624.5779453641017, hv_7[0], hv_7[1], deviation);
812 test_traverse_intersection::apply("hv7", 1, 1623.6936420295772, hv_7[0], hv_7[1], deviation);
813 }
814 }
815
816 // From "Random Ellipse Stars", robustness test.
817 // This all went wrong in the past when distances (see below) were zero (dz)
818 // "Distance zero", dz, means: the distance between two intersection points
819 // on a same segment is 0, therefore it can't be sorted normally, therefore
820 // the chance is 50% that the segments are not sorted correctly and the wrong
821 // decision is taken.
822 // Solved now (by sorting on sides in those cases)
823 if ( BOOST_GEOMETRY_CONDITION(! is_float_on_non_msvc) )
824 {
825 test_traverse_intersection::apply("dz_1",
826 2, 16.887537949472005, dz_1[0], dz_1[1]);
827 test_traverse_union::apply("dz_1",
828 3, 1444.2621305732864, dz_1[0], dz_1[1]);
829
830 test_traverse_intersection::apply("dz_2",
831 2, 68.678921274288541, dz_2[0], dz_2[1]);
832 test_traverse_union::apply("dz_2",
833 1, 1505.4202304878663, dz_2[0], dz_2[1]);
834
835 test_traverse_intersection::apply("dz_3",
836 5, 192.49316937645651, dz_3[0], dz_3[1]);
837 test_traverse_union::apply("dz_3",
838 5, 1446.496005965641, dz_3[0], dz_3[1]);
839
840 test_traverse_intersection::apply("dz_4",
841 1, 473.59423868207693, dz_4[0], dz_4[1]);
842 test_traverse_union::apply("dz_4",
843 1, 1871.6125138873476, dz_4[0], dz_4[1]);
844 }
845
846 // Real-life problems
847
848 // SNL (Subsidiestelsel Natuur & Landschap - verAANnen)
849
850 test_traverse_intersection::apply("snl-1",
851 2, 286.996062095888,
852 snl_1[0], snl_1[1],
853 float_might_deviate_more);
854
855 test_traverse_union::apply("snl-1",
856 2, 51997.5408506132,
857 snl_1[0], snl_1[1],
858 float_might_deviate_more);
859
860 {
861 test_traverse_intersection::apply("isov",
862 1, 88.1920, isovist[0], isovist[1],
863 float_might_deviate_more);
864 test_traverse_union::apply("isov",
865 1, 313.3604, isovist[0], isovist[1],
866 float_might_deviate_more);
867 }
868
869 if ( BOOST_GEOMETRY_CONDITION(! is_float) )
870 {
871
872 /* TODO check this BSG 2013-09-24
873 #if defined(_MSC_VER)
874 double const expected = if_typed_tt<T>(3.63794e-17, 0.0);
875 int expected_count = if_typed_tt<T>(1, 0);
876 #else
877 double const expected = if_typed<T, long double>(2.77555756156289135106e-17, 0.0);
878 int expected_count = if_typed<T, long double>(1, 0);
879 #endif
880
881 // Calculate intersection/union of two triangles. Robustness case.
882 // some precise types can form a very small intersection triangle
883 // (which is even not accomplished by SQL Server/PostGIS)
884 std::string const caseid = "ggl_list_20110820_christophe";
885 test_traverse_intersection::apply(caseid,
886 expected_count, expected,
887 ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1]);
888 test_traverse_union::apply(caseid,
889 1, 67.3550722317627,
890 ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1]);
891 */
892 }
893
894 test_traverse_union::apply("buffer_rt_f",
895 1, 4.60853,
896 buffer_rt_f[0], buffer_rt_f[1]);
897 test_traverse_intersection::apply("buffer_rt_f",
898 1, 0.0002943725152286,
899 buffer_rt_f[0], buffer_rt_f[1], 0.01);
900
901 test_traverse_union::apply("buffer_rt_g",
902 1, 16.571,
903 buffer_rt_g[0], buffer_rt_g[1]);
904
905 test_traverse_union::apply("buffer_rt_g_boxes1",
906 1, 20,
907 buffer_rt_g_boxes[0], buffer_rt_g_boxes[1]);
908 test_traverse_union::apply("buffer_rt_g_boxes2",
909 1, 24,
910 buffer_rt_g_boxes[0], buffer_rt_g_boxes[2]);
911 test_traverse_union::apply("buffer_rt_g_boxes3",
912 1, 28,
913 buffer_rt_g_boxes[0], buffer_rt_g_boxes[3]);
914
915 test_traverse_union::apply("buffer_rt_g_boxes43",
916 1, 30,
917 buffer_rt_g_boxes[4], buffer_rt_g_boxes[3]);
918
919 test_traverse_union::apply("buffer_rt_l",
920 1, 19.3995, buffer_rt_l[0], buffer_rt_l[1]);
921
922 test_traverse_union::apply("buffer_mp2",
923 1, 36.7535642, buffer_mp2[0], buffer_mp2[1], 0.01);
924 test_traverse_union::apply("collinear_opposite_rr",
925 1, 6.41, collinear_opposite_right[0], collinear_opposite_right[1]);
926 test_traverse_union::apply("collinear_opposite_ll",
927 1, 11.75, collinear_opposite_left[0], collinear_opposite_left[1]);
928 test_traverse_union::apply("collinear_opposite_ss",
929 1, 6, collinear_opposite_straight[0], collinear_opposite_straight[1]);
930 test_traverse_union::apply("collinear_opposite_lr",
931 1, 8.66, collinear_opposite_left[0], collinear_opposite_right[1]);
932 test_traverse_union::apply("collinear_opposite_rl",
933 1, 9, collinear_opposite_right[0], collinear_opposite_left[1]);
934
935 test_traverse_intersection::apply("ticket_7462", 1, 0.220582, ticket_7462[0], ticket_7462[1]);
936
937 test_traverse_intersection::apply
938 ("ticket_9081_15", 1, 0.006889578,
939 ticket_9081_15[0], ticket_9081_15[1]);
940
941 #ifdef BOOST_GEOMETRY_OVERLAY_NO_THROW
942 {
943 // NOTE: currently throws (normally)
944 std::string caseid = "ggl_list_20120229_volker";
945 test_traverse_union::apply(caseid,
946 1, 99,
947 ggl_list_20120229_volker[0], ggl_list_20120229_volker[1]);
948 test_traverse_intersection::apply(caseid,
949 1, 99,
950 ggl_list_20120229_volker[0], ggl_list_20120229_volker[1]);
951 caseid = "ggl_list_20120229_volker_2";
952 test_traverse_union::apply(caseid,
953 1, 99,
954 ggl_list_20120229_volker[2], ggl_list_20120229_volker[1]);
955 test_traverse_intersection::apply(caseid,
956 1, 99,
957 ggl_list_20120229_volker[2], ggl_list_20120229_volker[1]);
958 }
959 #endif
960 }
961
962 #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
963 template <typename T>
964 void test_open()
965 {
966 typedef bg::model::polygon
967 <
968 bg::model::point<T, 2, bg::cs::cartesian>,
969 true, false
970 > polygon;
971
972 typedef test_traverse
973 <
974 polygon, polygon, bg::overlay_intersection
975 > test_traverse_intersection;
976 typedef test_traverse
977 <
978 polygon, polygon, bg::overlay_union
979 > test_traverse_union;
980
981 test_traverse_intersection::apply("open_1", 1, 5.4736,
982 open_case_1[0], open_case_1[1]);
983 test_traverse_union::apply("open_1", 1, 11.5264,
984 open_case_1[0], open_case_1[1]);
985 }
986
987
988 template <typename T>
989 void test_ccw()
990 {
991 typedef bg::model::polygon
992 <
993 bg::model::point<T, 2, bg::cs::cartesian>,
994 false, true
995 > polygon;
996
997 test_traverse<polygon, polygon, bg::overlay_intersection, true, true>::apply("ccw_1", 1, 5.4736,
998 ccw_case_1[0], ccw_case_1[1]);
999 test_traverse<polygon, polygon, bg::overlay_union, true, true>::apply("ccw_1", 1, 11.5264,
1000 ccw_case_1[0], ccw_case_1[1]);
1001 }
1002 #endif
1003
1004
1005 int test_main(int, char* [])
1006 {
1007 #if defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
1008 test_all<double>();
1009 #else
1010 test_all<float>();
1011 test_all<double>();
1012 test_open<double>();
1013 test_ccw<double>();
1014
1015 #if ! defined(_MSC_VER)
1016 test_all<long double>();
1017 #endif
1018
1019 #endif
1020
1021 return 0;
1022 }
1023
1024 #endif