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