34 #include "access/gist.h"
35 #include "access/itup.h"
38 #include "utils/elog.h"
40 #include "../postgis_config.h"
42 #include "lwgeom_pg.h"
44 #define SHOW_DIGS_DOUBLE 15
45 #define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
69 double bigA(
double u2);
70 double bigB(
double u2);
82 char *
str = PG_GETARG_CSTRING(0);
89 if (strstr(
str,
"SPHEROID") !=
str )
91 elog(ERROR,
"SPHEROID parser - doesn't start with SPHEROID");
96 nitems = sscanf(
str,
"SPHEROID[\"%19[^\"]\",%lf,%lf]",
97 sphere->
name, &sphere->
a, &rf);
100 nitems = sscanf(
str,
"SPHEROID(\"%19[^\"]\",%lf,%lf)",
101 sphere->
name, &sphere->
a, &rf);
105 elog(ERROR,
"SPHEROID parser - couldnt parse the spheroid");
111 sphere->
b = sphere->
a - (1.0/rf)*sphere->
a;
112 sphere->
e_sq = ((sphere->
a*sphere->
a) - (sphere->
b*sphere->
b)) /
113 (sphere->
a*sphere->
a);
114 sphere->
e = sqrt(sphere->
e_sq);
116 PG_RETURN_POINTER(sphere);
128 snprintf(result, sz,
"SPHEROID(\"%s\",%.15g,%.15g)",
129 sphere->
name, sphere->
a, 1.0/sphere->
f);
131 PG_RETURN_CSTRING(result);
148 das = cos(azimuth)*cos(azimuth);
149 C = sphere->
f/16.0 * das * (4.0 + sphere->
f * (4.0 - 3.0 * das));
153 DL = ctsm + C * cos(sigma) * (-1.0 + 2.0 * ctsm*ctsm);
154 DL = sigma + C * sin(sigma) * DL;
155 return (1.0 - C) * sphere->
f * sin(azimuth) * DL;
171 e2 = sqrt(sphere->
a*sphere->
a-sphere->
b*sphere->
b)/sphere->
b;
172 return cos(azimuth)*cos(azimuth) * e2*e2;
186 return 1.0 + u2/256.0 * (64.0 + u2 * (-12.0 + 5.0 * u2));
200 return u2/512.0 * (128.0 + u2 * (-64.0 + 37.0 * u2));
207 double lat2,
double long2,
SPHEROID *sphere)
210 #if POSTGIS_DEBUG_LEVEL >= 4
214 if ( (lat1==lat2) && (long1 == long2) )
221 #if POSTGIS_DEBUG_LEVEL >= 4
224 POSTGIS_DEBUGF(4,
"delta = %lf, skae says: %.15lf,2 circle says: %.15lf",
225 (result2-result),result,result2);
226 POSTGIS_DEBUGF(4,
"2 circle says: %.15lf",result2);
229 if (result != result)
246 double lat2,
double long2,
SPHEROID *sphere)
255 double L1,L2,sinU1,sinU2,cosU1,cosU2;
256 double dl,dl1,dl2,dl3,cosdl1,sindl1;
257 double cosSigma,sigma,azimuthEQ,tsm;
266 L1 = atan((1.0 - sphere->
f ) * tan( lat1) );
267 L2 = atan((1.0 - sphere->
f ) * tan( lat2) );
280 cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosdl1;
281 sigma = acos(cosSigma);
282 azimuthEQ = asin((cosU1 * cosU2 * sindl1)/sin(sigma));
288 TEMP = cosSigma - (2.0 * sinU1 * sinU2)/
289 (cos(azimuthEQ)*cos(azimuthEQ));
306 dl3 = dl1 - (dl + dl2);
312 while ( (iterations<999) && (fabs(dl3) > 1.0e-032));
315 u2 =
mu2(azimuthEQ,sphere);
320 dsigma = B * sin(sigma) * (cos(tsm) +
321 (B*cosSigma*(-1.0 + 2.0 * (cos(tsm)*cos(tsm))))/4.0);
322 return sphere->
b * (A * (sigma - dsigma));
343 PG_FREE_IF_COPY(geom, 0);
344 PG_RETURN_FLOAT8(dist);
370 PG_RETURN_FLOAT8(0.0);
375 PG_FREE_IF_COPY(geom, 0);
380 elog(ERROR,
"lwgeom_length_spheroid returned length < 0.0");
385 PG_RETURN_FLOAT8(length);
453 double R,S,X,Y,deltaX,deltaY;
456 double sin_lat = sin(lat1);
457 double sin2_lat = sin_lat * sin_lat;
459 double Geocent_a = sphere->
a;
460 double Geocent_e2 = sphere->
e_sq;
462 R = Geocent_a / (sqrt(1.0e0 - Geocent_e2 * sin2_lat));
464 S = R * sin(M_PI_2 - lat1) ;
466 deltaX = long2 - long1;
467 deltaY = lat2 - lat1;
470 X = deltaX/(2.0*M_PI) * 2 * M_PI * S;
471 Y = deltaY/(2.0*M_PI) * 2 * M_PI * R;
489 bool use_spheroid = PG_GETARG_BOOL(3);
490 LWGEOM *lwgeom1, *lwgeom2;
498 if ( ! use_spheroid )
500 sphere->
a = sphere->
b = sphere->
radius;
506 elog(ERROR,
"geometry_distance_spheroid: Only point/line/polygon supported.\n");
513 elog(ERROR,
"geometry_distance_spheroid: Only point/line/polygon supported.\n");
535 PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), PG_GETARG_DATUM(2), BoolGetDatum(
true)));
545 s.a =
s.b =
s.radius;
548 PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), PointerGetDatum(&
s), BoolGetDatum(
false)));
void gserialized_error_if_srid_mismatch(const GSERIALIZED *g1, const GSERIALIZED *g2, const char *funcname)
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
void lwgeom_set_geodetic(LWGEOM *geom, int value)
Set the FLAGS geodetic bit on geometry an all sub-geometries and pointlists.
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.
void lwgeom_free(LWGEOM *geom)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
void spheroid_init(SPHEROID *s, double a, double b)
Initialize a spheroid object for use in geodetic functions.
double lwgeom_length_spheroid(const LWGEOM *geom, const SPHEROID *s)
Calculate the geodetic length of a lwgeom on the unit sphere.
#define LW_TRUE
Return types for functions with status returns.
This library is the generic geometry handling section of PostGIS.
Datum LWGEOM_distance_ellipsoid(PG_FUNCTION_ARGS)
double distance_ellipse_calculation(double lat1, double long1, double lat2, double long2, SPHEROID *sphere)
double mu2(double azimuth, SPHEROID *sphere)
double distance_sphere_method(double lat1, double long1, double lat2, double long2, SPHEROID *sphere)
Datum LWGEOM_distance_sphere(PG_FUNCTION_ARGS)
Datum LWGEOM_length_ellipsoid_linestring(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(ellipsoid_in)
double distance_ellipse(double lat1, double long1, double lat2, double long2, SPHEROID *sphere)
Datum ellipsoid_in(PG_FUNCTION_ARGS)
Datum ellipsoid_out(PG_FUNCTION_ARGS)
Datum geometry_distance_spheroid(PG_FUNCTION_ARGS)
Datum LWGEOM_length2d_ellipsoid(PG_FUNCTION_ARGS)
double deltaLongitude(double azimuth, double sigma, double tsm, SPHEROID *sphere)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
static double distance(double x1, double y1, double x2, double y2)