PostGIS  2.1.10dev-r@@SVN_REVISION@@
cu_ptarray.c
Go to the documentation of this file.
1 /**********************************************************************
2  * $Id: cu_print.c 6160 2010-11-01 01:28:12Z pramsey $
3  *
4  * PostGIS - Spatial Types for PostgreSQL
5  * http://postgis.net
6  *
7  * Copyright (C) 2011 Sandro Santilli <strk@keybit.net>
8  * Copyright (C) 2008 Paul Ramsey
9  *
10  * This is free software; you can redistribute and/or modify it under
11  * the terms of the GNU General Public Licence. See the COPYING file.
12  *
13  **********************************************************************/
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include "CUnit/Basic.h"
19 #include "CUnit/CUnit.h"
20 
21 #include "liblwgeom_internal.h"
22 #include "cu_tester.h"
23 
24 
25 static LWGEOM* lwgeom_from_text(const char *str)
26 {
28  if( LW_FAILURE == lwgeom_parse_wkt(&r, (char*)str, LW_PARSER_CHECK_NONE) )
29  return NULL;
30  return r.geom;
31 }
32 
33 static char* lwgeom_to_text(const LWGEOM *geom)
34 {
35  return lwgeom_to_wkt(geom, WKT_ISO, 8, NULL);
36 }
37 
38 static void test_ptarray_append_point(void)
39 {
40  LWLINE *line;
41  char *wkt;
42  POINT4D p;
43 
44  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0,1 1)"));
45  p.x = 1;
46  p.y = 1;
48  wkt = lwgeom_to_text(lwline_as_lwgeom(line));
49  CU_ASSERT_STRING_EQUAL(wkt,"LINESTRING(0 0,1 1,1 1)");
50  lwfree(wkt);
51 
53  wkt = lwgeom_to_text(lwline_as_lwgeom(line));
54  CU_ASSERT_STRING_EQUAL(wkt,"LINESTRING(0 0,1 1,1 1)");
55  lwfree(wkt);
56 
57  lwline_free(line);
58 }
59 
60 static void test_ptarray_insert_point(void)
61 {
62  LWLINE *line;
63  char *wkt;
64  POINT4D p;
65 
66  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING EMPTY"));
67  p.x = 1;
68  p.y = 1;
69  ptarray_insert_point(line->points, &p, 0);
70  wkt = lwgeom_to_text(lwline_as_lwgeom(line));
71  CU_ASSERT_STRING_EQUAL(wkt,"LINESTRING(1 1)");
72  lwfree(wkt);
73 
74  p.x = 2;
75  p.y = 20;
76  ptarray_insert_point(line->points, &p, 0);
77  wkt = lwgeom_to_text(lwline_as_lwgeom(line));
78  CU_ASSERT_STRING_EQUAL(wkt,"LINESTRING(2 20,1 1)");
79  lwfree(wkt);
80 
81  p.x = 3;
82  p.y = 30;
83  ptarray_insert_point(line->points, &p, 1);
84  wkt = lwgeom_to_text(lwline_as_lwgeom(line));
85  CU_ASSERT_STRING_EQUAL(wkt,"LINESTRING(2 20,3 30,1 1)");
86  lwfree(wkt);
87 
88  p.x = 4;
89  p.y = 40;
90  ptarray_insert_point(line->points, &p, 0);
91  wkt = lwgeom_to_text(lwline_as_lwgeom(line));
92  CU_ASSERT_STRING_EQUAL(wkt,"LINESTRING(4 40,2 20,3 30,1 1)");
93  lwfree(wkt);
94 
95  p.x = 5;
96  p.y = 50;
97  ptarray_insert_point(line->points, &p, 4);
98  wkt = lwgeom_to_text(lwline_as_lwgeom(line));
99  CU_ASSERT_STRING_EQUAL(wkt,"LINESTRING(4 40,2 20,3 30,1 1,5 50)");
100  lwfree(wkt);
101 
102  lwline_free(line);
103 }
104 
106 {
107  LWLINE *line1, *line2;
108  int ret;
109  char *wkt;
110 
111  /* Empty first line */
112  line1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING EMPTY"));
113  line2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0,0 10,5 5)"));
114  ret = ptarray_append_ptarray(line1->points, line2->points, -1);
115  CU_ASSERT(ret == LW_SUCCESS);
116  wkt = lwgeom_to_text(lwline_as_lwgeom(line1));
117  CU_ASSERT_STRING_EQUAL(wkt, "LINESTRING(0 0,0 10,5 5)");
118  lwfree(wkt);
119  lwline_free(line2);
120  lwline_free(line1);
121 
122  /* Empty second line */
123  line1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0, 5 5, 6 3)"));
124  line2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING EMPTY"));
125  ret = ptarray_append_ptarray(line1->points, line2->points, -1);
126  CU_ASSERT(ret == LW_SUCCESS);
127  wkt = lwgeom_to_text(lwline_as_lwgeom(line1));
128  CU_ASSERT_STRING_EQUAL(wkt, "LINESTRING(0 0,5 5,6 3)");
129  lwfree(wkt);
130  lwline_free(line2);
131  lwline_free(line1);
132 
133  /* Both lines empty */
134  line1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING EMPTY"));
135  line2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING EMPTY"));
136  ret = ptarray_append_ptarray(line1->points, line2->points, -1);
137  CU_ASSERT(ret == LW_SUCCESS);
138  wkt = lwgeom_to_text(lwline_as_lwgeom(line1));
139  CU_ASSERT_STRING_EQUAL(wkt, "LINESTRING EMPTY");
140  lwfree(wkt);
141  lwline_free(line2);
142  lwline_free(line1);
143 
144  /* Sane sewing */
145  line1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(10 4, 0 0,5 7)"));
146  line2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(5 7,12 43, 42 15)"));
147  ret = ptarray_append_ptarray(line1->points, line2->points, 0);
148  CU_ASSERT(ret == LW_SUCCESS);
149  wkt = lwgeom_to_text(lwline_as_lwgeom(line1));
150  CU_ASSERT_STRING_EQUAL(wkt, "LINESTRING(10 4,0 0,5 7,12 43,42 15)");
151  lwfree(wkt);
152  lwline_free(line2);
153  lwline_free(line1);
154 
155  /* Untolerated sewing */
156  line1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(10 4, 0 0,5 7)"));
157  line2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(5.5 7,12 43, 42 15)"));
158  ret = ptarray_append_ptarray(line1->points, line2->points, 0);
159  CU_ASSERT(ret == LW_FAILURE);
160  lwline_free(line2);
161  lwline_free(line1);
162 
163  /* Tolerated sewing */
164  line1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(10 4, 0 0,5 7)"));
165  line2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(5.5 7,12 43, 42 15)"));
166  ret = ptarray_append_ptarray(line1->points, line2->points, .7);
167  CU_ASSERT(ret == LW_SUCCESS);
168  wkt = lwgeom_to_text(lwline_as_lwgeom(line1));
169  CU_ASSERT_STRING_EQUAL(wkt, "LINESTRING(10 4,0 0,5 7,5.5 7,12 43,42 15)");
170  lwfree(wkt);
171  lwline_free(line2);
172  lwline_free(line1);
173 
174  /* Check user input trust (creates non-simple line */
175  line1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0,0 10)"));
176  line2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0,0 10)"));
177  ret = ptarray_append_ptarray(line1->points, line2->points, -1);
178  CU_ASSERT(ret == LW_SUCCESS);
179  wkt = lwgeom_to_text(lwline_as_lwgeom(line1));
180  CU_ASSERT_STRING_EQUAL(wkt, "LINESTRING(0 0,0 10,0 0,0 10)");
181  lwfree(wkt);
182  lwline_free(line2);
183  lwline_free(line1);
184 
185  /* Mixed dimensionality is not allowed */
186  line1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 10 0, 10 0 0)"));
187  line2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(10 0,11 0)"));
188  ret = ptarray_append_ptarray(line1->points, line2->points, -1);
189  CU_ASSERT(ret == LW_FAILURE);
190  lwline_free(line2);
191  lwline_free(line1);
192 
193  /* Appending a read-only pointarray is allowed */
194  line1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 10, 10 0)"));
195  line2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(10 0,11 0)"));
196  FLAGS_SET_READONLY(line2->points->flags, 1);
197  ret = ptarray_append_ptarray(line1->points, line2->points, -1);
198  CU_ASSERT(ret == LW_SUCCESS);
199  wkt = lwgeom_to_text(lwline_as_lwgeom(line1));
200  CU_ASSERT_STRING_EQUAL(wkt, "LINESTRING(0 10,10 0,11 0)");
201  lwfree(wkt);
202  FLAGS_SET_READONLY(line2->points->flags, 0); /* for lwline_free */
203  lwline_free(line2);
204  lwline_free(line1);
205 
206  /* Appending to a read-only pointarray is forbidden */
207  line1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 10, 10 0)"));
208  line2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(10 0,11 0)"));
209  FLAGS_SET_READONLY(line1->points->flags, 1);
210  ret = ptarray_append_ptarray(line1->points, line2->points, -1);
211  CU_ASSERT(ret == LW_FAILURE);
212  lwline_free(line2);
213  FLAGS_SET_READONLY(line1->points->flags, 0); /* for lwline_free */
214  lwline_free(line1);
215 
216 }
217 
218 static void test_ptarray_locate_point(void)
219 {
220  LWLINE *line;
221  double loc, dist;
222  POINT4D p, l;
223 
224  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 3,20 4)"));
225 
226  p = getPoint4d(line->points, 0);
227  loc = ptarray_locate_point(line->points, &p, &dist, &l);
228  CU_ASSERT_EQUAL(loc, 0);
229  CU_ASSERT_EQUAL(dist, 0.0);
230 
231  p = getPoint4d(line->points, 1);
232  loc = ptarray_locate_point(line->points, &p, &dist, &l);
233  CU_ASSERT_EQUAL(loc, 1);
234  CU_ASSERT_EQUAL(dist, 0.0);
235 
236  p.x = 21; p.y = 4;
237  loc = ptarray_locate_point(line->points, &p, &dist, NULL);
238  CU_ASSERT_EQUAL(loc, 1);
239  CU_ASSERT_EQUAL(dist, 1.0);
240 
241  p.x = 0; p.y = 2;
242  loc = ptarray_locate_point(line->points, &p, &dist, &l);
243  CU_ASSERT_EQUAL(loc, 0);
244  CU_ASSERT_EQUAL(dist, 1.0);
245 
246  lwline_free(line);
247  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0,20 0,40 0)"));
248 
249  p.x = 20; p.y = 0;
250  loc = ptarray_locate_point(line->points, &p, &dist, &l);
251  CU_ASSERT_EQUAL(loc, 0.5);
252  CU_ASSERT_EQUAL(dist, 0.0);
253 
254  lwline_free(line);
255  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-40 0,0 0,20 0,40 0)"));
256 
257  p.x = 20; p.y = 0;
258  loc = ptarray_locate_point(line->points, &p, &dist, &l);
259  CU_ASSERT_EQUAL(loc, 0.75);
260  CU_ASSERT_EQUAL(dist, 0.0);
261 
262  lwline_free(line);
263  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING M (0 0 0, 10 0 20)"));
264 
265  p.x = 5; p.y = 0;
266  loc = ptarray_locate_point(line->points, &p, &dist, &l);
267  CU_ASSERT_EQUAL(loc, 0.5);
268  CU_ASSERT_EQUAL(dist, 0.0);
269  CU_ASSERT_EQUAL(l.m, 10.0);
270 
271  lwline_free(line);
272 
273 }
274 
275 static void test_ptarray_isccw(void)
276 {
277  LWLINE *line;
278  LWPOLY* poly;
279  int ccw;
280 
281  /* clockwise rectangle */
282  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0,0 10,10 10,10 0, 0 0)"));
283  ccw = ptarray_isccw(line->points);
284  CU_ASSERT_EQUAL(ccw, 0);
285  lwline_free(line);
286 
287  /* clockwise triangle */
288  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 3,20 4,20 3, 0 3)"));
289  ccw = ptarray_isccw(line->points);
290  CU_ASSERT_EQUAL(ccw, 0);
291  lwline_free(line);
292 
293  /* counterclockwise triangle */
294  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 3,20 3,20 4, 0 3)"));
295  ccw = ptarray_isccw(line->points);
296  CU_ASSERT_EQUAL(ccw, 1);
297  lwline_free(line);
298 
299  /* counterclockwise narrow ring (see ticket #1302) */
300  line = lwgeom_as_lwline(lwgeom_from_hexwkb("01020000000500000000917E9BA468294100917E9B8AEA284137894120A4682941C976BE9F8AEA2841B39ABE1FA46829415ACCC29F8AEA2841C976BE1FA4682941C976BE9F8AEA284100917E9BA468294100917E9B8AEA2841", LW_PARSER_CHECK_NONE));
301  ccw = ptarray_isccw(line->points);
302  CU_ASSERT_EQUAL(ccw, 1);
303  lwline_free(line);
304 
305  /* clockwise narrow ring (see ticket #1302) */
306  line = lwgeom_as_lwline(lwgeom_from_hexwkb("01020000000500000000917E9BA468294100917E9B8AEA2841C976BE1FA4682941C976BE9F8AEA2841B39ABE1FA46829415ACCC29F8AEA284137894120A4682941C976BE9F8AEA284100917E9BA468294100917E9B8AEA2841", LW_PARSER_CHECK_NONE));
307  ccw = ptarray_isccw(line->points);
308  CU_ASSERT_EQUAL(ccw, 0);
309  lwline_free(line);
310 
311  /* Clockwise narrow ring (see ticket #1302) */
312  poly = lwgeom_as_lwpoly(lwgeom_from_hexwkb("0103000000010000000500000000917E9BA468294100917E9B8AEA2841C976BE1FA4682941C976BE9F8AEA2841B39ABE1FA46829415ACCC29F8AEA284137894120A4682941C976BE9F8AEA284100917E9BA468294100917E9B8AEA2841", LW_PARSER_CHECK_NONE));
313  ccw = ptarray_isccw(poly->rings[0]);
314  CU_ASSERT_EQUAL(ccw, 0);
315  lwpoly_free(poly);
316 }
317 
319 {
320  LWLINE *line;
321  double area;
322 
323  /* parallelogram */
324  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0,1 1, 2 1, 1 0, 0 0)"));
325  area = ptarray_signed_area(line->points);
326  CU_ASSERT_DOUBLE_EQUAL(area, 1.0, 0.0000001);
327  lwline_free(line);
328 
329  /* square */
330  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0,0 2, 2 2, 2 0, 0 0)"));
331  area = ptarray_signed_area(line->points);
332  CU_ASSERT_DOUBLE_EQUAL(area, 4.0, 0.0000001);
333  lwline_free(line);
334 
335  /* square backwares*/
336  line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0,2 0, 2 2, 0 2, 0 0)"));
337  area = ptarray_signed_area(line->points);
338  //printf("%g\n",area);
339  CU_ASSERT_DOUBLE_EQUAL(area, -4.0, 0.0000001);
340  lwline_free(line);
341 
342 }
343 
344 
345 
347 {
348  LWGEOM *in, *out;
349  char *str;
350 
351  /* It would be nice if this example returned two arcs (it's the intersection of two circles)
352  but it looks like the intersection itself is too sloppy in generating the derived point
353  to accurately reconstruct the circles.
354  in = lwgeom_from_text("POLYGON((0.5 0,0.471177920604846 -0.292635483024192,0.38581929876693 -0.574025148547634,0.247204418453818 -0.833355349529403,0.0606601717798223 -1.06066017177982,-5.44089437167602e-17 -1.11044268820754,-0.0606601717798188 -1.06066017177982,-0.247204418453816 -0.833355349529406,-0.385819298766929 -0.574025148547639,-0.471177920604845 -0.292635483024197,-0.5 -4.84663372329776e-15,-0.471177920604847 0.292635483024187,-0.385819298766932 0.57402514854763,-0.247204418453821 0.833355349529398,-0.0606601717798256 1.06066017177982,3.45538806345173e-16 1.11044268820754,0.0606601717798183 1.06066017177982,0.247204418453816 0.833355349529407,0.385819298766929 0.574025148547638,0.471177920604845 0.292635483024196,0.5 0))");
355  out = lwgeom_desegmentize(in);
356  str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
357  printf("%s\n", str);
358  CU_ASSERT_STRING_EQUAL(str, "CIRCULARSTRING(-1 0,0 1,0 -1)");
359  lwgeom_free(in);
360  lwgeom_free(out);
361  lwfree(str);
362  */
363 
364  in = lwgeom_from_text("CIRCULARSTRING(-1 0,0 1,0 -1)");
365  out = lwgeom_segmentize(in,8);
366  lwgeom_free(in);
367  in = out;
368  out = lwgeom_desegmentize(in);
369  str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
370  //printf("%s\n", str);
371  CU_ASSERT_STRING_EQUAL(str, "CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1)");
372  lwgeom_free(in);
373  lwgeom_free(out);
374  lwfree(str);
375 
376  in = lwgeom_from_text("COMPOUNDCURVE(CIRCULARSTRING(-1 0,0 1,0 -1),(0 -1,-1 -1))");
377  out = lwgeom_segmentize(in,8);
378  lwgeom_free(in);
379  in = out;
380  out = lwgeom_desegmentize(in);
381  str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
382  //printf("%s\n", str);
383  CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE(CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1),(0 -1,-1 -1))");
384  lwgeom_free(in);
385  lwgeom_free(out);
386  lwfree(str);
387 
388  in = lwgeom_from_text("COMPOUNDCURVE((-3 -3,-1 0),CIRCULARSTRING(-1 0,0 1,0 -1),(0 -1,0 -1.5,0 -2),CIRCULARSTRING(0 -2,-1 -3,1 -3),(1 -3,5 5))");
389  out = lwgeom_segmentize(in,8);
390  lwgeom_free(in);
391  in = out;
392  out = lwgeom_desegmentize(in);
393  str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
394  //printf("%s\n", str);
395  CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE((-3 -3,-1 0),CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1),(0 -1,0 -1.5,0 -2),CIRCULARSTRING(0 -2,-0.70710678 -3.7071068,1 -3),(1 -3,5 5))");
396  lwgeom_free(in);
397  lwgeom_free(out);
398  lwfree(str);
399 
400  in = lwgeom_from_text("COMPOUNDCURVE(CIRCULARSTRING(-1 0,0 1,0 -1),CIRCULARSTRING(0 -1,-1 -2,1 -2))");
401  out = lwgeom_segmentize(in,8);
402  lwgeom_free(in);
403  in = out;
404  out = lwgeom_desegmentize(in);
405  str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
406  //printf("%s\n", str);
407  CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE(CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1),CIRCULARSTRING(0 -1,-0.70710678 -2.7071068,1 -2))");
408  lwgeom_free(in);
409  lwgeom_free(out);
410  lwfree(str);
411 
412  in = lwgeom_from_text("COMPOUNDCURVE((0 0, 1 1), CIRCULARSTRING(1 1, 2 2, 3 1), (3 1, 4 4))");
413  out = lwgeom_segmentize(in,8);
414  lwgeom_free(in);
415  in = out;
416  out = lwgeom_desegmentize(in);
417  str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
418  CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE((0 0,1 1),CIRCULARSTRING(1 1,2 2,3 1),(3 1,4 4))");
419  lwgeom_free(in);
420  lwgeom_free(out);
421 // printf("%s\n", str);
422  lwfree(str);
423 
424  // See http://trac.osgeo.org/postgis/ticket/2425
425  // and http://trac.osgeo.org/postgis/ticket/2420
426  in = lwgeom_from_text("LINESTRING(0 0,10 0,10 10,0 10,0 0)");
427  out = lwgeom_desegmentize(in);
428  str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
429  CU_ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,10 0,10 10,0 10,0 0)");
430  lwgeom_free(in);
431  lwgeom_free(out);
432  lwfree(str);
433 
434  in = lwgeom_from_text("LINESTRING(10 10,0 10,0 0,10 0)");
435  out = lwgeom_desegmentize(in);
436  str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
437  CU_ASSERT_STRING_EQUAL(str, "LINESTRING(10 10,0 10,0 0,10 0)");
438  // printf("%s\n", str);
439  lwgeom_free(in);
440  lwgeom_free(out);
441  lwfree(str);
442 
443  in = lwgeom_from_text("LINESTRING(0 0,10 0,10 10,0 10)");
444  out = lwgeom_desegmentize(in);
445  str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
446  CU_ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,10 0,10 10,0 10)");
447  // printf("%s\n", str);
448  lwgeom_free(in);
449  lwgeom_free(out);
450  lwfree(str);
451 
452  // See http://trac.osgeo.org/postgis/ticket/2412
453  in = lwgeom_from_text("LINESTRING(0 0, 1 1)");
454  out = lwgeom_desegmentize(in);
455  str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL);
456 //printf("%s\n", str);
457  CU_ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,1 1)");
458  lwgeom_free(in);
459  lwgeom_free(out);
460  lwfree(str);
461 }
462 
464 {
465 /* int ptarray_contains_point(const POINTARRAY *pa, const POINT2D *pt, int *winding_number) */
466 
467  LWLINE *lwline;
468  POINTARRAY *pa;
469  POINT2D pt;
470  int rv;
471 
472  lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0, 0 1, 1 1, 1 0, 0 0)"));
473  pa = lwline->points;
474 
475  /* Point in middle of square */
476  pt.x = 0.5;
477  pt.y = 0.5;
478  rv = ptarray_contains_point(pa, &pt);
479  CU_ASSERT_EQUAL(rv, LW_INSIDE);
480 
481  /* Point on left edge of square */
482  pt.x = 0;
483  pt.y = 0.5;
484  rv = ptarray_contains_point(pa, &pt);
485  CU_ASSERT_EQUAL(rv, LW_BOUNDARY);
486 
487  /* Point on top edge of square */
488  pt.x = 0.5;
489  pt.y = 1;
490  rv = ptarray_contains_point(pa, &pt);
491  CU_ASSERT_EQUAL(rv, LW_BOUNDARY);
492 
493  /* Point on bottom left corner of square */
494  pt.x = 0;
495  pt.y = 0;
496  rv = ptarray_contains_point(pa, &pt);
497  CU_ASSERT_EQUAL(rv, LW_BOUNDARY);
498 
499  /* Point on top left corner of square */
500  pt.x = 0;
501  pt.y = 1;
502  rv = ptarray_contains_point(pa, &pt);
503  CU_ASSERT_EQUAL(rv, LW_BOUNDARY);
504 
505  /* Point outside top left corner of square */
506  pt.x = -0.1;
507  pt.y = 1;
508  rv = ptarray_contains_point(pa, &pt);
509  CU_ASSERT_EQUAL(rv, LW_OUTSIDE);
510 
511  /* Point outside top left corner of square */
512  pt.x = 0;
513  pt.y = 1.1;
514  rv = ptarray_contains_point(pa, &pt);
515  CU_ASSERT_EQUAL(rv, LW_OUTSIDE);
516 
517  /* Point outside left side of square */
518  pt.x = -0.2;
519  pt.y = 0.5;
520  rv = ptarray_contains_point(pa, &pt);
521  CU_ASSERT_EQUAL(rv, LW_OUTSIDE);
522 
523  lwline_free(lwline);
524  lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0, 1 1, 2 0, 0 0)"));
525  pa = lwline->points;
526 
527  /* Point outside grazing top of triangle */
528  pt.x = 0;
529  pt.y = 1;
530  rv = ptarray_contains_point(pa, &pt);
531  CU_ASSERT_EQUAL(rv, LW_OUTSIDE);
532 
533  lwline_free(lwline);
534  lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0, 0 4, 1 4, 2 2, 3 4, 4 4, 4 0, 0 0)"));
535  pa = lwline->points;
536 
537  /* Point outside grazing top of triangle */
538  pt.x = 1;
539  pt.y = 2;
540  rv = ptarray_contains_point(pa, &pt);
541  CU_ASSERT_EQUAL(rv, LW_INSIDE);
542 
543  /* Point outside grazing top of triangle */
544  pt.x = 3;
545  pt.y = 2;
546  rv = ptarray_contains_point(pa, &pt);
547  CU_ASSERT_EQUAL(rv, LW_INSIDE);
548 
549  lwline_free(lwline);
550 }
551 
553 {
554  /* int ptarrayarc_contains_point(const POINTARRAY *pa, const POINT2D *pt) */
555 
556  LWLINE *lwline;
557  POINTARRAY *pa;
558  POINT2D pt;
559  int rv;
560 
561  /*** Collection of semi-circles surrounding unit square ***/
562  lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 -1, -2 0, -1 1, 0 2, 1 1, 2 0, 1 -1, 0 -2, -1 -1)"));
563  pa = lwline->points;
564 
565  /* Point in middle of square */
566  pt.x = 0;
567  pt.y = 0;
568  rv = ptarrayarc_contains_point(pa, &pt);
569  CU_ASSERT_EQUAL(rv, LW_INSIDE);
570 
571  /* Point in left lobe */
572  pt.x = -1.1;
573  pt.y = 0.1;
574  rv = ptarrayarc_contains_point(pa, &pt);
575  CU_ASSERT_EQUAL(rv, LW_INSIDE);
576 
577  /* Point on boundary of left lobe */
578  pt.x = -1;
579  pt.y = 0;
580  rv = ptarrayarc_contains_point(pa, &pt);
581  CU_ASSERT_EQUAL(rv, LW_INSIDE);
582 
583  /* Point on boundary vertex */
584  pt.x = -1;
585  pt.y = 1;
586  rv = ptarrayarc_contains_point(pa, &pt);
587  CU_ASSERT_EQUAL(rv, LW_BOUNDARY);
588 
589  /* Point outside */
590  pt.x = -1.5;
591  pt.y = 1.5;
592  rv = ptarrayarc_contains_point(pa, &pt);
593  CU_ASSERT_EQUAL(rv, LW_OUTSIDE);
594 
595  /*** Two-edge ring made up of semi-circles (really, a circle) ***/
596  lwline_free(lwline);
597  lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0, 0 -1, -1 0)"));
598  pa = lwline->points;
599 
600  /* Point outside */
601  pt.x = -1.5;
602  pt.y = 1.5;
603  rv = ptarrayarc_contains_point(pa, &pt);
604  CU_ASSERT_EQUAL(rv, LW_OUTSIDE);
605 
606  /* Point more outside */
607  pt.x = 2.5;
608  pt.y = 1.5;
609  rv = ptarrayarc_contains_point(pa, &pt);
610  CU_ASSERT_EQUAL(rv, LW_OUTSIDE);
611 
612  /* Point more outside */
613  pt.x = 2.5;
614  pt.y = 2.5;
615  rv = ptarrayarc_contains_point(pa, &pt);
616  CU_ASSERT_EQUAL(rv, LW_OUTSIDE);
617 
618  /* Point inside at middle */
619  pt.x = 0;
620  pt.y = 0;
621  rv = ptarrayarc_contains_point(pa, &pt);
622  CU_ASSERT_EQUAL(rv, LW_INSIDE);
623 
624  /* Point inside offset from middle */
625  pt.x = 0.01;
626  pt.y = 0.01;
627  rv = ptarrayarc_contains_point(pa, &pt);
628  CU_ASSERT_EQUAL(rv, LW_INSIDE);
629 
630  /* Point on edge vertex */
631  pt.x = 0;
632  pt.y = 1;
633  rv = ptarrayarc_contains_point(pa, &pt);
634  CU_ASSERT_EQUAL(rv, LW_BOUNDARY);
635 
636  /*** Two-edge ring, closed ***/
637  lwline_free(lwline);
638  lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(1 6, 6 1, 9 7, 6 10, 1 6)"));
639  pa = lwline->points;
640 
641  /* Point to left of ring */
642  pt.x = 20;
643  pt.y = 4;
644  rv = ptarrayarc_contains_point(pa, &pt);
645  CU_ASSERT_EQUAL(rv, LW_OUTSIDE);
646 
647  /*** One-edge ring, closed circle ***/
648  lwline_free(lwline);
649  lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 1 0, -1 0)"));
650  pa = lwline->points;
651 
652  /* Point inside */
653  pt.x = 0;
654  pt.y = 0;
655  rv = ptarrayarc_contains_point(pa, &pt);
656  CU_ASSERT_EQUAL(rv, LW_INSIDE);
657 
658  /* Point outside */
659  pt.x = 0;
660  pt.y = 2;
661  rv = ptarrayarc_contains_point(pa, &pt);
662  CU_ASSERT_EQUAL(rv, LW_OUTSIDE);
663 
664  /* Point on boundary */
665  pt.x = 0;
666  pt.y = 1;
667  rv = ptarrayarc_contains_point(pa, &pt);
668  CU_ASSERT_EQUAL(rv, LW_BOUNDARY);
669 
670  /*** Overshort ring ***/
671  lwline_free(lwline);
672  lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 1 0)"));
673  pa = lwline->points;
675  rv = ptarrayarc_contains_point(pa, &pt);
676  //printf("%s\n", cu_error_msg);
677  CU_ASSERT_STRING_EQUAL("ptarrayarc_contains_point called with even number of points", cu_error_msg);
678 
679  /*** Unclosed ring ***/
680  lwline_free(lwline);
681  lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 1 0, 2 0)"));
682  pa = lwline->points;
684  rv = ptarrayarc_contains_point(pa, &pt);
685  CU_ASSERT_STRING_EQUAL("ptarrayarc_contains_point called on unclosed ring", cu_error_msg);
686 
687  lwline_free(lwline);
688 }
689 
690 
691 /*
692 ** Used by the test harness to register the tests in this file.
693 */
694 void ptarray_suite_setup(void);
696 {
697  CU_pSuite suite = CU_add_suite("Point Array", NULL, NULL);
707 }
double x
Definition: liblwgeom.h:308
double m
Definition: liblwgeom.h:308
int ptarray_isccw(const POINTARRAY *pa)
Definition: ptarray.c:990
char * r
Definition: cu_in_wkt.c:25
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:655
LWGEOM * lwgeom_desegmentize(LWGEOM *geom)
Definition: lwsegmentize.c:841
void lwfree(void *mem)
Definition: lwutil.c:190
Datum area(PG_FUNCTION_ARGS)
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1006
int ptarrayarc_contains_point(const POINTARRAY *pa, const POINT2D *pt)
For POINTARRAYs representing CIRCULARSTRINGS.
Definition: ptarray.c:796
#define LW_SUCCESS
Definition: liblwgeom.h:55
void lwline_free(LWLINE *line)
Definition: lwline.c:63
static void test_ptarray_isccw(void)
Definition: cu_ptarray.c:275
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:125
static void test_ptarray_append_ptarray(void)
Definition: cu_ptarray.c:105
void ptarray_suite_setup(void)
Definition: cu_ptarray.c:695
static void test_ptarray_desegmentize()
Definition: cu_ptarray.c:346
double ptarray_signed_area(const POINTARRAY *pa)
Returns the area in cartesian units.
Definition: ptarray.c:959
static void test_ptarray_insert_point(void)
Definition: cu_ptarray.c:60
LWGEOM * lwgeom_segmentize(LWGEOM *geom, uint32_t perQuad)
Definition: lwsegmentize.c:446
#define LW_FAILURE
Definition: liblwgeom.h:54
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:1706
double x
Definition: liblwgeom.h:284
double ptarray_locate_point(const POINTARRAY *pa, const POINT4D *pt, double *dist, POINT4D *p_located)
Definition: ptarray.c:1267
static LWGEOM * lwgeom_from_text(const char *str)
Definition: cu_ptarray.c:25
POINT4D getPoint4d(const POINTARRAY *pa, int n)
Definition: lwgeom_api.c:202
#define WKT_ISO
Definition: liblwgeom.h:1776
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:249
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_TRUE, then a duplicate point will not be added.
Definition: ptarray.c:141
#define LW_FALSE
Definition: liblwgeom.h:52
uint8_t flags
Definition: liblwgeom.h:325
int lwgeom_parse_wkt(LWGEOM_PARSER_RESULT *parser_result, char *wktstr, int parse_flags)
Parse a WKT geometry string into an LWGEOM structure.
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:79
void cu_error_msg_reset()
static char * lwgeom_to_text(const LWGEOM *geom)
Definition: cu_ptarray.c:33
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:51
Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM...
Definition: liblwgeom.h:1713
#define PG_ADD_TEST(suite, testfunc)
int ptarray_append_ptarray(POINTARRAY *pa1, POINTARRAY *pa2, double gap_tolerance)
Append a POINTARRAY, pa2 to the end of an existing POINTARRAY, pa1.
Definition: ptarray.c:172
POINTARRAY ** rings
Definition: liblwgeom.h:413
#define LW_INSIDE
Constants for point-in-polygon return values.
double y
Definition: liblwgeom.h:284
int ptarray_insert_point(POINTARRAY *pa, const POINT4D *p, int where)
Insert a point into an existing POINTARRAY.
Definition: ptarray.c:84
static void test_ptarray_locate_point(void)
Definition: cu_ptarray.c:218
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:89
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:753
static void test_ptarrayarc_contains_point()
Definition: cu_ptarray.c:552
#define LW_BOUNDARY
static void test_ptarray_contains_point()
Definition: cu_ptarray.c:463
int ptarray_contains_point(const POINTARRAY *pa, const POINT2D *pt)
Return 1 if the point is inside the POINTARRAY, -1 if it is outside, and 0 if it is on the boundary...
Definition: ptarray.c:697
#define LW_OUTSIDE
double y
Definition: liblwgeom.h:308
char cu_error_msg[MAX_CUNIT_ERROR_LENGTH+1]
static void test_ptarray_append_point(void)
Definition: cu_ptarray.c:38
static void test_ptarray_signed_area()
Definition: cu_ptarray.c:318
#define FLAGS_SET_READONLY(flags, value)
Definition: liblwgeom.h:116
POINTARRAY * points
Definition: liblwgeom.h:378