2007-11-13 12:24:29 +08:00
/* $PostgreSQL: pgsql / contrib / earthdistance / earthdistance.sql.in,v 1.11 2007 / 11 / 13 04:24:27 momjian Exp $ */
2002-10-19 02:41:22 +08:00
-- Adjust this setting to control where the objects get created.
SET search_path = public ;
2002-11-09 04:20:22 +08:00
-- The earth functions rely on contrib/cube having been installed and loaded.
-- earth() returns the radius of the earth in meters. This is the only
-- place you need to change things for the cube base distance functions
-- in order to use different units (or a better value for the Earth's radius).
CREATE OR REPLACE FUNCTION earth ( ) RETURNS float8
2006-02-28 00:09:50 +08:00
LANGUAGE SQL IMMUTABLE
2006-03-08 11:51:52 +08:00
AS ' SELECT '' 6378168 '' ::float8 ' ;
2002-11-09 04:20:22 +08:00
-- Astromers may want to change the earth function so that distances will be
-- returned in degrees. To do this comment out the above definition and
-- uncomment the one below. Note that doing this will break the regression
-- tests.
--
-- CREATE OR REPLACE FUNCTION earth() RETURNS float8
2006-02-28 00:09:50 +08:00
-- LANGUAGE SQL IMMUTABLE
2002-11-09 04:20:22 +08:00
-- AS 'SELECT 180/pi()';
-- Define domain for locations on the surface of the earth using a cube
-- datatype with constraints. cube provides 3D indexing.
2003-02-13 13:31:06 +08:00
-- The cube is restricted to be a point, no more than 3 dimensions
-- (for less than 3 dimensions 0 is assumed for the missing coordinates)
-- and that the point must be very near the surface of the sphere
-- centered about the origin with the radius of the earth.
2002-11-09 04:20:22 +08:00
2003-02-13 13:31:06 +08:00
CREATE DOMAIN earth AS cube
CONSTRAINT not_point check ( cube_is_point ( value ) )
CONSTRAINT not_3d check ( cube_dim ( value ) < = 3 )
CONSTRAINT on_surface check ( abs ( cube_distance ( value , ' (0) ' : : cube ) /
earth ( ) - 1 ) < ' 10e-7 ' : : float8 ) ;
2002-11-09 04:20:22 +08:00
CREATE OR REPLACE FUNCTION sec_to_gc ( float8 )
RETURNS float8
2006-02-28 00:09:50 +08:00
LANGUAGE SQL
2002-11-09 04:20:22 +08:00
IMMUTABLE STRICT
AS ' SELECT CASE WHEN $1 < 0 THEN 0::float8 WHEN $1/(2*earth()) > 1 THEN pi()*earth() ELSE 2*earth()*asin($1/(2*earth())) END ' ;
CREATE OR REPLACE FUNCTION gc_to_sec ( float8 )
RETURNS float8
2006-02-28 00:09:50 +08:00
LANGUAGE SQL
2002-11-09 04:20:22 +08:00
IMMUTABLE STRICT
AS ' SELECT CASE WHEN $1 < 0 THEN 0::float8 WHEN $1/earth() > pi() THEN 2*earth() ELSE 2*earth()*sin($1/(2*earth())) END ' ;
CREATE OR REPLACE FUNCTION ll_to_earth ( float8 , float8 )
RETURNS earth
2006-02-28 00:09:50 +08:00
LANGUAGE SQL
2002-11-09 04:20:22 +08:00
IMMUTABLE STRICT
2003-07-25 01:52:50 +08:00
AS ' SELECT cube(cube(cube(earth()*cos(radians($1))*cos(radians($2))),earth()*cos(radians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth ' ;
2002-11-09 04:20:22 +08:00
CREATE OR REPLACE FUNCTION latitude ( earth )
RETURNS float8
2006-02-28 00:09:50 +08:00
LANGUAGE SQL
2002-11-09 04:20:22 +08:00
IMMUTABLE STRICT
AS ' SELECT CASE WHEN cube_ll_coord($1, 3)/earth() < -1 THEN -90::float8 WHEN cube_ll_coord($1, 3)/earth() > 1 THEN 90::float8 ELSE degrees(asin(cube_ll_coord($1, 3)/earth())) END ' ;
CREATE OR REPLACE FUNCTION longitude ( earth )
RETURNS float8
2006-02-28 00:09:50 +08:00
LANGUAGE SQL
2002-11-09 04:20:22 +08:00
IMMUTABLE STRICT
AS ' SELECT degrees(atan2(cube_ll_coord($1, 2), cube_ll_coord($1, 1))) ' ;
CREATE OR REPLACE FUNCTION earth_distance ( earth , earth )
RETURNS float8
2006-02-28 00:09:50 +08:00
LANGUAGE SQL
2002-11-09 04:20:22 +08:00
IMMUTABLE STRICT
AS ' SELECT sec_to_gc(cube_distance($1, $2)) ' ;
CREATE OR REPLACE FUNCTION earth_box ( earth , float8 )
RETURNS cube
2006-02-28 00:09:50 +08:00
LANGUAGE SQL
2002-11-09 04:20:22 +08:00
IMMUTABLE STRICT
AS ' SELECT cube_enlarge($1, gc_to_sec($2), 3) ' ;
2000-06-16 03:05:22 +08:00
- - - - - - - - - - - - - -- geo_distance
2002-10-19 02:41:22 +08:00
CREATE OR REPLACE FUNCTION geo_distance ( point , point )
RETURNS float8
2006-02-28 00:09:50 +08:00
LANGUAGE C IMMUTABLE STRICT AS ' MODULE_PATHNAME ' ;
2000-06-16 03:05:22 +08:00
- - - - - - - - - - - - - -- geo_distance as operator <@>
CREATE OPERATOR < @ > (
2002-10-19 02:41:22 +08:00
LEFTARG = point ,
RIGHTARG = point ,
PROCEDURE = geo_distance ,
COMMUTATOR = < @ >
2000-06-16 03:05:22 +08:00
) ;