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