PostGIS  3.0.6dev-r@@SVN_REVISION@@
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 
29 struct LISTNODE
30 {
31  struct LISTNODE* next;
32  void* item;
33 };
34 typedef 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  */
45 {
48  uint32_t i;
50 };
51 
52 static LISTNODE*
53 prepend_node(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 
62 static LISTNODE*
64 {
65  LISTNODE* next = i->next;
66  lwfree(i);
67  return next;
68 }
69 
70 static 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 
83 static 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 
117 static 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  LWGEOM* g = lwcollection_getsubgeom(c, i);
134 
136  }
137 }
138 
142 static void
144 {
145  while(s->geoms && lwgeom_is_collection(s->geoms->item))
146  {
148  }
149 }
150 
151 static 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  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 
192 int
194 {
196  return LW_FAILURE;
197 
198  return getPoint4d_p(s->pointarrays->item, s->i, p);
199 }
200 
201 int
203 {
204  if (s->pointarrays && s->i < ((POINTARRAY*) s->pointarrays->item)->npoints)
205  return LW_TRUE;
206  return LW_FALSE;
207 }
208 
209 int
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 
223 int
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  ptarray_set_point4d(s->pointarrays->item, s->i, p);
236 
238  return LW_SUCCESS;
239 }
240 
243 {
246 
247  return it;
248 }
249 
252 {
253  LWPOINTITERATOR* it = lwalloc(sizeof(LWPOINTITERATOR));
254 
255  it->geoms = NULL;
256  it->pointarrays = NULL;
257  it->i = 0;
259 
260  add_lwgeom_to_stack(it, g);
262 
263  return it;
264 }
265 
266 void
268 {
269  while (s->geoms != NULL)
270  {
271  s->geoms = pop_node(s->geoms);
272  }
273 
274  while (s->pointarrays != NULL)
275  {
276  s->pointarrays = pop_node(s->pointarrays);
277  }
278 
279  lwfree(s);
280 }
char * s
Definition: cu_in_wkt.c:23
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:161
#define LW_FALSE
Definition: liblwgeom.h:108
#define LW_FAILURE
Definition: liblwgeom.h:110
#define LINETYPE
Definition: liblwgeom.h:117
LWGEOM * lwcollection_getsubgeom(LWCOLLECTION *col, int gnum)
Definition: lwcollection.c:114
#define LW_SUCCESS
Definition: liblwgeom.h:111
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:116
LWTRIANGLE * lwgeom_as_lwtriangle(const LWGEOM *lwgeom)
Definition: lwgeom.c:206
void lwfree(void *mem)
Definition: lwutil.c:242
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1079
#define POLYGONTYPE
Definition: liblwgeom.h:118
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:123
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:216
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:125
#define TRIANGLETYPE
Definition: liblwgeom.h:129
void * lwalloc(size_t size)
Definition: lwutil.c:227
LWCIRCSTRING * lwgeom_as_lwcircstring(const LWGEOM *lwgeom)
Definition: lwgeom.c:170
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:107
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:197
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
Definition: lwgeom_api.c:376
This library is the generic geometry handling section of PostGIS.
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwinline.h:135
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:193
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition: lwinline.h:121
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
static int add_lwgeom_to_stack(LWPOINTITERATOR *s, LWGEOM *g)
Definition: lwiterator.c:71
LWPOINTITERATOR * lwpointiterator_create(const LWGEOM *g)
Create a new LWPOINTITERATOR over supplied LWGEOM*.
Definition: lwiterator.c:242
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
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:267
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
LWPOINTITERATOR * lwpointiterator_create_rw(LWGEOM *g)
Create a new LWPOINTITERATOR over supplied LWGEOM* Supports modification of coordinates during iterat...
Definition: lwiterator.c:251
static LISTNODE * extract_pointarrays_from_lwgeom(LWGEOM *g)
Return a pointer to the first of one or more LISTNODEs holding the POINTARRAYs of a geometry.
Definition: lwiterator.c:84
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 * pop_node(LISTNODE *i)
Definition: lwiterator.c:63
static LISTNODE * prepend_node(void *g, LISTNODE *front)
Definition: lwiterator.c:53
struct LISTNODE * next
Definition: lwiterator.c:31
void * item
Definition: lwiterator.c:32
uint32_t ngeoms
Definition: liblwgeom.h:566
uint8_t type
Definition: liblwgeom.h:448
LISTNODE * pointarrays
Definition: lwiterator.c:47
LISTNODE * geoms
Definition: lwiterator.c:46
uint32_t i
Definition: lwiterator.c:48
char allow_modification
Definition: lwiterator.c:49
POINTARRAY ** rings
Definition: liblwgeom.h:505
uint32_t nrings
Definition: liblwgeom.h:510