PostGIS  2.1.10dev-r@@SVN_REVISION@@
lwin_wkt.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  *
5  * Copyright (C) 2010 Paul Ramsey <pramsey@cleverelephant.ca>
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 <stdlib.h>
13 #include <ctype.h> /* for isspace */
14 
15 #include "lwin_wkt.h"
16 #include "lwin_wkt_parse.h"
17 #include "lwgeom_log.h"
18 
19 
20 /*
21 * Error messages for failures in the parser.
22 */
23 const char *parser_error_messages[] =
24 {
25  "",
26  "geometry requires more points",
27  "geometry must have an odd number of points",
28  "geometry contains non-closed rings",
29  "can not mix dimensionality in a geometry",
30  "parse error - invalid geometry",
31  "invalid WKB type",
32  "incontinuous compound curve",
33  "triangle must have exactly 4 points",
34  "geometry has too many points",
35  "parse error - invalid geometry"
36 };
37 
38 #define SET_PARSER_ERROR(errno) { \
39  global_parser_result.message = parser_error_messages[(errno)]; \
40  global_parser_result.errcode = (errno); \
41  global_parser_result.errlocation = wkt_yylloc.last_column; \
42  }
43 
47 int wkt_lexer_read_srid(char *str)
48 {
49  char *c = str;
50  long i = 0;
51  int srid;
52 
53  if( ! str ) return SRID_UNKNOWN;
54  c += 5; /* Advance past "SRID=" */
55  i = strtol(c, NULL, 10);
56  srid = clamp_srid((int)i);
57  /* TODO: warn on explicit UNKNOWN srid ? */
58  return srid;
59 }
60 
61 static uint8_t wkt_dimensionality(char *dimensionality)
62 {
63  int i = 0;
64  uint8_t flags = 0;
65 
66  if( ! dimensionality )
67  return flags;
68 
69  /* If there's an explicit dimensionality, we use that */
70  for( i = 0; i < strlen(dimensionality); i++ )
71  {
72  if( (dimensionality[i] == 'Z') || (dimensionality[i] == 'z') )
73  FLAGS_SET_Z(flags,1);
74  else if( (dimensionality[i] == 'M') || (dimensionality[i] == 'm') )
75  FLAGS_SET_M(flags,1);
76  /* only a space is accepted in between */
77  else if( ! isspace(dimensionality[i]) ) break;
78  }
79  return flags;
80 }
81 
82 
87 static int wkt_parser_set_dims(LWGEOM *geom, uint8_t flags)
88 {
89  int hasz = FLAGS_GET_Z(flags);
90  int hasm = FLAGS_GET_M(flags);
91  int i = 0;
92 
93  /* Error on junk */
94  if( ! geom )
95  return LW_FAILURE;
96 
97  FLAGS_SET_Z(geom->flags, hasz);
98  FLAGS_SET_M(geom->flags, hasm);
99 
100  if( ! lwgeom_is_empty(geom) )
101  {
102  if( geom->type == POINTTYPE )
103  {
104  LWPOINT *pt = (LWPOINT*)geom;
105  FLAGS_SET_Z(pt->point->flags, hasz);
106  FLAGS_SET_M(pt->point->flags, hasm);
107  return LW_SUCCESS;
108  }
109  else if ( (geom->type == TRIANGLETYPE) ||
110  (geom->type == CIRCSTRINGTYPE) ||
111  (geom->type == LINETYPE) )
112  {
113  LWLINE *ln = (LWLINE*)geom;
114  FLAGS_SET_Z(ln->points->flags, hasz);
115  FLAGS_SET_M(ln->points->flags, hasm);
116  return LW_SUCCESS;
117  }
118  else if ( geom->type == POLYGONTYPE )
119  {
120  LWPOLY *poly = (LWPOLY*)geom;
121  for ( i = 0; i < poly->nrings; i++ )
122  {
123  FLAGS_SET_Z(poly->rings[i]->flags, hasz);
124  FLAGS_SET_M(poly->rings[i]->flags, hasm);
125  }
126  return LW_SUCCESS;
127  }
128  else if ( geom->type == CURVEPOLYTYPE )
129  {
130  LWCURVEPOLY *poly = (LWCURVEPOLY*)geom;
131  for ( i = 0; i < poly->nrings; i++ )
132  wkt_parser_set_dims(poly->rings[i], flags);
133  return LW_SUCCESS;
134  }
135  else if ( lwtype_is_collection(geom->type) )
136  {
137  LWCOLLECTION *col = (LWCOLLECTION*)geom;
138  for ( i = 0; i < col->ngeoms; i++ )
139  wkt_parser_set_dims(col->geoms[i], flags);
140  return LW_SUCCESS;
141  }
142  else
143  {
144  LWDEBUGF(2,"Unknown geometry type: %d", geom->type);
145  return LW_FAILURE;
146  }
147  }
148  return LW_SUCCESS;
149 }
150 
156 static int wkt_pointarray_dimensionality(POINTARRAY *pa, uint8_t flags)
157 {
158  int hasz = FLAGS_GET_Z(flags);
159  int hasm = FLAGS_GET_M(flags);
160  int ndims = 2 + hasz + hasm;
161 
162  /* No dimensionality or array means we go with what we have */
163  if( ! (flags && pa) )
164  return LW_TRUE;
165 
166  LWDEBUGF(5,"dimensionality ndims == %d", ndims);
167  LWDEBUGF(5,"FLAGS_NDIMS(pa->flags) == %d", FLAGS_NDIMS(pa->flags));
168 
169  /*
170  * ndims > 2 implies that the flags have something useful to add,
171  * that there is a 'Z' or an 'M' or both.
172  */
173  if( ndims > 2 )
174  {
175  /* Mismatch implies a problem */
176  if ( FLAGS_NDIMS(pa->flags) != ndims )
177  return LW_FALSE;
178  /* Match means use the explicit dimensionality */
179  else
180  {
181  FLAGS_SET_Z(pa->flags, hasz);
182  FLAGS_SET_M(pa->flags, hasm);
183  }
184  }
185 
186  return LW_TRUE;
187 }
188 
189 
190 
194 POINT wkt_parser_coord_2(double c1, double c2)
195 {
196  POINT p;
197  p.flags = 0;
198  p.x = c1;
199  p.y = c2;
200  p.z = p.m = 0.0;
201  FLAGS_SET_Z(p.flags, 0);
202  FLAGS_SET_M(p.flags, 0);
203  return p;
204 }
205 
210 POINT wkt_parser_coord_3(double c1, double c2, double c3)
211 {
212  POINT p;
213  p.flags = 0;
214  p.x = c1;
215  p.y = c2;
216  p.z = c3;
217  p.m = 0;
218  FLAGS_SET_Z(p.flags, 1);
219  FLAGS_SET_M(p.flags, 0);
220  return p;
221 }
222 
225 POINT wkt_parser_coord_4(double c1, double c2, double c3, double c4)
226 {
227  POINT p;
228  p.flags = 0;
229  p.x = c1;
230  p.y = c2;
231  p.z = c3;
232  p.m = c4;
233  FLAGS_SET_Z(p.flags, 1);
234  FLAGS_SET_M(p.flags, 1);
235  return p;
236 }
237 
239 {
240  POINT4D pt;
241  LWDEBUG(4,"entered");
242 
243  /* Error on trouble */
244  if( ! pa )
245  {
247  return NULL;
248  }
249 
250  /* Check that the coordinate has the same dimesionality as the array */
251  if( FLAGS_NDIMS(p.flags) != FLAGS_NDIMS(pa->flags) )
252  {
253  ptarray_free(pa);
255  return NULL;
256  }
257 
258  /* While parsing the point arrays, XYM and XMZ points are both treated as XYZ */
259  pt.x = p.x;
260  pt.y = p.y;
261  if( FLAGS_GET_Z(pa->flags) )
262  pt.z = p.z;
263  if( FLAGS_GET_M(pa->flags) )
264  pt.m = p.m;
265  /* If the destination is XYM, we'll write the third coordinate to m */
266  if( FLAGS_GET_M(pa->flags) && ! FLAGS_GET_Z(pa->flags) )
267  pt.m = p.z;
268 
269  ptarray_append_point(pa, &pt, LW_TRUE); /* Allow duplicate points in array */
270  return pa;
271 }
272 
277 {
278  int ndims = FLAGS_NDIMS(p.flags);
279  POINTARRAY *pa = ptarray_construct_empty((ndims>2), (ndims>3), 4);
280  LWDEBUG(4,"entered");
281  if ( ! pa )
282  {
284  return NULL;
285  }
286  return wkt_parser_ptarray_add_coord(pa, p);
287 }
288 
293 LWGEOM* wkt_parser_point_new(POINTARRAY *pa, char *dimensionality)
294 {
295  uint8_t flags = wkt_dimensionality(dimensionality);
296  LWDEBUG(4,"entered");
297 
298  /* No pointarray means it is empty */
299  if( ! pa )
301 
302  /* If the number of dimensions is not consistent, we have a problem. */
303  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
304  {
305  ptarray_free(pa);
307  return NULL;
308  }
309 
310  /* Only one point allowed in our point array! */
311  if( pa->npoints != 1 )
312  {
313  ptarray_free(pa);
315  return NULL;
316  }
317 
319 }
320 
321 
327 LWGEOM* wkt_parser_linestring_new(POINTARRAY *pa, char *dimensionality)
328 {
329  uint8_t flags = wkt_dimensionality(dimensionality);
330  LWDEBUG(4,"entered");
331 
332  /* No pointarray means it is empty */
333  if( ! pa )
335 
336  /* If the number of dimensions is not consistent, we have a problem. */
337  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
338  {
339  ptarray_free(pa);
341  return NULL;
342  }
343 
344  /* Apply check for not enough points, if requested. */
346  {
347  ptarray_free(pa);
349  return NULL;
350  }
351 
353 }
354 
362 {
363  uint8_t flags = wkt_dimensionality(dimensionality);
364  LWDEBUG(4,"entered");
365 
366  /* No pointarray means it is empty */
367  if( ! pa )
369 
370  /* If the number of dimensions is not consistent, we have a problem. */
371  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
372  {
373  ptarray_free(pa);
375  return NULL;
376  }
377 
378  /* Apply check for not enough points, if requested. */
380  {
381  ptarray_free(pa);
383  return NULL;
384  }
385 
386  /* Apply check for odd number of points, if requested. */
388  {
389  ptarray_free(pa);
391  return NULL;
392  }
393 
395 }
396 
397 LWGEOM* wkt_parser_triangle_new(POINTARRAY *pa, char *dimensionality)
398 {
399  uint8_t flags = wkt_dimensionality(dimensionality);
400  LWDEBUG(4,"entered");
401 
402  /* No pointarray means it is empty */
403  if( ! pa )
405 
406  /* If the number of dimensions is not consistent, we have a problem. */
407  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
408  {
409  ptarray_free(pa);
411  return NULL;
412  }
413 
414  /* Triangles need four points. */
415  if( (pa->npoints != 4) )
416  {
417  ptarray_free(pa);
419  return NULL;
420  }
421 
422  /* Triangles need closure. */
423  if( ! ptarray_is_closed(pa) )
424  {
425  ptarray_free(pa);
427  return NULL;
428  }
429 
431 }
432 
434 {
435  LWPOLY *poly = NULL;
436  LWDEBUG(4,"entered");
437 
438  /* No pointarray is a problem */
439  if( ! pa )
440  {
442  return NULL;
443  }
444 
446 
447  /* Error out if we can't build this polygon. */
448  if( ! poly )
449  {
451  return NULL;
452  }
453 
454  wkt_parser_polygon_add_ring(lwpoly_as_lwgeom(poly), pa, dimcheck);
455  return lwpoly_as_lwgeom(poly);
456 }
457 
459 {
460  LWDEBUG(4,"entered");
461 
462  /* Bad inputs are a problem */
463  if( ! (pa && poly) )
464  {
466  return NULL;
467  }
468 
469  /* Rings must agree on dimensionality */
470  if( FLAGS_NDIMS(poly->flags) != FLAGS_NDIMS(pa->flags) )
471  {
472  ptarray_free(pa);
473  lwgeom_free(poly);
475  return NULL;
476  }
477 
478  /* Apply check for minimum number of points, if requested. */
480  {
481  ptarray_free(pa);
482  lwgeom_free(poly);
484  return NULL;
485  }
486 
487  /* Apply check for not closed rings, if requested. */
489  ! (dimcheck == 'Z' ? ptarray_is_closed_z(pa) : ptarray_is_closed_2d(pa)) )
490  {
491  ptarray_free(pa);
492  lwgeom_free(poly);
494  return NULL;
495  }
496 
497  /* If something goes wrong adding a ring, error out. */
498  if ( LW_FAILURE == lwpoly_add_ring(lwgeom_as_lwpoly(poly), pa) )
499  {
500  ptarray_free(pa);
501  lwgeom_free(poly);
503  return NULL;
504  }
505  return poly;
506 }
507 
508 LWGEOM* wkt_parser_polygon_finalize(LWGEOM *poly, char *dimensionality)
509 {
510  uint8_t flags = wkt_dimensionality(dimensionality);
511  int flagdims = FLAGS_NDIMS(flags);
512  LWDEBUG(4,"entered");
513 
514  /* Null input implies empty return */
515  if( ! poly )
517 
518  /* If the number of dimensions are not consistent, we have a problem. */
519  if( flagdims > 2 )
520  {
521  if ( flagdims != FLAGS_NDIMS(poly->flags) )
522  {
523  lwgeom_free(poly);
525  return NULL;
526  }
527 
528  /* Harmonize the flags in the sub-components with the wkt flags */
529  if( LW_FAILURE == wkt_parser_set_dims(poly, flags) )
530  {
531  lwgeom_free(poly);
533  return NULL;
534  }
535  }
536 
537  return poly;
538 }
539 
541 {
542  LWGEOM *poly;
543  LWDEBUG(4,"entered");
544 
545  /* Toss error on null geometry input */
546  if( ! ring )
547  {
549  return NULL;
550  }
551 
552  /* Construct poly and add the ring. */
554  /* Return the result. */
555  return wkt_parser_curvepolygon_add_ring(poly,ring);
556 }
557 
559 {
560  LWDEBUG(4,"entered");
561 
562  /* Toss error on null input */
563  if( ! (ring && poly) )
564  {
566  LWDEBUG(4,"inputs are null");
567  return NULL;
568  }
569 
570  /* All the elements must agree on dimensionality */
571  if( FLAGS_NDIMS(poly->flags) != FLAGS_NDIMS(ring->flags) )
572  {
573  LWDEBUG(4,"dimensionality does not match");
574  lwgeom_free(ring);
575  lwgeom_free(poly);
577  return NULL;
578  }
579 
580  /* Apply check for minimum number of points, if requested. */
582  {
583  int vertices_needed = 3;
584 
585  if ( ring->type == LINETYPE )
586  vertices_needed = 4;
587 
588  if (lwgeom_count_vertices(ring) < vertices_needed)
589  {
590  LWDEBUG(4,"number of points is incorrect");
591  lwgeom_free(ring);
592  lwgeom_free(poly);
594  return NULL;
595  }
596  }
597 
598  /* Apply check for not closed rings, if requested. */
600  {
601  int is_closed = 1;
602  LWDEBUG(4,"checking ring closure");
603  switch ( ring->type )
604  {
605  case LINETYPE:
606  is_closed = lwline_is_closed(lwgeom_as_lwline(ring));
607  break;
608 
609  case CIRCSTRINGTYPE:
611  break;
612 
613  case COMPOUNDTYPE:
614  is_closed = lwcompound_is_closed(lwgeom_as_lwcompound(ring));
615  break;
616  }
617  if ( ! is_closed )
618  {
619  LWDEBUG(4,"ring is not closed");
620  lwgeom_free(ring);
621  lwgeom_free(poly);
623  return NULL;
624  }
625  }
626 
628  {
629  LWDEBUG(4,"failed to add ring");
630  lwgeom_free(ring);
631  lwgeom_free(poly);
633  return NULL;
634  }
635 
636  return poly;
637 }
638 
639 LWGEOM* wkt_parser_curvepolygon_finalize(LWGEOM *poly, char *dimensionality)
640 {
641  uint8_t flags = wkt_dimensionality(dimensionality);
642  int flagdims = FLAGS_NDIMS(flags);
643  LWDEBUG(4,"entered");
644 
645  /* Null input implies empty return */
646  if( ! poly )
648 
649  if ( flagdims > 2 )
650  {
651  /* If the number of dimensions are not consistent, we have a problem. */
652  if( flagdims != FLAGS_NDIMS(poly->flags) )
653  {
654  lwgeom_free(poly);
656  return NULL;
657  }
658 
659  /* Harmonize the flags in the sub-components with the wkt flags */
660  if( LW_FAILURE == wkt_parser_set_dims(poly, flags) )
661  {
662  lwgeom_free(poly);
664  return NULL;
665  }
666  }
667 
668  return poly;
669 }
670 
672 {
673  LWCOLLECTION *col;
674  LWGEOM **geoms;
675  static int ngeoms = 1;
676  LWDEBUG(4,"entered");
677 
678  /* Toss error on null geometry input */
679  if( ! geom )
680  {
682  return NULL;
683  }
684 
685  /* Create our geometry array */
686  geoms = lwalloc(sizeof(LWGEOM*) * ngeoms);
687  geoms[0] = geom;
688 
689  /* Make a new collection */
690  col = lwcollection_construct(COLLECTIONTYPE, SRID_UNKNOWN, NULL, ngeoms, geoms);
691 
692  /* Return the result. */
693  return lwcollection_as_lwgeom(col);
694 }
695 
696 
698 {
699  LWDEBUG(4,"entered");
700 
701  /* Toss error on null geometry input */
702  if( ! (geom && col) )
703  {
705  return NULL;
706  }
707 
708  /* All the elements must agree on dimensionality */
709  if( FLAGS_NDIMS(col->flags) != FLAGS_NDIMS(geom->flags) )
710  {
711  lwgeom_free(col);
712  lwgeom_free(geom);
714  return NULL;
715  }
716 
717  if( LW_FAILURE == lwcompound_add_lwgeom((LWCOMPOUND*)col, geom) )
718  {
719  lwgeom_free(col);
720  lwgeom_free(geom);
722  return NULL;
723  }
724 
725  return col;
726 }
727 
728 
730 {
731  LWDEBUG(4,"entered");
732 
733  /* Toss error on null geometry input */
734  if( ! (geom && col) )
735  {
737  return NULL;
738  }
739 
740  /* All the elements must agree on dimensionality */
741  if( FLAGS_NDIMS(col->flags) != FLAGS_NDIMS(geom->flags) )
742  {
743  lwgeom_free(col);
744  lwgeom_free(geom);
746  return NULL;
747  }
748 
750 }
751 
752 LWGEOM* wkt_parser_collection_finalize(int lwtype, LWGEOM *col, char *dimensionality)
753 {
754  uint8_t flags = wkt_dimensionality(dimensionality);
755  int flagdims = FLAGS_NDIMS(flags);
756 
757  /* No geometry means it is empty */
758  if( ! col )
759  {
761  }
762 
763  /* There are 'Z' or 'M' tokens in the signature */
764  if ( flagdims > 2 )
765  {
766  /* If the number of dimensions are not consistent, we have a problem. */
767  if( flagdims != FLAGS_NDIMS(col->flags) )
768  {
769  lwgeom_free(col);
771  return NULL;
772  }
773 
774  /* For GEOMETRYCOLLECTION, the exact type of the dimensions must match too */
775  if( lwtype == COLLECTIONTYPE &&
776  ( (FLAGS_GET_Z(flags) != FLAGS_GET_Z(col->flags)) ||
777  (FLAGS_GET_M(flags) != FLAGS_GET_M(col->flags)) ) )
778  {
779  lwgeom_free(col);
781  return NULL;
782  }
783 
784  /* Harmonize the collection dimensionality */
785  if( LW_FAILURE == wkt_parser_set_dims(col, flags) )
786  {
787  lwgeom_free(col);
789  return NULL;
790  }
791  }
792 
793  /* Set the collection type */
794  col->type=lwtype;
795 
796  return col;
797 }
798 
799 void wkt_parser_geometry_new(LWGEOM *geom, int srid)
800 {
801  LWDEBUG(4,"entered");
802  LWDEBUGF(4,"geom %p",geom);
803  LWDEBUGF(4,"srid %d",srid);
804 
805  if ( geom == NULL )
806  {
807  lwerror("Parsed geometry is null!");
808  return;
809  }
810 
811  if ( srid != SRID_UNKNOWN && srid < SRID_MAXIMUM )
812  lwgeom_set_srid(geom, srid);
813  else
815 
816  global_parser_result.geom = geom;
817 }
818 
820 {
821  memset(parser_result, 0, sizeof(LWGEOM_PARSER_RESULT));
822 }
823 
824 
826 {
827  if ( parser_result->geom )
828  {
829  lwgeom_free(parser_result->geom);
830  parser_result->geom = 0;
831  }
832  if ( parser_result->serialized_lwgeom )
833  {
834  lwfree(parser_result->serialized_lwgeom );
835  parser_result->serialized_lwgeom = 0;
836  }
837  /* We don't free parser_result->message because
838  it is a const *char */
839 }
840 
841 /*
842 * Public function used for easy access to the parser.
843 */
844 LWGEOM *lwgeom_from_wkt(const char *wkt, const char check)
845 {
847 
848  if( LW_FAILURE == lwgeom_parse_wkt(&r, (char*)wkt, check) )
849  {
850  lwerror(r.message);
851  return NULL;
852  }
853 
854  return r.geom;
855 }
856 
857 
double x
Definition: lwin_wkt.h:10
double x
Definition: liblwgeom.h:308
#define LINETYPE
Definition: liblwgeom.h:61
LWGEOM * wkt_parser_polygon_finalize(LWGEOM *poly, char *dimensionality)
Definition: lwin_wkt.c:508
int clamp_srid(int srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition: lwutil.c:326
LWGEOM * wkt_parser_triangle_new(POINTARRAY *pa, char *dimensionality)
Definition: lwin_wkt.c:397
double m
Definition: lwin_wkt.h:13
static int wkt_parser_set_dims(LWGEOM *geom, uint8_t flags)
Force the dimensionality of a geometry to match the dimensionality of a set of flags (usually derived...
Definition: lwin_wkt.c:87
LWLINE * lwline_construct_empty(int srid, char hasz, char hasm)
Definition: lwline.c:51
LWGEOM * wkt_parser_point_new(POINTARRAY *pa, char *dimensionality)
Create a new point.
Definition: lwin_wkt.c:293
double m
Definition: liblwgeom.h:308
LWGEOM * wkt_parser_collection_add_geom(LWGEOM *col, LWGEOM *geom)
Definition: lwin_wkt.c:729
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
Definition: lwcollection.c:30
#define PARSER_ERROR_INCONTINUOUS
Definition: liblwgeom.h:1735
char * r
Definition: cu_in_wkt.c:25
LWGEOM * wkt_parser_polygon_add_ring(LWGEOM *poly, POINTARRAY *pa, char dimcheck)
Definition: lwin_wkt.c:458
void lwfree(void *mem)
Definition: lwutil.c:190
LWTRIANGLE * lwtriangle_construct_empty(int srid, char hasz, char hasm)
Definition: lwtriangle.c:45
LWGEOM ** rings
Definition: liblwgeom.h:491
int npoints
Definition: liblwgeom.h:327
#define LW_PARSER_CHECK_MINPOINTS
Parser check flags.
Definition: liblwgeom.h:1701
LWGEOM * wkt_parser_curvepolygon_new(LWGEOM *ring)
Definition: lwin_wkt.c:540
int wkt_lexer_read_srid(char *str)
Read the SRID number from an SRID=<> string.
Definition: lwin_wkt.c:47
#define POLYGONTYPE
Definition: liblwgeom.h:62
LWGEOM * wkt_parser_circularstring_new(POINTARRAY *pa, char *dimensionality)
Create a new circularstring.
Definition: lwin_wkt.c:361
uint8_t flags
Definition: liblwgeom.h:353
LWGEOM * lwcircstring_as_lwgeom(const LWCIRCSTRING *obj)
Definition: lwgeom.c:224
#define CURVEPOLYTYPE
Definition: liblwgeom.h:69
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:57
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1006
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:315
#define COMPOUNDTYPE
Definition: liblwgeom.h:68
#define LW_SUCCESS
Definition: liblwgeom.h:55
void lwgeom_parser_result_free(LWGEOM_PARSER_RESULT *parser_result)
Definition: lwin_wkt.c:825
int ptarray_is_closed_z(const POINTARRAY *pa)
Definition: ptarray.c:684
LWGEOM * wkt_parser_collection_new(LWGEOM *geom)
Definition: lwin_wkt.c:671
LWCURVEPOLY * lwgeom_as_lwcurvepoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:116
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:50
#define TRIANGLETYPE
Definition: liblwgeom.h:73
int lwcompound_is_closed(const LWCOMPOUND *curve)
Definition: lwcompound.c:22
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:125
LWGEOM_PARSER_RESULT global_parser_result
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:118
POINTARRAY * point
Definition: liblwgeom.h:367
double y
Definition: lwin_wkt.h:11
#define PARSER_ERROR_MIXDIMS
Definition: liblwgeom.h:1732
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:672
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:239
LWGEOM * wkt_parser_collection_finalize(int lwtype, LWGEOM *col, char *dimensionality)
Definition: lwin_wkt.c:752
#define LW_FAILURE
Definition: liblwgeom.h:54
LWGEOM * wkt_parser_linestring_new(POINTARRAY *pa, char *dimensionality)
Create a new linestring.
Definition: lwin_wkt.c:327
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
#define FLAGS_SET_Z(flags, value)
Definition: liblwgeom.h:112
#define LW_PARSER_CHECK_ODD
Definition: liblwgeom.h:1702
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:249
LWCIRCSTRING * lwcircstring_construct_empty(int srid, char hasz, char hasm)
Definition: lwcircstring.c:67
LWGEOM * wkt_parser_curvepolygon_finalize(LWGEOM *poly, char *dimensionality)
Definition: lwin_wkt.c:639
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
POINTARRAY * wkt_parser_ptarray_new(POINT p)
Start a point array from the first coordinate.
Definition: lwin_wkt.c:276
#define LW_FALSE
Definition: liblwgeom.h:52
POINTARRAY * wkt_parser_ptarray_add_coord(POINTARRAY *pa, POINT p)
Definition: lwin_wkt.c:238
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.
#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
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:29
LWGEOM ** geoms
Definition: liblwgeom.h:465
LWGEOM * lwgeom_from_wkt(const char *wkt, const char check)
Definition: lwin_wkt.c:844
int lwcircstring_is_closed(const LWCIRCSTRING *curve)
Definition: lwcircstring.c:255
static uint8_t wkt_dimensionality(char *dimensionality)
Definition: lwin_wkt.c:61
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:154
POINTARRAY ** rings
Definition: liblwgeom.h:413
double z
Definition: lwin_wkt.h:12
int lwtype_is_collection(uint8_t type)
Determine whether a type number is a collection or not.
Definition: lwgeom.c:955
#define PARSER_ERROR_MOREPOINTS
Definition: liblwgeom.h:1729
LWCURVEPOLY * lwcurvepoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwcurvepoly.c:23
LWCOMPOUND * lwgeom_as_lwcompound(const LWGEOM *lwgeom)
Definition: lwgeom.c:107
int nrings
Definition: liblwgeom.h:411
LWGEOM * lwtriangle_as_lwgeom(const LWTRIANGLE *obj)
Definition: lwgeom.c:244
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:106
#define PARSER_ERROR_LESSPOINTS
Definition: liblwgeom.h:1737
double z
Definition: liblwgeom.h:308
LWTRIANGLE * lwtriangle_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwtriangle.c:27
Definition: lwin_wkt.h:7
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:89
LWCIRCSTRING * lwcircstring_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwcircstring.c:38
LWCIRCSTRING * lwgeom_as_lwcircstring(const LWGEOM *lwgeom)
Definition: lwgeom.c:98
#define PARSER_ERROR_ODDPOINTS
Definition: liblwgeom.h:1730
POINT wkt_parser_coord_2(double c1, double c2)
Build a 2d coordinate.
Definition: lwin_wkt.c:194
#define PARSER_ERROR_UNCLOSED
Definition: liblwgeom.h:1731
LWGEOM * wkt_parser_compound_add_geom(LWGEOM *col, LWGEOM *geom)
Definition: lwin_wkt.c:697
LWGEOM * wkt_parser_polygon_new(POINTARRAY *pa, char dimcheck)
Definition: lwin_wkt.c:433
const char * parser_error_messages[]
Definition: lwin_wkt.c:23
void lwgeom_parser_result_init(LWGEOM_PARSER_RESULT *parser_result)
Definition: lwin_wkt.c:819
POINT wkt_parser_coord_3(double c1, double c2, double c3)
Note, if this is an XYM coordinate we'll have to fix it later when we build the object itself and hav...
Definition: lwin_wkt.c:210
#define PARSER_ERROR_TRIANGLEPOINTS
Definition: liblwgeom.h:1736
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition: lwgeom.c:143
int lwline_is_closed(const LWLINE *line)
Definition: lwline.c:435
#define SET_PARSER_ERROR(errno)
Definition: lwin_wkt.c:38
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:66
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:107
uint8_t type
Definition: liblwgeom.h:352
int lwcurvepoly_add_ring(LWCURVEPOLY *poly, LWGEOM *ring)
Add a ring, allocating extra space if necessary.
Definition: lwcurvepoly.c:59
void wkt_parser_geometry_new(LWGEOM *geom, int srid)
Definition: lwin_wkt.c:799
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:254
void lwgeom_set_srid(LWGEOM *geom, int srid)
Set the SRID on an LWGEOM For collections, only the parent gets an SRID, all the children get SRID_UN...
LWGEOM * lwcurvepoly_as_lwgeom(const LWCURVEPOLY *obj)
Definition: lwgeom.c:229
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition: lwpoly.c:154
LWGEOM * wkt_parser_curvepolygon_add_ring(LWGEOM *poly, LWGEOM *ring)
Definition: lwin_wkt.c:558
#define SRID_MAXIMUM
Maximum allowed SRID value in serialized geometry.
Definition: liblwgeom.h:145
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:67
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:96
void * lwalloc(size_t size)
Definition: lwutil.c:175
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1229
int lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1072
double y
Definition: liblwgeom.h:308
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:81
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:118
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:174
static int wkt_pointarray_dimensionality(POINTARRAY *pa, uint8_t flags)
Read the dimensionality from a flag, if provided.
Definition: lwin_wkt.c:156
#define LW_PARSER_CHECK_CLOSURE
Definition: liblwgeom.h:1703
uint8_t flags
Definition: lwin_wkt.h:9
#define PARSER_ERROR_OTHER
Definition: liblwgeom.h:1738
int lwcompound_add_lwgeom(LWCOMPOUND *comp, LWGEOM *geom)
Add a component, allocating extra space if necessary.
Definition: lwcompound.c:75
int ptarray_is_closed(const POINTARRAY *pa)
Check for ring closure using whatever dimensionality is declared on the pointarray.
Definition: ptarray.c:665
#define COLLECTIONTYPE
Definition: liblwgeom.h:66
POINT wkt_parser_coord_4(double c1, double c2, double c3, double c4)
Definition: lwin_wkt.c:225
#define FLAGS_SET_M(flags, value)
Definition: liblwgeom.h:113
POINTARRAY * points
Definition: liblwgeom.h:378
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:219