PostGIS  2.4.9dev-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 
29 #include "../postgis_config.h"
30 #include "liblwgeom.h"
31 #include "lwgeom_transform.h"
32 
33 
34 Datum transform(PG_FUNCTION_ARGS);
35 Datum transform_geom(PG_FUNCTION_ARGS);
36 Datum postgis_proj_version(PG_FUNCTION_ARGS);
37 
38 
39 
47 Datum transform(PG_FUNCTION_ARGS)
48 {
49  GSERIALIZED *geom;
50  GSERIALIZED *result=NULL;
51  LWGEOM *lwgeom;
52  projPJ input_pj, output_pj;
53  int32 output_srid, input_srid;
54 
55  output_srid = PG_GETARG_INT32(1);
56  if (output_srid == SRID_UNKNOWN)
57  {
58  elog(ERROR,"%d is an invalid target SRID",SRID_UNKNOWN);
59  PG_RETURN_NULL();
60  }
61 
62  geom = PG_GETARG_GSERIALIZED_P_COPY(0);
63  input_srid = gserialized_get_srid(geom);
64  if ( input_srid == SRID_UNKNOWN )
65  {
66  PG_FREE_IF_COPY(geom, 0);
67  elog(ERROR,"Input geometry has unknown (%d) SRID",SRID_UNKNOWN);
68  PG_RETURN_NULL();
69  }
70 
71  /*
72  * If input SRID and output SRID are equal, return geometry
73  * without transform it
74  */
75  if ( input_srid == output_srid )
76  PG_RETURN_POINTER(PG_GETARG_DATUM(0));
77 
78  if ( GetProjectionsUsingFCInfo(fcinfo, input_srid, output_srid, &input_pj, &output_pj) == LW_FAILURE )
79  {
80  PG_FREE_IF_COPY(geom, 0);
81  elog(ERROR,"Failure reading projections from spatial_ref_sys.");
82  PG_RETURN_NULL();
83  }
84 
85  /* now we have a geometry, and input/output PJ structs. */
86  lwgeom = lwgeom_from_gserialized(geom);
87  lwgeom_transform(lwgeom, input_pj, output_pj);
88  lwgeom->srid = output_srid;
89 
90  /* Re-compute bbox if input had one (COMPUTE_BBOX TAINTING) */
91  if ( lwgeom->bbox )
92  {
93  lwgeom_drop_bbox(lwgeom);
94  lwgeom_add_bbox(lwgeom);
95  }
96 
97  result = geometry_serialize(lwgeom);
98  lwgeom_free(lwgeom);
99  PG_FREE_IF_COPY(geom, 0);
100 
101  PG_RETURN_POINTER(result); /* new geometry */
102 }
103 
113 Datum transform_geom(PG_FUNCTION_ARGS)
114 {
115  GSERIALIZED *geom;
116  GSERIALIZED *result=NULL;
117  LWGEOM *lwgeom;
118  projPJ input_pj, output_pj;
119  char *input_proj4, *output_proj4;
120  text *input_proj4_text;
121  text *output_proj4_text;
122  int32 result_srid ;
123  char *pj_errstr;
124 
125  result_srid = PG_GETARG_INT32(3);
126  geom = PG_GETARG_GSERIALIZED_P_COPY(0);
127 
128  /* Set the search path if we haven't already */
129  SetPROJ4LibPath();
130 
131  /* Read the arguments */
132  input_proj4_text = (PG_GETARG_TEXT_P(1));
133  output_proj4_text = (PG_GETARG_TEXT_P(2));
134 
135  /* Convert from text to cstring for libproj */
136  input_proj4 = text2cstring(input_proj4_text);
137  output_proj4 = text2cstring(output_proj4_text);
138 
139  /* make input and output projection objects */
140  input_pj = lwproj_from_string(input_proj4);
141  if ( input_pj == NULL )
142  {
143  pj_errstr = pj_strerrno(*pj_get_errno_ref());
144  if ( ! pj_errstr ) pj_errstr = "";
145 
146  /* we need this for error reporting */
147  /* pfree(input_proj4); */
148  pfree(output_proj4);
149  pfree(geom);
150 
151  elog(ERROR,
152  "transform_geom: could not parse proj4 string '%s' %s",
153  input_proj4, pj_errstr);
154  PG_RETURN_NULL();
155  }
156  pfree(input_proj4);
157 
158  output_pj = lwproj_from_string(output_proj4);
159 
160  if ( output_pj == NULL )
161  {
162  pj_errstr = pj_strerrno(*pj_get_errno_ref());
163  if ( ! pj_errstr ) pj_errstr = "";
164 
165  /* we need this for error reporting */
166  /* pfree(output_proj4); */
167  pj_free(input_pj);
168  pfree(geom);
169 
170  elog(ERROR,
171  "transform_geom: couldn't parse proj4 output string: '%s': %s",
172  output_proj4, pj_errstr);
173  PG_RETURN_NULL();
174  }
175  pfree(output_proj4);
176 
177  /* now we have a geometry, and input/output PJ structs. */
178  lwgeom = lwgeom_from_gserialized(geom);
179  lwgeom_transform(lwgeom, input_pj, output_pj);
180  lwgeom->srid = result_srid;
181 
182  /* clean up */
183  pj_free(input_pj);
184  pj_free(output_pj);
185 
186  /* Re-compute bbox if input had one (COMPUTE_BBOX TAINTING) */
187  if ( lwgeom->bbox )
188  {
189  lwgeom_drop_bbox(lwgeom);
190  lwgeom_add_bbox(lwgeom);
191  }
192 
193  result = geometry_serialize(lwgeom);
194 
195  lwgeom_free(lwgeom);
196  PG_FREE_IF_COPY(geom, 0);
197 
198  PG_RETURN_POINTER(result); /* new geometry */
199 }
200 
201 
203 Datum postgis_proj_version(PG_FUNCTION_ARGS)
204 {
205  const char *ver = pj_get_release();
206  text *result = cstring2text(ver);
207  PG_RETURN_POINTER(result);
208 }
unsigned int int32
Definition: shpopen.c:273
GBOX * bbox
Definition: liblwgeom.h:398
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:1099
int lwgeom_transform(LWGEOM *geom, projPJ inpj, projPJ outpj)
Transform (reproject) a geometry in-place.
void lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
Definition: lwgeom.c:635
int32_t srid
Definition: liblwgeom.h:399
#define LW_FAILURE
Definition: liblwgeom.h:79
projPJ lwproj_from_string(const char *txt)
Get a projection from a string representation.
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:188
char * text2cstring(const text *textptr)
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)
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:648
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:100
This library is the generic geometry handling section of PostGIS.