PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwiterator.c
Go to the documentation of this file.
1/**********************************************************************
2 *
3 * PostGIS - Spatial Types for PostgreSQL
4 * http://postgis.net
5 *
6 * PostGIS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * PostGIS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **********************************************************************
20 *
21 * Copyright 2015 Daniel Baston <dbaston@gmail.com>
22 *
23 **********************************************************************/
24
25
26#include "liblwgeom.h"
27#include "lwgeom_log.h"
28
30{
31 struct LISTNODE* next;
32 const void* item;
33};
34typedef struct LISTNODE LISTNODE;
35
36/* The LWPOINTITERATOR consists of two stacks of items to process: a stack
37 * of geometries, and a stack of POINTARRAYs extracted from those geometries.
38 * The index "i" refers to the "next" point, which is found at the top of the
39 * pointarrays stack.
40 *
41 * When the pointarrays stack is depleted, we pull a geometry from the geometry
42 * stack to replenish it.
43 */
51
52static LISTNODE*
53prepend_node(const void* g, LISTNODE* front)
54{
55 LISTNODE* n = lwalloc(sizeof(LISTNODE));
56 n->item = g;
57 n->next = front;
58
59 return n;
60}
61
62static LISTNODE*
64{
65 LISTNODE* next = i->next;
66 lwfree(i);
67 return next;
68}
69
70static int
72{
73 if (lwgeom_is_empty(g))
74 return LW_FAILURE;
75
76 s->geoms = prepend_node(g, s->geoms);
77 return LW_SUCCESS;
78}
79
83static LISTNODE*
85{
86 switch(lwgeom_get_type(g))
87 {
88 case POINTTYPE:
89 return prepend_node(lwgeom_as_lwpoint(g)->point, NULL);
90 case LINETYPE:
91 return prepend_node(lwgeom_as_lwline(g)->points, NULL);
92 case TRIANGLETYPE:
93 return prepend_node(lwgeom_as_lwtriangle(g)->points, NULL);
94 case CIRCSTRINGTYPE:
95 return prepend_node(lwgeom_as_lwcircstring(g)->points, NULL);
96 case POLYGONTYPE:
97 {
98 LISTNODE* n = NULL;
99
100 LWPOLY* p = lwgeom_as_lwpoly(g);
101 int i;
102 for (i = p->nrings - 1; i >= 0; i--)
103 n = prepend_node(p->rings[i], n);
104
105 return n;
106 }
107 default:
108 lwerror("%s: Unsupported geometry type: %s", __func__, lwtype_name(g->type));
109 }
110
111 return NULL;
112}
113
117static void
119{
120 int i;
121 LWCOLLECTION* c;
122
123 if (!s->geoms)
124 {
125 return;
126 }
127
128 c = (LWCOLLECTION*) s->geoms->item;
129 s->geoms = pop_node(s->geoms);
130
131 for (i = c->ngeoms - 1; i >= 0; i--)
132 {
133 const LWGEOM* g = lwcollection_getsubgeom(c, i);
134
136 }
137}
138
142static void
144{
145 while(s->geoms && lwgeom_is_collection(s->geoms->item))
146 {
148 }
149}
150
151static int
153{
154 s->i += 1;
155
156 /* We've reached the end of our current POINTARRAY. Try to see if there
157 * are any more POINTARRAYS on the stack. */
158 if (s->pointarrays && s->i >= ((POINTARRAY*) s->pointarrays->item)->npoints)
159 {
160 s->pointarrays = pop_node(s->pointarrays);
161 s->i = 0;
162 }
163
164 /* We don't have a current POINTARRAY. Pull a geometry from the stack, and
165 * decompose it into its POINTARRARYs. */
166 if (!s->pointarrays)
167 {
168 const LWGEOM* g;
170
171 if (!s->geoms)
172 {
173 return LW_FAILURE;
174 }
175
176 s->i = 0;
177 g = s->geoms->item;
178 s->pointarrays = extract_pointarrays_from_lwgeom(g);
179
180 s->geoms = pop_node(s->geoms);
181 }
182
183 if (!s->pointarrays)
184 {
185 return LW_FAILURE;
186 }
187 return LW_SUCCESS;
188}
189
190/* Public API implementation */
191
192int
194{
196 return LW_FAILURE;
197
198 return getPoint4d_p(s->pointarrays->item, s->i, p);
199}
200
201int
203{
204 if (s->pointarrays && s->i < ((POINTARRAY*) s->pointarrays->item)->npoints)
205 return LW_TRUE;
206 return LW_FALSE;
207}
208
209int
211{
213 return LW_FAILURE;
214
215 /* If p is NULL, just advance without reading */
216 if (p && !lwpointiterator_peek(s, p))
217 return LW_FAILURE;
218
220 return LW_SUCCESS;
221}
222
223int
225{
227 return LW_FAILURE;
228
229 if (!s->allow_modification)
230 {
231 lwerror("Cannot write to read-only iterator");
232 return LW_FAILURE;
233 }
234
235 POINTARRAY *pa = (POINTARRAY *)(s->pointarrays->item);
236 ptarray_set_point4d(pa, s->i, p);
237
239 return LW_SUCCESS;
240}
241
244{
247
248 return it;
249}
250
253{
255
256 it->geoms = NULL;
257 it->pointarrays = NULL;
258 it->i = 0;
260
261 add_lwgeom_to_stack(it, g);
263
264 return it;
265}
266
267void
269{
270 while (s->geoms != NULL)
271 {
272 s->geoms = pop_node(s->geoms);
273 }
274
275 while (s->pointarrays != NULL)
276 {
277 s->pointarrays = pop_node(s->pointarrays);
278 }
279
280 lwfree(s);
281}
char * s
Definition cu_in_wkt.c:23
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
#define LW_FALSE
Definition liblwgeom.h:94
#define LW_FAILURE
Definition liblwgeom.h:96
#define LINETYPE
Definition liblwgeom.h:103
#define LW_SUCCESS
Definition liblwgeom.h:97
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
void * lwalloc(size_t size)
Definition lwutil.c:227
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition lwgeom.c:243
void lwfree(void *mem)
Definition lwutil.c:248
LWTRIANGLE * lwgeom_as_lwtriangle(const LWGEOM *lwgeom)
Definition lwgeom.c:252
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM contains sub-geometries or not This basically just checks that the struct ...
Definition lwgeom.c:1125
#define POLYGONTYPE
Definition liblwgeom.h:104
const LWGEOM * lwcollection_getsubgeom(LWCOLLECTION *col, uint32_t gnum)
LWCIRCSTRING * lwgeom_as_lwcircstring(const LWGEOM *lwgeom)
Definition lwgeom.c:216
#define CIRCSTRINGTYPE
Definition liblwgeom.h:109
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition lwgeom_api.c:125
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition lwgeom.c:207
#define TRIANGLETYPE
Definition liblwgeom.h:115
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
Definition lwgeom_api.c:369
This library is the generic geometry handling section of PostGIS.
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition lwinline.h:141
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition lwinline.h:127
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition lwinline.h:199
static int add_lwgeom_to_stack(LWPOINTITERATOR *s, const LWGEOM *g)
Definition lwiterator.c:71
static void unroll_collection(LWPOINTITERATOR *s)
Remove an LWCOLLECTION from the iterator stack, and add the components of the LWCOLLECTIONs to the st...
Definition lwiterator.c:118
LWPOINTITERATOR * lwpointiterator_create(const LWGEOM *g)
Create a new LWPOINTITERATOR over supplied LWGEOM*.
Definition lwiterator.c:243
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:210
static int lwpointiterator_advance(LWPOINTITERATOR *s)
Definition lwiterator.c:152
LWPOINTITERATOR * lwpointiterator_create_rw(LWGEOM *g)
Create a new LWPOINTITERATOR over supplied LWGEOM* Supports modification of coordinates during iterat...
Definition lwiterator.c:252
static LISTNODE * prepend_node(const void *g, LISTNODE *front)
Definition lwiterator.c:53
int lwpointiterator_peek(LWPOINTITERATOR *s, POINT4D *p)
Attempts to assigns the next point in the iterator to p.
Definition lwiterator.c:193
void lwpointiterator_destroy(LWPOINTITERATOR *s)
Free all memory associated with the iterator.
Definition lwiterator.c:268
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:224
int lwpointiterator_has_next(LWPOINTITERATOR *s)
Returns LW_TRUE if there is another point available in the iterator.
Definition lwiterator.c:202
static void unroll_collections(LWPOINTITERATOR *s)
Unroll LWCOLLECTIONs from the top of the stack, as necessary, until the element at the top of the sta...
Definition lwiterator.c:143
static LISTNODE * extract_pointarrays_from_lwgeom(const LWGEOM *g)
Return a pointer to the first of one or more LISTNODEs holding the POINTARRAYs of a geometry.
Definition lwiterator.c:84
static LISTNODE * pop_node(LISTNODE *i)
Definition lwiterator.c:63
struct LISTNODE * next
Definition lwiterator.c:31
const void * item
Definition lwiterator.c:32
uint32_t ngeoms
Definition liblwgeom.h:580
LWGEOM ** geoms
Definition liblwgeom.h:575
uint8_t type
Definition liblwgeom.h:462
LISTNODE * pointarrays
Definition lwiterator.c:47
LISTNODE * geoms
Definition lwiterator.c:46
char allow_modification
Definition lwiterator.c:49
POINTARRAY ** rings
Definition liblwgeom.h:519
uint32_t nrings
Definition liblwgeom.h:524