PostGIS  3.3.9dev-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 lwvarlena_t *asgeojson_point(const LWPOINT *point, const char *srs, GBOX *bbox, int precision);
32 static lwvarlena_t *asgeojson_line(const LWLINE *line, const char *srs, GBOX *bbox, int precision);
33 static lwvarlena_t *asgeojson_triangle(const LWTRIANGLE *tri, const char *srs, GBOX *bbox, int precision);
34 static lwvarlena_t *asgeojson_poly(const LWPOLY *poly, const char *srs, GBOX *bbox, int precision);
35 static lwvarlena_t *asgeojson_multipoint(const LWMPOINT *mpoint, const char *srs, GBOX *bbox, int precision);
36 static lwvarlena_t *asgeojson_multiline(const LWMLINE *mline, const char *srs, GBOX *bbox, int precision);
37 static lwvarlena_t *asgeojson_multipolygon(const LWMPOLY *mpoly, const char *srs, GBOX *bbox, int precision);
38 static lwvarlena_t *asgeojson_collection(const LWCOLLECTION *col, const char *srs, GBOX *bbox, int precision);
39 static size_t asgeojson_geom_size(const LWGEOM *geom, GBOX *bbox, int precision);
40 static size_t asgeojson_geom_buf(const LWGEOM *geom, char *output, GBOX *bbox, int precision);
41 
42 static size_t pointArray_to_geojson(POINTARRAY *pa, char *buf, int precision);
44 
49 lwgeom_to_geojson(const LWGEOM *geom, const char *srs, int precision, int has_bbox)
50 {
51  int type = geom->type;
52  GBOX *bbox = NULL;
53  GBOX tmp = {0};
54 
55  if (has_bbox)
56  {
57  /* Whether these are geography or geometry,
58  the GeoJSON expects a cartesian bounding box */
60  bbox = &tmp;
61  }
62 
63  switch (type)
64  {
65  case POINTTYPE:
66  return asgeojson_point((LWPOINT*)geom, srs, bbox, precision);
67  case LINETYPE:
68  return asgeojson_line((LWLINE*)geom, srs, bbox, precision);
69  case POLYGONTYPE:
70  return asgeojson_poly((LWPOLY*)geom, srs, bbox, precision);
71  case MULTIPOINTTYPE:
72  return asgeojson_multipoint((LWMPOINT*)geom, srs, bbox, precision);
73  case MULTILINETYPE:
74  return asgeojson_multiline((LWMLINE*)geom, srs, bbox, precision);
75  case MULTIPOLYGONTYPE:
76  return asgeojson_multipolygon((LWMPOLY*)geom, srs, bbox, precision);
77  case TRIANGLETYPE:
78  return asgeojson_triangle((LWTRIANGLE *)geom, srs, bbox, precision);
79  case TINTYPE:
80  case COLLECTIONTYPE:
81  return asgeojson_collection((LWCOLLECTION*)geom, srs, bbox, precision);
82  default:
83  lwerror("lwgeom_to_geojson: '%s' geometry type not supported",
84  lwtype_name(type));
85  }
86 
87  /* Never get here */
88  return NULL;
89 }
90 
91 
92 
96 static size_t
97 asgeojson_srs_size(const char *srs)
98 {
99  int size;
100 
101  size = sizeof("'crs':{'type':'name',");
102  size += sizeof("'properties':{'name':''}},");
103  size += strlen(srs) * sizeof(char);
104 
105  return size;
106 }
107 
108 static size_t
109 asgeojson_srs_buf(char *output, const char *srs)
110 {
111  char *ptr = output;
112 
113  ptr += sprintf(ptr, "\"crs\":{\"type\":\"name\",");
114  ptr += sprintf(ptr, "\"properties\":{\"name\":\"%s\"}},", srs);
115 
116  return (ptr-output);
117 }
118 
119 
120 
124 static size_t
126 {
127  int size;
128 
129  if (!hasz)
130  {
131  size = sizeof("\"bbox\":[,,,],");
132  size += 2 * 2 * (OUT_MAX_BYTES_DOUBLE + precision);
133  }
134  else
135  {
136  size = sizeof("\"bbox\":[,,,,,],");
137  size += 2 * 3 * (OUT_MAX_BYTES_DOUBLE + precision);
138  }
139 
140  return size;
141 }
142 
143 static size_t
144 asgeojson_bbox_buf(char *output, GBOX *bbox, int hasz, int precision)
145 {
146  char *ptr = output;
147 
148  if (!hasz)
149  ptr += sprintf(ptr, "\"bbox\":[%.*f,%.*f,%.*f,%.*f],",
150  precision, bbox->xmin, precision, bbox->ymin,
151  precision, bbox->xmax, precision, bbox->ymax);
152  else
153  ptr += sprintf(ptr, "\"bbox\":[%.*f,%.*f,%.*f,%.*f,%.*f,%.*f],",
154  precision, bbox->xmin, precision, bbox->ymin, precision, bbox->zmin,
155  precision, bbox->xmax, precision, bbox->ymax, precision, bbox->zmax);
156 
157  return (ptr-output);
158 }
159 
160 
161 
166 static size_t
167 asgeojson_point_size(const LWPOINT *point, const char *srs, GBOX *bbox, int precision)
168 {
169  int size;
170 
171  size = pointArray_geojson_size(point->point, precision);
172  size += sizeof("{'type':'Point',");
173  size += sizeof("'coordinates':}");
174 
175  if ( lwpoint_is_empty(point) )
176  size += 2; /* [] */
177 
178  if (srs) size += asgeojson_srs_size(srs);
179  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(point->flags), precision);
180 
181  return size;
182 }
183 
184 static size_t
185 asgeojson_point_buf(const LWPOINT *point, const char *srs, char *output, GBOX *bbox, int precision)
186 {
187  char *ptr = output;
188 
189  ptr += sprintf(ptr, "{\"type\":\"Point\",");
190  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
191  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(point->flags), precision);
192 
193  ptr += sprintf(ptr, "\"coordinates\":");
194  if ( lwpoint_is_empty(point) )
195  ptr += sprintf(ptr, "[]");
196  ptr += pointArray_to_geojson(point->point, ptr, precision);
197  ptr += sprintf(ptr, "}");
198 
199  return (ptr-output);
200 }
201 
202 static lwvarlena_t *
203 asgeojson_point(const LWPOINT *point, const char *srs, GBOX *bbox, int precision)
204 {
205  uint32_t size = asgeojson_point_size(point, srs, bbox, precision);
206  lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
207  size = asgeojson_point_buf(point, srs, output->data, bbox, precision);
208  LWSIZE_SET(output->size, size + LWVARHDRSZ);
209  return output;
210 }
211 
216 static size_t
217 asgeojson_triangle_size(const LWTRIANGLE *tri, const char *srs, GBOX *bbox, int precision)
218 {
219  int size;
220 
221  size = sizeof("{'type':'Polygon',");
222  if (srs)
223  size += asgeojson_srs_size(srs);
224  if (bbox)
226  size += sizeof("'coordinates':[[]]}");
228 
229  return size;
230 }
231 
232 static size_t
233 asgeojson_triangle_buf(const LWTRIANGLE *tri, const char *srs, char *output, GBOX *bbox, int precision)
234 {
235  char *ptr = output;
236 
237  ptr += sprintf(ptr, "{\"type\":\"Polygon\",");
238  if (srs)
239  ptr += asgeojson_srs_buf(ptr, srs);
240  if (bbox)
241  ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(tri->flags), precision);
242  ptr += sprintf(ptr, "\"coordinates\":[[");
243  ptr += pointArray_to_geojson(tri->points, ptr, precision);
244  ptr += sprintf(ptr, "]]}");
245 
246  return (ptr - output);
247 }
248 
249 static lwvarlena_t *
250 asgeojson_triangle(const LWTRIANGLE *tri, const char *srs, GBOX *bbox, int precision)
251 {
252  uint32_t size = asgeojson_triangle_size(tri, srs, bbox, precision);
253  lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
254  size = asgeojson_triangle_buf(tri, srs, output->data, bbox, precision);
255  LWSIZE_SET(output->size, size + LWVARHDRSZ);
256  return output;
257 }
258 
263 static size_t
264 asgeojson_line_size(const LWLINE *line, const char *srs, GBOX *bbox, int precision)
265 {
266  int size;
267 
268  size = sizeof("{'type':'LineString',");
269  if (srs) size += asgeojson_srs_size(srs);
270  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(line->flags), precision);
271  size += sizeof("'coordinates':[]}");
272  size += pointArray_geojson_size(line->points, precision);
273 
274  return size;
275 }
276 
277 static size_t
278 asgeojson_line_buf(const LWLINE *line, const char *srs, char *output, GBOX *bbox, int precision)
279 {
280  char *ptr=output;
281 
282  ptr += sprintf(ptr, "{\"type\":\"LineString\",");
283  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
284  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(line->flags), precision);
285  ptr += sprintf(ptr, "\"coordinates\":[");
286  ptr += pointArray_to_geojson(line->points, ptr, precision);
287  ptr += sprintf(ptr, "]}");
288 
289  return (ptr-output);
290 }
291 
292 static lwvarlena_t *
293 asgeojson_line(const LWLINE *line, const char *srs, GBOX *bbox, int precision)
294 {
295  uint32_t size = asgeojson_line_size(line, srs, bbox, precision);
296  lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
297  size = asgeojson_line_buf(line, srs, output->data, bbox, precision);
298  LWSIZE_SET(output->size, size + LWVARHDRSZ);
299  return output;
300 }
301 
302 
303 
308 static size_t
309 asgeojson_poly_size(const LWPOLY *poly, const char *srs, GBOX *bbox, int precision)
310 {
311  size_t size;
312  uint32_t i;
313 
314  size = sizeof("{\"type\":\"Polygon\",");
315  if (srs) size += asgeojson_srs_size(srs);
316  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(poly->flags), precision);
317  size += sizeof("\"coordinates\":[");
318  for (i=0; i<poly->nrings; i++)
319  {
320  size += pointArray_geojson_size(poly->rings[i], precision);
321  size += sizeof("[]");
322  }
323  size += sizeof(",") * i;
324  size += sizeof("]}");
325 
326  return size;
327 }
328 
329 static size_t
330 asgeojson_poly_buf(const LWPOLY *poly, const char *srs, char *output, GBOX *bbox, int precision)
331 {
332  uint32_t i;
333 
334  char *ptr=output;
335 
336  ptr += sprintf(ptr, "{\"type\":\"Polygon\",");
337  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
338  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(poly->flags), precision);
339  ptr += sprintf(ptr, "\"coordinates\":[");
340  for (i=0; i<poly->nrings; i++)
341  {
342  if (i) ptr += sprintf(ptr, ",");
343  ptr += sprintf(ptr, "[");
344  ptr += pointArray_to_geojson(poly->rings[i], ptr, precision);
345  ptr += sprintf(ptr, "]");
346  }
347  ptr += sprintf(ptr, "]}");
348 
349  return (ptr-output);
350 }
351 
352 static lwvarlena_t *
353 asgeojson_poly(const LWPOLY *poly, const char *srs, GBOX *bbox, int precision)
354 {
355  uint32_t size = asgeojson_poly_size(poly, srs, bbox, precision);
356  lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
357  size = asgeojson_poly_buf(poly, srs, output->data, bbox, precision);
358  LWSIZE_SET(output->size, size + LWVARHDRSZ);
359  return output;
360 }
361 
362 
363 
368 static size_t
369 asgeojson_multipoint_size(const LWMPOINT *mpoint, const char *srs, GBOX *bbox, int precision)
370 {
371  LWPOINT * point;
372  int size;
373  uint32_t i, ngeoms = mpoint->ngeoms;
374 
375  size = sizeof("{'type':'MultiPoint',");
376  if (srs) size += asgeojson_srs_size(srs);
377  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(mpoint->flags), precision);
378  size += sizeof("'coordinates':[]}");
379 
380  if (lwgeom_is_empty((LWGEOM*)mpoint))
381  ngeoms = 0;
382 
383  for (i=0; i<ngeoms; i++)
384  {
385  point = mpoint->geoms[i];
386  size += pointArray_geojson_size(point->point, precision);
387  }
388  size += sizeof(",") * i;
389 
390  return size;
391 }
392 
393 static size_t
394 asgeojson_multipoint_buf(const LWMPOINT *mpoint, const char *srs, char *output, GBOX *bbox, int precision)
395 {
396  LWPOINT *point;
397  uint32_t i, ngeoms = mpoint->ngeoms;
398  char *ptr=output;
399 
400  ptr += sprintf(ptr, "{\"type\":\"MultiPoint\",");
401  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
402  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(mpoint->flags), precision);
403  ptr += sprintf(ptr, "\"coordinates\":[");
404 
405  if (lwgeom_is_empty((LWGEOM*)mpoint))
406  ngeoms = 0;
407 
408  for (i=0; i<ngeoms; i++)
409  {
410  if (i) ptr += sprintf(ptr, ",");
411  point = mpoint->geoms[i];
412  ptr += pointArray_to_geojson(point->point, ptr, precision);
413  }
414  ptr += sprintf(ptr, "]}");
415 
416  return (ptr - output);
417 }
418 
419 static lwvarlena_t *
420 asgeojson_multipoint(const LWMPOINT *mpoint, const char *srs, GBOX *bbox, int precision)
421 {
422  uint32_t size = asgeojson_multipoint_size(mpoint, srs, bbox, precision);
423  lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
424  size = asgeojson_multipoint_buf(mpoint, srs, output->data, bbox, precision);
425  LWSIZE_SET(output->size, size + LWVARHDRSZ);
426  return output;
427 }
428 
429 
430 
435 static size_t
436 asgeojson_multiline_size(const LWMLINE *mline, const char *srs, GBOX *bbox, int precision)
437 {
438  LWLINE * line;
439  int size;
440  uint32_t i, ngeoms = mline->ngeoms;
441 
442  size = sizeof("{'type':'MultiLineString',");
443  if (srs) size += asgeojson_srs_size(srs);
444  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(mline->flags), precision);
445  size += sizeof("'coordinates':[]}");
446 
447  if (lwgeom_is_empty((LWGEOM*)mline))
448  ngeoms = 0;
449 
450  for (i=0 ; i<ngeoms; i++)
451  {
452  line = mline->geoms[i];
453  size += pointArray_geojson_size(line->points, precision);
454  size += sizeof("[]");
455  }
456  size += sizeof(",") * i;
457 
458  return size;
459 }
460 
461 static size_t
462 asgeojson_multiline_buf(const LWMLINE *mline, const char *srs, char *output, GBOX *bbox, int precision)
463 {
464  LWLINE *line;
465  uint32_t i, ngeoms = mline->ngeoms;
466  char *ptr=output;
467 
468  ptr += sprintf(ptr, "{\"type\":\"MultiLineString\",");
469  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
470  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(mline->flags), precision);
471  ptr += sprintf(ptr, "\"coordinates\":[");
472 
473  if (lwgeom_is_empty((LWGEOM*)mline))
474  ngeoms = 0;
475 
476  for (i=0; i<ngeoms; i++)
477  {
478  if (i) ptr += sprintf(ptr, ",");
479  ptr += sprintf(ptr, "[");
480  line = mline->geoms[i];
481  ptr += pointArray_to_geojson(line->points, ptr, precision);
482  ptr += sprintf(ptr, "]");
483  }
484 
485  ptr += sprintf(ptr, "]}");
486 
487  return (ptr - output);
488 }
489 
490 static lwvarlena_t *
491 asgeojson_multiline(const LWMLINE *mline, const char *srs, GBOX *bbox, int precision)
492 {
493  uint32_t size = asgeojson_multiline_size(mline, srs, bbox, precision);
494  lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
495  size = asgeojson_multiline_buf(mline, srs, output->data, bbox, precision);
496  LWSIZE_SET(output->size, size + LWVARHDRSZ);
497  return output;
498 }
499 
500 
501 
506 static size_t
507 asgeojson_multipolygon_size(const LWMPOLY *mpoly, const char *srs, GBOX *bbox, int precision)
508 {
509  LWPOLY *poly;
510  int size;
511  uint32_t i, j, ngeoms = mpoly->ngeoms;
512 
513  size = sizeof("{'type':'MultiPolygon',");
514  if (srs) size += asgeojson_srs_size(srs);
515  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(mpoly->flags), precision);
516  size += sizeof("'coordinates':[]}");
517 
518  if (lwgeom_is_empty((LWGEOM*)mpoly))
519  ngeoms = 0;
520 
521  for (i=0; i < ngeoms; i++)
522  {
523  poly = mpoly->geoms[i];
524  for (j=0 ; j <poly->nrings ; j++)
525  {
526  size += pointArray_geojson_size(poly->rings[j], precision);
527  size += sizeof("[]");
528  }
529  size += sizeof("[]");
530  }
531  size += sizeof(",") * i;
532  size += sizeof("]}");
533 
534  return size;
535 }
536 
537 static size_t
538 asgeojson_multipolygon_buf(const LWMPOLY *mpoly, const char *srs, char *output, GBOX *bbox, int precision)
539 {
540  LWPOLY *poly;
541  uint32_t i, j, ngeoms = mpoly->ngeoms;
542  char *ptr=output;
543 
544  ptr += sprintf(ptr, "{\"type\":\"MultiPolygon\",");
545  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
546  if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(mpoly->flags), precision);
547  ptr += sprintf(ptr, "\"coordinates\":[");
548 
549  if (lwgeom_is_empty((LWGEOM*)mpoly))
550  ngeoms = 0;
551 
552  for (i=0; i < ngeoms; i++)
553  {
554  if (i) ptr += sprintf(ptr, ",");
555  ptr += sprintf(ptr, "[");
556  poly = mpoly->geoms[i];
557  for (j=0 ; j < poly->nrings ; j++)
558  {
559  if (j) ptr += sprintf(ptr, ",");
560  ptr += sprintf(ptr, "[");
561  ptr += pointArray_to_geojson(poly->rings[j], ptr, precision);
562  ptr += sprintf(ptr, "]");
563  }
564  ptr += sprintf(ptr, "]");
565  }
566  ptr += sprintf(ptr, "]}");
567 
568  return (ptr - output);
569 }
570 
571 static lwvarlena_t *
572 asgeojson_multipolygon(const LWMPOLY *mpoly, const char *srs, GBOX *bbox, int precision)
573 {
574  uint32_t size = asgeojson_multipolygon_size(mpoly, srs, bbox, precision);
575  lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
576  size = asgeojson_multipolygon_buf(mpoly, srs, output->data, bbox, precision);
577  LWSIZE_SET(output->size, size + LWVARHDRSZ);
578  return output;
579 }
580 
581 
582 
587 static size_t
588 asgeojson_collection_size(const LWCOLLECTION *col, const char *srs, GBOX *bbox, int precision)
589 {
590  uint32_t i, ngeoms = col->ngeoms;
591  size_t size;
592  LWGEOM *subgeom;
593 
594  size = sizeof("{'type':'GeometryCollection',");
595  if (srs) size += asgeojson_srs_size(srs);
596  if (bbox) size += asgeojson_bbox_size(FLAGS_GET_Z(col->flags), precision);
597  size += sizeof("'geometries':");
598 
599  if (lwgeom_is_empty((LWGEOM*)col))
600  ngeoms = 0;
601 
602  for (i=0; i<ngeoms; i++)
603  {
604  subgeom = col->geoms[i];
605  size += asgeojson_geom_size(subgeom, NULL, precision);
606  }
607  size += sizeof(",") * i;
608  size += sizeof("]}");
609 
610  return size;
611 }
612 
613 static size_t
614 asgeojson_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, GBOX *bbox, int precision)
615 {
616  uint32_t i, ngeoms = col->ngeoms;
617  char *ptr=output;
618  LWGEOM *subgeom;
619 
620  ptr += sprintf(ptr, "{\"type\":\"GeometryCollection\",");
621  if (srs) ptr += asgeojson_srs_buf(ptr, srs);
622  if (col->ngeoms && bbox) ptr += asgeojson_bbox_buf(ptr, bbox, FLAGS_GET_Z(col->flags), precision);
623  ptr += sprintf(ptr, "\"geometries\":[");
624 
625  if (lwgeom_is_empty((LWGEOM*)col))
626  ngeoms = 0;
627 
628  for (i=0; i<ngeoms; i++)
629  {
630  if (i) ptr += sprintf(ptr, ",");
631  subgeom = col->geoms[i];
632  ptr += asgeojson_geom_buf(subgeom, ptr, NULL, precision);
633  }
634 
635  ptr += sprintf(ptr, "]}");
636 
637  return (ptr - output);
638 }
639 
640 static lwvarlena_t *
641 asgeojson_collection(const LWCOLLECTION *col, const char *srs, GBOX *bbox, int precision)
642 {
643  uint32_t size = asgeojson_collection_size(col, srs, bbox, precision);
644  lwvarlena_t *output = (lwvarlena_t *)lwalloc(size + LWVARHDRSZ);
645  size = asgeojson_collection_buf(col, srs, output->data, bbox, precision);
646  LWSIZE_SET(output->size, size + LWVARHDRSZ);
647  return output;
648 }
649 
650 
651 
652 static size_t
653 asgeojson_geom_size(const LWGEOM *geom, GBOX *bbox, int precision)
654 {
655  switch (geom->type)
656  {
657  case POINTTYPE:
658  return asgeojson_point_size((LWPOINT *)geom, NULL, bbox, precision);
659  case LINETYPE:
660  return asgeojson_line_size((LWLINE *)geom, NULL, bbox, precision);
661  case TRIANGLETYPE:
662  return asgeojson_triangle_size((LWTRIANGLE *)geom, NULL, bbox, precision);
663  case POLYGONTYPE:
664  return asgeojson_poly_size((LWPOLY *)geom, NULL, bbox, precision);
665  case MULTIPOINTTYPE:
666  return asgeojson_multipoint_size((LWMPOINT *)geom, NULL, bbox, precision);
667  case MULTILINETYPE:
668  return asgeojson_multiline_size((LWMLINE *)geom, NULL, bbox, precision);
669  case MULTIPOLYGONTYPE:
670  return asgeojson_multipolygon_size((LWMPOLY *)geom, NULL, bbox, precision);
671  default:
672  lwerror("GeoJson: geometry not supported.");
673  return 0;
674  }
675 }
676 
677 
678 static size_t
679 asgeojson_geom_buf(const LWGEOM *geom, char *output, GBOX *bbox, int precision)
680 {
681  int type = geom->type;
682  char *ptr=output;
683 
684  switch (type)
685  {
686  case POINTTYPE:
687  ptr += asgeojson_point_buf((LWPOINT*)geom, NULL, ptr, bbox, precision);
688  break;
689 
690  case LINETYPE:
691  ptr += asgeojson_line_buf((LWLINE*)geom, NULL, ptr, bbox, precision);
692  break;
693 
694  case POLYGONTYPE:
695  ptr += asgeojson_poly_buf((LWPOLY*)geom, NULL, ptr, bbox, precision);
696  break;
697 
698  case TRIANGLETYPE:
699  ptr += asgeojson_triangle_buf((LWTRIANGLE *)geom, NULL, ptr, bbox, precision);
700  break;
701 
702  case MULTIPOINTTYPE:
703  ptr += asgeojson_multipoint_buf((LWMPOINT*)geom, NULL, ptr, bbox, precision);
704  break;
705 
706  case MULTILINETYPE:
707  ptr += asgeojson_multiline_buf((LWMLINE*)geom, NULL, ptr, bbox, precision);
708  break;
709 
710  case MULTIPOLYGONTYPE:
711  ptr += asgeojson_multipolygon_buf((LWMPOLY*)geom, NULL, ptr, bbox, precision);
712  break;
713 
714  default:
715  if (bbox) lwfree(bbox);
716  lwerror("GeoJson: geometry not supported.");
717  }
718 
719  return (ptr-output);
720 }
721 
722 static size_t
723 pointArray_to_geojson(POINTARRAY *pa, char *output, int precision)
724 {
725  char *ptr = output;
726 
727  if (!FLAGS_GET_Z(pa->flags))
728  {
729  for (uint32_t i = 0; i < pa->npoints; i++)
730  {
731  if (i)
732  {
733  *ptr = ',';
734  ptr++;
735  }
736  const POINT2D *pt = getPoint2d_cp(pa, i);
737 
738  *ptr = '[';
739  ptr++;
740  ptr += lwprint_double(pt->x, precision, ptr);
741  *ptr = ',';
742  ptr++;
743  ptr += lwprint_double(pt->y, precision, ptr);
744  *ptr = ']';
745  ptr++;
746  }
747  }
748  else
749  {
750  for (uint32_t i = 0; i < pa->npoints; i++)
751  {
752  if (i)
753  {
754  *ptr = ',';
755  ptr++;
756  }
757 
758  const POINT3D *pt = getPoint3d_cp(pa, i);
759  *ptr = '[';
760  ptr++;
761  ptr += lwprint_double(pt->x, precision, ptr);
762  *ptr = ',';
763  ptr++;
764  ptr += lwprint_double(pt->y, precision, ptr);
765  *ptr = ',';
766  ptr++;
767  ptr += lwprint_double(pt->z, precision, ptr);
768  *ptr = ']';
769  ptr++;
770  }
771  }
772  *ptr = '\0';
773 
774  return (ptr-output);
775 }
776 
780 static size_t
782 {
783  if (FLAGS_NDIMS(pa->flags) == 2)
784  return (OUT_MAX_BYTES_DOUBLE + precision + sizeof(",")) * 2 * pa->npoints + sizeof(",[]");
785 
786  return (OUT_MAX_BYTES_DOUBLE + precision + sizeof(",,")) * 3 * pa->npoints + sizeof(",[]");
787 }
static uint8_t precision
Definition: cu_in_twkb.c:25
int lwgeom_calculate_gbox_cartesian(const LWGEOM *lwgeom, GBOX *gbox)
Calculate the 2-4D bounding box of a geometry.
Definition: gbox.c:740
#define COLLECTIONTYPE
Definition: liblwgeom.h:123
#define LWVARHDRSZ
Definition: liblwgeom.h:326
#define MULTILINETYPE
Definition: liblwgeom.h:121
#define LINETYPE
Definition: liblwgeom.h:118
#define MULTIPOINTTYPE
Definition: liblwgeom.h:120
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:117
#define FLAGS_GET_Z(flags)
Definition: liblwgeom.h:180
#define TINTYPE
Definition: liblwgeom.h:131
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:122
void lwfree(void *mem)
Definition: lwutil.c:242
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:194
#define POLYGONTYPE
Definition: liblwgeom.h:119
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:216
#define LWSIZE_SET(varsize, len)
Definition: liblwgeom.h:340
#define TRIANGLETYPE
Definition: liblwgeom.h:130
void * lwalloc(size_t size)
Definition: lwutil.c:227
#define OUT_MAX_BYTES_DOUBLE
int lwpoint_is_empty(const LWPOINT *point)
int lwprint_double(double d, int maxdd, char *buf)
Definition: lwprint.c:463
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition: lwinline.h:101
static const POINT3D * getPoint3d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT3D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition: lwinline.h:113
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwinline.h:203
static size_t asgeojson_srs_buf(char *output, const char *srs)
static size_t asgeojson_geom_size(const LWGEOM *geom, GBOX *bbox, int precision)
static size_t asgeojson_point_buf(const LWPOINT *point, const char *srs, char *output, GBOX *bbox, int precision)
static lwvarlena_t * asgeojson_multipolygon(const LWMPOLY *mpoly, const char *srs, GBOX *bbox, int precision)
static size_t pointArray_geojson_size(POINTARRAY *pa, int precision)
static lwvarlena_t * asgeojson_triangle(const LWTRIANGLE *tri, const char *srs, GBOX *bbox, int precision)
static size_t asgeojson_srs_size(const char *srs)
Handle SRS.
Definition: lwout_geojson.c:97
static lwvarlena_t * asgeojson_point(const LWPOINT *point, const char *srs, GBOX *bbox, int precision)
static size_t asgeojson_geom_buf(const LWGEOM *geom, char *output, GBOX *bbox, int precision)
static size_t pointArray_to_geojson(POINTARRAY *pa, char *buf, int precision)
static size_t asgeojson_point_size(const LWPOINT *point, const char *srs, GBOX *bbox, int precision)
Point Geometry.
static lwvarlena_t * asgeojson_poly(const LWPOLY *poly, const char *srs, GBOX *bbox, int precision)
static lwvarlena_t * asgeojson_line(const LWLINE *line, const char *srs, GBOX *bbox, int precision)
static size_t asgeojson_triangle_size(const LWTRIANGLE *tri, const char *srs, GBOX *bbox, int precision)
Triangle Geometry.
lwvarlena_t * lwgeom_to_geojson(const LWGEOM *geom, const char *srs, int precision, int has_bbox)
Takes a GEOMETRY and returns a GeoJson representation.
Definition: lwout_geojson.c:49
static lwvarlena_t * asgeojson_multipoint(const LWMPOINT *mpoint, const char *srs, GBOX *bbox, int precision)
static size_t asgeojson_bbox_size(int hasz, int precision)
Handle Bbox.
static lwvarlena_t * asgeojson_collection(const LWCOLLECTION *col, const char *srs, GBOX *bbox, int precision)
static size_t asgeojson_triangle_buf(const LWTRIANGLE *tri, const char *srs, char *output, GBOX *bbox, int precision)
static size_t asgeojson_bbox_buf(char *output, GBOX *bbox, int hasz, int precision)
static lwvarlena_t * asgeojson_multiline(const LWMLINE *mline, const char *srs, GBOX *bbox, int precision)
type
Definition: ovdump.py:42
double ymax
Definition: liblwgeom.h:372
double zmax
Definition: liblwgeom.h:374
double xmax
Definition: liblwgeom.h:370
double zmin
Definition: liblwgeom.h:373
double ymin
Definition: liblwgeom.h:371
double xmin
Definition: liblwgeom.h:369
lwflags_t flags
Definition: liblwgeom.h:592
uint32_t ngeoms
Definition: liblwgeom.h:595
uint8_t type
Definition: liblwgeom.h:477
lwflags_t flags
Definition: liblwgeom.h:500
POINTARRAY * points
Definition: liblwgeom.h:498
lwflags_t flags
Definition: liblwgeom.h:564
uint32_t ngeoms
Definition: liblwgeom.h:567
lwflags_t flags
Definition: liblwgeom.h:550
uint32_t ngeoms
Definition: liblwgeom.h:553
uint32_t ngeoms
Definition: liblwgeom.h:581
lwflags_t flags
Definition: liblwgeom.h:578
POINTARRAY * point
Definition: liblwgeom.h:486
lwflags_t flags
Definition: liblwgeom.h:488
POINTARRAY ** rings
Definition: liblwgeom.h:534
uint32_t nrings
Definition: liblwgeom.h:539
lwflags_t flags
Definition: liblwgeom.h:536
lwflags_t flags
Definition: liblwgeom.h:512
POINTARRAY * points
Definition: liblwgeom.h:510
double y
Definition: liblwgeom.h:405
double x
Definition: liblwgeom.h:405
double z
Definition: liblwgeom.h:417
double x
Definition: liblwgeom.h:417
double y
Definition: liblwgeom.h:417
lwflags_t flags
Definition: liblwgeom.h:446
uint32_t npoints
Definition: liblwgeom.h:442
uint32_t size
Definition: liblwgeom.h:322
char data[]
Definition: liblwgeom.h:323