PostGIS  2.4.9dev-r@@SVN_REVISION@@
lwout_kml.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 2006 Corporacion Autonoma Regional de Santander
22  * Copyright 2010 Paul Ramsey <pramsey@cleverelephant.ca>
23  *
24  **********************************************************************/
25 
26 
27 #include "liblwgeom_internal.h"
28 #include "stringbuffer.h"
29 
30 static int lwgeom_to_kml2_sb(const LWGEOM *geom, int precision, const char *prefix, stringbuffer_t *sb);
31 static int lwpoint_to_kml2_sb(const LWPOINT *point, int precision, const char *prefix, stringbuffer_t *sb);
32 static int lwline_to_kml2_sb(const LWLINE *line, int precision, const char *prefix, stringbuffer_t *sb);
33 static int lwpoly_to_kml2_sb(const LWPOLY *poly, int precision, const char *prefix, stringbuffer_t *sb);
34 static int lwcollection_to_kml2_sb(const LWCOLLECTION *col, int precision, const char *prefix, stringbuffer_t *sb);
35 static int ptarray_to_kml2_sb(const POINTARRAY *pa, int precision, stringbuffer_t *sb);
36 
37 /*
38 * KML 2.2.0
39 */
40 
41 /* takes a GEOMETRY and returns a KML representation */
42 char*
43 lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix)
44 {
45  stringbuffer_t *sb;
46  int rv;
47  char *kml;
48 
49  /* Can't do anything with empty */
50  if( lwgeom_is_empty(geom) )
51  return NULL;
52 
53  sb = stringbuffer_create();
54  rv = lwgeom_to_kml2_sb(geom, precision, prefix, sb);
55 
56  if ( rv == LW_FAILURE )
57  {
59  return NULL;
60  }
61 
64 
65  return kml;
66 }
67 
68 static int
69 lwgeom_to_kml2_sb(const LWGEOM *geom, int precision, const char *prefix, stringbuffer_t *sb)
70 {
71  switch (geom->type)
72  {
73  case POINTTYPE:
74  return lwpoint_to_kml2_sb((LWPOINT*)geom, precision, prefix, sb);
75 
76  case LINETYPE:
77  return lwline_to_kml2_sb((LWLINE*)geom, precision, prefix, sb);
78 
79  case POLYGONTYPE:
80  return lwpoly_to_kml2_sb((LWPOLY*)geom, precision, prefix, sb);
81 
82  case MULTIPOINTTYPE:
83  case MULTILINETYPE:
84  case MULTIPOLYGONTYPE:
85  return lwcollection_to_kml2_sb((LWCOLLECTION*)geom, precision, prefix, sb);
86 
87  default:
88  lwerror("lwgeom_to_kml2: '%s' geometry type not supported", lwtype_name(geom->type));
89  return LW_FAILURE;
90  }
91 }
92 
93 static int
95 {
96  int i, j;
97  int dims = FLAGS_GET_Z(pa->flags) ? 3 : 2;
98  POINT4D pt;
99  double *d;
100 
101  for ( i = 0; i < pa->npoints; i++ )
102  {
103  getPoint4d_p(pa, i, &pt);
104  d = (double*)(&pt);
105  if ( i ) stringbuffer_append(sb," ");
106  for (j = 0; j < dims; j++)
107  {
108  if ( j ) stringbuffer_append(sb,",");
109  if( fabs(d[j]) < OUT_MAX_DOUBLE )
110  {
111  if ( stringbuffer_aprintf(sb, "%.*f", precision, d[j]) < 0 ) return LW_FAILURE;
112  }
113  else
114  {
115  if ( stringbuffer_aprintf(sb, "%g", d[j]) < 0 ) return LW_FAILURE;
116  }
118  }
119  }
120  return LW_SUCCESS;
121 }
122 
123 
124 static int
125 lwpoint_to_kml2_sb(const LWPOINT *point, int precision, const char *prefix, stringbuffer_t *sb)
126 {
127  /* Open point */
128  if ( stringbuffer_aprintf(sb, "<%sPoint><%scoordinates>", prefix, prefix) < 0 ) return LW_FAILURE;
129  /* Coordinate array */
130  if ( ptarray_to_kml2_sb(point->point, precision, sb) == LW_FAILURE ) return LW_FAILURE;
131  /* Close point */
132  if ( stringbuffer_aprintf(sb, "</%scoordinates></%sPoint>", prefix, prefix) < 0 ) return LW_FAILURE;
133  return LW_SUCCESS;
134 }
135 
136 static int
137 lwline_to_kml2_sb(const LWLINE *line, int precision, const char *prefix, stringbuffer_t *sb)
138 {
139  /* Open linestring */
140  if ( stringbuffer_aprintf(sb, "<%sLineString><%scoordinates>", prefix, prefix) < 0 ) return LW_FAILURE;
141  /* Coordinate array */
142  if ( ptarray_to_kml2_sb(line->points, precision, sb) == LW_FAILURE ) return LW_FAILURE;
143  /* Close linestring */
144  if ( stringbuffer_aprintf(sb, "</%scoordinates></%sLineString>", prefix, prefix) < 0 ) return LW_FAILURE;
145 
146  return LW_SUCCESS;
147 }
148 
149 static int
150 lwpoly_to_kml2_sb(const LWPOLY *poly, int precision, const char *prefix, stringbuffer_t *sb)
151 {
152  int i, rv;
153 
154  /* Open polygon */
155  if ( stringbuffer_aprintf(sb, "<%sPolygon>", prefix) < 0 ) return LW_FAILURE;
156  for ( i = 0; i < poly->nrings; i++ )
157  {
158  /* Inner or outer ring opening tags */
159  if( i )
160  rv = stringbuffer_aprintf(sb, "<%sinnerBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix);
161  else
162  rv = stringbuffer_aprintf(sb, "<%souterBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix);
163  if ( rv < 0 ) return LW_FAILURE;
164 
165  /* Coordinate array */
166  if ( ptarray_to_kml2_sb(poly->rings[i], precision, sb) == LW_FAILURE ) return LW_FAILURE;
167 
168  /* Inner or outer ring closing tags */
169  if( i )
170  rv = stringbuffer_aprintf(sb, "</%scoordinates></%sLinearRing></%sinnerBoundaryIs>", prefix, prefix, prefix);
171  else
172  rv = stringbuffer_aprintf(sb, "</%scoordinates></%sLinearRing></%souterBoundaryIs>", prefix, prefix, prefix);
173  if ( rv < 0 ) return LW_FAILURE;
174  }
175  /* Close polygon */
176  if ( stringbuffer_aprintf(sb, "</%sPolygon>", prefix) < 0 ) return LW_FAILURE;
177 
178  return LW_SUCCESS;
179 }
180 
181 static int
182 lwcollection_to_kml2_sb(const LWCOLLECTION *col, int precision, const char *prefix, stringbuffer_t *sb)
183 {
184  int i, rv;
185 
186  /* Open geometry */
187  if ( stringbuffer_aprintf(sb, "<%sMultiGeometry>", prefix) < 0 ) return LW_FAILURE;
188  for ( i = 0; i < col->ngeoms; i++ )
189  {
190  rv = lwgeom_to_kml2_sb(col->geoms[i], precision, prefix, sb);
191  if ( rv == LW_FAILURE ) return LW_FAILURE;
192  }
193  /* Close geometry */
194  if ( stringbuffer_aprintf(sb, "</%sMultiGeometry>", prefix) < 0 ) return LW_FAILURE;
195 
196  return LW_SUCCESS;
197 }
#define LINETYPE
Definition: liblwgeom.h:86
char * lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix)
Definition: lwout_kml.c:43
stringbuffer_t * stringbuffer_create(void)
Allocate a new stringbuffer_t.
Definition: stringbuffer.c:35
int npoints
Definition: liblwgeom.h:371
uint8_t type
Definition: liblwgeom.h:503
#define POLYGONTYPE
Definition: liblwgeom.h:87
char * stringbuffer_getstringcopy(stringbuffer_t *s)
Returns a newly allocated string large enough to contain the current state of the string...
Definition: stringbuffer.c:160
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
#define LW_SUCCESS
Definition: liblwgeom.h:80
POINTARRAY * point
Definition: liblwgeom.h:411
#define LW_FAILURE
Definition: liblwgeom.h:79
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:253
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
uint8_t flags
Definition: liblwgeom.h:369
LWGEOM ** geoms
Definition: liblwgeom.h:509
POINTARRAY ** rings
Definition: liblwgeom.h:457
uint8_t precision
Definition: cu_in_twkb.c:25
static int lwgeom_to_kml2_sb(const LWGEOM *geom, int precision, const char *prefix, stringbuffer_t *sb)
Definition: lwout_kml.c:69
int nrings
Definition: liblwgeom.h:455
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:140
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
#define OUT_MAX_DOUBLE
void stringbuffer_append(stringbuffer_t *s, const char *a)
Append the specified string to the stringbuffer_t.
Definition: stringbuffer.c:134
void stringbuffer_destroy(stringbuffer_t *s)
Free the stringbuffer_t and all memory managed within it.
Definition: stringbuffer.c:78
static int lwcollection_to_kml2_sb(const LWCOLLECTION *col, int precision, const char *prefix, stringbuffer_t *sb)
Definition: lwout_kml.c:182
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
uint8_t type
Definition: liblwgeom.h:396
static int ptarray_to_kml2_sb(const POINTARRAY *pa, int precision, stringbuffer_t *sb)
Definition: lwout_kml.c:94
static int lwpoly_to_kml2_sb(const LWPOLY *poly, int precision, const char *prefix, stringbuffer_t *sb)
Definition: lwout_kml.c:150
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:1346
static int lwline_to_kml2_sb(const LWLINE *line, int precision, const char *prefix, stringbuffer_t *sb)
Definition: lwout_kml.c:137
#define MULTILINETYPE
Definition: liblwgeom.h:89
int stringbuffer_trim_trailing_zeroes(stringbuffer_t *s)
Trims zeroes off the end of the last number in the stringbuffer.
Definition: stringbuffer.c:304
static int lwpoint_to_kml2_sb(const LWPOINT *point, int precision, const char *prefix, stringbuffer_t *sb)
Definition: lwout_kml.c:125
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:122
POINTARRAY * points
Definition: liblwgeom.h:422