PostGIS  2.1.10dev-r@@SVN_REVISION@@
lwout_kml.c
Go to the documentation of this file.
1 /**********************************************************************
2  * $Id: lwout_kml.c 13134 2014-12-01 08:47:21Z strk $
3  *
4  * PostGIS - Spatial Types for PostgreSQL
5  * http://postgis.net
6  *
7  * Copyright 2006 Corporacion Autonoma Regional de Santander
8  * Eduin Carrillo <yecarrillo@cas.gov.co>
9  * Copyright 2010 Paul Ramsey <pramsey@cleverelephant.ca>
10  *
11  * This is free software; you can redistribute and/or modify it under
12  * the terms of hte GNU General Public Licence. See the COPYING file.
13  *
14  **********************************************************************/
15 
16 #include "liblwgeom_internal.h"
17 #include "stringbuffer.h"
18 
19 static int lwgeom_to_kml2_sb(const LWGEOM *geom, int precision, const char *prefix, stringbuffer_t *sb);
20 static int lwpoint_to_kml2_sb(const LWPOINT *point, int precision, const char *prefix, stringbuffer_t *sb);
21 static int lwline_to_kml2_sb(const LWLINE *line, int precision, const char *prefix, stringbuffer_t *sb);
22 static int lwpoly_to_kml2_sb(const LWPOLY *poly, int precision, const char *prefix, stringbuffer_t *sb);
23 static int lwcollection_to_kml2_sb(const LWCOLLECTION *col, int precision, const char *prefix, stringbuffer_t *sb);
24 static int ptarray_to_kml2_sb(const POINTARRAY *pa, int precision, stringbuffer_t *sb);
25 
26 /*
27 * KML 2.2.0
28 */
29 
30 /* takes a GEOMETRY and returns a KML representation */
31 char*
32 lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix)
33 {
34  stringbuffer_t *sb;
35  int rv;
36  char *kml;
37 
38  /* Can't do anything with empty */
39  if( lwgeom_is_empty(geom) )
40  return NULL;
41 
42  sb = stringbuffer_create();
43  rv = lwgeom_to_kml2_sb(geom, precision, prefix, sb);
44 
45  if ( rv == LW_FAILURE )
46  {
48  return NULL;
49  }
50 
53 
54  return kml;
55 }
56 
57 static int
58 lwgeom_to_kml2_sb(const LWGEOM *geom, int precision, const char *prefix, stringbuffer_t *sb)
59 {
60  switch (geom->type)
61  {
62  case POINTTYPE:
63  return lwpoint_to_kml2_sb((LWPOINT*)geom, precision, prefix, sb);
64 
65  case LINETYPE:
66  return lwline_to_kml2_sb((LWLINE*)geom, precision, prefix, sb);
67 
68  case POLYGONTYPE:
69  return lwpoly_to_kml2_sb((LWPOLY*)geom, precision, prefix, sb);
70 
71  case MULTIPOINTTYPE:
72  case MULTILINETYPE:
73  case MULTIPOLYGONTYPE:
74  return lwcollection_to_kml2_sb((LWCOLLECTION*)geom, precision, prefix, sb);
75 
76  default:
77  lwerror("lwgeom_to_kml2: '%s' geometry type not supported", lwtype_name(geom->type));
78  return LW_FAILURE;
79  }
80 }
81 
82 static int
83 ptarray_to_kml2_sb(const POINTARRAY *pa, int precision, stringbuffer_t *sb)
84 {
85  int i, j;
86  int dims = FLAGS_GET_Z(pa->flags) ? 3 : 2;
87  POINT4D pt;
88  double *d;
89 
90  for ( i = 0; i < pa->npoints; i++ )
91  {
92  getPoint4d_p(pa, i, &pt);
93  d = (double*)(&pt);
94  if ( i ) stringbuffer_append(sb," ");
95  for (j = 0; j < dims; j++)
96  {
97  if ( j ) stringbuffer_append(sb,",");
98  if( fabs(d[j]) < OUT_MAX_DOUBLE )
99  {
100  if ( stringbuffer_aprintf(sb, "%.*f", precision, d[j]) < 0 ) return LW_FAILURE;
101  }
102  else
103  {
104  if ( stringbuffer_aprintf(sb, "%g", d[j]) < 0 ) return LW_FAILURE;
105  }
107  }
108  }
109  return LW_SUCCESS;
110 }
111 
112 
113 static int
114 lwpoint_to_kml2_sb(const LWPOINT *point, int precision, const char *prefix, stringbuffer_t *sb)
115 {
116  /* Open point */
117  if ( stringbuffer_aprintf(sb, "<%sPoint><%scoordinates>", prefix, prefix) < 0 ) return LW_FAILURE;
118  /* Coordinate array */
119  if ( ptarray_to_kml2_sb(point->point, precision, sb) == LW_FAILURE ) return LW_FAILURE;
120  /* Close point */
121  if ( stringbuffer_aprintf(sb, "</%scoordinates></%sPoint>", prefix, prefix) < 0 ) return LW_FAILURE;
122  return LW_SUCCESS;
123 }
124 
125 static int
126 lwline_to_kml2_sb(const LWLINE *line, int precision, const char *prefix, stringbuffer_t *sb)
127 {
128  /* Open linestring */
129  if ( stringbuffer_aprintf(sb, "<%sLineString><%scoordinates>", prefix, prefix) < 0 ) return LW_FAILURE;
130  /* Coordinate array */
131  if ( ptarray_to_kml2_sb(line->points, precision, sb) == LW_FAILURE ) return LW_FAILURE;
132  /* Close linestring */
133  if ( stringbuffer_aprintf(sb, "</%scoordinates></%sLineString>", prefix, prefix) < 0 ) return LW_FAILURE;
134 
135  return LW_SUCCESS;
136 }
137 
138 static int
139 lwpoly_to_kml2_sb(const LWPOLY *poly, int precision, const char *prefix, stringbuffer_t *sb)
140 {
141  int i, rv;
142 
143  /* Open polygon */
144  if ( stringbuffer_aprintf(sb, "<%sPolygon>", prefix) < 0 ) return LW_FAILURE;
145  for ( i = 0; i < poly->nrings; i++ )
146  {
147  /* Inner or outer ring opening tags */
148  if( i )
149  rv = stringbuffer_aprintf(sb, "<%sinnerBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix);
150  else
151  rv = stringbuffer_aprintf(sb, "<%souterBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix);
152  if ( rv < 0 ) return LW_FAILURE;
153 
154  /* Coordinate array */
155  if ( ptarray_to_kml2_sb(poly->rings[i], precision, sb) == LW_FAILURE ) return LW_FAILURE;
156 
157  /* Inner or outer ring closing tags */
158  if( i )
159  rv = stringbuffer_aprintf(sb, "</%scoordinates></%sLinearRing></%sinnerBoundaryIs>", prefix, prefix, prefix);
160  else
161  rv = stringbuffer_aprintf(sb, "</%scoordinates></%sLinearRing></%souterBoundaryIs>", prefix, prefix, prefix);
162  if ( rv < 0 ) return LW_FAILURE;
163  }
164  /* Close polygon */
165  if ( stringbuffer_aprintf(sb, "</%sPolygon>", prefix) < 0 ) return LW_FAILURE;
166 
167  return LW_SUCCESS;
168 }
169 
170 static int
171 lwcollection_to_kml2_sb(const LWCOLLECTION *col, int precision, const char *prefix, stringbuffer_t *sb)
172 {
173  int i, rv;
174 
175  /* Open geometry */
176  if ( stringbuffer_aprintf(sb, "<%sMultiGeometry>", prefix) < 0 ) return LW_FAILURE;
177  for ( i = 0; i < col->ngeoms; i++ )
178  {
179  rv = lwgeom_to_kml2_sb(col->geoms[i], precision, prefix, sb);
180  if ( rv == LW_FAILURE ) return LW_FAILURE;
181  }
182  /* Close geometry */
183  if ( stringbuffer_aprintf(sb, "</%sMultiGeometry>", prefix) < 0 ) return LW_FAILURE;
184 
185  return LW_SUCCESS;
186 }
#define LINETYPE
Definition: liblwgeom.h:61
char * lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix)
Definition: lwout_kml.c:32
stringbuffer_t * stringbuffer_create(void)
Allocate a new stringbuffer_t.
Definition: stringbuffer.c:47
int npoints
Definition: liblwgeom.h:327
#define POLYGONTYPE
Definition: liblwgeom.h:62
char * stringbuffer_getstringcopy(stringbuffer_t *s)
Returns a newly allocated string large enough to contain the current state of the string...
Definition: stringbuffer.c:154
#define MULTIPOINTTYPE
Definition: liblwgeom.h:63
#define LW_SUCCESS
Definition: liblwgeom.h:55
POINTARRAY * point
Definition: liblwgeom.h:367
#define LW_FAILURE
Definition: liblwgeom.h:54
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...
Definition: stringbuffer.c:247
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:164
uint8_t flags
Definition: liblwgeom.h:325
LWGEOM ** geoms
Definition: liblwgeom.h:465
POINTARRAY ** rings
Definition: liblwgeom.h:413
static int lwgeom_to_kml2_sb(const LWGEOM *geom, int precision, const char *prefix, stringbuffer_t *sb)
Definition: lwout_kml.c:58
int nrings
Definition: liblwgeom.h:411
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:106
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:65
#define OUT_MAX_DOUBLE
void stringbuffer_append(stringbuffer_t *s, const char *a)
Append the specified string to the stringbuffer_t.
Definition: stringbuffer.c:128
void stringbuffer_destroy(stringbuffer_t *s)
Free the stringbuffer_t and all memory managed within it.
Definition: stringbuffer.c:72
static int lwcollection_to_kml2_sb(const LWCOLLECTION *col, int precision, const char *prefix, stringbuffer_t *sb)
Definition: lwout_kml.c:171
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
uint8_t type
Definition: liblwgeom.h:352
static int ptarray_to_kml2_sb(const POINTARRAY *pa, int precision, stringbuffer_t *sb)
Definition: lwout_kml.c:83
static int lwpoly_to_kml2_sb(const LWPOLY *poly, int precision, const char *prefix, stringbuffer_t *sb)
Definition: lwout_kml.c:139
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:1229
static int lwline_to_kml2_sb(const LWLINE *line, int precision, const char *prefix, stringbuffer_t *sb)
Definition: lwout_kml.c:126
#define MULTILINETYPE
Definition: liblwgeom.h:64
int stringbuffer_trim_trailing_zeroes(stringbuffer_t *s)
Trims zeroes off the end of the last number in the stringbuffer.
Definition: stringbuffer.c:298
static int lwpoint_to_kml2_sb(const LWPOINT *point, int precision, const char *prefix, stringbuffer_t *sb)
Definition: lwout_kml.c:114
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:217
POINTARRAY * points
Definition: liblwgeom.h:378