PostGIS  3.4.0dev-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, in non-ISO format, 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 * Strictly speaking, the SFA spec also mandates use of parens in sub-members, but
228 * use the old non-parens interpretation for WKT_SFSQL
229 */
230 static void lwmpoint_to_wkt_sb(const LWMPOINT *mpoint, stringbuffer_t *sb, int precision, uint8_t variant)
231 {
232  uint32_t i = 0;
233  if ( ! (variant & WKT_NO_TYPE) )
234  {
235  stringbuffer_append_len(sb, "MULTIPOINT", 10); /* "MULTIPOINT" */
237  }
238  if ( mpoint->ngeoms < 1 )
239  {
240  empty_to_wkt_sb(sb);
241  return;
242  }
243  stringbuffer_append_len(sb, "(", 1);
244  variant = variant | WKT_IS_CHILD | WKT_NO_TYPE; /* Inform the sub-geometries they are children */
245  if ( !(variant & WKT_ISO) )
247  for ( i = 0; i < mpoint->ngeoms; i++ )
248  {
249  if ( i > 0 )
250  stringbuffer_append_len(sb, ",", 1);
251  /* We don't want type strings or parens on our subgeoms */
252  lwpoint_to_wkt_sb(mpoint->geoms[i], sb, precision, variant);
253  }
254  stringbuffer_append_len(sb, ")", 1);
255 }
256 
257 /*
258 * MULTILINESTRING
259 */
260 static void lwmline_to_wkt_sb(const LWMLINE *mline, stringbuffer_t *sb, int precision, uint8_t variant)
261 {
262  uint32_t i = 0;
263 
264  if ( ! (variant & WKT_NO_TYPE) )
265  {
266  stringbuffer_append_len(sb, "MULTILINESTRING", 15); /* "MULTILINESTRING" */
268  }
269  if ( mline->ngeoms < 1 )
270  {
271  empty_to_wkt_sb(sb);
272  return;
273  }
274 
275  stringbuffer_append_len(sb, "(", 1);
276  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
277  for ( i = 0; i < mline->ngeoms; i++ )
278  {
279  if ( i > 0 )
280  stringbuffer_append_len(sb, ",", 1);
281  /* We don't want type strings on our subgeoms */
282  lwline_to_wkt_sb(mline->geoms[i], sb, precision, variant | WKT_NO_TYPE );
283  }
284  stringbuffer_append_len(sb, ")", 1);
285 }
286 
287 /*
288 * MULTIPOLYGON
289 */
290 static void lwmpoly_to_wkt_sb(const LWMPOLY *mpoly, stringbuffer_t *sb, int precision, uint8_t variant)
291 {
292  uint32_t i = 0;
293 
294  if ( ! (variant & WKT_NO_TYPE) )
295  {
296  stringbuffer_append_len(sb, "MULTIPOLYGON", 12); /* "MULTIPOLYGON" */
298  }
299  if ( mpoly->ngeoms < 1 )
300  {
301  empty_to_wkt_sb(sb);
302  return;
303  }
304 
305  stringbuffer_append_len(sb, "(", 1);
306  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
307  for ( i = 0; i < mpoly->ngeoms; i++ )
308  {
309  if ( i > 0 )
310  stringbuffer_append_len(sb, ",", 1);
311  /* We don't want type strings on our subgeoms */
312  lwpoly_to_wkt_sb(mpoly->geoms[i], sb, precision, variant | WKT_NO_TYPE );
313  }
314  stringbuffer_append_len(sb, ")", 1);
315 }
316 
317 /*
318 * Compound curves provide type information for their curved sub-geometries
319 * but not their linestring sub-geometries.
320 * COMPOUNDCURVE((0 0, 1 1), CURVESTRING(1 1, 2 2, 3 3))
321 */
322 static void lwcompound_to_wkt_sb(const LWCOMPOUND *comp, stringbuffer_t *sb, int precision, uint8_t variant)
323 {
324  uint32_t i = 0;
325 
326  if ( ! (variant & WKT_NO_TYPE) )
327  {
328  stringbuffer_append_len(sb, "COMPOUNDCURVE", 13); /* "COMPOUNDCURVE" */
330  }
331  if ( comp->ngeoms < 1 )
332  {
333  empty_to_wkt_sb(sb);
334  return;
335  }
336 
337  stringbuffer_append_len(sb, "(", 1);
338  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
339  for ( i = 0; i < comp->ngeoms; i++ )
340  {
341  int type = comp->geoms[i]->type;
342  if ( i > 0 )
343  stringbuffer_append_len(sb, ",", 1);
344  /* Linestring subgeoms don't get type identifiers */
345  if ( type == LINETYPE )
346  {
348  }
349  /* But circstring subgeoms *do* get type identifiers */
350  else if ( type == CIRCSTRINGTYPE )
351  {
353  }
354  else
355  {
356  lwerror("lwcompound_to_wkt_sb: Unknown type received %d - %s", type, lwtype_name(type));
357  }
358  }
359  stringbuffer_append_len(sb, ")", 1);
360 }
361 
362 /*
363 * Curve polygons provide type information for their curved rings
364 * but not their linestring rings.
365 * CURVEPOLYGON((0 0, 1 1, 0 1, 0 0), CURVESTRING(0 0, 1 1, 0 1, 0.5 1, 0 0))
366 */
367 static void lwcurvepoly_to_wkt_sb(const LWCURVEPOLY *cpoly, stringbuffer_t *sb, int precision, uint8_t variant)
368 {
369  uint32_t i = 0;
370 
371  if ( ! (variant & WKT_NO_TYPE) )
372  {
373  stringbuffer_append_len(sb, "CURVEPOLYGON", 12); /* "CURVEPOLYGON" */
375  }
376  if ( cpoly->nrings < 1 )
377  {
378  empty_to_wkt_sb(sb);
379  return;
380  }
381  stringbuffer_append_len(sb, "(", 1);
382  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
383  for ( i = 0; i < cpoly->nrings; i++ )
384  {
385  int type = cpoly->rings[i]->type;
386  if ( i > 0 )
387  stringbuffer_append_len(sb, ",", 1);
388  switch (type)
389  {
390  case LINETYPE:
391  /* Linestring subgeoms don't get type identifiers */
393  break;
394  case CIRCSTRINGTYPE:
395  /* But circstring subgeoms *do* get type identifiers */
397  break;
398  case COMPOUNDTYPE:
399  /* And compoundcurve subgeoms *do* get type identifiers */
401  break;
402  default:
403  lwerror("lwcurvepoly_to_wkt_sb: Unknown type received %d - %s", type, lwtype_name(type));
404  }
405  }
406  stringbuffer_append_len(sb, ")", 1);
407 }
408 
409 
410 /*
411 * Multi-curves provide type information for their curved sub-geometries
412 * but not their linear sub-geometries.
413 * MULTICURVE((0 0, 1 1), CURVESTRING(0 0, 1 1, 2 2))
414 */
415 static void lwmcurve_to_wkt_sb(const LWMCURVE *mcurv, stringbuffer_t *sb, int precision, uint8_t variant)
416 {
417  uint32_t i = 0;
418 
419  if ( ! (variant & WKT_NO_TYPE) )
420  {
421  stringbuffer_append_len(sb, "MULTICURVE", 10); /* "MULTICURVE" */
423  }
424  if ( mcurv->ngeoms < 1 )
425  {
426  empty_to_wkt_sb(sb);
427  return;
428  }
429  stringbuffer_append_len(sb, "(", 1);
430  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
431  for ( i = 0; i < mcurv->ngeoms; i++ )
432  {
433  int type = mcurv->geoms[i]->type;
434  if ( i > 0 )
435  stringbuffer_append_len(sb, ",", 1);
436  switch (type)
437  {
438  case LINETYPE:
439  /* Linestring subgeoms don't get type identifiers */
441  break;
442  case CIRCSTRINGTYPE:
443  /* But circstring subgeoms *do* get type identifiers */
445  break;
446  case COMPOUNDTYPE:
447  /* And compoundcurve subgeoms *do* get type identifiers */
449  break;
450  default:
451  lwerror("lwmcurve_to_wkt_sb: Unknown type received %d - %s", type, lwtype_name(type));
452  }
453  }
454  stringbuffer_append_len(sb, ")", 1);
455 }
456 
457 
458 /*
459 * Multi-surfaces provide type information for their curved sub-geometries
460 * but not their linear sub-geometries.
461 * MULTISURFACE(((0 0, 1 1, 1 0, 0 0)), CURVEPOLYGON(CURVESTRING(0 0, 1 1, 2 2, 0 1, 0 0)))
462 */
463 static void lwmsurface_to_wkt_sb(const LWMSURFACE *msurf, stringbuffer_t *sb, int precision, uint8_t variant)
464 {
465  uint32_t i = 0;
466 
467  if ( ! (variant & WKT_NO_TYPE) )
468  {
469  stringbuffer_append_len(sb, "MULTISURFACE", 12); /* "MULTISURFACE" */
471  }
472  if ( msurf->ngeoms < 1 )
473  {
474  empty_to_wkt_sb(sb);
475  return;
476  }
477  stringbuffer_append_len(sb, "(", 1);
478  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
479  for ( i = 0; i < msurf->ngeoms; i++ )
480  {
481  int type = msurf->geoms[i]->type;
482  if ( i > 0 )
483  stringbuffer_append_len(sb, ",", 1);
484  switch (type)
485  {
486  case POLYGONTYPE:
487  /* Linestring subgeoms don't get type identifiers */
489  break;
490  case CURVEPOLYTYPE:
491  /* But circstring subgeoms *do* get type identifiers */
493  break;
494  default:
495  lwerror("lwmsurface_to_wkt_sb: Unknown type received %d - %s", type, lwtype_name(type));
496  }
497  }
498  stringbuffer_append_len(sb, ")", 1);
499 }
500 
501 /*
502 * Geometry collections provide type information for all their curved sub-geometries
503 * but not their linear sub-geometries.
504 * GEOMETRYCOLLECTION(POLYGON((0 0, 1 1, 1 0, 0 0)), CURVEPOLYGON(CURVESTRING(0 0, 1 1, 2 2, 0 1, 0 0)))
505 */
506 static void lwcollection_to_wkt_sb(const LWCOLLECTION *collection, stringbuffer_t *sb, int precision, uint8_t variant)
507 {
508  uint32_t i = 0;
509 
510  if ( ! (variant & WKT_NO_TYPE) )
511  {
512  stringbuffer_append_len(sb, "GEOMETRYCOLLECTION", 18); /* "GEOMETRYCOLLECTION" */
513  dimension_qualifiers_to_wkt_sb((LWGEOM*)collection, sb, variant);
514  }
515  if ( collection->ngeoms < 1 )
516  {
517  empty_to_wkt_sb(sb);
518  return;
519  }
520  stringbuffer_append_len(sb, "(", 1);
521  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are children */
522  for ( i = 0; i < collection->ngeoms; i++ )
523  {
524  if ( i > 0 )
525  stringbuffer_append_len(sb, ",", 1);
526  lwgeom_to_wkt_sb((LWGEOM*)collection->geoms[i], sb, precision, variant );
527  }
528  stringbuffer_append_len(sb, ")", 1);
529 }
530 
531 /*
532 * TRIANGLE
533 */
534 static void lwtriangle_to_wkt_sb(const LWTRIANGLE *tri, stringbuffer_t *sb, int precision, uint8_t variant)
535 {
536  if ( ! (variant & WKT_NO_TYPE) )
537  {
538  stringbuffer_append_len(sb, "TRIANGLE", 8); /* "TRIANGLE" */
540  }
541  if ( lwtriangle_is_empty(tri) )
542  {
543  empty_to_wkt_sb(sb);
544  return;
545  }
546 
547  stringbuffer_append_len(sb, "(", 1); /* Triangles have extraneous brackets */
549  stringbuffer_append_len(sb, ")", 1);
550 }
551 
552 /*
553 * TIN
554 */
555 static void lwtin_to_wkt_sb(const LWTIN *tin, stringbuffer_t *sb, int precision, uint8_t variant)
556 {
557  uint32_t i = 0;
558 
559  if ( ! (variant & WKT_NO_TYPE) )
560  {
561  stringbuffer_append_len(sb, "TIN", 3); /* "TIN" */
563  }
564  if ( tin->ngeoms < 1 )
565  {
566  empty_to_wkt_sb(sb);
567  return;
568  }
569 
570  stringbuffer_append_len(sb, "(", 1);
571  for ( i = 0; i < tin->ngeoms; i++ )
572  {
573  if ( i > 0 )
574  stringbuffer_append_len(sb, ",", 1);
575  /* We don't want type strings on our subgeoms */
577  }
578  stringbuffer_append_len(sb, ")", 1);
579 }
580 
581 /*
582 * POLYHEDRALSURFACE
583 */
584 static void lwpsurface_to_wkt_sb(const LWPSURFACE *psurf, stringbuffer_t *sb, int precision, uint8_t variant)
585 {
586  uint32_t i = 0;
587 
588  if ( ! (variant & WKT_NO_TYPE) )
589  {
590  stringbuffer_append_len(sb, "POLYHEDRALSURFACE", 17); /* "POLYHEDRALSURFACE" */
592  }
593  if ( psurf->ngeoms < 1 )
594  {
595  empty_to_wkt_sb(sb);
596  return;
597  }
598 
599  variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */
600 
601  stringbuffer_append_len(sb, "(", 1);
602  for ( i = 0; i < psurf->ngeoms; i++ )
603  {
604  if ( i > 0 )
605  stringbuffer_append_len(sb, ",", 1);
606  /* We don't want type strings on our subgeoms */
607  lwpoly_to_wkt_sb(psurf->geoms[i], sb, precision, variant | WKT_NO_TYPE );
608  }
609  stringbuffer_append_len(sb, ")", 1);
610 }
611 
612 
613 /*
614 * Generic GEOMETRY
615 */
616 static void lwgeom_to_wkt_sb(const LWGEOM *geom, stringbuffer_t *sb, int precision, uint8_t variant)
617 {
618  LWDEBUGF(4, "lwgeom_to_wkt_sb: type %s, hasz %d, hasm %d",
619  lwtype_name(geom->type), (geom->type),
620  FLAGS_GET_Z(geom->flags)?1:0, FLAGS_GET_M(geom->flags)?1:0);
621 
622  switch (geom->type)
623  {
624  case POINTTYPE:
626  break;
627  case LINETYPE:
629  break;
630  case POLYGONTYPE:
632  break;
633  case MULTIPOINTTYPE:
635  break;
636  case MULTILINETYPE:
638  break;
639  case MULTIPOLYGONTYPE:
641  break;
642  case COLLECTIONTYPE:
644  break;
645  case CIRCSTRINGTYPE:
647  break;
648  case COMPOUNDTYPE:
650  break;
651  case CURVEPOLYTYPE:
653  break;
654  case MULTICURVETYPE:
656  break;
657  case MULTISURFACETYPE:
659  break;
660  case TRIANGLETYPE:
662  break;
663  case TINTYPE:
664  lwtin_to_wkt_sb((LWTIN*)geom, sb, precision, variant);
665  break;
668  break;
669  default:
670  lwerror("lwgeom_to_wkt_sb: Type %d - %s unsupported.",
671  geom->type, lwtype_name(geom->type));
672  }
673 }
674 
675 static stringbuffer_t *
676 lwgeom_to_wkt_internal(const LWGEOM *geom, uint8_t variant, int precision)
677 {
678  stringbuffer_t *sb;
679  if ( geom == NULL )
680  return NULL;
681  sb = stringbuffer_create();
682  /* Extended mode starts with an "SRID=" section for geoms that have one */
683  if ( (variant & WKT_EXTENDED) && lwgeom_has_srid(geom) )
684  {
685  stringbuffer_aprintf(sb, "SRID=%d;", geom->srid);
686  }
687  lwgeom_to_wkt_sb(geom, sb, precision, variant);
688  if ( stringbuffer_getstring(sb) == NULL )
689  {
690  lwerror("Uh oh");
691  return NULL;
692  }
693  return sb;
694 }
695 
707 char *
708 lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
709 {
711  if (!sb)
712  return NULL;
713  char *str = stringbuffer_getstringcopy(sb);
714  if ( size_out )
715  *size_out = stringbuffer_getlength(sb) + 1;
717  return str;
718 }
719 
720 lwvarlena_t *
721 lwgeom_to_wkt_varlena(const LWGEOM *geom, uint8_t variant, int precision)
722 {
724  if (!sb)
725  return NULL;
728  return output;
729 }
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:108
#define COMPOUNDTYPE
Definition: liblwgeom.h:110
#define CURVEPOLYTYPE
Definition: liblwgeom.h:111
#define MULTILINETYPE
Definition: liblwgeom.h:106
#define MULTISURFACETYPE
Definition: liblwgeom.h:113
#define LINETYPE
Definition: liblwgeom.h:103
#define WKT_EXTENDED
Definition: liblwgeom.h:2186
#define MULTIPOINTTYPE
Definition: liblwgeom.h:105
int lwgeom_has_srid(const LWGEOM *geom)
Return true or false depending on whether a geometry has a valid SRID set.
Definition: lwgeom.c:1404
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:102
#define FLAGS_GET_Z(flags)
Definition: liblwgeom.h:165
#define TINTYPE
Definition: liblwgeom.h:116
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:107
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:179
#define POLYGONTYPE
Definition: liblwgeom.h:104
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:114
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:109
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:2184
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:166
#define MULTICURVETYPE
Definition: liblwgeom.h:112
#define TRIANGLETYPE
Definition: liblwgeom.h:115
#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:463
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:555
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:506
static void lwcompound_to_wkt_sb(const LWCOMPOUND *comp, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:322
static void lwmcurve_to_wkt_sb(const LWMCURVE *mcurv, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:415
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:534
static void lwmpoint_to_wkt_sb(const LWMPOINT *mpoint, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:230
static void lwcurvepoly_to_wkt_sb(const LWCURVEPOLY *cpoly, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:367
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:260
static void lwmpoly_to_wkt_sb(const LWMPOLY *mpoly, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:290
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:708
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:616
static void lwpsurface_to_wkt_sb(const LWPSURFACE *psurf, stringbuffer_t *sb, int precision, uint8_t variant)
Definition: lwout_wkt.c:584
static stringbuffer_t * lwgeom_to_wkt_internal(const LWGEOM *geom, uint8_t variant, int precision)
Definition: lwout_wkt.c:676
lwvarlena_t * lwgeom_to_wkt_varlena(const LWGEOM *geom, uint8_t variant, int precision)
Definition: lwout_wkt.c:721
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:247
lwvarlena_t * stringbuffer_getvarlenacopy(stringbuffer_t *s)
Definition: stringbuffer.c:151
char stringbuffer_lastchar(stringbuffer_t *s)
Return the last character in the buffer.
Definition: stringbuffer.c:107
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:166
void stringbuffer_destroy(stringbuffer_t *s)
Free the stringbuffer_t and all memory managed within it.
Definition: stringbuffer.c:85
char * stringbuffer_getstringcopy(stringbuffer_t *s)
Returns a newly allocated string large enough to contain the current state of the string.
Definition: stringbuffer.c:133
const char * stringbuffer_getstring(stringbuffer_t *s)
Returns a reference to the internal string being managed by the stringbuffer.
Definition: stringbuffer.c:122
static void stringbuffer_append_double(stringbuffer_t *s, double d, int precision)
Definition: stringbuffer.h:112
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:93
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:71
POINTARRAY * points
Definition: liblwgeom.h:507
uint32_t ngeoms
Definition: liblwgeom.h:580
LWGEOM ** geoms
Definition: liblwgeom.h:575
uint32_t ngeoms
Definition: liblwgeom.h:594
LWGEOM ** geoms
Definition: liblwgeom.h:589
LWGEOM ** rings
Definition: liblwgeom.h:603
uint32_t nrings
Definition: liblwgeom.h:608
uint8_t type
Definition: liblwgeom.h:462
int32_t srid
Definition: liblwgeom.h:460
lwflags_t flags
Definition: liblwgeom.h:461
POINTARRAY * points
Definition: liblwgeom.h:483
LWGEOM ** geoms
Definition: liblwgeom.h:617
uint32_t ngeoms
Definition: liblwgeom.h:622
LWLINE ** geoms
Definition: liblwgeom.h:547
uint32_t ngeoms
Definition: liblwgeom.h:552
uint32_t ngeoms
Definition: liblwgeom.h:538
LWPOINT ** geoms
Definition: liblwgeom.h:533
uint32_t ngeoms
Definition: liblwgeom.h:566
LWPOLY ** geoms
Definition: liblwgeom.h:561
uint32_t ngeoms
Definition: liblwgeom.h:636
LWGEOM ** geoms
Definition: liblwgeom.h:631
POINTARRAY * point
Definition: liblwgeom.h:471
uint8_t type
Definition: liblwgeom.h:474
POINTARRAY ** rings
Definition: liblwgeom.h:519
uint32_t nrings
Definition: liblwgeom.h:524
LWPOLY ** geoms
Definition: liblwgeom.h:645
uint32_t ngeoms
Definition: liblwgeom.h:650
uint32_t ngeoms
Definition: liblwgeom.h:664
LWTRIANGLE ** geoms
Definition: liblwgeom.h:659
POINTARRAY * points
Definition: liblwgeom.h:495
lwflags_t flags
Definition: liblwgeom.h:431
uint32_t npoints
Definition: liblwgeom.h:427