PostGIS  2.5.7dev-r@@SVN_REVISION@@
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 
37 static char * assvg_point(const LWPOINT *point, int relative, int precision);
38 static char * assvg_line(const LWLINE *line, int relative, int precision);
39 static char * assvg_polygon(const LWPOLY *poly, int relative, int precision);
40 static char * assvg_multipoint(const LWMPOINT *mpoint, int relative, int precision);
41 static char * assvg_multiline(const LWMLINE *mline, int relative, int precision);
42 static char * assvg_multipolygon(const LWMPOLY *mpoly, int relative, int precision);
43 static char * assvg_collection(const LWCOLLECTION *col, int relative, int precision);
44 
45 static size_t assvg_geom_size(const LWGEOM *geom, int relative, int precision);
46 static size_t assvg_geom_buf(const LWGEOM *geom, char *output, int relative, int precision);
47 static size_t pointArray_svg_size(POINTARRAY *pa, int precision);
48 static size_t pointArray_svg_rel(POINTARRAY *pa, char * output, int close_ring, int precision);
49 static size_t pointArray_svg_abs(POINTARRAY *pa, char * output, int close_ring, int precision);
50 
51 
55 char *
56 lwgeom_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;
86  case MULTIPOLYGONTYPE:
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 
106 static size_t
107 assvg_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 
118 static size_t
119 assvg_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 
137 static char *
138 assvg_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 
155 static size_t
156 assvg_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 
166 static size_t
167 assvg_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 
181 static char *
182 assvg_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 
199 static size_t
200 assvg_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 
212 static size_t
213 assvg_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 
238 static char *
239 assvg_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 
256 static size_t
257 assvg_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 
273 static size_t
274 assvg_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 
290 static char *
291 assvg_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 
308 static size_t
309 assvg_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 
325 static size_t
326 assvg_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 
342 static char *
343 assvg_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 
360 static size_t
361 assvg_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 
377 static size_t
378 assvg_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 
394 static char *
395 assvg_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 
412 static size_t
413 assvg_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 
433 static size_t
434 assvg_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 
453 static char *
454 assvg_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 
467 static size_t
468 assvg_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 
508 static size_t
509 assvg_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 
549 static size_t
550 pointArray_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 
613 static size_t
614 pointArray_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 
646 static 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
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
#define MULTILINETYPE
Definition: liblwgeom.h:89
#define LINETYPE
Definition: liblwgeom.h:86
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
Definition: lwgeom_api.c:348
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
#define POLYGONTYPE
Definition: liblwgeom.h:87
#define __attribute__(x)
Definition: liblwgeom.h:201
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwgeom.c:1393
void * lwalloc(size_t size)
Definition: lwutil.c:229
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition: lwgeom_api.c:374
#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:490
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
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_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
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
type
Definition: ovdump.py:41
uint32_t ngeoms
Definition: liblwgeom.h:510
LWGEOM ** geoms
Definition: liblwgeom.h:512
uint8_t type
Definition: liblwgeom.h:399
POINTARRAY * points
Definition: liblwgeom.h:425
LWLINE ** geoms
Definition: liblwgeom.h:486
uint32_t ngeoms
Definition: liblwgeom.h:484
uint32_t ngeoms
Definition: liblwgeom.h:471
LWPOINT ** geoms
Definition: liblwgeom.h:473
uint32_t ngeoms
Definition: liblwgeom.h:497
LWPOLY ** geoms
Definition: liblwgeom.h:499
POINTARRAY * point
Definition: liblwgeom.h:414
POINTARRAY ** rings
Definition: liblwgeom.h:460
uint32_t nrings
Definition: liblwgeom.h:458
double y
Definition: liblwgeom.h:331
double x
Definition: liblwgeom.h:331
uint32_t npoints
Definition: liblwgeom.h:374
unsigned int uint32_t
Definition: uthash.h:78