PostGIS 3.7.0dev-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#include "stringbuffer.h"
37
38
39static void
40assvg_geom(stringbuffer_t* sb, const LWGEOM *geom, int relative, int precision);
41
42
43static void
44pointArray_svg_rel(stringbuffer_t* sb, const POINTARRAY *pa, int close_ring, int precision, int start_at_index)
45{
46 int i, end;
47 const POINT2D *pt;
48
49 double f = 1.0;
50 double dx, dy, x, y, accum_x, accum_y;
51
54
55 if (precision >= 0)
56 {
57 f = pow(10, precision);
58 }
59
60 end = close_ring ? pa->npoints : pa->npoints - 1;
61
62 /* Starting point */
63 pt = getPoint2d_cp(pa, start_at_index);
64
65 x = round(pt->x*f)/f;
66 y = round(pt->y*f)/f;
67
70
71 stringbuffer_aprintf(sb, "%s %s l", sx, sy);
72
73 /* accum */
74 accum_x = x;
75 accum_y = y;
76
77 /* All the following ones */
78 for (i = (start_at_index + 1); i < end; i++)
79 {
80 pt = getPoint2d_cp(pa, i);
81
82 x = round(pt->x*f)/f;
83 y = round(pt->y*f)/f;
84
85 dx = x - accum_x;
86 dy = y - accum_y;
87
88 accum_x += dx;
89 accum_y += dy;
90
92 lwprint_double(-dy, precision, sy);
93 stringbuffer_aprintf(sb, " %s %s", sx, sy);
94 }
95}
96
97
101static void
102pointArray_svg_abs(stringbuffer_t* sb, const POINTARRAY *pa, int close_ring, int precision, int start_at_index)
103{
104 int i, end;
105 const POINT2D* pt;
106 char sx[OUT_DOUBLE_BUFFER_SIZE];
107 char sy[OUT_DOUBLE_BUFFER_SIZE];
108
109 end = close_ring ? pa->npoints : pa->npoints - 1;
110
111 for (i = start_at_index; i < end; i++)
112 {
113 pt = getPoint2d_cp(pa, i);
114
115 if (i == 1)
116 {
117 if (start_at_index > 0 ){
118 stringbuffer_append(sb, "L ");
119 }
120 else {
121 stringbuffer_append(sb, " L ");
122 }
123 }
124 else if (i) stringbuffer_append(sb, " ");
125
126 lwprint_double(pt->x, precision, sx);
127 lwprint_double(-(pt->y), precision, sy);
128
129 stringbuffer_aprintf(sb, "%s %s", sx, sy);
130 }
131}
132
133
134static void
135assvg_point(stringbuffer_t* sb, const LWPOINT *point, int circle, int precision)
136{
137 char sx[OUT_DOUBLE_BUFFER_SIZE];
138 char sy[OUT_DOUBLE_BUFFER_SIZE];
139 if ( !lwgeom_is_empty((LWGEOM*)point) ){
140 const POINT2D* pt = getPoint2d_cp(point->point, 0);
141 lwprint_double(pt->x, precision, sx);
142 lwprint_double(-(pt->y), precision, sy);
143
145 circle ? "x=\"%s\" y=\"%s\"" : "cx=\"%s\" cy=\"%s\"",
146 sx, sy);
147 }
148}
149
150
151static void
152assvg_line(stringbuffer_t* sb, const LWLINE *line, int relative, int precision)
153{
154 /* Start path with SVG MoveTo */
155 stringbuffer_append(sb, "M ");
156 if (relative)
157 pointArray_svg_rel(sb, line->points, 1, precision, 0);
158 else
159 pointArray_svg_abs(sb, line->points, 1, precision, 0);
160}
161
162static void pointArray_svg_arc(stringbuffer_t* sb, const POINTARRAY *pa, int close_ring, int relative, int precision)
163{
164 uint32_t i; //, end;
165 char sx[OUT_DOUBLE_BUFFER_SIZE];
166 char sy[OUT_DOUBLE_BUFFER_SIZE];
167
168 LWDEBUG(2, "pointArray_svg_arc called.");
169
170 for (i = 2; i < pa->npoints; i+=2)
171 {
172 LWDEBUGF(3, "assvg_circstring: arc ending at point %d", i);
173 int largeArcFlag, sweepFlag, clockwise;
174 int is_circle = LW_FALSE;
175 double a1, a3;
176 double radius; /* Arc radius */
177 double total_angle;
178 POINT2D center;
179 const POINT2D *t1;
180 const POINT2D *t2;
181 const POINT2D *t3;
182 int p2_side = 0;
183 t1 = getPoint2d_cp(pa, i - 2);
184 t2 = getPoint2d_cp(pa, i - 1);
185 t3 = getPoint2d_cp(pa, i);
186 radius = lw_arc_center(t1, t2, t3, &center);
187 if ( t1->x == t3->x && t1->y == t3->y ){
188 is_circle = LW_TRUE;
189 }
190 p2_side = lw_segment_side(t1, t3, t2);
191 if ( p2_side == -1 )
192 clockwise = LW_TRUE;
193 else
194 clockwise = LW_FALSE;
195 /* Angles of each point that defines the arc section */
196 a1 = atan2(t1->y - center.y, t1->x - center.x)*180/M_PI;
197 //a2 = atan2(t2->y - center.y, t2->x - center.x)*180/M_PI;
198 a3 = atan2(t3->y - center.y, t3->x - center.x)*180/M_PI;
199
200 LWDEBUGF(2, " center is POINT(%.15g %.15g) - radius:%g", center.x, center.y, radius);
201
202 total_angle = clockwise ? a1 - a3 : a3 - a1;
203 if (total_angle < 0 ){
204 total_angle += 360;
205 }
206
207 //stringbuffer_aprintf(sb, "angles (a1 a2 a3): %g %g %g is_circle: %d, total_angle: %g, t1.x: %f, t3.x: %f, t1.y: %f, t3.y: %f ", a1, a2, a3, is_circle, total_angle, t1->x, t3->x, t1->y, t3->y);
208
210 largeArcFlag = (total_angle <= 180)? 0 : 1;
211 /* The side of the t1/t3 line that t2 falls on dictates the sweep
212 direction from t1 to t3. */
213 sweepFlag = (p2_side == -1) ? 1 : 0;
214 if ( (i == 2) && !is_circle ){
216 lwprint_double(t1->x, precision, sx);
217 lwprint_double(-(t1->y), precision, sy);
218 stringbuffer_aprintf(sb, "%s %s", sx, sy);
219 }
221 if ( (i == 2) && is_circle){
223 lwprint_double(center.x, precision, sx);
224 lwprint_double(-(center.y), precision, sy);
225 stringbuffer_aprintf(sb, "%s %s", sx, sy);
226 }
227 lwprint_double(radius, precision, sx);
230 if (is_circle){
231 //https://stackoverflow.com/questions/5737975/circle-drawing-with-svgs-arc-path
232 lwprint_double(radius*2, precision, sy);
233 stringbuffer_aprintf(sb, " m %s 0 a %s %s 0 1 0 -%s 0", sx, sx, sx, sy);
234 stringbuffer_aprintf(sb, " a %s %s 0 1 0 %s 0", sx, sx, sy);
235 }
236 else {
237 /* Arc radius radius 0 arcflag swipeflag */
238 if (relative){
239 stringbuffer_aprintf(sb, " a %s %s 0 %d %d ", sx, sx, largeArcFlag, sweepFlag);
240 }
241 else {
242 stringbuffer_aprintf(sb, " A %s %s 0 %d %d ", sx, sx, largeArcFlag, sweepFlag);
243 }
244 lwprint_double(t3->x, precision, sx);
245 lwprint_double(-(t3->y), precision, sy);
246 /* end point */
247 stringbuffer_aprintf(sb, "%s %s", sx, sy);
248 }
249 }
250}
251
252static void
253assvg_circstring(stringbuffer_t* sb, const LWCIRCSTRING *icurve, int relative, int precision)
254{
255 /* Start path with SVG MoveTo */
256 stringbuffer_append(sb, "M ");
257 pointArray_svg_arc(sb, icurve->points, 1, relative, precision);
258}
259
260static void
261assvg_compound(stringbuffer_t* sb, const LWCOMPOUND *icompound, int relative, int precision)
262{
263 uint32_t i;
264 LWGEOM *geom;
265 LWCIRCSTRING *tmpc = NULL;
266 LWLINE *tmpl = NULL;
267 /* Start path with SVG MoveTo */
268 stringbuffer_append(sb, "M ");
269
270 for (i = 0; i < icompound->ngeoms; i++)
271 {
272 if (i) stringbuffer_append(sb, " "); /* SVG whitespace Separator */
273 geom = icompound->geoms[i];
274
275 switch (geom->type)
276 {
277 case CIRCSTRINGTYPE:
278 tmpc = (LWCIRCSTRING *)geom;
279 pointArray_svg_arc(sb, tmpc->points, 1, relative, precision);
280 break;
281
282 case LINETYPE:
283 tmpl = (LWLINE *)geom;
284
285 if (i){
289 if (relative)
290 pointArray_svg_rel(sb, tmpl->points, 1, precision, 1);
291 else
292 pointArray_svg_abs(sb, tmpl->points, 1, precision, 1);
293 }
294 else {
295 if (relative)
296 pointArray_svg_rel(sb, tmpl->points, 1, precision, 0);
297 else
298 pointArray_svg_abs(sb, tmpl->points, 1, precision, 0);
299 }
300 break;
301
302 default:
303 break;
304 }
305 }
306}
307
308static void
309assvg_polygon(stringbuffer_t* sb, const LWPOLY *poly, int relative, int precision)
310{
311 uint32_t i;
312
313 for (i = 0; i<poly->nrings; i++)
314 {
315 if (i) stringbuffer_append(sb, " "); /* Space between each ring */
316 stringbuffer_append(sb, "M "); /* Start path with SVG MoveTo */
317
318 if (relative)
319 {
320 pointArray_svg_rel(sb, poly->rings[i], 0, precision, 0);
321 stringbuffer_append(sb, " z"); /* SVG closepath */
322 }
323 else
324 {
325 pointArray_svg_abs(sb, poly->rings[i], 0, precision, 0);
326 stringbuffer_append(sb, " Z"); /* SVG closepath */
327 }
328 }
329}
330
331static void
332assvg_multipoint(stringbuffer_t* sb, const LWMPOINT *mpoint, int relative, int precision)
333{
334 const LWPOINT *point;
335 uint32_t i;
336
337 for (i = 0; i<mpoint->ngeoms; i++)
338 {
339 if (i) stringbuffer_append(sb, ","); /* Arbitrary comma separator */
340 point = mpoint->geoms[i];
341 assvg_point(sb, point, relative, precision);
342 }
343}
344
345
346static void
347assvg_multiline(stringbuffer_t* sb, const LWMLINE *mline, int relative, int precision)
348{
349 const LWLINE *line;
350 uint32_t i;
351
352 for (i = 0; i<mline->ngeoms; i++)
353 {
354 if (i) stringbuffer_append(sb, " "); /* SVG whitespace Separator */
355 line = mline->geoms[i];
356 assvg_line(sb, line, relative, precision);
357 }
358}
359
360static void
361assvg_multipolygon(stringbuffer_t* sb, const LWMPOLY *mpoly, int relative, int precision)
362{
363 const LWPOLY *poly;
364 uint32_t i;
365
366 for (i = 0; i<mpoly->ngeoms; i++)
367 {
368 if (i) stringbuffer_append(sb, " "); /* SVG whitespace Separator */
369 poly = mpoly->geoms[i];
370 assvg_polygon(sb, poly, relative, precision);
371 }
372}
373
374static void
375assvg_multicurve(stringbuffer_t* sb, const LWMCURVE *mcurve, int relative, int precision)
376{
377 uint32_t i;
378 LWGEOM *geom;
379 const LWCIRCSTRING *tmpc = NULL;
380 const LWLINE *tmpl = NULL;
381
382 for (i = 0; i < mcurve->ngeoms; i++)
383 {
384 if (i) stringbuffer_append(sb, " "); /* SVG whitespace Separator */
385 geom = mcurve->geoms[i];
386
387 switch (geom->type)
388 {
389 case CIRCSTRINGTYPE:
390 tmpc = (LWCIRCSTRING *)geom;
391 assvg_circstring(sb, tmpc, relative, precision);
392 break;
393
394 case LINETYPE:
395 tmpl = (LWLINE *)geom;
396 assvg_line(sb, tmpl, relative, precision);
397 break;
398
399 default:
400 break;
401 }
402 }
403}
404
405static void
406assvg_curvepoly(stringbuffer_t* sb, const LWCURVEPOLY *curvepoly, int relative, int precision)
407{
408 uint32_t i;
409 LWGEOM *tmp;
410
411 for (i = 0; i < curvepoly->nrings; i++)
412 {
413 if (i) stringbuffer_append(sb, " "); /* Space between each ring */
414 tmp = curvepoly->rings[i];
415 switch (tmp->type)
416 {
417 case CIRCSTRINGTYPE:
418 assvg_circstring(sb, (LWCIRCSTRING *)tmp, relative, precision);
419 break;
420
421 case LINETYPE:
422 assvg_line(sb, (LWLINE *)tmp, relative, precision);
423 break;
424
425 case COMPOUNDTYPE:
426 assvg_compound(sb, (LWCOMPOUND *)tmp, relative, precision);
427 break;
428
429 default:
430 break;
431 }
432 if (relative)
433 {
434 stringbuffer_append(sb, " z"); /* SVG closepath */
435 }
436 else
437 {
438 stringbuffer_append(sb, " Z"); /* SVG closepath */
439 }
440 }
441}
442
443static void
444assvg_multisurface(stringbuffer_t* sb, const LWMSURFACE *msurface, int relative, int precision)
445{
446 LWGEOM *geom;
447 uint32_t i;
448 const LWPOLY *poly;
449 const LWCURVEPOLY *curvepoly;
450
451 for (i = 0; i < msurface->ngeoms; i++)
452 {
453 if (i) stringbuffer_append(sb, " "); /* SVG whitespace Separator */
454 geom = msurface->geoms[i];
455 switch (geom->type)
456 {
457 case CURVEPOLYTYPE:
458 curvepoly = (LWCURVEPOLY *) geom;
459 assvg_curvepoly(sb, curvepoly, relative, precision);
460 break;
461 case POLYGONTYPE:
462 poly = (LWPOLY *) geom;
463 assvg_polygon(sb, poly, relative, precision);
464 break;
465 default:
466 break;
467 }
468 }
469}
470
471static void
472assvg_collection(stringbuffer_t* sb, const LWCOLLECTION *col, int relative, int precision)
473{
474 uint32_t i; uint32_t j = 0;
475 const LWGEOM *subgeom;
476
477 /* EMPTY GEOMETRYCOLLECTION */
478 if (col->ngeoms == 0) return;
479
480 for (i = 0; i<col->ngeoms; i++)
481 {
482 subgeom = col->geoms[i];
483 if (!lwgeom_is_empty(subgeom) ){
487 if (j) stringbuffer_append(sb, ";");
488 j++;
489 assvg_geom(sb, subgeom, relative, precision);
490 }
491 }
492
493}
494
495
496
497static void
498assvg_geom(stringbuffer_t* sb, const LWGEOM *geom, int relative, int precision)
499{
500 int type = geom->type;
501
502 switch (type)
503 {
504 case POINTTYPE:
505 assvg_point(sb, (LWPOINT*)geom, relative, precision);
506 break;
507
508 case LINETYPE:
509 assvg_line(sb, (LWLINE*)geom, relative, precision);
510 break;
511
512 case POLYGONTYPE:
513 assvg_polygon(sb, (LWPOLY*)geom, relative, precision);
514 break;
515
516 case MULTIPOINTTYPE:
517 assvg_multipoint(sb, (LWMPOINT*)geom, relative, precision);
518 break;
519
520 case MULTILINETYPE:
521 assvg_multiline(sb, (LWMLINE*)geom, relative, precision);
522 break;
523
524 case MULTIPOLYGONTYPE:
525 assvg_multipolygon(sb, (LWMPOLY*)geom, relative, precision);
526 break;
527
528 case CIRCSTRINGTYPE:
529 assvg_circstring(sb, (LWCIRCSTRING*)geom, relative, precision);
530 break;
531
532 case COMPOUNDTYPE:
533 assvg_compound(sb, (LWCOMPOUND*)geom, relative, precision);
534 break;
535
536 case CURVEPOLYTYPE:
537 assvg_curvepoly(sb, (LWCURVEPOLY*)geom, relative, precision);
538 break;
539
540 case MULTICURVETYPE:
541 assvg_multicurve(sb, (LWMCURVE*)geom, relative, precision);
542 break;
543
544 case MULTISURFACETYPE:
545 assvg_multisurface(sb, (LWMSURFACE*)geom, relative, precision);
546 break;
547
548 default:
549 lwerror("assvg_geom_buf: '%s' geometry type not supported.",
550 lwtype_name(type));
551 }
552
553}
554
559lwgeom_to_svg(const LWGEOM *geom, int precision, int relative)
560{
562 int type = geom->type;
563
564 /* Empty varlena for empties */
565 if(lwgeom_is_empty(geom))
566 {
569 return v;
570 }
571
573
574 switch (type)
575 {
576 case POINTTYPE:
577 assvg_point(&sb, (LWPOINT*)geom, relative, precision);
578 break;
579 case LINETYPE:
580 assvg_line(&sb, (LWLINE*)geom, relative, precision);
581 break;
582 case POLYGONTYPE:
583 assvg_polygon(&sb, (LWPOLY*)geom, relative, precision);
584 break;
585 case CIRCSTRINGTYPE:
586 assvg_circstring(&sb, (LWCIRCSTRING*)geom, relative, precision);
587 break;
588 case COMPOUNDTYPE:
589 assvg_compound(&sb, (LWCOMPOUND*)geom, relative, precision);
590 break;
591 case CURVEPOLYTYPE:
592 assvg_curvepoly(&sb, (LWCURVEPOLY*)geom, relative, precision);
593 break;
594 case MULTIPOINTTYPE:
595 assvg_multipoint(&sb, (LWMPOINT*)geom, relative, precision);
596 break;
597 case MULTILINETYPE:
598 assvg_multiline(&sb, (LWMLINE*)geom, relative, precision);
599 break;
600 case MULTICURVETYPE:
601 assvg_multicurve(&sb, (LWMCURVE*)geom, relative, precision);
602 break;
603 case MULTIPOLYGONTYPE:
604 assvg_multipolygon(&sb, (LWMPOLY*)geom, relative, precision);
605 break;
606 case MULTISURFACETYPE:
607 assvg_multisurface(&sb, (LWMSURFACE*)geom, relative, precision);
608 break;
609 case COLLECTIONTYPE:
610 assvg_collection(&sb, (LWCOLLECTION*)geom, relative, precision);
611 break;
612
613 default:
614 lwerror("lwgeom_to_svg: '%s' geometry type not supported", lwtype_name(type));
615 }
616
617 return stringbuffer_getvarlena(&sb);
618}
619
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 LW_FALSE
Definition liblwgeom.h:94
#define COLLECTIONTYPE
Definition liblwgeom.h:108
#define COMPOUNDTYPE
Definition liblwgeom.h:110
#define LWVARHDRSZ
Definition liblwgeom.h:311
#define CURVEPOLYTYPE
Definition liblwgeom.h:111
#define MULTILINETYPE
Definition liblwgeom.h:106
#define MULTISURFACETYPE
Definition liblwgeom.h:113
#define LINETYPE
Definition liblwgeom.h:103
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
void * lwalloc(size_t size)
Definition lwutil.c:227
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
#define POLYGONTYPE
Definition liblwgeom.h:104
#define CIRCSTRINGTYPE
Definition liblwgeom.h:109
#define LWSIZE_SET(varsize, len)
Definition liblwgeom.h:325
#define MULTICURVETYPE
Definition liblwgeom.h:112
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
double lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result)
Determines the center of the circle defined by the three given points.
#define OUT_DOUBLE_BUFFER_SIZE
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q)
lw_segment_side()
Definition lwalgorithm.c:70
int lwprint_double(double d, int maxdd, char *buf)
Definition lwprint.c:463
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:101
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
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 assvg_compound(stringbuffer_t *sb, const LWCOMPOUND *icompound, int relative, int precision)
Definition lwout_svg.c:261
static void assvg_multipoint(stringbuffer_t *sb, const LWMPOINT *mpoint, int relative, int precision)
Definition lwout_svg.c:332
static void pointArray_svg_rel(stringbuffer_t *sb, const POINTARRAY *pa, int close_ring, int precision, int start_at_index)
Definition lwout_svg.c:44
static void assvg_curvepoly(stringbuffer_t *sb, const LWCURVEPOLY *curvepoly, int relative, int precision)
Definition lwout_svg.c:406
lwvarlena_t * lwgeom_to_svg(const LWGEOM *geom, int precision, int relative)
Takes a GEOMETRY and returns a SVG representation.
Definition lwout_svg.c:559
static void assvg_multiline(stringbuffer_t *sb, const LWMLINE *mline, int relative, int precision)
Definition lwout_svg.c:347
static void assvg_multipolygon(stringbuffer_t *sb, const LWMPOLY *mpoly, int relative, int precision)
Definition lwout_svg.c:361
static void pointArray_svg_arc(stringbuffer_t *sb, const POINTARRAY *pa, int close_ring, int relative, int precision)
Definition lwout_svg.c:162
static void assvg_line(stringbuffer_t *sb, const LWLINE *line, int relative, int precision)
Definition lwout_svg.c:152
static void assvg_polygon(stringbuffer_t *sb, const LWPOLY *poly, int relative, int precision)
Definition lwout_svg.c:309
static void assvg_circstring(stringbuffer_t *sb, const LWCIRCSTRING *icurve, int relative, int precision)
Definition lwout_svg.c:253
static void assvg_multicurve(stringbuffer_t *sb, const LWMCURVE *mcurve, int relative, int precision)
Definition lwout_svg.c:375
static void assvg_point(stringbuffer_t *sb, const LWPOINT *point, int circle, int precision)
Definition lwout_svg.c:135
static void pointArray_svg_abs(stringbuffer_t *sb, const POINTARRAY *pa, int close_ring, int precision, int start_at_index)
Returns maximum size of rendered pointarray in bytes.
Definition lwout_svg.c:102
static void assvg_geom(stringbuffer_t *sb, const LWGEOM *geom, int relative, int precision)
Definition lwout_svg.c:498
static void assvg_multisurface(stringbuffer_t *sb, const LWMSURFACE *msurface, int relative, int precision)
Definition lwout_svg.c:444
static void assvg_collection(stringbuffer_t *sb, const LWCOLLECTION *col, int relative, int precision)
Definition lwout_svg.c:472
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(stringbuffer_t *s, const char *a)
Append the specified string to the stringbuffer_t.
POINTARRAY * points
Definition liblwgeom.h:507
uint32_t ngeoms
Definition liblwgeom.h:580
LWGEOM ** geoms
Definition liblwgeom.h:575
uint32_t ngeoms
Definition liblwgeom.h:594
LWGEOM ** geoms
Definition liblwgeom.h:589
LWGEOM ** rings
Definition liblwgeom.h:603
uint32_t nrings
Definition liblwgeom.h:608
uint8_t type
Definition liblwgeom.h:462
POINTARRAY * points
Definition liblwgeom.h:483
LWGEOM ** geoms
Definition liblwgeom.h:617
uint32_t ngeoms
Definition liblwgeom.h:622
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
uint32_t ngeoms
Definition liblwgeom.h:636
LWGEOM ** geoms
Definition liblwgeom.h:631
POINTARRAY * point
Definition liblwgeom.h:471
POINTARRAY ** rings
Definition liblwgeom.h:519
uint32_t nrings
Definition liblwgeom.h:524
double y
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:390
uint32_t npoints
Definition liblwgeom.h:427
uint32_t size
Definition liblwgeom.h:307