29 #include "utils/builtins.h"
31 #include "../postgis_config.h"
35 #include "lwgeom_transform.h"
58 int32 srid_to, srid_from;
60 srid_to = PG_GETARG_INT32(1);
63 elog(ERROR,
"ST_Transform: %d is an invalid target SRID",
SRID_UNKNOWN);
67 geom = PG_GETARG_GSERIALIZED_P_COPY(0);
72 PG_FREE_IF_COPY(geom, 0);
73 elog(ERROR,
"ST_Transform: Input geometry has unknown (%d) SRID",
SRID_UNKNOWN);
78 if ( srid_from == srid_to )
79 PG_RETURN_POINTER(geom);
81 postgis_initialize_cache();
82 if ( lwproj_lookup(srid_from, srid_to, &pj) ==
LW_FAILURE )
84 PG_FREE_IF_COPY(geom, 0);
85 elog(ERROR,
"ST_Transform: Failure reading projections from spatial_ref_sys.");
92 lwgeom->
srid = srid_to;
100 result = geometry_serialize(lwgeom);
102 PG_FREE_IF_COPY(geom, 0);
104 PG_RETURN_POINTER(
result);
120 char *input_srs, *output_srs;
125 gser = PG_GETARG_GSERIALIZED_P_COPY(0);
128 input_srs = text_to_cstring(PG_GETARG_TEXT_P(1));
129 output_srs = text_to_cstring(PG_GETARG_TEXT_P(2));
130 result_srid = PG_GETARG_INT32(3);
140 elog(ERROR,
"coordinate transformation failed");
145 geom->
srid = result_srid;
149 gser_result = geometry_serialize(geom);
151 PG_FREE_IF_COPY(gser, 0);
153 PG_RETURN_POINTER(gser_result);
166 char *input_pipeline;
172 gser = PG_GETARG_GSERIALIZED_P_COPY(0);
175 input_pipeline = text_to_cstring(PG_GETARG_TEXT_P(1));
176 is_forward = PG_GETARG_BOOL(2);
177 result_srid = PG_GETARG_INT32(3);
181 pfree(input_pipeline);
185 elog(ERROR,
"coordinate transformation failed");
190 geom->
srid = result_srid;
194 gser_result = geometry_serialize(geom);
196 PG_FREE_IF_COPY(gser, 0);
198 PG_RETURN_POINTER(gser_result);
207 PJ_INFO pji = proj_info();
211 #if POSTGIS_PROJ_VERSION >= 70100
214 " NETWORK_ENABLED=%s",
215 proj_context_is_network_enabled(NULL) ?
"ON" :
"OFF");
217 if (proj_context_get_url_endpoint(NULL))
220 if (proj_context_get_user_writable_directory(NULL, 0))
221 stringbuffer_aprintf(&sb,
" USER_WRITABLE_DIRECTORY=%s", proj_context_get_user_writable_directory(NULL, 0));
223 if (proj_context_get_database_path(NULL))
244 result = cstring_to_text(ver);
245 PG_RETURN_POINTER(
result);
256 const char *default_prefix =
"";
258 const char *prefix = default_prefix;
260 const int32_t srid_to = 4326;
263 GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P_COPY(0);
265 text *prefix_text = PG_GETARG_TEXT_P(2);
270 PG_FREE_IF_COPY(geom, 0);
271 elog(ERROR,
"ST_AsKML: Input geometry has unknown (%d) SRID",
SRID_UNKNOWN);
279 if (VARSIZE_ANY_EXHDR(prefix_text) > 0)
282 prefixbuf = palloc(VARSIZE_ANY_EXHDR(prefix_text)+2);
283 memcpy(prefixbuf, VARDATA(prefix_text),
284 VARSIZE_ANY_EXHDR(prefix_text));
286 prefixbuf[VARSIZE_ANY_EXHDR(prefix_text)] =
':';
287 prefixbuf[VARSIZE_ANY_EXHDR(prefix_text)+1] =
'\0';
293 if (srid_from != srid_to)
296 if (lwproj_lookup(srid_from, srid_to, &pj) ==
LW_FAILURE)
298 PG_FREE_IF_COPY(geom, 0);
299 elog(ERROR,
"ST_AsKML: Failure reading projections from spatial_ref_sys.");
307 PG_RETURN_TEXT_P(kml);
333 if (entry_a->
sort < entry_b->
sort)
return -1;
334 else if (entry_a->
sort > entry_b->
sort)
return 1;
342 Datum tuple_data[7] = {0, 0, 0, 0, 0, 0, 0};
343 bool tuple_null[7] = {
true,
true,
true,
true,
true,
true,
true};
344 PJ_CONTEXT * ctx = NULL;
345 const char *
const empty_options[2] = {NULL};
346 const char *
const wkt_options[2] = {
"MULTILINE=NO", NULL};
348 const char * proj4text;
350 double w_lon, s_lat, e_lon, n_lat;
353 PJ *obj = proj_create_from_database(ctx,
356 PJ_CATEGORY_CRS, 0, empty_options);
361 srtext = proj_as_wkt(ctx, obj, PJ_WKT1_GDAL, wkt_options);
362 proj4text = proj_as_proj_string(ctx, obj, PJ_PROJ_4, empty_options);
363 srname = proj_get_name(obj);
364 ok = proj_get_area_of_use(ctx, obj, &w_lon, &s_lat, &e_lon, &n_lat, NULL);
367 tuple_data[0] = PointerGetDatum(entry->
auth_name);
368 tuple_null[0] =
false;
372 tuple_data[1] = PointerGetDatum(entry->
auth_code);
373 tuple_null[1] =
false;
377 tuple_data[2] = PointerGetDatum(cstring_to_text(srname));
378 tuple_null[2] =
false;
382 tuple_data[3] = PointerGetDatum(cstring_to_text(srtext));
383 tuple_null[3] =
false;
387 tuple_data[4] = PointerGetDatum(cstring_to_text(proj4text));
388 tuple_null[4] =
false;
396 tuple_data[5] = PointerGetDatum(g_sw);
397 tuple_null[5] =
false;
398 tuple_data[6] = PointerGetDatum(g_ne);
399 tuple_null[6] =
false;
402 tuple = heap_form_tuple(tuple_desc, tuple_data, tuple_null);
405 return HeapTupleGetDatum(tuple);
411 struct srs_data *state = palloc0(
sizeof(*state));
437 PJ_TYPE types[
ntypes] = {PJ_TYPE_PROJECTED_CRS, PJ_TYPE_GEOGRAPHIC_CRS, PJ_TYPE_COMPOUND_CRS};
440 for (j = 0; j <
ntypes; j++)
442 PJ_CONTEXT *ctx = NULL;
443 int allow_deprecated = 0;
444 PJ_TYPE
type = types[j];
445 PROJ_STRING_LIST codes_ptr = proj_get_codes_from_database(ctx, auth_name,
type, allow_deprecated);
446 PROJ_STRING_LIST codes = codes_ptr;
448 while(codes && *codes)
461 proj_string_list_destroy(codes_ptr);
469 const int32_t srid_to = 4326;
471 PJ_TYPE types[1] = {PJ_TYPE_PROJECTED_CRS};
472 PROJ_CRS_INFO **crs_list_ptr, **crs_list;
474 PJ_CONTEXT *ctx = NULL;
476 PROJ_CRS_LIST_PARAMETERS *params = proj_get_crs_list_parameters_create();
477 params->types = types;
478 params->typesCount = 1;
479 params->crs_area_of_use_contains_bbox =
true;
480 params->bbox_valid =
true;
481 params->allow_deprecated =
false;
483 #if POSTGIS_PROJ_VERSION >= 80100
484 params->celestial_body_name =
"Earth";
487 if (srid_from != srid_to)
490 if (lwproj_lookup(srid_from, srid_to, &pj) ==
LW_FAILURE)
491 elog(ERROR,
"%s: Lookup of SRID %u => %u transform failed",
492 __func__, srid_from, srid_to);
497 params->west_lon_degree = gbox.
xmin;
498 params->south_lat_degree = gbox.
ymin;
499 params->east_lon_degree = gbox.
xmax;
500 params->north_lat_degree = gbox.
ymax;
502 crs_list = crs_list_ptr = proj_get_crs_info_list_from_database(
503 ctx, auth_name, params, &crs_count);
507 while (crs_list && *crs_list)
510 PROJ_CRS_INFO *crs = *crs_list++;
514 double height = crs->north_lat_degree - crs->south_lat_degree;
515 double width = crs->east_lon_degree - crs->west_lon_degree;
517 width = 360 - (crs->west_lon_degree - crs->east_lon_degree);
518 area = width * height;
533 proj_crs_info_list_destroy(crs_list_ptr);
534 proj_get_crs_list_parameters_destroy(params);
549 TupleDesc tuple_desc;
551 if (get_call_result_type(fcinfo, 0, &tuple_desc) != TYPEFUNC_COMPOSITE)
553 ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
554 errmsg(
"%s called with incompatible return type", __func__)));
556 BlessTupleDesc(tuple_desc);
573 FuncCallContext *funcctx;
574 MemoryContext oldcontext;
584 if (SRF_IS_FIRSTCALL())
586 funcctx = SRF_FIRSTCALL_INIT();
587 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
604 if (get_call_result_type(fcinfo, 0, &funcctx->tuple_desc) != TYPEFUNC_COMPOSITE)
606 ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
607 errmsg(
"%s called with incompatible return type", __func__)));
610 BlessTupleDesc(funcctx->tuple_desc);
611 funcctx->user_fctx = state;
612 MemoryContextSwitchTo(oldcontext);
616 funcctx = SRF_PERCALL_SETUP();
617 state = funcctx->user_fctx;
622 SRF_RETURN_DONE(funcctx);
628 funcctx->tuple_desc);
631 SRF_RETURN_NEXT(funcctx,
result);
634 SRF_RETURN_DONE(funcctx);
642 FuncCallContext *funcctx;
643 MemoryContext oldcontext;
646 text* auth_name = PG_GETARG_TEXT_P(0);
655 if (SRF_IS_FIRSTCALL())
661 funcctx = SRF_FIRSTCALL_INIT();
662 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
665 funcctx->user_fctx = state;
666 MemoryContextSwitchTo(oldcontext);
670 funcctx = SRF_PERCALL_SETUP();
671 state = funcctx->user_fctx;
676 SRF_RETURN_DONE(funcctx);
681 result = PointerGetDatum(auth_code);
685 SRF_RETURN_NEXT(funcctx,
result);
688 SRF_RETURN_DONE(funcctx);
689 SRF_RETURN_DONE(funcctx);
701 FuncCallContext *funcctx;
702 MemoryContext oldcontext;
712 if (SRF_IS_FIRSTCALL())
716 text *auth_name = PG_GETARG_TEXT_P(1);
718 funcctx = SRF_FIRSTCALL_INIT();
719 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
736 if (get_call_result_type(fcinfo, 0, &funcctx->tuple_desc) != TYPEFUNC_COMPOSITE)
738 ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
739 errmsg(
"%s called with incompatible return type", __func__)));
742 BlessTupleDesc(funcctx->tuple_desc);
743 funcctx->user_fctx = state;
744 MemoryContextSwitchTo(oldcontext);
748 funcctx = SRF_PERCALL_SETUP();
749 state = funcctx->user_fctx;
755 SRF_RETURN_DONE(funcctx);
761 funcctx->tuple_desc);
764 SRF_RETURN_NEXT(funcctx,
result);
767 SRF_RETURN_DONE(funcctx);
char result[OUT_DOUBLE_BUFFER_SIZE]
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)...
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
void lwgeom_refresh_bbox(LWGEOM *lwgeom)
Drop current bbox and calculate a fresh one.
lwvarlena_t * lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix)
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
LWPOINT * lwpoint_make2d(int32_t srid, double x, double y)
int lwgeom_transform(LWGEOM *geom, LWPROJ *pj)
Transform (reproject) a geometry in-place.
void lwgeom_free(LWGEOM *geom)
int box3d_transform(GBOX *box, LWPROJ *pj)
int lwgeom_transform_from_str(LWGEOM *geom, const char *instr, const char *outstr)
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
int lwgeom_transform_pipeline(LWGEOM *geom, const char *pipeline, bool is_forward)
Transform (reproject) a geometry in-place using a PROJ pipeline.
#define SRID_UNKNOWN
Unknown SRID value.
This library is the generic geometry handling section of PostGIS.
static struct srs_data * srs_state_init()
static void srs_state_memcheck(struct srs_data *state)
Datum postgis_proj_compiled_version(PG_FUNCTION_ARGS)
Datum postgis_srs_entry(PG_FUNCTION_ARGS)
Search for srtext and proj4text given auth_name and auth_srid, returns TABLE(auth_name text,...
static void srs_state_codes(const char *auth_name, struct srs_data *state)
Datum transform_geom(PG_FUNCTION_ARGS)
Datum postgis_srs_search(PG_FUNCTION_ARGS)
Search for projections given extent and (optional) auth_name returns TABLE(auth_name,...
Datum transform(PG_FUNCTION_ARGS)
Datum postgis_proj_version(PG_FUNCTION_ARGS)
Datum postgis_srs_entry_all(PG_FUNCTION_ARGS)
static Datum srs_tuple_from_entry(const struct srs_entry *entry, TupleDesc tuple_desc)
static int srs_entry_cmp(const void *a, const void *b)
Datum transform_pipeline_geom(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),...
static void srs_find_planar(const char *auth_name, const LWGEOM *bounds, struct srs_data *state)
Datum postgis_srs_codes(PG_FUNCTION_ARGS)
#define POSTGIS_PROJ_VERSION
int stringbuffer_aprintf(stringbuffer_t *s, const char *fmt,...)
Appends a formatted string to the current string buffer, using the format and argument list provided.
void stringbuffer_init(stringbuffer_t *s)
const char * stringbuffer_getstring(stringbuffer_t *s)
Returns a reference to the internal string being managed by the stringbuffer.
static void stringbuffer_append(stringbuffer_t *s, const char *a)
Append the specified string to the stringbuffer_t.
struct srs_entry * entries