35 #include "access/gist.h" 36 #include "access/itup.h" 39 #include "utils/elog.h" 41 #include "../postgis_config.h" 43 #include "lwgeom_pg.h" 45 #define SHOW_DIGS_DOUBLE 15 46 #define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1) 70 double bigA(
double u2);
71 double bigB(
double u2);
83 char *str = PG_GETARG_CSTRING(0);
90 if (strstr(str,
"SPHEROID") != str )
92 elog(ERROR,
"SPHEROID parser - doesn't start with SPHEROID");
97 nitems = sscanf(str,
"SPHEROID[\"%19[^\"]\",%lf,%lf]",
98 sphere->
name, &sphere->
a, &rf);
101 nitems = sscanf(str,
"SPHEROID(\"%19[^\"]\",%lf,%lf)",
102 sphere->
name, &sphere->
a, &rf);
106 elog(ERROR,
"SPHEROID parser - couldnt parse the spheroid");
112 sphere->
b = sphere->
a - (1.0/rf)*sphere->
a;
113 sphere->
e_sq = ((sphere->
a*sphere->
a) - (sphere->
b*sphere->
b)) /
114 (sphere->
a*sphere->
a);
115 sphere->
e = sqrt(sphere->
e_sq);
117 PG_RETURN_POINTER(sphere);
129 sprintf(result,
"SPHEROID(\"%s\",%.15g,%.15g)",
130 sphere->
name, sphere->
a, 1.0/sphere->
f);
132 PG_RETURN_CSTRING(result);
149 das = cos(azimuth)*cos(azimuth);
150 C = sphere->
f/16.0 * das * (4.0 + sphere->
f * (4.0 - 3.0 * das));
154 DL = ctsm + C * cos(sigma) * (-1.0 + 2.0 * ctsm*ctsm);
155 DL = sigma + C * sin(sigma) * DL;
156 return (1.0 - C) * sphere->
f * sin(azimuth) * DL;
172 e2 = sqrt(sphere->
a*sphere->
a-sphere->
b*sphere->
b)/sphere->
b;
173 return cos(azimuth)*cos(azimuth) * e2*e2;
187 return 1.0 + u2/256.0 * (64.0 + u2 * (-12.0 + 5.0 * u2));
201 return u2/512.0 * (128.0 + u2 * (-64.0 + 37.0 * u2));
208 double lat2,
double long2,
SPHEROID *sphere)
211 #if POSTGIS_DEBUG_LEVEL >= 4 215 if ( (lat1==lat2) && (long1 == long2) )
222 #if POSTGIS_DEBUG_LEVEL >= 4 225 POSTGIS_DEBUGF(4,
"delta = %lf, skae says: %.15lf,2 circle says: %.15lf",
226 (result2-result),result,result2);
227 POSTGIS_DEBUGF(4,
"2 circle says: %.15lf",result2);
230 if (result != result)
247 double lat2,
double long2,
SPHEROID *sphere)
256 double L1,L2,sinU1,sinU2,cosU1,cosU2;
257 double dl,dl1,dl2,dl3,cosdl1,sindl1;
258 double cosSigma,sigma,azimuthEQ,tsm;
267 L1 = atan((1.0 - sphere->
f ) * tan( lat1) );
268 L2 = atan((1.0 - sphere->
f ) * tan( lat2) );
281 cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosdl1;
282 sigma = acos(cosSigma);
283 azimuthEQ = asin((cosU1 * cosU2 * sindl1)/sin(sigma));
289 TEMP = cosSigma - (2.0 * sinU1 * sinU2)/
290 (cos(azimuthEQ)*cos(azimuthEQ));
307 dl3 = dl1 - (dl + dl2);
313 while ( (iterations<999) && (fabs(dl3) > 1.0e-032));
316 u2 =
mu2(azimuthEQ,sphere);
321 dsigma = B * sin(sigma) * (cos(tsm) +
322 (B*cosSigma*(-1.0 + 2.0 * (cos(tsm)*cos(tsm))))/4.0);
323 return sphere->
b * (A * (sigma - dsigma));
344 PG_FREE_IF_COPY(geom, 0);
345 PG_RETURN_FLOAT8(dist);
371 PG_RETURN_FLOAT8(0.0);
376 PG_FREE_IF_COPY(geom, 0);
381 elog(ERROR,
"lwgeom_length_spheroid returned length < 0.0");
386 PG_RETURN_FLOAT8(length);
454 double R,S,X,Y,deltaX,deltaY;
457 double sin_lat = sin(lat1);
458 double sin2_lat = sin_lat * sin_lat;
460 double Geocent_a = sphere->
a;
461 double Geocent_e2 = sphere->
e_sq;
463 R = Geocent_a / (sqrt(1.0e0 - Geocent_e2 * sin2_lat));
465 S = R * sin(M_PI_2 - lat1) ;
467 deltaX = long2 - long1;
468 deltaY = lat2 - lat1;
471 X = deltaX/(2.0*M_PI) * 2 * M_PI * S;
472 Y = deltaY/(2.0*M_PI) * 2 * M_PI * R;
474 distance = sqrt((X * X + Y * Y));
490 bool use_spheroid = PG_GETARG_BOOL(3);
491 LWGEOM *lwgeom1, *lwgeom2;
500 if ( ! use_spheroid )
502 sphere->
a = sphere->
b = sphere->
radius;
508 elog(ERROR,
"geometry_distance_spheroid: Only point/line/polygon supported.\n");
515 elog(ERROR,
"geometry_distance_spheroid: Only point/line/polygon supported.\n");
529 PG_RETURN_FLOAT8(distance);
537 PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), PG_GETARG_DATUM(2), BoolGetDatum(
TRUE)));
550 PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), PointerGetDatum(&s), BoolGetDatum(
FALSE)));
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area...
Datum LWGEOM_length_ellipsoid_linestring(PG_FUNCTION_ARGS)
void spheroid_init(SPHEROID *s, double a, double b)
Initialize a spheroid object for use in geodetic functions.
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Datum ellipsoid_in(PG_FUNCTION_ARGS)
void lwgeom_free(LWGEOM *geom)
Datum LWGEOM_length2d_ellipsoid(PG_FUNCTION_ARGS)
void error_if_srid_mismatch(int srid1, int srid2)
double lwgeom_length_spheroid(const LWGEOM *geom, const SPHEROID *s)
Calculate the geodetic length of a lwgeom on the unit sphere.
Datum LWGEOM_distance_sphere(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(ellipsoid_in)
double mu2(double azimuth, SPHEROID *sphere)
#define LW_TRUE
Return types for functions with status returns.
double distance_ellipse(double lat1, double long1, double lat2, double long2, SPHEROID *sphere)
double distance_sphere_method(double lat1, double long1, double lat2, double long2, SPHEROID *sphere)
Datum distance(PG_FUNCTION_ARGS)
void lwgeom_set_geodetic(LWGEOM *geom, int value)
Set the FLAGS geodetic bit on geometry an all sub-geometries and pointlists.
double distance_ellipse_calculation(double lat1, double long1, double lat2, double long2, SPHEROID *sphere)
double deltaLongitude(double azimuth, double sigma, double tsm, SPHEROID *sphere)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Datum geometry_distance_spheroid(PG_FUNCTION_ARGS)
double lwgeom_distance_spheroid(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2, const SPHEROID *spheroid, double tolerance)
Calculate the geodetic distance from lwgeom1 to lwgeom2 on the spheroid.
Datum LWGEOM_distance_ellipsoid(PG_FUNCTION_ARGS)
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Datum ellipsoid_out(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)...
This library is the generic geometry handling section of PostGIS.