* @param r - location of first point.
* @param spheroid - spheroid definition.
* @param distance - distance, in units of the spheroid def'n.
-* @param azimuth - azimuth in degrees.
+* @param azimuth - azimuth in radians.
* @return s - location of projected point.
*
*/
{
GEOGRAPHIC_POINT geo_source, geo_dest;
POINT4D pt_dest;
- double azimuth_radians;
double x, y;
POINTARRAY *pa;
LWPOINT *lwp;
/* Check the azimuth validity, convert to radians */
- if ( azimuth < -360.0 || azimuth > 360.0 )
+ if ( azimuth < -2.0 * M_PI || azimuth > 2.0 * M_PI )
{
- lwerror("Azimuth must be between -360 and 360");
+ lwerror("Azimuth must be between -2PI and 2PI");
return NULL;
}
- azimuth_radians = deg2rad(azimuth);
/* Check the distance validity */
if ( distance < 0.0 || distance > (M_PI * spheroid->radius) )
geographic_point_init(x, y, &geo_source);
/* Try the projection */
- if( spheroid_project(&geo_source, spheroid, distance, azimuth_radians, &geo_dest) == LW_FAILURE )
+ if( spheroid_project(&geo_source, spheroid, distance, azimuth, &geo_dest) == LW_FAILURE )
{
LWDEBUGF(3, "Unable to project from (%g %g) with azimuth %g and distance %g", x, y, azimuth, distance);
lwerror("Unable to project from (%g %g) with azimuth %g and distance %g", x, y, azimuth, distance);
/* Build the output LWPOINT */
pa = ptarray_construct(0, 0, 1);
- pt_dest.x = rad2deg(geo_dest.lon);
- pt_dest.y = rad2deg(geo_dest.lat);
+ pt_dest.x = rad2deg(longitude_radians_normalize(geo_dest.lon));
+ pt_dest.y = rad2deg(latitude_radians_normalize(geo_dest.lat));
pt_dest.z = pt_dest.m = 0.0;
ptarray_set_point4d(pa, 0, &pt_dest);
lwp = lwpoint_construct(r->srid, NULL, pa);
+ lwgeom_set_geodetic(lwpoint_as_lwgeom(lwp), LW_TRUE);
return lwp;
}
/**
-* Calculate a projected point given a source point, a distance and a bearing.
+* Calculate a bearing (azimuth) given a source and destination point.
* @param r - location of first point.
+* @param s - location of second point.
* @param spheroid - spheroid definition.
-* @param distance - distance, in units of the spheroid def'n.
-* @param azimuth - azimuth in degrees.
-* @return s - location of projected point.
+* @param azimuth - azimuth in radians.
+* @return
*
*/
double lwgeom_azumith_spheroid(const LWPOINT *r, const LWPOINT *s, const SPHEROID *spheroid)
y2 = lwpoint_get_y(s);
geographic_point_init(x2, y2, &g2);
+ /* Same point, return a standard azimuth instead of NULL or NaN */
+ if ( FP_EQUALS(x1, x2) && FP_EQUALS(y1, y2) )
+ {
+ return 0.0;
+ }
+
/* Do the direction calculation */
- return rad2deg(spheroid_direction(&g1, &g2, spheroid));
+ return spheroid_direction(&g1, &g2, spheroid);
}
/**
/*
** geography_project(GSERIALIZED *g, distance, azimuth)
** returns point of projection given start point,
-** azimuth (bearing) and distance
+** azimuth in radians (bearing) and distance in meters
*/
PG_FUNCTION_INFO_V1(geography_project);
Datum geography_project(PG_FUNCTION_ARGS)
}
/* Read the other parameters */
- distance = PG_GETARG_FLOAT8(1);
- azimuth = PG_GETARG_FLOAT8(2);
+ distance = PG_GETARG_FLOAT8(1); /* Meters */
+ azimuth = PG_GETARG_FLOAT8(2); /* Radians */
/* Initialize spheroid */
spheroid_init(&s, WGS84_MAJOR_AXIS, WGS84_MINOR_AXIS);
/* Calculate the direction */
azimuth = lwgeom_azumith_spheroid(lwgeom_as_lwpoint(lwgeom1), lwgeom_as_lwpoint(lwgeom2), &s);
- /* Clean up, but not all the way to the point arrays */
+ /* Clean up */
lwgeom_free(lwgeom1);
lwgeom_free(lwgeom2);
-- #1385
SELECT '#1385', ST_Extent(g) FROM ( select null::geometry as g ) as foo;
+-- #657
+SELECT '#657.1',Round(ST_X(ST_Project('POINT(175 10)'::geography, 2000000, 3.1415/2)::GEOMETRY)::numeric,2);
+SELECT '#657.2',Round(ST_Distance(ST_Project('POINT(10 10)'::geography, 10, 0), 'POINT(10 10)'::geography)::numeric,2);
+SELECT '#657.3',ST_DWithin(ST_Project('POINT(10 10)'::geography, 2000, pi()/2), 'POINT(10 10)'::geography, 2000);
+
+-- #1305
+SELECT '#1305.1',ST_AsText(ST_Project('POINT(10 10)'::geography, 0, 0));
+WITH pts AS ( SELECT 'POINT(0 45)'::geography AS s, 'POINT(45 45)'::geography AS e )
+SELECT '#1305.2',abs(ST_Distance(e, ST_Project(s, ST_Distance(s, e), ST_Azimuth(s, e)))) < 0.001 FROM pts;
+
-- Clean up
DELETE FROM spatial_ref_sys;