source: trunk/postgis/lwgeom_transform.c

Last change on this file was 17674, checked in by komzpa, 5 years ago

Triangle and TIN output support

Make all the "Unsupported geometry type" name themselves by func.
In case output format doesn't know about TIN/Triangle, output them as GeometryCollection/Polygon.

Closes #4399
Closes https://github.com/postgis/postgis/pull/454

  • Property svn:eol-style set to native
File size: 6.2 KB
Line 
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
36Datum transform(PG_FUNCTION_ARGS);
37Datum transform_geom(PG_FUNCTION_ARGS);
38Datum postgis_proj_version(PG_FUNCTION_ARGS);
39Datum LWGEOM_asKML(PG_FUNCTION_ARGS);
40
41/**
42 * transform( GEOMETRY, INT (output srid) )
43 * tmpPts - if there is a nadgrid error (-38), we re-try the transform
44 * on a copy of points. The transformed points
45 * are in an indeterminate state after the -38 error is thrown.
46 */
47PG_FUNCTION_INFO_V1(transform);
48Datum 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
102/**
103 * Transform_geom( GEOMETRY, TEXT (input proj4), TEXT (output proj4),
104 * INT (output srid)
105 *
106 * tmpPts - if there is a nadgrid error (-38), we re-try the transform
107 * on a copy of points. The transformed points
108 * are in an indeterminate state after the -38 error is thrown.
109 */
110PG_FUNCTION_INFO_V1(transform_geom);
111Datum 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
152PG_FUNCTION_INFO_V1(postgis_proj_version);
153Datum 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
166/**
167 * Encode feature in KML
168 */
169PG_FUNCTION_INFO_V1(LWGEOM_asKML);
170Datum 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}
Note: See TracBrowser for help on using the repository browser.