1 /**********************************************************************
2 *
3 * PostGIS - Spatial Types for PostgreSQL
4 * http://postgis.net
5 *
6 * Copyright (C) 2011-2015 Sandro Santilli <strk@kbt.io>
7 *
8 * This is free software; you can redistribute and/or modify it under
9 * the terms of the GNU General Public Licence. See the COPYING file.
10 *
11 **********************************************************************/
12
13 #include "CUnit/Basic.h"
14 #include "cu_tester.h"
15
16 #include "liblwgeom.h"
17 #include "liblwgeom_internal.h"
18 #include "../lwgeom_geos.h"
19
test_lwline_split_by_point_to(void)20 static void test_lwline_split_by_point_to(void)
21 {
22 LWLINE *line;
23 LWPOINT *point;
24 LWMLINE *coll;
25 int ret;
26
27 /* Because i don't trust that much prior tests... ;) */
28 cu_error_msg_reset();
29
30 coll = lwmline_construct_empty(SRID_UNKNOWN, 0, 0);
31 CU_ASSERT_EQUAL(coll->ngeoms, 0);
32
33 line = lwgeom_as_lwline(lwgeom_from_wkt("LINESTRING(0 0,5 5, 10 0)",
34 LW_PARSER_CHECK_NONE));
35 CU_ASSERT(line != NULL);
36
37 point = lwgeom_as_lwpoint(lwgeom_from_wkt(
38 "POINT(0 0)",
39 LW_PARSER_CHECK_NONE));
40 ret = lwline_split_by_point_to(line, point, coll);
41 CU_ASSERT_EQUAL(ret, 1);
42 CU_ASSERT_EQUAL(coll->ngeoms, 0);
43 lwpoint_free(point);
44
45 point = lwgeom_as_lwpoint(lwgeom_from_wkt(
46 "POINT(10 0)",
47 LW_PARSER_CHECK_NONE));
48 ret = lwline_split_by_point_to(line, point, coll);
49 CU_ASSERT_EQUAL(ret, 1);
50 CU_ASSERT_EQUAL(coll->ngeoms, 0);
51 lwpoint_free(point);
52
53 point = lwgeom_as_lwpoint(lwgeom_from_wkt(
54 "POINT(5 0)",
55 LW_PARSER_CHECK_NONE));
56 ret = lwline_split_by_point_to(line, point, coll);
57 CU_ASSERT_EQUAL(ret, 0);
58 CU_ASSERT_EQUAL(coll->ngeoms, 0);
59 lwpoint_free(point);
60
61 point = lwgeom_as_lwpoint(lwgeom_from_wkt(
62 "POINT(5 5)",
63 LW_PARSER_CHECK_NONE));
64 ret = lwline_split_by_point_to(line, point, coll);
65 CU_ASSERT_EQUAL(ret, 2);
66 CU_ASSERT_EQUAL(coll->ngeoms, 2);
67 lwpoint_free(point);
68
69 point = lwgeom_as_lwpoint(lwgeom_from_wkt(
70 "POINT(2 2)",
71 LW_PARSER_CHECK_NONE));
72 ret = lwline_split_by_point_to(line, point, coll);
73 CU_ASSERT_EQUAL(ret, 2);
74 CU_ASSERT_EQUAL(coll->ngeoms, 4);
75 lwpoint_free(point);
76
77 lwcollection_free((LWCOLLECTION*)coll);
78 lwline_free(line);
79 }
80
test_lwgeom_split(void)81 static void test_lwgeom_split(void)
82 {
83 LWGEOM *geom, *blade, *ret, *tmp1, *tmp2;
84 char *wkt, *in_wkt;
85
86 geom = lwgeom_from_wkt("MULTILINESTRING((-5 -2,0 0),(0 0,10 10))", LW_PARSER_CHECK_NONE);
87 CU_ASSERT(geom != NULL);
88 blade = lwgeom_from_wkt("POINT(0 0)", LW_PARSER_CHECK_NONE);
89 CU_ASSERT(blade != NULL);
90 ret = lwgeom_split(geom, blade);
91 CU_ASSERT(ret != NULL);
92 wkt = lwgeom_to_ewkt(ret);
93 in_wkt = "GEOMETRYCOLLECTION(LINESTRING(-5 -2,0 0),LINESTRING(0 0,10 10))";
94 ASSERT_STRING_EQUAL(wkt, in_wkt);
95 lwfree(wkt);
96 lwgeom_free(ret);
97 lwgeom_free(geom);
98 lwgeom_free(blade);
99
100 /* See #1311 */
101 geom = lwgeom_from_wkt("LINESTRING(0 0,10 0,20 4,0 3)", LW_PARSER_CHECK_NONE);
102 CU_ASSERT(geom != NULL);
103 blade = lwgeom_from_wkt("POINT(10 0)", LW_PARSER_CHECK_NONE);
104 ret = lwgeom_split(geom, blade);
105 CU_ASSERT(ret != NULL);
106 wkt = lwgeom_to_ewkt(ret);
107 in_wkt = "GEOMETRYCOLLECTION(LINESTRING(0 0,10 0),LINESTRING(10 0,20 4,0 3))";
108 ASSERT_STRING_EQUAL(wkt, in_wkt);
109 lwfree(wkt);
110 lwgeom_free(ret);
111 lwgeom_free(geom);
112 lwgeom_free(blade);
113
114 /* See #2528 (1) -- memory leak test, needs valgrind to check */
115 geom = lwgeom_from_wkt("SRID=1;LINESTRING(0 1,10 1)", LW_PARSER_CHECK_NONE);
116 CU_ASSERT(geom != NULL);
117 blade = lwgeom_from_wkt("LINESTRING(7 0,7 3)", LW_PARSER_CHECK_NONE);
118 ret = lwgeom_split(geom, blade);
119 CU_ASSERT(ret != NULL);
120 wkt = lwgeom_to_ewkt(ret);
121 in_wkt = "SRID=1;GEOMETRYCOLLECTION(LINESTRING(0 1,7 1),LINESTRING(7 1,10 1))";
122 ASSERT_STRING_EQUAL(wkt, in_wkt);
123 lwfree(wkt);
124 lwgeom_free(ret);
125 lwgeom_free(geom);
126 lwgeom_free(blade);
127
128 /* See #2528 (2) -- memory leak test, needs valgrind to check */
129 geom = lwgeom_from_wkt("SRID=1;POLYGON((0 1, 10 1, 10 10, 0 10, 0 1))", LW_PARSER_CHECK_NONE);
130 CU_ASSERT(geom != NULL);
131 blade = lwgeom_from_wkt("LINESTRING(7 0,7 20)", LW_PARSER_CHECK_NONE);
132 tmp1 = lwgeom_split(geom, blade);
133 ret = lwgeom_normalize(tmp1);
134 lwgeom_free(tmp1);
135 CU_ASSERT(ret != NULL);
136 wkt = lwgeom_to_ewkt(ret);
137 tmp1 = lwgeom_from_wkt(
138 "SRID=1;GEOMETRYCOLLECTION(POLYGON((7 1,0 1,0 10,7 10,7 1)),POLYGON((7 10,10 10,10 1,7 1,7 10)))",
139 LW_PARSER_CHECK_NONE);
140 tmp2 = lwgeom_normalize(tmp1);
141 in_wkt = lwgeom_to_ewkt(tmp2);
142 ASSERT_STRING_EQUAL(wkt, in_wkt);
143 lwfree(wkt);
144 lwfree(in_wkt);
145 lwgeom_free(tmp1);
146 lwgeom_free(tmp2);
147 lwgeom_free(ret);
148 lwgeom_free(geom);
149 lwgeom_free(blade);
150
151 /* Split line by multiline */
152 geom = lwgeom_from_wkt("LINESTRING(0 0, 10 0)", LW_PARSER_CHECK_NONE);
153 CU_ASSERT_FATAL(geom != NULL);
154 blade = lwgeom_from_wkt("MULTILINESTRING((1 1,1 -1),(2 1,2 -1,3 -1,3 1))", LW_PARSER_CHECK_NONE);
155 ret = lwgeom_split(geom, blade);
156 if (!ret)
157 printf("%s", cu_error_msg);
158 CU_ASSERT_FATAL(ret != NULL);
159 wkt = lwgeom_to_ewkt(ret);
160 CU_ASSERT_FATAL(wkt != NULL);
161 in_wkt = "GEOMETRYCOLLECTION(LINESTRING(0 0,1 0),LINESTRING(1 0,2 0),LINESTRING(2 0,3 0),LINESTRING(3 0,10 0))";
162 ASSERT_STRING_EQUAL(wkt, in_wkt);
163 lwfree(wkt);
164 lwgeom_free(ret);
165 lwgeom_free(geom);
166 lwgeom_free(blade);
167
168 /* Split line by polygon (boundary) */
169 geom = lwgeom_from_wkt("LINESTRING(0 0, 10 0)", LW_PARSER_CHECK_NONE);
170 CU_ASSERT_FATAL(geom != NULL);
171 blade = lwgeom_from_wkt("POLYGON((1 -2,1 1,2 1,2 -1,3 -1,3 1,11 1,11 -2,1 -2))", LW_PARSER_CHECK_NONE);
172 ret = lwgeom_split(geom, blade);
173 if (!ret)
174 printf("%s", cu_error_msg);
175 CU_ASSERT_FATAL(ret != NULL);
176 wkt = lwgeom_to_ewkt(ret);
177 CU_ASSERT_FATAL(wkt != NULL);
178 in_wkt = "GEOMETRYCOLLECTION(LINESTRING(0 0,1 0),LINESTRING(1 0,2 0),LINESTRING(2 0,3 0),LINESTRING(3 0,10 0))";
179 ASSERT_STRING_EQUAL(wkt, in_wkt);
180 lwfree(wkt);
181 lwgeom_free(ret);
182 lwgeom_free(geom);
183 lwgeom_free(blade);
184
185 /* Split line by EMPTY polygon (boundary) */
186 geom = lwgeom_from_wkt("LINESTRING(0 0, 10 0)", LW_PARSER_CHECK_NONE);
187 CU_ASSERT_FATAL(geom != NULL);
188 blade = lwgeom_from_wkt("POLYGON EMPTY", LW_PARSER_CHECK_NONE);
189 ret = lwgeom_split(geom, blade);
190 if (!ret)
191 printf("%s", cu_error_msg);
192 CU_ASSERT_FATAL(ret != NULL);
193 wkt = lwgeom_to_ewkt(ret);
194 CU_ASSERT_FATAL(wkt != NULL);
195 in_wkt = "GEOMETRYCOLLECTION(LINESTRING(0 0,10 0))";
196 ASSERT_STRING_EQUAL(wkt, in_wkt);
197 lwfree(wkt);
198 lwgeom_free(ret);
199 lwgeom_free(geom);
200 lwgeom_free(blade);
201
202 /* Split line by multipolygon (boundary) */
203 geom = lwgeom_from_wkt("LINESTRING(0 0, 10 0)", LW_PARSER_CHECK_NONE);
204 CU_ASSERT_FATAL(geom != NULL);
205 blade = lwgeom_from_wkt("MULTIPOLYGON(((1 -1,1 1,2 1,2 -1,1 -1)),((3 -1,3 1,11 1,11 -1,3 -1)))",
206 LW_PARSER_CHECK_NONE);
207 ret = lwgeom_split(geom, blade);
208 if (!ret)
209 printf("%s", cu_error_msg);
210 CU_ASSERT_FATAL(ret != NULL);
211 wkt = lwgeom_to_ewkt(ret);
212 CU_ASSERT_FATAL(wkt != NULL);
213 in_wkt = "GEOMETRYCOLLECTION(LINESTRING(0 0,1 0),LINESTRING(1 0,2 0),LINESTRING(2 0,3 0),LINESTRING(3 0,10 0))";
214 ASSERT_STRING_EQUAL(wkt, in_wkt);
215 lwfree(wkt);
216 lwgeom_free(ret);
217 lwgeom_free(geom);
218 lwgeom_free(blade);
219
220 /* Split line by multipoint */
221 geom = lwgeom_from_wkt("LINESTRING(0 0, 10 0)", LW_PARSER_CHECK_NONE);
222 CU_ASSERT_FATAL(geom != NULL);
223 blade = lwgeom_from_wkt("MULTIPOINT(2 0,8 0,4 0)", LW_PARSER_CHECK_NONE);
224 ret = lwgeom_split(geom, blade);
225 if (!ret)
226 printf("%s", cu_error_msg);
227 CU_ASSERT_FATAL(ret != NULL);
228 wkt = lwgeom_to_ewkt(ret);
229 CU_ASSERT_FATAL(wkt != NULL);
230 in_wkt = "GEOMETRYCOLLECTION(LINESTRING(8 0,10 0),LINESTRING(0 0,2 0),LINESTRING(4 0,8 0),LINESTRING(2 0,4 0))";
231 ASSERT_STRING_EQUAL(wkt, in_wkt);
232 lwfree(wkt);
233 lwgeom_free(ret);
234 lwgeom_free(geom);
235 lwgeom_free(blade);
236
237 /* See #3401 -- robustness issue */
238 geom = lwgeom_from_wkt("LINESTRING(-180 0,0 0)", LW_PARSER_CHECK_NONE);
239 CU_ASSERT(geom != NULL);
240 blade = lwgeom_from_wkt("POINT(-20 0)", LW_PARSER_CHECK_NONE);
241 ret = lwgeom_split(geom, blade);
242 CU_ASSERT(ret != NULL);
243 {
244 LWCOLLECTION *split = lwgeom_as_lwcollection(ret);
245 LWLINE *l1, *l2;
246 POINT2D pt;
247 CU_ASSERT(split != NULL);
248 l1 = lwgeom_as_lwline(split->geoms[0]);
249 CU_ASSERT(l1 != NULL);
250 getPoint2d_p(l1->points, 1, &pt);
251 ASSERT_DOUBLE_EQUAL(pt.x, -20);
252 ASSERT_DOUBLE_EQUAL(pt.y, 0);
253 l2 = lwgeom_as_lwline(split->geoms[1]);
254 CU_ASSERT(l2 != NULL);
255 getPoint2d_p(l2->points, 0, &pt);
256 ASSERT_DOUBLE_EQUAL(pt.x, -20);
257 ASSERT_DOUBLE_EQUAL(pt.y, 0);
258 }
259 lwgeom_free(ret);
260 lwgeom_free(geom);
261 lwgeom_free(blade);
262 }
263
264 static int
clean_geos_split_suite(void)265 clean_geos_split_suite(void)
266 {
267 finishGEOS();
268 return 0;
269 }
270
271 /*
272 ** Used by test harness to register the tests in this file.
273 */
274 void split_suite_setup(void);
split_suite_setup(void)275 void split_suite_setup(void)
276 {
277 CU_pSuite suite = CU_add_suite("split", NULL, clean_geos_split_suite);
278 PG_ADD_TEST(suite, test_lwline_split_by_point_to);
279 PG_ADD_TEST(suite, test_lwgeom_split);
280 }
281