PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwout_svg.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 *
23 **********************************************************************/
24
25
35#include "liblwgeom_internal.h"
36
37static char * assvg_point(const LWPOINT *point, int relative, int precision);
38static char * assvg_line(const LWLINE *line, int relative, int precision);
39static char * assvg_polygon(const LWPOLY *poly, int relative, int precision);
40static char * assvg_multipoint(const LWMPOINT *mpoint, int relative, int precision);
41static char * assvg_multiline(const LWMLINE *mline, int relative, int precision);
42static char * assvg_multipolygon(const LWMPOLY *mpoly, int relative, int precision);
43static char * assvg_collection(const LWCOLLECTION *col, int relative, int precision);
44
45static size_t assvg_geom_size(const LWGEOM *geom, int relative, int precision);
46static size_t assvg_geom_buf(const LWGEOM *geom, char *output, int relative, int precision);
47static size_t pointArray_svg_size(POINTARRAY *pa, int precision);
48static size_t pointArray_svg_rel(POINTARRAY *pa, char * output, int close_ring, int precision);
49static size_t pointArray_svg_abs(POINTARRAY *pa, char * output, int close_ring, int precision);
50
51
55char *
56lwgeom_to_svg(const LWGEOM *geom, int precision, int relative)
57{
58 char *ret = NULL;
59 int type = geom->type;
60
61 /* Empty string for empties */
62 if( lwgeom_is_empty(geom) )
63 {
64 ret = lwalloc(1);
65 ret[0] = '\0';
66 return ret;
67 }
68
69 switch (type)
70 {
71 case POINTTYPE:
72 ret = assvg_point((LWPOINT*)geom, relative, precision);
73 break;
74 case LINETYPE:
75 ret = assvg_line((LWLINE*)geom, relative, precision);
76 break;
77 case POLYGONTYPE:
78 ret = assvg_polygon((LWPOLY*)geom, relative, precision);
79 break;
80 case MULTIPOINTTYPE:
81 ret = assvg_multipoint((LWMPOINT*)geom, relative, precision);
82 break;
83 case MULTILINETYPE:
84 ret = assvg_multiline((LWMLINE*)geom, relative, precision);
85 break;
87 ret = assvg_multipolygon((LWMPOLY*)geom, relative, precision);
88 break;
89 case COLLECTIONTYPE:
90 ret = assvg_collection((LWCOLLECTION*)geom, relative, precision);
91 break;
92
93 default:
94 lwerror("lwgeom_to_svg: '%s' geometry type not supported",
95 lwtype_name(type));
96 }
97
98 return ret;
99}
100
101
106static size_t
107assvg_point_size(__attribute__((__unused__)) const LWPOINT *point, int circle, int precision)
108{
109 size_t size;
110
111 size = (OUT_MAX_DIGS_DOUBLE + precision) * 2;
112 if (circle) size += sizeof("cx='' cy=''");
113 else size += sizeof("x='' y=''");
114
115 return size;
116}
117
118static size_t
119assvg_point_buf(const LWPOINT *point, char * output, int circle, int precision)
120{
121 char *ptr=output;
124 POINT2D pt;
125
126 getPoint2d_p(point->point, 0, &pt);
127
130
131 if (circle) ptr += sprintf(ptr, "x=\"%s\" y=\"%s\"", x, y);
132 else ptr += sprintf(ptr, "cx=\"%s\" cy=\"%s\"", x, y);
133
134 return (ptr-output);
135}
136
137static char *
138assvg_point(const LWPOINT *point, int circle, int precision)
139{
140 char *output;
141 int size;
142
143 size = assvg_point_size(point, circle, precision);
144 output = lwalloc(size);
145 assvg_point_buf(point, output, circle, precision);
146
147 return output;
148}
149
150
155static size_t
156assvg_line_size(const LWLINE *line, __attribute__((__unused__)) int relative, int precision)
157{
158 size_t size;
159
160 size = sizeof("M ");
161 size += pointArray_svg_size(line->points, precision);
162
163 return size;
164}
165
166static size_t
167assvg_line_buf(const LWLINE *line, char * output, int relative, int precision)
168{
169 char *ptr=output;
170
171 /* Start path with SVG MoveTo */
172 ptr += sprintf(ptr, "M ");
173 if (relative)
174 ptr += pointArray_svg_rel(line->points, ptr, 1, precision);
175 else
176 ptr += pointArray_svg_abs(line->points, ptr, 1, precision);
177
178 return (ptr-output);
179}
180
181static char *
182assvg_line(const LWLINE *line, int relative, int precision)
183{
184 char *output;
185 int size;
186
187 size = assvg_line_size(line, relative, precision);
188 output = lwalloc(size);
189 assvg_line_buf(line, output, relative, precision);
190
191 return output;
192}
193
194
199static size_t
200assvg_polygon_size(const LWPOLY *poly, __attribute__((__unused__)) int relative, int precision)
201{
202 uint32_t i;
203 size_t size=0;
204
205 for (i=0; i<poly->nrings; i++)
206 size += pointArray_svg_size(poly->rings[i], precision) + sizeof(" ");
207 size += sizeof("M Z") * poly->nrings;
208
209 return size;
210}
211
212static size_t
213assvg_polygon_buf(const LWPOLY *poly, char * output, int relative, int precision)
214{
215 uint32_t i;
216 char *ptr=output;
217
218 for (i=0; i<poly->nrings; i++)
219 {
220 if (i) ptr += sprintf(ptr, " "); /* Space beetween each ring */
221 ptr += sprintf(ptr, "M "); /* Start path with SVG MoveTo */
222
223 if (relative)
224 {
225 ptr += pointArray_svg_rel(poly->rings[i], ptr, 0, precision);
226 ptr += sprintf(ptr, " z"); /* SVG closepath */
227 }
228 else
229 {
230 ptr += pointArray_svg_abs(poly->rings[i], ptr, 0, precision);
231 ptr += sprintf(ptr, " Z"); /* SVG closepath */
232 }
233 }
234
235 return (ptr-output);
236}
237
238static char *
239assvg_polygon(const LWPOLY *poly, int relative, int precision)
240{
241 char *output;
242 int size;
243
244 size = assvg_polygon_size(poly, relative, precision);
245 output = lwalloc(size);
246 assvg_polygon_buf(poly, output, relative, precision);
247
248 return output;
249}
250
251
256static size_t
257assvg_multipoint_size(const LWMPOINT *mpoint, int relative, int precision)
258{
259 const LWPOINT *point;
260 size_t size=0;
261 uint32_t i;
262
263 for (i=0 ; i<mpoint->ngeoms ; i++)
264 {
265 point = mpoint->geoms[i];
266 size += assvg_point_size(point, relative, precision);
267 }
268 size += sizeof(",") * --i; /* Arbitrary comma separator */
269
270 return size;
271}
272
273static size_t
274assvg_multipoint_buf(const LWMPOINT *mpoint, char *output, int relative, int precision)
275{
276 const LWPOINT *point;
277 uint32_t i;
278 char *ptr=output;
279
280 for (i=0 ; i<mpoint->ngeoms ; i++)
281 {
282 if (i) ptr += sprintf(ptr, ","); /* Arbitrary comma separator */
283 point = mpoint->geoms[i];
284 ptr += assvg_point_buf(point, ptr, relative, precision);
285 }
286
287 return (ptr-output);
288}
289
290static char *
291assvg_multipoint(const LWMPOINT *mpoint, int relative, int precision)
292{
293 char *output;
294 int size;
295
296 size = assvg_multipoint_size(mpoint, relative, precision);
297 output = lwalloc(size);
298 assvg_multipoint_buf(mpoint, output, relative, precision);
299
300 return output;
301}
302
303
308static size_t
309assvg_multiline_size(const LWMLINE *mline, int relative, int precision)
310{
311 const LWLINE *line;
312 size_t size=0;
313 uint32_t i;
314
315 for (i=0 ; i<mline->ngeoms ; i++)
316 {
317 line = mline->geoms[i];
318 size += assvg_line_size(line, relative, precision);
319 }
320 size += sizeof(" ") * --i; /* SVG whitespace Separator */
321
322 return size;
323}
324
325static size_t
326assvg_multiline_buf(const LWMLINE *mline, char *output, int relative, int precision)
327{
328 const LWLINE *line;
329 uint32_t i;
330 char *ptr=output;
331
332 for (i=0 ; i<mline->ngeoms ; i++)
333 {
334 if (i) ptr += sprintf(ptr, " "); /* SVG whitespace Separator */
335 line = mline->geoms[i];
336 ptr += assvg_line_buf(line, ptr, relative, precision);
337 }
338
339 return (ptr-output);
340}
341
342static char *
343assvg_multiline(const LWMLINE *mline, int relative, int precision)
344{
345 char *output;
346 int size;
347
348 size = assvg_multiline_size(mline, relative, precision);
349 output = lwalloc(size);
350 assvg_multiline_buf(mline, output, relative, precision);
351
352 return output;
353}
354
355
356/*
357 * Multipolygon Geometry
358 */
359
360static size_t
361assvg_multipolygon_size(const LWMPOLY *mpoly, int relative, int precision)
362{
363 const LWPOLY *poly;
364 size_t size=0;
365 uint32_t i;
366
367 for (i=0 ; i<mpoly->ngeoms ; i++)
368 {
369 poly = mpoly->geoms[i];
370 size += assvg_polygon_size(poly, relative, precision);
371 }
372 size += sizeof(" ") * --i; /* SVG whitespace Separator */
373
374 return size;
375}
376
377static size_t
378assvg_multipolygon_buf(const LWMPOLY *mpoly, char *output, int relative, int precision)
379{
380 const LWPOLY *poly;
381 uint32_t i;
382 char *ptr=output;
383
384 for (i=0 ; i<mpoly->ngeoms ; i++)
385 {
386 if (i) ptr += sprintf(ptr, " "); /* SVG whitespace Separator */
387 poly = mpoly->geoms[i];
388 ptr += assvg_polygon_buf(poly, ptr, relative, precision);
389 }
390
391 return (ptr-output);
392}
393
394static char *
395assvg_multipolygon(const LWMPOLY *mpoly, int relative, int precision)
396{
397 char *output;
398 int size;
399
400 size = assvg_multipolygon_size(mpoly, relative, precision);
401 output = lwalloc(size);
402 assvg_multipolygon_buf(mpoly, output, relative, precision);
403
404 return output;
405}
406
407
412static size_t
413assvg_collection_size(const LWCOLLECTION *col, int relative, int precision)
414{
415 uint32_t i = 0;
416 size_t size=0;
417 const LWGEOM *subgeom;
418
419 for (i=0; i<col->ngeoms; i++)
420 {
421 subgeom = col->geoms[i];
422 size += assvg_geom_size(subgeom, relative, precision);
423 }
424
425 if ( i ) /* We have some geometries, so add space for delimiters. */
426 size += sizeof(";") * --i;
427
428 if (size == 0) size++; /* GEOMETRYCOLLECTION EMPTY, space for null terminator */
429
430 return size;
431}
432
433static size_t
434assvg_collection_buf(const LWCOLLECTION *col, char *output, int relative, int precision)
435{
436 uint32_t i;
437 char *ptr=output;
438 const LWGEOM *subgeom;
439
440 /* EMPTY GEOMETRYCOLLECTION */
441 if (col->ngeoms == 0) *ptr = '\0';
442
443 for (i=0; i<col->ngeoms; i++)
444 {
445 if (i) ptr += sprintf(ptr, ";");
446 subgeom = col->geoms[i];
447 ptr += assvg_geom_buf(subgeom, ptr, relative, precision);
448 }
449
450 return (ptr - output);
451}
452
453static char *
454assvg_collection(const LWCOLLECTION *col, int relative, int precision)
455{
456 char *output;
457 int size;
458
459 size = assvg_collection_size(col, relative, precision);
460 output = lwalloc(size);
461 assvg_collection_buf(col, output, relative, precision);
462
463 return output;
464}
465
466
467static size_t
468assvg_geom_buf(const LWGEOM *geom, char *output, int relative, int precision)
469{
470 int type = geom->type;
471 char *ptr=output;
472
473 switch (type)
474 {
475 case POINTTYPE:
476 ptr += assvg_point_buf((LWPOINT*)geom, ptr, relative, precision);
477 break;
478
479 case LINETYPE:
480 ptr += assvg_line_buf((LWLINE*)geom, ptr, relative, precision);
481 break;
482
483 case POLYGONTYPE:
484 ptr += assvg_polygon_buf((LWPOLY*)geom, ptr, relative, precision);
485 break;
486
487 case MULTIPOINTTYPE:
488 ptr += assvg_multipoint_buf((LWMPOINT*)geom, ptr, relative, precision);
489 break;
490
491 case MULTILINETYPE:
492 ptr += assvg_multiline_buf((LWMLINE*)geom, ptr, relative, precision);
493 break;
494
495 case MULTIPOLYGONTYPE:
496 ptr += assvg_multipolygon_buf((LWMPOLY*)geom, ptr, relative, precision);
497 break;
498
499 default:
500 lwerror("assvg_geom_buf: '%s' geometry type not supported.",
501 lwtype_name(type));
502 }
503
504 return (ptr-output);
505}
506
507
508static size_t
509assvg_geom_size(const LWGEOM *geom, int relative, int precision)
510{
511 int type = geom->type;
512 size_t size = 0;
513
514 switch (type)
515 {
516 case POINTTYPE:
517 size = assvg_point_size((LWPOINT*)geom, relative, precision);
518 break;
519
520 case LINETYPE:
521 size = assvg_line_size((LWLINE*)geom, relative, precision);
522 break;
523
524 case POLYGONTYPE:
525 size = assvg_polygon_size((LWPOLY*)geom, relative, precision);
526 break;
527
528 case MULTIPOINTTYPE:
529 size = assvg_multipoint_size((LWMPOINT*)geom, relative, precision);
530 break;
531
532 case MULTILINETYPE:
533 size = assvg_multiline_size((LWMLINE*)geom, relative, precision);
534 break;
535
536 case MULTIPOLYGONTYPE:
537 size = assvg_multipolygon_size((LWMPOLY*)geom, relative, precision);
538 break;
539
540 default:
541 lwerror("assvg_geom_size: '%s' geometry type not supported.",
542 lwtype_name(type));
543 }
544
545 return size;
546}
547
548
549static size_t
550pointArray_svg_rel(POINTARRAY *pa, char *output, int close_ring, int precision)
551{
552 int i, end;
553 char *ptr;
554 char sx[OUT_DOUBLE_BUFFER_SIZE];
555 char sy[OUT_DOUBLE_BUFFER_SIZE];
556 const POINT2D *pt;
557
558 double f = 1.0;
559 double dx, dy, x, y, accum_x, accum_y;
560
561 ptr = output;
562
563 if (precision >= 0)
564 {
565 f = pow(10, precision);
566 }
567
568 if (close_ring) end = pa->npoints;
569 else end = pa->npoints - 1;
570
571 /* Starting point */
572 pt = getPoint2d_cp(pa, 0);
573
574 x = round(pt->x*f)/f;
575 y = round(pt->y*f)/f;
576
579 ptr += sprintf(ptr,"%s %s l", sx, sy);
580
581 /* accum */
582 accum_x = x;
583 accum_y = y;
584
585 /* All the following ones */
586 for (i=1 ; i < end ; i++)
587 {
588 // lpt = pt;
589
590 pt = getPoint2d_cp(pa, i);
591
592 x = round(pt->x*f)/f;
593 y = round(pt->y*f)/f;
594 dx = x - accum_x;
595 dy = y - accum_y;
596
599
600 accum_x += dx;
601 accum_y += dy;
602
603 ptr += sprintf(ptr," %s %s", sx, sy);
604 }
605
606 return (ptr-output);
607}
608
609
613static size_t
614pointArray_svg_abs(POINTARRAY *pa, char *output, int close_ring, int precision)
615{
616 int i, end;
617 char *ptr;
620 POINT2D pt;
621
622 ptr = output;
623
624 if (close_ring) end = pa->npoints;
625 else end = pa->npoints - 1;
626
627 for (i=0 ; i < end ; i++)
628 {
629 getPoint2d_p(pa, i, &pt);
630
633
634 if (i == 1) ptr += sprintf(ptr, " L ");
635 else if (i) ptr += sprintf(ptr, " ");
636 ptr += sprintf(ptr,"%s %s", x, y);
637 }
638
639 return (ptr-output);
640}
641
642
646static size_t
648{
649 return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(" "))
650 * 2 * pa->npoints + sizeof(" L ");
651}
static uint8_t precision
Definition cu_in_twkb.c:25
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:122
#define MULTILINETYPE
Definition liblwgeom.h:120
#define LINETYPE
Definition liblwgeom.h:117
#define MULTIPOINTTYPE
Definition liblwgeom.h:119
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
Definition lwgeom_api.c:349
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:116
void * lwalloc(size_t size)
Definition lwutil.c:227
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:121
#define POLYGONTYPE
Definition liblwgeom.h:118
#define __attribute__(x)
Definition liblwgeom.h:242
#define OUT_MAX_DIGS_DOUBLE
#define OUT_DOUBLE_BUFFER_SIZE
int lwprint_double(double d, int maxdd, char *buf, size_t bufsize)
Definition lwprint.c:492
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition lwutil.c:190
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:193
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:91
static size_t assvg_multipoint_buf(const LWMPOINT *mpoint, char *output, int relative, int precision)
Definition lwout_svg.c:274
static size_t assvg_geom_buf(const LWGEOM *geom, char *output, int relative, int precision)
Definition lwout_svg.c:468
static size_t assvg_multipoint_size(const LWMPOINT *mpoint, int relative, int precision)
Multipoint Geometry.
Definition lwout_svg.c:257
static size_t assvg_collection_buf(const LWCOLLECTION *col, char *output, int relative, int precision)
Definition lwout_svg.c:434
static size_t assvg_multiline_buf(const LWMLINE *mline, char *output, int relative, int precision)
Definition lwout_svg.c:326
static size_t assvg_line_buf(const LWLINE *line, char *output, int relative, int precision)
Definition lwout_svg.c:167
static char * assvg_multiline(const LWMLINE *mline, int relative, int precision)
Definition lwout_svg.c:343
static char * assvg_multipoint(const LWMPOINT *mpoint, int relative, int precision)
Definition lwout_svg.c:291
char * lwgeom_to_svg(const LWGEOM *geom, int precision, int relative)
Takes a GEOMETRY and returns a SVG representation.
Definition lwout_svg.c:56
static size_t assvg_collection_size(const LWCOLLECTION *col, int relative, int precision)
Collection Geometry.
Definition lwout_svg.c:413
static size_t assvg_line_size(const LWLINE *line, __attribute__((__unused__)) int relative, int precision)
Line Geometry.
Definition lwout_svg.c:156
static char * assvg_point(const LWPOINT *point, int relative, int precision)
Definition lwout_svg.c:138
static size_t assvg_multipolygon_size(const LWMPOLY *mpoly, int relative, int precision)
Definition lwout_svg.c:361
static char * assvg_collection(const LWCOLLECTION *col, int relative, int precision)
Definition lwout_svg.c:454
static size_t pointArray_svg_rel(POINTARRAY *pa, char *output, int close_ring, int precision)
Definition lwout_svg.c:550
static size_t assvg_point_buf(const LWPOINT *point, char *output, int circle, int precision)
Definition lwout_svg.c:119
static char * assvg_line(const LWLINE *line, int relative, int precision)
Definition lwout_svg.c:182
static size_t assvg_multiline_size(const LWMLINE *mline, int relative, int precision)
Multiline Geometry.
Definition lwout_svg.c:309
static size_t assvg_point_size(__attribute__((__unused__)) const LWPOINT *point, int circle, int precision)
Point Geometry.
Definition lwout_svg.c:107
static char * assvg_multipolygon(const LWMPOLY *mpoly, int relative, int precision)
Definition lwout_svg.c:395
static size_t pointArray_svg_abs(POINTARRAY *pa, char *output, int close_ring, int precision)
Returns maximum size of rendered pointarray in bytes.
Definition lwout_svg.c:614
static size_t assvg_geom_size(const LWGEOM *geom, int relative, int precision)
Definition lwout_svg.c:509
static size_t assvg_polygon_size(const LWPOLY *poly, __attribute__((__unused__)) int relative, int precision)
Polygon Geometry.
Definition lwout_svg.c:200
static char * assvg_polygon(const LWPOLY *poly, int relative, int precision)
Definition lwout_svg.c:239
static size_t pointArray_svg_size(POINTARRAY *pa, int precision)
Returns maximum size of rendered pointarray in bytes.
Definition lwout_svg.c:647
static size_t assvg_multipolygon_buf(const LWMPOLY *mpoly, char *output, int relative, int precision)
Definition lwout_svg.c:378
static size_t assvg_polygon_buf(const LWPOLY *poly, char *output, int relative, int precision)
Definition lwout_svg.c:213
uint32_t ngeoms
Definition liblwgeom.h:566
LWGEOM ** geoms
Definition liblwgeom.h:561
uint8_t type
Definition liblwgeom.h:448
POINTARRAY * points
Definition liblwgeom.h:469
LWLINE ** geoms
Definition liblwgeom.h:533
uint32_t ngeoms
Definition liblwgeom.h:538
uint32_t ngeoms
Definition liblwgeom.h:524
LWPOINT ** geoms
Definition liblwgeom.h:519
uint32_t ngeoms
Definition liblwgeom.h:552
LWPOLY ** geoms
Definition liblwgeom.h:547
POINTARRAY * point
Definition liblwgeom.h:457
POINTARRAY ** rings
Definition liblwgeom.h:505
uint32_t nrings
Definition liblwgeom.h:510
double y
Definition liblwgeom.h:376
double x
Definition liblwgeom.h:376
uint32_t npoints
Definition liblwgeom.h:413