PostGIS  2.1.10dev-r@@SVN_REVISION@@
lwout_geojson.c
Go to the documentation of this file.
1 /**********************************************************************
2  * $Id: lwout_geojson.c 14476 2015-12-04 00:07:45Z dbaston $
3  *
4  * PostGIS - Spatial Types for PostgreSQL
5  * http://postgis.net
6  * Copyright 2001-2003 Refractions Research Inc.
7  * Copyright 2009-2010 Olivier Courtin <olivier.courtin@oslandia.com>
8  *
9  * This is free software; you can redistribute and/or modify it under
10  * the terms of hte GNU General Public Licence. See the COPYING file.
11  *
12  **********************************************************************/
13 
14 #include "liblwgeom_internal.h"
15 #include <string.h> /* strlen */
16 #include <assert.h>
17 
18 static char *asgeojson_point(const LWPOINT *point, char *srs, GBOX *bbox, int precision);
19 static char *asgeojson_line(const LWLINE *line, char *srs, GBOX *bbox, int precision);
20 static char *asgeojson_poly(const LWPOLY *poly, char *srs, GBOX *bbox, int precision);
21 static char * asgeojson_multipoint(const LWMPOINT *mpoint, char *srs, GBOX *bbox, int precision);
22 static char * asgeojson_multiline(const LWMLINE *mline, char *srs, GBOX *bbox, int precision);
23 static char * asgeojson_multipolygon(const LWMPOLY *mpoly, char *srs, GBOX *bbox, int precision);
24 static char * asgeojson_collection(const LWCOLLECTION *col, char *srs, GBOX *bbox, int precision);
25 static size_t asgeojson_geom_size(const LWGEOM *geom, GBOX *bbox, int precision);
26 static size_t asgeojson_geom_buf(const LWGEOM *geom, char *output, GBOX *bbox, int precision);
27 
28 static size_t pointArray_to_geojson(POINTARRAY *pa, char *buf, int precision);
29 static size_t pointArray_geojson_size(POINTARRAY *pa, int precision);
30 
34 char *
35 lwgeom_to_geojson(const LWGEOM *geom, char *srs, int precision, int has_bbox)
36 {
37  int type = geom->type;
38  GBOX *bbox = NULL;
39  GBOX tmp;
40 
41  if ( precision > OUT_MAX_DOUBLE_PRECISION ) precision = OUT_MAX_DOUBLE_PRECISION;
42 
43  if (has_bbox)
44  {
45  /* Whether these are geography or geometry,
46  the GeoJSON expects a cartesian bounding box */
48  bbox = &tmp;
49  }
50 
51  switch (type)
52  {
53  case POINTTYPE:
54  return asgeojson_point((LWPOINT*)geom, srs, bbox, precision);
55  case LINETYPE:
56  return asgeojson_line((LWLINE*)geom, srs, bbox, precision);
57  case POLYGONTYPE:
58  return asgeojson_poly((LWPOLY*)geom, srs, bbox, precision);
59  case MULTIPOINTTYPE:
60  return asgeojson_multipoint((LWMPOINT*)geom, srs, bbox, precision);
61  case MULTILINETYPE:
62  return asgeojson_multiline((LWMLINE*)geom, srs, bbox, precision);
63  case MULTIPOLYGONTYPE:
64  return asgeojson_multipolygon((LWMPOLY*)geom, srs, bbox, precision);
65  case COLLECTIONTYPE:
66  return asgeojson_collection((LWCOLLECTION*)geom, srs, bbox, precision);
67  default:
68  lwerror("lwgeom_to_geojson: '%s' geometry type not supported",
69  lwtype_name(type));
70  }
71 
72  /* Never get here */
73  return NULL;
74 }
75 
76 
77 
81 static size_t
83 {
84  int size;
85 
86  size = sizeof("'crs':{'type':'name',");
87  size += sizeof("'properties':{'name':''}},");
88  size += strlen(srs) * sizeof(char);
89 
90  return size;
91 }
92 
93 static size_t
94 asgeojson_srs_buf(char *output, char *srs)
95 {
96  char *ptr = output;
97 
98  ptr += sprintf(ptr, "\"crs\":{\"type\":\"name\",");
99  ptr += sprintf(ptr, "\"properties\":{\"name\":\"%s\"}},", srs);
100 
101  return (ptr-output);
102 }
103 
104 
105 
109 static size_t
110 asgeojson_bbox_size(int hasz, int precision)
111 {
112  int size;
113 
114  if (!hasz)
115  {
116  size = sizeof("\"bbox\":[,,,],");
117  size += 2 * 2 * (OUT_MAX_DIGS_DOUBLE + precision);
118  }
119  else
120  {
121  size = sizeof("\"bbox\":[,,,,,],");
122  size += 2 * 3 * (OUT_MAX_DIGS_DOUBLE + precision);
123  }
124 
125  return size;
126 }
127 
128 static size_t
129 asgeojson_bbox_buf(char *output, GBOX *bbox, int hasz, int precision)
130 {
131  char *ptr = output;
132 
133  if (!hasz)
134  ptr += sprintf(ptr, "\"bbox\":[%.*f,%.*f,%.*f,%.*f],",
135  precision, bbox->xmin, precision, bbox->ymin,
136  precision, bbox->xmax, precision, bbox->ymax);
137  else
138  ptr += sprintf(ptr, "\"bbox\":[%.*f,%.*f,%.*f,%.*f,%.*f,%.*f],",
139  precision, bbox->xmin, precision, bbox->ymin, precision, bbox->zmin,
140  precision, bbox->xmax, precision, bbox->ymax, precision, bbox->zmax);
141 
142  return (ptr-output);
143 }
144 
145 
146 
151 static size_t
152 asgeojson_point_size(const LWPOINT *point, char *srs, GBOX *bbox, int precision)
153 {
154  int size;
155 
156  size = pointArray_geojson_size(point->point, precision);
157  size += sizeof("{'type':'Point',");
158  size += sizeof("'coordinates':}");
159 
160  if ( lwpoint_is_empty(point) )
161  size += 2; /* [] */
162 
163  if (srs) size += asgeojson_srs_size(srs);
164  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(point->flags), precision);
165 
166  return size;
167 }
168 
169 static size_t
170 asgeojson_point_buf(const LWPOINT *point, char *srs, char *output, GBOX *bbox, int precision)
171 {
172  char *ptr = output;
173 
174  ptr += sprintf(ptr, "{\"type\":\"Point\",");
175  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
176  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(point->flags), precision);
177 
178  ptr += sprintf(ptr, "\"coordinates\":");
179  if ( lwpoint_is_empty(point) )
180  ptr += sprintf(ptr, "[]");
181  ptr += pointArray_to_geojson(point->point, ptr, precision);
182  ptr += sprintf(ptr, "}");
183 
184  return (ptr-output);
185 }
186 
187 static char *
188 asgeojson_point(const LWPOINT *point, char *srs, GBOX *bbox, int precision)
189 {
190  char *output;
191  int size;
192 
193  size = asgeojson_point_size(point, srs, bbox, precision);
194  output = lwalloc(size);
195  asgeojson_point_buf(point, srs, output, bbox, precision);
196  return output;
197 }
198 
199 
200 
205 static size_t
206 asgeojson_line_size(const LWLINE *line, char *srs, GBOX *bbox, int precision)
207 {
208  int size;
209 
210  size = sizeof("{'type':'LineString',");
211  if (srs) size += asgeojson_srs_size(srs);
212  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(line->flags), precision);
213  size += sizeof("'coordinates':[]}");
214  size += pointArray_geojson_size(line->points, precision);
215 
216  return size;
217 }
218 
219 static size_t
220 asgeojson_line_buf(const LWLINE *line, char *srs, char *output, GBOX *bbox, int precision)
221 {
222  char *ptr=output;
223 
224  ptr += sprintf(ptr, "{\"type\":\"LineString\",");
225  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
226  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(line->flags), precision);
227  ptr += sprintf(ptr, "\"coordinates\":[");
228  ptr += pointArray_to_geojson(line->points, ptr, precision);
229  ptr += sprintf(ptr, "]}");
230 
231  return (ptr-output);
232 }
233 
234 static char *
235 asgeojson_line(const LWLINE *line, char *srs, GBOX *bbox, int precision)
236 {
237  char *output;
238  int size;
239 
240  size = asgeojson_line_size(line, srs, bbox, precision);
241  output = lwalloc(size);
242  asgeojson_line_buf(line, srs, output, bbox, precision);
243 
244  return output;
245 }
246 
247 
248 
253 static size_t
254 asgeojson_poly_size(const LWPOLY *poly, char *srs, GBOX *bbox, int precision)
255 {
256  size_t size;
257  int i;
258 
259  size = sizeof("{\"type\":\"Polygon\",");
260  if (srs) size += asgeojson_srs_size(srs);
261  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(poly->flags), precision);
262  size += sizeof("\"coordinates\":[");
263  for (i=0; i<poly->nrings; i++)
264  {
265  size += pointArray_geojson_size(poly->rings[i], precision);
266  size += sizeof("[]");
267  }
268  size += sizeof(",") * i;
269  size += sizeof("]}");
270 
271  return size;
272 }
273 
274 static size_t
275 asgeojson_poly_buf(const LWPOLY *poly, char *srs, char *output, GBOX *bbox, int precision)
276 {
277  int i;
278  char *ptr=output;
279 
280  ptr += sprintf(ptr, "{\"type\":\"Polygon\",");
281  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
282  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(poly->flags), precision);
283  ptr += sprintf(ptr, "\"coordinates\":[");
284  for (i=0; i<poly->nrings; i++)
285  {
286  if (i) ptr += sprintf(ptr, ",");
287  ptr += sprintf(ptr, "[");
288  ptr += pointArray_to_geojson(poly->rings[i], ptr, precision);
289  ptr += sprintf(ptr, "]");
290  }
291  ptr += sprintf(ptr, "]}");
292 
293  return (ptr-output);
294 }
295 
296 static char *
297 asgeojson_poly(const LWPOLY *poly, char *srs, GBOX *bbox, int precision)
298 {
299  char *output;
300  int size;
301 
302  size = asgeojson_poly_size(poly, srs, bbox, precision);
303  output = lwalloc(size);
304  asgeojson_poly_buf(poly, srs, output, bbox, precision);
305 
306  return output;
307 }
308 
309 
310 
315 static size_t
316 asgeojson_multipoint_size(const LWMPOINT *mpoint, char *srs, GBOX *bbox, int precision)
317 {
318  LWPOINT * point;
319  int size;
320  int i;
321 
322  size = sizeof("{'type':'MultiPoint',");
323  if (srs) size += asgeojson_srs_size(srs);
324  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(mpoint->flags), precision);
325  size += sizeof("'coordinates':[]}");
326 
327  for (i=0; i<mpoint->ngeoms; i++)
328  {
329  point = mpoint->geoms[i];
330  size += pointArray_geojson_size(point->point, precision);
331  }
332  size += sizeof(",") * i;
333 
334  return size;
335 }
336 
337 static size_t
338 asgeojson_multipoint_buf(const LWMPOINT *mpoint, char *srs, char *output, GBOX *bbox, int precision)
339 {
340  LWPOINT *point;
341  int i;
342  char *ptr=output;
343 
344  ptr += sprintf(ptr, "{\"type\":\"MultiPoint\",");
345  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
346  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(mpoint->flags), precision);
347  ptr += sprintf(ptr, "\"coordinates\":[");
348 
349  for (i=0; i<mpoint->ngeoms; i++)
350  {
351  if (i) ptr += sprintf(ptr, ",");
352  point = mpoint->geoms[i];
353  ptr += pointArray_to_geojson(point->point, ptr, precision);
354  }
355  ptr += sprintf(ptr, "]}");
356 
357  return (ptr - output);
358 }
359 
360 static char *
361 asgeojson_multipoint(const LWMPOINT *mpoint, char *srs, GBOX *bbox, int precision)
362 {
363  char *output;
364  int size;
365 
366  size = asgeojson_multipoint_size(mpoint, srs, bbox, precision);
367  output = lwalloc(size);
368  asgeojson_multipoint_buf(mpoint, srs, output, bbox, precision);
369 
370  return output;
371 }
372 
373 
374 
379 static size_t
380 asgeojson_multiline_size(const LWMLINE *mline, char *srs, GBOX *bbox, int precision)
381 {
382  LWLINE * line;
383  int size;
384  int i;
385 
386  size = sizeof("{'type':'MultiLineString',");
387  if (srs) size += asgeojson_srs_size(srs);
388  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(mline->flags), precision);
389  size += sizeof("'coordinates':[]}");
390 
391  for (i=0 ; i<mline->ngeoms; i++)
392  {
393  line = mline->geoms[i];
394  size += pointArray_geojson_size(line->points, precision);
395  size += sizeof("[]");
396  }
397  size += sizeof(",") * i;
398 
399  return size;
400 }
401 
402 static size_t
403 asgeojson_multiline_buf(const LWMLINE *mline, char *srs, char *output, GBOX *bbox, int precision)
404 {
405  LWLINE *line;
406  int i;
407  char *ptr=output;
408 
409  ptr += sprintf(ptr, "{\"type\":\"MultiLineString\",");
410  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
411  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(mline->flags), precision);
412  ptr += sprintf(ptr, "\"coordinates\":[");
413 
414  for (i=0; i<mline->ngeoms; i++)
415  {
416  if (i) ptr += sprintf(ptr, ",");
417  ptr += sprintf(ptr, "[");
418  line = mline->geoms[i];
419  ptr += pointArray_to_geojson(line->points, ptr, precision);
420  ptr += sprintf(ptr, "]");
421  }
422 
423  ptr += sprintf(ptr, "]}");
424 
425  return (ptr - output);
426 }
427 
428 static char *
429 asgeojson_multiline(const LWMLINE *mline, char *srs, GBOX *bbox, int precision)
430 {
431  char *output;
432  int size;
433 
434  size = asgeojson_multiline_size(mline, srs, bbox, precision);
435  output = lwalloc(size);
436  asgeojson_multiline_buf(mline, srs, output, bbox, precision);
437 
438  return output;
439 }
440 
441 
442 
447 static size_t
448 asgeojson_multipolygon_size(const LWMPOLY *mpoly, char *srs, GBOX *bbox, int precision)
449 {
450  LWPOLY *poly;
451  int size;
452  int i, j;
453 
454  size = sizeof("{'type':'MultiPolygon',");
455  if (srs) size += asgeojson_srs_size(srs);
456  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(mpoly->flags), precision);
457  size += sizeof("'coordinates':[]}");
458 
459  for (i=0; i < mpoly->ngeoms; i++)
460  {
461  poly = mpoly->geoms[i];
462  for (j=0 ; j <poly->nrings ; j++)
463  {
464  size += pointArray_geojson_size(poly->rings[j], precision);
465  size += sizeof("[]");
466  }
467  size += sizeof("[]");
468  }
469  size += sizeof(",") * i;
470  size += sizeof("]}");
471 
472  return size;
473 }
474 
475 static size_t
476 asgeojson_multipolygon_buf(const LWMPOLY *mpoly, char *srs, char *output, GBOX *bbox, int precision)
477 {
478  LWPOLY *poly;
479  int i, j;
480  char *ptr=output;
481 
482  ptr += sprintf(ptr, "{\"type\":\"MultiPolygon\",");
483  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
484  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(mpoly->flags), precision);
485  ptr += sprintf(ptr, "\"coordinates\":[");
486  for (i=0; i<mpoly->ngeoms; i++)
487  {
488  if (i) ptr += sprintf(ptr, ",");
489  ptr += sprintf(ptr, "[");
490  poly = mpoly->geoms[i];
491  for (j=0 ; j < poly->nrings ; j++)
492  {
493  if (j) ptr += sprintf(ptr, ",");
494  ptr += sprintf(ptr, "[");
495  ptr += pointArray_to_geojson(poly->rings[j], ptr, precision);
496  ptr += sprintf(ptr, "]");
497  }
498  ptr += sprintf(ptr, "]");
499  }
500  ptr += sprintf(ptr, "]}");
501 
502  return (ptr - output);
503 }
504 
505 static char *
506 asgeojson_multipolygon(const LWMPOLY *mpoly, char *srs, GBOX *bbox, int precision)
507 {
508  char *output;
509  int size;
510 
511  size = asgeojson_multipolygon_size(mpoly, srs, bbox, precision);
512  output = lwalloc(size);
513  asgeojson_multipolygon_buf(mpoly, srs, output, bbox, precision);
514 
515  return output;
516 }
517 
518 
519 
524 static size_t
525 asgeojson_collection_size(const LWCOLLECTION *col, char *srs, GBOX *bbox, int precision)
526 {
527  int i;
528  int size;
529  LWGEOM *subgeom;
530 
531  size = sizeof("{'type':'GeometryCollection',");
532  if (srs) size += asgeojson_srs_size(srs);
533  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(col->flags), precision);
534  size += sizeof("'geometries':");
535 
536  for (i=0; i<col->ngeoms; i++)
537  {
538  subgeom = col->geoms[i];
539  size += asgeojson_geom_size(subgeom, NULL, precision);
540  }
541  size += sizeof(",") * i;
542  size += sizeof("]}");
543 
544  return size;
545 }
546 
547 static size_t
548 asgeojson_collection_buf(const LWCOLLECTION *col, char *srs, char *output, GBOX *bbox, int precision)
549 {
550  int i;
551  char *ptr=output;
552  LWGEOM *subgeom;
553 
554  ptr += sprintf(ptr, "{\"type\":\"GeometryCollection\",");
555  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
556  if (col->ngeoms && bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(col->flags), precision);
557  ptr += sprintf(ptr, "\"geometries\":[");
558 
559  for (i=0; i<col->ngeoms; i++)
560  {
561  if (i) ptr += sprintf(ptr, ",");
562  subgeom = col->geoms[i];
563  ptr += asgeojson_geom_buf(subgeom, ptr, NULL, precision);
564  }
565 
566  ptr += sprintf(ptr, "]}");
567 
568  return (ptr - output);
569 }
570 
571 static char *
572 asgeojson_collection(const LWCOLLECTION *col, char *srs, GBOX *bbox, int precision)
573 {
574  char *output;
575  int size;
576 
577  size = asgeojson_collection_size(col, srs, bbox, precision);
578  output = lwalloc(size);
579  asgeojson_collection_buf(col, srs, output, bbox, precision);
580 
581  return output;
582 }
583 
584 
585 
586 static size_t
587 asgeojson_geom_size(const LWGEOM *geom, GBOX *bbox, int precision)
588 {
589  int type = geom->type;
590  size_t size = 0;
591 
592  switch (type)
593  {
594  case POINTTYPE:
595  size = asgeojson_point_size((LWPOINT*)geom, NULL, bbox, precision);
596  break;
597 
598  case LINETYPE:
599  size = asgeojson_line_size((LWLINE*)geom, NULL, bbox, precision);
600  break;
601 
602  case POLYGONTYPE:
603  size = asgeojson_poly_size((LWPOLY*)geom, NULL, bbox, precision);
604  break;
605 
606  case MULTIPOINTTYPE:
607  size = asgeojson_multipoint_size((LWMPOINT*)geom, NULL, bbox, precision);
608  break;
609 
610  case MULTILINETYPE:
611  size = asgeojson_multiline_size((LWMLINE*)geom, NULL, bbox, precision);
612  break;
613 
614  case MULTIPOLYGONTYPE:
615  size = asgeojson_multipolygon_size((LWMPOLY*)geom, NULL, bbox, precision);
616  break;
617 
618  default:
619  lwerror("GeoJson: geometry not supported.");
620  }
621 
622  return size;
623 }
624 
625 
626 static size_t
627 asgeojson_geom_buf(const LWGEOM *geom, char *output, GBOX *bbox, int precision)
628 {
629  int type = geom->type;
630  char *ptr=output;
631 
632  switch (type)
633  {
634  case POINTTYPE:
635  ptr += asgeojson_point_buf((LWPOINT*)geom, NULL, ptr, bbox, precision);
636  break;
637 
638  case LINETYPE:
639  ptr += asgeojson_line_buf((LWLINE*)geom, NULL, ptr, bbox, precision);
640  break;
641 
642  case POLYGONTYPE:
643  ptr += asgeojson_poly_buf((LWPOLY*)geom, NULL, ptr, bbox, precision);
644  break;
645 
646  case MULTIPOINTTYPE:
647  ptr += asgeojson_multipoint_buf((LWMPOINT*)geom, NULL, ptr, bbox, precision);
648  break;
649 
650  case MULTILINETYPE:
651  ptr += asgeojson_multiline_buf((LWMLINE*)geom, NULL, ptr, bbox, precision);
652  break;
653 
654  case MULTIPOLYGONTYPE:
655  ptr += asgeojson_multipolygon_buf((LWMPOLY*)geom, NULL, ptr, bbox, precision);
656  break;
657 
658  default:
659  if (bbox) lwfree(bbox);
660  lwerror("GeoJson: geometry not supported.");
661  }
662 
663  return (ptr-output);
664 }
665 
666 /*
667  * Print an ordinate value using at most the given number of decimal digits
668  *
669  * The actual number of printed decimal digits may be less than the
670  * requested ones if out of significant digits.
671  *
672  * The function will not write more than maxsize bytes, including the
673  * terminating NULL. Returns the number of bytes that would have been
674  * written if there was enough space (excluding terminating NULL).
675  * So a return of ``bufsize'' or more means that the string was
676  * truncated and misses a terminating NULL.
677  *
678  * TODO: export ?
679  *
680  */
681 static int
682 lwprint_double(double d, int maxdd, char *buf, size_t bufsize)
683 {
684  double ad = fabs(d);
685  int ndd = ad < 1 ? 0 : floor(log10(ad))+1; /* non-decimal digits */
686  if (fabs(d) < OUT_MAX_DOUBLE)
687  {
688  if ( maxdd > (OUT_MAX_DOUBLE_PRECISION - ndd) ) maxdd -= ndd;
689  return snprintf(buf, bufsize, "%.*f", maxdd, d);
690  }
691  else
692  {
693  return snprintf(buf, bufsize, "%g", d);
694  }
695 }
696 
697 
698 
699 static size_t
700 pointArray_to_geojson(POINTARRAY *pa, char *output, int precision)
701 {
702  int i;
703  char *ptr;
704 #define BUFSIZE OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION
705  char x[BUFSIZE+1];
706  char y[BUFSIZE+1];
707  char z[BUFSIZE+1];
708 
709  assert ( precision <= OUT_MAX_DOUBLE_PRECISION );
710 
711  /* Ensure a terminating NULL at the end of buffers
712  * so that we don't need to check for truncation
713  * inprint_double */
714  x[BUFSIZE] = '\0';
715  y[BUFSIZE] = '\0';
716  z[BUFSIZE] = '\0';
717 
718  ptr = output;
719 
720  /* TODO: rewrite this loop to be simpler and possibly quicker */
721  if (!FLAGS_GET_Z(pa->flags))
722  {
723  for (i=0; i<pa->npoints; i++)
724  {
725  const POINT2D *pt;
726  pt = getPoint2d_cp(pa, i);
727 
728  lwprint_double(pt->x, precision, x, BUFSIZE);
730  lwprint_double(pt->y, precision, y, BUFSIZE);
732 
733  if ( i ) ptr += sprintf(ptr, ",");
734  ptr += sprintf(ptr, "[%s,%s]", x, y);
735  }
736  }
737  else
738  {
739  for (i=0; i<pa->npoints; i++)
740  {
741  const POINT3DZ *pt;
742  pt = getPoint3dz_cp(pa, i);
743 
744  lwprint_double(pt->x, precision, x, BUFSIZE);
746  lwprint_double(pt->y, precision, y, BUFSIZE);
748  lwprint_double(pt->z, precision, z, BUFSIZE);
750 
751  if ( i ) ptr += sprintf(ptr, ",");
752  ptr += sprintf(ptr, "[%s,%s,%s]", x, y, z);
753  }
754  }
755 
756  return (ptr-output);
757 }
758 
759 
760 
764 static size_t
766 {
767  assert ( precision <= OUT_MAX_DOUBLE_PRECISION );
768  if (FLAGS_NDIMS(pa->flags) == 2)
769  return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(","))
770  * 2 * pa->npoints + sizeof(",[]");
771 
772  return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(",,"))
773  * 3 * pa->npoints + sizeof(",[]");
774 }
static size_t asgeojson_point_buf(const LWPOINT *point, char *srs, char *output, GBOX *bbox, int precision)
#define LINETYPE
Definition: liblwgeom.h:61
static char * asgeojson_collection(const LWCOLLECTION *col, char *srs, GBOX *bbox, int precision)
static size_t asgeojson_multiline_buf(const LWMLINE *mline, char *srs, char *output, GBOX *bbox, int precision)
double z
Definition: liblwgeom.h:290
double y
Definition: liblwgeom.h:290
static size_t asgeojson_srs_buf(char *output, char *srs)
Definition: lwout_geojson.c:94
double x
Definition: liblwgeom.h:290
static char * asgeojson_multipoint(const LWMPOINT *mpoint, char *srs, GBOX *bbox, int precision)
#define BUFSIZE
void lwfree(void *mem)
Definition: lwutil.c:190
int npoints
Definition: liblwgeom.h:327
#define OUT_MAX_DOUBLE_PRECISION
void trim_trailing_zeros(char *num)
Definition: lwutil.c:200
#define POLYGONTYPE
Definition: liblwgeom.h:62
double xmax
Definition: liblwgeom.h:249
#define MULTIPOINTTYPE
Definition: liblwgeom.h:63
static size_t asgeojson_poly_buf(const LWPOLY *poly, char *srs, char *output, GBOX *bbox, int precision)
uint8_t flags
Definition: liblwgeom.h:421
static size_t asgeojson_bbox_size(int hasz, int precision)
Handle Bbox.
POINTARRAY * point
Definition: liblwgeom.h:367
int ngeoms
Definition: liblwgeom.h:437
char * lwgeom_to_geojson(const LWGEOM *geom, char *srs, int precision, int has_bbox)
Takes a GEOMETRY and returns a GeoJson representation.
Definition: lwout_geojson.c:35
static size_t asgeojson_multiline_size(const LWMLINE *mline, char *srs, GBOX *bbox, int precision)
Multiline Geometry.
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
double x
Definition: liblwgeom.h:284
uint8_t flags
Definition: liblwgeom.h:460
uint8_t flags
Definition: liblwgeom.h:434
double zmax
Definition: liblwgeom.h:253
double ymin
Definition: liblwgeom.h:250
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:164
static char * asgeojson_multiline(const LWMLINE *mline, char *srs, GBOX *bbox, int precision)
static size_t asgeojson_multipoint_buf(const LWMPOINT *mpoint, char *srs, char *output, GBOX *bbox, int precision)
static char * asgeojson_line(const LWLINE *line, char *srs, GBOX *bbox, int precision)
double xmin
Definition: liblwgeom.h:248
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, int n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:458
uint8_t flags
Definition: liblwgeom.h:325
static char * asgeojson_point(const LWPOINT *point, char *srs, GBOX *bbox, int precision)
static size_t asgeojson_collection_buf(const LWCOLLECTION *col, char *srs, char *output, GBOX *bbox, int precision)
LWPOLY ** geoms
Definition: liblwgeom.h:452
LWGEOM ** geoms
Definition: liblwgeom.h:465
static int lwprint_double(double d, int maxdd, char *buf, size_t bufsize)
uint8_t flags
Definition: liblwgeom.h:447
POINTARRAY ** rings
Definition: liblwgeom.h:413
LWPOINT ** geoms
Definition: liblwgeom.h:426
static size_t asgeojson_bbox_buf(char *output, GBOX *bbox, int hasz, int precision)
int nrings
Definition: liblwgeom.h:411
double ymax
Definition: liblwgeom.h:251
double y
Definition: liblwgeom.h:284
static size_t pointArray_to_geojson(POINTARRAY *pa, char *buf, int precision)
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:106
static size_t asgeojson_line_buf(const LWLINE *line, char *srs, char *output, GBOX *bbox, int precision)
tuple x
Definition: pixval.py:53
int ngeoms
Definition: liblwgeom.h:450
static char * asgeojson_poly(const LWPOLY *poly, char *srs, GBOX *bbox, int precision)
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:65
#define OUT_MAX_DOUBLE
uint8_t flags
Definition: liblwgeom.h:364
static size_t asgeojson_point_size(const LWPOINT *point, char *srs, GBOX *bbox, int precision)
Point Geometry.
LWLINE ** geoms
Definition: liblwgeom.h:439
static size_t asgeojson_multipolygon_size(const LWMPOLY *mpoly, char *srs, GBOX *bbox, int precision)
MultiPolygon Geometry.
const POINT3DZ * getPoint3dz_cp(const POINTARRAY *pa, int n)
Returns a POINT3DZ pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:472
static size_t asgeojson_geom_size(const LWGEOM *geom, GBOX *bbox, int precision)
static size_t asgeojson_multipoint_size(const LWMPOINT *mpoint, char *srs, GBOX *bbox, int precision)
Multipoint Geometry.
double zmin
Definition: liblwgeom.h:252
static char * asgeojson_multipolygon(const LWMPOLY *mpoly, char *srs, GBOX *bbox, int precision)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
int lwpoint_is_empty(const LWPOINT *point)
Definition: lwpoint.c:258
static size_t asgeojson_multipolygon_buf(const LWMPOLY *mpoly, char *srs, char *output, GBOX *bbox, int precision)
uint8_t type
Definition: liblwgeom.h:352
static size_t asgeojson_srs_size(char *srs)
Handle SRS.
Definition: lwout_geojson.c:82
uint8_t flags
Definition: liblwgeom.h:408
static size_t asgeojson_line_size(const LWLINE *line, char *srs, GBOX *bbox, int precision)
Line Geometry.
void * lwalloc(size_t size)
Definition: lwutil.c:175
#define OUT_MAX_DIGS_DOUBLE
#define MULTILINETYPE
Definition: liblwgeom.h:64
int ngeoms
Definition: liblwgeom.h:424
uint8_t flags
Definition: liblwgeom.h:375
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:118
static size_t asgeojson_poly_size(const LWPOLY *poly, char *srs, GBOX *bbox, int precision)
Polygon Geometry.
tuple y
Definition: pixval.py:54
static size_t asgeojson_collection_size(const LWCOLLECTION *col, char *srs, GBOX *bbox, int precision)
Collection Geometry.
#define COLLECTIONTYPE
Definition: liblwgeom.h:66
static size_t asgeojson_geom_buf(const LWGEOM *geom, char *output, GBOX *bbox, int precision)
static size_t pointArray_geojson_size(POINTARRAY *pa, int precision)
Returns maximum size of rendered pointarray in bytes.
POINTARRAY * points
Definition: liblwgeom.h:378
int lwgeom_calculate_gbox_cartesian(const LWGEOM *lwgeom, GBOX *gbox)
Calculate the 2-4D bounding box of a geometry.
Definition: g_box.c:607