PostGIS  3.1.6dev-r@@SVN_REVISION@@
lwout_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) 2009 Paul Ramsey <pramsey@cleverelephant.ca>
22  *
23  **********************************************************************/
24 
25 
26 #include "liblwgeom_internal.h"
27 #include "lwgeom_log.h"
28 #include "stringbuffer.h"
29 
30 static void lwgeom_to_wkt_sb(const LWGEOM *geom, stringbuffer_t *sb, int precision, uint8_t variant);
31 
32 #define buffer_size 128
33 
34 /*
35 * ISO format uses both Z and M qualifiers.
36 * Extended format only uses an M qualifier for 3DM variants, where it is not
37 * clear what the third dimension represents.
38 * SFSQL format never has more than two dimensions, so no qualifiers.
39 */
40 static void dimension_qualifiers_to_wkt_sb(const LWGEOM *geom, stringbuffer_t *sb, uint8_t variant)
41 {
42 
43  /* Extended WKT: POINTM(0 0 0) */
44 #if 0
45  if ( (variant & WKT_EXTENDED) && ! (variant & WKT_IS_CHILD) && FLAGS_GET_M(geom->flags) && (!FLAGS_GET_Z(geom->flags)) )
46 #else
47  if ( (variant & WKT_EXTENDED) && FLAGS_GET_M(geom->flags) && (!FLAGS_GET_Z(geom->flags)) )
48 #endif
49  {
50  stringbuffer_append_len(sb, "M", 1); /* "M" */
51  return;
52  }
53 
54  /* ISO WKT: POINT ZM (0 0 0 0) */
55  if ( (variant & WKT_ISO) && (FLAGS_NDIMS(geom->flags) > 2) )
56  {
57  stringbuffer_append_len(sb, " ", 1);
58  if ( FLAGS_GET_Z(geom->flags) )
59  stringbuffer_append_len(sb, "Z", 1);
60  if ( FLAGS_GET_M(geom->flags) )
61  stringbuffer_append_len(sb, "M", 1);
62  stringbuffer_append_len(sb, " ", 1);
63  }
64 }
65 
66 /*
67 * Write an empty token out, padding with a space if
68 * necessary.
69 */
71 {
72  if ( ! strchr(" ,(", stringbuffer_lastchar(sb)) ) /* "EMPTY" */
73  {
74  stringbuffer_append_len(sb, " ", 1);
75  }
76  stringbuffer_append_len(sb, "EMPTY", 5);
77 }
78 
79 inline static void
80 coordinate_to_wkt_sb(double *coords, stringbuffer_t *sb, uint32_t dimensions, int precision)
81 {
82  uint32_t d = 0;
83  stringbuffer_append_double(sb, coords[d], precision);
84 
85  for (d = 1; d < dimensions; d++)
86  {
87  stringbuffer_append_len(sb, " ", 1);
88  stringbuffer_append_double(sb, coords[d], precision);
89  }
90 }
91 
92 /*
93 * Point array is a list of coordinates. Depending on output mode,
94 * we may suppress some dimensions. ISO and Extended formats include
95 * all dimensions. Standard OGC output only includes X/Y coordinates.
96 */
97 static void ptarray_to_wkt_sb(const POINTARRAY *ptarray, stringbuffer_t *sb, int precision, uint8_t variant)
98 {
99  /* OGC only includes X/Y */
100  uint32_t dimensions = 2;
101 
102  /* ISO and extended formats include all dimensions */
103  if ( variant & ( WKT_ISO | WKT_EXTENDED ) )
104  dimensions = FLAGS_NDIMS(ptarray->flags);
105 
106  stringbuffer_makeroom(sb, 2 + ((OUT_MAX_BYTES_DOUBLE + 1) * dimensions * ptarray->npoints));
107  /* Opening paren? */
108  if ( ! (variant & WKT_NO_PARENS) )
109  stringbuffer_append_len(sb, "(", 1);
110 
111  /* Digits and commas */
112  if (ptarray->npoints)
113  {
114  uint32_t i = 0;
115 
116  double *dbl_ptr = (double *)getPoint_internal(ptarray, i);
117  coordinate_to_wkt_sb(dbl_ptr, sb, dimensions, precision);
118 
119  for (i = 1; i < ptarray->npoints; i++)
120  {
121  stringbuffer_append_len(sb, ",", 1);
122  dbl_ptr = (double *)getPoint_internal(ptarray, i);
123  coordinate_to_wkt_sb(dbl_ptr, sb, dimensions, precision);
124  }
125  }
126 
127  /* Closing paren? */
128  if ( ! (variant & WKT_NO_PARENS) )
129  stringbuffer_append_len(sb, ")", 1);
130 }
131 
132 /*
133 * A four-dimensional point will have different outputs depending on variant.
134 * ISO: POINT ZM (0 0 0 0)
135 * Extended: POINT(0 0 0 0)
136 * OGC: POINT(0 0)
137 * A three-dimensional m-point will have different outputs too.
138 * ISO: POINT M (0 0 0)
139 * Extended: POINTM(0 0 0)
140 * OGC: POINT(0 0)
141 */
142 static void lwpoint_to_wkt_sb(const LWPOINT *pt, stringbuffer_t *sb, int precision, uint8_t variant)
143 {
144  if ( ! (variant & WKT_NO_TYPE) )
145  {
146  stringbuffer_append_len(sb, "POINT", 5); /* "POINT" */
148  }
149 
150  if ( lwpoint_is_empty(pt) )
151  {
152  empty_to_wkt_sb(sb);
153  return;
154  }
155 
157 }
158 
159 /*
160 * LINESTRING(0 0 0, 1 1 1)
161 */
162 static void lwline_to_wkt_sb(const LWLINE *line, stringbuffer_t *sb, int precision, uint8_t variant)
163 {
164  if ( ! (variant & WKT_NO_TYPE) )
165  {
166  stringbuffer_append_len(sb, "LINESTRING", 10); /* "LINESTRING" */
168  }
169  if ( lwline_is_empty(line) )
170  {
171  empty_to_wkt_sb(sb);
172  return;
173  }
174 
176 }
177 
178 /*
179 * POLYGON(0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)
180 */
181 static void lwpoly_to_wkt_sb(const LWPOLY *poly, stringbuffer_t *sb, int precision, uint8_t variant)
182 {
183  uint32_t i = 0;
184  if ( ! (variant & WKT_NO_TYPE) )
185  {
186  stringbuffer_append_len(sb, "POLYGON", 7); /* "POLYGON" */
188  }
189  if ( lwpoly_is_empty(poly) )
190  {
191  empty_to_wkt_sb(sb);
192  return;
193  }
194 
195  stringbuffer_append_len(sb, "(", 1);
196  for ( i = 0; i < poly->nrings; i++ )
197  {
198  if ( i > 0 )
199  stringbuffer_append_len(sb, ",", 1);
200  ptarray_to_wkt_sb(poly->rings[i], sb, precision, variant);
201  }
202  stringbuffer_append_len(sb, ")", 1);
203 }
204 
205 /*
206 * CIRCULARSTRING
207 */
208 static void lwcircstring_to_wkt_sb(const LWCIRCSTRING *circ, stringbuffer_t *sb, int precision, uint8_t variant)
209 {
210  if ( ! (variant & WKT_NO_TYPE) )
211  {
212  stringbuffer_append_len(sb, "CIRCULARSTRING", 14); /* "CIRCULARSTRING" */
214  }
215  if ( lwcircstring_is_empty(circ) )
216  {
217  empty_to_wkt_sb(sb);
218  return;
219  }
221 }
222 
223 
224 /*
225 * Multi-points do not wrap their sub-members in parens, unlike other multi-geometries.
226 * MULTPOINT(0 0, 1 1) instead of MULTIPOINT((0 0),(1 1))
227 */
228 static void lwmpoint_to_wkt_sb(const LWMPOINT *mpoint, stringbuffer_t *sb, int precision, uint8_t variant)
229 {
230  uint32_t i = 0;
231  if ( ! (variant & WKT_NO_TYPE) )
232  {
233  stringbuffer_append_len(sb, "MULTIPOINT", 10); /* "MULTIPOINT" */
235  }
236  if ( mpoint->ngeoms < 1 )
237  {
238  empty_to_wkt_sb(sb);
239  return;
240  }
241  stringbuffer_append_len(sb, "(", 1);
242  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
243  for ( i = 0; i < mpoint->ngeoms; i++ )
244  {
245  if ( i > 0 )
246  stringbuffer_append_len(sb, ",", 1);
247  /* We don't want type strings or parens on our subgeoms */
249  }
250  stringbuffer_append_len(sb, ")", 1);
251 }
252 
253 /*
254 * MULTILINESTRING
255 */
256 static void lwmline_to_wkt_sb(const LWMLINE *mline, stringbuffer_t *sb, int precision, uint8_t variant)
257 {
258  uint32_t i = 0;
259 
260  if ( ! (variant & WKT_NO_TYPE) )
261  {
262  stringbuffer_append_len(sb, "MULTILINESTRING", 15); /* "MULTILINESTRING" */
264  }
265  if ( mline->ngeoms < 1 )
266  {
267  empty_to_wkt_sb(sb);
268  return;
269  }
270 
271  stringbuffer_append_len(sb, "(", 1);
272  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
273  for ( i = 0; i < mline->ngeoms; i++ )
274  {
275  if ( i > 0 )
276  stringbuffer_append_len(sb, ",", 1);
277  /* We don't want type strings on our subgeoms */
278  lwline_to_wkt_sb(mline->geoms[i], sb, precision, variant | WKT_NO_TYPE );
279  }
280  stringbuffer_append_len(sb, ")", 1);
281 }
282 
283 /*
284 * MULTIPOLYGON
285 */
286 static void lwmpoly_to_wkt_sb(const LWMPOLY *mpoly, stringbuffer_t *sb, int precision, uint8_t variant)
287 {
288  uint32_t i = 0;
289 
290  if ( ! (variant & WKT_NO_TYPE) )
291  {
292  stringbuffer_append_len(sb, "MULTIPOLYGON", 12); /* "MULTIPOLYGON" */
294  }
295  if ( mpoly->ngeoms < 1 )
296  {
297  empty_to_wkt_sb(sb);
298  return;
299  }
300 
301  stringbuffer_append_len(sb, "(", 1);
302  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
303  for ( i = 0; i < mpoly->ngeoms; i++ )
304  {
305  if ( i > 0 )
306  stringbuffer_append_len(sb, ",", 1);
307  /* We don't want type strings on our subgeoms */
308  lwpoly_to_wkt_sb(mpoly->geoms[i], sb, precision, variant | WKT_NO_TYPE );
309  }
310  stringbuffer_append_len(sb, ")", 1);
311 }
312 
313 /*
314 * Compound curves provide type information for their curved sub-geometries
315 * but not their linestring sub-geometries.
316 * COMPOUNDCURVE((0 0, 1 1), CURVESTRING(1 1, 2 2, 3 3))
317 */
318 static void lwcompound_to_wkt_sb(const LWCOMPOUND *comp, stringbuffer_t *sb, int precision, uint8_t variant)
319 {
320  uint32_t i = 0;
321 
322  if ( ! (variant & WKT_NO_TYPE) )
323  {
324  stringbuffer_append_len(sb, "COMPOUNDCURVE", 13); /* "COMPOUNDCURVE" */
326  }
327  if ( comp->ngeoms < 1 )
328  {
329  empty_to_wkt_sb(sb);
330  return;
331  }
332 
333  stringbuffer_append_len(sb, "(", 1);
334  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
335  for ( i = 0; i < comp->ngeoms; i++ )
336  {
337  int type = comp->geoms[i]->type;
338  if ( i > 0 )
339  stringbuffer_append_len(sb, ",", 1);
340  /* Linestring subgeoms don't get type identifiers */
341  if ( type == LINETYPE )
342  {
344  }
345  /* But circstring subgeoms *do* get type identifiers */
346  else if ( type == CIRCSTRINGTYPE )
347  {
349  }
350  else
351  {
352  lwerror("lwcompound_to_wkt_sb: Unknown type received %d - %s", type, lwtype_name(type));
353  }
354  }
355  stringbuffer_append_len(sb, ")", 1);
356 }
357 
358 /*
359 * Curve polygons provide type information for their curved rings
360 * but not their linestring rings.
361 * CURVEPOLYGON((0 0, 1 1, 0 1, 0 0), CURVESTRING(0 0, 1 1, 0 1, 0.5 1, 0 0))
362 */
363 static void lwcurvepoly_to_wkt_sb(const LWCURVEPOLY *cpoly, stringbuffer_t *sb, int precision, uint8_t variant)
364 {
365  uint32_t i = 0;
366 
367  if ( ! (variant & WKT_NO_TYPE) )
368  {
369  stringbuffer_append_len(sb, "CURVEPOLYGON", 12); /* "CURVEPOLYGON" */
371  }
372  if ( cpoly->nrings < 1 )
373  {
374  empty_to_wkt_sb(sb);
375  return;
376  }
377  stringbuffer_append_len(sb, "(", 1);
378  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
379  for ( i = 0; i < cpoly->nrings; i++ )
380  {
381  int type = cpoly->rings[i]->type;
382  if ( i > 0 )
383  stringbuffer_append_len(sb, ",", 1);
384  switch (type)
385  {
386  case LINETYPE:
387  /* Linestring subgeoms don't get type identifiers */
389  break;
390  case CIRCSTRINGTYPE:
391  /* But circstring subgeoms *do* get type identifiers */
393  break;
394  case COMPOUNDTYPE:
395  /* And compoundcurve subgeoms *do* get type identifiers */
397  break;
398  default:
399  lwerror("lwcurvepoly_to_wkt_sb: Unknown type received %d - %s", type, lwtype_name(type));
400  }
401  }
402  stringbuffer_append_len(sb, ")", 1);
403 }
404 
405 
406 /*
407 * Multi-curves provide type information for their curved sub-geometries
408 * but not their linear sub-geometries.
409 * MULTICURVE((0 0, 1 1), CURVESTRING(0 0, 1 1, 2 2))
410 */
411 static void lwmcurve_to_wkt_sb(const LWMCURVE *mcurv, stringbuffer_t *sb, int precision, uint8_t variant)
412 {
413  uint32_t i = 0;
414 
415  if ( ! (variant & WKT_NO_TYPE) )
416  {
417  stringbuffer_append_len(sb, "MULTICURVE", 10); /* "MULTICURVE" */
419  }
420  if ( mcurv->ngeoms < 1 )
421  {
422  empty_to_wkt_sb(sb);
423  return;
424  }
425  stringbuffer_append_len(sb, "(", 1);
426  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
427  for ( i = 0; i < mcurv->ngeoms; i++ )
428  {
429  int type = mcurv->geoms[i]->type;
430  if ( i > 0 )
431  stringbuffer_append_len(sb, ",", 1);
432  switch (type)
433  {
434  case LINETYPE:
435  /* Linestring subgeoms don't get type identifiers */
437  break;
438  case CIRCSTRINGTYPE:
439  /* But circstring subgeoms *do* get type identifiers */
441  break;
442  case COMPOUNDTYPE:
443  /* And compoundcurve subgeoms *do* get type identifiers */
445  break;
446  default:
447  lwerror("lwmcurve_to_wkt_sb: Unknown type received %d - %s", type, lwtype_name(type));
448  }
449  }
450  stringbuffer_append_len(sb, ")", 1);
451 }
452 
453 
454 /*
455 * Multi-surfaces provide type information for their curved sub-geometries
456 * but not their linear sub-geometries.
457 * MULTISURFACE(((0 0, 1 1, 1 0, 0 0)), CURVEPOLYGON(CURVESTRING(0 0, 1 1, 2 2, 0 1, 0 0)))
458 */
459 static void lwmsurface_to_wkt_sb(const LWMSURFACE *msurf, stringbuffer_t *sb, int precision, uint8_t variant)
460 {
461  uint32_t i = 0;
462 
463  if ( ! (variant & WKT_NO_TYPE) )
464  {
465  stringbuffer_append_len(sb, "MULTISURFACE", 12); /* "MULTISURFACE" */
467  }
468  if ( msurf->ngeoms < 1 )
469  {
470  empty_to_wkt_sb(sb);
471  return;
472  }
473  stringbuffer_append_len(sb, "(", 1);
474  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
475  for ( i = 0; i < msurf->ngeoms; i++ )
476  {
477  int type = msurf->geoms[i]->type;
478  if ( i > 0 )
479  stringbuffer_append_len(sb, ",", 1);
480  switch (type)
481  {
482  case POLYGONTYPE:
483  /* Linestring subgeoms don't get type identifiers */
485  break;
486  case CURVEPOLYTYPE:
487  /* But circstring subgeoms *do* get type identifiers */
489  break;
490  default:
491  lwerror("lwmsurface_to_wkt_sb: Unknown type received %d - %s", type, lwtype_name(type));
492  }
493  }
494  stringbuffer_append_len(sb, ")", 1);
495 }
496 
497 /*
498 * Geometry collections provide type information for all their curved sub-geometries
499 * but not their linear sub-geometries.
500 * GEOMETRYCOLLECTION(POLYGON((0 0, 1 1, 1 0, 0 0)), CURVEPOLYGON(CURVESTRING(0 0, 1 1, 2 2, 0 1, 0 0)))
501 */
502 static void lwcollection_to_wkt_sb(const LWCOLLECTION *collection, stringbuffer_t *sb, int precision, uint8_t variant)
503 {
504  uint32_t i = 0;
505 
506  if ( ! (variant & WKT_NO_TYPE) )
507  {
508  stringbuffer_append_len(sb, "GEOMETRYCOLLECTION", 18); /* "GEOMETRYCOLLECTION" */
509  dimension_qualifiers_to_wkt_sb((LWGEOM*)collection, sb, variant);
510  }
511  if ( collection->ngeoms < 1 )
512  {
513  empty_to_wkt_sb(sb);
514  return;
515  }
516  stringbuffer_append_len(sb, "(", 1);
517  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are children */
518  for ( i = 0; i < collection->ngeoms; i++ )
519  {
520  if ( i > 0 )
521  stringbuffer_append_len(sb, ",", 1);
522  lwgeom_to_wkt_sb((LWGEOM*)collection->geoms[i], sb, precision, variant );
523  }
524  stringbuffer_append_len(sb, ")", 1);
525 }
526 
527 /*
528 * TRIANGLE
529 */
530 static void lwtriangle_to_wkt_sb(const LWTRIANGLE *tri, stringbuffer_t *sb, int precision, uint8_t variant)
531 {
532  if ( ! (variant & WKT_NO_TYPE) )
533  {
534  stringbuffer_append_len(sb, "TRIANGLE", 8); /* "TRIANGLE" */
536  }
537  if ( lwtriangle_is_empty(tri) )
538  {
539  empty_to_wkt_sb(sb);
540  return;
541  }
542 
543  stringbuffer_append_len(sb, "(", 1); /* Triangles have extraneous brackets */
545  stringbuffer_append_len(sb, ")", 1);
546 }
547 
548 /*
549 * TIN
550 */
551 static void lwtin_to_wkt_sb(const LWTIN *tin, stringbuffer_t *sb, int precision, uint8_t variant)
552 {
553  uint32_t i = 0;
554 
555  if ( ! (variant & WKT_NO_TYPE) )
556  {
557  stringbuffer_append_len(sb, "TIN", 3); /* "TIN" */
559  }
560  if ( tin->ngeoms < 1 )
561  {
562  empty_to_wkt_sb(sb);
563  return;
564  }
565 
566  stringbuffer_append_len(sb, "(", 1);
567  for ( i = 0; i < tin->ngeoms; i++ )
568  {
569  if ( i > 0 )
570  stringbuffer_append_len(sb, ",", 1);
571  /* We don't want type strings on our subgeoms */
573  }
574  stringbuffer_append_len(sb, ")", 1);
575 }
576 
577 /*
578 * POLYHEDRALSURFACE
579 */
580 static void lwpsurface_to_wkt_sb(const LWPSURFACE *psurf, stringbuffer_t *sb, int precision, uint8_t variant)
581 {
582  uint32_t i = 0;
583 
584  if ( ! (variant & WKT_NO_TYPE) )
585  {
586  stringbuffer_append_len(sb, "POLYHEDRALSURFACE", 17); /* "POLYHEDRALSURFACE" */
588  }
589  if ( psurf->ngeoms < 1 )
590  {
591  empty_to_wkt_sb(sb);
592  return;
593  }
594 
595  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
596 
597  stringbuffer_append_len(sb, "(", 1);
598  for ( i = 0; i < psurf->ngeoms; i++ )
599  {
600  if ( i > 0 )
601  stringbuffer_append_len(sb, ",", 1);
602  /* We don't want type strings on our subgeoms */
603  lwpoly_to_wkt_sb(psurf->geoms[i], sb, precision, variant | WKT_NO_TYPE );
604  }
605  stringbuffer_append_len(sb, ")", 1);
606 }
607 
608 
609 /*
610 * Generic GEOMETRY
611 */
612 static void lwgeom_to_wkt_sb(const LWGEOM *geom, stringbuffer_t *sb, int precision, uint8_t variant)
613 {
614  LWDEBUGF(4, "lwgeom_to_wkt_sb: type %s, hasz %d, hasm %d",
615  lwtype_name(geom->type), (geom->type),
616  FLAGS_GET_Z(geom->flags)?1:0, FLAGS_GET_M(geom->flags)?1:0);
617 
618  switch (geom->type)
619  {
620  case POINTTYPE:
622  break;
623  case LINETYPE:
625  break;
626  case POLYGONTYPE:
628  break;
629  case MULTIPOINTTYPE:
631  break;
632  case MULTILINETYPE:
634  break;
635  case MULTIPOLYGONTYPE:
637  break;
638  case COLLECTIONTYPE:
640  break;
641  case CIRCSTRINGTYPE:
643  break;
644  case COMPOUNDTYPE:
646  break;
647  case CURVEPOLYTYPE:
649  break;
650  case MULTICURVETYPE:
652  break;
653  case MULTISURFACETYPE:
655  break;
656  case TRIANGLETYPE:
658  break;
659  case TINTYPE:
660  lwtin_to_wkt_sb((LWTIN*)geom, sb, precision, variant);
661  break;
664  break;
665  default:
666  lwerror("lwgeom_to_wkt_sb: Type %d - %s unsupported.",
667  geom->type, lwtype_name(geom->type));
668  }
669 }
670 
671 static stringbuffer_t *
672 lwgeom_to_wkt_internal(const LWGEOM *geom, uint8_t variant, int precision)
673 {
674  stringbuffer_t *sb;
675  if ( geom == NULL )
676  return NULL;
677  sb = stringbuffer_create();
678  /* Extended mode starts with an "SRID=" section for geoms that have one */
679  if ( (variant & WKT_EXTENDED) && lwgeom_has_srid(geom) )
680  {
681  stringbuffer_aprintf(sb, "SRID=%d;", geom->srid);
682  }
683  lwgeom_to_wkt_sb(geom, sb, precision, variant);
684  if ( stringbuffer_getstring(sb) == NULL )
685  {
686  lwerror("Uh oh");
687  return NULL;
688  }
689  return sb;
690 }
691 
703 char *
704 lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
705 {
707  if (!sb)
708  return NULL;
709  char *str = stringbuffer_getstringcopy(sb);
710  if ( size_out )
711  *size_out = stringbuffer_getlength(sb) + 1;
713  return str;
714 }
715 
716 lwvarlena_t *
717 lwgeom_to_wkt_varlena(const LWGEOM *geom, uint8_t variant, int precision)
718 {
720  if (!sb)
721  return NULL;
724  return output;
725 }
static uint8_t variant
Definition: cu_in_twkb.c:26
static uint8_t precision
Definition: cu_in_twkb.c:25
#define COLLECTIONTYPE
Definition: liblwgeom.h:122
#define COMPOUNDTYPE
Definition: liblwgeom.h:124
#define CURVEPOLYTYPE
Definition: liblwgeom.h:125
#define MULTILINETYPE
Definition: liblwgeom.h:120
#define MULTISURFACETYPE
Definition: liblwgeom.h:127
#define LINETYPE
Definition: liblwgeom.h:117
#define WKT_EXTENDED
Definition: liblwgeom.h:2157
#define MULTIPOINTTYPE
Definition: liblwgeom.h:119
int lwgeom_has_srid(const LWGEOM *geom)
Return true or false depending on whether a geometry has a valid SRID set.
Definition: lwgeom.c:1387
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:116
#define FLAGS_GET_Z(flags)
Definition: liblwgeom.h:179
#define TINTYPE
Definition: liblwgeom.h:130
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:121
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:193
#define POLYGONTYPE
Definition: liblwgeom.h:118
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:128
#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
#define WKT_ISO
Definition: liblwgeom.h:2155
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:180
#define MULTICURVETYPE
Definition: liblwgeom.h:126
#define TRIANGLETYPE
Definition: liblwgeom.h:129
#define WKT_NO_PARENS
int lwline_is_empty(const LWLINE *line)
#define OUT_MAX_BYTES_DOUBLE
#define WKT_IS_CHILD
int lwpoint_is_empty(const LWPOINT *point)
int lwtriangle_is_empty(const LWTRIANGLE *triangle)
int lwpoly_is_empty(const LWPOLY *poly)
#define WKT_NO_TYPE
Well-Known Text (WKT) Output Variant Types.
int lwcircstring_is_empty(const LWCIRCSTRING *circ)
#define str(s)
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
static uint8_t * getPoint_internal(const POINTARRAY *pa, uint32_t n)
Definition: lwinline.h:77
static void lwcircstring_to_wkt_sb(const LWCIRCSTRING *circ, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:208
static void lwmsurface_to_wkt_sb(const LWMSURFACE *msurf, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:459
static void dimension_qualifiers_to_wkt_sb(const LWGEOM *geom, stringbuffer_t *sb, uint8_t variant)
Definition: lwout_wkt.c:40
static void lwtin_to_wkt_sb(const LWTIN *tin, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:551
static void empty_to_wkt_sb(stringbuffer_t *sb)
Definition: lwout_wkt.c:70
static void lwcollection_to_wkt_sb(const LWCOLLECTION *collection, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:502
static void lwcompound_to_wkt_sb(const LWCOMPOUND *comp, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:318
static void lwmcurve_to_wkt_sb(const LWMCURVE *mcurv, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:411
static void lwline_to_wkt_sb(const LWLINE *line, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:162
static void lwtriangle_to_wkt_sb(const LWTRIANGLE *tri, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:530
static void lwmpoint_to_wkt_sb(const LWMPOINT *mpoint, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:228
static void lwcurvepoly_to_wkt_sb(const LWCURVEPOLY *cpoly, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:363
static void lwpoint_to_wkt_sb(const LWPOINT *pt, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:142
static void lwmline_to_wkt_sb(const LWMLINE *mline, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:256
static void lwmpoly_to_wkt_sb(const LWMPOLY *mpoly, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:286
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:704
static void coordinate_to_wkt_sb(double *coords, stringbuffer_t *sb, uint32_t dimensions, int precision)
Definition: lwout_wkt.c:80
static void lwpoly_to_wkt_sb(const LWPOLY *poly, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:181
static void ptarray_to_wkt_sb(const POINTARRAY *ptarray, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:97
static void lwgeom_to_wkt_sb(const LWGEOM *geom, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:612
static void lwpsurface_to_wkt_sb(const LWPSURFACE *psurf, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:580
static stringbuffer_t * lwgeom_to_wkt_internal(const LWGEOM *geom, uint8_t variant, int precision)
Definition: lwout_wkt.c:672
lwvarlena_t * lwgeom_to_wkt_varlena(const LWGEOM *geom, uint8_t variant, int precision)
Definition: lwout_wkt.c:717
type
Definition: ovdump.py:42
int stringbuffer_aprintf(stringbuffer_t *s, const char *fmt,...)
Appends a formatted string to the current string buffer, using the format and argument list provided.
Definition: stringbuffer.c:228
lwvarlena_t * stringbuffer_getvarlenacopy(stringbuffer_t *s)
Definition: stringbuffer.c:134
char stringbuffer_lastchar(stringbuffer_t *s)
Return the last character in the buffer.
Definition: stringbuffer.c:98
stringbuffer_t * stringbuffer_create(void)
Allocate a new stringbuffer_t.
Definition: stringbuffer.c:33
int stringbuffer_getlength(stringbuffer_t *s)
Returns the length of the current string, not including the null terminator (same behavior as strlen(...
Definition: stringbuffer.c:149
void stringbuffer_destroy(stringbuffer_t *s)
Free the stringbuffer_t and all memory managed within it.
Definition: stringbuffer.c:76
char * stringbuffer_getstringcopy(stringbuffer_t *s)
Returns a newly allocated string large enough to contain the current state of the string.
Definition: stringbuffer.c:124
const char * stringbuffer_getstring(stringbuffer_t *s)
Returns a reference to the internal string being managed by the stringbuffer.
Definition: stringbuffer.c:113
static void stringbuffer_append_double(stringbuffer_t *s, double d, int precision)
Definition: stringbuffer.h:110
static void stringbuffer_append_len(stringbuffer_t *s, const char *a, size_t alen)
Append the specified string to the stringbuffer_t using known length.
Definition: stringbuffer.h:91
static void stringbuffer_makeroom(stringbuffer_t *s, size_t size_to_add)
If necessary, expand the stringbuffer_t internal buffer to accommodate the specified additional size.
Definition: stringbuffer.h:69
POINTARRAY * points
Definition: liblwgeom.h:521
uint32_t ngeoms
Definition: liblwgeom.h:594
LWGEOM ** geoms
Definition: liblwgeom.h:589
uint32_t ngeoms
Definition: liblwgeom.h:608
LWGEOM ** geoms
Definition: liblwgeom.h:603
LWGEOM ** rings
Definition: liblwgeom.h:617
uint32_t nrings
Definition: liblwgeom.h:622
uint8_t type
Definition: liblwgeom.h:476
int32_t srid
Definition: liblwgeom.h:474
lwflags_t flags
Definition: liblwgeom.h:475
POINTARRAY * points
Definition: liblwgeom.h:497
LWGEOM ** geoms
Definition: liblwgeom.h:631
uint32_t ngeoms
Definition: liblwgeom.h:636
LWLINE ** geoms
Definition: liblwgeom.h:561
uint32_t ngeoms
Definition: liblwgeom.h:566
uint32_t ngeoms
Definition: liblwgeom.h:552
LWPOINT ** geoms
Definition: liblwgeom.h:547
uint32_t ngeoms
Definition: liblwgeom.h:580
LWPOLY ** geoms
Definition: liblwgeom.h:575
uint32_t ngeoms
Definition: liblwgeom.h:650
LWGEOM ** geoms
Definition: liblwgeom.h:645
POINTARRAY * point
Definition: liblwgeom.h:485
uint8_t type
Definition: liblwgeom.h:488
POINTARRAY ** rings
Definition: liblwgeom.h:533
uint32_t nrings
Definition: liblwgeom.h:538
LWPOLY ** geoms
Definition: liblwgeom.h:659
uint32_t ngeoms
Definition: liblwgeom.h:664
uint32_t ngeoms
Definition: liblwgeom.h:678
LWTRIANGLE ** geoms
Definition: liblwgeom.h:673
POINTARRAY * points
Definition: liblwgeom.h:509
lwflags_t flags
Definition: liblwgeom.h:445
uint32_t npoints
Definition: liblwgeom.h:441