26 #include "../postgis_config.h"
49 #if POSTGIS_PROJ_VERSION < 60
56 if (pj_is_latlong(pj->pj_from))
to_rad(pt) ;
58 LWDEBUGF(4,
"transforming POINT(%f %f) from '%s' to '%s'",
59 orig_pt.
x, orig_pt.
y, pj_get_def(pj->pj_from,0), pj_get_def(pj->pj_to,0));
61 if (pj_transform(pj->pj_from, pj->pj_to, 1, 0, &(pt->
x), &(pt->
y), &(pt->
z)) != 0)
63 int pj_errno_val = *pj_get_errno_ref();
64 if (pj_errno_val == -38)
66 lwnotice(
"PostGIS was unable to transform the point because either no grid"
67 " shift files were found, or the point does not lie within the "
68 "range for which the grid shift is defined. Refer to the "
69 "ST_Transform() section of the PostGIS manual for details on how "
70 "to configure PostGIS to alter this behaviour.");
71 lwerror(
"transform: couldn't project point (%g %g %g): %s (%d)",
72 orig_pt.
x, orig_pt.
y, orig_pt.
z,
73 pj_strerrno(pj_errno_val), pj_errno_val);
78 pj_strerrno(pj_errno_val), pj_errno_val);
83 if (pj_is_latlong(pj->pj_to))
to_dec(pt);
97 for ( i = 0; i < pa->
npoints; i++ )
100 if ( ! point4d_transform(&p, pj) )
return LW_FAILURE;
114 pj.pj_from = projpj_from_string(instr);
117 pj_errstr = pj_strerrno(*pj_get_errno_ref());
118 if (!pj_errstr) pj_errstr =
"";
119 lwerror(
"could not parse proj string '%s'", instr);
123 pj.pj_to = projpj_from_string(outstr);
127 pj_errstr = pj_strerrno(*pj_get_errno_ref());
128 if (!pj_errstr) pj_errstr =
"";
129 lwerror(
"could not parse proj string '%s'", outstr);
166 for ( i = 0; i < g->
nrings; i++ )
184 for ( i = 0; i < g->
ngeoms; i++ )
192 lwerror(
"lwgeom_transform: Cannot handle type '%s'",
201 projpj_from_string(
const char *str1)
203 if (!str1 || str1[0] ==
'\0')
207 return pj_init_plus(str1);
218 if (proj_get_type(pj_crs) == PJ_TYPE_COMPOUND_CRS)
221 pj_sub = proj_crs_get_sub_crs(NULL, pj_crs, 0);
223 lwerror(
"%s: proj_crs_get_sub_crs(0) returned NULL", __func__);
225 else if (proj_get_type(pj_crs) == PJ_TYPE_BOUND_CRS)
227 pj_sub = proj_get_source_crs(NULL, pj_crs);
229 lwerror(
"%s: proj_get_source_crs returned NULL", __func__);
234 pj_sub = proj_crs_get_coordinate_system(NULL, pj_crs);
244 lwerror(
"%s: %s", __func__, proj_errno_string(proj_context_errno(NULL)));
247 int pj_type = proj_get_type(pj_sub);
248 if (pj_type == PJ_TYPE_GEOGRAPHIC_2D_CRS || pj_type == PJ_TYPE_PROJECTED_CRS)
250 PJ *pj_2d = proj_crs_get_coordinate_system(NULL, pj_sub);
251 proj_destroy(pj_sub);
256 if (pj_type == PJ_TYPE_COMPOUND_CRS || pj_type == PJ_TYPE_BOUND_CRS)
260 lwerror(
"%s: un-handled CRS sub-type: %s", __func__, pj_type);
265 #define STR_EQUALS(A, B) strcmp((A), (B)) == 0
266 #define STR_IEQUALS(A, B) (strcasecmp((A), (B)) == 0)
267 #define STR_ISTARTS(A, B) (strncasecmp((A), (B), strlen((B))) == 0)
275 lwerror(
"%s: proj_cs_get_simplecs returned NULL", __func__);
277 axis_count = proj_cs_get_axis_count(NULL, pj_cs);
280 const char *out_name1, *out_abbrev1, *out_direction1;
281 const char *out_name2, *out_abbrev2, *out_direction2;
283 proj_cs_get_axis_info(NULL,
285 &out_name1, &out_abbrev1, &out_direction1,
286 NULL, NULL, NULL, NULL);
288 proj_cs_get_axis_info(NULL,
290 &out_name2, &out_abbrev2, &out_direction2,
291 NULL, NULL, NULL, NULL);
296 if(out_direction1 &&
STR_IEQUALS(out_direction1,
"north") &&
297 out_direction2 &&
STR_IEQUALS(out_direction2,
"east") )
303 if(out_direction1 && out_direction2 &&
327 PJ *pj_source_crs = proj_get_source_crs(NULL, pj);
328 uint8_t source_is_latlong =
LW_FALSE;
329 double out_semi_major_metre = DBL_MAX, out_semi_minor_metre = DBL_MAX;
333 lwerror(
"%s: unable to access source crs", __func__);
339 if (!extra_geography_data)
341 proj_destroy(pj_source_crs);
346 double out_inv_flattening;
347 int out_is_semi_minor_computed;
349 PJ_TYPE pj_type = proj_get_type(pj_source_crs);
350 if (pj_type == PJ_TYPE_UNKNOWN)
352 proj_destroy(pj_source_crs);
353 lwerror(
"%s: unable to access source crs type", __func__);
356 source_is_latlong = (pj_type == PJ_TYPE_GEOGRAPHIC_2D_CRS) || (pj_type == PJ_TYPE_GEOGRAPHIC_3D_CRS);
358 pj_ellps = proj_get_ellipsoid(NULL, pj_source_crs);
359 proj_destroy(pj_source_crs);
362 lwerror(
"%s: unable to access source crs ellipsoid", __func__);
365 if (!proj_ellipsoid_get_parameters(NULL,
367 &out_semi_major_metre,
368 &out_semi_minor_metre,
369 &out_is_semi_minor_computed,
370 &out_inv_flattening))
372 proj_destroy(pj_ellps);
373 lwerror(
"%s: unable to access source crs ellipsoid parameters", __func__);
376 proj_destroy(pj_ellps);
379 PJ *pj_target_crs = proj_get_target_crs(NULL, pj);
382 lwerror(
"%s: unable to access target crs", __func__);
386 proj_destroy(pj_target_crs);
402 PJ *pj = proj_create_crs_to_crs(NULL, instr, outstr, NULL);
405 PJ *pj_in = proj_create(NULL, instr);
408 proj_errno_reset(NULL);
409 lwerror(
"could not parse proj string '%s'", instr);
413 PJ *pj_out = proj_create(NULL, outstr);
416 proj_errno_reset(NULL);
417 lwerror(
"could not parse proj string '%s'", outstr);
419 proj_destroy(pj_out);
420 lwerror(
"%s: Failed to transform", __func__);
458 for (i = 0; i < g->
nrings; i++)
477 for (i = 0; i < g->
ngeoms; i++)
486 lwerror(
"lwgeom_transform: Cannot handle type '%s'",
506 if (proj_angular_input(pj->
pj, PJ_FWD))
508 for (i = 0; i < pa->
npoints; i++)
521 PJ_XYZT v = {pa_double[0], pa_double[1], has_z ? pa_double[2] : 0.0, 0.0};
522 PJ_COORD t = proj_trans(pj->
pj, PJ_FWD, (PJ_COORD)v);
524 int pj_errno_val = proj_errno(pj->
pj);
527 lwerror(
"transform: %s (%d)", proj_errno_string(pj_errno_val), pj_errno_val);
530 pa_double[0] = ((PJ_XYZT)t.xyzt).x;
531 pa_double[1] = ((PJ_XYZT)t.xyzt).y;
533 pa_double[2] = ((PJ_XYZT)t.xyzt).z;
545 n_converted = proj_trans_generic(pj->
pj,
553 has_z ? pa_double + 2 : NULL,
554 has_z ? point_size : 0,
555 has_z ? n_points : 0,
561 if (n_converted != n_points)
563 lwerror(
"ptarray_transform: converted (%d) != input (%d)", n_converted, n_points);
567 int pj_errno_val = proj_errno(pj->
pj);
570 lwerror(
"transform: %s (%d)", proj_errno_string(pj_errno_val), pj_errno_val);
579 if (proj_angular_output(pj->
pj, PJ_FWD))
581 for (i = 0; i < pa->
npoints; i++)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
#define POLYHEDRALSURFACETYPE
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
void * lwalloc(size_t size)
#define LW_TRUE
Return types for functions with status returns.
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
int ptarray_has_z(const POINTARRAY *pa)
void ptarray_swap_ordinates(POINTARRAY *pa, LWORD o1, LWORD o2)
Swap ordinate values o1 and o2 on a given POINTARRAY.
#define LWDEBUGF(level, msg,...)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
static size_t ptarray_point_size(const POINTARRAY *pa)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
uint8_t source_is_latlong
double source_semi_major_metre
double source_semi_minor_metre
uint8_t * serialized_pointlist