PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
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 "stringbuffer.h"
29#include <string.h> /* strlen */
30#include <assert.h>
31
32
40
41enum {
44};
45
46static void asgeojson_geometry(stringbuffer_t *sb, const LWGEOM *geom, const geojson_opts *opts);
47
48
49
50static void
51coordinate_to_geojson(stringbuffer_t *sb, const POINTARRAY *pa, uint32_t i, const geojson_opts *opts)
52{
53 if (!FLAGS_GET_Z(pa->flags))
54 {
55 const POINT2D *pt = getPoint2d_cp(pa, i);
57 stringbuffer_append_double(sb, pt->x, opts->precision);
59 stringbuffer_append_double(sb, pt->y, opts->precision);
61 }
62 else
63 {
64 const POINT3D *pt = getPoint3d_cp(pa, i);
66 stringbuffer_append_double(sb, pt->x, opts->precision);
68 stringbuffer_append_double(sb, pt->y, opts->precision);
70 stringbuffer_append_double(sb, pt->z, opts->precision);
72 }
73}
74
75static void
77{
78 if (!pa || pa->npoints == 0)
79 {
80 stringbuffer_append_len(sb, "[]", 2);
81 return;
82 }
83
85 for (uint32_t i = 0; i < pa->npoints; i++)
86 {
87 if (i) stringbuffer_append_char(sb, ',');
88 coordinate_to_geojson(sb, pa, i, opts);
89 }
91 return;
92}
93
94static void
96{
97 if (!opts->srs) return;
98 stringbuffer_append_len(sb, "\"crs\":{\"type\":\"name\",", 21);
99 stringbuffer_aprintf(sb, "\"properties\":{\"name\":\"%s\"}},", opts->srs);
100 return;
101}
102
103
104static void
106{
107 if (!opts->bbox) return;
108 if (!opts->hasz)
109 stringbuffer_aprintf(sb, "\"bbox\":[%.*f,%.*f,%.*f,%.*f],",
110 opts->precision, opts->bbox->xmin,
111 opts->precision, opts->bbox->ymin,
112 opts->precision, opts->bbox->xmax,
113 opts->precision, opts->bbox->ymax);
114 else
115 stringbuffer_aprintf(sb, "\"bbox\":[%.*f,%.*f,%.*f,%.*f,%.*f,%.*f],",
116 opts->precision, opts->bbox->xmin,
117 opts->precision, opts->bbox->ymin,
118 opts->precision, opts->bbox->zmin,
119 opts->precision, opts->bbox->xmax,
120 opts->precision, opts->bbox->ymax,
121 opts->precision, opts->bbox->zmax);
122 return;
123}
124
125
129static void
130asgeojson_point_coords(stringbuffer_t *sb, const LWPOINT *point, const geojson_opts *opts, int tagged)
131{
132 if (tagged == geojson_tagged) stringbuffer_append_len(sb, "\"coordinates\":", 14);
133 if (lwgeom_is_empty((LWGEOM*)point))
134 stringbuffer_append_len(sb, "[]", 2);
135 else
136 coordinate_to_geojson(sb, point->point, 0, opts);
137 return;
138}
139
140static void
141asgeojson_line_coords(stringbuffer_t *sb, const LWLINE *line, const geojson_opts *opts, int tagged)
142{
143 if (tagged == geojson_tagged) stringbuffer_append_len(sb, "\"coordinates\":", 14);
144 if (lwgeom_is_empty((LWGEOM*)line))
145 stringbuffer_append_len(sb, "[]", 2);
146 else
147 pointArray_to_geojson(sb, line->points, opts);
148 return;
149}
150
151static void
152asgeojson_poly_coords(stringbuffer_t *sb, const LWPOLY *poly, const geojson_opts *opts, int tagged)
153{
154 uint32_t i;
155 if (tagged == geojson_tagged) stringbuffer_append_len(sb, "\"coordinates\":", 14);
156 if (lwgeom_is_empty((LWGEOM*)poly))
157 stringbuffer_append_len(sb, "[]", 2);
158 else
159 {
161 for (i = 0; i < poly->nrings; i++)
162 {
163 if (i) stringbuffer_append_char(sb, ',');
164 pointArray_to_geojson(sb, poly->rings[i], opts);
165 }
167 }
168 return;
169}
170
174static void
175asgeojson_point(stringbuffer_t *sb, const LWPOINT *point, const geojson_opts *opts)
176{
177 stringbuffer_append_len(sb, "{\"type\":\"Point\",", 16);
178 asgeojson_srs(sb, opts);
179 asgeojson_bbox(sb, opts);
180 asgeojson_point_coords(sb, point, opts, geojson_tagged);
182 return;
183}
184
188static void
190{
191 stringbuffer_append_len(sb, "{\"type\":\"Polygon\",", 18);
192 asgeojson_srs(sb, opts);
193 asgeojson_bbox(sb, opts);
194 stringbuffer_append_len(sb, "\"coordinates\":[", 15);
195 if (lwtriangle_is_empty(tri))
196 stringbuffer_append_len(sb, "[]", 2);
197 else
198 pointArray_to_geojson(sb, tri->points, opts);
199 stringbuffer_append_len(sb, "]}", 2);
200 return;
201}
202
206static void
207asgeojson_line(stringbuffer_t *sb, const LWLINE *line, const geojson_opts *opts)
208{
209 const char tmpl[] = "{\"type\":\"LineString\",";
210 stringbuffer_append_len(sb, tmpl, sizeof(tmpl)-1);
211 asgeojson_srs(sb, opts);
212 asgeojson_bbox(sb, opts);
213 asgeojson_line_coords(sb, line, opts, geojson_tagged);
215 return;
216}
217
221static void
222asgeojson_poly(stringbuffer_t *sb, const LWPOLY *poly, const geojson_opts *opts)
223{
224 stringbuffer_append_len(sb, "{\"type\":\"Polygon\",", 18);
225 asgeojson_srs(sb, opts);
226 asgeojson_bbox(sb, opts);
227 asgeojson_poly_coords(sb, poly, opts, geojson_tagged);
229 return;
230}
231
235static void
237{
238 uint32_t i, ngeoms = mpoint->ngeoms;
239 stringbuffer_append_len(sb, "{\"type\":\"MultiPoint\",", 21);
240 asgeojson_srs(sb, opts);
241 asgeojson_bbox(sb, opts);
242 stringbuffer_append_len(sb, "\"coordinates\":[", 15);
243
244 if (lwgeom_is_empty((LWGEOM*)mpoint))
245 ngeoms = 0;
246
247 for (i=0; i < ngeoms; i++)
248 {
249 if (i) stringbuffer_append_char(sb, ',');
250 asgeojson_point_coords(sb, mpoint->geoms[i], opts, geojson_untagged);
251 }
252 stringbuffer_append_len(sb, "]}", 2);
253 return;
254}
255
256
260static void
262{
263 uint32_t i, ngeoms = mline->ngeoms;
264 stringbuffer_append_len(sb, "{\"type\":\"MultiLineString\",", 26);
265 asgeojson_srs(sb, opts);
266 asgeojson_bbox(sb, opts);
267 stringbuffer_append_len(sb, "\"coordinates\":[", 15);
268
269 if (lwgeom_is_empty((LWGEOM*)mline))
270 ngeoms = 0;
271
272 for (i=0; i < ngeoms; i++)
273 {
274 if (i) stringbuffer_append_char(sb, ',');
275 asgeojson_line_coords(sb, mline->geoms[i], opts, geojson_untagged);
276 }
277 stringbuffer_append_len(sb, "]}", 2);
278 return;
279}
280
281
282static void
284{
285 uint32_t i, ngeoms = mpoly->ngeoms;
286
287 stringbuffer_append_len(sb, "{\"type\":\"MultiPolygon\",", 23);
288 asgeojson_srs(sb, opts);
289 asgeojson_bbox(sb, opts);
290 stringbuffer_append_len(sb, "\"coordinates\":[", 15);
291
292 if (lwgeom_is_empty((LWGEOM*)mpoly))
293 ngeoms = 0;
294
295 for (i=0; i < ngeoms; i++)
296 {
297 if (i) stringbuffer_append_char(sb, ',');
298 asgeojson_poly_coords(sb, mpoly->geoms[i], opts, geojson_untagged);
299 }
300 stringbuffer_append_len(sb, "]}", 2);
301 return;
302}
303
307static void
309{
310 uint32_t i, ngeoms = col->ngeoms;
311
312 /* subgeometries don't get boxes or srs */
313 geojson_opts subopts = *opts;
314 subopts.bbox = NULL;
315 subopts.srs = NULL;
317
318 stringbuffer_append_len(sb, "{\"type\":\"GeometryCollection\",", 29);
319 asgeojson_srs(sb, opts);
320 if (col->ngeoms) asgeojson_bbox(sb, opts);
321 stringbuffer_append_len(sb, "\"geometries\":[", 14);
322
323 if (lwgeom_is_empty((LWGEOM*)col))
324 ngeoms = 0;
325
326 for (i=0; i<ngeoms; i++)
327 {
328 if (i) stringbuffer_append_char(sb, ',');
329 asgeojson_geometry(sb, col->geoms[i], &subopts);
330 }
331
332 stringbuffer_append_len(sb, "]}", 2);
333 return;
334}
335
336static void
338{
339 switch (geom->type)
340 {
341 case POINTTYPE:
342 asgeojson_point(sb, (LWPOINT*)geom, opts);
343 break;
344 case LINETYPE:
345 asgeojson_line(sb, (LWLINE*)geom, opts);
346 break;
347 case POLYGONTYPE:
348 asgeojson_poly(sb, (LWPOLY*)geom, opts);
349 break;
350 case MULTIPOINTTYPE:
351 asgeojson_multipoint(sb, (LWMPOINT*)geom, opts);
352 break;
353 case MULTILINETYPE:
354 asgeojson_multiline(sb, (LWMLINE*)geom, opts);
355 break;
356 case MULTIPOLYGONTYPE:
357 asgeojson_multipolygon(sb, (LWMPOLY*)geom, opts);
358 break;
359 case TRIANGLETYPE:
360 asgeojson_triangle(sb, (LWTRIANGLE *)geom, opts);
361 break;
362 case TINTYPE:
363 case COLLECTIONTYPE:
364 if (opts->isCollectionElement) {
365 lwerror("GeoJson: geometry not supported.");
366 }
367 asgeojson_collection(sb, (LWCOLLECTION*)geom, opts);
368 break;
369 default:
370 lwerror("lwgeom_to_geojson: '%s' geometry type not supported", lwtype_name(geom->type));
371 }
372}
373
378lwgeom_to_geojson(const LWGEOM *geom, const char *srs, int precision, int has_bbox)
379{
380 GBOX static_bbox = {0};
381 geojson_opts opts;
383
384 memset(&opts, 0, sizeof(opts));
385 opts.precision = precision;
386 opts.hasz = FLAGS_GET_Z(geom->flags);
387 opts.srs = srs;
388
389 if (has_bbox)
390 {
391 /* Whether these are geography or geometry,
392 the GeoJSON expects a cartesian bounding box */
393 lwgeom_calculate_gbox_cartesian(geom, &static_bbox);
394 opts.bbox = &static_bbox;
395 }
396
397 /* To avoid taking a copy of the output, we make */
398 /* space for the VARLENA header before starting to */
399 /* serialize the geom */
401 /* Now serialize the geometry */
402 asgeojson_geometry(&sb, geom, &opts);
403 /* Leave the initially allocated buffer in place */
404 /* and write the varlena_t metadata into the slot we */
405 /* left at the start */
406 return stringbuffer_getvarlena(&sb);
407}
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:752
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
#define COLLECTIONTYPE
Definition liblwgeom.h:108
#define MULTILINETYPE
Definition liblwgeom.h:106
#define LINETYPE
Definition liblwgeom.h:103
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
#define FLAGS_GET_Z(flags)
Definition liblwgeom.h:165
#define TINTYPE
Definition liblwgeom.h:116
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
#define POLYGONTYPE
Definition liblwgeom.h:104
#define TRIANGLETYPE
Definition liblwgeom.h:115
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
int lwtriangle_is_empty(const LWTRIANGLE *triangle)
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
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:109
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:199
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:97
static void pointArray_to_geojson(stringbuffer_t *sb, const POINTARRAY *pa, const geojson_opts *opts)
static void asgeojson_point(stringbuffer_t *sb, const LWPOINT *point, const geojson_opts *opts)
Point Geometry.
static void asgeojson_srs(stringbuffer_t *sb, const geojson_opts *opts)
static void asgeojson_triangle(stringbuffer_t *sb, const LWTRIANGLE *tri, const geojson_opts *opts)
Triangle Geometry.
static void asgeojson_multipoint(stringbuffer_t *sb, const LWMPOINT *mpoint, const geojson_opts *opts)
Multipoint Geometry.
static void asgeojson_geometry(stringbuffer_t *sb, const LWGEOM *geom, const geojson_opts *opts)
static void asgeojson_bbox(stringbuffer_t *sb, const geojson_opts *opts)
static void asgeojson_line(stringbuffer_t *sb, const LWLINE *line, const geojson_opts *opts)
Line Geometry.
static void asgeojson_point_coords(stringbuffer_t *sb, const LWPOINT *point, const geojson_opts *opts, int tagged)
Point Geometry.
static void coordinate_to_geojson(stringbuffer_t *sb, const POINTARRAY *pa, uint32_t i, const geojson_opts *opts)
lwvarlena_t * lwgeom_to_geojson(const LWGEOM *geom, const char *srs, int precision, int has_bbox)
Takes a GEOMETRY and returns a GeoJson representation.
@ geojson_untagged
@ geojson_tagged
static void asgeojson_poly(stringbuffer_t *sb, const LWPOLY *poly, const geojson_opts *opts)
Polygon Geometry.
static void asgeojson_multipolygon(stringbuffer_t *sb, const LWMPOLY *mpoly, const geojson_opts *opts)
static void asgeojson_collection(stringbuffer_t *sb, const LWCOLLECTION *col, const geojson_opts *opts)
Collection Geometry.
static void asgeojson_poly_coords(stringbuffer_t *sb, const LWPOLY *poly, const geojson_opts *opts, int tagged)
static void asgeojson_multiline(stringbuffer_t *sb, const LWMLINE *mline, const geojson_opts *opts)
Multipoint Geometry.
static void asgeojson_line_coords(stringbuffer_t *sb, const LWLINE *line, const geojson_opts *opts, int tagged)
lwvarlena_t * stringbuffer_getvarlena(stringbuffer_t *s)
int stringbuffer_aprintf(stringbuffer_t *s, const char *fmt,...)
Appends a formatted string to the current string buffer, using the format and argument list provided.
void stringbuffer_init_varlena(stringbuffer_t *s)
static void stringbuffer_append_double(stringbuffer_t *s, double d, int precision)
static void stringbuffer_append_char(stringbuffer_t *s, char c)
static void stringbuffer_append_len(stringbuffer_t *s, const char *a, size_t alen)
Append the specified string to the stringbuffer_t using known length.
uint32_t ngeoms
Definition liblwgeom.h:580
LWGEOM ** geoms
Definition liblwgeom.h:575
uint8_t type
Definition liblwgeom.h:462
lwflags_t flags
Definition liblwgeom.h:461
POINTARRAY * points
Definition liblwgeom.h:483
LWLINE ** geoms
Definition liblwgeom.h:547
uint32_t ngeoms
Definition liblwgeom.h:552
uint32_t ngeoms
Definition liblwgeom.h:538
LWPOINT ** geoms
Definition liblwgeom.h:533
uint32_t ngeoms
Definition liblwgeom.h:566
LWPOLY ** geoms
Definition liblwgeom.h:561
POINTARRAY * point
Definition liblwgeom.h:471
uint8_t type
Definition liblwgeom.h:474
POINTARRAY ** rings
Definition liblwgeom.h:519
uint32_t nrings
Definition liblwgeom.h:524
POINTARRAY * points
Definition liblwgeom.h:495
double y
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:390
double z
Definition liblwgeom.h:402
double x
Definition liblwgeom.h:402
double y
Definition liblwgeom.h:402
lwflags_t flags
Definition liblwgeom.h:431
uint32_t npoints
Definition liblwgeom.h:427
const char * srs
int isCollectionElement