]> granicus.if.org Git - postgresql/blob - contrib/earthdistance/earthdistance--1.0.sql
Throw a useful error message if an extension script file is fed to psql.
[postgresql] / contrib / earthdistance / earthdistance--1.0.sql
1 /* contrib/earthdistance/earthdistance--1.0.sql */
2
3 -- complain if script is sourced in psql, rather than via CREATE EXTENSION
4 \echo Use "CREATE EXTENSION earthdistance" to load this file. \quit
5
6 -- earth() returns the radius of the earth in meters. This is the only
7 -- place you need to change things for the cube base distance functions
8 -- in order to use different units (or a better value for the Earth's radius).
9
10 CREATE FUNCTION earth() RETURNS float8
11 LANGUAGE SQL IMMUTABLE
12 AS 'SELECT ''6378168''::float8';
13
14 -- Astromers may want to change the earth function so that distances will be
15 -- returned in degrees. To do this comment out the above definition and
16 -- uncomment the one below. Note that doing this will break the regression
17 -- tests.
18 --
19 -- CREATE FUNCTION earth() RETURNS float8
20 -- LANGUAGE SQL IMMUTABLE
21 -- AS 'SELECT 180/pi()';
22
23 -- Define domain for locations on the surface of the earth using a cube
24 -- datatype with constraints. cube provides 3D indexing.
25 -- The cube is restricted to be a point, no more than 3 dimensions
26 -- (for less than 3 dimensions 0 is assumed for the missing coordinates)
27 -- and that the point must be very near the surface of the sphere
28 -- centered about the origin with the radius of the earth.
29
30 CREATE DOMAIN earth AS cube
31   CONSTRAINT not_point check(cube_is_point(value))
32   CONSTRAINT not_3d check(cube_dim(value) <= 3)
33   CONSTRAINT on_surface check(abs(cube_distance(value, '(0)'::cube) /
34   earth() - 1) < '10e-7'::float8);
35
36 CREATE FUNCTION sec_to_gc(float8)
37 RETURNS float8
38 LANGUAGE SQL
39 IMMUTABLE STRICT
40 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';
41
42 CREATE FUNCTION gc_to_sec(float8)
43 RETURNS float8
44 LANGUAGE SQL
45 IMMUTABLE STRICT
46 AS 'SELECT CASE WHEN $1 < 0 THEN 0::float8 WHEN $1/earth() > pi() THEN 2*earth() ELSE 2*earth()*sin($1/(2*earth())) END';
47
48 CREATE FUNCTION ll_to_earth(float8, float8)
49 RETURNS earth
50 LANGUAGE SQL
51 IMMUTABLE STRICT
52 AS 'SELECT cube(cube(cube(earth()*cos(radians($1))*cos(radians($2))),earth()*cos(radians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth';
53
54 CREATE FUNCTION latitude(earth)
55 RETURNS float8
56 LANGUAGE SQL
57 IMMUTABLE STRICT
58 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';
59
60 CREATE FUNCTION longitude(earth)
61 RETURNS float8
62 LANGUAGE SQL
63 IMMUTABLE STRICT
64 AS 'SELECT degrees(atan2(cube_ll_coord($1, 2), cube_ll_coord($1, 1)))';
65
66 CREATE FUNCTION earth_distance(earth, earth)
67 RETURNS float8
68 LANGUAGE SQL
69 IMMUTABLE STRICT
70 AS 'SELECT sec_to_gc(cube_distance($1, $2))';
71
72 CREATE FUNCTION earth_box(earth, float8)
73 RETURNS cube
74 LANGUAGE SQL
75 IMMUTABLE STRICT
76 AS 'SELECT cube_enlarge($1, gc_to_sec($2), 3)';
77
78 --------------- geo_distance
79
80 CREATE FUNCTION geo_distance (point, point)
81 RETURNS float8
82 LANGUAGE C IMMUTABLE STRICT AS 'MODULE_PATHNAME';
83
84 --------------- geo_distance as operator <@>
85
86 CREATE OPERATOR <@> (
87   LEFTARG = point,
88   RIGHTARG = point,
89   PROCEDURE = geo_distance,
90   COMMUTATOR = <@>
91 );