summaryrefslogtreecommitdiffstats
path: root/contrib/earthdistance/earthdistance--1.1.sql
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/earthdistance/earthdistance--1.1.sql')
-rw-r--r--contrib/earthdistance/earthdistance--1.1.sql98
1 files changed, 98 insertions, 0 deletions
diff --git a/contrib/earthdistance/earthdistance--1.1.sql b/contrib/earthdistance/earthdistance--1.1.sql
new file mode 100644
index 0000000..9ef20ab
--- /dev/null
+++ b/contrib/earthdistance/earthdistance--1.1.sql
@@ -0,0 +1,98 @@
+/* contrib/earthdistance/earthdistance--1.1.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION earthdistance" to load this file. \quit
+
+-- 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 FUNCTION earth() RETURNS float8
+LANGUAGE SQL IMMUTABLE PARALLEL SAFE
+AS 'SELECT ''6378168''::float8';
+
+-- Astronomers 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 FUNCTION earth() RETURNS float8
+-- LANGUAGE SQL IMMUTABLE
+-- AS 'SELECT 180/pi()';
+
+-- Define domain for locations on the surface of the earth using a cube
+-- datatype with constraints. cube provides 3D indexing.
+-- 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.
+
+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'::float8) < '10e-7'::float8);
+
+CREATE FUNCTION sec_to_gc(float8)
+RETURNS float8
+LANGUAGE SQL
+IMMUTABLE STRICT
+PARALLEL SAFE
+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 FUNCTION gc_to_sec(float8)
+RETURNS float8
+LANGUAGE SQL
+IMMUTABLE STRICT
+PARALLEL SAFE
+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 FUNCTION ll_to_earth(float8, float8)
+RETURNS earth
+LANGUAGE SQL
+IMMUTABLE STRICT
+PARALLEL SAFE
+AS 'SELECT cube(cube(cube(earth()*cos(radians($1))*cos(radians($2))),earth()*cos(radians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth';
+
+CREATE FUNCTION latitude(earth)
+RETURNS float8
+LANGUAGE SQL
+IMMUTABLE STRICT
+PARALLEL SAFE
+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 FUNCTION longitude(earth)
+RETURNS float8
+LANGUAGE SQL
+IMMUTABLE STRICT
+PARALLEL SAFE
+AS 'SELECT degrees(atan2(cube_ll_coord($1, 2), cube_ll_coord($1, 1)))';
+
+CREATE FUNCTION earth_distance(earth, earth)
+RETURNS float8
+LANGUAGE SQL
+IMMUTABLE STRICT
+PARALLEL SAFE
+AS 'SELECT sec_to_gc(cube_distance($1, $2))';
+
+CREATE FUNCTION earth_box(earth, float8)
+RETURNS cube
+LANGUAGE SQL
+IMMUTABLE STRICT
+PARALLEL SAFE
+AS 'SELECT cube_enlarge($1, gc_to_sec($2), 3)';
+
+--------------- geo_distance
+
+CREATE FUNCTION geo_distance (point, point)
+RETURNS float8
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE AS 'MODULE_PATHNAME';
+
+--------------- geo_distance as operator <@>
+
+CREATE OPERATOR <@> (
+ LEFTARG = point,
+ RIGHTARG = point,
+ PROCEDURE = geo_distance,
+ COMMUTATOR = <@>
+);