PostGIS  2.5.1dev-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 
35 Datum transform(PG_FUNCTION_ARGS);
36 Datum transform_geom(PG_FUNCTION_ARGS);
37 Datum postgis_proj_version(PG_FUNCTION_ARGS);
38 
39 
40 
48 Datum transform(PG_FUNCTION_ARGS)
49 {
50  GSERIALIZED *geom;
51  GSERIALIZED *result=NULL;
52  LWGEOM *lwgeom;
53  projPJ input_pj, output_pj;
54  int32 output_srid, input_srid;
55 
56  output_srid = PG_GETARG_INT32(1);
57  if (output_srid == SRID_UNKNOWN)
58  {
59  elog(ERROR, "%d is an invalid target SRID", SRID_UNKNOWN);
60  PG_RETURN_NULL();
61  }
62 
63  geom = PG_GETARG_GSERIALIZED_P_COPY(0);
64  input_srid = gserialized_get_srid(geom);
65 
66  if ( input_srid == SRID_UNKNOWN )
67  {
68  PG_FREE_IF_COPY(geom, 0);
69  elog(ERROR, "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 ( input_srid == output_srid )
75  PG_RETURN_POINTER(geom);
76 
77  if ( GetProjectionsUsingFCInfo(fcinfo, input_srid, output_srid, &input_pj, &output_pj) == LW_FAILURE )
78  {
79  PG_FREE_IF_COPY(geom, 0);
80  elog(ERROR, "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, input_pj, output_pj);
87  lwgeom->srid = output_srid;
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 *geom;
114  GSERIALIZED *result=NULL;
115  LWGEOM *lwgeom;
116  projPJ input_pj, output_pj;
117  char *input_proj4, *output_proj4;
118  text *input_proj4_text;
119  text *output_proj4_text;
120  int32 result_srid ;
121  char *pj_errstr;
122 
123  result_srid = PG_GETARG_INT32(3);
124  geom = PG_GETARG_GSERIALIZED_P_COPY(0);
125 
126  /* Set the search path if we haven't already */
127  SetPROJ4LibPath();
128 
129  /* Read the arguments */
130  input_proj4_text = (PG_GETARG_TEXT_P(1));
131  output_proj4_text = (PG_GETARG_TEXT_P(2));
132 
133  /* Convert from text to cstring for libproj */
134  input_proj4 = text_to_cstring(input_proj4_text);
135  output_proj4 = text_to_cstring(output_proj4_text);
136 
137  /* make input and output projection objects */
138  input_pj = lwproj_from_string(input_proj4);
139  if ( input_pj == NULL )
140  {
141  pj_errstr = pj_strerrno(*pj_get_errno_ref());
142  if ( ! pj_errstr ) pj_errstr = "";
143 
144  /* we need this for error reporting */
145  /* pfree(input_proj4); */
146  pfree(output_proj4);
147  pfree(geom);
148 
149  elog(ERROR,
150  "transform_geom: could not parse proj4 string '%s' %s",
151  input_proj4, pj_errstr);
152  PG_RETURN_NULL();
153  }
154  pfree(input_proj4);
155 
156  output_pj = lwproj_from_string(output_proj4);
157 
158  if ( output_pj == NULL )
159  {
160  pj_errstr = pj_strerrno(*pj_get_errno_ref());
161  if ( ! pj_errstr ) pj_errstr = "";
162 
163  /* we need this for error reporting */
164  /* pfree(output_proj4); */
165  pj_free(input_pj);
166  pfree(geom);
167 
168  elog(ERROR,
169  "transform_geom: couldn't parse proj4 output string: '%s': %s",
170  output_proj4, pj_errstr);
171  PG_RETURN_NULL();
172  }
173  pfree(output_proj4);
174 
175  /* now we have a geometry, and input/output PJ structs. */
176  lwgeom = lwgeom_from_gserialized(geom);
177  lwgeom_transform(lwgeom, input_pj, output_pj);
178  lwgeom->srid = result_srid;
179 
180  /* clean up */
181  pj_free(input_pj);
182  pj_free(output_pj);
183 
184  /* Re-compute bbox if input had one (COMPUTE_BBOX TAINTING) */
185  if ( lwgeom->bbox )
186  {
187  lwgeom_refresh_bbox(lwgeom);
188  }
189 
190  result = geometry_serialize(lwgeom);
191 
192  lwgeom_free(lwgeom);
193  PG_FREE_IF_COPY(geom, 0);
194 
195  PG_RETURN_POINTER(result); /* new geometry */
196 }
197 
198 
200 Datum postgis_proj_version(PG_FUNCTION_ARGS)
201 {
202  const char *ver = pj_get_release();
203  text *result = cstring_to_text(ver);
204  PG_RETURN_POINTER(result);
205 }
char * text_to_cstring(const text *textptr)
void lwgeom_refresh_bbox(LWGEOM *lwgeom)
Drop current bbox and calculate a fresh one.
Definition: lwgeom.c:698
unsigned int int32
Definition: shpopen.c:273
GBOX * bbox
Definition: liblwgeom.h:400
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Datum transform(PG_FUNCTION_ARGS)
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
int lwgeom_transform(LWGEOM *geom, projPJ inpj, projPJ outpj)
Transform (reproject) a geometry in-place.
int32_t srid
Definition: liblwgeom.h:401
#define LW_FAILURE
Definition: liblwgeom.h:78
projPJ lwproj_from_string(const char *txt)
Get a projection from a string representation.
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:187
Datum postgis_proj_version(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(transform)
transform( GEOMETRY, INT (output srid) ) tmpPts - if there is a nadgrid error (-38), we re-try the transform on a copy of points.
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
Datum transform_geom(PG_FUNCTION_ARGS)
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:99
This library is the generic geometry handling section of PostGIS.