PostGIS  2.2.7dev-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  * Copyright (C) 2001-2003 Refractions Research Inc.
7  *
8  * This is free software; you can redistribute and/or modify it under
9  * the terms of the GNU General Public Licence. See the COPYING file.
10  *
11  **********************************************************************/
12 
13 #include "postgres.h"
14 #include "fmgr.h"
15 
16 #include "../postgis_config.h"
17 #include "liblwgeom.h"
18 #include "lwgeom_transform.h"
19 
20 
21 Datum transform(PG_FUNCTION_ARGS);
22 Datum transform_geom(PG_FUNCTION_ARGS);
23 Datum postgis_proj_version(PG_FUNCTION_ARGS);
24 
25 
26 
34 Datum transform(PG_FUNCTION_ARGS)
35 {
36  GSERIALIZED *geom;
37  GSERIALIZED *result=NULL;
38  LWGEOM *lwgeom;
39  projPJ input_pj, output_pj;
40  int32 output_srid, input_srid;
41 
42  output_srid = PG_GETARG_INT32(1);
43  if (output_srid == SRID_UNKNOWN)
44  {
45  elog(ERROR,"%d is an invalid target SRID",SRID_UNKNOWN);
46  PG_RETURN_NULL();
47  }
48 
49  geom = PG_GETARG_GSERIALIZED_P_COPY(0);
50  input_srid = gserialized_get_srid(geom);
51  if ( input_srid == SRID_UNKNOWN )
52  {
53  PG_FREE_IF_COPY(geom, 0);
54  elog(ERROR,"Input geometry has unknown (%d) SRID",SRID_UNKNOWN);
55  PG_RETURN_NULL();
56  }
57 
58  /*
59  * If input SRID and output SRID are equal, return geometry
60  * without transform it
61  */
62  if ( input_srid == output_srid )
63  PG_RETURN_POINTER(PG_GETARG_DATUM(0));
64 
65  if ( GetProjectionsUsingFCInfo(fcinfo, input_srid, output_srid, &input_pj, &output_pj) == LW_FAILURE )
66  {
67  PG_FREE_IF_COPY(geom, 0);
68  elog(ERROR,"Failure reading projections from spatial_ref_sys.");
69  PG_RETURN_NULL();
70  }
71 
72  /* now we have a geometry, and input/output PJ structs. */
73  lwgeom = lwgeom_from_gserialized(geom);
74  lwgeom_transform(lwgeom, input_pj, output_pj);
75  lwgeom->srid = output_srid;
76 
77  /* Re-compute bbox if input had one (COMPUTE_BBOX TAINTING) */
78  if ( lwgeom->bbox )
79  {
80  lwgeom_drop_bbox(lwgeom);
81  lwgeom_add_bbox(lwgeom);
82  }
83 
84  result = geometry_serialize(lwgeom);
85  lwgeom_free(lwgeom);
86  PG_FREE_IF_COPY(geom, 0);
87 
88  PG_RETURN_POINTER(result); /* new geometry */
89 }
90 
100 Datum transform_geom(PG_FUNCTION_ARGS)
101 {
102  GSERIALIZED *geom;
103  GSERIALIZED *result=NULL;
104  LWGEOM *lwgeom;
105  projPJ input_pj, output_pj;
106  char *input_proj4, *output_proj4;
107  text *input_proj4_text;
108  text *output_proj4_text;
109  int32 result_srid ;
110  char *pj_errstr;
111 
112 
113 
114  result_srid = PG_GETARG_INT32(3);
115  if (result_srid == SRID_UNKNOWN)
116  {
117  elog(ERROR,"transform: destination SRID = %d",SRID_UNKNOWN);
118  PG_RETURN_NULL();
119  }
120 
121  geom = PG_GETARG_GSERIALIZED_P_COPY(0);
122  if (gserialized_get_srid(geom) == SRID_UNKNOWN)
123  {
124  pfree(geom);
125  elog(ERROR,"transform_geom: source SRID = %d",SRID_UNKNOWN);
126  PG_RETURN_NULL();
127  }
128 
129  /* Set the search path if we haven't already */
130  SetPROJ4LibPath();
131 
132  /* Read the arguments */
133  input_proj4_text = (PG_GETARG_TEXT_P(1));
134  output_proj4_text = (PG_GETARG_TEXT_P(2));
135 
136  /* Convert from text to cstring for libproj */
137  input_proj4 = text2cstring(input_proj4_text);
138  output_proj4 = text2cstring(output_proj4_text);
139 
140  /* make input and output projection objects */
141  input_pj = lwproj_from_string(input_proj4);
142  if ( input_pj == NULL )
143  {
144  pj_errstr = pj_strerrno(*pj_get_errno_ref());
145  if ( ! pj_errstr ) pj_errstr = "";
146 
147  /* we need this for error reporting */
148  /* pfree(input_proj4); */
149  pfree(output_proj4);
150  pfree(geom);
151 
152  elog(ERROR,
153  "transform_geom: could not parse proj4 string '%s' %s",
154  input_proj4, pj_errstr);
155  PG_RETURN_NULL();
156  }
157  pfree(input_proj4);
158 
159  output_pj = lwproj_from_string(output_proj4);
160 
161  if ( output_pj == NULL )
162  {
163  pj_errstr = pj_strerrno(*pj_get_errno_ref());
164  if ( ! pj_errstr ) pj_errstr = "";
165 
166  /* we need this for error reporting */
167  /* pfree(output_proj4); */
168  pj_free(input_pj);
169  pfree(geom);
170 
171  elog(ERROR,
172  "transform_geom: couldn't parse proj4 output string: '%s': %s",
173  output_proj4, pj_errstr);
174  PG_RETURN_NULL();
175  }
176  pfree(output_proj4);
177 
178  /* now we have a geometry, and input/output PJ structs. */
179  lwgeom = lwgeom_from_gserialized(geom);
180  lwgeom_transform(lwgeom, input_pj, output_pj);
181  lwgeom->srid = result_srid;
182 
183  /* clean up */
184  pj_free(input_pj);
185  pj_free(output_pj);
186 
187  /* Re-compute bbox if input had one (COMPUTE_BBOX TAINTING) */
188  if ( lwgeom->bbox )
189  {
190  lwgeom_drop_bbox(lwgeom);
191  lwgeom_add_bbox(lwgeom);
192  }
193 
194  result = geometry_serialize(lwgeom);
195 
196  lwgeom_free(lwgeom);
197  PG_FREE_IF_COPY(geom, 0);
198 
199  PG_RETURN_POINTER(result); /* new geometry */
200 }
201 
202 
204 Datum postgis_proj_version(PG_FUNCTION_ARGS)
205 {
206  const char *ver = pj_get_release();
207  text *result = cstring2text(ver);
208  PG_RETURN_POINTER(result);
209 }
unsigned int int32
Definition: shpopen.c:273
GBOX * bbox
Definition: liblwgeom.h:382
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:1050
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:586
int32_t srid
Definition: liblwgeom.h:383
#define LW_FAILURE
Definition: liblwgeom.h:64
projPJ lwproj_from_string(const char *txt)
Get a projection from a string representation.
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:172
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:599
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:69
This library is the generic geometry handling section of PostGIS.