summaryrefslogtreecommitdiff
path: root/libs/geometry/test/algorithms/set_operations
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2015-04-08 03:09:47 +0000
committer <>2015-05-05 14:37:32 +0000
commitf2541bb90af059680aa7036f315f052175999355 (patch)
treea5b214744b256f07e1dc2bd7273035a7808c659f /libs/geometry/test/algorithms/set_operations
parented232fdd34968697a68783b3195b1da4226915b5 (diff)
downloadboost-tarball-master.tar.gz
Imported from /home/lorry/working-area/delta_boost-tarball/boost_1_58_0.tar.bz2.HEADboost_1_58_0master
Diffstat (limited to 'libs/geometry/test/algorithms/set_operations')
-rw-r--r--libs/geometry/test/algorithms/set_operations/Jamfile.v220
-rw-r--r--libs/geometry/test/algorithms/set_operations/difference/Jamfile.v224
-rw-r--r--libs/geometry/test/algorithms/set_operations/difference/difference.cpp695
-rw-r--r--libs/geometry/test/algorithms/set_operations/difference/difference_linear_linear.cpp1480
-rw-r--r--libs/geometry/test/algorithms/set_operations/difference/difference_pl_pl.cpp226
-rw-r--r--libs/geometry/test/algorithms/set_operations/difference/multi_difference.cpp229
-rw-r--r--libs/geometry/test/algorithms/set_operations/difference/multi_difference_spike.cpp105
-rw-r--r--libs/geometry/test/algorithms/set_operations/difference/test_difference.hpp330
-rw-r--r--libs/geometry/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp154
-rw-r--r--libs/geometry/test/algorithms/set_operations/intersection/Jamfile.v223
-rw-r--r--libs/geometry/test/algorithms/set_operations/intersection/intersection.cpp693
-rw-r--r--libs/geometry/test/algorithms/set_operations/intersection/intersection_linear_linear.cpp1617
-rw-r--r--libs/geometry/test/algorithms/set_operations/intersection/intersection_pl_pl.cpp185
-rw-r--r--libs/geometry/test/algorithms/set_operations/intersection/intersection_segment.cpp134
-rw-r--r--libs/geometry/test/algorithms/set_operations/intersection/multi_intersection.cpp240
-rw-r--r--libs/geometry/test/algorithms/set_operations/intersection/test_intersection.hpp285
-rw-r--r--libs/geometry/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp229
-rw-r--r--libs/geometry/test/algorithms/set_operations/set_ops_ll.cpp17
-rw-r--r--libs/geometry/test/algorithms/set_operations/set_ops_pp.cpp16
-rw-r--r--libs/geometry/test/algorithms/set_operations/sym_difference/Jamfile.v220
-rw-r--r--libs/geometry/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp988
-rw-r--r--libs/geometry/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp174
-rw-r--r--libs/geometry/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp171
-rw-r--r--libs/geometry/test/algorithms/set_operations/test_set_ops_linear_linear.hpp374
-rw-r--r--libs/geometry/test/algorithms/set_operations/test_set_ops_pl_pl.hpp257
-rw-r--r--libs/geometry/test/algorithms/set_operations/union/Jamfile.v223
-rw-r--r--libs/geometry/test/algorithms/set_operations/union/multi_union.cpp168
-rw-r--r--libs/geometry/test/algorithms/set_operations/union/test_union.hpp198
-rw-r--r--libs/geometry/test/algorithms/set_operations/union/test_union_linear_linear.hpp185
-rw-r--r--libs/geometry/test/algorithms/set_operations/union/union.cpp446
-rw-r--r--libs/geometry/test/algorithms/set_operations/union/union_linear_linear.cpp1075
-rw-r--r--libs/geometry/test/algorithms/set_operations/union/union_pl_pl.cpp187
32 files changed, 10968 insertions, 0 deletions
diff --git a/libs/geometry/test/algorithms/set_operations/Jamfile.v2 b/libs/geometry/test/algorithms/set_operations/Jamfile.v2
new file mode 100644
index 000000000..27ebad64b
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/Jamfile.v2
@@ -0,0 +1,20 @@
+# Boost.Geometry (aka GGL, Generic Geometry Library)
+#
+# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+# Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+# Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+#
+# This file was modified by Oracle on 2014.
+# Modifications copyright (c) 2014, Oracle and/or its affiliates.
+#
+# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+#
+# Use, modification and distribution is subject to the Boost Software License,
+# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+build-project difference ;
+build-project intersection ;
+build-project sym_difference ;
+build-project union ;
diff --git a/libs/geometry/test/algorithms/set_operations/difference/Jamfile.v2 b/libs/geometry/test/algorithms/set_operations/difference/Jamfile.v2
new file mode 100644
index 000000000..8bbbbbdc6
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/difference/Jamfile.v2
@@ -0,0 +1,24 @@
+# Boost.Geometry (aka GGL, Generic Geometry Library)
+#
+# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+# Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+# Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+#
+# This file was modified by Oracle on 2014.
+# Modifications copyright (c) 2014, Oracle and/or its affiliates.
+#
+# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+#
+# Use, modification and distribution is subject to the Boost Software License,
+# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+test-suite boost-geometry-algorithms-difference
+ :
+ [ run difference.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE ]
+ [ run difference_linear_linear.cpp ]
+ [ run difference_pl_pl.cpp ]
+ [ run multi_difference.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE ]
+ [ run multi_difference_spike.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE ]
+ ;
diff --git a/libs/geometry/test/algorithms/set_operations/difference/difference.cpp b/libs/geometry/test/algorithms/set_operations/difference/difference.cpp
new file mode 100644
index 000000000..c6456a009
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/difference/difference.cpp
@@ -0,0 +1,695 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Unit Test
+
+// Copyright (c) 2010-2015 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2015.
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+// If defined, tests are run without rescaling-to-integer or robustness policy
+// Test which would fail then are disabled automatically
+// #define BOOST_GEOMETRY_NO_ROBUSTNESS
+
+#include <boost/geometry/algorithms/correct.hpp>
+#include <boost/geometry/algorithms/is_valid.hpp>
+#include <boost/geometry/algorithms/perimeter.hpp>
+
+#include <boost/geometry/multi/algorithms/correct.hpp>
+#include <boost/geometry/multi/algorithms/intersection.hpp>
+#include <boost/geometry/multi/algorithms/within.hpp>
+#include <boost/geometry/multi/io/wkt/wkt.hpp>
+
+#include <boost/geometry/geometries/point_xy.hpp>
+
+#include "test_difference.hpp"
+#include <algorithms/test_overlay.hpp>
+#include <algorithms/overlay/overlay_cases.hpp>
+#include <algorithms/overlay/multi_overlay_cases.hpp>
+#include <boost/geometry/multi/io/wkt/wkt.hpp>
+
+
+#ifdef HAVE_TTMATH
+# include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
+#endif
+
+
+
+template <typename Polygon, typename LineString>
+void test_areal_linear()
+{
+ std::string const poly_simplex = "POLYGON((1 1,1 3,3 3,3 1,1 1))";
+ test_one_lp<LineString, LineString, Polygon>("simplex", "LINESTRING(0 2,4 2)", poly_simplex, 2, 4, 2.0);
+ test_one_lp<LineString, LineString, Polygon>("case2", "LINESTRING(0 1,4 3)", poly_simplex, 2, 4, sqrt(5.0));
+ test_one_lp<LineString, LineString, Polygon>("case3", "LINESTRING(0 1,1 2,3 2,4 3,6 3,7 4)", "POLYGON((2 0,2 5,5 5,5 0,2 0))", 2, 6, 2.0 + 2.0 * sqrt(2.0));
+ test_one_lp<LineString, LineString, Polygon>("case4", "LINESTRING(1 1,3 2,1 3)", "POLYGON((0 0,0 4,2 4,2 0,0 0))", 1, 3, sqrt(5.0));
+
+ test_one_lp<LineString, LineString, Polygon>("case5", "LINESTRING(0 1,3 4)", poly_simplex, 2, 4, 2.0 * sqrt(2.0));
+ test_one_lp<LineString, LineString, Polygon>("case6", "LINESTRING(1 1,10 3)", "POLYGON((2 0,2 4,3 4,3 1,4 1,4 3,5 3,5 1,6 1,6 3,7 3,7 1,8 1,8 3,9 3,9 0,2 0))", 5, 10,
+ // Pieces are 1 x 2/9:
+ 5.0 * sqrt(1.0 + 4.0/81.0));
+
+
+ test_one_lp<LineString, LineString, Polygon>("case7", "LINESTRING(1.5 1.5,2.5 2.5)", poly_simplex, 0, 0, 0.0);
+ test_one_lp<LineString, LineString, Polygon>("case8", "LINESTRING(1 0,2 0)", poly_simplex, 1, 2, 1.0);
+
+ std::string const poly_9 = "POLYGON((1 1,1 4,4 4,4 1,1 1))";
+ test_one_lp<LineString, LineString, Polygon>("case9", "LINESTRING(0 1,1 2,2 2)", poly_9, 1, 2, sqrt(2.0));
+ test_one_lp<LineString, LineString, Polygon>("case10", "LINESTRING(0 1,1 2,0 2)", poly_9, 1, 3, 1.0 + sqrt(2.0));
+ test_one_lp<LineString, LineString, Polygon>("case11", "LINESTRING(2 2,4 2,3 3)", poly_9, 0, 0, 0.0);
+ test_one_lp<LineString, LineString, Polygon>("case12", "LINESTRING(2 3,4 4,5 6)", poly_9, 1, 2, sqrt(5.0));
+
+ test_one_lp<LineString, LineString, Polygon>("case13", "LINESTRING(3 2,4 4,2 3)", poly_9, 0, 0, 0.0);
+ test_one_lp<LineString, LineString, Polygon>("case14", "LINESTRING(5 6,4 4,6 5)", poly_9, 1, 3, 2.0 * sqrt(5.0));
+
+ test_one_lp<LineString, LineString, Polygon>("case15", "LINESTRING(0 2,1 2,1 3,0 3)", poly_9, 2, 4, 2.0);
+ test_one_lp<LineString, LineString, Polygon>("case16", "LINESTRING(2 2,1 2,1 3,2 3)", poly_9, 0, 0, 0.0);
+
+ std::string const angly = "LINESTRING(2 2,2 1,4 1,4 2,5 2,5 3,4 3,4 4,5 4,3 6,3 5,2 5,2 6,0 4)";
+ test_one_lp<LineString, LineString, Polygon>("case17", angly, "POLYGON((1 1,1 5,4 5,4 1,1 1))", 3, 11, 6.0 + 4.0 * sqrt(2.0));
+ test_one_lp<LineString, LineString, Polygon>("case18", angly, "POLYGON((1 1,1 5,5 5,5 1,1 1))", 2, 6, 2.0 + 3.0 * sqrt(2.0));
+ test_one_lp<LineString, LineString, Polygon>("case19", "LINESTRING(1 2,1 3,0 3)", poly_9, 1, 2, 1.0);
+ test_one_lp<LineString, LineString, Polygon>("case20", "LINESTRING(1 2,1 3,2 3)", poly_9, 0, 0, 0.0);
+
+ // PROPERTIES CHANGED BY switch_to_integer
+ // TODO test_one_lp<LineString, LineString, Polygon>("case21", "LINESTRING(1 2,1 4,4 4,4 1,2 1,2 2)", poly_9, 0, 0, 0.0);
+
+ // More collinear (opposite) cases
+ test_one_lp<LineString, LineString, Polygon>("case22", "LINESTRING(4 1,4 4,7 4)", poly_9, 1, 2, 3.0);
+ test_one_lp<LineString, LineString, Polygon>("case23", "LINESTRING(4 0,4 4,7 4)", poly_9, 2, 4, 4.0);
+ test_one_lp<LineString, LineString, Polygon>("case24", "LINESTRING(4 1,4 5,7 5)", poly_9, 1, 3, 4.0);
+ test_one_lp<LineString, LineString, Polygon>("case25", "LINESTRING(4 0,4 5,7 5)", poly_9, 2, 5, 5.0);
+ test_one_lp<LineString, LineString, Polygon>("case26", "LINESTRING(4 0,4 3,4 5,7 5)", poly_9, 2, 5, 5.0);
+ test_one_lp<LineString, LineString, Polygon>("case27", "LINESTRING(4 4,4 5,5 5)", poly_9, 1, 3, 2.0);
+}
+
+template <typename CoordinateType>
+void test_ticket_10658(std::string const& wkt_out)
+{
+ typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type;
+ typedef bg::model::polygon
+ <
+ point_type, /*ClockWise*/false, /*Closed*/false
+ > polygon_type;
+ typedef bg::model::multi_polygon<polygon_type> multipolygon_type;
+
+ polygon_type polygon1;
+ bg::read_wkt(ticket_10658[0], polygon1);
+ polygon_type polygon2;
+ bg::read_wkt(ticket_10658[1], polygon2);
+
+ multipolygon_type multipolygon_out;
+ bg::sym_difference(polygon1, polygon2, multipolygon_out);
+ std::stringstream stream;
+ stream << bg::wkt(multipolygon_out);
+
+ BOOST_CHECK_EQUAL(stream.str(), wkt_out);
+}
+
+template <typename CoordinateType>
+void test_ticket_10835(std::string const& wkt_out1, std::string const& wkt_out2)
+{
+ typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type;
+ typedef bg::model::linestring<point_type> linestring_type;
+ typedef bg::model::multi_linestring<linestring_type> multilinestring_type;
+ typedef bg::model::polygon
+ <
+ point_type, /*ClockWise*/false, /*Closed*/false
+ > polygon_type;
+
+ multilinestring_type multilinestring;
+ bg::read_wkt(ticket_10835[0], multilinestring);
+ polygon_type polygon1;
+ bg::read_wkt(ticket_10835[1], polygon1);
+ polygon_type polygon2;
+ bg::read_wkt(ticket_10835[2], polygon2);
+
+ multilinestring_type multilinestringOut1;
+ bg::difference(multilinestring, polygon1, multilinestringOut1);
+ std::stringstream stream;
+ stream << bg::wkt(multilinestringOut1);
+
+ BOOST_CHECK_EQUAL(stream.str(), wkt_out1);
+
+ multilinestring_type multilinestringOut2;
+ bg::difference(multilinestringOut1, polygon2, multilinestringOut2);
+ stream.str("");
+ stream.clear();
+ stream << bg::wkt(multilinestringOut2);
+
+ BOOST_CHECK_EQUAL(stream.str(), wkt_out2);
+}
+
+template <typename CoordinateType>
+void test_ticket_11121()
+{
+ typedef bg::model::point<CoordinateType,2,bg::cs::cartesian> point_type;
+ typedef bg::model::polygon
+ <
+ point_type, /*ClockWise*/false, /*Closed*/false
+ > polygon_type;
+ typedef bg::model::multi_polygon<polygon_type> multipolygon_type;
+
+ polygon_type polygon1;
+ bg::read_wkt(ticket_11121[0], polygon1);
+ polygon_type polygon2;
+ bg::read_wkt(ticket_11121[1], polygon2);
+
+ multipolygon_type diff12, diff21, sym_diff;
+ bg::difference(polygon1, polygon2, diff12);
+ bg::difference(polygon2, polygon1, diff21);
+ bg::sym_difference(polygon1, polygon2, sym_diff);
+
+ BOOST_CHECK(bg::is_valid(diff12));
+ BOOST_CHECK(bg::is_valid(diff21));
+ BOOST_CHECK(bg::is_valid(sym_diff));
+}
+
+template <typename P>
+void test_all()
+{
+ typedef bg::model::box<P> box;
+ typedef bg::model::polygon<P> polygon;
+ typedef bg::model::linestring<P> linestring;
+ typedef bg::model::ring<P> ring;
+
+ typedef typename bg::coordinate_type<P>::type ct;
+
+ test_areal_linear<polygon, linestring>();
+
+ test_one<polygon, polygon, polygon>("simplex_normal",
+ simplex_normal[0], simplex_normal[1],
+ 3, 12, 2.52636706856656,
+ 3, 12, 3.52636706856656);
+
+ test_one<polygon, polygon, polygon>("simplex_with_empty",
+ simplex_normal[0], polygon_empty,
+ 1, 4, 8.0,
+ 0, 0, 0.0);
+
+ test_one<polygon, polygon, polygon>(
+ "star_ring", example_star, example_ring,
+ 5, 22, 1.1901714,
+ 5, 27, 1.6701714);
+
+ test_one<polygon, polygon, polygon>("two_bends",
+ two_bends[0], two_bends[1],
+ 1, 5, 8.0,
+ 1, 5, 8.0);
+
+ test_one<polygon, polygon, polygon>("star_comb_15",
+ star_comb_15[0], star_comb_15[1],
+ 30, 160, 227.658275102812,
+ 30, 198, 480.485775259312);
+
+ test_one<polygon, polygon, polygon>("new_hole",
+ new_hole[0], new_hole[1],
+ 1, 9, 7.0,
+ 1, 13, 14.0);
+
+
+ test_one<polygon, polygon, polygon>("crossed",
+ crossed[0], crossed[1],
+ 1, 18, 19.5,
+ 1, 7, 2.5);
+
+ test_one<polygon, polygon, polygon>("disjoint",
+ disjoint[0], disjoint[1],
+ 1, 5, 1.0,
+ 1, 5, 1.0);
+
+ // The too small one might be discarded (depending on point-type / compiler)
+ // We check area only
+ test_one<polygon, polygon, polygon>("distance_zero",
+ distance_zero[0], distance_zero[1],
+ -1, -1, 8.7048386,
+ -1, -1, 0.0098387,
+ 0.001);
+
+ test_one<polygon, polygon, polygon>("equal_holes_disjoint",
+ equal_holes_disjoint[0], equal_holes_disjoint[1],
+ 1, 5, 9.0,
+ 1, 5, 9.0);
+
+ test_one<polygon, polygon, polygon>("only_hole_intersections1",
+ only_hole_intersections[0], only_hole_intersections[1],
+ 2, 10, 1.9090909,
+ 4, 16, 10.9090909);
+
+ test_one<polygon, polygon, polygon>("only_hole_intersection2",
+ only_hole_intersections[0], only_hole_intersections[2],
+ 3, 20, 30.9090909,
+ 4, 16, 10.9090909);
+
+ test_one<polygon, polygon, polygon>("first_within_second",
+ first_within_second[1], first_within_second[0],
+ 1, 10, 24,
+ 0, 0, 0);
+
+ test_one<polygon, polygon, polygon>("fitting",
+ fitting[0], fitting[1],
+ 1, 9, 21.0,
+ 1, 4, 4.0);
+
+ test_one<polygon, polygon, polygon>("identical",
+ identical[0], identical[1],
+ 0, 0, 0.0,
+ 0, 0, 0.0);
+
+ test_one<polygon, polygon, polygon>("intersect_exterior_and_interiors_winded",
+ intersect_exterior_and_interiors_winded[0], intersect_exterior_and_interiors_winded[1],
+ 4, 20, 11.533333,
+ 5, 26, 29.783333);
+
+ test_one<polygon, polygon, polygon>("intersect_holes_intersect_and_disjoint",
+ intersect_holes_intersect_and_disjoint[0], intersect_holes_intersect_and_disjoint[1],
+ 2, 16, 15.75,
+ 3, 17, 6.75);
+
+ test_one<polygon, polygon, polygon>("intersect_holes_intersect_and_touch",
+ intersect_holes_intersect_and_touch[0], intersect_holes_intersect_and_touch[1],
+ 3, 21, 16.25,
+ 3, 17, 6.25);
+
+ test_one<polygon, polygon, polygon>("intersect_holes_new_ring",
+ intersect_holes_new_ring[0], intersect_holes_new_ring[1],
+ 3, 15, 9.8961,
+ 4, 25, 121.8961, 0.01);
+
+ test_one<polygon, polygon, polygon>("first_within_hole_of_second",
+ first_within_hole_of_second[0], first_within_hole_of_second[1],
+ 1, 5, 1,
+ 1, 10, 16);
+
+ test_one<polygon, polygon, polygon>("intersect_holes_disjoint",
+ intersect_holes_disjoint[0], intersect_holes_disjoint[1],
+ 2, 14, 16.0,
+ 2, 10, 6.0);
+
+ test_one<polygon, polygon, polygon>("intersect_holes_intersect",
+ intersect_holes_intersect[0], intersect_holes_intersect[1],
+ 2, 16, 15.75,
+ 2, 12, 5.75);
+
+ test_one<polygon, polygon, polygon>(
+ "case4", case_4[0], case_4[1],
+ 6, 28, 2.77878787878788,
+ 4, 22, 4.77878787878788);
+
+ test_one<polygon, polygon, polygon>(
+ "case5", case_5[0], case_5[1],
+ 8, 36, 2.43452380952381,
+ 7, 33, 3.18452380952381);
+
+ test_one<polygon, polygon, polygon>("winded",
+ winded[0], winded[1],
+ 3, 37, 61,
+ 1, 15, 13);
+
+ test_one<polygon, polygon, polygon>("within_holes_disjoint",
+ within_holes_disjoint[0], within_holes_disjoint[1],
+ 2, 15, 25,
+ 1, 5, 1);
+
+ test_one<polygon, polygon, polygon>("side_side",
+ side_side[0], side_side[1],
+ 1, 5, 1,
+ 1, 5, 1);
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<polygon, polygon, polygon>("buffer_mp1",
+ buffer_mp1[0], buffer_mp1[1],
+ 1, 61, 10.2717,
+ 1, 61, 10.2717);
+#endif
+
+ if ( BOOST_GEOMETRY_CONDITION((boost::is_same<ct, double>::value)) )
+ {
+ test_one<polygon, polygon, polygon>("buffer_mp2",
+ buffer_mp2[0], buffer_mp2[1],
+ 1, 91, 12.09857,
+ 1, 155, 24.19714);
+ }
+
+ /*** TODO: self-tangencies for difference
+ test_one<polygon, polygon, polygon>("wrapped_a",
+ wrapped[0], wrapped[1],
+ 3, 1, 61,
+ 1, 0, 13);
+
+ test_one<polygon, polygon, polygon>("wrapped_b",
+ wrapped[0], wrapped[2],
+ 3, 1, 61,
+ 1, 0, 13);
+ ***/
+
+ // Isovist - the # output polygons differ per compiler/pointtype, (very) small
+ // rings might be discarded. We check area only
+ test_one<polygon, polygon, polygon>("isovist",
+ isovist1[0], isovist1[1],
+ -1, -1, 0.279121,
+ -1, -1, 224.8892,
+ 0.001);
+ // SQL Server gives: 0.279121891701124 and 224.889211358929
+ // PostGIS gives: 0.279121991127244 and 224.889205853156
+
+#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS
+ test_one<polygon, polygon, polygon>("geos_1",
+ geos_1[0], geos_1[1],
+ 21, -1, 0.31640625,
+ 9, -1, 0.01953125);
+
+ // Excluded this test in the normal suite, it is OK like this for many clang/gcc/msvc
+ // versions, but NOT OK for many other clang/gcc/msvc versions on other platforms
+ // It might depend on partition (order)
+ // 10, -1, 0.02148439); // change in partition might give these results
+
+ // SQL Server gives: 0.28937764436705 and 0.000786406897532288 with 44/35 rings
+ // PostGIS gives: 0.30859375 and 0.033203125 with 35/35 rings
+#endif
+
+ test_one<polygon, polygon, polygon>("geos_2",
+ geos_2[0], geos_2[1],
+ 1, -1, 138.6923828,
+ 1, -1, 211.859375,
+ 0.01); // MSVC 14 expects 138.69214 and 211.85913
+
+ test_one<polygon, polygon, polygon>("geos_3",
+ geos_3[0], geos_3[1],
+ 1, -1, 16211128.5,
+ 1, -1, 13180420.0);
+
+ test_one<polygon, polygon, polygon>("geos_4",
+ geos_4[0], geos_4[1],
+ 1, -1, 971.9163115,
+ 1, -1, 1332.4163115);
+
+ test_one<polygon, polygon, polygon>("ggl_list_20110306_javier",
+ ggl_list_20110306_javier[0], ggl_list_20110306_javier[1],
+ 1, -1, 71495.3331,
+ 2, -1, 8960.49049);
+
+ test_one<polygon, polygon, polygon>("ggl_list_20110307_javier",
+ ggl_list_20110307_javier[0], ggl_list_20110307_javier[1],
+ 1, if_typed<ct, float>(14, 13), 16815.6,
+ 1, 4, 3200.4,
+ 0.01);
+
+ if ( BOOST_GEOMETRY_CONDITION((! boost::is_same<ct, float>::value)) )
+ {
+ test_one<polygon, polygon, polygon>("ggl_list_20110716_enrico",
+ ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1],
+ 3, -1, 35723.8506317139,
+ 1, -1, 58456.4964294434
+ );
+ }
+
+ test_one<polygon, polygon, polygon>("ggl_list_20110820_christophe",
+ ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1],
+ 1, -1, 2.8570121719168924,
+ 1, -1, 64.498061986388564);
+
+ test_one<polygon, polygon, polygon>("ggl_list_20120717_volker",
+ ggl_list_20120717_volker[0], ggl_list_20120717_volker[1],
+ 1, 11, 3370866.2295081965,
+ 1, 5, 384.2295081964694, 0.01);
+
+ // 2011-07-02 / 2014-06-19
+ // Interesting FP-precision case.
+ // sql server gives: 6.62295817619452E-05
+ // PostGIS gives: 0.0 (no output)
+ // Boost.Geometry gave results depending on FP-type, and compiler, and operating system.
+ // Since rescaling to integer results are equal w.r.t. compiler/FP type,
+ // however, some long spikes are still generated in the resulting difference
+ test_one<polygon, polygon, polygon>("ggl_list_20110627_phillip",
+ ggl_list_20110627_phillip[0], ggl_list_20110627_phillip[1],
+ 1, -1,
+ if_typed_tt<ct>(0.0000000000001105367, 0.00021401892),
+ 1, -1, 3577.40960816756,
+ 0.01
+ );
+
+ // Ticket 8310, one should be completely subtracted from the other.
+ test_one<polygon, polygon, polygon>("ticket_8310a",
+ ticket_8310a[0], ticket_8310a[1],
+ 1, 10, 10.11562724,
+ 0, 0, 0);
+ test_one<polygon, polygon, polygon>("ticket_8310b",
+ ticket_8310b[0], ticket_8310b[1],
+ 1, 10, 10.12655608,
+ 0, 0, 0);
+ test_one<polygon, polygon, polygon>("ticket_8310c",
+ ticket_8310c[0], ticket_8310c[1],
+ 1, 10, 10.03103292,
+ 0, 0, 0);
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<polygon, polygon, polygon>("ticket_9081_15",
+ ticket_9081_15[0], ticket_9081_15[1],
+ 1, 10, 0.0334529710902111,
+ 0, 0, 0);
+#endif
+
+ test_one<polygon, polygon, polygon>("ticket_9081_314",
+ ticket_9081_314[0], ticket_9081_314[1],
+ 2, 12, 0.0451236449624935,
+ 0, 0, 0);
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<polygon, polygon, polygon>("ticket_9563",
+ ticket_9563[0], ticket_9563[1],
+ 0, 0, 0,
+ 6, 24, 20.096189);
+#endif
+
+ test_one<polygon, polygon, polygon>("ticket_10108_a",
+ ticket_10108_a[0], ticket_10108_a[1],
+ 1, 4, 0.0145037,
+ 1, 4, 0.029019232);
+ test_one<polygon, polygon, polygon>("ticket_10108_b",
+ ticket_10108_b[0], ticket_10108_b[1],
+ 1, 5, 1081.68697,
+ 1, 5, 1342.65795);
+
+ // From assemble-test, with a u/u case
+ test_one<polygon, polygon, polygon>("assemble_0210",
+ "POLYGON((0 0,0 10,10 10,10 0,0 0),(8.5 1,9.5 1,9.5 2,8.5 2,8.5 1))",
+ "POLYGON((2 0.5,0.5 2,0.5 8,2 9.5,6 9.5,8.5 8,8.5 2,7 0.5,2 0.5),(2 2,7 2,7 8,2 8,2 2))",
+ 2, 23, 62.25,
+ 0, 0, 0.0);
+
+ // Other combi's
+ {
+ test_one<polygon, polygon, ring>(
+ "star_ring_ring", example_star, example_ring,
+ 5, 22, 1.1901714, 5, 27, 1.6701714);
+
+ test_one<polygon, ring, polygon>(
+ "ring_star_ring", example_ring, example_star,
+ 5, 27, 1.6701714, 5, 22, 1.1901714);
+
+ static std::string const clip = "POLYGON((2.5 0.5,5.5 2.5))";
+
+ test_one<polygon, box, ring>("star_box",
+ clip, example_star,
+ 4, 20, 2.833333, 4, 16, 0.833333);
+
+ test_one<polygon, ring, box>("box_star",
+ example_star, clip,
+ 4, 16, 0.833333, 4, 20, 2.833333);
+ }
+
+ // Counter clockwise
+ {
+ typedef bg::model::polygon<P, false> polygon_ccw;
+ test_one<polygon, polygon_ccw, polygon_ccw>(
+ "star_ring_ccw", example_star, example_ring,
+ 5, 22, 1.1901714, 5, 27, 1.6701714);
+ test_one<polygon, polygon, polygon_ccw>(
+ "star_ring_ccw1", example_star, example_ring,
+ 5, 22, 1.1901714, 5, 27, 1.6701714);
+ test_one<polygon, polygon_ccw, polygon>(
+ "star_ring_ccw2", example_star, example_ring,
+ 5, 22, 1.1901714, 5, 27, 1.6701714);
+ }
+
+ // Multi/box (should be moved to multi)
+ {
+ /* Tested with SQL Geometry:
+ with viewy as (select geometry::STGeomFromText(
+ 'MULTIPOLYGON(((0 1,2 5,5 3,0 1)),((1 1,5 2,5 0,1 1)))',0) as p,
+ geometry::STGeomFromText(
+ 'POLYGON((2 2,2 4,4 4,4 2,2 2))',0) as q)
+
+ select
+ p.STDifference(q).STArea(),p.STDifference(q).STNumGeometries(),p.STDifference(q) as p_min_q,
+ q.STDifference(p).STArea(),q.STDifference(p).STNumGeometries(),q.STDifference(p) as q_min_p,
+ p.STSymDifference(q).STArea(),q.STSymDifference(p) as p_xor_q
+ from viewy
+
+ */
+ typedef bg::model::multi_polygon<polygon> mp;
+
+ static std::string const clip = "POLYGON((2 2,4 4))";
+
+ test_one<polygon, box, mp>("simplex_multi_box_mp",
+ clip, case_multi_simplex[0],
+ 2, -1, 0.53333333333, 3, -1, 8.53333333333);
+ test_one<polygon, mp, box>("simplex_multi_mp_box",
+ case_multi_simplex[0], clip,
+ 3, -1, 8.53333333333, 2, -1, 0.53333333333);
+
+ }
+
+ /***
+ Experimental (cut), does not work:
+ test_one<polygon, polygon, polygon>(
+ "polygon_pseudo_line",
+ "POLYGON((0 0,0 4,4 4,4 0,0 0))",
+ "POLYGON((2 -2,2 -1,2 6,2 -2))",
+ 5, 22, 1.1901714,
+ 5, 27, 1.6701714);
+ ***/
+}
+
+/*******
+// To be moved to another file
+template <typename T>
+void test_difference_parcel_precision()
+{
+ typedef bg::model::d2::point_xy<T> point_type;
+ typedef bg::model::polygon<point_type> polygon_type;
+ typedef bg::model::linestring<point_type> linestring_type;
+ typedef std::vector<boost::uint8_t> byte_vector;
+
+ polygon_type parcel, buffer;
+
+ {
+ byte_vector wkb;
+ bg::hex2wkb("0103000000010000001A00000023DBF97EE316064146B6F3FDD32513415A643BDFD216064175931804E225134196438B6C52150641C976BE9F34261341F6285C8F06150641022B871641261341F853E3A5D3140641E17A14AE50261341B81E85EBFB120641A4703D8A142713414E6210584D120641AC1C5A64602713414E621058431106414E621058C9271341A01A2FDD1B11064121B07268D8271341F4FDD478571006411904560ECF271341448B6CE7DD0F06418195438BC1271341F6285C8F6A0F06413BDF4F0DA72713410E2DB29D360F06416F1283C091271341E5D022DB070F0641F6285C0F7227134160E5D022DA0E06416F1283404F271341448B6CE7D30E0641F853E3A52427134154E3A59BE60E06411904568E07271341643BDF4F0C0F0641D7A3703DFC2613414A0C022B100F064125068115FB26134191ED7C3F310F0641B6F3FDD4F42613414C378941F11006414A0C022BA0261341EC51B81ECC1206413BDF4F0D40261341022B87167514064125068115F1251341B4C876BE8C160641C74B37897F25134121B07268C6160641508D976E7525134123DBF97EE316064146B6F3FDD3251341", std::back_inserter(wkb));
+ bg::read_wkb(wkb.begin(), wkb.end(), parcel);
+ }
+ {
+ byte_vector wkb;
+ bg::hex2wkb("01030000000100000083000000000032FCD716064100009E998F25134100000706D81606410040A4998F2513410000DA0FD816064100C0E6998F2513410000A819D81606410080659A8F25134100806A23D816064100C0209B8F25134100801E2DD81606410080189C8F2513410000BE36D816064100404D9D8F25134100004540D816064100C0BE9E8F2513410000AF49D816064100806DA08F2513410000F752D8160641008059A28F2513410000195CD816064100C082A48F25134100800F65D81606410080E9A68F2513410000D66DD816064100408EA98F25134100006876D816064100C070AC8F2513410000C17ED8160641000091AF8F2513410080DC86D816064100C0EFB28F25134100009E8ED816064100C081B68F2513410080EC95D816064100803ABA8F2513410080C79CD8160641000018BE8F25134100002FA3D8160641008017C28F251341008022A9D8160641000037C68F2513410080A1AED8160641000074CA8F2513410000ACB3D81606410040CCCE8F251341000042B8D816064100403DD38F251341000062BCD81606410000C5D78F25134100000DC0D8160641000061DC8F251341000042C3D816064100000FE18F251341000001C6D81606410080CCE58F251341008049C8D8160641004097EA8F25134100001BCAD816064100006DEF8F251341008075CBD816064100804BF48F251341008058CCD8160641004030F98F2513410000C4CCD8160641000019FE8F2513410080B7CCD81606410080030390251341008032CCD81606410000ED0790251341000035CBD81606410000D40C902513410080BEC9D81606410040B511902513410000CFC7D816064100408F1690251341008065C5D816064100005F1B90251341008082C2D81606410080222090251341000025BFD81606410080D7249025134100004DBBD816064100807B29902513410080FAB6D816064100800C2E9025134100002DB2D816064100C08732902513410080E3ACD81606410000EB369025134100801EA7D81606410000343B902513410000DEA0D81606410080603F902513410080209AD816064100406E43902513410080209AC015064100406E43302613410080FC92C015064100004F473026134100008B8BC01506410040F64A302613410000D083C015064100C0634E302613410000D17BC0150641008097513026134100009273C015064100409154302613410000186BC015064100C050573026134100806762C01506410000D6593026134100808559C01506410000215C3026134100007650C01506410000315E3026134100003E47C015064100800660302613410000E23DC01506410000A1613026134100006734C015064100800063302613410080D12AC015064100C024643026134100002621C015064100800D653026134100006917C015064100C0BA653026134100809F0DC015064100402C66302613410000CE03C015064100006266302613410000F9F9BF15064100C05B6630261341000026F0BF1506410040196630261341000058E6BF15064100809A6530261341008095DCBF1506410040DF64302613410080E1D2BF1506410080E76330261341000042C9BF15064100C0B262302613410000BBBFBF1506410040416130261341000051B6BF1506410080925F30261341000009ADBF1506410080A65D302613410000E7A3BF15064100407D5B302613410080F09ABF150641008016593026134100002A92BF15064100C071563026134100009889BF15064100408F533026134100003F81BF15064100006F503026134100802379BF1506410040104D3026134100006271BF15064100407E49302613410080136ABF1506410080C5453026134100803863BF1506410000E841302613410000D15CBF1506410080E83D302613410080DD56BF1506410000C9393026134100805E51BF15064100008C35302613410000544CBF15064100C03331302613410000BE47BF15064100C0C22C3026134100009E43BF15064100003B28302613410000F33FBF15064100009F23302613410000BE3CBF1506410000F11E302613410000FF39BF1506410080331A302613410080B637BF15064100C06815302613410000E535BF150641000093103026134100808A34BF1506410080B40B302613410080A733BF15064100C0CF063026134100003C33BF1506410000E7013026134100804833BF1506410080FCFC2F2613410080CD33BF150641000013F82F2613410000CB34BF15064100002CF32F26134100804136BF15064100C04AEE2F26134100003138BF15064100C070E92F26134100809A3ABF1506410000A1E42F26134100807D3DBF1506410080DDDF2F2613410000DB40BF150641008028DB2F2613410000B344BF150641008084D62F26134100800549BF1506410080F3D12F2613410000D34DBF150641004078CD2F26134100801C53BF150641000015C92F2613410080E158BF1506410000CCC42F2613410000225FBF15064100809FC02F2613410080DF65BF15064100C091BC2F2613410080DF65D716064100C091BC8F2513410080036DD71606410000B1B88F25134100007574D716064100C009B58F2513410000307CD716064100409CB18F25134100002F84D7160641008068AE8F25134100006E8CD716064100C06EAB8F2513410000E894D71606410040AFA88F2513410080989DD716064100002AA68F25134100807AA6D71606410000DFA38F25134100008AAFD71606410000CFA18F2513410000C2B8D71606410080F99F8F25134100001EC2D716064100005F9E8F251341000099CBD71606410080FF9C8F25134100802ED5D71606410040DB9B8F2513410000DADED71606410080F29A8F251341000097E8D71606410040459A8F251341008060F2D716064100C0D3998F251341000032FCD716064100009E998F251341", std::back_inserter(wkb));
+ bg::read_wkb(wkb.begin(), wkb.end(), buffer);
+ }
+ bg::correct(parcel);
+ bg::correct(buffer);
+
+ std::vector<polygon_type> pieces;
+ bg::difference(parcel, buffer, pieces);
+
+ std::vector<polygon_type> filled_out;
+ bg::difference(parcel, pieces.back(), filled_out);
+
+#if defined(TEST_OUTPUT)
+ std::cout << bg::area(parcel) << std::endl;
+ std::cout << bg::area(buffer) << std::endl;
+ std::cout << pieces.size() << std::endl;
+ std::cout << bg::area(pieces.front()) << std::endl;
+ std::cout << filled_out.size() << std::endl;
+ std::cout << std::setprecision(16) << bg::wkt(filled_out.front()) << std::endl;
+ std::cout << bg::wkt(filled_out.front()) << std::endl;
+ std::cout << bg::area(filled_out.front()) << std::endl;
+ std::cout << bg::perimeter(filled_out.front()) << std::endl;
+#endif
+
+#if defined(TEST_WITH_SVG)
+ {
+ linestring_type cut_line;
+ bg::read_wkt("linestring(180955 313700,180920 313740)", cut_line);
+
+ std::ostringstream filename;
+ filename << "difference_precision_"
+ << string_from_type<T>::name()
+ << ".svg";
+
+ std::ofstream svg(filename.str().c_str());
+
+ bg::svg_mapper<point_type> mapper(svg, 500, 500);
+
+ mapper.add(cut_line);
+
+ //mapper.map(parcel, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:3");
+ mapper.map(pieces.front(), "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:1");
+ mapper.map(pieces.back(), "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:1");
+ mapper.map(filled_out.front(), "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:3");
+
+ mapper.map(cut_line, "opacity:0.8;fill:none;stroke:rgb(255,128,0);stroke-width:5;stroke-dasharray:1,7;stroke-linecap:round");
+ //mapper.map(cut_line, "opacity:0.8;fill:none;stroke:rgb(255,128,0);stroke-width:2");
+ }
+#endif
+}
+*****/
+
+
+template <typename P, bool clockwise, bool closed>
+void test_specific()
+{
+ typedef bg::model::polygon<P, clockwise, closed> polygon;
+
+ test_one<polygon, polygon, polygon>("ggl_list_20120717_volker",
+ ggl_list_20120717_volker[0], ggl_list_20120717_volker[1],
+ 1, 11, 3371540,
+ 1, 4, 384, 0.001);
+
+ test_one<polygon, polygon, polygon>("ticket_10658",
+ ticket_10658[0], ticket_10658[1],
+ 1, 6, 1510434,
+ 0, 0, 0);
+
+ test_one<polygon, polygon, polygon>("ticket_11121",
+ ticket_11121[0], ticket_11121[1],
+ 2, 8, 489763.5,
+ 1, 4, 6743503.5);
+}
+
+
+int test_main(int, char* [])
+{
+ //test_difference_parcel_precision<float>();
+ //test_difference_parcel_precision<double>();
+
+ test_all<bg::model::d2::point_xy<double> >();
+
+ test_specific<bg::model::d2::point_xy<int>, false, false>();
+
+ test_ticket_10658<int>
+ ("MULTIPOLYGON(((516 2484,516 1608,1308 1932,2094 2466,2094 3150,1308 3066,516 2484)))");
+
+ test_ticket_10658<double>
+ ("MULTIPOLYGON(((516 2484,516 1608,1308 1932,2094 2466,2094 3150,1308 3066,516 2484)))");
+
+ test_ticket_10835<int>
+ ("MULTILINESTRING((5239 2113,5233 2114),(4795 2205,1020 2986))",
+ "MULTILINESTRING((5239 2113,5233 2114),(4795 2205,1460 2895))");
+
+ test_ticket_10835<double>
+ ("MULTILINESTRING((5239 2113,5232.52 2114.34),(4794.39 2205,1020 2986))",
+ "MULTILINESTRING((5239 2113,5232.52 2114.34),(4794.39 2205,1459.78 2895))");
+
+ test_ticket_11121<int>();
+
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+ test_all<bg::model::d2::point_xy<float> >();
+
+#ifdef HAVE_TTMATH
+ std::cout << "Testing TTMATH" << std::endl;
+ test_all<bg::model::d2::point_xy<ttmath_big> >();
+ //test_difference_parcel_precision<ttmath_big>();
+#endif
+#endif
+
+ return 0;
+}
diff --git a/libs/geometry/test/algorithms/set_operations/difference/difference_linear_linear.cpp b/libs/geometry/test/algorithms/set_operations/difference/difference_linear_linear.cpp
new file mode 100644
index 000000000..9f79baa08
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/difference/difference_linear_linear.cpp
@@ -0,0 +1,1480 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#include <iostream>
+
+#ifndef BOOST_TEST_MODULE
+#define BOOST_TEST_MODULE test_difference_linear_linear
+#endif
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+#define BOOST_GEOMETRY_DEBUG_TURNS
+#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
+#endif
+
+#include <boost/test/included/unit_test.hpp>
+
+#include "test_difference_linear_linear.hpp"
+
+#include <boost/geometry/geometries/linestring.hpp>
+#include <boost/geometry/multi/geometries/multi_linestring.hpp>
+#include <boost/geometry/algorithms/difference.hpp>
+
+typedef bg::model::point<double,2,bg::cs::cartesian> point_type;
+typedef bg::model::segment<point_type> segment_type;
+typedef bg::model::linestring<point_type> linestring_type;
+typedef bg::model::multi_linestring<linestring_type> multi_linestring_type;
+
+
+
+//===========================================================================
+//===========================================================================
+//===========================================================================
+
+
+BOOST_AUTO_TEST_CASE( test_difference_linestring_linestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** LINESTRING / LINESTRING DIFFERENCE ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_difference_of_geometries<L, L, ML> tester;
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 1,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(0 2,1 1,2 1,3 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1),(2 1,3 2))"),
+ "lldf00");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 2,1 1,2 1,3 0)"),
+ from_wkt<L>("LINESTRING(0 0,1 1,2 1,3 2)"),
+ from_wkt<ML>("MULTILINESTRING((0 2,1 1),(2 1,3 0))"),
+ "lldf00-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,5 0)"),
+ from_wkt<L>("LINESTRING(3 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,3 0),(4 0,5 0))"),
+ "lldf01");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(3 0,4 0)"),
+ from_wkt<L>("LINESTRING(0 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "lldf01-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,6 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,3 0))"),
+ "lldf01-2");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(3 0,6 0)"),
+ from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((4 0,6 0))"),
+ "lldf01-3");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,6 0)"),
+ from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((4 0,6 0))"),
+ "lldf01-4");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<L>("LINESTRING(0 0,6 0)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "lldf01-5");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<L>("LINESTRING(0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,4 0),(5 0,20 0))"),
+ "lldf01-6");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-20 0,20 0)"),
+ from_wkt<L>("LINESTRING(0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0)"),
+ from_wkt<ML>("MULTILINESTRING((-20 0,4 0),(5 0,20 0))"),
+ "lldf01-7");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<L>("LINESTRING(2 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0))"),
+ "lldf01-8");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(2 0,4 0)"),
+ from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "lldf01-9");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0)"),
+ from_wkt<L>("LINESTRING(4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0))"),
+ "lldf01-10");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0)"),
+ from_wkt<L>("LINESTRING(2 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0))"),
+ "lldf01-11");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,3 0))"),
+ "lldf01-11a");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,3 0))"),
+ "lldf01-11b");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,6 0)"),
+ from_wkt<L>("LINESTRING(2 0,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(5 0,6 0))"),
+ "lldf01-12");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,5 5,10 5,15 0)"),
+ from_wkt<L>("LINESTRING(-1 6,0 5,15 5)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,5 5),(10 5,15 0))"),
+ "lldf02");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0))"),
+ "lldf03");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,5 5,10 5,15 0,20 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 5,10 5,15 0))"),
+ "lldf04");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,25 1)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (20 0,25 1))"),
+ "lldf05");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0))"),
+ "lldf05-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (30 0,31 0))"),
+ "lldf06");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,25 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (30 0,31 0))"),
+ "lldf07");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (30 0,31 0))"),
+ "lldf08");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (30 0,31 1))"),
+ "lldf09");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (30 0,31 1))"),
+ "lldf10");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,20 0,\
+ 30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(2 0,3 0),\
+ (4 0,5 5,10 5,15 0),(30 0,31 1))"),
+ "lldf11");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(2 0,3 0),\
+ (4 0,5 5,10 5,15 0),(30 0,31 0))"),
+ "lldf11-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "lldf12");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<L>("LINESTRING(3 1,2 0,0 0)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "lldf12-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 5,4 0)"),
+ from_wkt<L>("LINESTRING(1 0,2 1,3 5,4 0,5 10)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0))"),
+ "lldf13");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 0,2.5 0,3 1)"),
+ from_wkt<L>("LINESTRING(0 0,2 0,2.5 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "lldf14");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 5,4 0)"),
+ from_wkt<L>("LINESTRING(1 0,2 1,3 5)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(3 5,4 0))"),
+ "lldf15");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(0.5 0,1 0,3 2,4 5)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,0.5 0))"),
+ "lldf16");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(4 5,3 2,1 0,0.5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,0.5 0))"),
+ "lldf16-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1,30 1)"),
+ from_wkt<L>("LINESTRING(1 1,2 0,3 1,20 1,25 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(25 1,30 1))"),
+ "lldf17");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1,21 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 1,2 0,3 1,20 1,25 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1,21 0,30 0))"),
+ "lldf18");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,4 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19a");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(4 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19a-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19b");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0,6 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19c");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,3 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19d");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,3 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19e");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0,5 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19f");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,5 0,4 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19f-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,5 0,5 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19g");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,5 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0))"),
+ "lldf19g-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0,30 30,10 30,10 -10,15 0,40 0)"),
+ from_wkt<L>("LINESTRING(5 5,10 0,10 30,20 0,25 0,25 25,50 0,35 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(25 0,30 0,30 30,10 30),\
+ (10 0,10 -10,15 0,20 0),(25 0,35 0))"),
+ "lldf20");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0,30 30,10 30,10 -10,15 0,40 0)"),
+ from_wkt<L>("LINESTRING(5 5,10 0,10 30,20 0,25 0,25 25,50 0,15 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,15 0),(30 0,30 30,10 30),\
+ (10 0,10 -10,15 0))"),
+ "lldf20a");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<L>("LINESTRING(2 2,5 -1,15 2,18 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,18 0),(20 0,30 0))"),
+ "lldf21"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(2 2,5 -1,15 2,18 0,20 0)"),
+ from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((2 2,5 -1,15 2,18 0))"),
+ "lldf21a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0)"),
+ from_wkt<L>("LINESTRING(1 0,4 0,2 1,5 1,4 0,8 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(8 0,10 0))"),
+ "lldf22"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0)"),
+ from_wkt<L>("LINESTRING(4 0,5 0,5 1,1 1,1 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,10 0))"),
+ "lldf23"
+ );
+
+ // the following two tests have been discussed with by Adam
+ tester::apply
+ (from_wkt<L>("LINESTRING(1 0,1 1,2 1)"),
+ from_wkt<L>("LINESTRING(2 1,1 1,1 0)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "lldf24"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(1 0,1 1,2 1)"),
+ from_wkt<L>("LINESTRING(1 2,1 1,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 1))"),
+ "lldf25"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(6 0,0 0,5 0)"),
+ from_wkt<L>("LINESTRING(2 0,-10 0)"),
+ from_wkt<ML>("MULTILINESTRING((6 0,2 0),(2 0,5 0))"),
+ "lldf27a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(6 0,0 0,5 0)"),
+ from_wkt<L>("LINESTRING(2 0,-1 0,-10 0)"),
+ from_wkt<ML>("MULTILINESTRING((6 0,2 0),(2 0,5 0))"),
+ "lldf27b"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(6 0,0 0,5 0)"),
+ from_wkt<L>("LINESTRING(2 0,0 0,-10 0)"),
+ from_wkt<ML>("MULTILINESTRING((6 0,2 0),(2 0,5 0))"),
+ "lldf27c"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(2 0,0 0,-10 0)"),
+ from_wkt<L>("LINESTRING(6 0,0 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,-10 0))"),
+ "lldf27d"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5)"),
+ from_wkt<L>("LINESTRING(-3 2,-3 0,-3 -10)"),
+ from_wkt<ML>("MULTILINESTRING((-3 6,-3 2),(-3 2,-3 5))"),
+ "lldf28a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-3 2,-3 0,-3 -10)"),
+ from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5)"),
+ from_wkt<ML>("MULTILINESTRING((-3 0,-3 -10))"),
+ "lldf28b"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5)"),
+ from_wkt<L>("LINESTRING(-3 2,-3 0,-3 -10)"),
+ from_wkt<ML>("MULTILINESTRING((-3 6,-3 2),(-3 2,-3 5))"),
+ "lldf28c"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-7 -8,3 0,4 -1)"),
+ from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,7 -4)"),
+ from_wkt<ML>("MULTILINESTRING((-7 -8,3 0))"),
+ "lldf29a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-7 -8,3 0,4 -1,-7 10)"),
+ from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,2 -1)"),
+ from_wkt<ML>("MULTILINESTRING((-7 -8,3 0),(3 0,-7 10))"),
+ "lldf29b"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-7 -8,3 0,4 -1,-7 10)"),
+ from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1)"),
+ from_wkt<ML>("MULTILINESTRING((-7 -8,3 0),(3 0,-7 10))"),
+ "lldf29c"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1)"),
+ from_wkt<L>("LINESTRING(-7 -8,3 0,4 -1,-7 10)"),
+ from_wkt<ML>("MULTILINESTRING((-5 -4,3 0),(4 -1,7 -4,2 -1))"),
+ "lldf29c-r"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,\
+ 3 0,4 -1,-7 10,-4 10)"),
+ from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1,-4 -1,-2 6)"),
+ from_wkt<ML>("MULTILINESTRING((-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,\
+ 3 0),(3 0,-7 10,-4 10))"),
+ "lldf29d"
+ );
+
+#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS
+ tester::apply
+ (from_wkt<L>("LINESTRING(8 5,5 1,-2 3,1 10)"),
+ from_wkt<L>("LINESTRING(1.9375 1.875,\
+ 1.7441860465116283 1.9302325581395348,\
+ -0.7692307692307692 2.6483516483516487,\
+ -2 3,-1.0071942446043165 5.316546762589928)"),
+ from_wkt<ML>("MULTILINESTRING((8 5,5 1,-2 3,1 10))"),
+ "lldf30a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(1.9375 1.875,\
+ 1.7441860465116283 1.9302325581395348,\
+ -0.7692307692307692 2.6483516483516487,\
+ -2 3,-1.0071942446043165 5.316546762589928)"),
+ from_wkt<L>("LINESTRING(8 5,5 1,-2 3,1 10)"),
+ from_wkt<ML>("MULTILINESTRING((1.9375 1.875,\
+ 1.7441860465116283 1.9302325581395348,\
+ -0.7692307692307692 2.6483516483516487,\
+ -2 3,-1.0071942446043165 5.316546762589928))"),
+ "lldf30b"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(5 -8,-7 -6,-3 6,-3 1,-5 4,-1 0,8 5,\
+ 5 1,-2 3,1 10,8 5,6 2,7 4)"),
+ from_wkt<L>("LINESTRING(1.9375 1.875,\
+ 1.7441860465116283 1.9302325581395348,\
+ -0.7692307692307692 2.6483516483516487,\
+ -2 3,-1.0071942446043165 5.316546762589928)"),
+ from_wkt<ML>("MULTILINESTRING((5 -8,-7 -6,-3 6,-3 1,-5 4,-1 0,8 5,\
+ 5 1,-2 3,1 10,8 5,6 2,7 4))"),
+
+ "lldf30c"
+ );
+#endif
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(8 1, 4 .4)"),
+ from_wkt<L>("LINESTRING(0 -.2, 8 1)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "lldf31s"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(8 1, 4 .4,2 8)"),
+ from_wkt<L>("LINESTRING(0 -.2, 8 1)"),
+ from_wkt<ML>("MULTILINESTRING((4 .4,2 8))"),
+ "lldf31x"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(2 8,4 .4,8 1)"),
+ from_wkt<L>("LINESTRING(0 -.2, 8 1)"),
+ from_wkt<ML>("MULTILINESTRING((2 8,4 .4))"),
+ "lldf31x-r"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 5, 8 1, 4 .4, 2 8)"),
+ from_wkt<L>("LINESTRING(0 -.2, 8 1, -.5 7)"),
+ from_wkt<ML>("MULTILINESTRING((0 5,8 1),(4 .4,2 8))"),
+ "lldf31y",
+ 1e-10
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 -.2, 8 1, -.5 7)"),
+ from_wkt<L>("LINESTRING(0 5, 8 1, 4 .4, 2 8)"),
+ from_wkt<ML>("MULTILINESTRING((0 -.2,4 .4),(8 1,-.5 7))"),
+ "lldf31y-r",
+ 1e-10
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 5, 8 1, 4 .4, 2 8)"),
+ from_wkt<L>("LINESTRING(0 -.2, 8 1, -.5 7, 6 +.2)"),
+ from_wkt<ML>("MULTILINESTRING((0 5,8 1),(4 .4,2 8))"),
+ "lldf31y+",
+ 1e-10
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(10.0002 2,9 -1032.34324, .3 8, 0 5, 8 1, 4 .4, 2 8)"),
+ from_wkt<L>("LINESTRING(0 -.2, 8 1, -.5 7, 6 +.2)"),
+ from_wkt<ML>("MULTILINESTRING((10.0002 2,9 -1032.34324,.3 8,0 5,8 1),(4 .4,2 8))"),
+ "lldf31z",
+ 1e-10
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 -.2, 8 1, -.5 7, 6 +.2)"),
+ from_wkt<L>("LINESTRING(10.0002 2,9 -1032.34324, .3 8, 0 5, 8 1, 4 .4, 2 8)"),
+ from_wkt<ML>("MULTILINESTRING((0 -.2,4 .4),(8 1,-.5 7,6 .2))"),
+ "lldf31z-r",
+ 1e-10
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0, 8 1, -.5 7)"),
+ from_wkt<L>("LINESTRING(0 5, 8 1, 4 .5, 2 8)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,4 .5),(8 1,-.5 7))"),
+ "lldf32"
+ );
+}
+
+
+
+BOOST_AUTO_TEST_CASE( test_difference_linestring_multilinestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** LINESTRING / MULTILINESTRING DIFFERENCE ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_difference_of_geometries<L, ML, ML> tester;
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 2,4 3),(1 1,2 2,5 3))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1))"),
+ "lmldf01"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1))"),
+ "lmldf02"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(5 0,10 0,20 1))"),
+ "lmldf03"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1))"),
+ "lmldf04"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0))"),
+ "lmldf07"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0))"),
+ "lmldf07a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "lmldf07b"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0))"),
+ "lmldf08"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 0.5,3 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0.5,3 0))"),
+ "lmldf09"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,1.5 0,2 0.5,3 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,1 0,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(1.5 0,2 0.5,3 0))"),
+ "lmldf10"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (1 1,2 0,18 0,19 1),(2 1,3 0,17 0,18 1),\
+ (3 1,4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "lmldf12"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0,20 1),\
+ (2 0,18 0,19 1),(3 0,17 0,18 1),\
+ (4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "lmldf13"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "lmldf14"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "lmldf15"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "lmldf15a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,5 0,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "lmldf16"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,5 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "lmldf16a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0))"),
+ "lmldf17"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0,26 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0))"),
+ "lmldf17a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0))"),
+ "lmldf18"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0))"),
+ "lmldf18a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(20 0,30 0))"),
+ "lmldf18b"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,25 0,26 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,25 0),(26 0,30 0))"),
+ "lmldf18c"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,25 0,21 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,21 0),(25 0,30 0))"),
+ "lmldf18d"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 5,1 0,9 0,10 5),(0 1,2 0,3 1),\
+ (0 -2,3 0,4 4),(0 -5,4 0,5 0,6 3))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(9 0,10))"),
+ "lmldf19"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,0 0),(10 0,12 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ "lmldf20"
+ );
+}
+
+
+
+
+
+BOOST_AUTO_TEST_CASE( test_difference_multilinestring_linestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / LINESTRING DIFFERENCE ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_difference_of_geometries<ML, L, ML> tester;
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<L>("LINESTRING(1 1,2 2,4 3)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ "mlldf01"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<L>("LINESTRING(1 1,2 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\
+ (1 0,2 0),(4 0,7 0))"),
+ "mlldf02"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<L>("LINESTRING(-1 -1,1 0,101 0,200 -1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0))"),
+ "mlldf03"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<L>("LINESTRING(0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "mlldf04"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((-1 0,-1 10),(0 0,20 0),(25 0,30 0))"),
+ from_wkt<L>("LINESTRING(0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,-1 10),(0 0,1 0),(19 0,20 0),(25 0,30 0))"),
+ "mlldf05"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((-3 2,-3 0,-3 -10))"),
+ from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5)"),
+ from_wkt<ML>("MULTILINESTRING((-3 0,-3 -10))"),
+ "mlldf06a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((6 6,-3 2,-3 0,-3 -10,9 -2))"),
+ from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\
+ -6 1,10 -6)"),
+ from_wkt<ML>("MULTILINESTRING((6 6,-3 2),(-3 0,-3 -10,9 -2))"),
+ "mlldf06b"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 -3,5 4,6 6,-3 2,-3 0,-3 -10,\
+ 9 -2,9 5,5 -5,-4 -8,9 0))"),
+ from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\
+ -6 1,10 -6)"),
+ from_wkt<ML>("MULTILINESTRING((0 -3,5 4,6 6,-3 2),\
+ (-3 0,-3 -10,9 -2,9 5,5 -5,-4 -8,9 0))"),
+ "mlldf06c"
+ );
+}
+
+
+
+
+
+
+
+BOOST_AUTO_TEST_CASE( test_difference_multilinestring_multilinestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / MULTILINESTRING DIFFERENCE ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef multi_linestring_type ML;
+
+ typedef test_difference_of_geometries<ML, ML, ML> tester;
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 2,4 3),(1 1,2 2,5 3))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ "mlmldf01"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\
+ (1 0,2 0),(4 0,7 0))"),
+ "mlmldf02"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(5 0,10 0,20 1),\
+ (1 0,2 0),(5 0,7 0))"),
+ "mlmldf03"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\
+ (1 0,2 0),(4 0,7 0))"),
+ "mlmldf04"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (10 10,20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (10 20,15 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\
+ (1 0,2 0),(4 0,7 0),(10 10,15 10),(20 10,30 20))"),
+ "mlmldf05"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 10),(1 0,7 0),\
+ (10 10,20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (-1 -1,0 0,9 0,11 10,12 10,13 3,14 4,15 5),\
+ (10 20,15 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((9 0,10 0,13 3),(15 5,20 10),\
+ (10 10,11 10),(12 10,15 10),(20 10,30 20))"),
+ "mlmldf06"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (-1 -1,0 0,9 0,11 10,12 10,13 3,14 4,15 5),\
+ (10 20,15 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 10),(1 0,7 0),\
+ (10 10,20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0),(-1 -1,0 0),(9 0,11 10),\
+ (12 10,13 3),(10 20,15 10),(20 10,25 10,30 15))"),
+ "mlmldf06a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0))"),
+ "mlmldf07"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((-1 1,0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0))"),
+ "mlmldf07a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "mlmldf07b"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0))"),
+ "mlmldf08"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0.5,3 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0.5,3 0))"),
+ "mlmldf09"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 0,1.5 0,2 0.5,3 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,1 0,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(1.5 0,2 0.5,3 0))"),
+ "mlmldf10"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 1,100 1,101 0),\
+ (0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1,3 0,4 0,5 1,6 1,\
+ 7 0,8 0,9 1,10 1,11 0,12 0,13 1,14 1,15 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1),(2 1,5 1),(6 1,9 1),\
+ (10 1,13 1),(14 1,100 1,101 0),(0 0,1 0))"),
+ "mlmldf11"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (1 1,2 0,18 0,19 1),(2 1,3 0,17 0,18 1),\
+ (3 1,4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "mlmldf12"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0,20 1),\
+ (2 0,18 0,19 1),(3 0,17 0,18 1),\
+ (4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "mlmldf13"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "mlmldf14"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "mlmldf15"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "mlmldf15a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,5 0,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "mlmldf16"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,5 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "mlmldf16a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0))"),
+ "mlmldf17"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0,26 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0))"),
+ "mlmldf17a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0))"),
+ "mlmldf18"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,18 0,19 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0))"),
+ "mlmldf18a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,0 0),(10 0,12 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ "mlmldf19"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((1 5, -4.3 -.1), (0 6, 8.6 6, 189.7654 5, 1 3, 6 3, 3 5, 6 2.232432, 0 4), (-6 5, 1 2.232432), (3 -1032.34324, 9 0, 189.7654 1, -1.4 3, 3 189.7654, +.3 10.0002, 1 5, 6 3, 5 1, 9 1, 10.0002 -1032.34324, -0.7654 0, 5 3, 3 4), (2.232432 2.232432, 8.6 +.4, 0.0 2.232432, 4 0, -8.8 10.0002), (1 0, 6 6, 7 2, -0 8.4), (-0.7654 3, +.6 8, 4 -1032.34324, 1 6, 0 4), (0 7, 2 1, 8 -7, 7 -.7, -1032.34324 9), (5 0, 10.0002 4, 8 7, 3 3, -8.1 5))"),
+ from_wkt<ML>("MULTILINESTRING((5 10.0002, 2 7, -0.7654 0, 5 3), (0 -0.7654, 4 10.0002, 4 +.1, -.8 3, -.1 8, 10.0002 2, +.9 -1032.34324))"),
+ from_wkt<ML>("MULTILINESTRING((1 5,-4.3 -0.1),(0 6,8.6 6,189.7654 5,1 3,6 3,3 5,6 2.232432,0 4),(-6 5,1 2.232432),(5 3,3 4),(3 -1032.34324,9 0,189.7654 1,-1.4 3,3 189.7654,0.3 10.0002,1 5,6 3,5 1,9 1,10.0002 -1032.34324,-0.7654 0),(2.232432 2.232432,8.6 0.4,0 2.232432,4 0,-8.8 10.0002),(1 0,6 6,7 2,-0 8.4),(-0.7654 3,0.6 8,4 -1032.34324,1 6,0 4),(0 7,2 1,8 -7,7 -0.7,-1032.34324 9),(5 0,10.0002 4,8 7,3 3,-8.1 5))"),
+ "mlmldf24",
+ 1e-10
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((5 10.0002, 2 7, -0.7654 0, 5 3), (0 -0.7654, 4 10.0002, 4 +.1, -.8 3, -.1 8, 10.0002 2, +.9 -1032.34324))"),
+ from_wkt<ML>("MULTILINESTRING((1 5, -4.3 -.1), (0 6, 8.6 6, 189.7654 5, 1 3, 6 3, 3 5, 6 2.232432, 0 4), (-6 5, 1 2.232432), (3 -1032.34324, 9 0, 189.7654 1, -1.4 3, 3 189.7654, +.3 10.0002, 1 5, 6 3, 5 1, 9 1, 10.0002 -1032.34324, -0.7654 0, 5 3, 3 4), (2.232432 2.232432, 8.6 +.4, 0.0 2.232432, 4 0, -8.8 10.0002), (1 0, 6 6, 7 2, -0 8.4), (-0.7654 3, +.6 8, 4 -1032.34324, 1 6, 0 4), (0 7, 2 1, 8 -7, 7 -.7, -1032.34324 9), (5 0, 10.0002 4, 8 7, 3 3, -8.1 5))"),
+ from_wkt<ML>("MULTILINESTRING((5 10.0002,2 7,-0.7654 8.88178e-16),(0 -0.7654,4 10.0002,4 0.1,-0.8 3,-0.1 8,10.0002 2,0.9 -1032.34324))"),
+ "mlmldf24-r",
+ 1e-10
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((-.4 2, 2.232432 3, 6 9, 8 189.7654, -1032.34324 5.4, 2.232432 9), (-1032.34324 3, 8 -1.6), (0 -.2, 8 1, -.5 7, 6 +.2))"),
+ from_wkt<ML>("MULTILINESTRING((-8 1, 4.8 6, 2 +.5), (10.0002 2,9 -1032.34324, .3 8, 0 5, 8 1, 4 .4, 2 8), (6 7, +.1 7, 0 -.5))"),
+ from_wkt<ML>("MULTILINESTRING((-0.4 2,2.232432 3,6 9,8 189.7654,-1032.34324 5.4,2.232432 9),(-1032.34324 3,8 -1.6),(0 -0.2,4 0.4),(8 1,-0.5 7,6 0.2))"),
+ "mlmldf25",
+ 1e-10
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((-8 1, 4.8 6, 2 +.5), (10.0002 2,9 -1032.34324, .3 8, 0 5, 8 1, 4 .4, 2 8), (6 7, +.1 7, 0 -.5))"),
+ from_wkt<ML>("MULTILINESTRING((-.4 2, 2.232432 3, 6 9, 8 189.7654, -1032.34324 5.4, 2.232432 9), (-1032.34324 3, 8 -1.6), (0 -.2, 8 1, -.5 7, 6 +.2))"),
+ from_wkt<ML>("MULTILINESTRING((-8 1,4.8 6,2 0.5),(10.0002 2,9 -1032.34324,0.3 8,0 5,8 1),(4 0.4,2 8),(6 7,0.1 7,0 -0.5))"),
+ "mlmldf25-r",
+ 1e-10
+ );
+}
+
+
+
+
+
+
+#ifndef BOOST_GEOMETRY_TEST_NO_DEGENERATE
+BOOST_AUTO_TEST_CASE( test_difference_ml_ml_degenerate )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / MULTILINESTRING DIFFERENCE"
+ << " (DEGENERATE) ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef multi_linestring_type ML;
+
+ typedef test_difference_of_geometries<ML, ML, ML> tester;
+
+ // the following test cases concern linestrings with duplicate
+ // points and possibly linestrings with zero length.
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((5 5,5 5),(0 0,18 0,18 0,\
+ 19 0,19 0,19 0,30 0),(2 0,2 0),(4 10,4 10))"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 10),\
+ (4 0,4 10),(5 5,5 5))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0),(20 0,30 0))"),
+ "mlmldf20a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((5 5,5 5),(0 0,0 0,18 0,18 0,\
+ 19 0,19 0,19 0,30 0,30 0),(2 0,2 0),(4 10,4 10))"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,1 1,2 2,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (4 0,4 10,4 10),(5 5,5 5))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0),(20 0,30 0))"),
+ "mlmldf20aa"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((10 10,10 10),(0 0,0 0,18 0,18 0,\
+ 19 0,19 0,19 0,30 0,30 0),(2 0,2 0),(4 10,4 10))"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,1 1,2 2,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (4 0,4 10,4 10),(5 5,5 5))"),
+ from_wkt<ML>("MULTILINESTRING((10 10,10 10),(0 0,5 0),(20 0,30 0))"),
+ "mlmldf20aaa"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((10 10),(0 0,0 0,18 0,18 0,\
+ 19 0,19 0,19 0,30 0,30 0),(2 0,2 0),(4 10,4 10))"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,1 1,2 2,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (4 0,4 10,4 10),(5 5,5 5))"),
+ from_wkt<ML>("MULTILINESTRING((10 10,10 10),(0 0,5 0),(20 0,30 0))"),
+ "mlmldf20aaaa"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,0 0),(1 1,1 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,1 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,0 0))"),
+ "mlmldf21"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,0 0),(2 2,2 2),(1 1,1 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,1 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,0 0),(2 2,2 2))"),
+ "mlmldf22"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,0 0),(1 1,1 1),(2 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,1 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,0 0),(2 2,2 2))"),
+ "mlmldf23"
+ );
+}
+#endif // BOOST_GEOMETRY_TEST_NO_DEGENERATE
+
+
+
+
+BOOST_AUTO_TEST_CASE( test_difference_ml_ml_spikes )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / MULTILINESTRING DIFFERENCE"
+ << " (WITH SPIKES) ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef multi_linestring_type ML;
+
+ typedef test_difference_of_geometries<ML, ML, ML> tester;
+
+ // the following test cases concern linestrings with spikes
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,9 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(9 0,10 0))"),
+ "mlmldf-spikes-01"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((9 0,1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(9 0,10 0))"),
+ "mlmldf-spikes-02"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,9 0,2 0,8 0,3 0,7 0,4 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(9 0,10 0))"),
+ "mlmldf-spikes-03"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,3 0,2 0,4 0,3 0,5 0,4 0,6 0,\
+ 5 0,7 0,6 0,8 0,7 0,9 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(9 0,10 0))"),
+ "mlmldf-spikes-04"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(7 0,8 0,7 0),\
+ (9 1,9 0,9 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(6 0,7 0),(8 0,10 0))"),
+ "mlmldf-spikes-05"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(7 0,8 0,7 0),\
+ (9 0,9 2,9 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(6 0,7 0),(8 0,10 0))"),
+ "mlmldf-spikes-05a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(9 0,6 0,8 0),\
+ (11 0,8 0,12 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0))"),
+ "mlmldf-spikes-06"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,0 0,-2 0),(11 0,10 0,12 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ "mlmldf-spikes-07"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,-2 -2),(11 1,10 0,12 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ "mlmldf-spikes-07a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(11 0,10 0,12 0),\
+ (7 5,7 0,8 0,6.5 0,8.5 0,8.5 5))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(6 0,6.5 0),(8.5 0,10 0))"),
+ "mlmldf-spikes-08"
+ );
+
+ // now the first geometry has a spike
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,7 0,4 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,8 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(8 0,10 0))"),
+ "mlmldf-spikes-09"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,7 0,4 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(9 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,7 0,4 0,9 0))"),
+ "mlmldf-spikes-09a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,7 0,4 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0),(9 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,7 0,5 0),(5 0,9 0))"),
+ "mlmldf-spikes-09b"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,7 0,4 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0),(6 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,6 0),(6 0,5 0),(5 0,6 0))"),
+ "mlmldf-spikes-09c"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,8 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(8 0,10 0,8 0))"),
+ "mlmldf-spikes-10"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,8 0,4 0),(2 0,9 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(9 0,10 0,9 0))"),
+ "mlmldf-spikes-11"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((11 1,10 0,12 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ "mlmldf-spikes-12"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((11 -1,10 0,12 -2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ "mlmldf-spikes-12a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((11 0,10 0,12 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ "mlmldf-spikes-13"
+ );
+
+ // the following three tests have been discussed with Adam
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 2,1 1,1 2))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1))"),
+ "mlmldf-spikes-14"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 0,0 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,1 0,2 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,0 0))"),
+ "mlmldf-spikes-15"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,1 1,2 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1))"),
+ "mlmldf-spikes-16"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1))"),
+ from_wkt<ML>("MULTILINESTRING((2 1,1 1,2 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,1 1))"),
+ "mlmldf-spikes-17"
+ );
+
+ // test cases sent by Adam on the mailing list (equal slikes)
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 1,0 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1,0 0))"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "mlmldf-spikes-18"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 1,0 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,0 0,1 1))"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "mlmldf-spikes-19"
+ );
+}
diff --git a/libs/geometry/test/algorithms/set_operations/difference/difference_pl_pl.cpp b/libs/geometry/test/algorithms/set_operations/difference/difference_pl_pl.cpp
new file mode 100644
index 000000000..1e3326451
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/difference/difference_pl_pl.cpp
@@ -0,0 +1,226 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#include <iostream>
+
+#ifndef BOOST_TEST_MODULE
+#define BOOST_TEST_MODULE test_difference_pointlike_pointlike
+#endif
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+#define BOOST_GEOMETRY_DEBUG_TURNS
+#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
+#endif
+
+#include <boost/test/included/unit_test.hpp>
+
+#include "../test_set_ops_pl_pl.hpp"
+
+#include <boost/geometry/geometries/multi_point.hpp>
+
+typedef bg::model::point<double,2,bg::cs::cartesian> point_type;
+typedef bg::model::multi_point<point_type> multi_point_type;
+
+
+
+//===========================================================================
+//===========================================================================
+//===========================================================================
+
+
+BOOST_AUTO_TEST_CASE( test_difference_point_point )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** POINT / POINT DIFFERENCE ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef point_type P;
+ typedef multi_point_type MP;
+
+ typedef test_set_op_of_pointlike_geometries
+ <
+ P, P, MP, bg::overlay_difference
+ > tester;
+
+ tester::apply
+ (from_wkt<P>("POINT(0 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(1 1)"),
+ "ppdf01");
+
+ tester::apply
+ (from_wkt<P>("POINT(0 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "ppdf02");
+}
+
+
+BOOST_AUTO_TEST_CASE( test_difference_multipoint_point )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTIPOINT / POINT DIFFERENCE ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef point_type P;
+ typedef multi_point_type MP;
+
+ typedef test_set_op_of_pointlike_geometries
+ <
+ MP, P, MP, bg::overlay_difference
+ > tester;
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(1 1)"),
+ "mppdf01");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mppdf02");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT(0 0,0 0)"),
+ from_wkt<MP>("MULTIPOINT(1 1)"),
+ "mppdf03");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mppdf04");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0)"),
+ from_wkt<MP>("MULTIPOINT(1 1)"),
+ "mppdf05");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0)"),
+ from_wkt<P>("POINT(1 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0,0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mppdf06");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(1 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mppdf07");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ "mppdf08");
+}
+
+
+BOOST_AUTO_TEST_CASE( test_difference_point_multipoint )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** POINT / MULTIPOINT DIFFERENCE ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef point_type P;
+ typedef multi_point_type MP;
+
+ typedef test_set_op_of_pointlike_geometries
+ <
+ P, MP, MP, bg::overlay_difference
+ > tester;
+
+ tester::apply
+ (from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(1 0,1 1,1 1)"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(1 0,1 1,1 1)"),
+ "pmpdf01");
+
+ tester::apply
+ (from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,1 1,0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT(1 0,1 1)"),
+ "pmpdf02");
+
+ tester::apply
+ (from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "pmpdf03");
+}
+
+
+BOOST_AUTO_TEST_CASE( test_difference_multipoint_multipoint )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTIPOINT / MULTIPOINT DIFFERENCE ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef multi_point_type MP;
+
+ typedef test_set_op_of_pointlike_geometries
+ <
+ MP, MP, MP, bg::overlay_difference
+ > tester;
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(2 2,3 3,0 0,0 0,2 2,1 1,1 1,1 0,1 0)"),
+ from_wkt<MP>("MULTIPOINT(1 0,1 1,1 1,4 4)"),
+ from_wkt<MP>("MULTIPOINT(2 2,3 3,0 0,0 0,2 2)"),
+ from_wkt<MP>("MULTIPOINT(4 4)"),
+ "mpmpdf01");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,1 1,1 0,1 1)"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,1 1,0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mpmpdf02");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,1 1,0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,1 1,0 0)"),
+ "mpmpdf03");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,1 1,1 0,1 1)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT(0 0,1 1,1 0,1 1)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mpmpdf04");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mpmpdf05");
+}
diff --git a/libs/geometry/test/algorithms/set_operations/difference/multi_difference.cpp b/libs/geometry/test/algorithms/set_operations/difference/multi_difference.cpp
new file mode 100644
index 000000000..cad1b9bff
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/difference/multi_difference.cpp
@@ -0,0 +1,229 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Unit Test
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <string>
+
+// If defined, tests are run without rescaling-to-integer or robustness policy
+// This multi_difference currently contains no tests for double which then fail
+// #define BOOST_GEOMETRY_NO_ROBUSTNESS
+
+//#define HAVE_TTMATH
+//#define BOOST_GEOMETRY_DEBUG_ASSEMBLE
+//#define BOOST_GEOMETRY_CHECK_WITH_SQLSERVER
+
+//#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
+//#define BOOST_GEOMETRY_DEBUG_FOLLOW
+//#define BOOST_GEOMETRY_DEBUG_TRAVERSE
+
+
+#include "test_difference.hpp"
+#include <algorithms/test_overlay.hpp>
+#include <algorithms/overlay/multi_overlay_cases.hpp>
+
+#include <boost/geometry/multi/algorithms/correct.hpp>
+#include <boost/geometry/multi/algorithms/intersection.hpp>
+#include <boost/geometry/multi/algorithms/within.hpp> // only for testing #77
+
+#include <boost/geometry/geometries/point_xy.hpp>
+#include <boost/geometry/multi/geometries/multi_point.hpp>
+#include <boost/geometry/multi/geometries/multi_linestring.hpp>
+#include <boost/geometry/multi/geometries/multi_polygon.hpp>
+
+#include <boost/geometry/multi/io/wkt/read.hpp>
+
+template <typename Ring, typename Polygon, typename MultiPolygon>
+void test_areal()
+{
+ test_one<Polygon, MultiPolygon, MultiPolygon>("simplex_multi",
+ case_multi_simplex[0], case_multi_simplex[1],
+ 5, 21, 5.58, 4, 17, 2.58);
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_multi_no_ip",
+ case_multi_no_ip[0], case_multi_no_ip[1],
+ 2, 12, 24.0, 2, 12, 34.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_multi_2",
+ case_multi_2[0], case_multi_2[1],
+ 2, 15, 19.6, 2, 13, 33.6);
+
+ test_one<Polygon, MultiPolygon, Polygon>("simplex_multi_mp_p",
+ case_multi_simplex[0], case_single_simplex,
+ 5, 21, 5.58, 4, 17, 2.58);
+ test_one<Polygon, Ring, MultiPolygon>("simplex_multi_r_mp",
+ case_single_simplex, case_multi_simplex[0],
+ 4, 17, 2.58, 5, 21, 5.58);
+ test_one<Ring, MultiPolygon, Polygon>("simplex_multi_mp_r",
+ case_multi_simplex[0], case_single_simplex,
+ 5, 21, 5.58, 4, 17, 2.58);
+
+ // Constructed cases for multi/touch/equal/etc
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_61_multi",
+ case_61_multi[0], case_61_multi[1],
+ 2, 10, 2, 2, 10, 2);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_62_multi",
+ case_62_multi[0], case_62_multi[1],
+ 0, 0, 0, 1, 5, 1);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_63_multi",
+ case_63_multi[0], case_63_multi[1],
+ 0, 0, 0, 1, 5, 1);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_64_multi",
+ case_64_multi[0], case_64_multi[1],
+ 1, 5, 1, 1, 5, 1);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_65_multi",
+ case_65_multi[0], case_65_multi[1],
+ 0, 0, 0, 2, 10, 3);
+ /* TODO: fix
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_72_multi",
+ case_72_multi[0], case_72_multi[1],
+ 3, 13, 1.65, 3, 17, 6.15);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_77_multi",
+ case_77_multi[0], case_77_multi[1],
+ 6, 31, 7, 6, 36, 13);
+ */
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_78_multi",
+ case_78_multi[0], case_78_multi[1],
+ 1, 5, 1.0, 1, 5, 1.0);
+
+ // Ticket on GGL list 2011/10/25
+ // to mix polygon/multipolygon in call to difference
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20111025_vd_pp",
+ ggl_list_20111025_vd[0], ggl_list_20111025_vd[1],
+ 1, 4, 8.0, 1, 4, 12.5);
+ test_one<Polygon, Polygon, MultiPolygon>("ggl_list_20111025_vd_pm",
+ ggl_list_20111025_vd[0], ggl_list_20111025_vd[3],
+ 1, 4, 8.0, 1, 4, 12.5);
+ test_one<Polygon, MultiPolygon, Polygon>("ggl_list_20111025_vd_mp",
+ ggl_list_20111025_vd[2], ggl_list_20111025_vd[1],
+ 1, 4, 8.0, 1, 4, 12.5);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20111025_vd_mm",
+ ggl_list_20111025_vd[2], ggl_list_20111025_vd[3],
+ 1, 4, 8.0, 1, 4, 12.5);
+
+ // Second case
+ // This can be tested with this SQL for SQL-Server
+ /*
+ with viewy as (select geometry::STGeomFromText(
+ 'POLYGON((5 0,5 4,8 4,8 0,5 0))',0) as p,
+ geometry::STGeomFromText(
+ 'MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((4 0,4 2,6 2,6 0,4 0)))',0) as q)
+ select
+ p.STDifference(q).STArea(),p.STDifference(q).STNumGeometries(),p.STDifference(q) as p_min_q,
+ q.STDifference(p).STArea(),q.STDifference(p).STNumGeometries(),q.STDifference(p) as q_min_p,
+ p.STSymDifference(q).STArea(),q.STSymDifference(p) as p_xor_q
+ from viewy
+
+ Outputting:
+ 10, 1, <WKB>, 6, 2, <WKB>, 16, <WKB>
+ */
+
+ test_one<Polygon, Polygon, MultiPolygon>("ggl_list_20111025_vd_2",
+ ggl_list_20111025_vd_2[0], ggl_list_20111025_vd_2[1],
+ 1, 7, 10.0, 2, 10, 6.0);
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120915_h2_a",
+ ggl_list_20120915_h2[0], ggl_list_20120915_h2[1],
+ 2, 13, 17.0, 0, 0, 0.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120915_h2_b",
+ ggl_list_20120915_h2[0], ggl_list_20120915_h2[2],
+ 2, 13, 17.0, 0, 0, 0.0);
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120221_volker",
+ ggl_list_20120221_volker[0], ggl_list_20120221_volker[1],
+ 2, 12, 7962.66, 1, 18, 2775258.93,
+ 0.001);
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ticket_9081",
+ ticket_9081[0], ticket_9081[1],
+ 2, 28, 0.0907392476356186, 4, 25, 0.126018011439877,
+ 0.001);
+
+ /* TODO: fix
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_101_multi",
+ case_101_multi[0], case_101_multi[1],
+ 5, 23, 4.75, 5, 40, 12.75);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_102_multi",
+ case_102_multi[0], case_102_multi[1],
+ 2, 8, 0.75, 6, 25, 3.75);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_107_multi",
+ case_107_multi[0], case_107_multi[1],
+ 2, 11, 2.25, 3, 14, 3.0);
+ */
+ /*
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_1",
+ case_recursive_boxes_1[0], case_recursive_boxes_1[1],
+ 1, 1, 1, 1, 1, 1);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_2",
+ case_recursive_boxes_2[0], case_recursive_boxes_2[1],
+ 1, 1, 1, 1, 1, 1);
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_3",
+ case_recursive_boxes_3[0], case_recursive_boxes_3[1],
+ 1, 1, 1, 1, 1, 1);
+*/
+}
+
+template <typename MultiPolygon, typename MultiLineString>
+void test_areal_linear()
+{
+ typedef typename boost::range_value<MultiPolygon>::type Polygon;
+ typedef typename boost::range_value<MultiLineString>::type LineString;
+ typedef typename bg::point_type<Polygon>::type Point;
+ typedef bg::model::ring<Point> Ring;
+
+ test_one_lp<LineString, LineString, MultiPolygon>("case_mp_ls_1", "LINESTRING(2 0,2 5)", case_multi_simplex[0], 2, 4, 1.30);
+ test_one_lp<LineString, MultiLineString, Polygon>("case_p_mls_1", "MULTILINESTRING((2 0,2 5),(3 0,3 5))", case_single_simplex, 3, 6, 2.5);
+ test_one_lp<LineString, MultiLineString, MultiPolygon>("case_mp_mls_1", "MULTILINESTRING((2 0,2 5),(3 0,3 5))", case_multi_simplex[0], 5, 10, 3.1666667);
+ test_one_lp<LineString, MultiLineString, Ring>("case_r_mls_1", "MULTILINESTRING((2 0,2 5),(3 0,3 5))", case_single_simplex, 3, 6, 2.5);
+
+ // Collinear cases, with multiple turn points at the same location
+ test_one_lp<LineString, LineString, MultiPolygon>("case_mp_ls_2a", "LINESTRING(1 0,1 1,2 1,2 0)", "MULTIPOLYGON(((0 0,0 1,1 1,1 0,0 0)),((1 1,1 2,2 2,2 1,1 1)))", 1, 2, 1.0);
+ test_one_lp<LineString, LineString, MultiPolygon>("case_mp_ls_2b", "LINESTRING(1 0,1 1,2 1,2 0)", "MULTIPOLYGON(((1 1,1 2,2 2,2 1,1 1)),((0 0,0 1,1 1,1 0,0 0)))", 1, 2, 1.0);
+
+ test_one_lp<LineString, LineString, MultiPolygon>("case_mp_ls_3",
+ "LINESTRING(6 6,6 7,7 7,7 6,8 6,8 7,9 7,9 6)",
+ "MULTIPOLYGON(((5 7,5 8,6 8,6 7,5 7)),((6 6,6 7,7 7,7 6,6 6)),((8 8,9 8,9 7,8 7,7 7,7 8,8 8)))", 2, 5, 3.0);
+
+ return;
+
+ // TODO: this case contains collinearities and should still be solved
+ test_one_lp<LineString, LineString, MultiPolygon>("case_mp_ls_4",
+ "LINESTRING(0 5,0 6,1 6,1 5,2 5,2 6,3 6,3 5,3 4,3 3,2 3,2 4,1 4,1 3,0 3,0 4)",
+ "MULTIPOLYGON(((0 2,0 3,1 2,0 2)),((2 5,3 6,3 5,2 5)),((1 5,1 6,2 6,2 5,1 5)),((2 3,2 4,3 4,2 3)),((0 3,1 4,1 3,0 3)),((4 3,3 3,3 5,4 5,4 4,4 3)))", 5, 11, 6.0);
+}
+
+
+template <typename P>
+void test_all()
+{
+ //typedef bg::model::box<P> box;
+ typedef bg::model::ring<P> ring;
+ typedef bg::model::polygon<P> polygon;
+ typedef bg::model::multi_polygon<polygon> multi_polygon;
+ test_areal<ring, polygon, multi_polygon>();
+ test_areal_linear<multi_polygon, bg::model::multi_linestring<bg::model::linestring<P> > >();
+}
+
+
+int test_main(int, char* [])
+{
+ test_all<bg::model::d2::point_xy<double > >();
+
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+ test_all<bg::model::d2::point_xy<float> >();
+
+#if defined(HAVE_TTMATH)
+ std::cout << "Testing TTMATH" << std::endl;
+ test_all<bg::model::d2::point_xy<ttmath_big> >();
+#endif
+
+#endif
+
+ return 0;
+}
diff --git a/libs/geometry/test/algorithms/set_operations/difference/multi_difference_spike.cpp b/libs/geometry/test/algorithms/set_operations/difference/multi_difference_spike.cpp
new file mode 100644
index 000000000..56a909262
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/difference/multi_difference_spike.cpp
@@ -0,0 +1,105 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Unit Test
+
+// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#include <boost/geometry.hpp>
+#include <boost/geometry/geometries/geometries.hpp>
+#include <boost/geometry/geometries/point_xy.hpp>
+#include <boost/geometry/multi/geometries/multi_geometries.hpp>
+
+#include "test_difference.hpp"
+
+
+template <typename P, bool ClockWise, bool Closed>
+void test_spikes_in_ticket_8364()
+{
+ // See: https://svn.boost.org/trac/boost/ticket/8364
+ //_TPolygon<T> polygon( "MULTIPOLYGON(((1031 1056,3232 1056,3232 2856,1031 2856)))" );
+ //polygon -= _TPolygon<T>( "MULTIPOLYGON(((1032 1458,1032 1212,2136 2328,3234 2220,3234 2412,2136 2646)))" );
+ //polygon -= _TPolygon<T>( "MULTIPOLYGON(((1032 1764,1032 1458,2136 2646,3234 2412,3234 2532,2136 2790)))" );
+ // RESULTS OF ABOVE IS USED IN STEP 3 BELOW
+ //polygon -= _TPolygon<T>( "MULTIPOLYGON(((1032 2130,1032 1764,2052 2712)),((3234 2580,2558 2690,3234 2532)),((2558 2690,2136 2790,2052 2712,2136 2760)))" ); USED IN STEP 3
+ //polygon -= _TPolygon<T>( "MULTIPOLYGON(((1032 2556,1032 2130,1778 2556)),((3234 2580,2136 2760,1778 2556,3234 2556)))" ); USED IN STEP 4
+ // NOTE: polygons below are closed and clockwise
+
+ typedef typename bg::coordinate_type<P>::type ct;
+ typedef bg::model::polygon<P, ClockWise, Closed> polygon;
+ typedef bg::model::multi_polygon<polygon> multi_polygon;
+
+ // The difference of polygons below result in a spike. The spike should be there, it is also generated in ttmath,
+ // and (e.g.) in SQL Server. However, using int-coordinates, the spike makes the polygon invalid. Therefore it is now (since August 2013) checked and removed.
+
+ // So using int's, the spike is removed automatically. Therefore there is one polygon less, and less points. Also area differs
+ test_one<polygon, multi_polygon, multi_polygon>("ticket_8364_step3",
+ "MULTIPOLYGON(((3232 2532,2136 2790,1032 1764,1032 1458,1032 1212,2136 2328,3232 2220,3232 1056,1031 1056,1031 2856,3232 2856,3232 2532)))",
+ "MULTIPOLYGON(((1032 2130,2052 2712,1032 1764,1032 2130)),((3234 2580,3234 2532,2558 2690,3234 2580)),((2558 2690,2136 2760,2052 2712,2136 2790,2558 2690)))",
+ 2,
+ if_typed<ct, int>(19, 22),
+ if_typed<ct, int>(2775595.5, 2775256.487954), // SQL Server: 2775256.47588724
+ 3,
+ -1, // don't check point-count
+ if_typed<ct, int>(7907.0, 7810.487954)); // SQL Server: 7810.48711165739
+
+ test_one<polygon, multi_polygon, multi_polygon>("ticket_8364_step4",
+ "MULTIPOLYGON(((2567 2688,2136 2790,2052 2712,1032 2130,1032 1764,1032 1458,1032 1212,2136 2328,3232 2220,3232 1056,1031 1056,1031 2856,3232 2856,3232 2580,2567 2688)))",
+ "MULTIPOLYGON(((1032 2556,1778 2556,1032 2130,1032 2556)),((3234 2580,3234 2556,1778 2556,2136 2760,3234 2580)))",
+ 1,
+ if_typed<ct, int>(17, 20),
+ if_typed<ct, int>(2616125.0, 2616029.559567), // SQL Server: 2616029.55616044
+ 1,
+ if_typed<ct, int>(9, 11),
+ if_typed<ct, int>(161211.5, 161054.559567)); // SQL Server: 161054.560110092
+}
+
+template <typename P, bool ClockWise, bool Closed>
+void test_spikes_in_ticket_8365()
+{
+ // See: https://svn.boost.org/trac/boost/ticket/8365
+ // NOTE: polygons below are closed and clockwise
+
+ typedef typename bg::coordinate_type<P>::type ct;
+ typedef bg::model::polygon<P, ClockWise, Closed> polygon;
+ typedef bg::model::multi_polygon<polygon> multi_polygon;
+
+ test_one<polygon, multi_polygon, multi_polygon>("ticket_8365_step2",
+ "MULTIPOLYGON(((971 2704,971 1402,4640 1402,3912 1722,3180 2376,3912 1884,4643 1402,5395 1402,5395 3353,971 3353,971 2865,1704 3348)))",
+ "MULTIPOLYGON(((5388 1560,4650 1722,3912 1884,4650 1398)),((2442 3186,1704 3348,966 2700,1704 3024)))",
+ if_typed<ct, int>(1, 2),
+ if_typed<ct, int>(17, 21),
+ if_typed<ct, int>(7974930.5, 7975207.6047877), // SQL Server:
+ 2,
+ -1,
+ if_typed<ct, int>(196.5, 197.1047877)); // SQL Server:
+}
+
+
+
+
+
+int test_main(int, char* [])
+{
+ test_spikes_in_ticket_8364<bg::model::d2::point_xy<double>, true, true>();
+ test_spikes_in_ticket_8364<bg::model::d2::point_xy<double>, false, false>();
+ test_spikes_in_ticket_8365<bg::model::d2::point_xy<double>, true, true>();
+ test_spikes_in_ticket_8365<bg::model::d2::point_xy<double>, false, false>();
+
+ test_spikes_in_ticket_8364<bg::model::d2::point_xy<int>, true, true>();
+ test_spikes_in_ticket_8364<bg::model::d2::point_xy<int>, false, false>();
+ test_spikes_in_ticket_8365<bg::model::d2::point_xy<int>, true, true >();
+ test_spikes_in_ticket_8365<bg::model::d2::point_xy<int>, false, false >();
+
+#ifdef HAVE_TTMATH
+ std::cout << "Testing TTMATH" << std::endl;
+ test_spikes_in_ticket_8364<bg::model::d2::point_xy<ttmath_big>, true, true>();
+ test_spikes_in_ticket_8365<bg::model::d2::point_xy<ttmath_big>, true, true>();
+#endif
+
+ return 0;
+}
+
diff --git a/libs/geometry/test/algorithms/set_operations/difference/test_difference.hpp b/libs/geometry/test/algorithms/set_operations/difference/test_difference.hpp
new file mode 100644
index 000000000..e3cda5d95
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/difference/test_difference.hpp
@@ -0,0 +1,330 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Unit Test
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_TEST_DIFFERENCE_HPP
+#define BOOST_GEOMETRY_TEST_DIFFERENCE_HPP
+
+#include <fstream>
+#include <iomanip>
+
+#include <geometry_test_common.hpp>
+
+#include <boost/core/ignore_unused.hpp>
+#include <boost/foreach.hpp>
+
+#include <boost/range/algorithm/copy.hpp>
+
+#include <boost/geometry/algorithms/correct.hpp>
+#include <boost/geometry/algorithms/difference.hpp>
+#include <boost/geometry/algorithms/sym_difference.hpp>
+
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+
+#include <boost/geometry/geometries/geometries.hpp>
+
+
+#include <boost/geometry/multi/geometries/multi_point.hpp>
+#include <boost/geometry/multi/geometries/multi_linestring.hpp>
+#include <boost/geometry/multi/geometries/multi_polygon.hpp>
+
+#include <boost/geometry/strategies/strategies.hpp>
+
+#include <boost/geometry/io/wkt/wkt.hpp>
+
+
+#if defined(TEST_WITH_SVG)
+# define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
+# define BOOST_GEOMETRY_DEBUG_IDENTIFIER
+# include <boost/geometry/io/svg/svg_mapper.hpp>
+# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
+#endif
+
+
+template <typename Output, typename G1, typename G2>
+void difference_output(std::string const& caseid, G1 const& g1, G2 const& g2, Output const& output)
+{
+ boost::ignore_unused(caseid, g1, g2, output);
+
+#if defined(TEST_WITH_SVG)
+ {
+ typedef typename bg::coordinate_type<G1>::type coordinate_type;
+ typedef typename bg::point_type<G1>::type point_type;
+
+ std::ostringstream filename;
+ filename << "difference_"
+ << caseid << "_"
+ << string_from_type<coordinate_type>::name()
+#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ << "_no_rob"
+#endif
+ << ".svg";
+
+ std::ofstream svg(filename.str().c_str());
+
+ bg::svg_mapper<point_type> mapper(svg, 500, 500);
+
+ mapper.add(g1);
+ mapper.add(g2);
+
+ mapper.map(g1, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:3");
+ mapper.map(g2, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:3");
+
+
+ for (typename Output::const_iterator it = output.begin(); it != output.end(); ++it)
+ {
+ mapper.map(*it,
+ //sym ? "fill-opacity:0.2;stroke-opacity:0.4;fill:rgb(255,255,0);stroke:rgb(255,0,255);stroke-width:8" :
+ "fill-opacity:0.2;stroke-opacity:0.4;fill:rgb(255,0,0);stroke:rgb(255,0,255);stroke-width:8");
+ }
+ }
+#endif
+}
+
+template <typename OutputType, typename G1, typename G2>
+void test_difference(std::string const& caseid, G1 const& g1, G2 const& g2,
+ int expected_count, int expected_point_count,
+ double expected_area,
+ double percentage = 0.0001,
+ bool sym = false)
+{
+ typedef typename bg::coordinate_type<G1>::type coordinate_type;
+ boost::ignore_unused<coordinate_type>();
+
+ std::vector<OutputType> clip;
+
+ if (sym)
+ {
+ bg::sym_difference(g1, g2, clip);
+ }
+ else
+ {
+ bg::difference(g1, g2, clip);
+ }
+
+ typename bg::default_area_result<G1>::type area = 0;
+ std::size_t n = 0;
+ for (typename std::vector<OutputType>::iterator it = clip.begin();
+ it != clip.end();
+ ++it)
+ {
+ if (expected_point_count >= 0)
+ {
+ n += bg::num_points(*it);
+ }
+
+ area += bg::area(*it);
+ }
+
+ difference_output(caseid, g1, g2, clip);
+
+#ifndef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+ {
+ // Test inserter functionality
+ // Test if inserter returns output-iterator (using Boost.Range copy)
+ typedef typename bg::point_type<G1>::type point_type;
+ typedef typename bg::rescale_policy_type<point_type>::type
+ rescale_policy_type;
+
+ rescale_policy_type rescale_policy
+ = bg::get_rescale_policy<rescale_policy_type>(g1, g2);
+
+ std::vector<OutputType> inserted, array_with_one_empty_geometry;
+ array_with_one_empty_geometry.push_back(OutputType());
+ if (sym)
+ {
+ boost::copy(array_with_one_empty_geometry,
+ bg::detail::sym_difference::sym_difference_insert<OutputType>
+ (g1, g2, rescale_policy, std::back_inserter(inserted)));
+ }
+ else
+ {
+ boost::copy(array_with_one_empty_geometry,
+ bg::detail::difference::difference_insert<OutputType>(
+ g1, g2, rescale_policy, std::back_inserter(inserted)));
+ }
+
+ BOOST_CHECK_EQUAL(boost::size(clip), boost::size(inserted) - 1);
+ }
+#endif
+
+
+
+#if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST)
+ if (expected_point_count >= 0)
+ {
+ BOOST_CHECK_MESSAGE(bg::math::abs(int(n) - expected_point_count) < 3,
+ "difference: " << caseid
+ << " #points expected: " << expected_point_count
+ << " detected: " << n
+ << " type: " << (type_for_assert_message<G1, G2>())
+ );
+ }
+
+ if (expected_count >= 0)
+ {
+ BOOST_CHECK_MESSAGE(int(clip.size()) == expected_count,
+ "difference: " << caseid
+ << " #outputs expected: " << expected_count
+ << " detected: " << clip.size()
+ << " type: " << (type_for_assert_message<G1, G2>())
+ );
+ }
+
+ BOOST_CHECK_CLOSE(area, expected_area, percentage);
+#endif
+
+
+}
+
+
+#ifdef BOOST_GEOMETRY_CHECK_WITH_POSTGIS
+static int counter = 0;
+#endif
+
+
+template <typename OutputType, typename G1, typename G2>
+void test_one(std::string const& caseid,
+ std::string const& wkt1, std::string const& wkt2,
+ int expected_count1,
+ int expected_point_count1,
+ double expected_area1,
+
+ int expected_count2,
+ int expected_point_count2,
+ double expected_area2,
+
+ double percentage = 0.0001)
+{
+#ifdef BOOST_GEOMETRY_CHECK_WITH_SQLSERVER
+ std::cout
+ << "-- " << caseid << std::endl
+ << "with qu as (" << std::endl
+ << "select geometry::STGeomFromText('" << wkt1 << "',0) as p," << std::endl
+ << "geometry::STGeomFromText('" << wkt2 << "',0) as q)" << std::endl
+ << "select " << std::endl
+ << " p.STDifference(q).STNumGeometries() as cnt1,p.STDifference(q).STNumPoints() as pcnt1,p.STDifference(q).STArea() as area1," << std::endl
+ << " q.STDifference(p).STNumGeometries() as cnt2,q.STDifference(p).STNumPoints() as pcnt2,q.STDifference(p).STArea() as area2," << std::endl
+ << " p.STDifference(q) as d1,q.STDifference(p) as d2 from qu" << std::endl << std::endl;
+#endif
+
+
+ G1 g1;
+ bg::read_wkt(wkt1, g1);
+
+ G2 g2;
+ bg::read_wkt(wkt2, g2);
+
+ bg::correct(g1);
+ bg::correct(g2);
+
+ test_difference<OutputType>(caseid + "_a", g1, g2,
+ expected_count1, expected_point_count1,
+ expected_area1, percentage);
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+ return;
+#endif
+ test_difference<OutputType>(caseid + "_b", g2, g1,
+ expected_count2, expected_point_count2,
+ expected_area2, percentage);
+ test_difference<OutputType>(caseid + "_s", g1, g2,
+ expected_count1 + expected_count2,
+ expected_point_count1 >= 0 && expected_point_count2 >= 0
+ ? (expected_point_count1 + expected_point_count2) : -1,
+ expected_area1 + expected_area2,
+ percentage, true);
+
+
+#ifdef BOOST_GEOMETRY_CHECK_WITH_POSTGIS
+ std::cout
+ << (counter > 0 ? "union " : "")
+ << "select " << counter++
+ << ", '" << caseid << "' as caseid"
+ << ", ST_NumPoints(ST_Difference(ST_GeomFromText('" << wkt1 << "'), "
+ << " ST_GeomFromText('" << wkt2 << "'))) "
+ << ", ST_NumGeometries(ST_Difference(ST_GeomFromText('" << wkt1 << "'), "
+ << " ST_GeomFromText('" << wkt2 << "'))) "
+ << ", ST_Area(ST_Difference(ST_GeomFromText('" << wkt1 << "'), "
+ << " ST_GeomFromText('" << wkt2 << "'))) "
+ //<< ", " << expected_area1 << " as expected_area_a"
+ //<< ", " << expected_count1 << " as expected_count_a"
+ << ", ST_NumPoints(ST_Difference(ST_GeomFromText('" << wkt2 << "'), "
+ << " ST_GeomFromText('" << wkt1 << "'))) "
+ << ", ST_NumGeometries(ST_Difference(ST_GeomFromText('" << wkt2 << "'), "
+ << " ST_GeomFromText('" << wkt1 << "'))) "
+ << ", ST_Area(ST_Difference(ST_GeomFromText('" << wkt2 << "'), "
+ << " ST_GeomFromText('" << wkt1 << "'))) "
+ //<< ", " << expected_area2 << " as expected_area_b"
+ //<< ", " << expected_count2 << " as expected_count_b"
+ << ", ST_NumPoints(ST_SymDifference(ST_GeomFromText('" << wkt1 << "'), "
+ << " ST_GeomFromText('" << wkt2 << "'))) "
+ << ", ST_NumGeometries(ST_SymDifference(ST_GeomFromText('" << wkt1 << "'), "
+ << " ST_GeomFromText('" << wkt2 << "'))) "
+ << ", ST_Area(ST_SymDifference(ST_GeomFromText('" << wkt1 << "'), "
+ << " ST_GeomFromText('" << wkt2 << "'))) "
+ //<< ", " << expected_area1 + expected_area2 << " as expected_area_s"
+ //<< ", " << expected_count1 + expected_count2 << " as expected_count_s"
+ << std::endl;
+#endif
+
+}
+
+template <typename OutputType, typename G1, typename G2>
+void test_one_lp(std::string const& caseid,
+ std::string const& wkt1, std::string const& wkt2,
+ std::size_t expected_count,
+ int expected_point_count,
+ double expected_length)
+{
+ G1 g1;
+ bg::read_wkt(wkt1, g1);
+
+ G2 g2;
+ bg::read_wkt(wkt2, g2);
+
+ bg::correct(g1);
+
+ std::vector<OutputType> pieces;
+ bg::difference(g1, g2, pieces);
+
+ typename bg::default_length_result<G1>::type length = 0;
+ std::size_t n = 0;
+ std::size_t piece_count = 0;
+ for (typename std::vector<OutputType>::iterator it = pieces.begin();
+ it != pieces.end();
+ ++it)
+ {
+ if (expected_point_count >= 0)
+ {
+ n += bg::num_points(*it);
+ }
+ piece_count++;
+ length += bg::length(*it);
+ }
+
+ BOOST_CHECK_MESSAGE(piece_count == expected_count,
+ "difference: " << caseid
+ << " #outputs expected: " << expected_count
+ << " detected: " << pieces.size()
+ );
+
+ if (expected_point_count >= 0)
+ {
+ BOOST_CHECK_EQUAL(n, std::size_t(expected_point_count));
+ }
+
+ BOOST_CHECK_CLOSE(length, expected_length, 0.001);
+
+ std::string lp = "lp_";
+ difference_output(lp + caseid, g1, g2, pieces);
+}
+
+
+
+#endif
diff --git a/libs/geometry/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp b/libs/geometry/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp
new file mode 100644
index 000000000..cbfd9fa5d
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/difference/test_difference_linear_linear.hpp
@@ -0,0 +1,154 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#ifndef BOOST_GEOMETRY_TEST_DIFFERENCE_LINEAR_LINEAR_HPP
+#define BOOST_GEOMETRY_TEST_DIFFERENCE_LINEAR_LINEAR_HPP
+
+#include <limits>
+
+#include <boost/geometry/geometry.hpp>
+#include "../test_set_ops_linear_linear.hpp"
+#include <from_wkt.hpp>
+#include <to_svg.hpp>
+
+
+//==================================================================
+//==================================================================
+// difference of (linear) geometries
+//==================================================================
+//==================================================================
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename MultiLineString
+>
+class test_difference_of_geometries
+{
+private:
+ static inline void base_test(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiLineString const& mls_diff,
+ std::string const& case_id,
+ double tolerance,
+ bool test_vector_and_deque = true,
+ bool reverse_output_for_checking = false)
+ {
+ static bool vector_deque_already_tested = false;
+
+ typedef typename boost::range_value<MultiLineString>::type LineString;
+ typedef std::vector<LineString> linestring_vector;
+ typedef std::deque<LineString> linestring_deque;
+
+ MultiLineString mls_output;
+
+ linestring_vector ls_vector_output;
+ linestring_deque ls_deque_output;
+
+ bg::difference(geometry1, geometry2, mls_output);
+
+ if ( reverse_output_for_checking )
+ {
+ bg::reverse(mls_output);
+ }
+
+ BOOST_CHECK_MESSAGE( equals::apply(mls_diff, mls_output, tolerance),
+ "case id: " << case_id
+ << ", difference L/L: " << bg::wkt(geometry1)
+ << " " << bg::wkt(geometry2)
+ << " -> Expected: " << bg::wkt(mls_diff)
+ << " computed: " << bg::wkt(mls_output) );
+
+ set_operation_output("difference", case_id,
+ geometry1, geometry2, mls_output);
+
+ if ( !vector_deque_already_tested && test_vector_and_deque )
+ {
+ vector_deque_already_tested = true;
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl;
+ std::cout << "Testing with vector and deque as output container..."
+ << std::endl;
+#endif
+ bg::difference(geometry1, geometry2, ls_vector_output);
+ bg::difference(geometry1, geometry2, ls_deque_output);
+
+ BOOST_CHECK(multilinestring_equals
+ <
+ false
+ >::apply(mls_diff, ls_vector_output, tolerance));
+
+ BOOST_CHECK(multilinestring_equals
+ <
+ false
+ >::apply(mls_diff, ls_deque_output, tolerance));
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Done!" << std::endl << std::endl;
+#endif
+ }
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl;
+ std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl;
+ std::cout << "difference : " << bg::wkt(mls_output) << std::endl;
+ std::cout << "expected difference : " << bg::wkt(mls_diff) << std::endl;
+ std::cout << std::endl;
+ std::cout << "************************************" << std::endl;
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+ }
+
+
+public:
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiLineString const& mls_diff,
+ std::string const& case_id,
+ double tolerance
+ = std::numeric_limits<double>::epsilon())
+ {
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "test case: " << case_id << std::endl;
+ std::stringstream sstr;
+ sstr << "svgs/" << case_id << ".svg";
+#ifdef TEST_WITH_SVG
+ to_svg(geometry1, geometry2, sstr.str());
+#endif
+#endif
+
+ Geometry1 rg1(geometry1);
+ bg::reverse<Geometry1>(rg1);
+
+ Geometry2 rg2(geometry2);
+ bg::reverse<Geometry2>(rg2);
+
+ test_get_turns_ll_invariance<>::apply(geometry1, geometry2);
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl
+ << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
+ << std::endl << std::endl;
+#endif
+ test_get_turns_ll_invariance<>::apply(rg1, geometry2);
+
+ base_test(geometry1, geometry2, mls_diff, case_id, tolerance);
+ base_test(geometry1, rg2, mls_diff, case_id, tolerance, false);
+ base_test(rg1, geometry2, mls_diff, case_id, tolerance, false, true);
+ base_test(rg1, rg2, mls_diff, case_id, tolerance, false, true);
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+ }
+};
+
+
+#endif // BOOST_GEOMETRY_TEST_DIFFERENCE_LINEAR_LINEAR_HPP
diff --git a/libs/geometry/test/algorithms/set_operations/intersection/Jamfile.v2 b/libs/geometry/test/algorithms/set_operations/intersection/Jamfile.v2
new file mode 100644
index 000000000..b21302819
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/intersection/Jamfile.v2
@@ -0,0 +1,23 @@
+# Boost.Geometry (aka GGL, Generic Geometry Library)
+#
+# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+# Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+# Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+#
+# This file was modified by Oracle on 2014.
+# Modifications copyright (c) 2014, Oracle and/or its affiliates.
+#
+# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+#
+# Use, modification and distribution is subject to the Boost Software License,
+# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+test-suite boost-geometry-algorithms-intersection
+ :
+ [ run intersection.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE ]
+ [ run intersection_linear_linear.cpp ]
+ [ run intersection_pl_pl.cpp ]
+ [ run multi_intersection.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE ]
+ ;
diff --git a/libs/geometry/test/algorithms/set_operations/intersection/intersection.cpp b/libs/geometry/test/algorithms/set_operations/intersection/intersection.cpp
new file mode 100644
index 000000000..e15c3ee54
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/intersection/intersection.cpp
@@ -0,0 +1,693 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Unit Test
+
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2015.
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <climits>
+#include <iostream>
+#include <string>
+
+// If defined, tests are run without rescaling-to-integer or robustness policy
+// Test which would fail then are disabled automatically
+// #define BOOST_GEOMETRY_NO_ROBUSTNESS
+
+#include <boost/config.hpp>
+#include <boost/core/ignore_unused.hpp>
+
+#include <boost/geometry/geometries/point_xy.hpp>
+#include <boost/geometry/geometries/register/linestring.hpp>
+
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/rational.hpp>
+
+#include "test_intersection.hpp"
+#include <algorithms/test_overlay.hpp>
+
+#include <algorithms/overlay/overlay_cases.hpp>
+
+#include <test_common/test_point.hpp>
+#include <test_common/with_pointer.hpp>
+#include <test_geometries/custom_segment.hpp>
+
+
+BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::vector)
+
+
+template <typename Polygon>
+void test_areal()
+{
+ typedef typename bg::coordinate_type<Polygon>::type ct;
+ bool const ccw = bg::point_order<Polygon>::value == bg::counterclockwise;
+ bool const open = bg::closure<Polygon>::value == bg::open;
+
+ test_one<Polygon, Polygon, Polygon>("simplex_with_empty_1",
+ simplex_normal[0], polygon_empty,
+ 0, 0, 0.0);
+ test_one<Polygon, Polygon, Polygon>("simplex_with_empty_2",
+ polygon_empty, simplex_normal[0],
+ 0, 0, 0.0);
+
+ test_one<Polygon, Polygon, Polygon>("simplex_normal",
+ simplex_normal[0], simplex_normal[1],
+ 1, 7, 5.47363293);
+ test_one<Polygon, Polygon, Polygon>("star_ring", example_star, example_ring,
+ 1, 18, 2.80983);
+
+ test_one<Polygon, Polygon, Polygon>("star_poly", example_star, example_polygon,
+ 1, 0, // CLN: 23 points, other types: 22 point (one is merged)
+ 2.5020508);
+ test_one<Polygon, Polygon, Polygon>("first_within_second1",
+ first_within_second[0], first_within_second[1],
+ 1, 5, 1.0);
+
+ test_one<Polygon, Polygon, Polygon>("first_within_second2",
+ first_within_second[1], first_within_second[0],
+ 1, 5, 1.0);
+
+ test_one<Polygon, Polygon, Polygon>("first_within_hole_of_second",
+ first_within_hole_of_second[0], first_within_hole_of_second[1],
+ 0, 0, 0.0);
+
+ // Two forming new hole
+ test_one<Polygon, Polygon, Polygon>("new_hole",
+ new_hole[0], new_hole[1],
+ 2, 10, 2.0);
+
+ // Two identical
+ test_one<Polygon, Polygon, Polygon>("identical",
+ identical[0], identical[1],
+ 1, 5, 1.0);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_exterior_and_interiors_winded",
+ intersect_exterior_and_interiors_winded[0], intersect_exterior_and_interiors_winded[1],
+ 1, 14, 25.2166667);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_holes_disjoint",
+ intersect_holes_disjoint[0], intersect_holes_disjoint[1],
+ 1, 15, 18.0);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_holes_intersect",
+ intersect_holes_intersect[0], intersect_holes_intersect[1],
+ 1, 14, 18.25);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_holes_intersect_and_disjoint",
+ intersect_holes_intersect_and_disjoint[0], intersect_holes_intersect_and_disjoint[1],
+ 1, 19, 17.25);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_holes_intersect_and_touch",
+ intersect_holes_intersect_and_touch[0], intersect_holes_intersect_and_touch[1],
+ 1, 23, 17.25);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_holes_new_ring",
+ intersect_holes_new_ring[0], intersect_holes_new_ring[1],
+ 2, 23, 122.1039);
+
+ test_one<Polygon, Polygon, Polygon>("winded",
+ winded[0], winded[1],
+ 1, 22, 40.0);
+
+ test_one<Polygon, Polygon, Polygon>("within_holes_disjoint",
+ within_holes_disjoint[0], within_holes_disjoint[1],
+ 1, 15, 23.0);
+
+ test_one<Polygon, Polygon, Polygon>("side_side",
+ side_side[0], side_side[1],
+ 0, 0, 0.0);
+
+ test_one<Polygon, Polygon, Polygon>("two_bends",
+ two_bends[0], two_bends[1],
+ 1, 7, 24.0);
+
+ test_one<Polygon, Polygon, Polygon>("star_comb_15",
+ star_comb_15[0], star_comb_15[1],
+ 28, 150, 189.952883);
+
+ test_one<Polygon, Polygon, Polygon>("simplex_normal",
+ simplex_normal[0], simplex_normal[1],
+ 1, 7, 5.47363293);
+
+ test_one<Polygon, Polygon, Polygon>("distance_zero",
+ distance_zero[0], distance_zero[1],
+ 1, 0 /* f: 4, other: 5 */, 0.29516139, 0.01);
+
+ test_one<Polygon, Polygon, Polygon>("equal_holes_disjoint",
+ equal_holes_disjoint[0], equal_holes_disjoint[1],
+ 1, 20, 81 - 2 * 3 * 3 - 3 * 7);
+
+ test_one<Polygon, Polygon, Polygon>("only_hole_intersections1",
+ only_hole_intersections[0], only_hole_intersections[1],
+ 1, 21, 178.090909);
+ test_one<Polygon, Polygon, Polygon>("only_hole_intersection2",
+ only_hole_intersections[0], only_hole_intersections[2],
+ 1, 21, 149.090909);
+
+ test_one<Polygon, Polygon, Polygon>("fitting",
+ fitting[0], fitting[1],
+ 0, 0, 0);
+
+ test_one<Polygon, Polygon, Polygon>("crossed",
+ crossed[0], crossed[1],
+ 3, 0, 1.5);
+
+ test_one<Polygon, Polygon, Polygon>("pie_2_3_23_0",
+ pie_2_3_23_0[0], pie_2_3_23_0[1],
+ 1, 4, 163292.679042133, 0.1);
+
+ test_one<Polygon, Polygon, Polygon>("isovist",
+ isovist1[0], isovist1[1],
+ 1, 19, 88.19203,
+ if_typed_tt<ct>(0.01, 0.1));
+
+ // SQL Server gives: 88.1920416352664
+ // PostGIS gives: 88.19203677911
+
+ test_one<Polygon, Polygon, Polygon>("geos_1",
+ geos_1[0], geos_1[1],
+ 1, -1, 3461.0214843, 0.005); // MSVC 14 reports 3461.025390625
+
+ test_one<Polygon, Polygon, Polygon>("geos_2",
+ geos_2[0], geos_2[1],
+ 0, 0, 0.0);
+ test_one<Polygon, Polygon, Polygon>("geos_3",
+ geos_3[0], geos_3[1],
+ 0, -0, 0.0);
+ test_one<Polygon, Polygon, Polygon>("geos_4",
+ geos_4[0], geos_4[1],
+ 1, -1, 0.08368849);
+
+
+ if ( BOOST_GEOMETRY_CONDITION(! ccw && open) )
+ {
+ // Pointcount for ttmath/double (both 5) or float (4)
+ // double returns 5 (since method append_no_dups_or_spikes)
+ // but not for ccw/open. Those cases has to be adapted once, anyway,
+ // because for open always one point too much is generated...
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20110306_javier",
+ ggl_list_20110306_javier[0], ggl_list_20110306_javier[1],
+ 1, if_typed<ct, float>(4, 5),
+ 0.6649875,
+ if_typed<ct, float>(1.0, 0.01));
+ }
+
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20110307_javier",
+ ggl_list_20110307_javier[0], ggl_list_20110307_javier[1],
+ 1, 4, 0.4, 0.01);
+
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20110627_phillip",
+ ggl_list_20110627_phillip[0], ggl_list_20110627_phillip[1],
+ 1, if_typed_tt<ct>(6, 5), 11151.6618);
+
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20110716_enrico",
+ ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1],
+ 3, 16, 35723.8506317139);
+
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20131119_james",
+ ggl_list_20131119_james[0], ggl_list_20131119_james[1],
+ 1, 4, 6.6125873045, 0.1);
+
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20140223_shalabuda",
+ ggl_list_20140223_shalabuda[0], ggl_list_20140223_shalabuda[1],
+ 1, 4, 3.77106);
+
+#if 0
+ // TODO: fix this testcase, it should give 0 but instead it gives one of the input polygons
+ // Mailed to the Boost.Geometry list on 2014/03/21 by 7415963@gmail.com
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20140321_7415963",
+ ggl_list_20140321_7415963[0], ggl_list_20140321_7415963[1],
+ 0, 0, 0, 0.1);
+#endif
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1],
+ 1, 4, 0.00029437899183903937, 0.01);
+#endif
+
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1],
+ 1, 0, 2.914213562373);
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<Polygon, Polygon, Polygon>("ticket_8254", ticket_8254[0], ticket_8254[1],
+ 1, 4, 3.6334e-08, 0.01);
+#endif
+
+ test_one<Polygon, Polygon, Polygon>("ticket_6958", ticket_6958[0], ticket_6958[1],
+ 1, 4, 4.34355e-05, 0.01);
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<Polygon, Polygon, Polygon>("ticket_8652", ticket_8652[0], ticket_8652[1],
+ 1, 4, 0.0003);
+#endif
+
+ test_one<Polygon, Polygon, Polygon>("ticket_8310a", ticket_8310a[0], ticket_8310a[1],
+ 1, 5, 0.3843747);
+ test_one<Polygon, Polygon, Polygon>("ticket_8310b", ticket_8310b[0], ticket_8310b[1],
+ 1, 5, 0.3734379);
+ test_one<Polygon, Polygon, Polygon>("ticket_8310c", ticket_8310c[0], ticket_8310c[1],
+ 1, 5, 0.4689541);
+
+ test_one<Polygon, Polygon, Polygon>("ticket_9081_15",
+ ticket_9081_15[0], ticket_9081_15[1],
+ 1, 4, 0.0068895780745301394);
+
+ test_one<Polygon, Polygon, Polygon>("ticket_10108_a",
+ ticket_10108_a[0], ticket_10108_a[1],
+ 0, 0, 0.0);
+ test_one<Polygon, Polygon, Polygon>("ticket_10108_b",
+ ticket_10108_b[0], ticket_10108_b[1],
+ 0, 0, 0.0);
+
+ test_one<Polygon, Polygon, Polygon>("ticket_10747_a",
+ ticket_10747_a[0], ticket_10747_a[1],
+ 1, 4, 70368744177664);
+ test_one<Polygon, Polygon, Polygon>("ticket_10747_b",
+ ticket_10747_b[0], ticket_10747_b[1],
+ 1, 4, 7036874417766400);
+ test_one<Polygon, Polygon, Polygon>("ticket_10747_c",
+ ticket_10747_c[0], ticket_10747_c[1],
+ 1, 4, 17592186044416);
+ test_one<Polygon, Polygon, Polygon>("ticket_10747_d",
+ ticket_10747_d[0], ticket_10747_d[1],
+ 1, 4, 703687777321);
+ test_one<Polygon, Polygon, Polygon>("ticket_10747_e",
+ ticket_10747_e[0], ticket_10747_e[1],
+ 1, 4, 7.0368748575710959e-15);
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<Polygon, Polygon, Polygon>("ticket_9563", ticket_9563[0], ticket_9563[1],
+ 1, 8, 129.90381);
+#endif
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<Polygon, Polygon, Polygon>("buffer_mp1", buffer_mp1[0], buffer_mp1[1],
+ 1, 31, 2.271707796);
+#endif
+
+ test_one<Polygon, Polygon, Polygon>("buffer_mp2", buffer_mp2[0], buffer_mp2[1],
+ 1, 29, 0.457126);
+
+ return;
+
+
+ test_one<Polygon, Polygon, Polygon>(
+ "polygon_pseudo_line",
+ "Polygon((0 0,0 4,4 4,4 0,0 0))",
+ "Polygon((2 -2,2 -1,2 6,2 -2))",
+ 5, 22, 1.1901714);
+}
+
+template <typename Polygon, typename Box>
+void test_areal_clip()
+{
+ test_one<Polygon, Box, Polygon>("boxring", example_box, example_ring,
+ 2, 12, 1.09125);
+ test_one<Polygon, Polygon, Box>("boxring2", example_ring,example_box,
+ 2, 12, 1.09125);
+
+ test_one<Polygon, Box, Polygon>("boxpoly", example_box, example_polygon,
+ 3, 19, 0.840166);
+
+ test_one<Polygon, Box, Polygon>("poly1", example_box,
+ "POLYGON((3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2))",
+ 2, 12, 1.09125);
+
+ test_one<Polygon, Box, Polygon>("clip_poly2", example_box,
+ "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,5.3 2.5,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))",
+ 2, 12, 1.00375);
+
+ test_one<Polygon, Box, Polygon>("clip_poly3", example_box,
+ "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 1.2,4.9 0.8,2.9 0.7,2 1.3))",
+ 2, 12, 1.00375);
+
+ test_one<Polygon, Box, Polygon>("clip_poly4", example_box,
+ "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))",
+ 2, 16, 0.860892);
+
+ test_one<Polygon, Box, Polygon>("clip_poly5", example_box,
+ "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 1.2,2.9 0.7,2 1.3))",
+ 2, 11, 0.7575961);
+
+ test_one<Polygon, Box, Polygon>("clip_poly6", example_box,
+ "POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.0 3.0,5.0 2.0,2.9 0.7,2 1.3))",
+ 2, 13, 1.0744456);
+
+ test_one<Polygon, Box, Polygon>("clip_poly7", "Box(0 0, 3 3)",
+ "POLYGON((2 2, 1 4, 2 4, 3 3, 2 2))",
+ 1, 4, 0.75);
+}
+
+
+template <typename Box>
+void test_boxes(std::string const& wkt1, std::string const& wkt2, double expected_area, bool expected_result)
+{
+ Box box1, box2;
+ bg::read_wkt(wkt1, box1);
+ bg::read_wkt(wkt2, box2);
+
+ Box box_out;
+ bool detected = bg::intersection(box1, box2, box_out);
+ typename bg::default_area_result<Box>::type area = bg::area(box_out);
+
+ BOOST_CHECK_EQUAL(detected, expected_result);
+ if (detected && expected_result)
+ {
+ BOOST_CHECK_CLOSE(area, expected_area, 0.01);
+ }
+}
+
+template <typename P>
+void test_point_output()
+{
+ typedef bg::model::linestring<P> linestring;
+ typedef bg::model::polygon<P> polygon;
+ typedef bg::model::box<P> box;
+ //typedef bg::model::segment<P> segment;
+
+ test_point_output<polygon, polygon>(simplex_normal[0], simplex_normal[1], 6);
+ test_point_output<box, polygon>("box(1 1,6 4)", simplex_normal[0], 4);
+ test_point_output<linestring, polygon>("linestring(0 2,6 2)", simplex_normal[0], 2);
+ // NYI because of sectionize:
+ // test_point_output<segment, polygon>("linestring(0 2,6 2)", simplex_normal[0], 2);
+ // NYI because needs special treatment:
+ // test_point_output<box, box>("box(0 0,4 4)", "box(2 2,6 6)", 2);
+}
+
+
+template <typename Polygon, typename LineString>
+void test_areal_linear()
+{
+ std::string const poly_simplex = "POLYGON((1 1,1 3,3 3,3 1,1 1))";
+
+ test_one_lp<LineString, Polygon, LineString>("simplex", poly_simplex, "LINESTRING(0 2,4 2)", 1, 2, 2.0);
+ test_one_lp<LineString, Polygon, LineString>("case2", poly_simplex, "LINESTRING(0 1,4 3)", 1, 2, sqrt(5.0));
+ test_one_lp<LineString, Polygon, LineString>("case3", "POLYGON((2 0,2 5,5 5,5 0,2 0))", "LINESTRING(0 1,1 2,3 2,4 3,6 3,7 4)", 1, 4, 2 + sqrt(2.0));
+ test_one_lp<LineString, Polygon, LineString>("case4", "POLYGON((0 0,0 4,2 4,2 0,0 0))", "LINESTRING(1 1,3 2,1 3)", 2, 4, sqrt(5.0));
+
+ test_one_lp<LineString, Polygon, LineString>("case5", poly_simplex, "LINESTRING(0 1,3 4)", 1, 2, sqrt(2.0));
+ test_one_lp<LineString, Polygon, LineString>("case6", "POLYGON((2 0,2 4,3 4,3 1,4 1,4 3,5 3,5 1,6 1,6 3,7 3,7 1,8 1,8 3,9 3,9 0,2 0))", "LINESTRING(1 1,10 3)", 4, 8,
+ // Pieces are 1 x 2/9:
+ 4.0 * sqrt(1.0 + 4.0/81.0));
+ test_one_lp<LineString, Polygon, LineString>("case7", poly_simplex, "LINESTRING(1.5 1.5,2.5 2.5)", 1, 2, sqrt(2.0));
+ test_one_lp<LineString, Polygon, LineString>("case8", poly_simplex, "LINESTRING(1 0,2 0)", 0, 0, 0.0);
+
+ std::string const poly_9 = "POLYGON((1 1,1 4,4 4,4 1,1 1))";
+ test_one_lp<LineString, Polygon, LineString>("case9", poly_9, "LINESTRING(0 1,1 2,2 2)", 1, 2, 1.0);
+ test_one_lp<LineString, Polygon, LineString>("case10", poly_9, "LINESTRING(0 1,1 2,0 2)", 0, 0, 0.0);
+ test_one_lp<LineString, Polygon, LineString>("case11", poly_9, "LINESTRING(2 2,4 2,3 3)", 1, 3, 2.0 + sqrt(2.0));
+ test_one_lp<LineString, Polygon, LineString>("case12", poly_9, "LINESTRING(2 3,4 4,5 6)", 1, 2, sqrt(5.0));
+
+ test_one_lp<LineString, Polygon, LineString>("case13", poly_9, "LINESTRING(3 2,4 4,2 3)", 1, 3, 2.0 * sqrt(5.0));
+ test_one_lp<LineString, Polygon, LineString>("case14", poly_9, "LINESTRING(5 6,4 4,6 5)", 0, 0, 0.0);
+ test_one_lp<LineString, Polygon, LineString>("case15", poly_9, "LINESTRING(0 2,1 2,1 3,0 3)", 1, 2, 1.0);
+ test_one_lp<LineString, Polygon, LineString>("case16", poly_9, "LINESTRING(2 2,1 2,1 3,2 3)", 1, 4, 3.0);
+
+ std::string const angly = "LINESTRING(2 2,2 1,4 1,4 2,5 2,5 3,4 3,4 4,5 4,3 6,3 5,2 5,2 6,0 4)";
+ // PROPERTIES CHANGED BY switch_to_integer
+ // TODO test_one_lp<LineString, Polygon, LineString>("case17", "POLYGON((1 1,1 5,4 5,4 1,1 1))", angly, 3, 8, 6.0);
+ test_one_lp<LineString, Polygon, LineString>("case18", "POLYGON((1 1,1 5,5 5,5 1,1 1))", angly, 2, 12, 10.0 + sqrt(2.0));
+ test_one_lp<LineString, Polygon, LineString>("case19", poly_9, "LINESTRING(1 2,1 3,0 3)", 1, 2, 1.0);
+ test_one_lp<LineString, Polygon, LineString>("case20", poly_9, "LINESTRING(1 2,1 3,2 3)", 1, 3, 2.0);
+
+ // PROPERTIES CHANGED BY switch_to_integer
+ // TODO test_one_lp<LineString, Polygon, LineString>("case21", poly_9, "LINESTRING(1 2,1 4,4 4,4 1,2 1,2 2)", 1, 6, 11.0);
+
+ // Compile test - arguments in any order:
+ test_one<LineString, Polygon, LineString>("simplex", poly_simplex, "LINESTRING(0 2,4 2)", 1, 2, 2.0);
+ test_one<LineString, LineString, Polygon>("simplex", "LINESTRING(0 2,4 2)", poly_simplex, 1, 2, 2.0);
+
+ typedef typename bg::point_type<Polygon>::type Point;
+ test_one<LineString, bg::model::ring<Point>, LineString>("simplex", poly_simplex, "LINESTRING(0 2,4 2)", 1, 2, 2.0);
+
+}
+
+template <typename P>
+void test_all()
+{
+ typedef bg::model::linestring<P> linestring;
+ typedef bg::model::polygon<P> polygon;
+ typedef bg::model::box<P> box;
+ typedef bg::model::segment<P> segment;
+
+ typedef bg::model::polygon<P, false> polygon_ccw;
+ typedef bg::model::polygon<P, true, false> polygon_open;
+ typedef bg::model::polygon<P, false, false> polygon_ccw_open;
+ boost::ignore_unused<polygon_ccw, polygon_open, polygon_ccw_open>();
+
+ std::string clip = "box(2 2,8 8)";
+
+ test_areal_linear<polygon, linestring>();
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+ test_areal_linear<polygon_open, linestring>();
+ test_areal_linear<polygon_ccw, linestring>();
+ test_areal_linear<polygon_ccw_open, linestring>();
+#endif
+
+ // Test polygons clockwise and counter clockwise
+ test_areal<polygon>();
+
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+ test_areal<polygon_ccw>();
+ test_areal<polygon_open>();
+ test_areal<polygon_ccw_open>();
+#endif
+
+ test_areal_clip<polygon, box>();
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+ test_areal_clip<polygon_ccw, box>();
+#endif
+
+#if defined(TEST_FAIL_DIFFERENT_ORIENTATIONS)
+ // Should NOT compile
+ // NOTE: this can probably be relaxed later on.
+ test_one<polygon, polygon_ccw, polygon>("simplex_normal",
+ simplex_normal[0], simplex_normal[1],
+ 1, 7, 5.47363293);
+ // Output ccw, nyi (should be just reversing afterwards)
+ test_one<polygon, polygon, polygon_ccw>("simplex_normal",
+ simplex_normal[0], simplex_normal[1],
+ 1, 7, 5.47363293);
+#endif
+
+ // Basic check: box/linestring, is clipping OK? should compile in any order
+ test_one<linestring, linestring, box>("llb", "LINESTRING(0 0,10 10)", clip, 1, 2, sqrt(2.0 * 6.0 * 6.0));
+ test_one<linestring, box, linestring>("lbl", clip, "LINESTRING(0 0,10 10)", 1, 2, sqrt(2.0 * 6.0 * 6.0));
+
+ // Box/segment
+ test_one<linestring, segment, box>("lsb", "LINESTRING(0 0,10 10)", clip, 1, 2, sqrt(2.0 * 6.0 * 6.0));
+ test_one<linestring, box, segment>("lbs", clip, "LINESTRING(0 0,10 10)", 1, 2, sqrt(2.0 * 6.0 * 6.0));
+
+ // Completely inside
+ test_one<linestring, linestring, box>("llbi", "LINESTRING(3 3,7 7)", clip, 1, 2, sqrt(2.0 * 4.0 * 4.0));
+
+ // Completely outside
+ test_one<linestring, linestring, box>("llbo", "LINESTRING(9 9,10 10)", clip, 0, 0, 0);
+
+ // Touching with point (-> output linestring with ONE point)
+ //std::cout << "Note: the output line is degenerate! Might be removed!" << std::endl;
+ test_one<linestring, linestring, box>("llb_touch", "LINESTRING(8 8,10 10)", clip, 1, 1, 0.0);
+
+ // Along border
+ test_one<linestring, linestring, box>("llb_along", "LINESTRING(2 2,2 8)", clip, 1, 2, 6);
+
+ // Outputting two lines (because of 3-4-5 constructions (0.3,0.4,0.5)
+ // which occur 4 times, the length is expected to be 2.0)
+ test_one<linestring, linestring, box>("llb_2", "LINESTRING(1.7 1.6,2.3 2.4,2.9 1.6,3.5 2.4,4.1 1.6)", clip, 2, 6, 4 * 0.5);
+
+ // linear
+ test_one<P, linestring, linestring>("llp1", "LINESTRING(0 0,1 1)", "LINESTRING(0 1,1 0)", 1, 1, 0);
+ test_one<P, segment, segment>("ssp1", "LINESTRING(0 0,1 1)", "LINESTRING(0 1,1 0)", 1, 1, 0);
+ test_one<P, linestring, linestring>("llp2", "LINESTRING(0 0,1 1)", "LINESTRING(0 0,2 2)", 2, 2, 0);
+
+ // polygons outputing points
+ //test_one<P, polygon, polygon>("ppp1", simplex_normal[0], simplex_normal[1], 1, 7, 5.47363293);
+
+ test_boxes<box>("box(2 2,8 8)", "box(4 4,10 10)", 16, true);
+ test_boxes<box>("box(2 2,8 7)", "box(4 4,10 10)", 12, true);
+ test_boxes<box>("box(2 2,8 7)", "box(14 4,20 10)", 0, false);
+ test_boxes<box>("box(2 2,4 4)", "box(4 4,8 8)", 0, true);
+
+ test_point_output<P>();
+
+
+ /*
+ test_one<polygon, box, polygon>(99, "box(115041.10 471900.10, 118334.60 474523.40)",
+ "POLYGON ((115483.40 474533.40, 116549.40 474059.20, 117199.90 473762.50, 117204.90 473659.50, 118339.40 472796.90, 118334.50 472757.90, 118315.10 472604.00, 118344.60 472520.90, 118277.90 472419.10, 118071.40 472536.80, 118071.40 472536.80, 117943.10 472287.70, 117744.90 472248.40, 117708.00 472034.50, 117481.90 472056.90, 117481.90 472056.90, 117272.30 471890.10, 117077.90 472161.20, 116146.60 473054.50, 115031.10 473603.30, 115483.40 474533.40))",
+ 1, 26, 3727690.74);
+ */
+
+}
+
+void test_pointer_version()
+{
+ std::vector<test::test_point_xy*> ln;
+ test::test_point_xy* p;
+ p = new test::test_point_xy; p->x = 0; p->y = 0; ln.push_back(p);
+ p = new test::test_point_xy; p->x = 10; p->y = 10; ln.push_back(p);
+
+ bg::model::box<bg::model::d2::point_xy<double> > box;
+ bg::assign_values(box, 2, 2, 8, 8);
+
+ typedef bg::model::linestring<bg::model::d2::point_xy<double> > output_type;
+ std::vector<output_type> clip;
+ bg::detail::intersection::intersection_insert<output_type>(box, ln, std::back_inserter(clip));
+
+ double length = 0;
+ int n = 0;
+ for (std::vector<output_type>::const_iterator it = clip.begin();
+ it != clip.end(); ++it)
+ {
+ length += bg::length(*it);
+ n += bg::num_points(*it);
+ }
+
+ BOOST_CHECK_EQUAL(clip.size(), 1u);
+ BOOST_CHECK_EQUAL(n, 2);
+ BOOST_CHECK_CLOSE(length, sqrt(2.0 * 6.0 * 6.0), 0.001);
+
+ for (unsigned int i = 0; i < ln.size(); i++)
+ {
+ delete ln[i];
+ }
+}
+
+
+template <typename P>
+void test_exception()
+{
+ typedef bg::model::polygon<P> polygon;
+
+ try
+ {
+ // Define polygon with a spike (= invalid)
+ std::string spike = "POLYGON((0 0,0 4,2 4,2 6,2 4,4 4,4 0,0 0))";
+
+ test_one<polygon, polygon, polygon>("with_spike",
+ simplex_normal[0], spike,
+ 0, 0, 0);
+ }
+ catch(bg::overlay_invalid_input_exception const& )
+ {
+ return;
+ }
+ BOOST_CHECK_MESSAGE(false, "No exception thrown");
+}
+
+template <typename Point>
+void test_rational()
+{
+ typedef bg::model::polygon<Point> polygon;
+ test_one<polygon, polygon, polygon>("simplex_normal",
+ simplex_normal[0], simplex_normal[1],
+ 1, 7, 5.47363293);
+}
+
+
+template <typename P>
+void test_boxes_per_d(P const& min1, P const& max1, P const& min2, P const& max2, bool expected_result)
+{
+ typedef bg::model::box<P> box;
+
+ box box_out;
+ bool detected = bg::intersection(box(min1, max1), box(min2, max2), box_out);
+
+ BOOST_CHECK_EQUAL(detected, expected_result);
+ if ( detected && expected_result )
+ {
+ BOOST_CHECK( bg::equals(box_out, box(min2,max1)) );
+ }
+}
+
+template <typename CoordinateType>
+void test_boxes_nd()
+{
+ typedef bg::model::point<CoordinateType, 1, bg::cs::cartesian> p1;
+ typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> p2;
+ typedef bg::model::point<CoordinateType, 3, bg::cs::cartesian> p3;
+
+ test_boxes_per_d(p1(0), p1(5), p1(3), p1(6), true);
+ test_boxes_per_d(p2(0,0), p2(5,5), p2(3,3), p2(6,6), true);
+ test_boxes_per_d(p3(0,0,0), p3(5,5,5), p3(3,3,3), p3(6,6,6), true);
+}
+
+template <typename CoordinateType>
+void test_ticket_10868(std::string const& wkt_out)
+{
+ typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type;
+ typedef bg::model::polygon
+ <
+ point_type, /*ClockWise*/false, /*Closed*/false
+ > polygon_type;
+ typedef bg::model::multi_polygon<polygon_type> multipolygon_type;
+
+ polygon_type polygon1;
+ bg::read_wkt(ticket_10868[0], polygon1);
+ polygon_type polygon2;
+ bg::read_wkt(ticket_10868[1], polygon2);
+
+ multipolygon_type multipolygon_out;
+ bg::intersection(polygon1, polygon2, multipolygon_out);
+ std::stringstream stream;
+ stream << bg::wkt(multipolygon_out);
+
+ BOOST_CHECK_EQUAL(stream.str(), wkt_out);
+
+ test_one<polygon_type, polygon_type, polygon_type>("ticket_10868",
+ ticket_10868[0], ticket_10868[1],
+ 1, 7, 20266195244586);
+}
+
+int test_main(int, char* [])
+{
+ test_all<bg::model::d2::point_xy<double> >();
+
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+ test_all<bg::model::d2::point_xy<float> >();
+
+#if defined(HAVE_TTMATH)
+ std::cout << "Testing TTMATH" << std::endl;
+ test_all<bg::model::d2::point_xy<ttmath_big> >();
+#endif
+
+#endif
+
+ test_exception<bg::model::d2::point_xy<double> >();
+ test_pointer_version();
+#if ! defined(BOOST_GEOMETRY_RESCALE_TO_ROBUST)
+ test_rational<bg::model::d2::point_xy<boost::rational<int> > >();
+#endif
+
+ test_boxes_nd<double>();
+
+#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS
+ // ticket #10868 still fails for 32-bit integers
+ test_ticket_10868<int32_t>("MULTIPOLYGON(((33520458 6878575,33480192 14931538,31446819 18947953,30772384 19615678,30101303 19612322,30114725 16928001,33520458 6878575)))");
+
+#if !defined(BOOST_NO_INT64) || defined(BOOST_HAS_INT64_T) || defined(BOOST_HAS_MS_INT64)
+ test_ticket_10868<int64_t>("MULTIPOLYGON(((33520458 6878575,33480192 14931538,31446819 18947953,30772384 19615678,30101303 19612322,30114725 16928001,33520458 6878575)))");
+#endif
+
+ if (BOOST_GEOMETRY_CONDITION(sizeof(long) * CHAR_BIT >= 64))
+ {
+ test_ticket_10868<long>("MULTIPOLYGON(((33520458 6878575,33480192 14931538,31446819 18947953,30772384 19615678,30101303 19612322,30114725 16928001,33520458 6878575)))");
+ }
+
+#if defined(BOOST_HAS_LONG_LONG)
+ test_ticket_10868<boost::long_long_type>("MULTIPOLYGON(((33520458 6878575,33480192 14931538,31446819 18947953,30772384 19615678,30101303 19612322,30114725 16928001,33520458 6878575)))");
+#endif
+#endif
+
+ return 0;
+}
diff --git a/libs/geometry/test/algorithms/set_operations/intersection/intersection_linear_linear.cpp b/libs/geometry/test/algorithms/set_operations/intersection/intersection_linear_linear.cpp
new file mode 100644
index 000000000..0102edc5c
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/intersection/intersection_linear_linear.cpp
@@ -0,0 +1,1617 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#include <iostream>
+
+#ifndef BOOST_TEST_MODULE
+#define BOOST_TEST_MODULE test_intersection_linear_linear
+#endif
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+#define BOOST_GEOMETRY_DEBUG_TURNS
+#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
+#endif
+
+#include <boost/test/included/unit_test.hpp>
+
+#include "test_intersection_linear_linear.hpp"
+
+#include <boost/geometry/geometries/linestring.hpp>
+#include <boost/geometry/multi/geometries/multi_linestring.hpp>
+#include <boost/geometry/algorithms/intersection.hpp>
+
+typedef bg::model::point<double,2,bg::cs::cartesian> point_type;
+typedef bg::model::segment<point_type> segment_type;
+typedef bg::model::linestring<point_type> linestring_type;
+typedef bg::model::multi_linestring<linestring_type> multi_linestring_type;
+
+
+
+//===========================================================================
+//===========================================================================
+//===========================================================================
+
+
+BOOST_AUTO_TEST_CASE( test_intersection_linestring_linestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** LINESTRING / LINESTRING INTERSECTION ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_intersection_of_geometries<L, L, ML> tester;
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 1,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(0 2,1 1,2 1,3 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 1))"),
+ "lli00");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,5 0)"),
+ from_wkt<L>("LINESTRING(3 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((3 0,4 0))"),
+ "lli01");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,6 0)"),
+ from_wkt<ML>("MULTILINESTRING((3 0,4 0))"),
+ "lli01-2");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,6 0)"),
+ from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,4 0))"),
+ "lli01-4");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<L>("LINESTRING(0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((4 0,5 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0),(2 0),(4 0,5 0),(6.5 0),(8 0))"),
+#endif
+ "lli01-6");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-20 0,20 0)"),
+ from_wkt<L>("LINESTRING(0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((4 0,5 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0),(2 0),(4 0,5 0),(6.5 0),(8 0))"),
+#endif
+ "lli01-7");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<L>("LINESTRING(2 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0))"),
+ "lli01-8");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0)"),
+ from_wkt<L>("LINESTRING(4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "lli01-10");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0)"),
+ from_wkt<L>("LINESTRING(2 0,5 0)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING()"),
+#else
+ from_wkt<ML>("MULTILINESTRING((2 0))"),
+#endif
+ "lli01-11");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((3 0,4 0))"),
+ "lli01-11a");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((3 0,4 0))"),
+ "lli01-11b");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,5 0,10 0)"),
+ from_wkt<L>("LINESTRING(2 0,6 0,8 0)"),
+ from_wkt<ML>("MULTILINESTRING((2 0,5 0,8 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,6 0,8 0))"),
+ "lli01-11c");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,6 0)"),
+ from_wkt<L>("LINESTRING(2 0,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((2 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0,5 0))"),
+ "lli01-12");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,5 5,10 5,15 0)"),
+ from_wkt<L>("LINESTRING(-1 6,0 5,15 5)"),
+ from_wkt<ML>("MULTILINESTRING((5 5,10 5))"),
+ "lli02");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,20 0))"),
+ "lli03");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,5 5,10 5,15 0,20 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,20 0))"),
+ "lli04");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,25 1)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0)(15 0,20 0))"),
+ "lli05");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,20 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,30 0))"),
+ "lli05-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,20 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,30 0))"),
+ "lli06");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,25 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,20 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,25 0,30 0))"),
+ "lli07");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,20 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,19 0,30 0))"),
+ "lli08");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,20 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,30 0))"),
+ "lli09");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,20 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(15 0,30 0))"),
+ "lli10");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,20 0,\
+ 30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0),(3 0,4 0),\
+ (15 0,20 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0),(3 0,4 0),\
+ (15 0,30 0))"),
+ "lli11");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0),\
+ (3 0,4 0),(15 0,30 0))"),
+ "lli11-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0,3 1))"),
+ "lli12");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<L>("LINESTRING(3 1,2 0,0 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((3 1,2 0,0 0))"),
+ "lli12-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 5,4 0)"),
+ from_wkt<L>("LINESTRING(1 0,2 1,3 5,4 0,5 10)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,2 1,3 5,4 0))"),
+ "lli13");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 0,2.5 0,3 1)"),
+ from_wkt<L>("LINESTRING(0 0,2 0,2.5 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0,2.5 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0,2.5 0,3 1))"),
+ "lli14");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 5,4 0)"),
+ from_wkt<L>("LINESTRING(1 0,2 1,3 5)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,2 1,3 5))"),
+ "lli15");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(0.5 0,1 0,3 2,4 5)"),
+ from_wkt<ML>("MULTILINESTRING((0.5 0,1 0,2 1,3 2))"),
+ from_wkt<ML>("MULTILINESTRING((0.5 0,1 0,3 2))"),
+ "lli16");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(4 5,3 2,1 0,0.5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0.5 0,1 0,2 1,3 2))"),
+ from_wkt<ML>("MULTILINESTRING((0.5 0,1 0,3 2))"),
+ "lli16-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1,30 1)"),
+ from_wkt<L>("LINESTRING(1 1,2 0,3 1,20 1,25 1)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((20 1,25 1))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((2 0),(20 1,25 1))"),
+#endif
+ "lli17");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1,21 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 1,2 0,3 1,20 1,25 0)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING()"),
+#else
+ from_wkt<ML>("MULTILINESTRING((2 0),(20 1),(25 0))"),
+#endif
+ "lli18");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 1)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0),(4 0))"),
+#endif
+ "lli19");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,4 0,4 1,20 1,5 0,1 0)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0),(4 0))"),
+#endif
+ "lli19-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0),(4 0))"),
+#endif
+ "lli19a");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(4 0,4 1,20 1,5 0,1 0)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0),(4 0))"),
+#endif
+ "lli19a-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0),(4 0,5 0))"),
+ "lli19b");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0,6 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0),(4 0,5 0))"),
+ "lli19c");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,3 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0),(4 0,3 0))"),
+ "lli19d");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,3 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0),(4 0,3 0))"),
+ "lli19e");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0,5 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0),(4 0,5 0))"),
+ "lli19f");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,5 0,4 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,4 0),(5 0,1 0))"),
+ "lli19f-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,5 0,5 1)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0),(5 0))"),
+#endif
+ "lli19g");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,5 0,4 1,20 1,5 0,1 0)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0),(5 0))"),
+#endif
+ "lli19g-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0,30 30,10 30,10 -10,15 0,40 0)"),
+ from_wkt<L>("LINESTRING(5 5,10 0,10 30,20 0,25 0,25 25,50 0,35 0)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((20 0,25 0),(10 30,10 0),\
+ (35 0,40 0),(20 0,25 0))"),
+ from_wkt<ML>("MULTILINESTRING((20 0,25 0),(10 0,10 30),\
+ (40 0,35 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((10 0),(20 0,25 0),(10 30,10 0),\
+ (30 20),(35 0,40 0),(20 0,25 0))"),
+ from_wkt<ML>("MULTILINESTRING((10 0),(20 0,25 0),(10 0,10 30),\
+ (30 20),(40 0,35 0))"),
+#endif
+ "lli20");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0,30 30,10 30,10 -10,15 0,40 0)"),
+ from_wkt<L>("LINESTRING(5 5,10 0,10 30,20 0,25 0,25 25,50 0,15 0)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((15 0,30 0),(10 30,10 0),\
+ (15 0,40 0))"),
+ from_wkt<ML>("MULTILINESTRING((10 0,10 30),(20 0,25 0),(40 0,15 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((10 0),(15 0,30 0),(10 30,10 0),\
+ (30 20),(15 0,40 0))"),
+ from_wkt<ML>("MULTILINESTRING((10 0),(10 0,10 30),(20 0,25 0),\
+ (30 20),(40 0,15 0))"),
+#endif
+ "lli20a");
+
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<L>("LINESTRING(2 2,5 -1,15 2,18 0,20 0)"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((18 0,19 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((18 0,20 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((4 0),(8.33333333333333333 0),\
+ (18 0,19 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((4 0),(8.33333333333333333 0),\
+ (18 0,20 0))"),
+#endif
+ "lli21"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0)"),
+ from_wkt<L>("LINESTRING(1 0,4 0,2 1,5 1,4 0,8 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,4 0),(4 0,8 0))"),
+ "lli22"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0)"),
+ from_wkt<L>("LINESTRING(4 0,5 0,5 1,1 1,1 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,4 0),(4 0,5 0))"),
+ "lli23"
+ );
+
+ // the following two tests have been discussed with by Adam
+ tester::apply
+ (from_wkt<L>("LINESTRING(1 0,1 1,2 1)"),
+ from_wkt<L>("LINESTRING(2 1,1 1,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1))"),
+ "lli24"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(1 0,1 1,2 1)"),
+ from_wkt<L>("LINESTRING(1 2,1 1,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,1 1))"),
+ "lli25"
+ );
+}
+
+
+
+
+BOOST_AUTO_TEST_CASE( test_intersection_linestring_multilinestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** LINESTRING / MULTILINESTRING INTERSECTION ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_intersection_of_geometries<L, ML, ML> tester;
+
+ // the inertsection code automatically reverses the order of the
+ // geometries according to the geometry IDs.
+ // all calls below are actually reversed, and internally the
+ // intersection of the linestring with the multi-linestring is
+ // computed.
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 2,4 3),(1 1,2 2,5 3))"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "lmli01"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0))"),
+ "lmli02"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,5 0))"),
+ "lmli03"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0))"),
+ "lmli04"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,101 0))"),
+ "lmli07"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ "lmli07a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ "lmli07b"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,101 0))"),
+ "lmli08"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 0.5,3 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((3 0,101 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0),(2 0.5),(3 0,101 0))"),
+#endif
+ "lmli09"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,1.5 0,2 0.5,3 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,1 0,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,1.5 0),(3 0,101 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0),(2 0.5),(1 0,1.5 0),(3 0,101 0))"),
+#endif
+ "lmli10"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (1 1,2 0,18 0,19 1),(2 1,3 0,17 0,18 1),\
+ (3 1,4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ "lmli12"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0,20 1),\
+ (2 0,18 0,19 1),(3 0,17 0,18 1),\
+ (4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ "lmli13"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ "lmli14"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ "lmli15"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ "lmli15a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,5 0,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ "lmli16"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,5 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ "lmli16a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(25 0))"),
+#endif
+ "lmli17"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0,26 2))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(25 0))"),
+#endif
+ "lmli17a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ "lmli18"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,18 0,19 0))"),
+ "lmli18a"
+ );
+}
+
+
+
+
+
+
+#ifndef BOOST_GEOMETRY_TEST_NO_DEGENERATE
+BOOST_AUTO_TEST_CASE( test_intersection_l_ml_degenerate )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** LINESTRING / MULTILINESTRING INTERSECTION"
+ << " (DEGENERATE) ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_intersection_of_geometries<L, ML, ML> tester;
+
+ // the following test cases concern linestrings with duplicate
+ // points and possibly linestrings with zero length.
+
+ // no unique: (3 0) appears twice
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,0 0,18 0,18 0,19 0,19 0,19 0,30 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,1 1,2 2,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (4 0,4 10,4 10))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((5 0,18 0,19 0,20 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0),(1 0),(2 0),(3 0),(4 0),\
+ (5 0,18 0,19 0,20 0))"),
+#endif
+ "lmli20a"
+ );
+
+ // no unique: (3 0) appears twice
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,0 0,18 0,18 0,19 0,19 0,19 0,30 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,1 1,2 2,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (4 0,4 0,4 10,4 10))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((5 0,18 0,19 0,20 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0),(1 0),(2 0),(3 0),(4 0),\
+ (5 0,18 0,19 0,20 0))"),
+#endif
+ "lmli20b"
+ );
+
+ // no unique: (3 0) appears twice
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,0 0,18 0,18 0,19 0,19 0,19 0,30 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,1 1,2 2,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (30 0,30 0,30 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((5 0,18 0,19 0,20 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0),(1 0),(2 0),(3 0),\
+ (5 0,18 0,19 0,20 0),(30 0))"),
+#endif
+ "lmli20c"
+ );
+
+ // no unique: (3 0) appears twice
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,0 0,18 0,18 0,19 0,19 0,19 0,30 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,1 1,2 2,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (30 0,30 0,31 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((5 0,18 0,19 0,20 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0),(1 0),(2 0),(3 0),\
+ (5 0,18 0,19 0,20 0),(30 0))"),
+#endif
+ "lmli20d"
+ );
+}
+#endif // BOOST_GEOMETRY_TEST_NO_DEGENERATE
+
+
+
+
+BOOST_AUTO_TEST_CASE( test_intersection_multilinestring_linestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / LINESTRING INTERSECTION ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_intersection_of_geometries<ML, L, ML> tester;
+
+ // the intersection code automatically reverses the order of the
+ // geometries according to the geometry IDs.
+ // all calls below are actually reversed, and internally the
+ // intersection of the linestring with the multi-linestring is
+ // computed.
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<L>("LINESTRING(1 1,2 2,4 3)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "mlli01"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<L>("LINESTRING(1 1,2 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0))"),
+ "mlli02"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<L>("LINESTRING(-1 -1,1 0,101 0,200 -1)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,101 0))"),
+ "mlli03"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<L>("LINESTRING(0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(18 0,2 0),\
+ (3 0,17 0),(16 0,4 0))"),
+ "mlli04"
+ );
+}
+
+
+
+
+
+
+BOOST_AUTO_TEST_CASE( test_intersection_multilinestring_multilinestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / MULTILINESTRING INTERSECTION ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef multi_linestring_type ML;
+
+ typedef test_intersection_of_geometries<ML, ML, ML> tester;
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 2,4 3),(1 1,2 2,5 3))"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "mlmli01"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0),(2 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0),(3 0,4 0))"),
+ "mlmli02"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,5 0),(2 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0),(3 0,5 0))"),
+ "mlmli03"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0),(2 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0))"),
+ "mlmli04"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (10 10,20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (10 20,15 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0),(2 0,4 0),(15 10,20 10))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0),(15 10,20 10))"),
+ "mlmli05"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 10),(1 0,7 0),\
+ (10 10,20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (-1 -1,0 0,9 0,11 10,12 10,13 3,14 4,15 5),\
+ (10 20,15 10,25 10,30 15))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((0 0,9 0),(13 3,15 5),\
+ (1 0,7 0),(11 10,12 10),(15 10,20 10))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0),(0 0,9 0),(13 3,14 4,15 5),\
+ (11 10,12 10),(15 10,20 10))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0,9 0),(13 3,15 5),(20 10),\
+ (1 0,7 0),(11 10,12 10),(15 10,20 10))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0),(0 0,9 0),(13 3,14 4,15 5),\
+ (11 10,12 10),(15 10,20 10))"),
+#endif
+ "mlmli06"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,101 0))"),
+ "mlmli07"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((-1 1,0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,50 0),(20 0,101 0))"),
+ "mlmli07a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,50 0),(20 0,101 0))"),
+ "mlmli07b"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,101 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0),(1 0,101 0))"),
+#endif
+ "mlmli08"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0.5,3 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((3 0,101 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0),(2 0.5),(3 0,101 0))"),
+#endif
+ "mlmli09"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 0,1.5 0,2 0.5,3 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,1 0,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,1.5 0),(3 0,101 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,1.5 0),(2 0.5),(3 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0),(1 0,1.5 0),(2 0.5),(3 0,101 0))"),
+#endif
+ "mlmli10"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 1,100 1,101 0),\
+ (0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1,3 0,4 0,5 1,6 1,\
+ 7 0,8 0,9 1,10 1,11 0,12 0,13 1,14 1,15 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 1,2 1),(5 1,6 1),(9 1,10 1),\
+ (13 1,14 1),(1 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 1),(5 1,6 1),(9 1,10 1),\
+ (13 1,14 1),(3 0,4 0),(7 0,8 0),(11 0,12 0),\
+ (1 0,101 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 1,2 1),(5 1,6 1),(9 1,10 1),\
+ (13 1,14 1),(101 0),(1 0),(1 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0),(1 1,2 1),(5 1,6 1),(9 1,10 1),\
+ (13 1,14 1),(3 0,4 0),(7 0,8 0),(11 0,12 0),(15 0),\
+ (1 0,101 0))"),
+#endif
+ "mlmli11"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (1 1,2 0,18 0,19 1),(2 1,3 0,17 0,18 1),\
+ (3 1,4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(2 0,18 0),(3 0,17 0),\
+ (4 0,16 0))"),
+ "mlmli12"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0,20 1),\
+ (2 0,18 0,19 1),(3 0,17 0,18 1),\
+ (4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(2 0,18 0),(3 0,17 0),\
+ (4 0,16 0))"),
+ "mlmli13"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(18 0,2 0),\
+ (3 0,17 0),(16 0,4 0))"),
+ "mlmli14"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,6 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(6 0))"),
+#endif
+ "mlmli15"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,4 2,2 2))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(6 0))"),
+#endif
+ "mlmli15a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,5 0,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(5 0,6 0))"),
+ "mlmli16"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,5 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(6 0,5 0))"),
+ "mlmli16a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(25 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(4 0),(25 0))"),
+#endif
+ "mlmli17"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0,26 2))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(25 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(4 0),(25 0))"),
+#endif
+ "mlmli17a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(4 0),\
+ (8.3333333333333333333 0),(18 0))"),
+#endif
+ "mlmli18"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,18 0,19 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,18 0,19 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,18 0,19 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(4 0),\
+ (8.3333333333333333333 0),(18 0))"),
+#endif
+ "mlmli18a"
+ );
+}
+
+
+
+
+
+
+#ifndef BOOST_GEOMETRY_TEST_NO_DEGENERATE
+BOOST_AUTO_TEST_CASE( test_intersection_ml_ml_degenerate )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / MULTILINESTRING INTERSECTION"
+ << " (DEGENERATE) ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef multi_linestring_type ML;
+
+ typedef test_intersection_of_geometries<ML, ML, ML> tester;
+
+ // the following test cases concern linestrings with duplicate
+ // points and possibly linestrings with zero length.
+
+ // no unique: (3 0) appears twice
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((5 5,5 5),(0 0,18 0,18 0,\
+ 19 0,19 0,19 0,30 0),(2 0,2 0),(4 10,4 10))"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 10),\
+ (4 0,4 10),(5 5,5 5))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((5 0,18 0,19 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((5 5),(0 0),(1 0),(2 0),(3 0),\
+ (4 0),(5 0,18 0,19 0,20 0),(2 0),(4 10))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0),(1 0),(2 0),(2 0),(3 0),\
+ (0 0),(4 0),(4 10),(5 5))"),
+#endif
+ "mlmli20a"
+ );
+
+ // no unique: (3 0) appears three times
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((5 5,5 5),(0 0,0 0,18 0,18 0,\
+ 19 0,19 0,19 0,30 0,30 0),(2 0,2 0),(4 10,4 10))"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,1 1,2 2,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (4 0,4 10,4 10),(5 5,5 5))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((5 0,18 0,19 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((5 5),(0 0),(1 0),(2 0),(3 0),(4 0),\
+ (5 0,18 0,19 0,20 0),(2 0),(4 10))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0),(1 0),(2 0),(2 0),\
+ (3 0),(0 0),(4 0),(4 10),(5 5))"),
+#endif
+ "mlmli20aa"
+ );
+
+ // no unique: (3 0) appears twice
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((5 5,5 5),(0 0,0 0,18 0,18 0,\
+ 19 0,19 0,19 0,30 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,1 1,2 2,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (4 0,4 0,4 10,4 10),(0 5,15 5))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((5 0,18 0,19 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((5 5),(0 0),(1 0),(2 0),(3 0),(4 0),\
+ (5 0,18 0,19 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0),(1 0),(2 0),(3 0),\
+ (0 0),(4 0),(5 5))"),
+#endif
+ "mlmli20b"
+ );
+
+ // no unique: (3 0) and (30 0) appear twice
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,0 0,18 0,18 0,\
+ 19 0,19 0,19 0,30 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,1 1,2 2,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (30 0,30 0,30 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((5 0,18 0,19 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0),(1 0),(2 0),(3 0),\
+ (5 0,18 0,19 0,20 0),(30 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0),(1 0),(2 0),(3 0),\
+ (0 0),(30 0))"),
+#endif
+ "mlmli20c"
+ );
+
+ // no unique: (3 0) appears twice
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,0 0,18 0,18 0,\
+ 19 0,19 0,19 0,30 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((-10 0,-9 0),(0 10,5 0,20 0,20 0,30 10),\
+ (1 1,1 1,2 2,2 2),(1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (30 0,30 0,31 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((5 0,18 0,19 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0),(1 0),(2 0),(3 0),\
+ (5 0,18 0,19 0,20 0),(30 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0),(1 0),(2 0),(3 0),\
+ (0 0),(30 0))"),
+#endif
+ "mlmli20d"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,0 0,18 0,18 0,\
+ 19 0,19 0,19 0,30 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 10,5 0,20 0,20 0,30 0),\
+ (1 10,1 10,1 0,1 0,1 -10),\
+ (2 0,2 0),(3 0,3 0,3 0),(0 0,0 0,0 10,0 10),\
+ (30 0,30 0,31 0,31 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((5 0,18 0,19 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0,30 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0),(1 0),(2 0),(3 0),\
+ (5 0,18 0,19 0,30 0),(30 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 0,20 0,30 0),(1 0),(2 0),(3 0),\
+ (0 0),(30 0))"),
+#endif
+ "mlmli20e"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((1 5, -4.3 -.1), (0 6, 8.6 6, 189.7654 5, 1 3, 6 3, 3 5, 6 2.232432, 0 4), (-6 5, 1 2.232432), (3 -1032.34324, 9 0, 189.7654 1, -1.4 3, 3 189.7654, +.3 10.0002, 1 5, 6 3, 5 1, 9 1, 10.0002 -1032.34324, -0.7654 0, 5 3, 3 4), (2.232432 2.232432, 8.6 +.4, 0.0 2.232432, 4 0, -8.8 10.0002), (1 0, 6 6, 7 2, -0 8.4), (-0.7654 3, +.6 8, 4 -1032.34324, 1 6, 0 4), (0 7, 2 1, 8 -7, 7 -.7, -1032.34324 9), (5 0, 10.0002 4, 8 7, 3 3, -8.1 5))"),
+ from_wkt<ML>("MULTILINESTRING((5 10.0002, 2 7, -0.7654 0, 5 3), (0 -0.7654, 4 10.0002, 4 +.1, -.8 3, -.1 8, 10.0002 2, +.9 -1032.34324))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((-0.7654 8.88178e-16,-0.7654 0,5 3))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((-0.756651 3.30964),(1.60494 6),\
+ (2.51371 6),(3.26673 6),(4 6),(8.18862 3.07616),\
+ (4 3.03179),(1.40063 3.00424),(1.39905 3),\
+ (4 3),(5 3),(4 4.33333),(4 4.07748),\
+ (4.41962 2.698),(4 2.82162),(1.59592 3.52985),\
+ (0.729883 3.78498),(-0.532243 2.83823),\
+ (0.235887 2.53454),(7.08745 -329.0674155),\
+ (9.98265 0.00543606),(8.49103 2.89652),\
+ (4.87386 2.93436),(4 2.9435),(1.38821 2.97083)\
+ (0.412281 2.98104),(-0.789427 2.99361),\
+ (0.641699 7.5594),(1.18124 4.9275),\
+ (1.99437 4.60225),(4 3.8),(9.09826 -100.515944),\
+ (5.06428 -559.024344),\
+ (4 3.5),(3.06464 1.99294),(4 1.72377),\
+ (4 1.38014),(2.50083 1.69957),(1.03214 2.01251),\
+ (0.72677 2.07758),(0.10749 2.20953),\
+ (0.0954852 2.17914),(0.92255 1.71755),\
+ (1.70073 1.28324),(3.43534 0.441146),\
+ (2.09493 1.48836),(1.12031 2.2498),\
+ (0.358522 2.84496),(-0.705343 3.67612),\
+ (2.06005 1.27206),(2.3516 1.62191),(4 3.6),\
+ (5.09496 4.91395),(6.47672 4.09311),(4 4.74286),\
+ (2.54193 6.07595),(1.87562 6.68515),\
+ (1.43457 7.08839),(0.502294 7.64221),\
+ (0.601362 7.58336),(0.614728 3.49349),\
+ (0.619143 2.1426),(0.623165 0.911787),\
+ (0.623783 0.722855),(3.16036 -775.427199),\
+ (3.23365 -767.0972558),(1.01466 0.926246),\
+ (1.01183 1.90535),(1.01168 1.95744),\
+ (1.00439 4.47984),(0.91526 4.25422),\
+ (1.36441 2.90677),(1.8713 1.38609),\
+ (1.87531 1.37408),(0.0484053 -0.635122),\
+ (8.5655 2.85228),(5.26567 4.81254),(4 3.8),\
+ (1.4995 3.27036),(0.591231 3.43401),\
+ (-0.706503 3.66784),\
+ (-0.7654 8.88178e-16,-0.7654 0,5 3))"),
+ from_wkt<ML>("MULTILINESTRING((1.87562 6.68515),(1.60494 6),\
+ (1.18124 4.9275),(1.00439 4.47984),(0.91526 4.25422),\
+ (0.729883 3.78498),(0.614728 3.49349),\
+ (0.591231 3.43401),(0.412281 2.98104),\
+ (0.358522 2.84496),(0.235887 2.53454),\
+ (0.10749 2.20953),(0.0954852 2.17914),\
+ (5 3),(0.0484053 -0.635122),(0.535994 0.677175),\
+ (0.623165 0.911787),(0.92255 1.71755),\
+ (1.01168 1.95744),(1.03214 2.01251),\
+ (1.12031 2.2498),(1.36441 2.90677),\
+ (1.38821 2.97083),(1.39905 3),(1.40063 3.00424),\
+ (1.4995 3.27036),(1.59592 3.52985),\
+ (1.99437 4.60225),(2.51371 6),(2.54193 6.07595),\
+ (4 6),(4 4.74286),(4 4.33333),(4 4.07748),(4 3.8),\
+ (4 3.8),(4 3.6),(4 3.5),(4 3.03179),(4 3),\
+ (4 2.9435),(4 2.82162),(4 2.47965),(4 1.72377),\
+ (4 1.38014),(3.43534 0.441146),(2.06005 1.27206),\
+ (1.88383 1.37852),(1.8713 1.38609),\
+ (1.01183 1.90535),(0.72677 2.07758),\
+ (0.619143 2.1426),(-0.532243 2.83823),\
+ (-0.789427 2.99361),(-0.756651 3.30964),\
+ (-0.706503 3.66784),(-0.705343 3.67612),\
+ (0.502294 7.64221),(0.601362 7.58336),\
+ (0.641699 7.5594),(1.43457 7.08839),\
+ (3.26673 6),(5.09496 4.91395),(5.26567 4.81254),\
+ (6.47672 4.09311),(8.18862 3.07616),\
+ (8.49103 2.89652),(8.5655 2.85228),\
+ (9.98265 0.00543606),(9.09826 -100.515944),\
+ (7.08745 -329.0674155),(5.06428 -559.024344),\
+ (3.23365 -767.0972558),(3.16036 -775.427199),\
+ (-0.7654 8.88178e-16,-0.7654 0,5 3))"),
+#endif
+ "mlmli21",
+ 1e-4
+ );
+}
+#endif // BOOST_GEOMETRY_TEST_NO_DEGENERATE
+
+
+
+
+BOOST_AUTO_TEST_CASE( test_intersection_ml_ml_spikes )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / MULTILINESTRING INTERSECTION"
+ << " (WITH SPIKES) ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef multi_linestring_type ML;
+
+ typedef test_intersection_of_geometries<ML, ML, ML> tester;
+
+ // the following test cases concern linestrings with spikes
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,9 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,9 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,9 0,5 0))"),
+ "mlmli-spikes-01"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((9 0,1 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,9 0))"),
+ from_wkt<ML>("MULTILINESTRING((9 0,1 0,5 0))"),
+ "mlmli-spikes-02"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,9 0,2 0,8 0,3 0,7 0,4 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,9 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,9 0,2 0,8 0,3 0,7 0,4 0,5 0))"),
+ "mlmli-spikes-03"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,3 0,2 0,4 0,3 0,5 0,4 0,6 0,\
+ 5 0,7 0,6 0,8 0,7 0,9 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,9 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,3 0,2 0,4 0,3 0,5 0,4 0,6 0,\
+ 5 0,7 0,6 0,8 0,7 0,9 0))"),
+ "mlmli-spikes-04"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(7 0,8 0,7 0),\
+ (9 1,9 0,9 2))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0),(7 0,8 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(7 0,8 0,7 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0),(7 0,8 0),(9 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(7 0,8 0,7 0),(9 0))"),
+#endif
+ "mlmli-spikes-05"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(7 0,8 0,7 0),\
+ (9 0,9 2,9 1))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0),(7 0,8 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(7 0,8 0,7 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0),(7 0,8 0),(9 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(7 0,8 0,7 0),(9 0))"),
+#endif
+ "mlmli-spikes-05a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(9 0,6 0,8 0),\
+ (11 0,8 0,12 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0),(6 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(9 0,6 0,8 0),\
+ (10 0,8 0,10 0))"),
+ "mlmli-spikes-06"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,0 0,-2 0),(11 0,10 0,12 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING()"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0),(10 0))"),
+#endif
+ "mlmli-spikes-07"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,-2 -2),(11 1,10 0,12 2))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING()"),
+#else
+ from_wkt<ML>("MULTILINESTRING((0 0),(10 0))"),
+#endif
+ "mlmli-spikes-07a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(11 0,10 0,12 0),\
+ (7 5,7 0,8 0,6.5 0,8.5 0,8.5 5))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0),(6.5 0,8.5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(7 0,8 0,6.5 0,8.5 0))"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0),(6.5 0,8.5 0),(10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,6 0,5 0),(7 0,8 0,6.5 0,8.5 0),(10 0))"),
+#endif
+ "mlmli-spikes-08"
+ );
+
+ // now the first geometry has a spike
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,7 0,4 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,8 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,7 0,4 0,8 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,8 0))"),
+ "mlmli-spikes-09"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,7 0,4 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(9 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(9 0,10 0))"),
+ "mlmli-spikes-09a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,7 0,4 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0),(9 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0),(5 0,4 0,5 0),(9 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0),(9 0,10 0))"),
+ "mlmli-spikes-09b"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,7 0,4 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0),(6 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0),(6 0,7 0,6 0),(5 0,4 0,5 0),\
+ (6 0,10 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0),(6 0,10 0))"),
+ "mlmli-spikes-09c"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,8 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,8 0),(8 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,8 0))"),
+ "mlmli-spikes-10"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,8 0,4 0),(2 0,9 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,9 0),(9 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,8 0,4 0),(2 0,9 0,5 0))"),
+ "mlmli-spikes-11"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((11 1,10 0,12 2))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING()"),
+#else
+ from_wkt<ML>("MULTILINESTRING((10 0))"),
+#endif
+ "mlmli-spikes-12"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((11 -1,10 0,12 -2))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING()"),
+#else
+ from_wkt<ML>("MULTILINESTRING((10 0))"),
+#endif
+ "mlmli-spikes-12a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((11 0,10 0,12 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING()"),
+#else
+ from_wkt<ML>("MULTILINESTRING((10 0))"),
+#endif
+ "mlmli-spikes-13"
+ );
+
+ // the following three tests have been discussed with Adam
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 2,1 1,1 2))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING()"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 1))"),
+#endif
+ "mlmli-spikes-14"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 0,0 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,1 0,2 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING()"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 0))"),
+#endif
+ "mlmli-spikes-15"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,1 1,2 0))"),
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
+ from_wkt<ML>("MULTILINESTRING()"),
+#else
+ from_wkt<ML>("MULTILINESTRING((1 1))"),
+#endif
+ "mlmli-spikes-16"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1))"),
+ from_wkt<ML>("MULTILINESTRING((2 1,1 1,2 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 1))"),
+ from_wkt<ML>("MULTILINESTRING((2 1,1 1,2 1))"),
+ "mlmli-spikes-17"
+ );
+
+ // test cases sent by Adam on the mailing list (equal slikes)
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 1,0 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1,0 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1,0 0))"),
+ "mlmli-spikes-18"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 1,0 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,0 0,1 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1,0 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,0 0,1 1))"),
+ "mlmli-spikes-19"
+ );
+}
diff --git a/libs/geometry/test/algorithms/set_operations/intersection/intersection_pl_pl.cpp b/libs/geometry/test/algorithms/set_operations/intersection/intersection_pl_pl.cpp
new file mode 100644
index 000000000..212f914af
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/intersection/intersection_pl_pl.cpp
@@ -0,0 +1,185 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#include <iostream>
+
+#ifndef BOOST_TEST_MODULE
+#define BOOST_TEST_MODULE test_intersection_pointlike_pointlike
+#endif
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+#define BOOST_GEOMETRY_DEBUG_TURNS
+#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
+#endif
+
+#include <boost/test/included/unit_test.hpp>
+
+#include "../test_set_ops_pl_pl.hpp"
+
+#include <boost/geometry/geometries/multi_point.hpp>
+
+typedef bg::model::point<double,2,bg::cs::cartesian> point_type;
+typedef bg::model::multi_point<point_type> multi_point_type;
+
+
+
+//===========================================================================
+//===========================================================================
+//===========================================================================
+
+
+BOOST_AUTO_TEST_CASE( test_intersection_point_point )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** POINT / POINT INTERSECTION ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef point_type P;
+ typedef multi_point_type MP;
+
+ typedef test_set_op_of_pointlike_geometries
+ <
+ P, P, MP, bg::overlay_intersection
+ > tester;
+
+ tester::apply
+ (from_wkt<P>("POINT(0 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "ppi01");
+
+ tester::apply
+ (from_wkt<P>("POINT(0 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ "ppi02");
+}
+
+
+BOOST_AUTO_TEST_CASE( test_intersection_multipoint_point )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTIPOINT / POINT INTERSECTION ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef point_type P;
+ typedef multi_point_type MP;
+
+ typedef test_set_op_of_pointlike_geometries
+ <
+ MP, P, MP, bg::overlay_intersection
+ > tester;
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mppi01");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ "mppi02");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mppi03");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ "mppi04");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mppi05");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0)"),
+ from_wkt<P>("POINT(1 0)"),
+ from_wkt<MP>("MULTIPOINT(1 0)"),
+ "mppi06");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ "mppi07");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mppi08");
+}
+
+
+BOOST_AUTO_TEST_CASE( test_intersection_multipoint_multipoint )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTIPOINT / MULTIPOINT INTERSECTION ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef multi_point_type MP;
+
+ typedef test_set_op_of_pointlike_geometries
+ <
+ MP, MP, MP, bg::overlay_intersection
+ > tester;
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(2 2,3 3,0 0,0 0,2 2,1 1,1 1,1 0,1 0)"),
+ from_wkt<MP>("MULTIPOINT(1 0,1 1,1 1,1 1)"),
+ from_wkt<MP>("MULTIPOINT(1 0,1 1,1 1,1 1)"),
+ "mpmpi01");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,1 1,1 0,1 1)"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,1 1,0 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0,1 1,1 0,1 1)"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,1 1,0 0)"),
+ "mpmpi02");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,1 1,0 0)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mpmpi03");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,1 1,1 0,1 1)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mpmpi04");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mpmpi05");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,1 0,2 0,3 0,0 0,1 0,2 0)"),
+ from_wkt<MP>("MULTIPOINT(0 1,0 2,1 0,0 0,2 0)"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,2 0)"),
+ "mpmpi06");
+}
+
diff --git a/libs/geometry/test/algorithms/set_operations/intersection/intersection_segment.cpp b/libs/geometry/test/algorithms/set_operations/intersection/intersection_segment.cpp
new file mode 100644
index 000000000..664d37c9b
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/intersection/intersection_segment.cpp
@@ -0,0 +1,134 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <algorithm>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <boost/config.hpp>
+#include <geometry_test_common.hpp>
+
+#include <boost/geometry/algorithms/correct.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+#include <boost/geometry/algorithms/intersection_segment.hpp>
+#include <boost/geometry/io/wkt/aswkt.hpp>
+
+static std::ostream & operator<<(std::ostream &s, const bg::intersection_result& r)
+{
+ switch(r)
+ {
+ case bg::is_intersect_no : s << "is_intersect_no"; break;
+ case bg::is_intersect : s << "is_intersect"; break;
+ case bg::is_parallel : s << "is_parallel"; break;
+ case bg::is_collinear_no : s << "is_collinear_no"; break;
+ case bg::is_collinear_one : s << "is_collinear_one"; break;
+ case bg::is_collinear_connect : s << "is_collinear_connect"; break;
+ case bg::is_collinear_overlap : s << "is_collinear_overlap"; break;
+ case bg::is_collinear_overlap_opposite : s << "is_collinear_overlap_opposite"; break;
+ case bg::is_collinear_connect_opposite : s << "is_collinear_connect_opposite"; break;
+
+ // detailed connection results:
+ case bg::is_intersect_connect_s1p1 : s << "is_intersect_connect_s1p1"; break;
+ case bg::is_intersect_connect_s1p2 : s << "is_intersect_connect_s1p2"; break;
+ case bg::is_intersect_connect_s2p1 : s << "is_intersect_connect_s2p1"; break;
+ case bg::is_intersect_connect_s2p2 : s << "is_intersect_connect_s2p2"; break;
+ }
+ return s;
+}
+
+static std::string as_string(const bg::intersection_result& r)
+{
+ std::stringstream out;
+ out << r;
+ return out.str();
+}
+
+typedef bg::model::point<double> P;
+typedef bg::const_segment<P> S;
+
+
+static void test_intersection(double s1x1, double s1y1, double s1x2, double s1y2,
+ double s2x1, double s2y1, double s2x2, double s2y2,
+ // Expected results
+ bg::intersection_result expected_result,
+ int exptected_count, const P& exp_p1, const P& exp_p2)
+{
+ S s1(P(s1x1, s1y1), P(s1x2, s1y2));
+ S s2(P(s2x1, s2y1), P(s2x2, s2y2));
+ std::vector<P> ip;
+ double ra, rb;
+ bg::intersection_result r = bg::intersection_s(s1, s2, ra, rb, ip);
+ r = bg::intersection_connect_result(r, ra, rb);
+
+ BOOST_CHECK_EQUAL(ip.size(), exptected_count);
+ BOOST_CHECK_EQUAL(as_string(expected_result), as_string(r));
+
+ if (ip.size() == 2 && ip[0] != exp_p1)
+ {
+ // Swap results, second point is not as expected, swap results, order is not prescribed,
+ // it might be OK.
+ std::reverse(ip.begin(), ip.end());
+ }
+
+ if (ip.size() >= 1)
+ {
+ BOOST_CHECK_EQUAL(ip[0], exp_p1);
+ }
+ if (ip.size() >= 2)
+ {
+ BOOST_CHECK_EQUAL(ip[1], exp_p2);
+ }
+
+
+ /*
+ std::cout << exptected_count << " " << r;
+ if (exptected_count >= 1) std::cout << " " << ip[0];
+ if (exptected_count >= 2) std::cout << " " << ip[1];
+ std::cout << std::endl;
+ */
+}
+
+//BOOST_AUTO_TEST_CASE( test1 )
+int test_main( int , char* [] )
+{
+ // Identical cases
+ test_intersection(0,0, 1,1, 0,0, 1,1, bg::is_collinear_overlap, 2, P(0,0), P(1,1));
+ test_intersection(1,1, 0,0, 0,0, 1,1, bg::is_collinear_overlap_opposite, 2, P(1,1), P(0,0));
+ test_intersection(0,1, 0,2, 0,1, 0,2, bg::is_collinear_overlap, 2, P(0,1), P(0,2)); // Vertical
+ test_intersection(0,2, 0,1, 0,1, 0,2, bg::is_collinear_overlap_opposite, 2, P(0,2), P(0,1)); // Vertical
+ // Overlap cases
+ test_intersection(0,0, 1,1, -0.5,-0.5, 2,2, bg::is_collinear_overlap, 2, P(0,0), P(1,1));
+ test_intersection(0,0, 1,1, 0.5,0.5, 1.5,1.5, bg::is_collinear_overlap, 2, P(0.5,0.5), P(1,1));
+ test_intersection(0,0, 0,1, 0,-10, 0,10, bg::is_collinear_overlap, 2, P(0,0), P(0,1)); // Vertical
+ test_intersection(0,0, 0,1, 0,10, 0,-10, bg::is_collinear_overlap_opposite, 2, P(0,0), P(0,1)); // Vertical
+ test_intersection(0,0, 1,1, 1,1, 2,2, bg::is_collinear_connect, 1, P(1,1), P(0,0)); // Single point
+ // Colinear, non overlap cases
+ test_intersection(0,0, 1,1, 1.5,1.5, 2.5,2.5, bg::is_collinear_no, 0, P(0,0), P(0,0));
+ test_intersection(0,0, 0,1, 0,5, 0,6, bg::is_collinear_no, 0, P(0,0), P(0,0)); // Vertical
+ // Parallel cases
+ test_intersection(0,0, 1,1, 1,0, 2,1, bg::is_parallel, 0, P(0,0), P(0,1));
+ // Intersect cases
+ test_intersection(0,2, 4,2, 3,0, 3,4, bg::is_intersect, 1, P(3,2), P(0,0));
+ // Non intersect cases
+
+ // Single point cases
+ test_intersection(0,0, 0,0, 1,1, 2,2, bg::is_collinear_no, 0, P(1,1), P(0,0)); // Colinear/no
+ test_intersection(2,2, 2,2, 1,1, 3,3, bg::is_collinear_one, 1, P(2,2.01), P(0,0)); // On segment
+ test_intersection(1,1, 3,3, 2,2, 2,2, bg::is_collinear_one, 1, P(2,2), P(0,0)); // On segment
+ test_intersection(1,1, 3,3, 1,1, 1,1, bg::is_collinear_one, 1, P(1,1), P(0,0)); // On segment, start
+ test_intersection(1,1, 3,3, 3,3, 3,3, bg::is_collinear_one, 1, P(3,3), P(0,0)); // On segment, end
+
+ return 0;
+}
diff --git a/libs/geometry/test/algorithms/set_operations/intersection/multi_intersection.cpp b/libs/geometry/test/algorithms/set_operations/intersection/multi_intersection.cpp
new file mode 100644
index 000000000..46106022d
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/intersection/multi_intersection.cpp
@@ -0,0 +1,240 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Unit Test
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <string>
+
+// If defined, tests are run without rescaling-to-integer or robustness policy
+// This multi_intersection currently contains no tests for double then failing
+// #define BOOST_GEOMETRY_NO_ROBUSTNESS
+
+// #define BOOST_GEOMETRY_DEBUG_ASSEMBLE
+
+#include "test_intersection.hpp"
+#include <algorithms/test_overlay.hpp>
+#include <algorithms/overlay/multi_overlay_cases.hpp>
+
+#include <boost/geometry/multi/algorithms/correct.hpp>
+#include <boost/geometry/multi/algorithms/intersection.hpp>
+#include <boost/geometry/multi/algorithms/within.hpp> // only for testing #77
+
+#include <boost/geometry/geometries/point_xy.hpp>
+#include <boost/geometry/multi/geometries/multi_point.hpp>
+#include <boost/geometry/multi/geometries/multi_linestring.hpp>
+#include <boost/geometry/multi/geometries/multi_polygon.hpp>
+
+#include <boost/geometry/multi/io/wkt/read.hpp>
+
+template <typename Ring, typename Polygon, typename MultiPolygon>
+void test_areal()
+{
+ test_one<Polygon, MultiPolygon, MultiPolygon>("simplex_multi",
+ case_multi_simplex[0], case_multi_simplex[1],
+ 2, 12, 6.42);
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_multi_no_ip",
+ case_multi_no_ip[0], case_multi_no_ip[1],
+ 2, 8, 8.5);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_multi_2",
+ case_multi_2[0], case_multi_2[1],
+ 3, 12, 5.9);
+
+ test_one<Polygon, MultiPolygon, Polygon>("simplex_multi_mp_p",
+ case_multi_simplex[0], case_single_simplex,
+ 2, 12, 6.42);
+
+ test_one<Polygon, Ring, MultiPolygon>("simplex_multi_r_mp",
+ case_single_simplex, case_multi_simplex[0],
+ 2, 12, 6.42);
+ test_one<Ring, MultiPolygon, Polygon>("simplex_multi_mp_r",
+ case_multi_simplex[0], case_single_simplex,
+ 2, 12, 6.42);
+
+ // Constructed cases for multi/touch/equal/etc
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_61_multi",
+ case_61_multi[0], case_61_multi[1],
+ 0, 0, 0.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_62_multi",
+ case_62_multi[0], case_62_multi[1],
+ 1, 5, 1.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_63_multi",
+ case_63_multi[0], case_63_multi[1],
+ 1, 5, 1.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_64_multi",
+ case_64_multi[0], case_64_multi[1],
+ 1, 5, 1.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_65_multi",
+ case_65_multi[0], case_65_multi[1],
+ 1, 5, 1.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_72_multi",
+ case_72_multi[0], case_72_multi[1],
+ 3, 14, 2.85);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_77_multi",
+ case_77_multi[0], case_77_multi[1],
+ 5, 33, 9);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_78_multi",
+ case_78_multi[0], case_78_multi[1],
+ 1, 0, 22); // In "get_turns" using partitioning, #points went from 17 to 16
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_101_multi",
+ case_101_multi[0], case_101_multi[1],
+ 4, 22, 4.75);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_102_multi",
+ case_102_multi[0], case_102_multi[1],
+ 3, 26, 19.75);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_107_multi",
+ case_107_multi[0], case_107_multi[1],
+ 2, 10, 1.5);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_1",
+ case_recursive_boxes_1[0], case_recursive_boxes_1[1],
+ 10, 97, 47.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_2",
+ case_recursive_boxes_2[0], case_recursive_boxes_2[1],
+ 1, 47, 90.0); // Area from SQL Server
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_3",
+ case_recursive_boxes_3[0], case_recursive_boxes_3[1],
+ 19, 87, 12.5); // Area from SQL Server
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_4",
+ case_recursive_boxes_4[0], case_recursive_boxes_4[1],
+ 13, 157, 67.0); // Area from SQL Server
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120915_h2_a",
+ ggl_list_20120915_h2[0], ggl_list_20120915_h2[1],
+ 2, 10, 6.0); // Area from SQL Server
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120915_h2_b",
+ ggl_list_20120915_h2[0], ggl_list_20120915_h2[2],
+ 2, 10, 6.0); // Area from SQL Server
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ticket_9081",
+ ticket_9081[0], ticket_9081[1],
+ 2, 10, 0.0019812556);
+}
+
+template <typename Polygon, typename MultiPolygon, typename Box>
+void test_areal_clip()
+{
+ static std::string const clip = "POLYGON((1 1,4 4))";
+ test_one<Polygon, Box, MultiPolygon>("simplex_multi_mp_b", clip, case_multi_simplex[0],
+ 2, 11, 6.791666);
+ test_one<Polygon, MultiPolygon, Box>("simplex_multi_b_mp", case_multi_simplex[0], clip,
+ 2, 11, 6.791666);
+}
+
+template <typename LineString, typename MultiLineString, typename Box>
+void test_linear()
+{
+ typedef typename bg::point_type<MultiLineString>::type point;
+ test_one<point, MultiLineString, MultiLineString>("case_multi_ml_ml_1",
+ "MULTILINESTRING((0 0,1 1))", "MULTILINESTRING((0 1,1 0))",
+ 1, 1, 0);
+ test_one<point, MultiLineString, MultiLineString>("case_multi_ml_ml_2",
+ "MULTILINESTRING((0 0,1 1),(0.5 0,1.5 1))", "MULTILINESTRING((0 1,1 0),(0.5 1,1.5 0))",
+ 4, 4, 0);
+
+ test_one<point, LineString, MultiLineString>("case_multi_l_ml",
+ "LINESTRING(0 0,1 1)", "MULTILINESTRING((0 1,1 0),(0.5 1,1.5 0))",
+ 2, 2, 0);
+ test_one<point, MultiLineString, LineString>("case_multi_ml_l",
+ "MULTILINESTRING((0 1,1 0),(0.5 1,1.5 0))", "LINESTRING(0 0,1 1)",
+ 2, 2, 0);
+
+ test_one<LineString, MultiLineString, Box>("case_multi_ml_b",
+ "MULTILINESTRING((0 0,3 3)(1 0,4 3))", "POLYGON((1 1,3 2))",
+ 2, 4, 2 * std::sqrt(2.0));
+ test_one<LineString, Box, MultiLineString>("case_multi_b_ml",
+ "POLYGON((1 1,3 2))", "MULTILINESTRING((0 0,3 3)(1 0,4 3))",
+ 2, 4, 2 * std::sqrt(2.0));
+}
+
+template <typename P>
+void test_point_output()
+{
+ typedef bg::model::box<P> box;
+ typedef bg::model::linestring<P> linestring;
+ typedef bg::model::polygon<P> polygon;
+ typedef bg::model::multi_polygon<polygon> multi_polygon;
+
+ test_point_output<multi_polygon, multi_polygon>(case_multi_simplex[0], case_multi_simplex[1], 10);
+ test_point_output<linestring, multi_polygon>("linestring(4 0,0 4)", case_multi_simplex[0], 4);
+ test_point_output<box, multi_polygon>("box(3 0,4 6)", case_multi_simplex[0], 8);
+}
+
+template <typename MultiPolygon, typename MultiLineString>
+void test_areal_linear()
+{
+ typedef typename boost::range_value<MultiPolygon>::type Polygon;
+ typedef typename boost::range_value<MultiLineString>::type LineString;
+ typedef typename bg::point_type<Polygon>::type Point;
+ typedef bg::model::ring<Point> Ring;
+
+ test_one_lp<LineString, MultiPolygon, LineString>("case_mp_ls_1", case_multi_simplex[0], "LINESTRING(2 0,2 5)", 2, 4, 3.70);
+ test_one_lp<LineString, Polygon, MultiLineString>("case_p_mls_1", case_single_simplex, "MULTILINESTRING((2 0,2 5),(3 0,3 5))", 2, 4, 7.5);
+ test_one_lp<LineString, MultiPolygon, MultiLineString>("case_mp_mls_1", case_multi_simplex[0], "MULTILINESTRING((2 0,2 5),(3 0,3 5))", 4, 8, 6.8333333);
+ test_one_lp<LineString, Ring, MultiLineString>("case_r_mls_1", case_single_simplex, "MULTILINESTRING((2 0,2 5),(3 0,3 5))", 2, 4, 7.5);
+}
+
+template <typename P>
+void test_all()
+{
+ //typedef bg::model::box<P> box;
+ typedef bg::model::ring<P> ring;
+ typedef bg::model::polygon<P> polygon;
+ typedef bg::model::multi_polygon<polygon> multi_polygon;
+ test_areal<ring, polygon, multi_polygon>();
+
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+
+ typedef bg::model::ring<P, false> ring_ccw;
+ typedef bg::model::polygon<P, false> polygon_ccw;
+ typedef bg::model::multi_polygon<polygon_ccw> multi_polygon_ccw;
+ test_areal<ring_ccw, polygon_ccw, multi_polygon_ccw>();
+
+ typedef bg::model::ring<P, true, false> ring_open;
+ typedef bg::model::polygon<P, true, false> polygon_open;
+ typedef bg::model::multi_polygon<polygon_open> multi_polygon_open;
+ test_areal<ring_open, polygon_open, multi_polygon_open>();
+
+ typedef bg::model::ring<P, false, false> ring_open_ccw;
+ typedef bg::model::polygon<P, false, false> polygon_open_ccw;
+ typedef bg::model::multi_polygon<polygon_open_ccw> multi_polygon_open_ccw;
+ test_areal<ring_open_ccw, polygon_open_ccw, multi_polygon_open_ccw>();
+
+ test_areal_clip<polygon, multi_polygon, box>();
+ test_areal_clip<polygon_ccw, multi_polygon_ccw, box>();
+
+ typedef bg::model::linestring<P> linestring;
+ typedef bg::model::multi_linestring<linestring> multi_linestring;
+
+ test_linear<linestring, multi_linestring, box>();
+ test_areal_linear<multi_polygon, multi_linestring>();
+#endif
+
+ test_point_output<P>();
+ // linear
+
+}
+
+
+int test_main(int, char* [])
+{
+ test_all<bg::model::d2::point_xy<double> >();
+
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+ test_all<bg::model::d2::point_xy<float> >();
+
+#if defined(HAVE_TTMATH)
+ std::cout << "Testing TTMATH" << std::endl;
+ test_all<bg::model::d2::point_xy<ttmath_big> >();
+#endif
+
+#endif
+
+ return 0;
+}
diff --git a/libs/geometry/test/algorithms/set_operations/intersection/test_intersection.hpp b/libs/geometry/test/algorithms/set_operations/intersection/test_intersection.hpp
new file mode 100644
index 000000000..4a7cc645c
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/intersection/test_intersection.hpp
@@ -0,0 +1,285 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Unit Test
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_TEST_INTERSECTION_HPP
+#define BOOST_GEOMETRY_TEST_INTERSECTION_HPP
+
+#include <fstream>
+#include <iomanip>
+
+#include <boost/foreach.hpp>
+#include <boost/variant/variant.hpp>
+
+#include <boost/geometry/algorithms/intersection.hpp>
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/correct.hpp>
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+
+#include <boost/geometry/geometries/geometries.hpp>
+
+#include <boost/geometry/strategies/strategies.hpp>
+
+#include <boost/geometry/io/wkt/wkt.hpp>
+
+
+#if defined(TEST_WITH_SVG)
+# include <boost/geometry/io/svg/svg_mapper.hpp>
+#endif
+
+#include <geometry_test_common.hpp>
+
+template <typename G1, typename G2, typename OutputType>
+typename bg::default_area_result<G1>::type
+check_result(
+ std::vector<OutputType> const& intersection_output,
+ std::string const& caseid,
+ std::size_t expected_count = 0, int expected_point_count = 0,
+ double expected_length_or_area = 0,
+ double percentage = 0.0001,
+ bool debug = false)
+{
+ bool const is_line = bg::geometry_id<OutputType>::type::value == 2;
+
+ typename bg::default_area_result<G1>::type length_or_area = 0;
+ int n = 0;
+ for (typename std::vector<OutputType>::const_iterator it = intersection_output.begin();
+ it != intersection_output.end();
+ ++it)
+ {
+ if (expected_point_count > 0)
+ {
+ n += bg::num_points(*it, true);
+ }
+
+ // instead of specialization we check it run-time here
+ length_or_area += is_line
+ ? bg::length(*it)
+ : bg::area(*it);
+
+ if (debug)
+ {
+ std::cout << std::setprecision(20) << bg::wkt(*it) << std::endl;
+ }
+ }
+
+#if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST)
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ if (expected_point_count > 0)
+ {
+ BOOST_CHECK_MESSAGE(bg::math::abs(n - expected_point_count) < 3,
+ "intersection: " << caseid
+ << " #points expected: " << expected_point_count
+ << " detected: " << n
+ << " type: " << (type_for_assert_message<G1, G2>())
+ );
+ }
+#endif
+
+ if (expected_count > 0)
+ {
+ BOOST_CHECK_MESSAGE(intersection_output.size() == expected_count,
+ "intersection: " << caseid
+ << " #outputs expected: " << expected_count
+ << " detected: " << intersection_output.size()
+ << " type: " << (type_for_assert_message<G1, G2>())
+ );
+ }
+
+ double const detected_length_or_area = boost::numeric_cast<double>(length_or_area);
+ BOOST_CHECK_CLOSE(detected_length_or_area, expected_length_or_area, percentage);
+#endif
+
+ return length_or_area;
+}
+
+
+template <typename OutputType, typename CalculationType, typename G1, typename G2>
+typename bg::default_area_result<G1>::type test_intersection(std::string const& caseid,
+ G1 const& g1, G2 const& g2,
+ std::size_t expected_count = 0, int expected_point_count = 0,
+ double expected_length_or_area = 0,
+ double percentage = 0.0001,
+ bool debug = false)
+{
+ if (debug)
+ {
+ std::cout << std::endl << "case " << caseid << std::endl;
+ }
+
+ typedef typename bg::point_type<G1>::type point_type;
+
+ if (! debug)
+ {
+ // Check _inserter behaviour with stratey
+ typedef bg::strategy_intersection
+ <
+ typename bg::cs_tag<point_type>::type,
+ G1,
+ G2,
+ point_type,
+ typename bg::rescale_policy_type<point_type>::type,
+ CalculationType
+ > strategy;
+ std::vector<OutputType> clip;
+ bg::detail::intersection::intersection_insert<OutputType>(g1, g2, std::back_inserter(clip), strategy());
+ }
+
+ typename bg::default_area_result<G1>::type length_or_area = 0;
+
+ // Check normal behaviour
+ std::vector<OutputType> intersection_output;
+ bg::intersection(g1, g2, intersection_output);
+
+ check_result<G1, G2>(intersection_output, caseid, expected_count, expected_point_count,
+ expected_length_or_area, percentage, debug);
+
+ // Check variant behaviour
+ intersection_output.clear();
+ bg::intersection(boost::variant<G1>(g1), g2, intersection_output);
+
+ check_result<G1, G2>(intersection_output, caseid, expected_count, expected_point_count,
+ expected_length_or_area, percentage, debug);
+
+ intersection_output.clear();
+ bg::intersection(g1, boost::variant<G2>(g2), intersection_output);
+
+ check_result<G1, G2>(intersection_output, caseid, expected_count, expected_point_count,
+ expected_length_or_area, percentage, debug);
+
+ intersection_output.clear();
+ bg::intersection(boost::variant<G1>(g1), boost::variant<G2>(g2), intersection_output);
+
+ check_result<G1, G2>(intersection_output, caseid, expected_count, expected_point_count,
+ expected_length_or_area, percentage, debug);
+
+#if defined(TEST_WITH_SVG)
+ {
+ bool const is_line = bg::geometry_id<OutputType>::type::value == 2;
+ typedef typename bg::coordinate_type<G1>::type coordinate_type;
+
+ bool const ccw =
+ bg::point_order<G1>::value == bg::counterclockwise
+ || bg::point_order<G2>::value == bg::counterclockwise;
+ bool const open =
+ bg::closure<G1>::value == bg::open
+ || bg::closure<G2>::value == bg::open;
+
+ std::ostringstream filename;
+ filename << "intersection_"
+ << caseid << "_"
+ << string_from_type<coordinate_type>::name()
+ << string_from_type<CalculationType>::name()
+ << (ccw ? "_ccw" : "")
+ << (open ? "_open" : "")
+#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ << "_no_rob"
+#endif
+ << ".svg";
+
+ std::ofstream svg(filename.str().c_str());
+
+ bg::svg_mapper<point_type> mapper(svg, 500, 500);
+
+ mapper.add(g1);
+ mapper.add(g2);
+
+ mapper.map(g1, is_line
+ ? "opacity:0.6;stroke:rgb(0,255,0);stroke-width:5"
+ : "fill-opacity:0.5;fill:rgb(153,204,0);"
+ "stroke:rgb(153,204,0);stroke-width:3");
+ mapper.map(g2, "fill-opacity:0.3;fill:rgb(51,51,153);"
+ "stroke:rgb(51,51,153);stroke-width:3");
+
+ for (typename std::vector<OutputType>::const_iterator it = intersection_output.begin();
+ it != intersection_output.end(); ++it)
+ {
+ mapper.map(*it, "fill-opacity:0.2;stroke-opacity:0.4;fill:rgb(255,0,0);"
+ "stroke:rgb(255,0,255);stroke-width:8");
+ }
+ }
+#endif
+
+
+ if (debug)
+ {
+ std::cout << "end case " << caseid << std::endl;
+ }
+
+ return length_or_area;
+}
+
+template <typename OutputType, typename G1, typename G2>
+typename bg::default_area_result<G1>::type test_one(std::string const& caseid,
+ std::string const& wkt1, std::string const& wkt2,
+ std::size_t expected_count = 0, int expected_point_count = 0,
+ double expected_length_or_area = 0,
+ double percentage = 0.0001,
+ bool debug = false)
+{
+ G1 g1;
+ bg::read_wkt(wkt1, g1);
+
+ G2 g2;
+ bg::read_wkt(wkt2, g2);
+
+ // Reverse if necessary
+ bg::correct(g1);
+ bg::correct(g2);
+
+ return test_intersection<OutputType, void>(caseid, g1, g2,
+ expected_count, expected_point_count,
+ expected_length_or_area, percentage,
+ debug);
+}
+
+template <typename OutputType, typename Areal, typename Linear>
+void test_one_lp(std::string const& caseid,
+ std::string const& wkt_areal, std::string const& wkt_linear,
+ std::size_t expected_count = 0, int expected_point_count = 0,
+ double expected_length = 0,
+ double percentage = 0.0001,
+ bool debug1 = false, bool debug2 = false)
+{
+ Areal areal;
+ bg::read_wkt(wkt_areal, areal);
+ bg::correct(areal);
+
+ Linear linear;
+ bg::read_wkt(wkt_linear, linear);
+
+ test_intersection<OutputType, void>(caseid, areal, linear,
+ expected_count, expected_point_count,
+ expected_length, percentage, debug1);
+
+ // A linestring reversed should deliver exactly the same.
+ bg::reverse(linear);
+
+ test_intersection<OutputType, void>(caseid + "_rev", areal, linear,
+ expected_count, expected_point_count,
+ expected_length, percentage, debug2);
+}
+
+template <typename Geometry1, typename Geometry2>
+void test_point_output(std::string const& wkt1, std::string const& wkt2, unsigned int expected_count)
+{
+ Geometry1 g1;
+ bg::read_wkt(wkt1, g1);
+ bg::correct(g1);
+
+ Geometry2 g2;
+ bg::read_wkt(wkt2, g2);
+ bg::correct(g2);
+
+ std::vector<typename bg::point_type<Geometry1>::type> points;
+ bg::intersection(g1, g2, points);
+ BOOST_CHECK_EQUAL(points.size(), expected_count);
+}
+
+
+#endif
diff --git a/libs/geometry/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp b/libs/geometry/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp
new file mode 100644
index 000000000..8e9254040
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/intersection/test_intersection_linear_linear.hpp
@@ -0,0 +1,229 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#ifndef BOOST_GEOMETRY_TEST_INTERSECTION_LINEAR_LINEAR_HPP
+#define BOOST_GEOMETRY_TEST_INTERSECTION_LINEAR_LINEAR_HPP
+
+#include <limits>
+
+#include <boost/geometry/multi/geometries/multi_point.hpp>
+#include <boost/geometry/geometry.hpp>
+#include "../test_set_ops_linear_linear.hpp"
+#include <from_wkt.hpp>
+#include <to_svg.hpp>
+
+
+//==================================================================
+//==================================================================
+// intersection of (linear) geometries
+//==================================================================
+//==================================================================
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename MultiLineString
+>
+class test_intersection_of_geometries
+{
+private:
+ static inline void base_test(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiLineString const& mls_int1,
+ MultiLineString const& mls_int2,
+ std::string const& case_id,
+ double tolerance,
+ bool test_vector_and_deque = false)
+ {
+ static bool vector_deque_already_tested = false;
+
+ typedef typename boost::range_value<MultiLineString>::type LineString;
+ typedef std::vector<LineString> linestring_vector;
+ typedef std::deque<LineString> linestring_deque;
+
+ MultiLineString mls_output;
+
+ linestring_vector ls_vector_output;
+ linestring_deque ls_deque_output;
+
+ bg::intersection(geometry1, geometry2, mls_output);
+
+ BOOST_CHECK_MESSAGE( equals::apply(mls_int1, mls_output, tolerance)
+ || equals::apply(mls_int2, mls_output, tolerance),
+ "case id: " << case_id
+ << ", intersection L/L: " << bg::wkt(geometry1)
+ << " " << bg::wkt(geometry2)
+ << " -> Expected: " << bg::wkt(mls_int1)
+ << " or: " << bg::wkt(mls_int2)
+ << " computed: " << bg::wkt(mls_output) );
+
+ set_operation_output("intersection", case_id,
+ geometry1, geometry2, mls_output);
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl;
+ std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl;
+ std::cout << "intersection : " << bg::wkt(mls_output) << std::endl;
+ std::cout << "expected intersection : " << bg::wkt(mls_int1)
+ << std::endl;
+ std::cout << std::endl;
+ std::cout << "************************************" << std::endl;
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+
+ if ( !vector_deque_already_tested && test_vector_and_deque )
+ {
+ vector_deque_already_tested = true;
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl;
+ std::cout << "Testing with vector and deque as output container..."
+ << std::endl;
+#endif
+ bg::intersection(geometry1, geometry2, ls_vector_output);
+ bg::intersection(geometry1, geometry2, ls_deque_output);
+
+ BOOST_CHECK(multilinestring_equals
+ <
+ false
+ >::apply(mls_int1, ls_vector_output, tolerance));
+
+ BOOST_CHECK(multilinestring_equals
+ <
+ false
+ >::apply(mls_int1, ls_deque_output, tolerance));
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Done!" << std::endl << std::endl;
+#endif
+ }
+
+ // check the intersection where the order of the two
+ // geometries is reversed
+ bg::clear(mls_output);
+ bg::intersection(geometry2, geometry1, mls_output);
+
+ BOOST_CHECK_MESSAGE( equals::apply(mls_int1, mls_output, tolerance)
+ || equals::apply(mls_int2, mls_output, tolerance),
+ "case id: " << case_id
+ << ", intersection L/L: " << bg::wkt(geometry1)
+ << " " << bg::wkt(geometry2)
+ << " -> Expected: " << bg::wkt(mls_int1)
+ << " or: " << bg::wkt(mls_int2)
+ << " computed: " << bg::wkt(mls_output) );
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Geometry #1: " << bg::wkt(geometry2) << std::endl;
+ std::cout << "Geometry #2: " << bg::wkt(geometry1) << std::endl;
+ std::cout << "intersection : " << bg::wkt(mls_output) << std::endl;
+ std::cout << "expected intersection : " << bg::wkt(mls_int2)
+ << std::endl;
+ std::cout << std::endl;
+ std::cout << "************************************" << std::endl;
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+ }
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ static inline void base_test_all(Geometry1 const& geometry1,
+ Geometry2 const& geometry2)
+ {
+ typedef typename bg::point_type<MultiLineString>::type Point;
+ typedef bg::model::multi_point<Point> multi_point;
+
+ MultiLineString mls12_output, mls21_output;
+ multi_point mp12_output, mp21_output;
+
+ bg::intersection(geometry1, geometry2, mls12_output);
+ bg::intersection(geometry1, geometry2, mp12_output);
+ bg::intersection(geometry2, geometry1, mls21_output);
+ bg::intersection(geometry2, geometry1, mp21_output);
+
+ std::cout << "************************************" << std::endl;
+ std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl;
+ std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl;
+ std::cout << "intersection(1,2) [MLS]: " << bg::wkt(mls12_output)
+ << std::endl;
+ std::cout << "intersection(2,1) [MLS]: " << bg::wkt(mls21_output)
+ << std::endl;
+ std::cout << std::endl;
+ std::cout << "intersection(1,2) [MP]: " << bg::wkt(mp12_output)
+ << std::endl;
+ std::cout << "intersection(2,1) [MP]: " << bg::wkt(mp21_output)
+ << std::endl;
+ std::cout << std::endl;
+ std::cout << "************************************" << std::endl;
+ std::cout << std::endl;
+ std::cout << std::endl;
+ }
+#else
+ static inline void base_test_all(Geometry1 const&, Geometry2 const&)
+ {
+ }
+#endif
+
+
+public:
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiLineString const& mls_int1,
+ MultiLineString const& mls_int2,
+ std::string const& case_id,
+ double tolerance
+ = std::numeric_limits<double>::epsilon())
+ {
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "test case: " << case_id << std::endl;
+ std::stringstream sstr;
+ sstr << "svgs/" << case_id << ".svg";
+#ifdef TEST_WITH_SVG
+ to_svg(geometry1, geometry2, sstr.str());
+#endif
+#endif
+
+ Geometry1 rg1(geometry1);
+ bg::reverse<Geometry1>(rg1);
+
+ Geometry2 rg2(geometry2);
+ bg::reverse<Geometry2>(rg2);
+
+ test_get_turns_ll_invariance<>::apply(geometry1, geometry2);
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl
+ << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
+ << std::endl << std::endl;
+#endif
+ test_get_turns_ll_invariance<>::apply(rg1, geometry2);
+
+
+ base_test(geometry1, geometry2, mls_int1, mls_int2, case_id, tolerance);
+ // base_test(rg1, rg2, mls_int1, mls_int2);
+ base_test_all(geometry1, geometry2);
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+ }
+
+
+
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiLineString const& mls_int,
+ std::string const& case_id,
+ double tolerance
+ = std::numeric_limits<double>::epsilon())
+ {
+ apply(geometry1, geometry2, mls_int, mls_int, case_id, tolerance);
+ }
+};
+
+
+#endif // BOOST_GEOMETRY_TEST_INTERSECTION_LINEAR_LINEAR_HPP
diff --git a/libs/geometry/test/algorithms/set_operations/set_ops_ll.cpp b/libs/geometry/test/algorithms/set_operations/set_ops_ll.cpp
new file mode 100644
index 000000000..c3311a054
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/set_ops_ll.cpp
@@ -0,0 +1,17 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#ifndef BOOST_TEST_MODULE
+#define BOOST_TEST_MODULE test_set_ops_linear_linear
+#endif
+
+#include "intersection_linear_linear.cpp"
+#include "union_linear_linear.cpp"
+#include "difference_linear_linear.cpp"
+#include "sym_difference_linear_linear.cpp"
diff --git a/libs/geometry/test/algorithms/set_operations/set_ops_pp.cpp b/libs/geometry/test/algorithms/set_operations/set_ops_pp.cpp
new file mode 100644
index 000000000..725737e1b
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/set_ops_pp.cpp
@@ -0,0 +1,16 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#ifndef BOOST_TEST_MODULE
+#define BOOST_TEST_MODULE test_set_ops_pointlike_pointlike
+#endif
+
+#include "intersection_pl_pl.cpp"
+#include "union_pl_pl.cpp"
+#include "difference_pl_pl.cpp"
diff --git a/libs/geometry/test/algorithms/set_operations/sym_difference/Jamfile.v2 b/libs/geometry/test/algorithms/set_operations/sym_difference/Jamfile.v2
new file mode 100644
index 000000000..f64bb92ba
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/sym_difference/Jamfile.v2
@@ -0,0 +1,20 @@
+# Boost.Geometry (aka GGL, Generic Geometry Library)
+#
+# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+# Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+# Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+#
+# This file was modified by Oracle on 2014.
+# Modifications copyright (c) 2014, Oracle and/or its affiliates.
+#
+# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+#
+# Use, modification and distribution is subject to the Boost Software License,
+# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+test-suite boost-geometry-algorithms-sym_difference
+ :
+ [ run sym_difference_linear_linear.cpp ]
+ ;
diff --git a/libs/geometry/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp b/libs/geometry/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp
new file mode 100644
index 000000000..bcd0398ad
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/sym_difference/sym_difference_linear_linear.cpp
@@ -0,0 +1,988 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014-2015 Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#include <iostream>
+
+#ifndef BOOST_TEST_MODULE
+#define BOOST_TEST_MODULE test_sym_difference_linear_linear
+#endif
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+#define BOOST_GEOMETRY_DEBUG_TURNS
+#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
+#endif
+
+#include <boost/test/included/unit_test.hpp>
+
+#include "test_sym_difference_linear_linear.hpp"
+
+#include <boost/geometry/geometries/linestring.hpp>
+#include <boost/geometry/multi/geometries/multi_linestring.hpp>
+#include <boost/geometry/algorithms/sym_difference.hpp>
+
+typedef bg::model::point<double,2,bg::cs::cartesian> point_type;
+typedef bg::model::segment<point_type> segment_type;
+typedef bg::model::linestring<point_type> linestring_type;
+typedef bg::model::multi_linestring<linestring_type> multi_linestring_type;
+
+
+
+//===========================================================================
+//===========================================================================
+//===========================================================================
+
+
+BOOST_AUTO_TEST_CASE( test_sym_difference_linestring_linestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** LINESTRING / LINESTRING SYMMETRIC DIFFERENCE ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_sym_difference_of_geometries<L, L, ML> tester;
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 1,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(0 2,1 1,2 1,3 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1),(2 1,3 2),\
+ (0 2,1 1),(2 1,3 0))"),
+ "llsdf00");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,5 0)"),
+ from_wkt<L>("LINESTRING(3 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,3 0),(4 0,5 0))"),
+ "llsdf01");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,6 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,3 0),(4 0,6 0))"),
+ "llsdf01-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,6 0)"),
+ from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((4 0,6 0))"),
+ "llsdf01-2");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<L>("LINESTRING(0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,4 0),(5 0,20 0),\
+ (0 0,1 1,2 0,3 1,4 0),(5 0,6 1,7 -1,8 0))"),
+ "llsdf01-3");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-20 0,20 0)"),
+ from_wkt<L>("LINESTRING(0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0)"),
+ from_wkt<ML>("MULTILINESTRING((-20 0,4 0),(5 0,20 0),\
+ (0 0,1 1,2 0,3 1,4 0),(5 0,6 1,7 -1,8 0))"),
+ "llsdf01-4");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<L>("LINESTRING(2 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0))"),
+ "llsdf01-5");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0)"),
+ from_wkt<L>("LINESTRING(4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,5 0))"),
+ "llsdf01-6");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0)"),
+ from_wkt<L>("LINESTRING(2 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(2 0,5 0))"),
+ "llsdf01-7");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,3 0),(4 0,5 0))"),
+ "llsdf01-8");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,3 0),(4 0,5 0))"),
+ "llsdf01-9");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,6 0)"),
+ from_wkt<L>("LINESTRING(2 0,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(5 0,6 0))"),
+ "llsdf01-10");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,5 5,10 5,15 0)"),
+ from_wkt<L>("LINESTRING(-1 6,0 5,15 5)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,5 5),(10 5,15 0),\
+ (-1 6,0 5,5 5),(10 5,15 5))"),
+ "llsdf02");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (-1 0,0 0),(1 0,15 0),(20 0,30 0))"),
+ "llsdf03");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,5 5,10 5,15 0,20 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 5,10 5,15 0),\
+ (-1 0,0 0),(1 0,15 0),(20 0,30 0))"),
+ "llsdf04");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,25 1)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (20 0,25 1),(-1 0,0 0),(1 0,15 0),(20 0,30 0))"),
+ "llsdf05");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (-1 0,0 0),(1 0,15 0))"),
+ "llsdf05-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (30 0,31 0),(-1 0,0 0),(1 0,15 0))"),
+ "llsdf06");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,25 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (30 0,31 0),(-1 0,0 0),(1 0,15 0))"),
+ "llsdf07");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (30 0,31 0),(-1 0,0 0),(1 0,15 0))"),
+ "llsdf08");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (30 0,31 1),(-1 0,0 0),(1 0,15 0))"),
+ "llsdf09");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(1 0,5 5,10 5,15 0),\
+ (30 0,31 1),(-1 -1,0 0),(1 0,2 1,3 0,15 0))"),
+ "llsdf10");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,20 0,\
+ 30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(2 0,3 0),\
+ (4 0,5 5,10 5,15 0),(30 0,31 1),(-1 -1,0 0),\
+ (2 0,2.5 1,3 0),(4 0,15 0))"),
+ "llsdf11");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(2 0,3 0),\
+ (4 0,5 5,10 5,15 0),(30 0,31 0),(-1 -1,0 0),\
+ (2 0,2.5 1,3 0),(4 0,15 0))"),
+ "llsdf11-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "llsdf12");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<L>("LINESTRING(3 1,2 0,0 0)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "llsdf12-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 5,4 0)"),
+ from_wkt<L>("LINESTRING(1 0,2 1,3 5,4 0,5 10)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(4 0,5 10))"),
+ "llsdf13");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 0,2.5 0,3 1)"),
+ from_wkt<L>("LINESTRING(0 0,2 0,2.5 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING()"),
+ "llsdf14");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 5,4 0)"),
+ from_wkt<L>("LINESTRING(1 0,2 1,3 5)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(3 5,4 0))"),
+ "llsdf15");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(0.5 0,1 0,3 2,4 5)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,0.5 0),(3 2,4 5))"),
+ "llsdf16");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(4 5,3 2,1 0,0.5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,0.5 0),(4 5,3 2))"),
+ "llsdf16-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1,30 1)"),
+ from_wkt<L>("LINESTRING(1 1,2 0,3 1,20 1,25 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(25 1,30 1),\
+ (1 1,2 0,3 1,20 1))"),
+ "llsdf17");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1,21 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 1,2 0,3 1,20 1,25 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1,21 0,30 0),\
+ (1 1,2 0,3 1,20 1,25 0))"),
+ "llsdf18");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (5 0,20 1,4 1,4 0,5 1))"),
+ "llsdf19");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,4 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (5 1,4 0,4 1,20 1,5 0))"),
+ "llsdf19-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (5 0,20 1,4 1,4 0))"),
+ "llsdf19a");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(4 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (4 0,4 1,20 1,5 0))"),
+ "llsdf19a-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (5 0,20 1,4 1,4 0))"),
+ "llsdf19b");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0,6 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (5 0,20 1,4 1,4 0),(5 0,6 1))"),
+ "llsdf19c");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,3 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (5 0,20 1,4 1,4 0))"),
+ "llsdf19d");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,3 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (5 0,20 1,4 1,4 0),(3 0,3 1))"),
+ "llsdf19e");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0,5 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (5 0,20 1,4 1,4 0),(5 0,5 1))"),
+ "llsdf19f");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,5 0,4 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (5 1,5 0),(4 0,4 1,20 1,5 0))"),
+ "llsdf19f-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,5 0,5 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (5 0,20 1,4 1,5 0,5 1))"),
+ "llsdf19g");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,5 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(5 0,30 0),\
+ (5 1,5 0,4 1,20 1,5 0))"),
+ "llsdf19g-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0,30 30,10 30,10 -10,15 0,40 0)"),
+ from_wkt<L>("LINESTRING(5 5,10 0,10 30,20 0,25 0,25 25,50 0,35 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(25 0,30 0,30 30,10 30),\
+ (10 0,10 -10,15 0,20 0),(25 0,35 0),\
+ (5 5,10 0),(10 30,20 0),(25 0,25 25,50 0,40 0))"),
+ "llsdf20");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0,30 30,10 30,10 -10,15 0,40 0)"),
+ from_wkt<L>("LINESTRING(5 5,10 0,10 30,20 0,25 0,25 25,50 0,15 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,15 0),(30 0,30 30,10 30),\
+ (10 0,10 -10,15 0),(5 5,10 0),(10 30,20 0),\
+ (25 0,25 25,50 0,40 0))"),
+ "llsdf20a");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<L>("LINESTRING(2 2,5 -1,15 2,18 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,18 0),(20 0,30 0),\
+ (2 2,5 -1,15 2,18 0))"),
+ "llsdf21"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 -3,5 4,6 6,-3 2,-3 0,-3 -10,9 -2,\
+ 9 5,5 -5,-4 -8,9 0)"),
+ from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,\
+ 2 8,-6 1,10 -6)"),
+ from_wkt<ML>("MULTILINESTRING((0 -3,5 4,6 6,-3 2),\
+ (-3 0,-3 -10,9 -2,9 5,5 -5,-4 -8,9 0),(-3 6,-3 2),\
+ (-3 2,-3 5,2 -3,-6 10,5 0,2 8,-6 1,10 -6))"),
+ "llsdf22"
+ );
+}
+
+
+
+BOOST_AUTO_TEST_CASE( test_sym_difference_linestring_multilinestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** LINESTRING / MULTILINESTRING SYMMETRIC DIFFERENCE ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_sym_difference_of_geometries<L, ML, ML> tester;
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 2,4 3),(1 1,2 2,5 3))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),\
+ (1 1,2 2,4 3),(1 1,2 2,5 3))"),
+ "lmlsdf01"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\
+ (1 1,2 0),(1 1,3 0))"),
+ "lmlsdf02"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(5 0,10 0,20 1),\
+ (1 1,2 0),(1 1,3 0))"),
+ "lmlsdf03"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\
+ (1 1,2 0))"),
+ "lmlsdf04"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(-1 -1,1 0),(101 0,200 -1))"),
+ "lmlsdf07"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(-1 -1,0 0),\
+ (19 -1,20 0),(101 0,200 -1))"),
+ "lmlsdf07a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0),(19 -1,20 0),\
+ (101 0,200 -1))"),
+ "lmlsdf07b"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(0 1,1 1,2 0),\
+ (-1 -1,1 0),(101 0,200 -1))"),
+ "lmlsdf08"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 0.5,3 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0.5,3 0),\
+ (0 1,1 1,2 0.5),(-1 -1,1 0,3 0),(101 0,200 -1))"),
+ "lmlsdf09"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,1.5 0,2 0.5,3 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,1 0,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(1.5 0,2 0.5,3 0),\
+ (0 1,1 1,1 0,2 0.5),(-1 -1,1 0),(1.5 0,3 0),\
+ (101 0,200 -1))"),
+ "lmlsdf10"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (1 1,2 0,18 0,19 1),(2 1,3 0,17 0,18 1),\
+ (3 1,4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1),(1 1,2 0),(18 0,19 1),\
+ (2 1,3 0),(17 0,18 1),(3 1,4 0),(16 0,17 1))"),
+ "lmlsdf12"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0,20 1),\
+ (2 0,18 0,19 1),(3 0,17 0,18 1),\
+ (4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (19 0,20 1),(18 0,19 1),(17 0,18 1),(16 0,17 1))"),
+ "lmlsdf13"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(2 0,18 0),(3 0,17 0),\
+ (4 0,16 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "lmlsdf13a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1,19 1,18 0),(2 0,1 1,2 1,3 0),\
+ (17 0,18 1,17 1,16 0),(4 0,3 1))"),
+ "lmlsdf14"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,4 2,6 0))"),
+ "lmlsdf15"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1),(6 0,4 2,2 2))"),
+ "lmlsdf15a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,5 0,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,4 2,5 0))"),
+ "lmlsdf16"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,5 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1),(5 0,4 2,2 2))"),
+ "lmlsdf16a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,4 0,5 2,20 2,25 0))"),
+ "lmlsdf17"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0,26 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,4 0,5 2,20 2,25 0,26 2))"),
+ "lmlsdf17a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,5 -1,15 2,18 0))"),
+ "lmlsdf18"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,5 -1,15 2,18 0))"),
+ "lmlsdf18a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(20 0,30 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,5 -1,15 2,18 0))"),
+ "lmlsdf18b"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,25 0,26 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,25 0),(26 0,30 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,5 -1,15 2,25 0))"),
+ "lmlsdf18c"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,25 0,21 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,21 0),(25 0,30 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,5 -1,15 2,25 0))"),
+ "lmlsdf18d"
+ );
+
+#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS
+ tester::apply
+ (from_wkt<L>("LINESTRING(1 5,4 2,1 -1.1,1 6,1 189.7654,2 5,-0.7654 3)"),
+ from_wkt<ML>("MULTILINESTRING((2 5,-0.7654 2),\
+ (-1032.34324 4,1 5,9 7,3 9,0.2 5,1 -0.3),\
+ (1 0.9,1 6,1 -0.6,2.232432 -0.7654,0.9 3,1 5,\
+ -0.7654 9,3 0.1,9 0,-6 8,-0.7 8,0 1,-1032.34324 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 5,-0.7654 2),\
+ (-1032.34324 4,1 5,9 7,3 9,0.2 5,1 -0.3),\
+ (1 -0.6,2.232432 -0.7654,0.9 3,1 5,-0.7654 9,\
+ 3 0.1,9 0,-6 8,-0.7 8,0 1,-1032.34324 0),\
+ (1 5,4 2,1 -1.1,1 -0.6),\
+ (1 6,1 189.7654,2 5,-0.7654 3))"),
+ "lmlsdf19",
+ 1e-10
+ );
+#endif
+}
+
+
+
+
+BOOST_AUTO_TEST_CASE( test_sym_difference_multilinestring_linestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / LINESTRING SYMMETRIC DIFFERENCE ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_sym_difference_of_geometries<ML, L, ML> tester;
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<L>("LINESTRING(1 1,2 2,4 3)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (1 1,2 2,4 3))"),
+ "mllsdf01"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<L>("LINESTRING(1 1,2 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\
+ (1 0,2 0),(4 0,7 0),(1 1,2 0))"),
+ "mllsdf02"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<L>("LINESTRING(-1 -1,1 0,101 0,200 -1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(-1 -1,1 0),(101 0,200 -1))"),
+ "mllsdf03"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<L>("LINESTRING(0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1,19 1,18 0),(2 0,1 1,2 1,3 0),\
+ (17 0,18 1,17 1,16 0),(4 0,3 1))"),
+ "mllsdf04"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 -3,5 4,6 6,-3 2,-3 0,\
+ -3 -10,9 -2,9 5,5 -5,-4 -8,9 0),\
+ (-7 9,-4 -9,-5 -10,5 3),\
+ (-8 -3,-6 6,-9 0,-4 -3,-1 -10),\
+ (0 1,7 -1,-2 3,-7 1),\
+ (-5 -9,-4 -10,7 -10,0 -6,1 6,2 -1,1 5,-5 -5))"),
+ from_wkt<L>("LINESTRING(-3 6,-3 0,-3 5,2 -3,-6 10,5 0,2 8,\
+ -6 1,10 -6)"),
+ from_wkt<ML>("MULTILINESTRING((0 -3,5 4,6 6,-3 2),\
+ (-3 0,-3 -10,9 -2,9 5,5 -5,-4 -8,9 0),\
+ (-7 9,-4 -9,-5 -10,5 3),\
+ (-8 -3,-6 6,-9 0,-4 -3,-1 -10),\
+ (0 1,7 -1,-2 3,-7 1),\
+ (-5 -9,-4 -10,7 -10,0 -6,1 6,2 -1,1 5,-5 -5),\
+ (-3 6,-3 2),(-3 2,-3 5,2 -3,-6 10,5 0,2 8,-6 1,10 -6))"),
+ "mllsdf05"
+ );
+}
+
+
+
+
+
+
+BOOST_AUTO_TEST_CASE( test_sym_difference_multilinestring_multilinestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / MULTILINESTRING SYMMETRIC DIFFERENCE ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef multi_linestring_type ML;
+
+ typedef test_sym_difference_of_geometries<ML, ML, ML> tester;
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 2,4 3),(1 1,2 2,5 3))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (1 1,2 2,4 3),(1 1,2 2,5 3))"),
+ "mlmlsdf01"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\
+ (1 0,2 0),(4 0,7 0),(1 1,2 0),(1 1,3 0))"),
+ "mlmlsdf02"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(5 0,10 0,20 1),\
+ (1 0,2 0),(5 0,7 0),(1 1,2 0),(1 1,3 0))"),
+ "mlmlsdf03"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\
+ (1 0,2 0),(4 0,7 0),(1 1,2 0))"),
+ "mlmlsdf04"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (10 10,20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (10 20,15 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,10 0,20 1),\
+ (1 0,2 0),(4 0,7 0),(10 10,15 10),(20 10,30 20),\
+ (1 1,2 0),(10 20,15 10),(20 10,25 10,30 15))"),
+ "mlmlsdf05"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (10 10,20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (-1 -1,0 0,9 0,11 10,12 10,13 0.3,14 0.4,15 0.5),\
+ (10 20,15 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((9 0,10 0,13 0.3),(15 0.5,20 1),\
+ (10 10,11 10),(12 10,15 10),(20 10,30 20),\
+ (1 1,2 0),(-1 -1,0 0),(9 0,11 10),(12 10,13 0.3),\
+ (10 20,15 10),(20 10,25 10,30 15))"),
+ "mlmlsdf06"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 10),(1 0,7 0),\
+ (10 10,20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (-1 -1,0 0,9 0,11 10,12 10,13 3,14 4,15 5),\
+ (10 20,15 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((9 0,10 0,13 3),(15 5,20 10),\
+ (10 10,11 10),(12 10,15 10),(20 10,30 20),\
+ (1 1,2 0),(-1 -1,0 0),(9 0,11 10),(12 10,13 3),\
+ (10 20,15 10),(20 10,25 10,30 15))"),
+ "mlmlsdf06a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(-1 -1,1 0),\
+ (101 0,200 -1))"),
+ "mlmlsdf07"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((-1 1,0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0),(-1 -1,0 0),\
+ (19 -1,20 0),(101 0,200 -1))"),
+ "mlmlsdf07a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0),(19 -1,20 0),\
+ (101 0,200 -1))"),
+ "mlmlsdf07b"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(0 1,1 1,2 0),\
+ (-1 -1,1 0),(101 0,200 -1))"),
+ "mlmlsdf08"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0.5,3 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0.5,3 0),(0 1,1 1,2 0.5),\
+ (-1 -1,1 0,3 0),(101 0,200 -1))"),
+ "mlmlsdf09"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 0,1.5 0,2 0.5,3 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,1 0,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(1.5 0,2 0.5,3 0),\
+ (0 1,1 1,1 0,2 0.5),(-1 -1,1 0),(1.5 0,3 0),\
+ (101 0,200 -1))"),
+ "mlmlsdf10"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 1,100 1,101 0),\
+ (0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1,3 0,4 0,5 1,6 1,\
+ 7 0,8 0,9 1,10 1,11 0,12 0,13 1,14 1,15 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1),(2 1,5 1),(6 1,9 1),\
+ (10 1,13 1),(14 1,100 1,101 0),(0 0,1 0),\
+ (1 0,1 1),(2 1,3 0),(4 0,5 1),(6 1,7 0),\
+ (8 0,9 1),(10 1,11 0),(12 0,13 1),(14 1,15 0),\
+ (-1 -1,1 0),(101 0,200 -1))"),
+ "mlmlsdf11"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (1 1,2 0,18 0,19 1),(2 1,3 0,17 0,18 1),\
+ (3 1,4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1),(1 1,2 0),(18 0,19 1),\
+ (2 1,3 0),(17 0,18 1),(3 1,4 0),(16 0,17 1))"),
+ "mlmlsdf12"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0,20 1),\
+ (2 0,18 0,19 1),(3 0,17 0,18 1),\
+ (4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (19 0,20 1),(18 0,19 1),(17 0,18 1),(16 0,17 1))"),
+ "mlmlsdf13"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0),(2 0,18 0),(3 0,17 0),\
+ (4 0,16 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0))"),
+ "mlmlsdf13a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1,19 1,18 0),(2 0,1 1,2 1,3 0),\
+ (17 0,18 1,17 1,16 0),(4 0,3 1))"),
+ "mlmlsdf14"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,4 2,6 0))"),
+ "mlmlsdf15"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1),(6 0,4 2,2 2))"),
+ "mlmlsdf15a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,5 0,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,4 2,5 0))"),
+ "mlmlsdf16"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,5 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,20 0),\
+ (0 1,1 0),(19 0,20 1),(5 0,4 2,2 2))"),
+ "mlmlsdf16a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,4 0,5 2,20 2,25 0))"),
+ "mlmlsdf17"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0,26 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,4 0,5 2,20 2,25 0,26 2))"),
+ "mlmlsdf17a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,5 -1,15 2,18 0))"),
+ "mlmlsdf18"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,18 0,19 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0),(19 0,30 0),\
+ (0 1,1 0),(19 0,20 1),(2 2,5 -1,15 2,18 0))"),
+ "mlmlsdf18a"
+ );
+}
diff --git a/libs/geometry/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp b/libs/geometry/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp
new file mode 100644
index 000000000..3676fd9a2
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/sym_difference/test_sym_difference_linear_linear.hpp
@@ -0,0 +1,174 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#ifndef BOOST_GEOMETRY_TEST_SYM_DIFFERENCE_LINEAR_LINEAR_HPP
+#define BOOST_GEOMETRY_TEST_SYM_DIFFERENCE_LINEAR_LINEAR_HPP
+
+#include <limits>
+
+#include <boost/geometry/geometry.hpp>
+#include "../test_set_ops_linear_linear.hpp"
+#include <from_wkt.hpp>
+#include <to_svg.hpp>
+
+
+//==================================================================
+//==================================================================
+// symmetric difference of (linear) geometries
+//==================================================================
+//==================================================================
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename MultiLineString
+>
+class test_sym_difference_of_geometries
+{
+private:
+ static inline void base_test(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiLineString const& mls_sym_diff,
+ std::string const& case_id,
+ double tolerance,
+ bool test_vector_and_deque = false)
+ {
+ static bool vector_deque_already_tested = false;
+
+ typedef typename boost::range_value<MultiLineString>::type LineString;
+ typedef std::vector<LineString> linestring_vector;
+ typedef std::deque<LineString> linestring_deque;
+
+ MultiLineString mls_output;
+
+ linestring_vector ls_vector_output;
+ linestring_deque ls_deque_output;
+
+ bg::sym_difference(geometry1, geometry2, mls_output);
+
+ BOOST_CHECK_MESSAGE( equals::apply(mls_sym_diff, mls_output, tolerance),
+ "case id: " << case_id
+ << ", sym diff L/L: " << bg::wkt(geometry1)
+ << " " << bg::wkt(geometry2)
+ << " -> Expected: " << bg::wkt(mls_sym_diff)
+ << " computed: " << bg::wkt(mls_output) );
+
+
+ set_operation_output("sym_difference", case_id,
+ geometry1, geometry2, mls_output);
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl;
+ std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl;
+ std::cout << "sym_difference : " << bg::wkt(mls_output) << std::endl;
+ std::cout << "expected sym_difference : " << bg::wkt(mls_sym_diff)
+ << std::endl;
+ std::cout << std::endl;
+ std::cout << "************************************" << std::endl;
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+
+ if ( !vector_deque_already_tested && test_vector_and_deque )
+ {
+ vector_deque_already_tested = true;
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl;
+ std::cout << "Testing with vector and deque as output container..."
+ << std::endl;
+#endif
+ bg::sym_difference(geometry1, geometry2, ls_vector_output);
+ bg::sym_difference(geometry1, geometry2, ls_deque_output);
+
+ BOOST_CHECK(multilinestring_equals
+ <
+ false
+ >::apply(mls_sym_diff, ls_vector_output, tolerance));
+
+ BOOST_CHECK(multilinestring_equals
+ <
+ false
+ >::apply(mls_sym_diff, ls_deque_output, tolerance));
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Done!" << std::endl << std::endl;
+#endif
+ }
+
+ // check the symmetric difference where the order of the two
+ // geometries is reversed
+ bg::clear(mls_output);
+ bg::sym_difference(geometry2, geometry1, mls_output);
+
+ BOOST_CHECK_MESSAGE( equals::apply(mls_sym_diff, mls_output, tolerance),
+ "case id: " << case_id
+ << ", sym diff L/L: " << bg::wkt(geometry2)
+ << " " << bg::wkt(geometry1)
+ << " -> Expected: " << bg::wkt(mls_sym_diff)
+ << " computed: " << bg::wkt(mls_output) );
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Geometry #1: " << bg::wkt(geometry2) << std::endl;
+ std::cout << "Geometry #2: " << bg::wkt(geometry1) << std::endl;
+ std::cout << "sym_difference : " << bg::wkt(mls_output) << std::endl;
+ std::cout << "expected sym_difference : " << bg::wkt(mls_sym_diff)
+ << std::endl;
+ std::cout << std::endl;
+ std::cout << "************************************" << std::endl;
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+ }
+
+
+public:
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiLineString const& mls_sym_diff,
+ std::string const& case_id,
+ double tolerance
+ = std::numeric_limits<double>::epsilon())
+ {
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "test case: " << case_id << std::endl;
+ std::stringstream sstr;
+ sstr << "svgs/" << case_id << ".svg";
+#ifdef TEST_WITH_SVG
+ to_svg(geometry1, geometry2, sstr.str());
+#endif
+#endif
+
+ Geometry1 rg1(geometry1);
+ bg::reverse<Geometry1>(rg1);
+
+ Geometry2 rg2(geometry2);
+ bg::reverse<Geometry2>(rg2);
+
+ test_get_turns_ll_invariance<>::apply(geometry1, geometry2);
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl
+ << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
+ << std::endl << std::endl;
+#endif
+ test_get_turns_ll_invariance<>::apply(rg1, geometry2);
+
+ base_test(geometry1, geometry2, mls_sym_diff, case_id, tolerance, true);
+ // base_test(geometry1, rg2, mls_sym_diff);
+ // base_test(rg1, geometry2, mls_sym_diff);
+ base_test(rg1, rg2, mls_sym_diff, case_id, tolerance);
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+ }
+};
+
+
+#endif // BOOST_GEOMETRY_TEST_SYM_DIFFERENCE_LINEAR_LINEAR_HPP
diff --git a/libs/geometry/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp b/libs/geometry/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp
new file mode 100644
index 000000000..b2a962ada
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/test_get_turns_ll_invariance.hpp
@@ -0,0 +1,171 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#ifndef BOOST_GEOMETRY_TEST_GET_TURNS_LL_INVARIANCE_HPP
+#define BOOST_GEOMETRY_TEST_GET_TURNS_LL_INVARIANCE_HPP
+
+#include <vector>
+
+#include <boost/geometry/algorithms/reverse.hpp>
+
+#include <boost/geometry/algorithms/detail/signed_index_type.hpp>
+
+#include <boost/geometry/algorithms/detail/relate/turns.hpp>
+
+#include <boost/geometry/algorithms/detail/turns/compare_turns.hpp>
+#include <boost/geometry/algorithms/detail/turns/print_turns.hpp>
+#include <boost/geometry/algorithms/detail/turns/filter_continue_turns.hpp>
+#include <boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp>
+
+#include <boost/geometry/io/wkt/write.hpp>
+
+
+namespace bg = ::boost::geometry;
+namespace bg_detail = ::boost::geometry::detail;
+namespace bg_turns = bg_detail::turns;
+
+template
+<
+ bool EnableRemoveDuplicateTurns = true,
+ bool EnableDegenerateTurns = true
+>
+class test_get_turns_ll_invariance
+{
+private:
+ struct assign_policy
+ {
+ static bool const include_no_turn = false;
+ static bool const include_degenerate = EnableDegenerateTurns;
+ static bool const include_opposite = false;
+
+ template
+ <
+ typename Info,
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo
+ >
+ static inline void apply(Info& , Point1 const& , Point2 const& ,
+ IntersectionInfo const&)
+ {
+ }
+ };
+
+
+
+ template
+ <
+ typename Turns,
+ typename LinearGeometry1,
+ typename LinearGeometry2
+ >
+ static inline void compute_turns(Turns& turns,
+ LinearGeometry1 const& linear1,
+ LinearGeometry2 const& linear2)
+ {
+ turns.clear();
+ bg_detail::relate::turns::get_turns
+ <
+ LinearGeometry1,
+ LinearGeometry2,
+ bg_detail::get_turns::get_turn_info_type
+ <
+ LinearGeometry1,
+ LinearGeometry2,
+ assign_policy
+ >
+ >::apply(turns, linear1, linear2);
+ }
+
+
+
+public:
+ template <typename Linear1, typename Linear2>
+ static inline void apply(Linear1 const& lineargeometry1,
+ Linear2 const& lineargeometry2)
+ {
+ typedef typename bg_detail::relate::turns::get_turns
+ <
+ Linear1, Linear2
+ >::turn_info turn_info;
+
+ typedef std::vector<turn_info> turns_container;
+
+ typedef bg_turns::filter_continue_turns
+ <
+ turns_container, true
+ > filter_continue_turns;
+
+ typedef bg_turns::remove_duplicate_turns
+ <
+ turns_container, EnableRemoveDuplicateTurns
+ > remove_duplicate_turns;
+
+ turns_container turns;
+
+ Linear1 linear1(lineargeometry1);
+ Linear2 linear2(lineargeometry2);
+
+ Linear2 linear2_reverse(linear2);
+ boost::geometry::reverse(linear2_reverse);
+
+ turns_container turns_all, rturns_all;
+ compute_turns(turns_all, linear1, linear2);
+ compute_turns(rturns_all, linear1, linear2_reverse);
+
+ turns_container turns_wo_cont(turns_all);
+ turns_container rturns_wo_cont(rturns_all);
+
+ filter_continue_turns::apply(turns_wo_cont);
+ filter_continue_turns::apply(rturns_wo_cont);
+
+ std::sort(boost::begin(turns_all), boost::end(turns_all),
+ bg_turns::less_seg_fraction_other_op<>());
+
+ std::sort(boost::begin(turns_wo_cont), boost::end(turns_wo_cont),
+ bg_turns::less_seg_fraction_other_op<>());
+
+ std::sort(boost::begin(rturns_all), boost::end(rturns_all),
+ bg_turns::less_seg_fraction_other_op<std::greater<boost::geometry::signed_index_type> >());
+
+ std::sort(boost::begin(rturns_wo_cont), boost::end(rturns_wo_cont),
+ bg_turns::less_seg_fraction_other_op<std::greater<boost::geometry::signed_index_type> >());
+
+ remove_duplicate_turns::apply(turns_all);
+ remove_duplicate_turns::apply(turns_wo_cont);
+ remove_duplicate_turns::apply(rturns_all);
+ remove_duplicate_turns::apply(rturns_wo_cont);
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl;
+ std::cout << "### ORIGINAL TURNS ###" << std::endl;
+ bg_turns::print_turns(linear1, linear2, turns_all);
+ std::cout << std::endl << std::endl;
+ std::cout << "### ORIGINAL REVERSE TURNS ###" << std::endl;
+ bg_turns::print_turns(linear1, linear2_reverse, rturns_all);
+ std::cout << std::endl << std::endl;
+ std::cout << "### TURNS W/O CONTINUE TURNS ###" << std::endl;
+ bg_turns::print_turns(linear1, linear2, turns_wo_cont);
+ std::cout << std::endl << std::endl;
+ std::cout << "### REVERSE TURNS W/O CONTINUE TURNS ###" << std::endl;
+ bg_turns::print_turns(linear1, linear2_reverse, rturns_wo_cont);
+ std::cout << std::endl << std::endl;
+#endif
+
+ BOOST_CHECK_MESSAGE(boost::size(turns_wo_cont) == boost::size(rturns_wo_cont),
+ "Incompatible turns count: " << boost::size(turns_wo_cont) <<
+ " and " << boost::size(rturns_wo_cont) <<
+ " for L1: " << bg::wkt(lineargeometry1) <<
+ ", L2: " << bg::wkt(lineargeometry2));
+ }
+};
+
+
+
+#endif // BOOST_GEOMETRY_TEST_GET_TURNS_LL_INVARIANCE_HPP
diff --git a/libs/geometry/test/algorithms/set_operations/test_set_ops_linear_linear.hpp b/libs/geometry/test/algorithms/set_operations/test_set_ops_linear_linear.hpp
new file mode 100644
index 000000000..884b5028a
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/test_set_ops_linear_linear.hpp
@@ -0,0 +1,374 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#ifndef BOOST_GEOMETRY_TEST_SET_OPS_LINEAR_LINEAR_HPP
+#define BOOST_GEOMETRY_TEST_SET_OPS_LINEAR_LINEAR_HPP
+
+
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <algorithm>
+
+#include <boost/core/ignore_unused.hpp>
+#include <boost/range.hpp>
+#include <boost/geometry/policies/compare.hpp>
+#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/algorithms/reverse.hpp>
+#include <boost/geometry/multi/algorithms/reverse.hpp>
+
+#include "test_get_turns_ll_invariance.hpp"
+
+namespace bg = ::boost::geometry;
+
+
+
+template <typename Linestring1, typename Linestring2>
+struct ls_less
+{
+ typedef typename boost::range_iterator<Linestring1 const>::type Iterator1;
+ typedef typename boost::range_iterator<Linestring2 const>::type Iterator2;
+
+ typedef bg::less<typename bg::point_type<Linestring1>::type> point_less;
+
+ bool operator()(Linestring1 const& linestring1,
+ Linestring2 const& linestring2) const
+ {
+ if ( boost::size(linestring1) != boost::size(linestring2) )
+ return boost::size(linestring1) < boost::size(linestring2);
+
+ Iterator1 it1 = boost::begin(linestring1);
+ Iterator2 it2 = boost::begin(linestring2);
+ point_less less;
+ for (; it1 != boost::end(linestring1); ++it1, ++it2)
+ {
+ if ( less(*it1, *it2) )
+ return true;
+ if ( less(*it2, *it1) )
+ return false;
+ }
+ return false;
+ }
+};
+
+
+template <typename Linestring1, typename Linestring2>
+struct ls_equal
+{
+ bool operator()(Linestring1 const& linestring1,
+ Linestring2 const& linestring2) const
+ {
+ ls_less<Linestring1, Linestring2> less;
+
+ return !less(linestring1, linestring2)
+ && !less(linestring2, linestring1);
+ }
+};
+
+
+template <typename Point1, typename Point2>
+class pt_equal
+{
+private:
+ double m_tolerence;
+
+ template <typename T>
+ static inline T const& get_max(T const& a, T const& b, T const& c)
+ {
+ return (std::max)((std::max)(a, b), c);
+ }
+
+ template <typename T>
+ static inline bool check_close(T const& a, T const& b, T const& tol)
+ {
+ return (a == b)
+ || (std::abs(a - b) <= tol * get_max(std::abs(a), std::abs(b), 1.0));
+ }
+
+public:
+ pt_equal(double tolerence) : m_tolerence(tolerence) {}
+
+ bool operator()(Point1 const& point1, Point2 const& point2) const
+ {
+ // allow for some tolerence in testing equality of points
+ return check_close(bg::get<0>(point1), bg::get<0>(point2), m_tolerence)
+ && check_close(bg::get<1>(point1), bg::get<1>(point2), m_tolerence);
+ }
+};
+
+
+template <bool EnableUnique = false>
+struct multilinestring_equals
+{
+ template <typename MultiLinestring, bool Enable>
+ struct unique
+ {
+ typedef typename boost::range_value<MultiLinestring>::type Linestring;
+ typedef typename bg::point_type<MultiLinestring>::type point_type;
+ typedef ls_equal<Linestring, Linestring> linestring_equal;
+ typedef pt_equal<point_type, point_type> point_equal;
+
+ template <typename Range, typename EqualTo>
+ void apply_to_range(Range& range, EqualTo const& equal_to)
+ {
+ range.erase(std::unique(boost::begin(range), boost::end(range),
+ equal_to),
+ boost::end(range));
+ }
+
+ void operator()(MultiLinestring& mls, double tolerance)
+ {
+ for (typename boost::range_iterator<MultiLinestring>::type it
+ = boost::begin(mls); it != boost::end(mls); ++it)
+ {
+ apply_to_range(*it, point_equal(tolerance));
+ }
+ apply_to_range(mls, linestring_equal());
+ }
+ };
+
+ template <typename MultiLinestring>
+ struct unique<MultiLinestring, false>
+ {
+ void operator()(MultiLinestring&, double)
+ {
+ }
+ };
+
+ template <typename MultiLinestring1, typename MultiLinestring2>
+ static inline
+ bool apply(MultiLinestring1 const& multilinestring1,
+ MultiLinestring2 const& multilinestring2,
+ double tolerance)
+ {
+ typedef typename boost::range_iterator
+ <
+ MultiLinestring1 const
+ >::type ls1_iterator;
+
+ typedef typename boost::range_iterator
+ <
+ MultiLinestring2 const
+ >::type ls2_iterator;
+
+ typedef typename boost::range_value<MultiLinestring1>::type Linestring1;
+
+ typedef typename boost::range_value<MultiLinestring2>::type Linestring2;
+
+ typedef typename boost::range_iterator
+ <
+ Linestring1 const
+ >::type point1_iterator;
+
+ typedef typename boost::range_iterator
+ <
+ Linestring2 const
+ >::type point2_iterator;
+
+ typedef ls_less<Linestring1, Linestring2> linestring_less;
+
+ typedef pt_equal
+ <
+ typename boost::range_value
+ <
+ typename boost::range_value<MultiLinestring1>::type
+ >::type,
+ typename boost::range_value
+ <
+ typename boost::range_value<MultiLinestring2>::type
+ >::type
+ > point_equal;
+
+
+ MultiLinestring1 mls1 = multilinestring1;
+ MultiLinestring2 mls2 = multilinestring2;
+
+ std::sort(boost::begin(mls1), boost::end(mls1), linestring_less());
+ std::sort(boost::begin(mls2), boost::end(mls2), linestring_less());
+
+ unique<MultiLinestring1, EnableUnique>()(mls1, tolerance);
+ unique<MultiLinestring2, EnableUnique>()(mls2, tolerance);
+
+ if ( boost::size(mls1) != boost::size(mls2) )
+ {
+ return false;
+ }
+
+ ls1_iterator it1 = boost::begin(mls1);
+ ls2_iterator it2 = boost::begin(mls2);
+ for (; it1 != boost::end(mls1); ++it1, ++it2)
+ {
+ if ( boost::size(*it1) != boost::size(*it2) )
+ {
+ return false;
+ }
+ point1_iterator pit1 = boost::begin(*it1);
+ point2_iterator pit2 = boost::begin(*it2);
+ for (; pit1 != boost::end(*it1); ++pit1, ++pit2)
+ {
+ if (! point_equal(tolerance)(*pit1, *pit2))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+};
+
+
+
+
+class equals
+{
+private:
+ template <typename Linestring, typename OutputIterator>
+ static inline OutputIterator
+ isolated_point_to_segment(Linestring const& linestring, OutputIterator oit)
+ {
+ BOOST_ASSERT( boost::size(linestring) == 1 );
+
+ *oit++ = *boost::begin(linestring);
+ *oit++ = *boost::begin(linestring);
+ return oit;
+ }
+
+
+ template <typename MultiLinestring, typename OutputIterator>
+ static inline OutputIterator
+ convert_isolated_points_to_segments(MultiLinestring const& multilinestring,
+ OutputIterator oit)
+ {
+ BOOST_AUTO_TPL(it, boost::begin(multilinestring));
+
+ for (; it != boost::end(multilinestring); ++it)
+ {
+ if ( boost::size(*it) == 1 )
+ {
+ typename boost::range_value<MultiLinestring>::type linestring;
+ isolated_point_to_segment(*it, std::back_inserter(linestring));
+ *oit++ = linestring;
+ }
+ else
+ {
+ *oit++ = *it;
+ }
+ }
+ return oit;
+ }
+
+
+ template <typename MultiLinestring1, typename MultiLinestring2>
+ static inline bool apply_base(MultiLinestring1 const& multilinestring1,
+ MultiLinestring2 const& multilinestring2,
+ double tolerance)
+ {
+ typedef multilinestring_equals<true> mls_equals;
+
+ if ( mls_equals::apply(multilinestring1, multilinestring2, tolerance) )
+ {
+ return true;
+ }
+
+ MultiLinestring1 reverse_multilinestring1 = multilinestring1;
+ bg::reverse(reverse_multilinestring1);
+ if ( mls_equals::apply(reverse_multilinestring1,
+ multilinestring2,
+ tolerance) )
+ {
+ return true;
+ }
+
+ MultiLinestring2 reverse_multilinestring2 = multilinestring2;
+ bg::reverse(reverse_multilinestring2);
+ if ( mls_equals::apply(multilinestring1,
+ reverse_multilinestring2,
+ tolerance) )
+ {
+ return true;
+ }
+
+ return mls_equals::apply(reverse_multilinestring1,
+ reverse_multilinestring2,
+ tolerance);
+ }
+
+
+
+public:
+ template <typename MultiLinestring1, typename MultiLinestring2>
+ static inline bool apply(MultiLinestring1 const& multilinestring1,
+ MultiLinestring2 const& multilinestring2,
+ double tolerance)
+ {
+#ifndef BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS
+ MultiLinestring1 converted_multilinestring1;
+ convert_isolated_points_to_segments
+ (multilinestring1, std::back_inserter(converted_multilinestring1));
+ MultiLinestring2 converted_multilinestring2;
+ convert_isolated_points_to_segments
+ (multilinestring2, std::back_inserter(converted_multilinestring2));
+ return apply_base(converted_multilinestring1,
+ converted_multilinestring2, tolerance);
+#else
+ return apply_base(multilinestring1, multilinestring2, tolerance);
+#endif
+ }
+};
+
+
+
+
+template <typename Output, typename G1, typename G2>
+void set_operation_output(std::string const& set_op_id,
+ std::string const& caseid,
+ G1 const& g1, G2 const& g2,
+ Output const& output)
+{
+ boost::ignore_unused(set_op_id, caseid, g1, g2, output);
+
+#if defined(TEST_WITH_SVG)
+ typedef typename bg::coordinate_type<G1>::type coordinate_type;
+ typedef typename bg::point_type<G1>::type point_type;
+
+ std::ostringstream filename;
+ filename << "svgs/" << set_op_id << "_" << caseid << ".svg";
+
+ std::ofstream svg(filename.str().c_str());
+
+ bg::svg_mapper<point_type> mapper(svg, 500, 500);
+
+ mapper.add(g1);
+ mapper.add(g2);
+
+ mapper.map(g2, "stroke-opacity:1;stroke:rgb(153,204,0);stroke-width:4");
+ mapper.map(g1, "stroke-opacity:1;stroke:rgb(51,51,153);stroke-width:2");
+
+ BOOST_AUTO_TPL(it, output.begin());
+ for (; it != output.end(); ++it)
+ {
+ if ( boost::size(*it) == 2
+ && bg::equals(*boost::begin(*it), *++boost::begin(*it)) )
+ {
+ // draw isolated points (generated by the intersection operation)
+ mapper.map(*boost::begin(*it),
+ "fill:rgb(255,0,255);stroke:rgb(0,0,0);stroke-width:1",
+ 4);
+ }
+ else
+ {
+ mapper.map(*it,
+ "stroke-opacity:0.4;stroke:rgb(255,0,255);stroke-width:8");
+ }
+ }
+#endif
+}
+
+
+#endif // BOOST_GEOMETRY_TEST_SET_OPS_LINEAR_LINEAR_HPP
diff --git a/libs/geometry/test/algorithms/set_operations/test_set_ops_pl_pl.hpp b/libs/geometry/test/algorithms/set_operations/test_set_ops_pl_pl.hpp
new file mode 100644
index 000000000..fd825d003
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/test_set_ops_pl_pl.hpp
@@ -0,0 +1,257 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#ifndef BOOST_GEOMETRY_TEST_SET_OPS_PL_PL_HPP
+#define BOOST_GEOMETRY_TEST_SET_OPS_PL_PL_HPP
+
+
+#include <boost/geometry/geometry.hpp>
+
+namespace bg = ::boost::geometry;
+
+#include <from_wkt.hpp>
+#include <to_svg.hpp>
+
+#include <algorithm>
+#include <fstream>
+#include <boost/core/ignore_unused.hpp>
+
+#include <boost/geometry/policies/compare.hpp>
+#include <boost/geometry/algorithms/equals.hpp>
+
+#include <boost/geometry/algorithms/union.hpp>
+#include <boost/geometry/algorithms/difference.hpp>
+#include <boost/geometry/algorithms/intersection.hpp>
+#include <boost/geometry/algorithms/sym_difference.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+
+
+//==================================================================
+//==================================================================
+// svg output
+//==================================================================
+//==================================================================
+
+template <typename Output, typename G1, typename G2>
+void set_operation_output(std::string const& set_op_id,
+ std::string const& caseid,
+ G1 const& g1, G2 const& g2,
+ Output const& output)
+{
+ boost::ignore_unused(set_op_id, caseid, g1, g2, output);
+
+#if defined(TEST_WITH_SVG)
+ typedef typename bg::coordinate_type<G1>::type coordinate_type;
+ typedef typename bg::point_type<G1>::type point_type;
+
+ std::ostringstream filename;
+ filename << "svgs/" << set_op_id << "_" << caseid << ".svg";
+
+ std::ofstream svg(filename.str().c_str());
+
+ bg::svg_mapper<point_type> mapper(svg, 500, 500);
+
+ mapper.add(g1);
+ mapper.add(g2);
+
+ mapper.map(g2, "stroke-opacity:1;stroke:rgb(153,204,0);stroke-width:4");
+ mapper.map(g1, "stroke-opacity:1;stroke:rgb(51,51,153);stroke-width:2");
+
+ BOOST_AUTO_TPL(it, output.begin());
+ for (; it != output.end(); ++it)
+ {
+ mapper.map(*it,
+ "fill:rgb(255,0,255);stroke:rgb(0,0,0);stroke-width:1",
+ 4);
+ }
+#endif
+}
+
+
+//==================================================================
+//==================================================================
+// testing equality of multi-points
+//==================================================================
+//==================================================================
+
+
+struct equals
+{
+ template <typename MultiPoint1, typename MultiPoint2>
+ static inline bool apply(MultiPoint1 const& multipoint1,
+ MultiPoint2 const& multipoint2)
+ {
+ MultiPoint1 mp1(multipoint1);
+ MultiPoint2 mp2(multipoint2);
+
+ std::sort(mp1.begin(), mp1.end(),
+ bg::less<typename bg::point_type<MultiPoint1>::type>());
+ std::sort(mp2.begin(), mp2.end(),
+ bg::less<typename bg::point_type<MultiPoint2>::type>());
+
+ if ( boost::size(mp1) != boost::size(mp2) )
+ {
+ return false;
+ }
+
+ BOOST_AUTO_TPL(it1, boost::begin(mp1));
+ BOOST_AUTO_TPL(it2, boost::begin(mp2));
+ for (; it1 != boost::end(mp1); ++it1, ++it2)
+ {
+ if ( !bg::equals(*it1, *it2) )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
+
+
+//==================================================================
+//==================================================================
+// struct for calling the appropriate set op function
+//==================================================================
+//==================================================================
+
+template <bg::overlay_type OverlayType> struct set_op;
+
+
+template<>
+struct set_op<bg::overlay_difference>
+{
+ static inline std::string name() { return "difference"; }
+
+ template <typename Geometry1, typename Geometry2, typename GeometryOut>
+ static inline void apply(Geometry1 const& g1,
+ Geometry2 const& g2,
+ GeometryOut& gout)
+ {
+ bg::difference(g1, g2, gout);
+ }
+};
+
+
+template<>
+struct set_op<bg::overlay_union>
+{
+ static inline std::string name() { return "union"; }
+
+ template <typename Geometry1, typename Geometry2, typename GeometryOut>
+ static inline void apply(Geometry1 const& g1,
+ Geometry2 const& g2,
+ GeometryOut& gout)
+ {
+ bg::union_(g1, g2, gout);
+ }
+};
+
+
+template<>
+struct set_op<bg::overlay_intersection>
+{
+ static inline std::string name() { return "intersection"; }
+
+ template <typename Geometry1, typename Geometry2, typename GeometryOut>
+ static inline void apply(Geometry1 const& g1,
+ Geometry2 const& g2,
+ GeometryOut& gout)
+ {
+ bg::intersection(g1, g2, gout);
+ }
+};
+
+
+
+//==================================================================
+//==================================================================
+// test the set operation of (point-like) geometries
+//==================================================================
+//==================================================================
+
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename MultiPoint,
+ bg::overlay_type OverlayType
+>
+class test_set_op_of_pointlike_geometries
+{
+private:
+ template <typename G1, typename G2, typename MP>
+ static inline void base_test(G1 const& geometry1,
+ G2 const& geometry2,
+ MP const& mp_expected,
+ std::string const& case_id)
+ {
+ MultiPoint mp_output;
+
+ set_op<OverlayType>::apply(geometry1, geometry2, mp_output);
+
+ std::string op_name = set_op<OverlayType>::name();
+
+ BOOST_CHECK_MESSAGE( equals::apply(mp_expected, mp_output),
+ op_name << " P/P: " << bg::wkt(geometry1)
+ << " " << bg::wkt(geometry2)
+ << " -> Expected: " << bg::wkt(mp_expected)
+ << " computed: " << bg::wkt(mp_output) );
+
+ set_operation_output(op_name, case_id,
+ geometry1, geometry2, mp_output);
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl;
+ std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl;
+ std::cout << "expected " << op_name << " : "
+ << bg::wkt(mp_expected) << std::endl;
+ std::cout << op_name << " : " << bg::wkt(mp_output) << std::endl;
+ std::cout << std::endl;
+ std::cout << "************************************" << std::endl;
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+ }
+
+
+public:
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiPoint const& mp_expected12,
+ MultiPoint const& mp_expected21,
+ std::string const& case_id)
+ {
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "test case: " << case_id << std::endl;
+#endif
+
+ base_test(geometry1, geometry2, mp_expected12, case_id);
+ base_test(geometry2, geometry1, mp_expected21, case_id);
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+ }
+
+
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiPoint const& mp_expected,
+ std::string const& case_id)
+ {
+ apply(geometry1, geometry2, mp_expected, mp_expected, case_id);
+ }
+};
+
+
+#endif // BOOST_GEOMETRY_TEST_SET_OPS_PL_PL_HPP
diff --git a/libs/geometry/test/algorithms/set_operations/union/Jamfile.v2 b/libs/geometry/test/algorithms/set_operations/union/Jamfile.v2
new file mode 100644
index 000000000..1f6b4f17e
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/union/Jamfile.v2
@@ -0,0 +1,23 @@
+# Boost.Geometry (aka GGL, Generic Geometry Library)
+#
+# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+# Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+# Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+#
+# This file was modified by Oracle on 2014.
+# Modifications copyright (c) 2014, Oracle and/or its affiliates.
+#
+# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+#
+# Use, modification and distribution is subject to the Boost Software License,
+# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+test-suite boost-geometry-algorithms-union
+ :
+ [ run multi_union.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE ]
+ [ run union.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE ]
+ [ run union_linear_linear.cpp ]
+ [ run union_pl_pl.cpp ]
+ ;
diff --git a/libs/geometry/test/algorithms/set_operations/union/multi_union.cpp b/libs/geometry/test/algorithms/set_operations/union/multi_union.cpp
new file mode 100644
index 000000000..74c9d060d
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/union/multi_union.cpp
@@ -0,0 +1,168 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Unit Test
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <string>
+
+// If defined, tests are run without rescaling-to-integer or robustness policy
+// This multi_union currently contains no tests for double which then fail
+// #define BOOST_GEOMETRY_NO_ROBUSTNESS
+
+#include "test_union.hpp"
+#include <algorithms/test_overlay.hpp>
+#include <algorithms/overlay/multi_overlay_cases.hpp>
+
+#include <boost/geometry/multi/algorithms/correct.hpp>
+#include <boost/geometry/multi/algorithms/intersection.hpp>
+#include <boost/geometry/multi/algorithms/within.hpp>
+
+#include <boost/geometry/geometries/point_xy.hpp>
+#include <boost/geometry/multi/geometries/multi_linestring.hpp>
+#include <boost/geometry/multi/geometries/multi_polygon.hpp>
+
+#include <boost/geometry/multi/io/wkt/read.hpp>
+
+
+template <typename Ring, typename Polygon, typename MultiPolygon>
+void test_areal()
+{
+ test_one<Polygon, MultiPolygon, MultiPolygon>("simplex_multi",
+ case_multi_simplex[0], case_multi_simplex[1],
+ 1, 0, 20, 14.58);
+
+ test_one<Polygon, Polygon, MultiPolygon>("simplex_multi_p_mp",
+ case_single_simplex, case_multi_simplex[0],
+ 1, 0, 20, 14.58);
+ test_one<Polygon, MultiPolygon, Polygon>("simplex_multi_mp_p",
+ case_multi_simplex[0], case_single_simplex,
+ 1, 0, 20, 14.58);
+
+ test_one<Polygon, Ring, MultiPolygon>("simplex_multi_r_mp",
+ case_single_simplex, case_multi_simplex[0],
+ 1, 0, 20, 14.58);
+ test_one<Ring, MultiPolygon, Polygon>("simplex_multi_mp_r",
+ case_multi_simplex[0], case_single_simplex,
+ 1, 0, 20, 14.58);
+
+
+ // Normal test cases
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_multi_no_ip",
+ case_multi_no_ip[0], case_multi_no_ip[1],
+ 4, 0, 16, 66.5);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_multi_2",
+ case_multi_2[0], case_multi_2[1],
+ 3, 0, 16, 59.1);
+
+ // Constructed cases for multi/touch/equal/etc
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_61_multi",
+ case_61_multi[0], case_61_multi[1],
+ 1, 0, 11, 4.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_62_multi",
+ case_62_multi[0], case_62_multi[1],
+ 2, 0, 10, 2.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_63_multi",
+ case_63_multi[0], case_63_multi[1],
+ 2, 0, 10, 2.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_64_multi",
+ case_64_multi[0], case_64_multi[1],
+ 1, 0, 9, 3.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_65_multi",
+ case_65_multi[0], case_65_multi[1],
+ 3, 0, 15, 4.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_66_multi",
+ case_66_multi[0], case_66_multi[1],
+ 3, 0, 23, 7.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_72_multi",
+ case_72_multi[0], case_72_multi[1],
+ 1, 0, 13, 10.65);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_75_multi",
+ case_75_multi[0], case_75_multi[1],
+ 5, 0, 25, 5.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_76_multi",
+ case_76_multi[0], case_76_multi[1],
+ 5, 0, 31, 8.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_89_multi",
+ case_89_multi[0], case_89_multi[1],
+ 1, 0, 13, 6);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_101_multi",
+ case_101_multi[0], case_101_multi[1],
+ 1, 0, 32, 22.25);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_103_multi",
+ case_103_multi[0], case_103_multi[1],
+ 1, 0, 7, 25);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_104_multi",
+ case_104_multi[0], case_104_multi[1],
+ 1, 0, 8, 25);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_105_multi",
+ case_105_multi[0], case_105_multi[1],
+ 1, 0, 5, 25);
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_1",
+ case_recursive_boxes_1[0], case_recursive_boxes_1[1],
+ 1, 1, 36, 97.0);
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_2",
+ case_recursive_boxes_2[0], case_recursive_boxes_2[1],
+ 1, 0, 14, 100.0); // Area from SQL Server
+ test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_3",
+ case_recursive_boxes_3[0], case_recursive_boxes_3[1],
+ 17, 0, 159, 56.5); // Area from SQL Server
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120915_h2_a",
+ ggl_list_20120915_h2[0], ggl_list_20120915_h2[1],
+ 1, 0, 12, 23.0); // Area from SQL Server
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120915_h2_b",
+ ggl_list_20120915_h2[0], ggl_list_20120915_h2[2],
+ 1, 0, 12, 23.0); // Area from SQL Server
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20140212_sybren",
+ ggl_list_20140212_sybren[0], ggl_list_20140212_sybren[1],
+ 2, 0, 16, 0.002471626);
+
+ test_one<Polygon, MultiPolygon, MultiPolygon>("ticket_9081",
+ ticket_9081[0], ticket_9081[1],
+ 3, 0, 31, 0.2187385);
+}
+
+template <typename P>
+void test_all()
+{
+
+ {
+ typedef bg::model::ring<P> ring;
+ typedef bg::model::polygon<P> polygon;
+ typedef bg::model::multi_polygon<polygon> multi_polygon;
+ test_areal<ring, polygon, multi_polygon>();
+ }
+
+ {
+ typedef bg::model::ring<P, false> ring_ccw;
+ typedef bg::model::polygon<P, false> polygon_ccw;
+ typedef bg::model::multi_polygon<polygon_ccw> multi_polygon_ccw;
+ test_areal<ring_ccw, polygon_ccw, multi_polygon_ccw>();
+ }
+
+}
+
+
+int test_main(int, char* [])
+{
+ test_all<bg::model::d2::point_xy<double> >();
+
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+ test_all<bg::model::d2::point_xy<float> >();
+
+#if defined(HAVE_TTMATH)
+ std::cout << "Testing TTMATH" << std::endl;
+ test_all<bg::model::d2::point_xy<ttmath_big> >();
+#endif
+
+#endif
+
+ return 0;
+}
diff --git a/libs/geometry/test/algorithms/set_operations/union/test_union.hpp b/libs/geometry/test/algorithms/set_operations/union/test_union.hpp
new file mode 100644
index 000000000..2c1868ef2
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/union/test_union.hpp
@@ -0,0 +1,198 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Unit Test
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_TEST_UNION_HPP
+#define BOOST_GEOMETRY_TEST_UNION_HPP
+
+#include <fstream>
+
+#include <geometry_test_common.hpp>
+
+#include <boost/core/ignore_unused.hpp>
+#include <boost/range/algorithm/copy.hpp>
+
+#include <boost/geometry/algorithms/union.hpp>
+
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/correct.hpp>
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+
+#include <boost/geometry/geometries/geometries.hpp>
+
+#include <boost/geometry/strategies/strategies.hpp>
+
+#include <boost/geometry/io/wkt/wkt.hpp>
+
+
+#if defined(TEST_WITH_SVG)
+# include <boost/geometry/io/svg/svg_mapper.hpp>
+#endif
+
+
+
+template <typename OutputType, typename G1, typename G2>
+void test_union(std::string const& caseid, G1 const& g1, G2 const& g2,
+ int expected_count, int expected_hole_count,
+ int expected_point_count, double expected_area,
+ double percentage)
+{
+ typedef typename bg::coordinate_type<G1>::type coordinate_type;
+ boost::ignore_unused<coordinate_type>();
+
+ std::vector<OutputType> clip;
+
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
+ std::cout << "*** UNION " << caseid << std::endl;
+#endif
+
+ bg::union_(g1, g2, clip);
+
+ typename bg::default_area_result<OutputType>::type area = 0;
+ std::size_t n = 0;
+ std::size_t holes = 0;
+ for (typename std::vector<OutputType>::iterator it = clip.begin();
+ it != clip.end(); ++it)
+ {
+ area += bg::area(*it);
+ holes += bg::num_interior_rings(*it);
+ n += bg::num_points(*it, true);
+ }
+
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+ {
+ // Test inserter functionality
+ // Test if inserter returns output-iterator (using Boost.Range copy)
+ std::vector<OutputType> inserted, array_with_one_empty_geometry;
+ array_with_one_empty_geometry.push_back(OutputType());
+ boost::copy(array_with_one_empty_geometry, bg::detail::union_::union_insert<OutputType>(g1, g2, std::back_inserter(inserted)));
+
+ typename bg::default_area_result<OutputType>::type area_inserted = 0;
+ int index = 0;
+ for (typename std::vector<OutputType>::iterator it = inserted.begin();
+ it != inserted.end();
+ ++it, ++index)
+ {
+ // Skip the empty polygon created above to avoid the empty_input_exception
+ if (bg::num_points(*it) > 0)
+ {
+ area_inserted += bg::area(*it);
+ }
+ }
+ BOOST_CHECK_EQUAL(boost::size(clip), boost::size(inserted) - 1);
+ BOOST_CHECK_CLOSE(area_inserted, expected_area, percentage);
+ }
+#endif
+
+
+
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
+ std::cout << "*** case: " << caseid
+ << " area: " << area
+ << " points: " << n
+ << " polygons: " << boost::size(clip)
+ << " holes: " << holes
+ << std::endl;
+#endif
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ BOOST_CHECK_MESSAGE(expected_point_count < 0 || std::abs(int(n) - expected_point_count) < 3,
+ "union: " << caseid
+ << " #points expected: " << expected_point_count
+ << " detected: " << n
+ << " type: " << (type_for_assert_message<G1, G2>())
+ );
+#endif
+
+ BOOST_CHECK_MESSAGE(expected_count < 0 || int(clip.size()) == expected_count,
+ "union: " << caseid
+ << " #clips expected: " << expected_count
+ << " detected: " << clip.size()
+ << " type: " << (type_for_assert_message<G1, G2>())
+ );
+
+ BOOST_CHECK_MESSAGE(expected_hole_count < 0 || int(holes) == expected_hole_count,
+ "union: " << caseid
+ << " #holes expected: " << expected_hole_count
+ << " detected: " << holes
+ << " type: " << (type_for_assert_message<G1, G2>())
+ );
+
+ BOOST_CHECK_CLOSE(area, expected_area, percentage);
+
+#if defined(TEST_WITH_SVG)
+ {
+ bool const ccw =
+ bg::point_order<G1>::value == bg::counterclockwise
+ || bg::point_order<G2>::value == bg::counterclockwise;
+ bool const open =
+ bg::closure<G1>::value == bg::open
+ || bg::closure<G2>::value == bg::open;
+
+ std::ostringstream filename;
+ filename << "union_"
+ << caseid << "_"
+ << string_from_type<coordinate_type>::name()
+ << (ccw ? "_ccw" : "")
+ << (open ? "_open" : "")
+#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ << "_no_rob"
+#endif
+ << ".svg";
+
+ std::ofstream svg(filename.str().c_str());
+
+ bg::svg_mapper
+ <
+ typename bg::point_type<G2>::type
+ > mapper(svg, 500, 500);
+ mapper.add(g1);
+ mapper.add(g2);
+
+ mapper.map(g1, "fill-opacity:0.5;fill:rgb(153,204,0);"
+ "stroke:rgb(153,204,0);stroke-width:3");
+ mapper.map(g2, "fill-opacity:0.3;fill:rgb(51,51,153);"
+ "stroke:rgb(51,51,153);stroke-width:3");
+ //mapper.map(g1, "opacity:0.6;fill:rgb(0,0,255);stroke:rgb(0,0,0);stroke-width:1");
+ //mapper.map(g2, "opacity:0.6;fill:rgb(0,255,0);stroke:rgb(0,0,0);stroke-width:1");
+
+ for (typename std::vector<OutputType>::const_iterator it = clip.begin();
+ it != clip.end(); ++it)
+ {
+ mapper.map(*it, "fill-opacity:0.2;stroke-opacity:0.4;fill:rgb(255,0,0);"
+ "stroke:rgb(255,0,255);stroke-width:8");
+ //mapper.map(*it, "opacity:0.6;fill:none;stroke:rgb(255,0,0);stroke-width:5");
+ }
+ }
+#endif
+}
+
+template <typename OutputType, typename G1, typename G2>
+void test_one(std::string const& caseid, std::string const& wkt1, std::string const& wkt2,
+ int expected_count, int expected_hole_count,
+ int expected_point_count, double expected_area,
+ double percentage = 0.001)
+{
+ G1 g1;
+ bg::read_wkt(wkt1, g1);
+
+ G2 g2;
+ bg::read_wkt(wkt2, g2);
+
+ // Reverse if necessary
+ bg::correct(g1);
+ bg::correct(g2);
+
+ test_union<OutputType>(caseid, g1, g2,
+ expected_count, expected_hole_count, expected_point_count,
+ expected_area, percentage);
+}
+
+
+
+#endif
diff --git a/libs/geometry/test/algorithms/set_operations/union/test_union_linear_linear.hpp b/libs/geometry/test/algorithms/set_operations/union/test_union_linear_linear.hpp
new file mode 100644
index 000000000..1b6dda37c
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/union/test_union_linear_linear.hpp
@@ -0,0 +1,185 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#ifndef BOOST_GEOMETRY_TEST_UNION_LINEAR_LINEAR_HPP
+#define BOOST_GEOMETRY_TEST_UNION_LINEAR_LINEAR_HPP
+
+#include <limits>
+
+#include <boost/geometry/geometry.hpp>
+#include "../test_set_ops_linear_linear.hpp"
+#include <from_wkt.hpp>
+#include <to_svg.hpp>
+
+
+//==================================================================
+//==================================================================
+// union of (linear) geometries
+//==================================================================
+//==================================================================
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename MultiLineString
+>
+class test_union_of_geometries
+{
+private:
+ static inline void base_test(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiLineString const& mls_union1,
+ MultiLineString const& mls_union2,
+ std::string const& case_id,
+ double tolerance,
+ bool test_vector_and_deque = false)
+ {
+ static bool vector_deque_already_tested = false;
+
+ typedef typename boost::range_value<MultiLineString>::type LineString;
+ typedef std::vector<LineString> linestring_vector;
+ typedef std::deque<LineString> linestring_deque;
+
+ MultiLineString mls_output;
+
+ linestring_vector ls_vector_output;
+ linestring_deque ls_deque_output;
+
+ bg::union_(geometry1, geometry2, mls_output);
+
+ BOOST_CHECK_MESSAGE( equals::apply(mls_union1, mls_output, tolerance),
+ "case id: " << case_id
+ << ", union L/L: " << bg::wkt(geometry1)
+ << " " << bg::wkt(geometry2)
+ << " -> Expected: " << bg::wkt(mls_union1)
+ << " computed: " << bg::wkt(mls_output) );
+
+ set_operation_output("union", case_id,
+ geometry1, geometry2, mls_output);
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl;
+ std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl;
+ std::cout << "union : " << bg::wkt(mls_output) << std::endl;
+ std::cout << "expected union : " << bg::wkt(mls_union1)
+ << std::endl;
+ std::cout << std::endl;
+ std::cout << "************************************" << std::endl;
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+
+ if ( !vector_deque_already_tested && test_vector_and_deque )
+ {
+ vector_deque_already_tested = true;
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl;
+ std::cout << "Testing with vector and deque as output container..."
+ << std::endl;
+#endif
+ bg::union_(geometry1, geometry2, ls_vector_output);
+ bg::union_(geometry1, geometry2, ls_deque_output);
+
+ BOOST_CHECK(multilinestring_equals
+ <
+ false
+ >::apply(mls_union1, ls_vector_output, tolerance));
+
+ BOOST_CHECK(multilinestring_equals
+ <
+ false
+ >::apply(mls_union1, ls_deque_output, tolerance));
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Done!" << std::endl << std::endl;
+#endif
+ }
+
+ // check the symmetric difference where the order of the two
+ // geometries is reversed
+ bg::clear(mls_output);
+ bg::union_(geometry2, geometry1, mls_output);
+
+ BOOST_CHECK_MESSAGE( equals::apply(mls_union2, mls_output, tolerance),
+ "case id: " << case_id
+ << ", union L/L: " << bg::wkt(geometry2)
+ << " " << bg::wkt(geometry1)
+ << " -> Expected: " << bg::wkt(mls_union2)
+ << " computed: " << bg::wkt(mls_output) );
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "Geometry #1: " << bg::wkt(geometry2) << std::endl;
+ std::cout << "Geometry #2: " << bg::wkt(geometry1) << std::endl;
+ std::cout << "union : " << bg::wkt(mls_output) << std::endl;
+ std::cout << "expected union : " << bg::wkt(mls_union2)
+ << std::endl;
+ std::cout << std::endl;
+ std::cout << "************************************" << std::endl;
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+ }
+
+
+public:
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiLineString const& mls_union1,
+ MultiLineString const& mls_union2,
+ std::string const& case_id,
+ double tolerance
+ = std::numeric_limits<double>::epsilon())
+ {
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << "test case: " << case_id << std::endl;
+ std::stringstream sstr;
+ sstr << "svgs/" << case_id << ".svg";
+ to_svg(geometry1, geometry2, sstr.str());
+#endif
+
+ Geometry1 rg1(geometry1);
+ bg::reverse<Geometry1>(rg1);
+
+ Geometry2 rg2(geometry2);
+ bg::reverse<Geometry2>(rg2);
+
+ test_get_turns_ll_invariance<>::apply(geometry1, geometry2);
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl
+ << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
+ << std::endl << std::endl;
+#endif
+ test_get_turns_ll_invariance<>::apply(rg1, geometry2);
+
+ base_test(geometry1, geometry2, mls_union1, mls_union2,
+ case_id, tolerance, true);
+ // base_test(geometry1, rg2, mls_sym_diff);
+ // base_test(rg1, geometry2, mls_sym_diff);
+ base_test(rg1, rg2, mls_union1, mls_union2, case_id, tolerance);
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl;
+ std::cout << std::endl;
+#endif
+ }
+
+
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ MultiLineString const& mls_union,
+ std::string const& case_id,
+ double tolerance
+ = std::numeric_limits<double>::epsilon())
+ {
+ apply(geometry1, geometry2, mls_union, mls_union, case_id, tolerance);
+ }
+};
+
+
+#endif // BOOST_GEOMETRY_TEST_UNION1_HPP
diff --git a/libs/geometry/test/algorithms/set_operations/union/union.cpp b/libs/geometry/test/algorithms/set_operations/union/union.cpp
new file mode 100644
index 000000000..20820a2d2
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/union/union.cpp
@@ -0,0 +1,446 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Unit Test
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <string>
+
+// If defined, tests are run without rescaling-to-integer or robustness policy
+// Test which would fail then are disabled automatically
+// #define BOOST_GEOMETRY_NO_ROBUSTNESS
+
+#include "test_union.hpp"
+#include <algorithms/test_overlay.hpp>
+
+#include <algorithms/overlay/overlay_cases.hpp>
+#include <boost/geometry/geometries/point_xy.hpp>
+
+
+
+template <typename Ring, typename Polygon>
+void test_areal()
+{
+ typedef typename bg::coordinate_type<Polygon>::type ct;
+
+ test_one<Polygon, Polygon, Polygon>("simplex_normal",
+ simplex_normal[0], simplex_normal[1],
+ 1, 0, 13, 11.526367);
+
+ test_one<Polygon, Polygon, Polygon>("simplex_with_empty_1",
+ simplex_normal[0], polygon_empty,
+ 1, 0, 4, 8.0);
+ test_one<Polygon, Polygon, Polygon>("simplex_with_empty_2",
+ polygon_empty, simplex_normal[0],
+ 1, 0, 4, 8.0);
+
+ test_one<Polygon, Polygon, Polygon>("star_ring", example_star, example_ring,
+ 1, 0, 23, 5.67017141);
+
+ // This sample was selected because of the border case, and ttmath generates one point more.
+ test_one<Polygon, Polygon, Polygon>("star_poly", example_star, example_polygon,
+ 1, 1,
+ if_typed_tt<ct>(28, 27), 5.647949);
+
+ // Pseudo-box as Polygon
+ // (note, internally, the intersection points is different, so yes,
+ // it has to be tested)
+ test_one<Polygon, Polygon, Polygon>("box_poly3", "POLYGON((1.5 1.5 , 1.5 2.5 , 4.5 2.5 , 4.5 1.5 , 1.5 1.5))",
+ "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,5.3 2.5,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))",
+ 1, 1, 15, 5.93625);
+
+ test_one<Polygon, Polygon, Polygon>("first_within_second",
+ first_within_second[0], first_within_second[1],
+ 1, 0, 5, 25.0);
+
+ test_one<Polygon, Polygon, Polygon>("second_within_first",
+ first_within_second[1], first_within_second[0],
+ 1, 0, 5, 25.0);
+
+ test_one<Polygon, Polygon, Polygon>("first_within_hole_of_second",
+ first_within_hole_of_second[0], first_within_hole_of_second[1],
+ 2, 1, 15, 17.0);
+
+ test_one<Polygon, Polygon, Polygon>("new_hole",
+ new_hole[0], new_hole[1],
+ 1, 1, 14, 23.0);
+
+ test_one<Polygon, Polygon, Polygon>("side_side",
+ side_side[0], side_side[1], 1, 0, 7, 2.0);
+
+ test_one<Polygon, Polygon, Polygon>("identical",
+ identical[0], identical[1], 1, 0, 5, 1.0);
+
+ test_one<Polygon, Polygon, Polygon>("disjoint",
+ disjoint[0], disjoint[1], 2, 0, 10, 2.0);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_holes_intersect",
+ intersect_holes_intersect[0], intersect_holes_intersect[1],
+ 1, 1, 14, 39.75);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_holes_intersect_and_disjoint",
+ intersect_holes_intersect_and_disjoint[0], intersect_holes_intersect_and_disjoint[1],
+ 1, 1, 14, 39.75);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_holes_intersect_and_touch",
+ intersect_holes_intersect_and_touch[0], intersect_holes_intersect_and_touch[1],
+ 1, 1, 14, 39.75);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_holes_new_ring",
+ intersect_holes_new_ring[0], intersect_holes_new_ring[1],
+ 1, 2, 15, 253.8961);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_holes_disjoint",
+ intersect_holes_disjoint[0],
+ intersect_holes_disjoint[1],
+ 1, 0, 9, 40.0);
+
+ test_one<Polygon, Polygon, Polygon>("within_holes_disjoint",
+ within_holes_disjoint[0], within_holes_disjoint[1],
+ 1, 0, 5, 49.0);
+
+ test_one<Polygon, Polygon, Polygon>("winded",
+ winded[0], winded[1],
+ 1, 5, 30, 114.0);
+
+ test_one<Polygon, Polygon, Polygon>("two_bends",
+ two_bends[0], two_bends[1],
+ 1, 0, 7, 40.0);
+
+ test_one<Polygon, Polygon, Polygon>("star_comb_15",
+ star_comb_15[0], star_comb_15[1],
+ 1, 27, 204, 898.09693338);
+
+ test_one<Polygon, Polygon, Polygon>("equal_holes_disjoint",
+ equal_holes_disjoint[0], equal_holes_disjoint[1],
+ 1, 1, 10, 81 - 3 * 7);
+
+ test_one<Polygon, Polygon, Polygon>("only_hole_intersections1",
+ only_hole_intersections[0], only_hole_intersections[1],
+ 1, 2, 13, 190.9090909);
+ test_one<Polygon, Polygon, Polygon>("only_hole_intersections2",
+ only_hole_intersections[0], only_hole_intersections[2],
+ 1, 2, 13, 190.9090909);
+
+ test_one<Polygon, Polygon, Polygon>("intersect_exterior_and_interiors_winded",
+ intersect_exterior_and_interiors_winded[0], intersect_exterior_and_interiors_winded[1],
+ 1, 1, 26, 66.5333333);
+
+ test_one<Polygon, Polygon, Polygon>("crossed",
+ crossed[0], crossed[1],
+ 1, 3, 17, 23.5); // Area from SQL Server - was somehow wrong before
+
+ test_one<Polygon, Polygon, Polygon>("fitting",
+ fitting[0], fitting[1],
+ 1, 0, 5, 25);
+
+ test_one<Polygon, Polygon, Polygon>("distance_zero",
+ distance_zero[0], distance_zero[1],
+ 1, 0, if_typed<ct, float>(9, 11), 9.0098387);
+
+ test_one<Polygon, Polygon, Polygon>("wrapped_a",
+ wrapped[0], wrapped[1],
+ 1, 1, 16, 16);
+ test_one<Polygon, Polygon, Polygon>("wrapped_b",
+ wrapped[0], wrapped[2],
+ 1, 1, 16, 16);
+
+ test_one<Polygon, Polygon, Polygon>("9",
+ case_9[0], case_9[1], 2, 0, 8, 11);
+ test_one<Polygon, Polygon, Polygon>("22",
+ case_22[0], case_22[1], 2, 0, 8, 9.5);
+ test_one<Polygon, Polygon, Polygon>("25",
+ case_25[0], case_25[1], 2, 0, 8, 7);
+ test_one<Polygon, Polygon, Polygon>("26",
+ case_26[0], case_26[1], 2, 0, 9, 7.5);
+ test_one<Polygon, Polygon, Polygon>("31",
+ case_31[0], case_31[1], 2, 0, 8, 4.5);
+ test_one<Polygon, Polygon, Polygon>("32",
+ case_32[0], case_32[1], 2, 0, 8, 4.5);
+ test_one<Polygon, Polygon, Polygon>("33",
+ case_33[0], case_33[1], 2, 0, 8, 4.5);
+ test_one<Polygon, Polygon, Polygon>("36",
+ case_36[0], case_36[1], 1, 0, 10, 14.375);
+ test_one<Polygon, Polygon, Polygon>("40",
+ case_40[0], case_40[1], 2, 0, 18, 11);
+
+ // Test rings which should be generated by assemble
+ test_one<Polygon, Polygon, Polygon>("53_iet",
+ case_53[0], case_53[2], 1, 1, 16, 16);
+ test_one<Polygon, Polygon, Polygon>("58_iet",
+ case_58[0], case_58[2], 1, 3, 20, 12.16666);
+ test_one<Polygon, Polygon, Polygon>("59_iet",
+ case_59[0], case_59[2], 1, 1, 14, 17.20833);
+
+
+ /*
+ test_one<Polygon, Polygon, Polygon>(102,
+ simplex_normal[0], simplex_reversed[1],
+ 1, 0, 7, X);
+
+ test_one<Polygon, Polygon, Polygon>(103,
+ simplex_reversed[0], simplex_normal[1],
+ 1, 0, 7, 24.0);
+
+ test_one<Polygon, Polygon, Polygon>(104,
+ simplex_reversed[0], simplex_reversed[1],
+ 1, 0, 7, 24.0);
+
+ test_one<Polygon, Polygon, Polygon>(100,
+ star_15, comb_15,
+ 1, 10, 7, 24.0);
+ */
+
+ // test some other input/output types
+
+ // 1 input Ring
+ test_one<Polygon, Polygon, Ring>("identical_pr", identical[0], identical[1], 1, 0, 5, 1.0);
+ test_one<Polygon, Ring, Polygon>("identical_rp", identical[0], identical[1], 1, 0, 5, 1.0);
+
+ // 2 input rings
+ test_one<Polygon, Ring, Ring>("identical_rr", identical[0], identical[1], 1, 0, 5, 1.0);
+
+ // output is also Ring
+ test_one<Ring, Ring, Ring>("identical_rrr", identical[0], identical[1], 1, 0, 5, 1.0);
+
+ // "new hole", tested with Ring -> the newly formed hole will be omitted
+ test_one<Ring, Ring, Ring>("new_hole_discarded", new_hole[0], new_hole[1], 1, 0, 9, 24.0);
+
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20110306_javier",
+ ggl_list_20110306_javier[0], ggl_list_20110306_javier[1],
+ 1, 1, 16, 80456.4904910401);
+
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20110307_javier",
+ ggl_list_20110307_javier[0], ggl_list_20110307_javier[1],
+ 1, 1, 13, 20016.4);
+
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20110627_phillip",
+ ggl_list_20110627_phillip[0], ggl_list_20110627_phillip[1],
+ 1, 0, 8, 14729.07145);
+
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20110716_enrico",
+ ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1],
+ 1, 1, 15, 129904.197692871);
+
+ test_one<Polygon, Polygon, Polygon>("ggl_list_20110820_christophe",
+ ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1],
+ -1, // Either 1 or 2, depending if the intersection/turn point (eps.region) is missed
+ 0,
+ if_typed_tt<ct>(9, 8),
+ 67.3550722317627);
+
+
+ test_one<Polygon, Polygon, Polygon>("isovist",
+ isovist1[0], isovist1[1],
+ 1,
+ 0,
+ -1,
+ 313.36036462, 0.01);
+
+ // SQL Server gives: 313.360374193241
+ // PostGIS gives: 313.360364623393
+
+ // Ticket 5103 https://svn.boost.org/trac/boost/ticket/5103
+ // This ticket was actually reported for Boost.Polygon
+ // We check it for Boost.Geometry as well.
+ // SQL Server gives: 2515271331437.69
+ // PostGIS gives: 2515271327070.52
+ // Boost.Geometry gives: 2515271327070.5237746891 (ttmath)
+ // 2515271327070.5156 (double)
+ // 2515271320603.0000 (int)
+ // Note the int-test was tested outside of this unit test. It is in two points 0.37 off (logical for an int).
+ // Because of the width of the polygon (400000 meter) this causes a substantial difference.
+
+ test_one<Polygon, Polygon, Polygon>("ticket_5103", ticket_5103[0], ticket_5103[1],
+ 1, 0, 25, 2515271327070.5);
+
+ test_one<Polygon, Polygon, Polygon>("ticket_8310a", ticket_8310a[0], ticket_8310a[1],
+ 1, 0, 5, 10.5000019595);
+ test_one<Polygon, Polygon, Polygon>("ticket_8310b", ticket_8310b[0], ticket_8310b[1],
+ 1, 0, 5, 10.5000019595);
+ test_one<Polygon, Polygon, Polygon>("ticket_8310c", ticket_8310c[0], ticket_8310c[1],
+ 1, 0, 5, 10.5000019595);
+
+ test_one<Polygon, Polygon, Polygon>("ticket_9081_15",
+ ticket_9081_15[0], ticket_9081_15[1],
+ 1, 0, 7, 0.0403425433);
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<Polygon, Polygon, Polygon>("ticket_9563", ticket_9563[0], ticket_9563[1],
+ 1, 0, 13, 150.0);
+#endif
+
+ test_one<Polygon, Polygon, Polygon>("ticket_9756", ticket_9756[0], ticket_9756[1],
+ 1, 0, 10, 1289.08374);
+
+ test_one<Polygon, Polygon, Polygon>("ticket_10108_a", ticket_10108_a[0], ticket_10108_a[1],
+ 2, 0, 8, 0.0435229);
+ test_one<Polygon, Polygon, Polygon>("ticket_10108_b", ticket_10108_b[0], ticket_10108_b[1],
+ 2, 0, 10, 2424.3449);
+
+ test_one<Polygon, Polygon, Polygon>("geos_1", geos_1[0], geos_1[1],
+ 1, 0, -1, 3461.3203125);
+ test_one<Polygon, Polygon, Polygon>("geos_2", geos_2[0], geos_2[1],
+ 1, 0, -1, 350.55102539);
+ test_one<Polygon, Polygon, Polygon>("geos_3", geos_3[0], geos_3[1],
+ 1, 0, -1, 29391548.4998779);
+ test_one<Polygon, Polygon, Polygon>("geos_4", geos_4[0], geos_4[1],
+ 1, 0, -1, 2304.4163115);
+
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_a", buffer_rt_a[0], buffer_rt_a[1],
+ 1, 0, 265, 19.280667);
+
+ // Robustness issues, followed out buffer-robustness-tests, test them also reverse
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1],
+ 1, 0, if_typed<ct, double>(21, 23), 4.60853);
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_f_rev", buffer_rt_f[1], buffer_rt_f[0],
+ 1, 0, if_typed<ct, double>(21, 23), 4.60853);
+#endif
+
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1],
+ 1, 0, if_typed<ct, float>(18, 17), 16.571);
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_g_rev", buffer_rt_g[1], buffer_rt_g[0],
+ 1, 0, if_typed<ct, float>(18, 17), 16.571);
+
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_i", buffer_rt_i[0], buffer_rt_i[1],
+ 1, 0, if_typed<ct, float>(14, 13), 13.6569);
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_i_rev", buffer_rt_i[1], buffer_rt_i[0],
+ 1, 0, 13, 13.6569);
+
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_j", buffer_rt_j[0], buffer_rt_j[1],
+ 1, 0, -1, 16.5711);
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_j_rev", buffer_rt_j[1], buffer_rt_j[0],
+ 1, 0, -1, 16.5711);
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_l", buffer_rt_l[0], buffer_rt_l[1],
+ 1, 0, -1, 19.3995);
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_l_rev", buffer_rt_l[1], buffer_rt_l[0],
+ 1, 0, -1, 19.3995);
+#endif
+
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_m1", buffer_rt_m1[0], buffer_rt_m1[1],
+ 1, 0, if_typed_tt<ct>(14, 13), 19.4852);
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_m1_rev", buffer_rt_m1[1], buffer_rt_m1[0],
+ 1, 0, if_typed_tt<ct>(14, 13), 19.4852);
+
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_m2", buffer_rt_m2[0], buffer_rt_m2[1],
+ 1, 0, if_typed_tt<ct>(20, 19), 21.4853);
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_m2_rev", buffer_rt_m2[1], buffer_rt_m2[0],
+ 1, 0, if_typed_tt<ct>(20, 19), 21.4853);
+
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_q", buffer_rt_q[0], buffer_rt_q[1],
+ 1, 0, 18, 18.5710);
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_q_rev", buffer_rt_q[1], buffer_rt_q[0],
+ 1, 0, 18, 18.5710);
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_r", buffer_rt_r[0], buffer_rt_r[1],
+ 1, 0, 19, 21.07612);
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_r_rev", buffer_rt_r[1], buffer_rt_r[0],
+ 1, 0, if_typed_tt<ct>(20, 19), 21.07612);
+#endif
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_t", buffer_rt_t[0], buffer_rt_t[1],
+ 1, 0, if_typed_tt<ct>(16, 14), 15.6569);
+#endif
+ test_one<Polygon, Polygon, Polygon>("buffer_rt_t_ref", buffer_rt_t[1], buffer_rt_t[0],
+ 1, 0, if_typed_tt<ct>(16, if_typed<ct, float>(15, 14)), 15.6569);
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_one<Polygon, Polygon, Polygon>("buffer_mp1", buffer_mp1[0], buffer_mp1[1],
+ 1, 0, if_typed_tt<ct>(93, 91), 22.815);
+#endif
+
+ test_one<Polygon, Polygon, Polygon>("buffer_mp2", buffer_mp2[0], buffer_mp2[1],
+ 1, 0, 217, 36.752837);
+}
+
+template <typename P>
+void test_all()
+{
+ typedef bg::model::polygon<P> polygon;
+ typedef bg::model::ring<P> ring;
+ typedef bg::model::box<P> box;
+
+ test_areal<ring, polygon>();
+
+ // Open
+ test_areal<bg::model::ring<P, true, false>, bg::model::polygon<P, true, false> >();
+
+ // Counter clockwise
+ test_areal<bg::model::ring<P, false>, bg::model::polygon<P, false> >();
+
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+ // Counter clockwise and open
+ test_areal<bg::model::ring<P, false, false>, bg::model::polygon<P, false, false> >();
+#endif
+
+ test_one<polygon, box, polygon>("box_ring", example_box, example_ring,
+ 1, 1, 15, 6.38875);
+
+ test_one<polygon, box, polygon>("box_poly", example_box, example_polygon,
+ 1, 3, 23, 6.30983);
+
+
+ test_one<polygon, box, polygon>("box_poly1", example_box,
+ "POLYGON((3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2))",
+ 1, 1, 15, 6.38875);
+ test_one<polygon, box, polygon>("box_poly2", example_box,
+ "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,5.3 2.5,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))",
+ 1, 1, 15, 5.93625);
+
+ // 3: see areal
+
+ test_one<polygon, box, polygon>("box_poly4", example_box,
+ "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 1.2,4.9 0.8,2.9 0.7,2 1.3))",
+ 1, 1, 15, 4.651245);
+
+ test_one<polygon, box, polygon>("box_poly5", example_box,
+ "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))",
+ 1, 1, 21, 4.7191);
+
+ test_one<polygon, box, polygon>("box_poly6", example_box,
+ "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 1.2,2.9 0.7,2 1.3))",
+ 1, 1, 15, 4.2174);
+
+ test_one<polygon, box, polygon>("box_poly7", example_box,
+ "POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.0 3.0,5.0 2.0,2.9 0.7,2 1.3))",
+ 1, 1, 17, 4.270554);
+
+ test_one<polygon, box, polygon>("box_poly8", "box(0 0, 3 3)",
+ "POLYGON((2 2, 1 4, 2 4, 3 3, 2 2))",
+ 1, 0, 8, 10.25);
+}
+
+
+int test_main(int, char* [])
+{
+ test_all<bg::model::d2::point_xy<double> >();
+
+#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
+
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ test_all<bg::model::d2::point_xy<float> >();
+ test_all<bg::model::d2::point_xy<long double> >();
+#endif
+
+#if defined(HAVE_TTMATH)
+ std::cout << "Testing TTMATH" << std::endl;
+ test_all<bg::model::d2::point_xy<ttmath_big> >();
+#endif
+#endif
+
+ return 0;
+}
diff --git a/libs/geometry/test/algorithms/set_operations/union/union_linear_linear.cpp b/libs/geometry/test/algorithms/set_operations/union/union_linear_linear.cpp
new file mode 100644
index 000000000..925c8363b
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/union/union_linear_linear.cpp
@@ -0,0 +1,1075 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#include <iostream>
+
+#ifndef BOOST_TEST_MODULE
+#define BOOST_TEST_MODULE test_union_linear_linear
+#endif
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+#define BOOST_GEOMETRY_DEBUG_TURNS
+#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
+#endif
+
+#include <boost/test/included/unit_test.hpp>
+
+#include "test_union_linear_linear.hpp"
+
+#include <boost/geometry/geometries/linestring.hpp>
+#include <boost/geometry/multi/geometries/multi_linestring.hpp>
+#include <boost/geometry/algorithms/union.hpp>
+
+typedef bg::model::point<double,2,bg::cs::cartesian> point_type;
+typedef bg::model::segment<point_type> segment_type;
+typedef bg::model::linestring<point_type> linestring_type;
+typedef bg::model::multi_linestring<linestring_type> multi_linestring_type;
+
+
+
+//===========================================================================
+//===========================================================================
+//===========================================================================
+
+
+BOOST_AUTO_TEST_CASE( test_union_linestring_linestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** LINESTRING / LINESTRING UNION ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_union_of_geometries<L, L, ML> tester;
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 1,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(0 2,1 1,2 1,3 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1,2 1,3 2),\
+ (0 2,1 1),(2 1,3 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 2,1 1,2 1,3 0),\
+ (0 0,1 1),(2 1,3 2))"),
+ "llu00");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,5 0)"),
+ from_wkt<L>("LINESTRING(3 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((3 0,4 0),(0 0,3 0),(4 0,5 0))"),
+ "llu01");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(3 0,4 0)"),
+ from_wkt<L>("LINESTRING(0 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((3 0,4 0),(0 0,3 0),(4 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,5 0))"),
+ "llu01-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,6 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,4 0),(4 0,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((3 0,6 0),(0 0,3 0))"),
+ "llu01-2");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(3 0,6 0)"),
+ from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((3 0,6 0),(0 0,3 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,4 0),(4 0,6 0))"),
+ "llu01-3");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,6 0)"),
+ from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,4 0),(4 0,6 0))"),
+ "llu01-4");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<L>("LINESTRING(0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),\
+ (0 0,1 1,2 0,3 1,4 0),\
+ (5 0,6 1,7 -1,8 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0),\
+ (0 0,4 0),(5 0,20 0))"),
+ "llu01-6");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-20 0,20 0)"),
+ from_wkt<L>("LINESTRING(0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0)"),
+ from_wkt<ML>("MULTILINESTRING((-20 0,20 0),\
+ (0 0,1 1,2 0,3 1,4 0),\
+ (5 0,6 1,7 -1,8 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1,2 0,3 1,4 0,5 0,6 1,7 -1,8 0),\
+ (-20 0,4 0),(5 0,20 0))"),
+ "llu01-7");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,4 0)"),
+ from_wkt<L>("LINESTRING(2 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0),(0 0,2 0))"),
+ "llu01-8");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0)"),
+ from_wkt<L>("LINESTRING(4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(4 0,5 0))"),
+ "llu01-10");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0)"),
+ from_wkt<L>("LINESTRING(2 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0),(2 0,5 0))"),
+ "llu01-11");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,4 0),(4 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((3 0,5 0),(0 0,1 0,3 0))"),
+ "llu01-11a");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,4 0)"),
+ from_wkt<L>("LINESTRING(3 0,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,4 0),(4 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((3 0,4 0,5 0),(0 0,1 0,3 0))"),
+ "llu01-11b");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,6 0)"),
+ from_wkt<L>("LINESTRING(2 0,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 0,4 0,5 0),(0 0,2 0),(5 0,6 0))"),
+ "llu01-12");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,5 5,10 5,15 0)"),
+ from_wkt<L>("LINESTRING(-1 6,0 5,15 5)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,5 5,10 5,15 0),\
+ (-1 6,0 5,5 5),(10 5,15 5))"),
+ from_wkt<ML>("MULTILINESTRING((-1 6,0 5,15 5),\
+ (0 0,1 0,5 5),(10 5,15 0))"),
+ "llu02");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,1 0,5 5,10 5,15 0,20 0),\
+ (-1 0,0 0),(1 0,15 0),(20 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,30 0),(-1 1,0 0),\
+ (1 0,5 5,10 5,15 0))"),
+ "llu03");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,5 5,10 5,15 0,20 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,5 5,10 5,15 0,20 0),\
+ (-1 0,0 0),(1 0,15 0),(20 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,30 0),(1 0,5 5,10 5,15 0))"),
+ "llu04");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,25 1)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,1 0,5 5,10 5,15 0,20 0,25 1),\
+ (-1 0,0 0),(1 0,15 0),(20 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,30 0),(-1 1,0 0),\
+ (1 0,5 5,10 5,15 0),(20 0,25 1))"),
+ "llu05");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0),\
+ (-1 0,0 0),(1 0,15 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,30 0),(-1 1,0 0),\
+ (1 0,5 5,10 5,15 0))"),
+ "llu05-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0),\
+ (-1 0,0 0),(1 0,15 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,30 0),(-1 1,0 0),\
+ (1 0,5 5,10 5,15 0),(30 0,31 0))"),
+ "llu06");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,25 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0),\
+ (-1 0,0 0),(1 0,15 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,25 0,30 0),(-1 1,0 0),\
+ (1 0,5 5,10 5,15 0),(30 0,31 0))"),
+ "llu07");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,1 0,5 5,10 5,15 0,20 0,31 0),\
+ (-1 0,0 0),(1 0,15 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,19 0,30 0),(-1 1,0 0),\
+ (1 0,5 5,10 5,15 0),(30 0,31 0))"),
+ "llu08");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,1 0,5 5,10 5,15 0,20 0,\
+ 30 0,31 1),(-1 0,0 0),(1 0,15 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 0,30 0),(-1 1,0 0),\
+ (1 0,5 5,10 5,15 0),(30 0,31 1))"),
+ "llu09");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,5 5,10 5,15 0,20 0,30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,1 0,5 5,10 5,15 0,20 0,\
+ 30 0,31 1),(-1 -1,0 0),(1 0,2 1,3 0,15 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,1 0,2 1,3 0,30 0),\
+ (-1 1,0 0),(1 0,5 5,10 5,15 0),(30 0,31 1))"),
+ "llu10");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,20 0,\
+ 30 0,31 1)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,1 0,4 0,5 5,10 5,15 0,20 0,\
+ 30 0,31 1),(-1 -1,0 0),(2 0,2.5 1,3 0),(4 0,15 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0),\
+ (-1 1,0 0),(2 0,3 0),(4 0,5 5,10 5,15 0),(30 0,31 1))"),
+ "llu11");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,1 0,4 0,5 5,10 5,15 0,31 0)"),
+ from_wkt<L>("LINESTRING(-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,1 0,4 0,5 5,10 5,15 0,31 0),\
+ (-1 -1,0 0),(2 0,2.5 1,3 0),(4 0,15 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,1 0,2 0,2.5 1,3 0,30 0),\
+ (-1 1,0 0),(2 0,3 0),(4 0,5 5,10 5,15 0),(30 0,31 0))"),
+ "llu11-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0,3 1))"),
+ "llu12");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,2 0,3 1)"),
+ from_wkt<L>("LINESTRING(3 1,2 0,0 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((3 1,2 0,0 0))"),
+ "llu12-1");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 5,4 0)"),
+ from_wkt<L>("LINESTRING(1 0,2 1,3 5,4 0,5 10)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 1,3 5,4 0),(4 0,5 10))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,2 1,3 5,4 0,5 10),(0 0,1 0))"),
+ "llu13");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 0,2.5 0,3 1)"),
+ from_wkt<L>("LINESTRING(0 0,2 0,2.5 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0,2.5 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,2 0,2.5 0,3 1))"),
+ "llu14");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 5,4 0)"),
+ from_wkt<L>("LINESTRING(1 0,2 1,3 5)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 1,3 5,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,2 1,3 5),(0 0,1 0),(3 5,4 0))"),
+ "llu15");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(0.5 0,1 0,3 2,4 5)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 1,3 2),(3 2,4 5))"),
+ from_wkt<ML>("MULTILINESTRING((0.5 0,1 0,3 2,4 5),(0 0,0.5 0))"),
+ "llu16");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 1,3 2)"),
+ from_wkt<L>("LINESTRING(4 5,3 2,1 0,0.5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 1,3 2),(4 5,3 2))"),
+ from_wkt<ML>("MULTILINESTRING((4 5,3 2,1 0,0.5 0),(0 0,0.5 0))"),
+ "llu16-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1,30 1)"),
+ from_wkt<L>("LINESTRING(1 1,2 0,3 1,20 1,25 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1,30 1),(1 1,2 0,3 1,20 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,3 1,20 1,25 1),\
+ (0 0,10 0,20 1),(25 1,30 1))"),
+ "llu17");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1,21 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 1,2 0,3 1,20 1,25 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1,21 0,30 0),\
+ (1 1,2 0,3 1,20 1,25 0))"),
+ "llu18");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(5 0,20 1,4 1,4 0,5 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0,20 1,4 1,4 0,5 1),\
+ (0 0,1 0),(5 0,30 0))"),
+ "llu19");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,4 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(5 1,4 0,4 1,20 1,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 1,4 0,4 1,20 1,5 0,1 0),\
+ (0 0,1 0),(5 0,30 0))"),
+ "llu19-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(5 0,20 1,4 1,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0,20 1,4 1,4 0),(0 0,1 0),\
+ (5 0,30 0))"),
+ "llu19a");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(4 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(4 0,4 1,20 1,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((4 0,4 1,20 1,5 0,1 0),(0 0,1 0),\
+ (5 0,30 0))"),
+ "llu19a-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(5 0,20 1,4 1,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0,20 1,4 1,4 0,5 0),\
+ (0 0,1 0),(5 0,30 0))"),
+ "llu19b");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0,6 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(5 0,20 1,4 1,4 0),(5 0,6 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0,20 1,4 1,4 0,5 0,6 1),\
+ (0 0,1 0),(5 0,30 0))"),
+ "llu19c");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,3 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(5 0,20 1,4 1,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0,20 1,4 1,4 0,3 0),\
+ (0 0,1 0),(5 0,30 0))"),
+ "llu19d");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,3 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(5 0,20 1,4 1,4 0),(3 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0,20 1,4 1,4 0,3 0,3 1),\
+ (0 0,1 0),(5 0,30 0))"),
+ "llu19e");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,4 0,5 0,5 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(5 0,20 1,4 1,4 0),(5 0,5 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0,20 1,4 1,4 0,5 0,5 1),\
+ (0 0,1 0),(5 0,30 0))"),
+ "llu19f");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,5 0,4 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(5 1,5 0),\
+ (4 0,4 1,20 1,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 1,5 0,4 0,4 1,20 1,5 0,1 0),\
+ (0 0,1 0),(5 0,30 0))"),
+ "llu19f-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(1 0,5 0,20 1,4 1,5 0,5 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(5 0,20 1,4 1,5 0,5 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,5 0,20 1,4 1,5 0,5 1),\
+ (0 0,1 0),(5 0,30 0))"),
+ "llu19g");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<L>("LINESTRING(5 1,5 0,4 1,20 1,5 0,1 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(5 1,5 0,4 1,20 1,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 1,5 0,4 1,20 1,5 0,1 0),\
+ (0 0,1 0),(5 0,30 0))"),
+ "llu19g-r");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0,30 30,10 30,10 -10,15 0,40 0)"),
+ from_wkt<L>("LINESTRING(5 5,10 0,10 30,20 0,25 0,25 25,50 0,35 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0,30 30,10 30,10 -10,15 0,40 0),\
+ (5 5,10 0),(10 30,20 0),(25 0,25 25,50 0,40 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 5,10 0,10 30,20 0,25 0,25 25,50 0,35 0),\
+ (0 0,20 0),(25 0,30 0,30 30,10 30),\
+ (10 0,10 -10,15 0,20 0),(25 0,35 0))"),
+ "llu20");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0,30 30,10 30,10 -10,15 0,40 0)"),
+ from_wkt<L>("LINESTRING(5 5,10 0,10 30,20 0,25 0,25 25,50 0,15 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0,30 30,10 30,10 -10,15 0,40 0),\
+ (5 5,10 0),(10 30,20 0),(25 0,25 25,50 0,40 0))"),
+ from_wkt<ML>("MULTILINESTRING((5 5,10 0,10 30,20 0,25 0,25 25,50 0,15 0),\
+ (0 0,15 0),(30 0,30 30,10 30),(10 0,10 -10,15 0))"),
+ "llu20a");
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<L>("LINESTRING(2 2,5 -1,15 2,18 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 0,18 0,19 0,30 0),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((2 2,5 -1,15 2,18 0,20 0),\
+ (0 0,18 0),(20 0,30 0))"),
+ "llu21"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(2 2,5 -1,15 2,18 0,20 0)"),
+ from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((2 2,5 -1,15 2,18 0,20 0),\
+ (0 0,18 0),(20 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,18 0,19 0,30 0),\
+ (2 2,5 -1,15 2,18 0))"),
+ "llu21a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,3 0,\
+ 4 -1,-7 10,-4 10)"),
+ from_wkt<L>("LINESTRING(-5 -4,3 0,4 -1,7 -4,2 -1,-4 -1,-2 6)"),
+ from_wkt<ML>("MULTILINESTRING((-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,3 0,\
+ 4 -1,-7 10,-4 10),(-5 -4,3 0),\
+ (4 -1,7 -4,2 -1,-4 -1,-2 6))"),
+ from_wkt<ML>("MULTILINESTRING((-5 -4,3 0,4 -1,7 -4,2 -1,-4 -1,-2 6),\
+ (-2 -2,-4 0,1 -8,-2 6,8 5,-7 -8,3 0),\
+ (3 0,-7 10,-4 10))"),
+ "llu22"
+ );
+}
+
+
+
+BOOST_AUTO_TEST_CASE( test_union_linestring_multilinestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** LINESTRING / MULTILINESTRING UNION ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_union_of_geometries<L, ML, ML> tester;
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 2,4 3),(1 1,2 2,5 3))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 1,2 2,4 3),\
+ (1 1,2 2,5 3))"),
+ "lmlu01"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 1,2 0),(1 1,3 0))"),
+ "lmlu02"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 1,2 0),(1 1,3 0))"),
+ "lmlu03"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,10 0,20 1)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 1,2 0))"),
+ "lmlu04"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,101 0),(-1 -1,1 0),(101 0,200 -1))"),
+ "lmlu07"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(-1 1,0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,101 0),(-1 -1,0 0),\
+ (19 -1,20 0),(101 0,200 -1))"),
+ "lmlu07a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,101 0),(-1 -1,0 0),\
+ (19 -1,20 0),(101 0,200 -1))"),
+ "lmlu07b"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,101 0),(0 1,1 1,2 0),\
+ (-1 -1,1 0),(101 0,200 -1))"),
+ "lmlu08"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,2 0.5,3 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0.5,3 0,101 0),\
+ (0 1,1 1,2 0.5),(-1 -1,1 0,3 0),(101 0,200 -1))"),
+ "lmlu09"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,1 0,1.5 0,2 0.5,3 0,101 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,1 0,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,1.5 0,2 0.5,3 0,101 0),\
+ (0 1,1 1,1 0,2 0.5),(-1 -1,1 0),(1.5 0,3 0),\
+ (101 0,200 -1))"),
+ "lmlu10"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (1 1,2 0,18 0,19 1),(2 1,3 0,17 0,18 1),\
+ (3 1,4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),(19 0,20 1),\
+ (1 1,2 0),(18 0,19 1),(2 1,3 0),(17 0,18 1),\
+ (3 1,4 0),(16 0,17 1))"),
+ "lmlu12"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0,20 1),\
+ (2 0,18 0,19 1),(3 0,17 0,18 1),\
+ (4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(19 0,20 1),(18 0,19 1),\
+ (17 0,18 1),(16 0,17 1))"),
+ "lmlu13"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),\
+ (19 0,20 1,19 1,18 0),(2 0,1 1,2 1,3 0),\
+ (17 0,18 1,17 1,16 0),(4 0,3 1))"),
+ "lmlu14"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),(19 0,20 1),\
+ (2 2,4 2,6 0))"),
+ "lmlu15"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),(19 0,20 1),\
+ (6 0,4 2,2 2))"),
+ "lmlu15a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,5 0,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),(19 0,20 1),\
+ (2 2,4 2,5 0))"),
+ "lmlu16"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,20 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,5 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),(19 0,20 1),\
+ (5 0,4 2,2 2))"),
+ "lmlu16a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(0 1,1 0),(19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0))"),
+ "lmlu17"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0,26 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(0 1,1 0),(19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0,26 2))"),
+ "lmlu17a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(0 1,1 0),(19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ "lmlu18"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,18 0,19 0,30 0),(0 1,1 0),\
+ (19 0,20 1),(2 2,5 -1,15 2,18 0))"),
+ "lmlu18a"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,18 0,19 0,30 0),(0 1,1 0),\
+ (19 0,20 1),(2 2,5 -1,15 2,18 0))"),
+ "lmlu18b"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,25 0,26 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,18 0,19 0,30 0),(0 1,1 0),\
+ (19 0,20 1),(2 2,5 -1,15 2,25 0))"),
+ "lmlu18c"
+ );
+
+ tester::apply
+ (from_wkt<L>("LINESTRING(0 0,18 0,19 0,30 0)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,25 0,21 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,18 0,19 0,30 0),(0 1,1 0),\
+ (19 0,20 1),(2 2,5 -1,15 2,25 0))"),
+ "lmlu18d"
+ );
+}
+
+
+
+BOOST_AUTO_TEST_CASE( test_union_multilinestring_linestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / LINESTRING UNION ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef linestring_type L;
+ typedef multi_linestring_type ML;
+
+ typedef test_union_of_geometries<ML, L, ML> tester;
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<L>("LINESTRING(1 1,2 2,4 3)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 2,4 3),(0 0,10 0,20 1),(1 0,7 0))"),
+ "mllu01"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<L>("LINESTRING(1 1,2 0,4 0)"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(0 0,2 0),(4 0,10 0,20 1),\
+ (1 0,2 0),(4 0,7 0))"),
+ "mllu02"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<L>("LINESTRING(-1 -1,1 0,101 0,200 -1)"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,1 0,101 0,200 -1),(0 0,1 0))"),
+ "mllu03"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<L>("LINESTRING(0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1)"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1),\
+ (0 0,1 0),(19 0,20 0))"),
+ "mllu04"
+ );
+}
+
+
+
+
+
+
+
+BOOST_AUTO_TEST_CASE( test_union_multilinestring_multilinestring )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTILINESTRING / MULTILINESTRING UNION ***"
+ << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef multi_linestring_type ML;
+
+ typedef test_union_of_geometries<ML, ML, ML> tester;
+
+ // disjoint linestrings
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 2,4 3),(1 1,2 2,5 3))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (1 1,2 2,4 3),(1 1,2 2,5 3))"),
+ "mlmlu01"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (1 1,2 0),(1 1,3 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,4 0),\
+ (0 0,2 0),(4 0,10 0,20 1),(1 0,2 0),(4 0,7 0))"),
+ "mlmlu02"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (1 1,2 0),(1 1,3 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(1 1,3 0,5 0),\
+ (0 0,2 0),(5 0,10 0,20 1),(1 0,2 0),(5 0,7 0))"),
+ "mlmlu03"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (1 1,2 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),(0 0,2 0),\
+ (4 0,10 0,20 1),(1 0,2 0),(4 0,7 0))"),
+ "mlmlu04"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (10 10,20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (10 20,15 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 1),(1 0,7 0),\
+ (10 10,20 10,30 20),(1 1,2 0),(10 20,15 10),\
+ (20 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (10 20,15 10,25 10,30 15),(0 0,2 0),(4 0,10 0,20 1),\
+ (1 0,2 0),(4 0,7 0),(10 10,15 10),(20 10,30 20))"),
+ "mlmlu05"
+ );
+
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 10),(1 0,7 0),\
+ (10 10,20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (-1 -1,0 0,9 0,11 10,12 10,13 3,14 4,15 5),\
+ (10 20,15 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 10),(1 0,7 0),\
+ (10 10,20 10,30 20),(1 1,2 0),\
+ (-1 -1,0 0),(9 0,11 10),(12 10,13 3),(10 20,15 10),\
+ (20 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (-1 -1,0 0,9 0,11 10,12 10,13 3,14 4,15 5),\
+ (10 20,15 10,25 10,30 15),(9 0,10 0,13 3),\
+ (15 5,20 10),(10 10,11 10),(12 10,15 10),(20 10,30 20))"),
+ "mlmlu06"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (-1 -1,0 0,9 0,11 10,12 10,13 3,14 4,15 5),\
+ (10 20,15 10,25 10,30 15))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 10),(1 0,7 0),\
+ (10 10,20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((1 1,2 0,4 0),\
+ (-1 -1,0 0,9 0,11 10,12 10,13 3,14 4,15 5),\
+ (10 20,15 10,25 10,30 15),(9 0,10 0,13 3),\
+ (15 5,20 10),(10 10,11 10),(12 10,15 10),\
+ (20 10,30 20))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,10 0,20 10),(1 0,7 0),\
+ (10 10,20 10,30 20),(1 1,2 0),(-1 -1,0 0), \
+ (9 0,11 10),(12 10,13 3),(10 20,15 10),\
+ (20 10,25 10,30 15))"),
+ "mlmlu06a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,101 0),(-1 -1,1 0),(101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,1 0,101 0,200 -1),(0 0,1 0))"),
+ "mlmlu07"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((-1 1,0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((-1 1,0 0,101 0),(-1 -1,0 0),\
+ (19 -1,20 0),(101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1),(-1 1,0 0))"),
+ "mlmlu07a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,101 0),(-1 -1,0 0),\
+ (19 -1,20 0),(101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((-1 -1,0 0,50 0),\
+ (19 -1,20 0,101 0,200 -1))"),
+ "mlmlu07b"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,101 0),(0 1,1 1,2 0),\
+ (-1 -1,1 0),(101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0),\
+ (-1 -1,1 0,101 0,200 -1),(0 0,1 0))"),
+ "mlmlu08"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0.5,3 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,2 0.5,3 0,101 0),\
+ (0 1,1 1,2 0.5),(-1 -1,1 0,3 0),(101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1),(0 0,1 0,2 0.5,3 0))"),
+ "mlmlu09"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 0,1.5 0,2 0.5,3 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,1 0,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 0,1.5 0,2 0.5,3 0,101 0),\
+ (0 1,1 1,1 0,2 0.5),(-1 -1,1 0),(1.5 0,3 0),\
+ (101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 1,1 0,2 0.5),\
+ (-1 -1,1 0,101 0,200 -1),(0 0,1 0),(1.5 0,2 0.5,3 0))"),
+ "mlmlu10"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,1 1,100 1,101 0),\
+ (0 0,101 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1,3 0,4 0,5 1,6 1,\
+ 7 0,8 0,9 1,10 1,11 0,12 0,13 1,14 1,15 0),\
+ (-1 -1,1 0,101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,1 1,100 1,101 0),\
+ (0 0,101 0),(1 0,1 1),(2 1,3 0),(4 0,5 1),(6 1,7 0),\
+ (8 0,9 1),(10 1,11 0),(12 0,13 1),(14 1,15 0),\
+ (-1 -1,1 0),(101 0,200 -1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,1 1,2 1,3 0,4 0,5 1,6 1,\
+ 7 0,8 0,9 1,10 1,11 0,12 0,13 1,14 1,15 0),\
+ (-1 -1,1 0,101 0,200 -1),(0 0,1 1),(2 1,5 1),\
+ (6 1,9 1),(10 1,13 1),(14 1,100 1,101 0),(0 0,1 0))"),
+ "mlmlu11"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (1 1,2 0,18 0,19 1),(2 1,3 0,17 0,18 1),\
+ (3 1,4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),(19 0,20 1),\
+ (1 1,2 0),(18 0,19 1),(2 1,3 0),(17 0,18 1),\
+ (3 1,4 0),(16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (1 1,2 0,18 0,19 1),(2 1,3 0,17 0,18 1),\
+ (3 1,4 0,16 0,17 1),(0 0,1 0),(19 0,20 0))"),
+ "mlmlu12"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0,20 1),\
+ (2 0,18 0,19 1),(3 0,17 0,18 1),\
+ (4 0,16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(19 0,20 1),(18 0,19 1),\
+ (17 0,18 1),(16 0,17 1))"),
+ from_wkt<ML>("MULTILINESTRING((1 0,19 0,20 1),\
+ (2 0,18 0,19 1),(3 0,17 0,18 1),\
+ (4 0,16 0,17 1),(0 0,1 0),(19 0,20 0))"),
+ "mlmlu13"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),\
+ (19 0,20 1,19 1,18 0),(2 0,1 1,2 1,3 0),\
+ (17 0,18 1,17 1,16 0),(4 0,3 1))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1,19 1,18 0,2 0,\
+ 1 1,2 1,3 0,17 0,18 1,17 1,16 0,4 0,3 1),\
+ (0 0,1 0),(19 0,20 0))"),
+ "mlmlu14"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),(19 0,20 1),\
+ (2 2,4 2,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,6 0),(0 0,1 0),(19 0,20 0))"),
+ "mlmlu15"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),(19 0,20 1),\
+ (6 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,4 2,2 2),(0 0,1 0),(19 0,20 0))"),
+ "mlmlu15a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,5 0,6 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),(19 0,20 1),\
+ (2 2,4 2,5 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 2,5 0,6 0),(0 0,1 0),(19 0,20 0))"),
+ "mlmlu16"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,20 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,5 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,20 0),(0 1,1 0),(19 0,20 1),\
+ (5 0,4 2,2 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (6 0,5 0,4 2,2 2),(0 0,1 0),(19 0,20 0))"),
+ "mlmlu16a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(0 1,1 0),(19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0),(0 0,1 0),(19 0,30 0))"),
+ "mlmlu17"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0,26 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(0 1,1 0),(19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0,26 2))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,4 0,5 2,20 2,25 0,26 2),(0 0,1 0),(19 0,30 0))"),
+ "mlmlu17a"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,30 0),(0 1,1 0),(19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0),(0 0,1 0),(19 0,30 0))"),
+ "mlmlu18"
+ );
+
+ tester::apply
+ (from_wkt<ML>("MULTILINESTRING((0 0,18 0,19 0,30 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 0,18 0,19 0,30 0),(0 1,1 0),\
+ (19 0,20 1),(2 2,5 -1,15 2,18 0))"),
+ from_wkt<ML>("MULTILINESTRING((0 1,1 0,19 0,20 1),\
+ (2 2,5 -1,15 2,18 0),(0 0,1 0),(19 0,30 0))"),
+ "mlmlu18a"
+ );
+}
diff --git a/libs/geometry/test/algorithms/set_operations/union/union_pl_pl.cpp b/libs/geometry/test/algorithms/set_operations/union/union_pl_pl.cpp
new file mode 100644
index 000000000..59798be23
--- /dev/null
+++ b/libs/geometry/test/algorithms/set_operations/union/union_pl_pl.cpp
@@ -0,0 +1,187 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+
+#include <iostream>
+
+#ifndef BOOST_TEST_MODULE
+#define BOOST_TEST_MODULE test_union_pointlike_pointlike
+#endif
+
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+#define BOOST_GEOMETRY_DEBUG_TURNS
+#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
+#endif
+
+#include <boost/test/included/unit_test.hpp>
+
+#include "../test_set_ops_pl_pl.hpp"
+
+#include <boost/geometry/geometries/multi_point.hpp>
+
+typedef bg::model::point<double,2,bg::cs::cartesian> point_type;
+typedef bg::model::multi_point<point_type> multi_point_type;
+
+
+
+//===========================================================================
+//===========================================================================
+//===========================================================================
+
+
+BOOST_AUTO_TEST_CASE( test_union_point_point )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** POINT / POINT UNION ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef point_type P;
+ typedef multi_point_type MP;
+
+ typedef test_set_op_of_pointlike_geometries
+ <
+ P, P, MP, bg::overlay_union
+ > tester;
+
+ tester::apply
+ (from_wkt<P>("POINT(0 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT(0 0,1 1)"),
+ "ppu01");
+
+ tester::apply
+ (from_wkt<P>("POINT(0 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ "ppu02");
+}
+
+
+BOOST_AUTO_TEST_CASE( test_union_multipoint_point )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTIPOINT / POINT UNION ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef point_type P;
+ typedef multi_point_type MP;
+
+ typedef test_set_op_of_pointlike_geometries
+ <
+ MP, P, MP, bg::overlay_union
+ > tester;
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT(0 0,1 1)"),
+ "mppu01");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ "mppu02");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT(0 0,0 0,1 1)"),
+ "mppu03");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ "mppu04");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0)"),
+ from_wkt<P>("POINT(1 1)"),
+ from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0,1 1)"),
+ "mppu05");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0)"),
+ from_wkt<P>("POINT(1 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0)"),
+ "mppu06");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,0 0,1 0)"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0,1 0)"),
+ "mppu07");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<P>("POINT(0 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0)"),
+ "mppu08");
+}
+
+
+BOOST_AUTO_TEST_CASE( test_union_multipoint_multipoint )
+{
+#ifdef BOOST_GEOMETRY_TEST_DEBUG
+ std::cout << std::endl << std::endl << std::endl;
+ std::cout << "*** MULTIPOINT / MULTIPOINT UNION ***" << std::endl;
+ std::cout << std::endl;
+#endif
+
+ typedef multi_point_type MP;
+
+ typedef test_set_op_of_pointlike_geometries
+ <
+ MP, MP, MP, bg::overlay_union
+ > tester;
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(2 2,3 3,0 0,0 0,2 2,1 1,1 1,1 0,1 0)"),
+ from_wkt<MP>("MULTIPOINT(1 0,1 1,1 1,1 1)"),
+ from_wkt<MP>("MULTIPOINT(2 2,3 3,0 0,0 0,2 2,1 1,1 1,1 0,1 0)"),
+ from_wkt<MP>("MULTIPOINT(1 0,1 1,1 1,1 1,2 2,3 3,0 0,0 0,2 2)"),
+ "mpmpu01");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,1 1,1 0,1 1)"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,1 1,0 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0,1 1,1 0,1 1)"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,1 1,0 0)"),
+ "mpmpu02");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,1 1,0 0)"),
+ from_wkt<MP>("MULTIPOINT(1 0,0 0,1 1,0 0)"),
+ "mpmpu03");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,1 1,1 0,1 1)"),
+ from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT(0 0,1 1,1 0,1 1)"),
+ "mpmpu04");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT()"),
+ from_wkt<MP>("MULTIPOINT()"),
+ "mpmpu05");
+
+ tester::apply
+ (from_wkt<MP>("MULTIPOINT(0 0,1 0,2 0,3 0,0 0,1 0,2 0)"),
+ from_wkt<MP>("MULTIPOINT(0 1,0 2,1 0,0 0,2 0)"),
+ from_wkt<MP>("MULTIPOINT(0 0,1 0,2 0,3 0,0 0,1 0,2 0,0 1,0 2)"),
+ from_wkt<MP>("MULTIPOINT(0 1,0 2,1 0,0 0,2 0,3 0)"),
+ "mpmpu06");
+}
+