PostGIS  2.2.7dev-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  switch( geom->type )
101  {
102  case POINTTYPE:
103  {
104  LWPOINT *pt = (LWPOINT*)geom;
105  if ( pt->point )
106  {
107  FLAGS_SET_Z(pt->point->flags, hasz);
108  FLAGS_SET_M(pt->point->flags, hasm);
109  }
110  break;
111  }
112  case TRIANGLETYPE:
113  case CIRCSTRINGTYPE:
114  case LINETYPE:
115  {
116  LWLINE *ln = (LWLINE*)geom;
117  if ( ln->points )
118  {
119  FLAGS_SET_Z(ln->points->flags, hasz);
120  FLAGS_SET_M(ln->points->flags, hasm);
121  }
122  break;
123  }
124  case POLYGONTYPE:
125  {
126  LWPOLY *poly = (LWPOLY*)geom;
127  for ( i = 0; i < poly->nrings; i++ )
128  {
129  if( poly->rings[i] )
130  {
131  FLAGS_SET_Z(poly->rings[i]->flags, hasz);
132  FLAGS_SET_M(poly->rings[i]->flags, hasm);
133  }
134  }
135  break;
136  }
137  case CURVEPOLYTYPE:
138  {
139  LWCURVEPOLY *poly = (LWCURVEPOLY*)geom;
140  for ( i = 0; i < poly->nrings; i++ )
141  wkt_parser_set_dims(poly->rings[i], flags);
142  break;
143  }
144  default:
145  {
146  if ( lwtype_is_collection(geom->type) )
147  {
148  LWCOLLECTION *col = (LWCOLLECTION*)geom;
149  for ( i = 0; i < col->ngeoms; i++ )
150  wkt_parser_set_dims(col->geoms[i], flags);
151  return LW_SUCCESS;
152  }
153  else
154  {
155  LWDEBUGF(2,"Unknown geometry type: %d", geom->type);
156  return LW_FAILURE;
157  }
158  }
159  }
160 
161  return LW_SUCCESS;
162 }
163 
169 static int wkt_pointarray_dimensionality(POINTARRAY *pa, uint8_t flags)
170 {
171  int hasz = FLAGS_GET_Z(flags);
172  int hasm = FLAGS_GET_M(flags);
173  int ndims = 2 + hasz + hasm;
174 
175  /* No dimensionality or array means we go with what we have */
176  if( ! (flags && pa) )
177  return LW_TRUE;
178 
179  LWDEBUGF(5,"dimensionality ndims == %d", ndims);
180  LWDEBUGF(5,"FLAGS_NDIMS(pa->flags) == %d", FLAGS_NDIMS(pa->flags));
181 
182  /*
183  * ndims > 2 implies that the flags have something useful to add,
184  * that there is a 'Z' or an 'M' or both.
185  */
186  if( ndims > 2 )
187  {
188  /* Mismatch implies a problem */
189  if ( FLAGS_NDIMS(pa->flags) != ndims )
190  return LW_FALSE;
191  /* Match means use the explicit dimensionality */
192  else
193  {
194  FLAGS_SET_Z(pa->flags, hasz);
195  FLAGS_SET_M(pa->flags, hasm);
196  }
197  }
198 
199  return LW_TRUE;
200 }
201 
202 
203 
207 POINT wkt_parser_coord_2(double c1, double c2)
208 {
209  POINT p;
210  p.flags = 0;
211  p.x = c1;
212  p.y = c2;
213  p.z = p.m = 0.0;
214  FLAGS_SET_Z(p.flags, 0);
215  FLAGS_SET_M(p.flags, 0);
216  return p;
217 }
218 
223 POINT wkt_parser_coord_3(double c1, double c2, double c3)
224 {
225  POINT p;
226  p.flags = 0;
227  p.x = c1;
228  p.y = c2;
229  p.z = c3;
230  p.m = 0;
231  FLAGS_SET_Z(p.flags, 1);
232  FLAGS_SET_M(p.flags, 0);
233  return p;
234 }
235 
238 POINT wkt_parser_coord_4(double c1, double c2, double c3, double c4)
239 {
240  POINT p;
241  p.flags = 0;
242  p.x = c1;
243  p.y = c2;
244  p.z = c3;
245  p.m = c4;
246  FLAGS_SET_Z(p.flags, 1);
247  FLAGS_SET_M(p.flags, 1);
248  return p;
249 }
250 
252 {
253  POINT4D pt;
254  LWDEBUG(4,"entered");
255 
256  /* Error on trouble */
257  if( ! pa )
258  {
260  return NULL;
261  }
262 
263  /* Check that the coordinate has the same dimesionality as the array */
264  if( FLAGS_NDIMS(p.flags) != FLAGS_NDIMS(pa->flags) )
265  {
266  ptarray_free(pa);
268  return NULL;
269  }
270 
271  /* While parsing the point arrays, XYM and XMZ points are both treated as XYZ */
272  pt.x = p.x;
273  pt.y = p.y;
274  if( FLAGS_GET_Z(pa->flags) )
275  pt.z = p.z;
276  if( FLAGS_GET_M(pa->flags) )
277  pt.m = p.m;
278  /* If the destination is XYM, we'll write the third coordinate to m */
279  if( FLAGS_GET_M(pa->flags) && ! FLAGS_GET_Z(pa->flags) )
280  pt.m = p.z;
281 
282  ptarray_append_point(pa, &pt, LW_TRUE); /* Allow duplicate points in array */
283  return pa;
284 }
285 
290 {
291  int ndims = FLAGS_NDIMS(p.flags);
292  POINTARRAY *pa = ptarray_construct_empty((ndims>2), (ndims>3), 4);
293  LWDEBUG(4,"entered");
294  if ( ! pa )
295  {
297  return NULL;
298  }
299  return wkt_parser_ptarray_add_coord(pa, p);
300 }
301 
306 LWGEOM* wkt_parser_point_new(POINTARRAY *pa, char *dimensionality)
307 {
308  uint8_t flags = wkt_dimensionality(dimensionality);
309  LWDEBUG(4,"entered");
310 
311  /* No pointarray means it is empty */
312  if( ! pa )
314 
315  /* If the number of dimensions is not consistent, we have a problem. */
316  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
317  {
318  ptarray_free(pa);
320  return NULL;
321  }
322 
323  /* Only one point allowed in our point array! */
324  if( pa->npoints != 1 )
325  {
326  ptarray_free(pa);
328  return NULL;
329  }
330 
332 }
333 
334 
340 LWGEOM* wkt_parser_linestring_new(POINTARRAY *pa, char *dimensionality)
341 {
342  uint8_t flags = wkt_dimensionality(dimensionality);
343  LWDEBUG(4,"entered");
344 
345  /* No pointarray means it is empty */
346  if( ! pa )
348 
349  /* If the number of dimensions is not consistent, we have a problem. */
350  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
351  {
352  ptarray_free(pa);
354  return NULL;
355  }
356 
357  /* Apply check for not enough points, if requested. */
359  {
360  ptarray_free(pa);
362  return NULL;
363  }
364 
366 }
367 
375 {
376  uint8_t flags = wkt_dimensionality(dimensionality);
377  LWDEBUG(4,"entered");
378 
379  /* No pointarray means it is empty */
380  if( ! pa )
382 
383  /* If the number of dimensions is not consistent, we have a problem. */
384  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
385  {
386  ptarray_free(pa);
388  return NULL;
389  }
390 
391  /* Apply check for not enough points, if requested. */
393  {
394  ptarray_free(pa);
396  return NULL;
397  }
398 
399  /* Apply check for odd number of points, if requested. */
401  {
402  ptarray_free(pa);
404  return NULL;
405  }
406 
408 }
409 
410 LWGEOM* wkt_parser_triangle_new(POINTARRAY *pa, char *dimensionality)
411 {
412  uint8_t flags = wkt_dimensionality(dimensionality);
413  LWDEBUG(4,"entered");
414 
415  /* No pointarray means it is empty */
416  if( ! pa )
418 
419  /* If the number of dimensions is not consistent, we have a problem. */
420  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
421  {
422  ptarray_free(pa);
424  return NULL;
425  }
426 
427  /* Triangles need four points. */
428  if( (pa->npoints != 4) )
429  {
430  ptarray_free(pa);
432  return NULL;
433  }
434 
435  /* Triangles need closure. */
436  if( ! ptarray_is_closed(pa) )
437  {
438  ptarray_free(pa);
440  return NULL;
441  }
442 
444 }
445 
447 {
448  LWPOLY *poly = NULL;
449  LWDEBUG(4,"entered");
450 
451  /* No pointarray is a problem */
452  if( ! pa )
453  {
455  return NULL;
456  }
457 
459 
460  /* Error out if we can't build this polygon. */
461  if( ! poly )
462  {
464  return NULL;
465  }
466 
467  wkt_parser_polygon_add_ring(lwpoly_as_lwgeom(poly), pa, dimcheck);
468  return lwpoly_as_lwgeom(poly);
469 }
470 
472 {
473  LWDEBUG(4,"entered");
474 
475  /* Bad inputs are a problem */
476  if( ! (pa && poly) )
477  {
479  return NULL;
480  }
481 
482  /* Rings must agree on dimensionality */
483  if( FLAGS_NDIMS(poly->flags) != FLAGS_NDIMS(pa->flags) )
484  {
485  ptarray_free(pa);
486  lwgeom_free(poly);
488  return NULL;
489  }
490 
491  /* Apply check for minimum number of points, if requested. */
493  {
494  ptarray_free(pa);
495  lwgeom_free(poly);
497  return NULL;
498  }
499 
500  /* Apply check for not closed rings, if requested. */
502  ! (dimcheck == 'Z' ? ptarray_is_closed_z(pa) : ptarray_is_closed_2d(pa)) )
503  {
504  ptarray_free(pa);
505  lwgeom_free(poly);
507  return NULL;
508  }
509 
510  /* If something goes wrong adding a ring, error out. */
511  if ( LW_FAILURE == lwpoly_add_ring(lwgeom_as_lwpoly(poly), pa) )
512  {
513  ptarray_free(pa);
514  lwgeom_free(poly);
516  return NULL;
517  }
518  return poly;
519 }
520 
521 LWGEOM* wkt_parser_polygon_finalize(LWGEOM *poly, char *dimensionality)
522 {
523  uint8_t flags = wkt_dimensionality(dimensionality);
524  int flagdims = FLAGS_NDIMS(flags);
525  LWDEBUG(4,"entered");
526 
527  /* Null input implies empty return */
528  if( ! poly )
530 
531  /* If the number of dimensions are not consistent, we have a problem. */
532  if( flagdims > 2 )
533  {
534  if ( flagdims != FLAGS_NDIMS(poly->flags) )
535  {
536  lwgeom_free(poly);
538  return NULL;
539  }
540 
541  /* Harmonize the flags in the sub-components with the wkt flags */
542  if( LW_FAILURE == wkt_parser_set_dims(poly, flags) )
543  {
544  lwgeom_free(poly);
546  return NULL;
547  }
548  }
549 
550  return poly;
551 }
552 
554 {
555  LWGEOM *poly;
556  LWDEBUG(4,"entered");
557 
558  /* Toss error on null geometry input */
559  if( ! ring )
560  {
562  return NULL;
563  }
564 
565  /* Construct poly and add the ring. */
567  /* Return the result. */
568  return wkt_parser_curvepolygon_add_ring(poly,ring);
569 }
570 
572 {
573  LWDEBUG(4,"entered");
574 
575  /* Toss error on null input */
576  if( ! (ring && poly) )
577  {
579  LWDEBUG(4,"inputs are null");
580  return NULL;
581  }
582 
583  /* All the elements must agree on dimensionality */
584  if( FLAGS_NDIMS(poly->flags) != FLAGS_NDIMS(ring->flags) )
585  {
586  LWDEBUG(4,"dimensionality does not match");
587  lwgeom_free(ring);
588  lwgeom_free(poly);
590  return NULL;
591  }
592 
593  /* Apply check for minimum number of points, if requested. */
595  {
596  int vertices_needed = 3;
597 
598  if ( ring->type == LINETYPE )
599  vertices_needed = 4;
600 
601  if (lwgeom_count_vertices(ring) < vertices_needed)
602  {
603  LWDEBUG(4,"number of points is incorrect");
604  lwgeom_free(ring);
605  lwgeom_free(poly);
607  return NULL;
608  }
609  }
610 
611  /* Apply check for not closed rings, if requested. */
613  {
614  int is_closed = 1;
615  LWDEBUG(4,"checking ring closure");
616  switch ( ring->type )
617  {
618  case LINETYPE:
619  is_closed = lwline_is_closed(lwgeom_as_lwline(ring));
620  break;
621 
622  case CIRCSTRINGTYPE:
624  break;
625 
626  case COMPOUNDTYPE:
627  is_closed = lwcompound_is_closed(lwgeom_as_lwcompound(ring));
628  break;
629  }
630  if ( ! is_closed )
631  {
632  LWDEBUG(4,"ring is not closed");
633  lwgeom_free(ring);
634  lwgeom_free(poly);
636  return NULL;
637  }
638  }
639 
641  {
642  LWDEBUG(4,"failed to add ring");
643  lwgeom_free(ring);
644  lwgeom_free(poly);
646  return NULL;
647  }
648 
649  return poly;
650 }
651 
652 LWGEOM* wkt_parser_curvepolygon_finalize(LWGEOM *poly, char *dimensionality)
653 {
654  uint8_t flags = wkt_dimensionality(dimensionality);
655  int flagdims = FLAGS_NDIMS(flags);
656  LWDEBUG(4,"entered");
657 
658  /* Null input implies empty return */
659  if( ! poly )
661 
662  if ( flagdims > 2 )
663  {
664  /* If the number of dimensions are not consistent, we have a problem. */
665  if( flagdims != FLAGS_NDIMS(poly->flags) )
666  {
667  lwgeom_free(poly);
669  return NULL;
670  }
671 
672  /* Harmonize the flags in the sub-components with the wkt flags */
673  if( LW_FAILURE == wkt_parser_set_dims(poly, flags) )
674  {
675  lwgeom_free(poly);
677  return NULL;
678  }
679  }
680 
681  return poly;
682 }
683 
685 {
686  LWCOLLECTION *col;
687  LWGEOM **geoms;
688  static int ngeoms = 1;
689  LWDEBUG(4,"entered");
690 
691  /* Toss error on null geometry input */
692  if( ! geom )
693  {
695  return NULL;
696  }
697 
698  /* Create our geometry array */
699  geoms = lwalloc(sizeof(LWGEOM*) * ngeoms);
700  geoms[0] = geom;
701 
702  /* Make a new collection */
703  col = lwcollection_construct(COLLECTIONTYPE, SRID_UNKNOWN, NULL, ngeoms, geoms);
704 
705  /* Return the result. */
706  return lwcollection_as_lwgeom(col);
707 }
708 
709 
711 {
712  LWCOLLECTION *col;
713  LWGEOM **geoms;
714  static int ngeoms = 1;
715  LWDEBUG(4,"entered");
716 
717  /* Toss error on null geometry input */
718  if( ! geom )
719  {
721  return NULL;
722  }
723 
724  /* Elements of a compoundcurve cannot be empty, because */
725  /* empty things can't join up and form a ring */
726  if ( lwgeom_is_empty(geom) )
727  {
728  lwgeom_free(geom);
730  return NULL;
731  }
732 
733  /* Create our geometry array */
734  geoms = lwalloc(sizeof(LWGEOM*) * ngeoms);
735  geoms[0] = geom;
736 
737  /* Make a new collection */
738  col = lwcollection_construct(COLLECTIONTYPE, SRID_UNKNOWN, NULL, ngeoms, geoms);
739 
740  /* Return the result. */
741  return lwcollection_as_lwgeom(col);
742 }
743 
744 
746 {
747  LWDEBUG(4,"entered");
748 
749  /* Toss error on null geometry input */
750  if( ! (geom && col) )
751  {
753  return NULL;
754  }
755 
756  /* All the elements must agree on dimensionality */
757  if( FLAGS_NDIMS(col->flags) != FLAGS_NDIMS(geom->flags) )
758  {
759  lwgeom_free(col);
760  lwgeom_free(geom);
762  return NULL;
763  }
764 
765  if( LW_FAILURE == lwcompound_add_lwgeom((LWCOMPOUND*)col, geom) )
766  {
767  lwgeom_free(col);
768  lwgeom_free(geom);
770  return NULL;
771  }
772 
773  return col;
774 }
775 
776 
778 {
779  LWDEBUG(4,"entered");
780 
781  /* Toss error on null geometry input */
782  if( ! (geom && col) )
783  {
785  return NULL;
786  }
787 
789 }
790 
791 LWGEOM* wkt_parser_collection_finalize(int lwtype, LWGEOM *geom, char *dimensionality)
792 {
793  uint8_t flags = wkt_dimensionality(dimensionality);
794  int flagdims = FLAGS_NDIMS(flags);
795 
796  /* No geometry means it is empty */
797  if( ! geom )
798  {
800  }
801 
802  /* There are 'Z' or 'M' tokens in the signature */
803  if ( flagdims > 2 )
804  {
806  int i;
807 
808  for ( i = 0 ; i < col->ngeoms; i++ )
809  {
810  LWGEOM *subgeom = col->geoms[i];
811  if ( FLAGS_NDIMS(flags) != FLAGS_NDIMS(subgeom->flags) &&
812  ! lwgeom_is_empty(subgeom) )
813  {
814  lwgeom_free(geom);
816  return NULL;
817  }
818 
819  if ( lwtype == COLLECTIONTYPE &&
820  ( (FLAGS_GET_Z(flags) != FLAGS_GET_Z(subgeom->flags)) ||
821  (FLAGS_GET_M(flags) != FLAGS_GET_M(subgeom->flags)) ) &&
822  ! lwgeom_is_empty(subgeom) )
823  {
824  lwgeom_free(geom);
826  return NULL;
827  }
828  }
829 
830  /* Harmonize the collection dimensionality */
831  if( LW_FAILURE == wkt_parser_set_dims(geom, flags) )
832  {
833  lwgeom_free(geom);
835  return NULL;
836  }
837  }
838 
839  /* Set the collection type */
840  geom->type = lwtype;
841 
842  return geom;
843 }
844 
845 void wkt_parser_geometry_new(LWGEOM *geom, int srid)
846 {
847  LWDEBUG(4,"entered");
848  LWDEBUGF(4,"geom %p",geom);
849  LWDEBUGF(4,"srid %d",srid);
850 
851  if ( geom == NULL )
852  {
853  lwerror("Parsed geometry is null!");
854  return;
855  }
856 
857  if ( srid != SRID_UNKNOWN && srid < SRID_MAXIMUM )
858  lwgeom_set_srid(geom, srid);
859  else
861 
862  global_parser_result.geom = geom;
863 }
864 
866 {
867  memset(parser_result, 0, sizeof(LWGEOM_PARSER_RESULT));
868 }
869 
870 
872 {
873  if ( parser_result->geom )
874  {
875  lwgeom_free(parser_result->geom);
876  parser_result->geom = 0;
877  }
878  if ( parser_result->serialized_lwgeom )
879  {
880  lwfree(parser_result->serialized_lwgeom );
881  parser_result->serialized_lwgeom = 0;
882  }
883  /* We don't free parser_result->message because
884  it is a const *char */
885 }
886 
887 /*
888 * Public function used for easy access to the parser.
889 */
890 LWGEOM *lwgeom_from_wkt(const char *wkt, const char check)
891 {
893 
894  if( LW_FAILURE == lwgeom_parse_wkt(&r, (char*)wkt, check) )
895  {
896  lwerror(r.message);
897  return NULL;
898  }
899 
900  return r.geom;
901 }
902 
903 
double x
Definition: lwin_wkt.h:10
double x
Definition: liblwgeom.h:336
#define LINETYPE
Definition: liblwgeom.h:71
LWGEOM * wkt_parser_polygon_finalize(LWGEOM *poly, char *dimensionality)
Definition: lwin_wkt.c:521
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:350
LWGEOM * wkt_parser_triangle_new(POINTARRAY *pa, char *dimensionality)
Definition: lwin_wkt.c:410
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:306
double m
Definition: liblwgeom.h:336
LWGEOM * wkt_parser_collection_add_geom(LWGEOM *col, LWGEOM *geom)
Definition: lwin_wkt.c:777
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:1898
char * r
Definition: cu_in_wkt.c:24
LWGEOM * wkt_parser_polygon_add_ring(LWGEOM *poly, POINTARRAY *pa, char dimcheck)
Definition: lwin_wkt.c:471
void lwfree(void *mem)
Definition: lwutil.c:214
LWTRIANGLE * lwtriangle_construct_empty(int srid, char hasz, char hasm)
Definition: lwtriangle.c:45
LWGEOM ** rings
Definition: liblwgeom.h:519
int npoints
Definition: liblwgeom.h:355
#define LW_PARSER_CHECK_MINPOINTS
Parser check flags.
Definition: liblwgeom.h:1864
LWGEOM * wkt_parser_curvepolygon_new(LWGEOM *ring)
Definition: lwin_wkt.c:553
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:72
LWGEOM * wkt_parser_circularstring_new(POINTARRAY *pa, char *dimensionality)
Create a new circularstring.
Definition: lwin_wkt.c:374
uint8_t flags
Definition: liblwgeom.h:381
LWGEOM * lwcircstring_as_lwgeom(const LWCIRCSTRING *obj)
Definition: lwgeom.c:224
#define CURVEPOLYTYPE
Definition: liblwgeom.h:79
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1050
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:330
#define COMPOUNDTYPE
Definition: liblwgeom.h:78
#define LW_SUCCESS
Definition: liblwgeom.h:65
void lwgeom_parser_result_free(LWGEOM_PARSER_RESULT *parser_result)
Definition: lwin_wkt.c:871
int ptarray_is_closed_z(const POINTARRAY *pa)
Definition: ptarray.c:720
LWGEOM * wkt_parser_collection_new(LWGEOM *geom)
Definition: lwin_wkt.c:684
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:83
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:120
POINTARRAY * point
Definition: liblwgeom.h:395
double y
Definition: lwin_wkt.h:11
#define PARSER_ERROR_MIXDIMS
Definition: liblwgeom.h:1895
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:694
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:239
#define LW_FAILURE
Definition: liblwgeom.h:64
LWGEOM * wkt_parser_linestring_new(POINTARRAY *pa, char *dimensionality)
Create a new linestring.
Definition: lwin_wkt.c:340
#define FLAGS_SET_Z(flags, value)
Definition: liblwgeom.h:130
#define LW_PARSER_CHECK_ODD
Definition: liblwgeom.h:1865
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:652
LWGEOM * wkt_parser_collection_finalize(int lwtype, LWGEOM *geom, char *dimensionality)
Definition: lwin_wkt.c:791
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:156
POINTARRAY * wkt_parser_ptarray_new(POINT p)
Start a point array from the first coordinate.
Definition: lwin_wkt.c:289
#define LW_FALSE
Definition: liblwgeom.h:62
POINTARRAY * wkt_parser_ptarray_add_coord(POINTARRAY *pa, POINT p)
Definition: lwin_wkt.c:251
uint8_t flags
Definition: liblwgeom.h:353
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:61
Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM...
Definition: liblwgeom.h:1876
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:29
LWGEOM ** geoms
Definition: liblwgeom.h:493
LWGEOM * lwgeom_from_wkt(const char *wkt, const char check)
Definition: lwin_wkt.c:890
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:172
POINTARRAY ** rings
Definition: liblwgeom.h:441
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:999
#define PARSER_ERROR_MOREPOINTS
Definition: liblwgeom.h:1892
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:439
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:124
#define PARSER_ERROR_LESSPOINTS
Definition: liblwgeom.h:1900
double z
Definition: liblwgeom.h:336
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:1893
POINT wkt_parser_coord_2(double c1, double c2)
Build a 2d coordinate.
Definition: lwin_wkt.c:207
#define PARSER_ERROR_UNCLOSED
Definition: liblwgeom.h:1894
LWGEOM * wkt_parser_compound_add_geom(LWGEOM *col, LWGEOM *geom)
Definition: lwin_wkt.c:745
LWGEOM * wkt_parser_polygon_new(POINTARRAY *pa, char dimcheck)
Definition: lwin_wkt.c:446
const char * parser_error_messages[]
Definition: lwin_wkt.c:23
void lwgeom_parser_result_init(LWGEOM_PARSER_RESULT *parser_result)
Definition: lwin_wkt.c:865
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:223
#define PARSER_ERROR_TRIANGLEPOINTS
Definition: liblwgeom.h:1899
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition: lwgeom.c:143
int lwline_is_closed(const LWLINE *line)
Definition: lwline.c:439
#define SET_PARSER_ERROR(errno)
Definition: lwin_wkt.c:38
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:70
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:66
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:125
uint8_t type
Definition: liblwgeom.h:380
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:845
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:571
#define SRID_MAXIMUM
Maximum allowed SRID value in serialized geometry.
Definition: liblwgeom.h:163
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:77
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:98
void * lwalloc(size_t size)
Definition: lwutil.c:199
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:1297
int lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1140
double y
Definition: liblwgeom.h:336
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:136
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:169
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:74
#define LW_PARSER_CHECK_CLOSURE
Definition: liblwgeom.h:1866
uint8_t flags
Definition: lwin_wkt.h:9
#define PARSER_ERROR_OTHER
Definition: liblwgeom.h:1901
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:680
#define COLLECTIONTYPE
Definition: liblwgeom.h:76
POINT wkt_parser_coord_4(double c1, double c2, double c3, double c4)
Definition: lwin_wkt.c:238
#define FLAGS_SET_M(flags, value)
Definition: liblwgeom.h:131
LWGEOM * wkt_parser_compound_new(LWGEOM *geom)
Definition: lwin_wkt.c:710
POINTARRAY * points
Definition: liblwgeom.h:406
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:219