1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3 
4 // Copyright (c) 2010-2015 Barend Gehrels, Amsterdam, the Netherlands.
5 
6 // Use, modification and distribution is subject to the Boost Software License,
7 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 
10 #include <iostream>
11 #include <string>
12 
13 // If defined, tests are run without rescaling-to-integer or robustness policy
14 // This multi_difference currently contains no tests for double which then fail
15 // #define BOOST_GEOMETRY_NO_ROBUSTNESS
16 
17 //#define HAVE_TTMATH
18 //#define BOOST_GEOMETRY_DEBUG_ASSEMBLE
19 //#define BOOST_GEOMETRY_CHECK_WITH_SQLSERVER
20 
21 //#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
22 //#define BOOST_GEOMETRY_DEBUG_FOLLOW
23 //#define BOOST_GEOMETRY_DEBUG_TRAVERSE
24 
25 
26 #include "test_difference.hpp"
27 #include <algorithms/test_overlay.hpp>
28 #include <algorithms/overlay/multi_overlay_cases.hpp>
29 
30 #include <boost/geometry/algorithms/correct.hpp>
31 #include <boost/geometry/algorithms/intersection.hpp>
32 #include <boost/geometry/algorithms/within.hpp> // only for testing #77
33 
34 #include <boost/geometry/geometries/point_xy.hpp>
35 #include <boost/geometry/geometries/multi_point.hpp>
36 #include <boost/geometry/geometries/multi_linestring.hpp>
37 #include <boost/geometry/geometries/multi_polygon.hpp>
38 
39 #include <boost/geometry/io/wkt/read.hpp>
40 
41 template <typename Ring, typename Polygon, typename MultiPolygon>
test_areal()42 void test_areal()
43 {
44     test_one<Polygon, MultiPolygon, MultiPolygon>("simplex_multi",
45             case_multi_simplex[0], case_multi_simplex[1],
46             5, 21, 5.58, 4, 17, 2.58);
47 
48     test_one<Polygon, MultiPolygon, MultiPolygon>("case_multi_no_ip",
49             case_multi_no_ip[0], case_multi_no_ip[1],
50             2, 12, 24.0, 2, 12, 34.0);
51     test_one<Polygon, MultiPolygon, MultiPolygon>("case_multi_2",
52             case_multi_2[0], case_multi_2[1],
53             2, 15, 19.6, 2, 13, 33.6);
54 
55     test_one<Polygon, MultiPolygon, Polygon>("simplex_multi_mp_p",
56             case_multi_simplex[0], case_single_simplex,
57             5, 21, 5.58, 4, 17, 2.58);
58     test_one<Polygon, Ring, MultiPolygon>("simplex_multi_r_mp",
59             case_single_simplex, case_multi_simplex[0],
60             4, 17, 2.58, 5, 21, 5.58);
61     test_one<Polygon, MultiPolygon, Ring>("simplex_multi_mp_r",
62             case_multi_simplex[0], case_single_simplex,
63             5, 21, 5.58, 4, 17, 2.58);
64 
65     // Constructed cases for multi/touch/equal/etc
66     test_one<Polygon, MultiPolygon, MultiPolygon>("case_61_multi",
67             case_61_multi[0], case_61_multi[1],
68             2, 10, 2, 2, 10, 2, 1, 10, 4);
69     test_one<Polygon, MultiPolygon, MultiPolygon>("case_62_multi",
70             case_62_multi[0], case_62_multi[1],
71             0, 0, 0, 1, 5, 1);
72     test_one<Polygon, MultiPolygon, MultiPolygon>("case_63_multi",
73             case_63_multi[0], case_63_multi[1],
74             0, 0, 0, 1, 5, 1);
75     test_one<Polygon, MultiPolygon, MultiPolygon>("case_64_multi",
76         case_64_multi[0], case_64_multi[1],
77         1, 5, 1, 1, 5, 1, 1, 7, 2);
78     test_one<Polygon, MultiPolygon, MultiPolygon>("case_65_multi",
79         case_65_multi[0], case_65_multi[1],
80             0, 0, 0, 2, 10, 3);
81     /* TODO: fix
82     test_one<Polygon, MultiPolygon, MultiPolygon>("case_72_multi",
83         case_72_multi[0], case_72_multi[1],
84             3, 13, 1.65, 3, 17, 6.15);
85     test_one<Polygon, MultiPolygon, MultiPolygon>("case_77_multi",
86         case_77_multi[0], case_77_multi[1],
87             6, 31, 7, 6, 36, 13);
88     */
89 
90     test_one<Polygon, MultiPolygon, MultiPolygon>("case_78_multi",
91         case_78_multi[0], case_78_multi[1],
92             1, 5, 1.0, 1, 5, 1.0);
93 
94     // Ticket on GGL list 2011/10/25
95     // to mix polygon/multipolygon in call to difference
96     test_one<Polygon, Polygon, Polygon>("ggl_list_20111025_vd_pp",
97         ggl_list_20111025_vd[0], ggl_list_20111025_vd[1],
98             1, 4, 8.0, 1, 4, 12.5);
99     test_one<Polygon, Polygon, MultiPolygon>("ggl_list_20111025_vd_pm",
100         ggl_list_20111025_vd[0], ggl_list_20111025_vd[3],
101             1, 4, 8.0, 1, 4, 12.5);
102     test_one<Polygon, MultiPolygon, Polygon>("ggl_list_20111025_vd_mp",
103         ggl_list_20111025_vd[2], ggl_list_20111025_vd[1],
104             1, 4, 8.0, 1, 4, 12.5);
105     test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20111025_vd_mm",
106         ggl_list_20111025_vd[2], ggl_list_20111025_vd[3],
107             1, 4, 8.0, 1, 4, 12.5);
108 
109     // Second case
110     // This can be tested with this SQL for SQL-Server
111     /*
112     with viewy as (select geometry::STGeomFromText(
113             'POLYGON((5 0,5 4,8 4,8 0,5 0))',0) as  p,
114       geometry::STGeomFromText(
115             'MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((4 0,4 2,6 2,6 0,4 0)))',0) as q)
116     select
117         p.STDifference(q).STArea(),p.STDifference(q).STNumGeometries(),p.STDifference(q) as p_min_q,
118         q.STDifference(p).STArea(),q.STDifference(p).STNumGeometries(),q.STDifference(p) as q_min_p,
119         p.STSymDifference(q).STArea(),q.STSymDifference(p) as p_xor_q
120     from viewy
121 
122     Outputting:
123     10, 1, <WKB>, 6, 2, <WKB>, 16, <WKB>
124     */
125 
126     test_one<Polygon, Polygon, MultiPolygon>("ggl_list_20111025_vd_2",
127         ggl_list_20111025_vd_2[0], ggl_list_20111025_vd_2[1],
128             1, 7, 10.0, 2, 10, 6.0);
129 
130     test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120915_h2_a",
131         ggl_list_20120915_h2[0], ggl_list_20120915_h2[1],
132             2, 13, 17.0, 0, 0, 0.0);
133     test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120915_h2_b",
134         ggl_list_20120915_h2[0], ggl_list_20120915_h2[2],
135             2, 13, 17.0, 0, 0, 0.0);
136 
137     test_one<Polygon, MultiPolygon, MultiPolygon>("ggl_list_20120221_volker",
138         ggl_list_20120221_volker[0], ggl_list_20120221_volker[1],
139             2, 12, 7962.66, 1, 18, 2775258.93,
140             0.001);
141 
142 #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
143     test_one<Polygon, MultiPolygon, MultiPolygon>("ticket_9081",
144         ticket_9081[0], ticket_9081[1],
145             2, 28, 0.0907392476356186, 4, 25, 0.126018011439877,
146             4, 42, 0.0907392476356186 + 0.126018011439877,
147             0.001);
148 #endif
149 
150     /* TODO: fix
151     test_one<Polygon, MultiPolygon, MultiPolygon>("case_101_multi",
152         case_101_multi[0], case_101_multi[1],
153             5, 23, 4.75, 5, 40, 12.75);
154     test_one<Polygon, MultiPolygon, MultiPolygon>("case_102_multi",
155         case_102_multi[0], case_102_multi[1],
156             2, 8, 0.75, 6, 25, 3.75);
157     test_one<Polygon, MultiPolygon, MultiPolygon>("case_107_multi",
158         case_107_multi[0], case_107_multi[1],
159             2, 11, 2.25, 3, 14, 3.0);
160     */
161     /*
162     test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_1",
163         case_recursive_boxes_1[0], case_recursive_boxes_1[1],
164             1, 1, 1, 1, 1, 1);
165     test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_2",
166         case_recursive_boxes_2[0], case_recursive_boxes_2[1],
167             1, 1, 1, 1, 1, 1);
168 
169      test_one<Polygon, MultiPolygon, MultiPolygon>("case_recursive_boxes_3",
170          case_recursive_boxes_3[0], case_recursive_boxes_3[1],
171             1, 1, 1, 1, 1, 1);
172 */
173 }
174 
175 template <typename MultiPolygon, typename MultiLineString>
test_areal_linear()176 void test_areal_linear()
177 {
178     typedef typename boost::range_value<MultiPolygon>::type Polygon;
179     typedef typename boost::range_value<MultiLineString>::type LineString;
180     typedef typename bg::point_type<Polygon>::type Point;
181     typedef bg::model::ring<Point> Ring;
182 
183     test_one_lp<LineString, LineString, MultiPolygon>("case_mp_ls_1", "LINESTRING(2 0,2 5)", case_multi_simplex[0], 2, 4, 1.30);
184     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);
185     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);
186     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);
187 
188     // Collinear cases, with multiple turn points at the same location
189     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);
190     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);
191 
192     test_one_lp<LineString, LineString, MultiPolygon>("case_mp_ls_3",
193             "LINESTRING(6 6,6 7,7 7,7 6,8 6,8 7,9 7,9 6)",
194             "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);
195 
196     return;
197 
198     // TODO: this case contains collinearities and should still be solved
199     test_one_lp<LineString, LineString, MultiPolygon>("case_mp_ls_4",
200             "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)",
201             "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);
202 }
203 
204 
205 template <typename P>
test_all()206 void test_all()
207 {
208     //typedef bg::model::box<P> box;
209     typedef bg::model::ring<P> ring;
210     typedef bg::model::polygon<P> polygon;
211     typedef bg::model::multi_polygon<polygon> multi_polygon;
212     test_areal<ring, polygon, multi_polygon>();
213     test_areal_linear<multi_polygon, bg::model::multi_linestring<bg::model::linestring<P> > >();
214 }
215 
216 
test_main(int,char * [])217 int test_main(int, char* [])
218 {
219     test_all<bg::model::d2::point_xy<double > >();
220 
221 #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
222     test_all<bg::model::d2::point_xy<float> >();
223 
224 #if defined(HAVE_TTMATH)
225     std::cout << "Testing TTMATH" << std::endl;
226     test_all<bg::model::d2::point_xy<ttmath_big> >();
227 #endif
228 
229 #endif
230 
231     return 0;
232 }
233