PostGIS  2.3.8dev-r@@SVN_REVISION@@
lwin_wkt.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 (C) 2010 Paul Ramsey <pramsey@cleverelephant.ca>
22  *
23  **********************************************************************/
24 
25 
26 #include <stdlib.h>
27 #include <ctype.h> /* for isspace */
28 
29 #include "lwin_wkt.h"
30 #include "lwin_wkt_parse.h"
31 #include "lwgeom_log.h"
32 
33 
34 /*
35 * Error messages for failures in the parser.
36 */
37 const char *parser_error_messages[] =
38 {
39  "",
40  "geometry requires more points",
41  "geometry must have an odd number of points",
42  "geometry contains non-closed rings",
43  "can not mix dimensionality in a geometry",
44  "parse error - invalid geometry",
45  "invalid WKB type",
46  "incontinuous compound curve",
47  "triangle must have exactly 4 points",
48  "geometry has too many points",
49  "parse error - invalid geometry"
50 };
51 
52 #define SET_PARSER_ERROR(errno) { \
53  global_parser_result.message = parser_error_messages[(errno)]; \
54  global_parser_result.errcode = (errno); \
55  global_parser_result.errlocation = wkt_yylloc.last_column; \
56  }
57 
61 int wkt_lexer_read_srid(char *str)
62 {
63  char *c = str;
64  long i = 0;
65  int srid;
66 
67  if( ! str ) return SRID_UNKNOWN;
68  c += 5; /* Advance past "SRID=" */
69  i = strtol(c, NULL, 10);
70  srid = clamp_srid((int)i);
71  /* TODO: warn on explicit UNKNOWN srid ? */
72  return srid;
73 }
74 
75 static uint8_t wkt_dimensionality(char *dimensionality)
76 {
77  int i = 0;
78  uint8_t flags = 0;
79 
80  if( ! dimensionality )
81  return flags;
82 
83  /* If there's an explicit dimensionality, we use that */
84  for( i = 0; i < strlen(dimensionality); i++ )
85  {
86  if( (dimensionality[i] == 'Z') || (dimensionality[i] == 'z') )
87  FLAGS_SET_Z(flags,1);
88  else if( (dimensionality[i] == 'M') || (dimensionality[i] == 'm') )
89  FLAGS_SET_M(flags,1);
90  /* only a space is accepted in between */
91  else if( ! isspace(dimensionality[i]) ) break;
92  }
93  return flags;
94 }
95 
96 
101 static int wkt_parser_set_dims(LWGEOM *geom, uint8_t flags)
102 {
103  int hasz = FLAGS_GET_Z(flags);
104  int hasm = FLAGS_GET_M(flags);
105  int i = 0;
106 
107  /* Error on junk */
108  if( ! geom )
109  return LW_FAILURE;
110 
111  FLAGS_SET_Z(geom->flags, hasz);
112  FLAGS_SET_M(geom->flags, hasm);
113 
114  switch( geom->type )
115  {
116  case POINTTYPE:
117  {
118  LWPOINT *pt = (LWPOINT*)geom;
119  if ( pt->point )
120  {
121  FLAGS_SET_Z(pt->point->flags, hasz);
122  FLAGS_SET_M(pt->point->flags, hasm);
123  }
124  break;
125  }
126  case TRIANGLETYPE:
127  case CIRCSTRINGTYPE:
128  case LINETYPE:
129  {
130  LWLINE *ln = (LWLINE*)geom;
131  if ( ln->points )
132  {
133  FLAGS_SET_Z(ln->points->flags, hasz);
134  FLAGS_SET_M(ln->points->flags, hasm);
135  }
136  break;
137  }
138  case POLYGONTYPE:
139  {
140  LWPOLY *poly = (LWPOLY*)geom;
141  for ( i = 0; i < poly->nrings; i++ )
142  {
143  if( poly->rings[i] )
144  {
145  FLAGS_SET_Z(poly->rings[i]->flags, hasz);
146  FLAGS_SET_M(poly->rings[i]->flags, hasm);
147  }
148  }
149  break;
150  }
151  case CURVEPOLYTYPE:
152  {
153  LWCURVEPOLY *poly = (LWCURVEPOLY*)geom;
154  for ( i = 0; i < poly->nrings; i++ )
155  wkt_parser_set_dims(poly->rings[i], flags);
156  break;
157  }
158  default:
159  {
160  if ( lwtype_is_collection(geom->type) )
161  {
162  LWCOLLECTION *col = (LWCOLLECTION*)geom;
163  for ( i = 0; i < col->ngeoms; i++ )
164  wkt_parser_set_dims(col->geoms[i], flags);
165  return LW_SUCCESS;
166  }
167  else
168  {
169  LWDEBUGF(2,"Unknown geometry type: %d", geom->type);
170  return LW_FAILURE;
171  }
172  }
173  }
174 
175  return LW_SUCCESS;
176 }
177 
183 static int wkt_pointarray_dimensionality(POINTARRAY *pa, uint8_t flags)
184 {
185  int hasz = FLAGS_GET_Z(flags);
186  int hasm = FLAGS_GET_M(flags);
187  int ndims = 2 + hasz + hasm;
188 
189  /* No dimensionality or array means we go with what we have */
190  if( ! (flags && pa) )
191  return LW_TRUE;
192 
193  LWDEBUGF(5,"dimensionality ndims == %d", ndims);
194  LWDEBUGF(5,"FLAGS_NDIMS(pa->flags) == %d", FLAGS_NDIMS(pa->flags));
195 
196  /*
197  * ndims > 2 implies that the flags have something useful to add,
198  * that there is a 'Z' or an 'M' or both.
199  */
200  if( ndims > 2 )
201  {
202  /* Mismatch implies a problem */
203  if ( FLAGS_NDIMS(pa->flags) != ndims )
204  return LW_FALSE;
205  /* Match means use the explicit dimensionality */
206  else
207  {
208  FLAGS_SET_Z(pa->flags, hasz);
209  FLAGS_SET_M(pa->flags, hasm);
210  }
211  }
212 
213  return LW_TRUE;
214 }
215 
216 
217 
221 POINT wkt_parser_coord_2(double c1, double c2)
222 {
223  POINT p;
224  p.flags = 0;
225  p.x = c1;
226  p.y = c2;
227  p.z = p.m = 0.0;
228  FLAGS_SET_Z(p.flags, 0);
229  FLAGS_SET_M(p.flags, 0);
230  return p;
231 }
232 
237 POINT wkt_parser_coord_3(double c1, double c2, double c3)
238 {
239  POINT p;
240  p.flags = 0;
241  p.x = c1;
242  p.y = c2;
243  p.z = c3;
244  p.m = 0;
245  FLAGS_SET_Z(p.flags, 1);
246  FLAGS_SET_M(p.flags, 0);
247  return p;
248 }
249 
252 POINT wkt_parser_coord_4(double c1, double c2, double c3, double c4)
253 {
254  POINT p;
255  p.flags = 0;
256  p.x = c1;
257  p.y = c2;
258  p.z = c3;
259  p.m = c4;
260  FLAGS_SET_Z(p.flags, 1);
261  FLAGS_SET_M(p.flags, 1);
262  return p;
263 }
264 
266 {
267  POINT4D pt;
268  LWDEBUG(4,"entered");
269 
270  /* Error on trouble */
271  if( ! pa )
272  {
274  return NULL;
275  }
276 
277  /* Check that the coordinate has the same dimesionality as the array */
278  if( FLAGS_NDIMS(p.flags) != FLAGS_NDIMS(pa->flags) )
279  {
280  ptarray_free(pa);
282  return NULL;
283  }
284 
285  /* While parsing the point arrays, XYM and XMZ points are both treated as XYZ */
286  pt.x = p.x;
287  pt.y = p.y;
288  if( FLAGS_GET_Z(pa->flags) )
289  pt.z = p.z;
290  if( FLAGS_GET_M(pa->flags) )
291  pt.m = p.m;
292  /* If the destination is XYM, we'll write the third coordinate to m */
293  if( FLAGS_GET_M(pa->flags) && ! FLAGS_GET_Z(pa->flags) )
294  pt.m = p.z;
295 
296  ptarray_append_point(pa, &pt, LW_TRUE); /* Allow duplicate points in array */
297  return pa;
298 }
299 
304 {
305  int ndims = FLAGS_NDIMS(p.flags);
306  POINTARRAY *pa = ptarray_construct_empty((ndims>2), (ndims>3), 4);
307  LWDEBUG(4,"entered");
308  if ( ! pa )
309  {
311  return NULL;
312  }
313  return wkt_parser_ptarray_add_coord(pa, p);
314 }
315 
320 LWGEOM* wkt_parser_point_new(POINTARRAY *pa, char *dimensionality)
321 {
322  uint8_t flags = wkt_dimensionality(dimensionality);
323  LWDEBUG(4,"entered");
324 
325  /* No pointarray means it is empty */
326  if( ! pa )
328 
329  /* If the number of dimensions is not consistent, we have a problem. */
330  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
331  {
332  ptarray_free(pa);
334  return NULL;
335  }
336 
337  /* Only one point allowed in our point array! */
338  if( pa->npoints != 1 )
339  {
340  ptarray_free(pa);
342  return NULL;
343  }
344 
346 }
347 
348 
354 LWGEOM* wkt_parser_linestring_new(POINTARRAY *pa, char *dimensionality)
355 {
356  uint8_t flags = wkt_dimensionality(dimensionality);
357  LWDEBUG(4,"entered");
358 
359  /* No pointarray means it is empty */
360  if( ! pa )
362 
363  /* If the number of dimensions is not consistent, we have a problem. */
364  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
365  {
366  ptarray_free(pa);
368  return NULL;
369  }
370 
371  /* Apply check for not enough points, if requested. */
373  {
374  ptarray_free(pa);
376  return NULL;
377  }
378 
380 }
381 
389 {
390  uint8_t flags = wkt_dimensionality(dimensionality);
391  LWDEBUG(4,"entered");
392 
393  /* No pointarray means it is empty */
394  if( ! pa )
396 
397  /* If the number of dimensions is not consistent, we have a problem. */
398  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
399  {
400  ptarray_free(pa);
402  return NULL;
403  }
404 
405  /* Apply check for not enough points, if requested. */
407  {
408  ptarray_free(pa);
410  return NULL;
411  }
412 
413  /* Apply check for odd number of points, if requested. */
415  {
416  ptarray_free(pa);
418  return NULL;
419  }
420 
422 }
423 
424 LWGEOM* wkt_parser_triangle_new(POINTARRAY *pa, char *dimensionality)
425 {
426  uint8_t flags = wkt_dimensionality(dimensionality);
427  LWDEBUG(4,"entered");
428 
429  /* No pointarray means it is empty */
430  if( ! pa )
432 
433  /* If the number of dimensions is not consistent, we have a problem. */
434  if( wkt_pointarray_dimensionality(pa, flags) == LW_FALSE )
435  {
436  ptarray_free(pa);
438  return NULL;
439  }
440 
441  /* Triangles need four points. */
442  if( (pa->npoints != 4) )
443  {
444  ptarray_free(pa);
446  return NULL;
447  }
448 
449  /* Triangles need closure. */
450  if( ! ptarray_is_closed_z(pa) )
451  {
452  ptarray_free(pa);
454  return NULL;
455  }
456 
458 }
459 
461 {
462  LWPOLY *poly = NULL;
463  LWDEBUG(4,"entered");
464 
465  /* No pointarray is a problem */
466  if( ! pa )
467  {
469  return NULL;
470  }
471 
473 
474  /* Error out if we can't build this polygon. */
475  if( ! poly )
476  {
478  return NULL;
479  }
480 
481  wkt_parser_polygon_add_ring(lwpoly_as_lwgeom(poly), pa, dimcheck);
482  return lwpoly_as_lwgeom(poly);
483 }
484 
486 {
487  LWDEBUG(4,"entered");
488 
489  /* Bad inputs are a problem */
490  if( ! (pa && poly) )
491  {
493  return NULL;
494  }
495 
496  /* Rings must agree on dimensionality */
497  if( FLAGS_NDIMS(poly->flags) != FLAGS_NDIMS(pa->flags) )
498  {
499  ptarray_free(pa);
500  lwgeom_free(poly);
502  return NULL;
503  }
504 
505  /* Apply check for minimum number of points, if requested. */
507  {
508  ptarray_free(pa);
509  lwgeom_free(poly);
511  return NULL;
512  }
513 
514  /* Apply check for not closed rings, if requested. */
516  ! (dimcheck == 'Z' ? ptarray_is_closed_z(pa) : ptarray_is_closed_2d(pa)) )
517  {
518  ptarray_free(pa);
519  lwgeom_free(poly);
521  return NULL;
522  }
523 
524  /* If something goes wrong adding a ring, error out. */
525  if ( LW_FAILURE == lwpoly_add_ring(lwgeom_as_lwpoly(poly), pa) )
526  {
527  ptarray_free(pa);
528  lwgeom_free(poly);
530  return NULL;
531  }
532  return poly;
533 }
534 
535 LWGEOM* wkt_parser_polygon_finalize(LWGEOM *poly, char *dimensionality)
536 {
537  uint8_t flags = wkt_dimensionality(dimensionality);
538  int flagdims = FLAGS_NDIMS(flags);
539  LWDEBUG(4,"entered");
540 
541  /* Null input implies empty return */
542  if( ! poly )
544 
545  /* If the number of dimensions are not consistent, we have a problem. */
546  if( flagdims > 2 )
547  {
548  if ( flagdims != FLAGS_NDIMS(poly->flags) )
549  {
550  lwgeom_free(poly);
552  return NULL;
553  }
554 
555  /* Harmonize the flags in the sub-components with the wkt flags */
556  if( LW_FAILURE == wkt_parser_set_dims(poly, flags) )
557  {
558  lwgeom_free(poly);
560  return NULL;
561  }
562  }
563 
564  return poly;
565 }
566 
568 {
569  LWGEOM *poly;
570  LWDEBUG(4,"entered");
571 
572  /* Toss error on null geometry input */
573  if( ! ring )
574  {
576  return NULL;
577  }
578 
579  /* Construct poly and add the ring. */
581  /* Return the result. */
582  return wkt_parser_curvepolygon_add_ring(poly,ring);
583 }
584 
586 {
587  LWDEBUG(4,"entered");
588 
589  /* Toss error on null input */
590  if( ! (ring && poly) )
591  {
593  LWDEBUG(4,"inputs are null");
594  return NULL;
595  }
596 
597  /* All the elements must agree on dimensionality */
598  if( FLAGS_NDIMS(poly->flags) != FLAGS_NDIMS(ring->flags) )
599  {
600  LWDEBUG(4,"dimensionality does not match");
601  lwgeom_free(ring);
602  lwgeom_free(poly);
604  return NULL;
605  }
606 
607  /* Apply check for minimum number of points, if requested. */
609  {
610  int vertices_needed = 3;
611 
612  if ( ring->type == LINETYPE )
613  vertices_needed = 4;
614 
615  if (lwgeom_count_vertices(ring) < vertices_needed)
616  {
617  LWDEBUG(4,"number of points is incorrect");
618  lwgeom_free(ring);
619  lwgeom_free(poly);
621  return NULL;
622  }
623  }
624 
625  /* Apply check for not closed rings, if requested. */
627  {
628  int is_closed = 1;
629  LWDEBUG(4,"checking ring closure");
630  switch ( ring->type )
631  {
632  case LINETYPE:
633  is_closed = lwline_is_closed(lwgeom_as_lwline(ring));
634  break;
635 
636  case CIRCSTRINGTYPE:
638  break;
639 
640  case COMPOUNDTYPE:
641  is_closed = lwcompound_is_closed(lwgeom_as_lwcompound(ring));
642  break;
643  }
644  if ( ! is_closed )
645  {
646  LWDEBUG(4,"ring is not closed");
647  lwgeom_free(ring);
648  lwgeom_free(poly);
650  return NULL;
651  }
652  }
653 
655  {
656  LWDEBUG(4,"failed to add ring");
657  lwgeom_free(ring);
658  lwgeom_free(poly);
660  return NULL;
661  }
662 
663  return poly;
664 }
665 
666 LWGEOM* wkt_parser_curvepolygon_finalize(LWGEOM *poly, char *dimensionality)
667 {
668  uint8_t flags = wkt_dimensionality(dimensionality);
669  int flagdims = FLAGS_NDIMS(flags);
670  LWDEBUG(4,"entered");
671 
672  /* Null input implies empty return */
673  if( ! poly )
675 
676  if ( flagdims > 2 )
677  {
678  /* If the number of dimensions are not consistent, we have a problem. */
679  if( flagdims != FLAGS_NDIMS(poly->flags) )
680  {
681  lwgeom_free(poly);
683  return NULL;
684  }
685 
686  /* Harmonize the flags in the sub-components with the wkt flags */
687  if( LW_FAILURE == wkt_parser_set_dims(poly, flags) )
688  {
689  lwgeom_free(poly);
691  return NULL;
692  }
693  }
694 
695  return poly;
696 }
697 
699 {
700  LWCOLLECTION *col;
701  LWGEOM **geoms;
702  static int ngeoms = 1;
703  LWDEBUG(4,"entered");
704 
705  /* Toss error on null geometry input */
706  if( ! geom )
707  {
709  return NULL;
710  }
711 
712  /* Create our geometry array */
713  geoms = lwalloc(sizeof(LWGEOM*) * ngeoms);
714  geoms[0] = geom;
715 
716  /* Make a new collection */
717  col = lwcollection_construct(COLLECTIONTYPE, SRID_UNKNOWN, NULL, ngeoms, geoms);
718 
719  /* Return the result. */
720  return lwcollection_as_lwgeom(col);
721 }
722 
723 
725 {
726  LWCOLLECTION *col;
727  LWGEOM **geoms;
728  static int ngeoms = 1;
729  LWDEBUG(4,"entered");
730 
731  /* Toss error on null geometry input */
732  if( ! geom )
733  {
735  return NULL;
736  }
737 
738  /* Elements of a compoundcurve cannot be empty, because */
739  /* empty things can't join up and form a ring */
740  if ( lwgeom_is_empty(geom) )
741  {
742  lwgeom_free(geom);
744  return NULL;
745  }
746 
747  /* Create our geometry array */
748  geoms = lwalloc(sizeof(LWGEOM*) * ngeoms);
749  geoms[0] = geom;
750 
751  /* Make a new collection */
752  col = lwcollection_construct(COLLECTIONTYPE, SRID_UNKNOWN, NULL, ngeoms, geoms);
753 
754  /* Return the result. */
755  return lwcollection_as_lwgeom(col);
756 }
757 
758 
760 {
761  LWDEBUG(4,"entered");
762 
763  /* Toss error on null geometry input */
764  if( ! (geom && col) )
765  {
767  return NULL;
768  }
769 
770  /* All the elements must agree on dimensionality */
771  if( FLAGS_NDIMS(col->flags) != FLAGS_NDIMS(geom->flags) )
772  {
773  lwgeom_free(col);
774  lwgeom_free(geom);
776  return NULL;
777  }
778 
779  if( LW_FAILURE == lwcompound_add_lwgeom((LWCOMPOUND*)col, geom) )
780  {
781  lwgeom_free(col);
782  lwgeom_free(geom);
784  return NULL;
785  }
786 
787  return col;
788 }
789 
790 
792 {
793  LWDEBUG(4,"entered");
794 
795  /* Toss error on null geometry input */
796  if( ! (geom && col) )
797  {
799  return NULL;
800  }
801 
803 }
804 
805 LWGEOM* wkt_parser_collection_finalize(int lwtype, LWGEOM *geom, char *dimensionality)
806 {
807  uint8_t flags = wkt_dimensionality(dimensionality);
808  int flagdims = FLAGS_NDIMS(flags);
809 
810  /* No geometry means it is empty */
811  if( ! geom )
812  {
814  }
815 
816  /* There are 'Z' or 'M' tokens in the signature */
817  if ( flagdims > 2 )
818  {
820  int i;
821 
822  for ( i = 0 ; i < col->ngeoms; i++ )
823  {
824  LWGEOM *subgeom = col->geoms[i];
825  if ( FLAGS_NDIMS(flags) != FLAGS_NDIMS(subgeom->flags) &&
826  ! lwgeom_is_empty(subgeom) )
827  {
828  lwgeom_free(geom);
830  return NULL;
831  }
832 
833  if ( lwtype == COLLECTIONTYPE &&
834  ( (FLAGS_GET_Z(flags) != FLAGS_GET_Z(subgeom->flags)) ||
835  (FLAGS_GET_M(flags) != FLAGS_GET_M(subgeom->flags)) ) &&
836  ! lwgeom_is_empty(subgeom) )
837  {
838  lwgeom_free(geom);
840  return NULL;
841  }
842  }
843 
844  /* Harmonize the collection dimensionality */
845  if( LW_FAILURE == wkt_parser_set_dims(geom, flags) )
846  {
847  lwgeom_free(geom);
849  return NULL;
850  }
851  }
852 
853  /* Set the collection type */
854  geom->type = lwtype;
855 
856  return geom;
857 }
858 
859 void wkt_parser_geometry_new(LWGEOM *geom, int srid)
860 {
861  LWDEBUG(4,"entered");
862  LWDEBUGF(4,"geom %p",geom);
863  LWDEBUGF(4,"srid %d",srid);
864 
865  if ( geom == NULL )
866  {
867  lwerror("Parsed geometry is null!");
868  return;
869  }
870 
871  if ( srid != SRID_UNKNOWN && srid < SRID_MAXIMUM )
872  lwgeom_set_srid(geom, srid);
873  else
875 
876  global_parser_result.geom = geom;
877 }
878 
880 {
881  memset(parser_result, 0, sizeof(LWGEOM_PARSER_RESULT));
882 }
883 
884 
886 {
887  if ( parser_result->geom )
888  {
889  lwgeom_free(parser_result->geom);
890  parser_result->geom = 0;
891  }
892  if ( parser_result->serialized_lwgeom )
893  {
894  lwfree(parser_result->serialized_lwgeom );
895  parser_result->serialized_lwgeom = 0;
896  }
897  /* We don't free parser_result->message because
898  it is a const *char */
899 }
900 
901 /*
902 * Public function used for easy access to the parser.
903 */
904 LWGEOM *lwgeom_from_wkt(const char *wkt, const char check)
905 {
907 
908  if( LW_FAILURE == lwgeom_parse_wkt(&r, (char*)wkt, check) )
909  {
910  lwerror(r.message);
911  return NULL;
912  }
913 
914  return r.geom;
915 }
916 
917 
double x
Definition: lwin_wkt.h:35
double x
Definition: liblwgeom.h:351
#define LINETYPE
Definition: liblwgeom.h:85
LWGEOM * wkt_parser_polygon_finalize(LWGEOM *poly, char *dimensionality)
Definition: lwin_wkt.c:535
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:378
LWGEOM * wkt_parser_triangle_new(POINTARRAY *pa, char *dimensionality)
Definition: lwin_wkt.c:424
double m
Definition: lwin_wkt.h:38
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:101
LWLINE * lwline_construct_empty(int srid, char hasz, char hasm)
Definition: lwline.c:64
LWGEOM * wkt_parser_point_new(POINTARRAY *pa, char *dimensionality)
Create a new point.
Definition: lwin_wkt.c:320
double m
Definition: liblwgeom.h:351
LWGEOM * wkt_parser_collection_add_geom(LWGEOM *col, LWGEOM *geom)
Definition: lwin_wkt.c:791
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
Definition: lwcollection.c:43
#define PARSER_ERROR_INCONTINUOUS
Definition: liblwgeom.h:2014
char * r
Definition: cu_in_wkt.c:24
LWGEOM * wkt_parser_polygon_add_ring(LWGEOM *poly, POINTARRAY *pa, char dimcheck)
Definition: lwin_wkt.c:485
void lwfree(void *mem)
Definition: lwutil.c:242
LWTRIANGLE * lwtriangle_construct_empty(int srid, char hasz, char hasm)
Definition: lwtriangle.c:58
LWGEOM ** rings
Definition: liblwgeom.h:534
int npoints
Definition: liblwgeom.h:370
#define LW_PARSER_CHECK_MINPOINTS
Parser check flags.
Definition: liblwgeom.h:1980
LWGEOM * wkt_parser_curvepolygon_new(LWGEOM *ring)
Definition: lwin_wkt.c:567
int wkt_lexer_read_srid(char *str)
Read the SRID number from an SRID=<> string.
Definition: lwin_wkt.c:61
#define POLYGONTYPE
Definition: liblwgeom.h:86
LWGEOM * wkt_parser_circularstring_new(POINTARRAY *pa, char *dimensionality)
Create a new circularstring.
Definition: lwin_wkt.c:388
uint8_t flags
Definition: liblwgeom.h:396
LWGEOM * lwcircstring_as_lwgeom(const LWCIRCSTRING *obj)
Definition: lwgeom.c:237
#define CURVEPOLYTYPE
Definition: liblwgeom.h:93
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:1063
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:330
#define COMPOUNDTYPE
Definition: liblwgeom.h:92
#define LW_SUCCESS
Definition: liblwgeom.h:79
void lwgeom_parser_result_free(LWGEOM_PARSER_RESULT *parser_result)
Definition: lwin_wkt.c:885
int ptarray_is_closed_z(const POINTARRAY *pa)
Definition: ptarray.c:720
LWGEOM * wkt_parser_collection_new(LWGEOM *geom)
Definition: lwin_wkt.c:698
LWCURVEPOLY * lwgeom_as_lwcurvepoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:129
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
#define TRIANGLETYPE
Definition: liblwgeom.h:97
int lwcompound_is_closed(const LWCOMPOUND *curve)
Definition: lwcompound.c:35
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:138
LWGEOM_PARSER_RESULT global_parser_result
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:133
POINTARRAY * point
Definition: liblwgeom.h:410
double y
Definition: lwin_wkt.h:36
#define PARSER_ERROR_MIXDIMS
Definition: liblwgeom.h:2011
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:694
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:252
#define LW_FAILURE
Definition: liblwgeom.h:78
LWGEOM * wkt_parser_linestring_new(POINTARRAY *pa, char *dimensionality)
Create a new linestring.
Definition: lwin_wkt.c:354
#define FLAGS_SET_Z(flags, value)
Definition: liblwgeom.h:145
#define LW_PARSER_CHECK_ODD
Definition: liblwgeom.h:1981
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:262
LWCIRCSTRING * lwcircstring_construct_empty(int srid, char hasz, char hasm)
Definition: lwcircstring.c:80
LWGEOM * wkt_parser_curvepolygon_finalize(LWGEOM *poly, char *dimensionality)
Definition: lwin_wkt.c:666
LWGEOM * wkt_parser_collection_finalize(int lwtype, LWGEOM *geom, char *dimensionality)
Definition: lwin_wkt.c:805
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_FALSE, 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:303
#define LW_FALSE
Definition: liblwgeom.h:76
POINTARRAY * wkt_parser_ptarray_add_coord(POINTARRAY *pa, POINT p)
Definition: lwin_wkt.c:265
uint8_t flags
Definition: liblwgeom.h:368
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:75
Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM...
Definition: liblwgeom.h:1992
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
LWGEOM ** geoms
Definition: liblwgeom.h:508
LWGEOM * lwgeom_from_wkt(const char *wkt, const char check)
Definition: lwin_wkt.c:904
int lwcircstring_is_closed(const LWCIRCSTRING *curve)
Definition: lwcircstring.c:268
static uint8_t wkt_dimensionality(char *dimensionality)
Definition: lwin_wkt.c:75
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:187
POINTARRAY ** rings
Definition: liblwgeom.h:456
double z
Definition: lwin_wkt.h:37
int lwtype_is_collection(uint8_t type)
Determine whether a type number is a collection or not.
Definition: lwgeom.c:1012
#define PARSER_ERROR_MOREPOINTS
Definition: liblwgeom.h:2008
LWCURVEPOLY * lwcurvepoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwcurvepoly.c:36
LWCOMPOUND * lwgeom_as_lwcompound(const LWGEOM *lwgeom)
Definition: lwgeom.c:120
int nrings
Definition: liblwgeom.h:454
LWGEOM * lwtriangle_as_lwgeom(const LWTRIANGLE *obj)
Definition: lwgeom.c:257
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:139
#define PARSER_ERROR_LESSPOINTS
Definition: liblwgeom.h:2016
double z
Definition: liblwgeom.h:351
LWTRIANGLE * lwtriangle_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwtriangle.c:40
Definition: lwin_wkt.h:32
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:102
LWCIRCSTRING * lwcircstring_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwcircstring.c:51
LWCIRCSTRING * lwgeom_as_lwcircstring(const LWGEOM *lwgeom)
Definition: lwgeom.c:111
#define PARSER_ERROR_ODDPOINTS
Definition: liblwgeom.h:2009
POINT wkt_parser_coord_2(double c1, double c2)
Build a 2d coordinate.
Definition: lwin_wkt.c:221
#define PARSER_ERROR_UNCLOSED
Definition: liblwgeom.h:2010
LWGEOM * wkt_parser_compound_add_geom(LWGEOM *col, LWGEOM *geom)
Definition: lwin_wkt.c:759
LWGEOM * wkt_parser_polygon_new(POINTARRAY *pa, char dimcheck)
Definition: lwin_wkt.c:460
const char * parser_error_messages[]
Definition: lwin_wkt.c:37
void lwgeom_parser_result_init(LWGEOM_PARSER_RESULT *parser_result)
Definition: lwin_wkt.c:879
POINT wkt_parser_coord_3(double c1, double c2, double c3)
Note, if this is an XYM coordinate we&#39;ll have to fix it later when we build the object itself and hav...
Definition: lwin_wkt.c:237
#define PARSER_ERROR_TRIANGLEPOINTS
Definition: liblwgeom.h:2015
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition: lwgeom.c:156
int lwline_is_closed(const LWLINE *line)
Definition: lwline.c:468
#define SET_PARSER_ERROR(errno)
Definition: lwin_wkt.c:52
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:84
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:139
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:140
uint8_t type
Definition: liblwgeom.h:395
int lwcurvepoly_add_ring(LWCURVEPOLY *poly, LWGEOM *ring)
Add a ring, allocating extra space if necessary.
Definition: lwcurvepoly.c:72
void wkt_parser_geometry_new(LWGEOM *geom, int srid)
Definition: lwin_wkt.c:859
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:267
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:242
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition: lwpoly.c:227
LWGEOM * wkt_parser_curvepolygon_add_ring(LWGEOM *poly, LWGEOM *ring)
Definition: lwin_wkt.c:585
#define SRID_MAXIMUM
Maximum allowed SRID value in serialized geometry.
Definition: liblwgeom.h:178
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:91
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:111
void * lwalloc(size_t size)
Definition: lwutil.c:227
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:1310
int lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1153
double y
Definition: liblwgeom.h:351
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:151
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:187
static int wkt_pointarray_dimensionality(POINTARRAY *pa, uint8_t flags)
Read the dimensionality from a flag, if provided.
Definition: lwin_wkt.c:183
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:102
#define LW_PARSER_CHECK_CLOSURE
Definition: liblwgeom.h:1982
uint8_t flags
Definition: lwin_wkt.h:34
#define PARSER_ERROR_OTHER
Definition: liblwgeom.h:2017
int lwcompound_add_lwgeom(LWCOMPOUND *comp, LWGEOM *geom)
Add a component, allocating extra space if necessary.
Definition: lwcompound.c:88
#define COLLECTIONTYPE
Definition: liblwgeom.h:90
POINT wkt_parser_coord_4(double c1, double c2, double c3, double c4)
Definition: lwin_wkt.c:252
#define FLAGS_SET_M(flags, value)
Definition: liblwgeom.h:146
LWGEOM * wkt_parser_compound_new(LWGEOM *geom)
Definition: lwin_wkt.c:724
POINTARRAY * points
Definition: liblwgeom.h:421
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:232