PostGIS  2.5.0dev-r@@SVN_REVISION@@
cu_iterator.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  * Copyright 2015 Daniel Baston
6  *
7  * This is free software; you can redistribute and/or modify it under
8  * the terms of the GNU General Public Licence. See the COPYING file.
9  *
10  **********************************************************************/
11 
12 #include "CUnit/Basic.h"
13 #include "cu_tester.h"
14 
15 #include "../liblwgeom_internal.h"
16 
17 char* inputs[] =
18 {
19  "POINT (17 253)",
20  "POINT Z (17 253 018)",
21  "TRIANGLE ((0 0, 10 0, 10 10, 0 0))",
22  "LINESTRING (17 253, -44 28, 33 11, 26 44)",
23  "LINESTRING M (17 253 0, -44 28 1, 33 11 2, 26 44 3)",
24  "POLYGON((26426 65078,26531 65242,26075 65136,26096 65427,26426 65078))",
25  "MULTIPOINT ((1 1), (1 1))",
26  "MULTILINESTRING Z ((1 1 0, 2 2 0), (3 3 1, 4 4 1))",
27  "MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1)), ((20 20, 20 30, 30 30, 20 20)))",
28  "POINT EMPTY",
29  "LINESTRING M EMPTY",
30  "POLYGON Z EMPTY",
31  "GEOMETRYCOLLECTION EMPTY",
32  "GEOMETRYCOLLECTION (MULTIPOINT ((14 80), (22 12)))",
33  "GEOMETRYCOLLECTION (POINT (3 7), LINESTRING (0 0, 14 3), GEOMETRYCOLLECTION(POINT (2 8)))",
34  "GEOMETRYCOLLECTION (POINT (3 7), GEOMETRYCOLLECTION(MULTIPOINT ((2 8))))",
35  "GEOMETRYCOLLECTION (POINT (3 7), GEOMETRYCOLLECTION(LINESTRING (2 8, 4 3), POLYGON EMPTY, MULTIPOINT ((2 8), (17 3), EMPTY)))",
36  "CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3)",
37  "COMPOUNDCURVE(CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3),(4 3, 4 5, 1 4, 0 0))",
38  "MULTICURVE((0 0, 5 5),CIRCULARSTRING(4 0, 4 4, 8 4))",
39  "CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3),(4 3, 4 5, 1 4, 0 0)), LINESTRING (0.1 0.1, 0.3 0.1, 0.3 0.3, 0.1 0.1) )",
40  "MULTISURFACE(CURVEPOLYGON(CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0),(1 1, 3 3, 3 1, 1 1)),((10 10, 14 12, 11 10, 10 10),(11 11, 11.5 11, 11 11.5, 11 11)))",
41  "POLYHEDRALSURFACE( ((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)), ((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)), ((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)), ((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) )",
42  "TIN(((80 130,50 160,80 70,80 130)),((50 160,10 190,10 70,50 160)), ((80 70,50 160,10 70,80 70)),((120 160,120 190,50 160,120 160)), ((120 190,10 190,50 160,120 190)))"
43 };
44 
45 static uint32_t
47 {
48  POINT4D p;
49  uint32_t count = 0;
51 
52  while (lwpointiterator_has_next(it))
53  {
54  CU_ASSERT_TRUE(lwpointiterator_next(it, &p));
55  count++;
56  }
57 
59 
60  return count;
61 }
62 
63 static void
65 {
66  char* types_visited = lwalloc(NUMTYPES * sizeof(char));
67  memset(types_visited, LW_FALSE, NUMTYPES * sizeof(char));
68 
69  uint32_t i;
70  for (i = 0; i < sizeof(inputs)/sizeof(char*); i++)
71  {
73  types_visited[lwgeom_get_type(input)] = LW_TRUE;
74 
75  uint32_t itercount = count_points_using_iterator(input);
76 
77  CU_ASSERT_EQUAL(lwgeom_count_vertices(input), itercount);
78 
79  lwgeom_free(input);
80  }
81 
82  /* Assert that every valid LWGEOM type has been tested */
83  for (i = 1; i < NUMTYPES; i++)
84  {
85  CU_ASSERT_TRUE(types_visited[i]);
86  }
87 
88  lwfree(types_visited);
89 }
90 
91 static void
93 {
96 
97  POINT4D p;
98  p.x = 3.2;
99  p.y = 4.8;
100 
101  CU_ASSERT_EQUAL(LW_FAILURE, lwpointiterator_modify_next(it, &p));
102 
103  lwgeom_free(input);
105 }
106 
107 static void
109 {
110  uint32_t i;
111  uint32_t j = 0;
112 
113  for (i = 0; i < sizeof(inputs)/sizeof(char*); i++)
114  {
118 
119  while (lwpointiterator_has_next(it1))
120  {
121  /* Make up a coordinate, assign it to the next spot in it1,
122  * read it from it2 to verify that it was assigned correctly. */
123  POINT4D p1, p2;
124  p1.x = sqrt(j++);
125  p1.y = sqrt(j++);
126  p1.z = sqrt(j++);
127  p1.m = sqrt(j++);
128 
129  CU_ASSERT_TRUE(lwpointiterator_modify_next(it1, &p1));
130  CU_ASSERT_TRUE(lwpointiterator_next(it2, &p2));
131 
132  CU_ASSERT_EQUAL(p1.x, p2.x);
133  CU_ASSERT_EQUAL(p1.y, p2.y);
134 
135  if (lwgeom_has_z(input))
136  CU_ASSERT_EQUAL(p1.z, p2.z);
137 
138  if (lwgeom_has_m(input))
139  CU_ASSERT_EQUAL(p1.m, p2.m);
140  }
141 
142  lwgeom_free(input);
143 
146  }
147 }
148 
149 static void
151 {
152  LWGEOM* g = lwgeom_from_wkt("GEOMETRYCOLLECTION (POINT (3 7), GEOMETRYCOLLECTION(LINESTRING (2 8, 4 3), POLYGON EMPTY, MULTIPOINT ((2 8), (17 3), EMPTY)))", LW_PARSER_CHECK_NONE);
153 
155  lwpointiterator_next(it, NULL);
156  lwpointiterator_next(it, NULL);
157 
159  lwgeom_free(g);
160 }
161 
162 static void
164 {
165  uint32_t i = 0;
166  LWGEOM* g = lwgeom_from_wkt("GEOMETRYCOLLECTION (POINT (3 7), GEOMETRYCOLLECTION(LINESTRING (2 8, 4 3), POLYGON EMPTY, MULTIPOINT ((2 8), (17 3), EMPTY)))", LW_PARSER_CHECK_NONE);
169 
170  /* Flip the coordinates of the 3rd point */
171  while(lwpointiterator_has_next(it1))
172  {
173  if (i == 2)
174  {
175  POINT4D p;
176  double tmp;
177 
178  lwpointiterator_peek(it1, &p);
179  tmp = p.x;
180  p.x = p.y;
181  p.y = tmp;
182 
184  }
185  else
186  {
187  lwpointiterator_next(it1, NULL);
188  }
189  i++;
190  }
191  CU_ASSERT_EQUAL(5, i); /* Every point was visited */
193 
194  /* Verify that the points are as expected */
195  POINT2D points[] =
196  {
197  { .x = 3, .y = 7 },
198  { .x = 2, .y = 8 },
199  { .x = 3, .y = 4 },
200  { .x = 2, .y = 8 },
201  { .x = 17, .y = 3}
202  };
203 
204  for (i = 0; lwpointiterator_has_next(it2); i++)
205  {
206  POINT4D p;
207 
208  lwpointiterator_next(it2, &p);
209 
210  CU_ASSERT_EQUAL(p.x, points[i].x);
211  CU_ASSERT_EQUAL(p.y, points[i].y);
212  }
213 
215  lwgeom_free(g);
216 }
217 
218 static void
220 {
221  uint32_t i = 0;
222  LWGEOM* g = lwgeom_from_wkt("GEOMETRYCOLLECTION (POLYGON ((0 0, 0 10, 10 10, 0 10, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1)), MULTIPOINT((4 4), (3 3)))", LW_PARSER_CHECK_NONE);
223 
224  POINT2D points[] = { {.x = 0, .y = 0},
225  {.x = 0, .y = 10},
226  {.x = 10, .y = 10},
227  {.x = 0, .y = 10},
228  {.x = 0, .y = 0},
229  {.x = 1, .y = 1},
230  {.x = 1, .y = 2},
231  {.x = 2, .y = 2},
232  {.x = 2, .y = 1},
233  {.x = 1, .y = 1},
234  {.x = 4, .y = 4},
235  {.x = 3, .y = 3}
236  };
237 
239  POINT4D p;
240 
241  for (i = 0; lwpointiterator_has_next(it); i++)
242  {
243  CU_ASSERT_EQUAL(LW_SUCCESS, lwpointiterator_next(it, &p));
244  CU_ASSERT_EQUAL(p.x, points[i].x);
245  CU_ASSERT_EQUAL(p.y, points[i].y);
246  }
247 
249  lwgeom_free(g);
250 }
251 
252 /*
253 ** Used by test harness to register the tests in this file.
254 */
255 void iterator_suite_setup(void);
257 {
258  CU_pSuite suite = CU_add_suite("iterator", NULL, NULL);
260  PG_ADD_TEST(suite, test_ordering);
265 }
double x
Definition: liblwgeom.h:351
double m
Definition: liblwgeom.h:351
int lwpointiterator_next(LWPOINTITERATOR *s, POINT4D *p)
Attempts to assign the next point in the iterator to p, and advances the iterator to the next point...
Definition: lwiterator.c:212
int lwpointiterator_modify_next(LWPOINTITERATOR *s, const POINT4D *p)
Attempts to replace the next point int the iterator with p, and advances the iterator to the next poi...
Definition: lwiterator.c:226
void lwfree(void *mem)
Definition: lwutil.c:244
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwgeom.c:916
static void test_cannot_modify_read_only(void)
Definition: cu_iterator.c:92
static uint32_t count_points_using_iterator(LWGEOM *g)
Definition: cu_iterator.c:46
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1137
#define LW_SUCCESS
Definition: liblwgeom.h:79
LWPOINTITERATOR * lwpointiterator_create_rw(LWGEOM *g)
Create a new LWPOINTITERATOR over supplied LWGEOM* Supports modification of coordinates during iterat...
Definition: lwiterator.c:253
LWGEOM * lwgeom_from_wkt(const char *wkt, const char check)
Definition: lwin_wkt.c:904
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:923
LWPOINTITERATOR * lwpointiterator_create(const LWGEOM *g)
Create a new LWPOINTITERATOR over supplied LWGEOM*.
Definition: lwiterator.c:244
#define LW_FAILURE
Definition: liblwgeom.h:78
unsigned int uint32_t
Definition: uthash.h:78
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:1998
double x
Definition: liblwgeom.h:327
int lwpointiterator_has_next(LWPOINTITERATOR *s)
Returns LW_TRUE if there is another point available in the iterator.
Definition: lwiterator.c:204
void lwpointiterator_destroy(LWPOINTITERATOR *s)
Free all memory associated with the iterator.
Definition: lwiterator.c:269
#define LW_FALSE
Definition: liblwgeom.h:76
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:75
static void test_ordering(void)
Definition: cu_iterator.c:219
#define PG_ADD_TEST(suite, testfunc)
int count
Definition: genraster.py:56
#define NUMTYPES
Definition: liblwgeom.h:100
double y
Definition: liblwgeom.h:327
char * inputs[]
Definition: cu_iterator.c:17
static void test_modification(void)
Definition: cu_iterator.c:108
double z
Definition: liblwgeom.h:351
uint32_t lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1228
static void test_mixed_rw_access(void)
Definition: cu_iterator.c:163
static void test_no_memory_leaked_when_iterator_is_partially_used(void)
Definition: cu_iterator.c:150
static void test_point_count(void)
Definition: cu_iterator.c:64
void * lwalloc(size_t size)
Definition: lwutil.c:229
double y
Definition: liblwgeom.h:351
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:930
int lwpointiterator_peek(LWPOINTITERATOR *s, POINT4D *p)
Attempts to assigns the next point in the iterator to p.
Definition: lwiterator.c:195
void iterator_suite_setup(void)
Definition: cu_iterator.c:256