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