PostGIS  3.0.6dev-r@@SVN_REVISION@@
postgis/lwgeom_transform.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 (C) 2001-2003 Refractions Research Inc.
22  *
23  **********************************************************************/
24 
25 
26 #include "postgres.h"
27 #include "fmgr.h"
28 #include "utils/builtins.h"
29 
30 #include "../postgis_config.h"
31 #include "liblwgeom.h"
32 #include "lwgeom_transform.h"
33 
34 #include "float.h" /* DBL_DIG */
35 
36 Datum transform(PG_FUNCTION_ARGS);
37 Datum transform_geom(PG_FUNCTION_ARGS);
38 Datum postgis_proj_version(PG_FUNCTION_ARGS);
39 Datum LWGEOM_asKML(PG_FUNCTION_ARGS);
40 
48 Datum transform(PG_FUNCTION_ARGS)
49 {
50  GSERIALIZED* geom;
51  GSERIALIZED* result=NULL;
52  LWGEOM* lwgeom;
53  LWPROJ *pj;
54  int32 srid_to, srid_from;
55 
56  srid_to = PG_GETARG_INT32(1);
57  if (srid_to == SRID_UNKNOWN)
58  {
59  elog(ERROR, "ST_Transform: %d is an invalid target SRID", SRID_UNKNOWN);
60  PG_RETURN_NULL();
61  }
62 
63  geom = PG_GETARG_GSERIALIZED_P_COPY(0);
64  srid_from = gserialized_get_srid(geom);
65 
66  if ( srid_from == SRID_UNKNOWN )
67  {
68  PG_FREE_IF_COPY(geom, 0);
69  elog(ERROR, "ST_Transform: Input geometry has unknown (%d) SRID", SRID_UNKNOWN);
70  PG_RETURN_NULL();
71  }
72 
73  /* Input SRID and output SRID are equal, noop */
74  if ( srid_from == srid_to )
75  PG_RETURN_POINTER(geom);
76 
77  if ( GetPJUsingFCInfo(fcinfo, srid_from, srid_to, &pj) == LW_FAILURE )
78  {
79  PG_FREE_IF_COPY(geom, 0);
80  elog(ERROR, "ST_Transform: Failure reading projections from spatial_ref_sys.");
81  PG_RETURN_NULL();
82  }
83 
84  /* now we have a geometry, and input/output PJ structs. */
85  lwgeom = lwgeom_from_gserialized(geom);
86  lwgeom_transform(lwgeom, pj);
87  lwgeom->srid = srid_to;
88 
89  /* Re-compute bbox if input had one (COMPUTE_BBOX TAINTING) */
90  if ( lwgeom->bbox )
91  {
92  lwgeom_refresh_bbox(lwgeom);
93  }
94 
95  result = geometry_serialize(lwgeom);
96  lwgeom_free(lwgeom);
97  PG_FREE_IF_COPY(geom, 0);
98 
99  PG_RETURN_POINTER(result); /* new geometry */
100 }
101 
111 Datum transform_geom(PG_FUNCTION_ARGS)
112 {
113  GSERIALIZED *gser, *gser_result=NULL;
114  LWGEOM *geom;
115  char *input_srs, *output_srs;
116  int32 result_srid;
117  int rv;
118 
119  /* Take a copy, since we will be altering the coordinates */
120  gser = PG_GETARG_GSERIALIZED_P_COPY(0);
121 
122  /* Convert from text to cstring for libproj */
123  input_srs = text_to_cstring(PG_GETARG_TEXT_P(1));
124  output_srs = text_to_cstring(PG_GETARG_TEXT_P(2));
125  result_srid = PG_GETARG_INT32(3);
126 
127  /* now we have a geometry, and input/output PJ structs. */
128  geom = lwgeom_from_gserialized(gser);
129  rv = lwgeom_transform_from_str(geom, input_srs, output_srs);
130  pfree(input_srs);
131  pfree(output_srs);
132 
133  if (rv == LW_FAILURE)
134  {
135  elog(ERROR, "coordinate transformation failed");
136  PG_RETURN_NULL();
137  }
138 
139  /* Re-compute bbox if input had one (COMPUTE_BBOX TAINTING) */
140  geom->srid = result_srid;
141  if (geom->bbox)
142  lwgeom_refresh_bbox(geom);
143 
144  gser_result = geometry_serialize(geom);
145  lwgeom_free(geom);
146  PG_FREE_IF_COPY(gser, 0);
147 
148  PG_RETURN_POINTER(gser_result); /* new geometry */
149 }
150 
151 
153 Datum postgis_proj_version(PG_FUNCTION_ARGS)
154 {
155 #if POSTGIS_PROJ_VERSION < 60
156  const char *ver = pj_get_release();
157  text *result = cstring_to_text(ver);
158 #else
159  PJ_INFO pji = proj_info();
160  text *result = cstring_to_text(pji.version);
161 #endif
162  PG_RETURN_POINTER(result);
163 }
164 
165 
170 Datum LWGEOM_asKML(PG_FUNCTION_ARGS)
171 {
172  LWGEOM *lwgeom;
173  char *kml;
174  text *result;
175  const char *default_prefix = ""; /* default prefix */
176  char *prefixbuf;
177  const char *prefix = default_prefix;
178  int32_t srid_from;
179  const int32_t srid_to = 4326;
180 
181  /* Get the geometry */
182  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P_COPY(0);
183  int precision = PG_GETARG_INT32(1);
184  text *prefix_text = PG_GETARG_TEXT_P(2);
185  srid_from = gserialized_get_srid(geom);
186 
187  if ( srid_from == SRID_UNKNOWN )
188  {
189  PG_FREE_IF_COPY(geom, 0);
190  elog(ERROR, "ST_AsKML: Input geometry has unknown (%d) SRID", SRID_UNKNOWN);
191  PG_RETURN_NULL();
192  }
193 
194  /* Condition precision */
195  if (precision > DBL_DIG)
196  precision = DBL_DIG;
197  if (precision < 0)
198  precision = 0;
199 
200  if (VARSIZE_ANY_EXHDR(prefix_text) > 0)
201  {
202  /* +2 is one for the ':' and one for term null */
203  prefixbuf = palloc(VARSIZE_ANY_EXHDR(prefix_text)+2);
204  memcpy(prefixbuf, VARDATA(prefix_text),
205  VARSIZE_ANY_EXHDR(prefix_text));
206  /* add colon and null terminate */
207  prefixbuf[VARSIZE_ANY_EXHDR(prefix_text)] = ':';
208  prefixbuf[VARSIZE_ANY_EXHDR(prefix_text)+1] = '\0';
209  prefix = prefixbuf;
210  }
211 
212  lwgeom = lwgeom_from_gserialized(geom);
213 
214  if (srid_from != srid_to)
215  {
216  LWPROJ *pj;
217  if (GetPJUsingFCInfo(fcinfo, srid_from, srid_to, &pj) == LW_FAILURE)
218  {
219  PG_FREE_IF_COPY(geom, 0);
220  elog(ERROR, "ST_AsKML: Failure reading projections from spatial_ref_sys.");
221  PG_RETURN_NULL();
222  }
223  lwgeom_transform(lwgeom, pj);
224  }
225 
226  kml = lwgeom_to_kml2(lwgeom, precision, prefix);
227  lwgeom_free(lwgeom);
228  PG_FREE_IF_COPY(geom, 0);
229 
230  if (!kml)
231  PG_RETURN_NULL();
232 
233  result = cstring_to_text(kml);
234  lwfree(kml);
235 
236  PG_RETURN_POINTER(result);
237 }
static uint8_t precision
Definition: cu_in_twkb.c:25
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: gserialized.c:126
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:239
void lwgeom_refresh_bbox(LWGEOM *lwgeom)
Drop current bbox and calculate a fresh one.
Definition: lwgeom.c:689
#define LW_FAILURE
Definition: liblwgeom.h:110
int lwgeom_transform(LWGEOM *geom, LWPROJ *pj)
Transform (reproject) a geometry in-place.
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1138
char * lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix)
Definition: lwout_kml.c:44
void lwfree(void *mem)
Definition: lwutil.c:242
int lwgeom_transform_from_str(LWGEOM *geom, const char *instr, const char *outstr)
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:229
This library is the generic geometry handling section of PostGIS.
char * text_to_cstring(const text *textptr)
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
Datum transform_geom(PG_FUNCTION_ARGS)
Datum transform(PG_FUNCTION_ARGS)
Datum postgis_proj_version(PG_FUNCTION_ARGS)
Datum LWGEOM_asKML(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(transform)
transform( GEOMETRY, INT (output srid) ) tmpPts - if there is a nadgrid error (-38),...
unsigned int int32
Definition: shpopen.c:273
GBOX * bbox
Definition: liblwgeom.h:444
int32_t srid
Definition: liblwgeom.h:446