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