diff -c -r -N --exclude=CVS /usr/local/src/postgres-cvs/contrib/earthdistance/Makefile earthdistance/Makefile *** /usr/local/src/postgres-cvs/contrib/earthdistance/Makefile Thu Sep 6 05:49:29 2001 --- earthdistance/Makefile Mon Sep 9 18:04:38 2002 *************** *** 1,4 **** ! # $Header: /projects/cvsroot/contrib/earthdistance/Makefile,v 1.11 2001/09/06 10:49:29 petere Exp $ subdir = contrib/earthdistance top_builddir = ../.. --- 1,4 ---- ! # $Header: /cvsroot/contrib/earthdistance/Makefile,v 1.11 2001/09/06 10:49:29 petere Exp $ subdir = contrib/earthdistance top_builddir = ../.. *************** *** 7,11 **** --- 7,12 ---- MODULES = earthdistance DATA_built = earthdistance.sql DOCS = README.earthdistance + REGRESS = earthdistance include $(top_srcdir)/contrib/contrib-global.mk diff -c -r -N --exclude=CVS /usr/local/src/postgres-cvs/contrib/earthdistance/README.earthdistance earthdistance/README.earthdistance *** /usr/local/src/postgres-cvs/contrib/earthdistance/README.earthdistance Mon Jun 19 09:01:20 2000 --- earthdistance/README.earthdistance Tue Sep 10 08:47:45 2002 *************** *** 1,3 **** --- 1,103 ---- + This contrib package contains two different approaches to calculating + great circle distances on the surface of the Earth. The one described + first depends on the contrib/cube package (which MUST be installed before + earthdistance is installed). The second one is based on the point + datatype using latitude and longitude for the coordinates. The install + script makes the defined functions executable by anyone. + + Make sure contrib/cube has been installed. + make + make install + make installcheck + + To use these functions in a particular database as a postgres superuser do: + psql databasename < earthdistance.sql + + ------------------------------------------- + contrib/cube based Earth distance functions + Bruno Wolff III + September 2002 + + A spherical model of the Earth is used. + + Data is stored in cubes that are points (both corners are the same) using 3 + coordinates representing the distance from the center of the Earth. + + The radius of the Earth is obtained from the earth() function. It is + given in meters. But by changing this one function you can change it + to use some other units or to use a different value of the radius + that you feel is more appropiate. + + This package also has applications to astronomical databases as well. + Astronomers will probably want to change earth() to return a radius of + 180/pi() so that distances are in degrees. + + Functions are provided to allow for input in latitude and longitude (in + degrees), to allow for output of latitude and longitude, to calculate + the great circle distance between two points and to easily specify a + bounding box usable for index searches. + + The functions are all 'sql' functions. If you want to make these functions + executable by other people you will also have to make the referenced + cube functions executable. cube(text), cube_distance(cube,cube), + cube_ll_coord(cube,int) and cube_enlarge(cube,float8,int) are used indirectly + by the earth distance functions. is_point(cube) and cube_dim(cube) are used + in suggested constraints for data in domain earth. cube_ur_coord(cube,int) + is used in the regression tests and might be useful for looking at bounding + box coordinates in user applications. + + A domain of type cube named earth is defined. Since check constraints + are not supported for domains yet, this isn't as useful as it might be. + However the checks that should be supplied to all data of type earth are: + + constraint not_point check(is_point(earth)) + constraint not_3d check(cube_dim(earth) <= 3) + constraint on_surface check(abs(cube_distance(earth, '(0)'::cube) / + earth() - 1) < '10e-12'::float8); + + The following functions are provided: + + earth() - Returns the radius of the earth in meters. + + sec_to_gc(float8) - Converts the normal straight line (secant) distance between + between two points on the surface of the Earth to the great circle distance + between them. + + gc_to_sec(float8) - Converts the great circle distance between two points + on the surface of the Earth to the normal straight line (secant) distance + between them. + + ll_to_cube(float8, float8) - Returns the location of a point on the surface of + the Earth given its latitude (argument 1) and longitude (argument 2) in degrees. + + latitude(earth) - Returns the latitude in degrees of a point on the surface + of the Earth. + + longitude(earth) - Returns the longitude in degrees of a point on the surface + of the Earth. + + earth_distance(earth, earth) - Returns the great circle distance between + two points on the surface of the Earth. + + earth_box(earth, float8) - Returns a box suitable for an indexed search using + the cube @ operator for points within a given great circle distance of a + location. Some points in this box are further than the specified great circle + distance from the location so a second check using earth_distance should be + made at the same time. + + One advantage of using cube representation over a point using latitude and + longitude for coordinates, is that you don't have to worry about special + conditions at +/- 180 degrees of longitude or near the poles. + + Below is the documentation for the Earth distance operator that works + with the point data type. + --------------------------------------------------------------------- + I corrected a bug in the geo_distance code where two double constants + were declared as int. I also changed the distance function to use + the haversine formula which is more accurate for small distances. + Bruno Wolff + September 2002 + --------------------------------------------------------------------- Date: Wed, 1 Apr 1998 15:19:32 -0600 (CST) From: Hal Snyder To: vmehr@ctp.com diff -c -r -N --exclude=CVS /usr/local/src/postgres-cvs/contrib/earthdistance/earthdistance.c earthdistance/earthdistance.c *** /usr/local/src/postgres-cvs/contrib/earthdistance/earthdistance.c Wed Mar 21 21:59:09 2001 --- earthdistance/earthdistance.c Mon Sep 9 18:04:38 2002 *************** *** 6,13 **** /* Earth's radius is in statute miles. */ ! const int EARTH_RADIUS = 3958.747716; ! const int TWO_PI = 2.0 * M_PI; double *geo_distance(Point *pt1, Point *pt2); --- 6,13 ---- /* Earth's radius is in statute miles. */ ! const double EARTH_RADIUS = 3958.747716; ! const double TWO_PI = 2.0 * M_PI; double *geo_distance(Point *pt1, Point *pt2); *************** *** 50,55 **** --- 50,56 ---- long2, lat2; double longdiff; + double sino; double *resultp = palloc(sizeof(double)); /* convert degrees to radians */ *************** *** 65,72 **** if (longdiff > M_PI) longdiff = TWO_PI - longdiff; ! *resultp = EARTH_RADIUS * acos ! (sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(longdiff)); return resultp; } --- 66,75 ---- if (longdiff > M_PI) longdiff = TWO_PI - longdiff; ! sino = sqrt(sin(fabs(lat1-lat2)/2.)*sin(fabs(lat1-lat2)/2.) + ! cos(lat1) * cos(lat2) * sin(longdiff/2.)*sin(longdiff/2.)); ! if (sino > 1.) sino = 1.; ! *resultp = 2. * EARTH_RADIUS * asin(sino); return resultp; } diff -c -r -N --exclude=CVS /usr/local/src/postgres-cvs/contrib/earthdistance/earthdistance.sql.in earthdistance/earthdistance.sql.in *** /usr/local/src/postgres-cvs/contrib/earthdistance/earthdistance.sql.in Thu Aug 16 17:24:43 2001 --- earthdistance/earthdistance.sql.in Thu Sep 12 08:03:06 2002 *************** *** 1,16 **** ! --------------- geo_distance ! DROP FUNCTION geo_distance (point, point); ! CREATE FUNCTION geo_distance (point, point) RETURNS float8 ! AS 'MODULE_PATHNAME' LANGUAGE 'c' ! WITH (isstrict); ! SELECT geo_distance ('(1,2)'::point, '(3,4)'::point); --------------- geo_distance as operator <@> - DROP OPERATOR <@> (point, point); CREATE OPERATOR <@> ( leftarg = point, rightarg = point, --- 1,67 ---- + begin; ! -- 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 language 'sql' immutable as ! 'select \'6378168\'::float8'; ! ! -- 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 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. ! -- Check constraints aren't currently supported. ! ! create domain earth as cube; ! -- constraint not_point check(is_point(earth)) ! -- constraint not_3d check(cube_dim(earth) <= 3) ! -- constraint on_surface check(abs(cube_distance(earth, '(0)'::cube) / ! -- earth() - 1) < '10e-12'::float8); ! ! create or replace function sec_to_gc(float8) returns float8 language 'sql' ! 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 language 'sql' ! 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 language 'sql' ! immutable strict as ! 'select cube(\'(\'||earth()*cos(radians($1))*cos(radians($2))||\',\'||earth()*cos(radians($1))*sin(radians($2))||\',\'||earth()*sin(radians($1))||\')\')'; ! ! create or replace function latitude(earth) returns float8 language 'sql' ! 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 language 'sql' ! 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 language 'sql' ! immutable strict as ! 'select sec_to_gc(cube_distance($1, $2))'; ! ! create or replace function earth_box(earth, float8) returns cube language 'sql' ! immutable strict as ! 'select cube_enlarge($1, gc_to_sec($2), 3)'; ! --------------- geo_distance ! CREATE OR REPLACE FUNCTION geo_distance (point, point) RETURNS float8 ! LANGUAGE 'c' IMMUTABLE STRICT AS 'MODULE_PATHNAME'; --------------- geo_distance as operator <@> CREATE OPERATOR <@> ( leftarg = point, rightarg = point, *************** *** 18,24 **** commutator = <@> ); ! -- ( 87.6, 41.8) is in Chicago ! -- (106.7, 35.1) is in Albuquerque ! -- The cities are about 1100 miles apart ! SELECT '(87.6,41.8)'::point <@> '(106.7,35.1)'::point; --- 69,89 ---- commutator = <@> ); ! -- ! -- By default these functions are made executable by anyone. To restrict ! -- their access, comment out the following grant commands. Also note ! -- that some of these functions refer to functions in contrib/cube ! -- and execute access to those referenced functions to use the functions ! -- defined here. ! -- ! ! grant execute on function earth() to public; ! grant execute on function sec_to_gc(float8) to public; ! grant execute on function gc_to_sec(float8) to public; ! grant execute on function ll_to_earth(float8, float8) to public; ! grant execute on function latitude(earth) to public; ! grant execute on function longitude(earth) to public; ! grant execute on function earth_distance(earth, earth) to public; ! grant execute on function earth_box(earth, float8) to public; ! ! commit; diff -c -r -N --exclude=CVS /usr/local/src/postgres-cvs/contrib/earthdistance/expected/earthdistance.out earthdistance/expected/earthdistance.out *** /usr/local/src/postgres-cvs/contrib/earthdistance/expected/earthdistance.out Wed Dec 31 18:00:00 1969 --- earthdistance/expected/earthdistance.out Mon Sep 9 18:04:38 2002 *************** *** 0 **** --- 1,948 ---- + -- + -- Test earth distance functions + -- + -- + -- first, define the datatype. Turn off echoing so that expected file + -- does not depend on contents of earthdistance.sql or cube.sql. + -- + \set ECHO none + psql:../cube/cube.sql:11: WARNING: ProcedureCreate: type cube is not yet defined + psql:../cube/cube.sql:16: WARNING: Argument type "cube" is only a shell + -- + -- The radius of the Earth we are using. + -- + select earth()::numeric(20,5); + earth + --------------- + 6378168.00000 + (1 row) + + -- + -- Convert straight line distances to great circle distances. + -- + select (pi()*earth())::numeric(20,5); + numeric + ---------------- + 20037605.73216 + (1 row) + + select sec_to_gc(0)::numeric(20,5); + sec_to_gc + ----------- + 0.00000 + (1 row) + + select sec_to_gc(2*earth())::numeric(20,5); + sec_to_gc + ---------------- + 20037605.73216 + (1 row) + + select sec_to_gc(10*earth())::numeric(20,5); + sec_to_gc + ---------------- + 20037605.73216 + (1 row) + + select sec_to_gc(-earth())::numeric(20,5); + sec_to_gc + ----------- + 0.00000 + (1 row) + + select sec_to_gc(1000)::numeric(20,5); + sec_to_gc + ------------ + 1000.00000 + (1 row) + + select sec_to_gc(10000)::numeric(20,5); + sec_to_gc + ------------- + 10000.00102 + (1 row) + + select sec_to_gc(100000)::numeric(20,5); + sec_to_gc + -------------- + 100001.02426 + (1 row) + + select sec_to_gc(1000000)::numeric(20,5); + sec_to_gc + --------------- + 1001027.07131 + (1 row) + + -- + -- Convert great circle distances to straight line distances. + -- + select gc_to_sec(0)::numeric(20,5); + gc_to_sec + ----------- + 0.00000 + (1 row) + + select gc_to_sec(sec_to_gc(2*earth()))::numeric(20,5); + gc_to_sec + ---------------- + 12756336.00000 + (1 row) + + select gc_to_sec(10*earth())::numeric(20,5); + gc_to_sec + ---------------- + 12756336.00000 + (1 row) + + select gc_to_sec(pi()*earth())::numeric(20,5); + gc_to_sec + ---------------- + 12756336.00000 + (1 row) + + select gc_to_sec(-1000)::numeric(20,5); + gc_to_sec + ----------- + 0.00000 + (1 row) + + select gc_to_sec(1000)::numeric(20,5); + gc_to_sec + ------------ + 1000.00000 + (1 row) + + select gc_to_sec(10000)::numeric(20,5); + gc_to_sec + ------------ + 9999.99898 + (1 row) + + select gc_to_sec(100000)::numeric(20,5); + gc_to_sec + ------------- + 99998.97577 + (1 row) + + select gc_to_sec(1000000)::numeric(20,5); + gc_to_sec + -------------- + 998976.08618 + (1 row) + + -- + -- Set coordinates using latitude and longitude. + -- Extract each coordinate separately so we can round them. + -- + select cube_ll_coord(ll_to_earth(0,0),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,0),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,0),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord + ---------------+---------------+--------------- + 6378168.00000 | 0.00000 | 0.00000 + (1 row) + + select cube_ll_coord(ll_to_earth(360,360),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(360,360),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(360,360),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord + ---------------+---------------+--------------- + 6378168.00000 | 0.00000 | 0.00000 + (1 row) + + select cube_ll_coord(ll_to_earth(180,180),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(180,180),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(180,180),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord + ---------------+---------------+--------------- + 6378168.00000 | 0.00000 | 0.00000 + (1 row) + + select cube_ll_coord(ll_to_earth(180,360),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(180,360),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(180,360),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord + ----------------+---------------+--------------- + -6378168.00000 | 0.00000 | 0.00000 + (1 row) + + select cube_ll_coord(ll_to_earth(-180,-360),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(-180,-360),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(-180,-360),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord + ----------------+---------------+--------------- + -6378168.00000 | 0.00000 | 0.00000 + (1 row) + + select cube_ll_coord(ll_to_earth(0,180),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,180),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,180),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord + ----------------+---------------+--------------- + -6378168.00000 | 0.00000 | 0.00000 + (1 row) + + select cube_ll_coord(ll_to_earth(0,-180),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,-180),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,-180),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord + ----------------+---------------+--------------- + -6378168.00000 | 0.00000 | 0.00000 + (1 row) + + select cube_ll_coord(ll_to_earth(90,0),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(90,0),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(90,0),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord + ---------------+---------------+--------------- + 0.00000 | 0.00000 | 6378168.00000 + (1 row) + + select cube_ll_coord(ll_to_earth(90,180),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(90,180),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(90,180),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord + ---------------+---------------+--------------- + 0.00000 | 0.00000 | 6378168.00000 + (1 row) + + select cube_ll_coord(ll_to_earth(-90,0),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(-90,0),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(-90,0),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord + ---------------+---------------+---------------- + 0.00000 | 0.00000 | -6378168.00000 + (1 row) + + select cube_ll_coord(ll_to_earth(-90,180),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(-90,180),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(-90,180),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord + ---------------+---------------+---------------- + 0.00000 | 0.00000 | -6378168.00000 + (1 row) + + -- + -- Test getting the latitude of a location. + -- + select latitude(ll_to_earth(0,0))::numeric(20,10); + latitude + -------------- + 0.0000000000 + (1 row) + + select latitude(ll_to_earth(45,0))::numeric(20,10); + latitude + --------------- + 45.0000000000 + (1 row) + + select latitude(ll_to_earth(90,0))::numeric(20,10); + latitude + --------------- + 90.0000000000 + (1 row) + + select latitude(ll_to_earth(-45,0))::numeric(20,10); + latitude + ---------------- + -45.0000000000 + (1 row) + + select latitude(ll_to_earth(-90,0))::numeric(20,10); + latitude + ---------------- + -90.0000000000 + (1 row) + + select latitude(ll_to_earth(0,90))::numeric(20,10); + latitude + -------------- + 0.0000000000 + (1 row) + + select latitude(ll_to_earth(45,90))::numeric(20,10); + latitude + --------------- + 45.0000000000 + (1 row) + + select latitude(ll_to_earth(90,90))::numeric(20,10); + latitude + --------------- + 90.0000000000 + (1 row) + + select latitude(ll_to_earth(-45,90))::numeric(20,10); + latitude + ---------------- + -45.0000000000 + (1 row) + + select latitude(ll_to_earth(-90,90))::numeric(20,10); + latitude + ---------------- + -90.0000000000 + (1 row) + + select latitude(ll_to_earth(0,180))::numeric(20,10); + latitude + -------------- + 0.0000000000 + (1 row) + + select latitude(ll_to_earth(45,180))::numeric(20,10); + latitude + --------------- + 45.0000000000 + (1 row) + + select latitude(ll_to_earth(90,180))::numeric(20,10); + latitude + --------------- + 90.0000000000 + (1 row) + + select latitude(ll_to_earth(-45,180))::numeric(20,10); + latitude + ---------------- + -45.0000000000 + (1 row) + + select latitude(ll_to_earth(-90,180))::numeric(20,10); + latitude + ---------------- + -90.0000000000 + (1 row) + + select latitude(ll_to_earth(0,-90))::numeric(20,10); + latitude + -------------- + 0.0000000000 + (1 row) + + select latitude(ll_to_earth(45,-90))::numeric(20,10); + latitude + --------------- + 45.0000000000 + (1 row) + + select latitude(ll_to_earth(90,-90))::numeric(20,10); + latitude + --------------- + 90.0000000000 + (1 row) + + select latitude(ll_to_earth(-45,-90))::numeric(20,10); + latitude + ---------------- + -45.0000000000 + (1 row) + + select latitude(ll_to_earth(-90,-90))::numeric(20,10); + latitude + ---------------- + -90.0000000000 + (1 row) + + -- + -- Test getting the longitude of a location. + -- + select longitude(ll_to_earth(0,0))::numeric(20,10); + longitude + -------------- + 0.0000000000 + (1 row) + + select longitude(ll_to_earth(45,0))::numeric(20,10); + longitude + -------------- + 0.0000000000 + (1 row) + + select longitude(ll_to_earth(90,0))::numeric(20,10); + longitude + -------------- + 0.0000000000 + (1 row) + + select longitude(ll_to_earth(-45,0))::numeric(20,10); + longitude + -------------- + 0.0000000000 + (1 row) + + select longitude(ll_to_earth(-90,0))::numeric(20,10); + longitude + -------------- + 0.0000000000 + (1 row) + + select longitude(ll_to_earth(0,90))::numeric(20,10); + longitude + --------------- + 90.0000000000 + (1 row) + + select longitude(ll_to_earth(45,90))::numeric(20,10); + longitude + --------------- + 90.0000000000 + (1 row) + + select longitude(ll_to_earth(90,90))::numeric(20,10); + longitude + --------------- + 90.0000000000 + (1 row) + + select longitude(ll_to_earth(-45,90))::numeric(20,10); + longitude + --------------- + 90.0000000000 + (1 row) + + select longitude(ll_to_earth(-90,90))::numeric(20,10); + longitude + --------------- + 90.0000000000 + (1 row) + + select longitude(ll_to_earth(0,180))::numeric(20,10); + longitude + ---------------- + 180.0000000000 + (1 row) + + select longitude(ll_to_earth(45,180))::numeric(20,10); + longitude + ---------------- + 180.0000000000 + (1 row) + + select longitude(ll_to_earth(90,180))::numeric(20,10); + longitude + ---------------- + 180.0000000000 + (1 row) + + select longitude(ll_to_earth(-45,180))::numeric(20,10); + longitude + ---------------- + 180.0000000000 + (1 row) + + select longitude(ll_to_earth(-90,180))::numeric(20,10); + longitude + ---------------- + 180.0000000000 + (1 row) + + select longitude(ll_to_earth(0,-90))::numeric(20,10); + longitude + ---------------- + -90.0000000000 + (1 row) + + select longitude(ll_to_earth(45,-90))::numeric(20,10); + longitude + ---------------- + -90.0000000000 + (1 row) + + select longitude(ll_to_earth(90,-90))::numeric(20,10); + longitude + ---------------- + -90.0000000000 + (1 row) + + select longitude(ll_to_earth(-45,-90))::numeric(20,10); + longitude + ---------------- + -90.0000000000 + (1 row) + + select longitude(ll_to_earth(-90,-90))::numeric(20,10); + longitude + ---------------- + -90.0000000000 + (1 row) + + -- + -- For the distance tests the following is some real life data. + -- + -- Chicago has a latitude of 41.8 and a longitude of 87.6. + -- Albuquerque has a latitude of 35.1 and a longitude of 106.7. + -- (Note that latitude and longitude are specified differently + -- in the cube based functions than for the point based functions.) + -- + -- + -- Test getting the distance between two points using earth_distance. + -- + select earth_distance(ll_to_earth(0,0),ll_to_earth(0,0))::numeric(20,5); + earth_distance + ---------------- + 0.00000 + (1 row) + + select earth_distance(ll_to_earth(0,0),ll_to_earth(0,180))::numeric(20,5); + earth_distance + ---------------- + 20037605.73216 + (1 row) + + select earth_distance(ll_to_earth(0,0),ll_to_earth(90,0))::numeric(20,5); + earth_distance + ---------------- + 10018802.86608 + (1 row) + + select earth_distance(ll_to_earth(0,0),ll_to_earth(0,90))::numeric(20,5); + earth_distance + ---------------- + 10018802.86608 + (1 row) + + select earth_distance(ll_to_earth(0,0),ll_to_earth(0,1))::numeric(20,5); + earth_distance + ---------------- + 111320.03185 + (1 row) + + select earth_distance(ll_to_earth(0,0),ll_to_earth(1,0))::numeric(20,5); + earth_distance + ---------------- + 111320.03185 + (1 row) + + select earth_distance(ll_to_earth(30,0),ll_to_earth(30,1))::numeric(20,5); + earth_distance + ---------------- + 96405.66962 + (1 row) + + select earth_distance(ll_to_earth(30,0),ll_to_earth(31,0))::numeric(20,5); + earth_distance + ---------------- + 111320.03185 + (1 row) + + select earth_distance(ll_to_earth(60,0),ll_to_earth(60,1))::numeric(20,5); + earth_distance + ---------------- + 55659.48608 + (1 row) + + select earth_distance(ll_to_earth(60,0),ll_to_earth(61,0))::numeric(20,5); + earth_distance + ---------------- + 111320.03185 + (1 row) + + select earth_distance(ll_to_earth(41.8,87.6),ll_to_earth(35.1,106.7))::numeric(20,5); + earth_distance + ---------------- + 1819303.21265 + (1 row) + + select (earth_distance(ll_to_earth(41.8,87.6),ll_to_earth(35.1,106.7))* + 100./2.54/12./5280.)::numeric(20,5); + numeric + ------------ + 1130.46261 + (1 row) + + -- + -- Test getting the distance between two points using geo_distance. + -- + select geo_distance('(0,0)'::point,'(0,0)'::point)::numeric(20,5); + geo_distance + -------------- + 0.00000 + (1 row) + + select geo_distance('(0,0)'::point,'(180,0)'::point)::numeric(20,5); + geo_distance + -------------- + 12436.77274 + (1 row) + + select geo_distance('(0,0)'::point,'(0,90)'::point)::numeric(20,5); + geo_distance + -------------- + 6218.38637 + (1 row) + + select geo_distance('(0,0)'::point,'(90,0)'::point)::numeric(20,5); + geo_distance + -------------- + 6218.38637 + (1 row) + + select geo_distance('(0,0)'::point,'(1,0)'::point)::numeric(20,5); + geo_distance + -------------- + 69.09318 + (1 row) + + select geo_distance('(0,0)'::point,'(0,1)'::point)::numeric(20,5); + geo_distance + -------------- + 69.09318 + (1 row) + + select geo_distance('(0,30)'::point,'(1,30)'::point)::numeric(20,5); + geo_distance + -------------- + 59.83626 + (1 row) + + select geo_distance('(0,30)'::point,'(0,31)'::point)::numeric(20,5); + geo_distance + -------------- + 69.09318 + (1 row) + + select geo_distance('(0,60)'::point,'(1,60)'::point)::numeric(20,5); + geo_distance + -------------- + 34.54626 + (1 row) + + select geo_distance('(0,60)'::point,'(0,61)'::point)::numeric(20,5); + geo_distance + -------------- + 69.09318 + (1 row) + + select geo_distance('(87.6,41.8)'::point,'(106.7,35.1)'::point)::numeric(20,5); + geo_distance + -------------- + 1129.18983 + (1 row) + + select (geo_distance('(87.6,41.8)'::point,'(106.7,35.1)'::point)*5280.*12.*2.54/100.)::numeric(20,5); + numeric + --------------- + 1817254.87730 + (1 row) + + -- + -- Test getting the distance between two points using the <@> operator. + -- + select ('(0,0)'::point <@> '(0,0)'::point)::numeric(20,5); + numeric + --------- + 0.00000 + (1 row) + + select ('(0,0)'::point <@> '(180,0)'::point)::numeric(20,5); + numeric + ------------- + 12436.77274 + (1 row) + + select ('(0,0)'::point <@> '(0,90)'::point)::numeric(20,5); + numeric + ------------ + 6218.38637 + (1 row) + + select ('(0,0)'::point <@> '(90,0)'::point)::numeric(20,5); + numeric + ------------ + 6218.38637 + (1 row) + + select ('(0,0)'::point <@> '(1,0)'::point)::numeric(20,5); + numeric + ---------- + 69.09318 + (1 row) + + select ('(0,0)'::point <@> '(0,1)'::point)::numeric(20,5); + numeric + ---------- + 69.09318 + (1 row) + + select ('(0,30)'::point <@> '(1,30)'::point)::numeric(20,5); + numeric + ---------- + 59.83626 + (1 row) + + select ('(0,30)'::point <@> '(0,31)'::point)::numeric(20,5); + numeric + ---------- + 69.09318 + (1 row) + + select ('(0,60)'::point <@> '(1,60)'::point)::numeric(20,5); + numeric + ---------- + 34.54626 + (1 row) + + select ('(0,60)'::point <@> '(0,61)'::point)::numeric(20,5); + numeric + ---------- + 69.09318 + (1 row) + + select ('(87.6,41.8)'::point <@> '(106.7,35.1)'::point)::numeric(20,5); + numeric + ------------ + 1129.18983 + (1 row) + + select (('(87.6,41.8)'::point <@> '(106.7,35.1)'::point)*5280.*12.*2.54/100.)::numeric(20,5); + numeric + --------------- + 1817254.87730 + (1 row) + + -- + -- Test getting a bounding box around points. + -- + select cube_ll_coord(earth_box(ll_to_earth(0,0),112000),1)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),112000),2)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),112000),3)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),112000),1)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),112000),2)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),112000),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord | cube_ur_coord | cube_ur_coord | cube_ur_coord + ---------------+---------------+---------------+---------------+---------------+--------------- + 6266169.43896 | -111998.56104 | -111998.56104 | 6490166.56104 | 111998.56104 | 111998.56104 + (1 row) + + select cube_ll_coord(earth_box(ll_to_earth(0,0),pi()*earth()),1)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),pi()*earth()),2)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),pi()*earth()),3)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),pi()*earth()),1)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),pi()*earth()),2)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),pi()*earth()),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord | cube_ur_coord | cube_ur_coord | cube_ur_coord + ----------------+-----------------+-----------------+----------------+----------------+---------------- + -6378168.00000 | -12756336.00000 | -12756336.00000 | 19134504.00000 | 12756336.00000 | 12756336.00000 + (1 row) + + select cube_ll_coord(earth_box(ll_to_earth(0,0),10*earth()),1)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),10*earth()),2)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),10*earth()),3)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),10*earth()),1)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),10*earth()),2)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),10*earth()),3)::numeric(20,5); + cube_ll_coord | cube_ll_coord | cube_ll_coord | cube_ur_coord | cube_ur_coord | cube_ur_coord + ----------------+-----------------+-----------------+----------------+----------------+---------------- + -6378168.00000 | -12756336.00000 | -12756336.00000 | 19134504.00000 | 12756336.00000 | 12756336.00000 + (1 row) + + -- + -- Test for points that should be in bounding boxes. + -- + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,1))*1.00001) @ + ll_to_earth(0,1); + ?column? + ---------- + t + (1 row) + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.1))*1.00001) @ + ll_to_earth(0,0.1); + ?column? + ---------- + t + (1 row) + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.01))*1.00001) @ + ll_to_earth(0,0.01); + ?column? + ---------- + t + (1 row) + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.001))*1.00001) @ + ll_to_earth(0,0.001); + ?column? + ---------- + t + (1 row) + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.0001))*1.00001) @ + ll_to_earth(0,0.0001); + ?column? + ---------- + t + (1 row) + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0.0001,0.0001))*1.00001) @ + ll_to_earth(0.0001,0.0001); + ?column? + ---------- + t + (1 row) + + select earth_box(ll_to_earth(45,45), + earth_distance(ll_to_earth(45,45),ll_to_earth(45.0001,45.0001))*1.00001) @ + ll_to_earth(45.0001,45.0001); + ?column? + ---------- + t + (1 row) + + select earth_box(ll_to_earth(90,180), + earth_distance(ll_to_earth(90,180),ll_to_earth(90.0001,180.0001))*1.00001) @ + ll_to_earth(90.0001,180.0001); + ?column? + ---------- + t + (1 row) + + -- + -- Test for points that shouldn't be in bounding boxes. Note that we need + -- to make points way outside, since some points close may be in the box + -- but further away than the distance we are testing. + -- + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,1))*.57735) @ + ll_to_earth(0,1); + ?column? + ---------- + f + (1 row) + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.1))*.57735) @ + ll_to_earth(0,0.1); + ?column? + ---------- + f + (1 row) + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.01))*.57735) @ + ll_to_earth(0,0.01); + ?column? + ---------- + f + (1 row) + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.001))*.57735) @ + ll_to_earth(0,0.001); + ?column? + ---------- + f + (1 row) + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.0001))*.57735) @ + ll_to_earth(0,0.0001); + ?column? + ---------- + f + (1 row) + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0.0001,0.0001))*.57735) @ + ll_to_earth(0.0001,0.0001); + ?column? + ---------- + f + (1 row) + + select earth_box(ll_to_earth(45,45), + earth_distance(ll_to_earth(45,45),ll_to_earth(45.0001,45.0001))*.57735) @ + ll_to_earth(45.0001,45.0001); + ?column? + ---------- + f + (1 row) + + select earth_box(ll_to_earth(90,180), + earth_distance(ll_to_earth(90,180),ll_to_earth(90.0001,180.0001))*.57735) @ + ll_to_earth(90.0001,180.0001); + ?column? + ---------- + f + (1 row) + + -- + -- Test the recommended constraints. + -- + select is_point(ll_to_earth(0,0)); + ERROR: Function is_point(earth) does not exist + Unable to identify a function that satisfies the given argument types + You may need to add explicit typecasts + select cube_dim(ll_to_earth(0,0)) <= 3; + ?column? + ---------- + t + (1 row) + + select abs(cube_distance(ll_to_earth(0,0), '(0)'::cube) / earth() - 1) < + '10e-12'::float8; + ?column? + ---------- + t + (1 row) + + select is_point(ll_to_earth(30,60)); + ERROR: Function is_point(earth) does not exist + Unable to identify a function that satisfies the given argument types + You may need to add explicit typecasts + select cube_dim(ll_to_earth(30,60)) <= 3; + ?column? + ---------- + t + (1 row) + + select abs(cube_distance(ll_to_earth(30,60), '(0)'::cube) / earth() - 1) < + '10e-12'::float8; + ?column? + ---------- + t + (1 row) + + select is_point(ll_to_earth(60,90)); + ERROR: Function is_point(earth) does not exist + Unable to identify a function that satisfies the given argument types + You may need to add explicit typecasts + select cube_dim(ll_to_earth(60,90)) <= 3; + ?column? + ---------- + t + (1 row) + + select abs(cube_distance(ll_to_earth(60,90), '(0)'::cube) / earth() - 1) < + '10e-12'::float8; + ?column? + ---------- + t + (1 row) + + select is_point(ll_to_earth(-30,-90)); + ERROR: Function is_point(earth) does not exist + Unable to identify a function that satisfies the given argument types + You may need to add explicit typecasts + select cube_dim(ll_to_earth(-30,-90)) <= 3; + ?column? + ---------- + t + (1 row) + + select abs(cube_distance(ll_to_earth(-30,-90), '(0)'::cube) / earth() - 1) < + '10e-12'::float8; + ?column? + ---------- + t + (1 row) + diff -c -r -N --exclude=CVS /usr/local/src/postgres-cvs/contrib/earthdistance/sql/earthdistance.sql earthdistance/sql/earthdistance.sql *** /usr/local/src/postgres-cvs/contrib/earthdistance/sql/earthdistance.sql Wed Dec 31 18:00:00 1969 --- earthdistance/sql/earthdistance.sql Mon Sep 9 18:04:38 2002 *************** *** 0 **** --- 1,299 ---- + -- + -- Test earth distance functions + -- + + -- + -- first, define the datatype. Turn off echoing so that expected file + -- does not depend on contents of earthdistance.sql or cube.sql. + -- + \set ECHO none + \i ../cube/cube.sql + \i earthdistance.sql + \set ECHO all + + -- + -- The radius of the Earth we are using. + -- + + select earth()::numeric(20,5); + + -- + -- Convert straight line distances to great circle distances. + -- + select (pi()*earth())::numeric(20,5); + select sec_to_gc(0)::numeric(20,5); + select sec_to_gc(2*earth())::numeric(20,5); + select sec_to_gc(10*earth())::numeric(20,5); + select sec_to_gc(-earth())::numeric(20,5); + select sec_to_gc(1000)::numeric(20,5); + select sec_to_gc(10000)::numeric(20,5); + select sec_to_gc(100000)::numeric(20,5); + select sec_to_gc(1000000)::numeric(20,5); + + -- + -- Convert great circle distances to straight line distances. + -- + + select gc_to_sec(0)::numeric(20,5); + select gc_to_sec(sec_to_gc(2*earth()))::numeric(20,5); + select gc_to_sec(10*earth())::numeric(20,5); + select gc_to_sec(pi()*earth())::numeric(20,5); + select gc_to_sec(-1000)::numeric(20,5); + select gc_to_sec(1000)::numeric(20,5); + select gc_to_sec(10000)::numeric(20,5); + select gc_to_sec(100000)::numeric(20,5); + select gc_to_sec(1000000)::numeric(20,5); + + -- + -- Set coordinates using latitude and longitude. + -- Extract each coordinate separately so we can round them. + -- + + select cube_ll_coord(ll_to_earth(0,0),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,0),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,0),3)::numeric(20,5); + select cube_ll_coord(ll_to_earth(360,360),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(360,360),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(360,360),3)::numeric(20,5); + select cube_ll_coord(ll_to_earth(180,180),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(180,180),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(180,180),3)::numeric(20,5); + select cube_ll_coord(ll_to_earth(180,360),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(180,360),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(180,360),3)::numeric(20,5); + select cube_ll_coord(ll_to_earth(-180,-360),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(-180,-360),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(-180,-360),3)::numeric(20,5); + select cube_ll_coord(ll_to_earth(0,180),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,180),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,180),3)::numeric(20,5); + select cube_ll_coord(ll_to_earth(0,-180),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,-180),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(0,-180),3)::numeric(20,5); + select cube_ll_coord(ll_to_earth(90,0),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(90,0),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(90,0),3)::numeric(20,5); + select cube_ll_coord(ll_to_earth(90,180),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(90,180),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(90,180),3)::numeric(20,5); + select cube_ll_coord(ll_to_earth(-90,0),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(-90,0),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(-90,0),3)::numeric(20,5); + select cube_ll_coord(ll_to_earth(-90,180),1)::numeric(20,5), + cube_ll_coord(ll_to_earth(-90,180),2)::numeric(20,5), + cube_ll_coord(ll_to_earth(-90,180),3)::numeric(20,5); + + -- + -- Test getting the latitude of a location. + -- + + select latitude(ll_to_earth(0,0))::numeric(20,10); + select latitude(ll_to_earth(45,0))::numeric(20,10); + select latitude(ll_to_earth(90,0))::numeric(20,10); + select latitude(ll_to_earth(-45,0))::numeric(20,10); + select latitude(ll_to_earth(-90,0))::numeric(20,10); + select latitude(ll_to_earth(0,90))::numeric(20,10); + select latitude(ll_to_earth(45,90))::numeric(20,10); + select latitude(ll_to_earth(90,90))::numeric(20,10); + select latitude(ll_to_earth(-45,90))::numeric(20,10); + select latitude(ll_to_earth(-90,90))::numeric(20,10); + select latitude(ll_to_earth(0,180))::numeric(20,10); + select latitude(ll_to_earth(45,180))::numeric(20,10); + select latitude(ll_to_earth(90,180))::numeric(20,10); + select latitude(ll_to_earth(-45,180))::numeric(20,10); + select latitude(ll_to_earth(-90,180))::numeric(20,10); + select latitude(ll_to_earth(0,-90))::numeric(20,10); + select latitude(ll_to_earth(45,-90))::numeric(20,10); + select latitude(ll_to_earth(90,-90))::numeric(20,10); + select latitude(ll_to_earth(-45,-90))::numeric(20,10); + select latitude(ll_to_earth(-90,-90))::numeric(20,10); + + -- + -- Test getting the longitude of a location. + -- + + select longitude(ll_to_earth(0,0))::numeric(20,10); + select longitude(ll_to_earth(45,0))::numeric(20,10); + select longitude(ll_to_earth(90,0))::numeric(20,10); + select longitude(ll_to_earth(-45,0))::numeric(20,10); + select longitude(ll_to_earth(-90,0))::numeric(20,10); + select longitude(ll_to_earth(0,90))::numeric(20,10); + select longitude(ll_to_earth(45,90))::numeric(20,10); + select longitude(ll_to_earth(90,90))::numeric(20,10); + select longitude(ll_to_earth(-45,90))::numeric(20,10); + select longitude(ll_to_earth(-90,90))::numeric(20,10); + select longitude(ll_to_earth(0,180))::numeric(20,10); + select longitude(ll_to_earth(45,180))::numeric(20,10); + select longitude(ll_to_earth(90,180))::numeric(20,10); + select longitude(ll_to_earth(-45,180))::numeric(20,10); + select longitude(ll_to_earth(-90,180))::numeric(20,10); + select longitude(ll_to_earth(0,-90))::numeric(20,10); + select longitude(ll_to_earth(45,-90))::numeric(20,10); + select longitude(ll_to_earth(90,-90))::numeric(20,10); + select longitude(ll_to_earth(-45,-90))::numeric(20,10); + select longitude(ll_to_earth(-90,-90))::numeric(20,10); + + -- + -- For the distance tests the following is some real life data. + -- + -- Chicago has a latitude of 41.8 and a longitude of 87.6. + -- Albuquerque has a latitude of 35.1 and a longitude of 106.7. + -- (Note that latitude and longitude are specified differently + -- in the cube based functions than for the point based functions.) + -- + + -- + -- Test getting the distance between two points using earth_distance. + -- + + select earth_distance(ll_to_earth(0,0),ll_to_earth(0,0))::numeric(20,5); + select earth_distance(ll_to_earth(0,0),ll_to_earth(0,180))::numeric(20,5); + select earth_distance(ll_to_earth(0,0),ll_to_earth(90,0))::numeric(20,5); + select earth_distance(ll_to_earth(0,0),ll_to_earth(0,90))::numeric(20,5); + select earth_distance(ll_to_earth(0,0),ll_to_earth(0,1))::numeric(20,5); + select earth_distance(ll_to_earth(0,0),ll_to_earth(1,0))::numeric(20,5); + select earth_distance(ll_to_earth(30,0),ll_to_earth(30,1))::numeric(20,5); + select earth_distance(ll_to_earth(30,0),ll_to_earth(31,0))::numeric(20,5); + select earth_distance(ll_to_earth(60,0),ll_to_earth(60,1))::numeric(20,5); + select earth_distance(ll_to_earth(60,0),ll_to_earth(61,0))::numeric(20,5); + select earth_distance(ll_to_earth(41.8,87.6),ll_to_earth(35.1,106.7))::numeric(20,5); + select (earth_distance(ll_to_earth(41.8,87.6),ll_to_earth(35.1,106.7))* + 100./2.54/12./5280.)::numeric(20,5); + + -- + -- Test getting the distance between two points using geo_distance. + -- + + select geo_distance('(0,0)'::point,'(0,0)'::point)::numeric(20,5); + select geo_distance('(0,0)'::point,'(180,0)'::point)::numeric(20,5); + select geo_distance('(0,0)'::point,'(0,90)'::point)::numeric(20,5); + select geo_distance('(0,0)'::point,'(90,0)'::point)::numeric(20,5); + select geo_distance('(0,0)'::point,'(1,0)'::point)::numeric(20,5); + select geo_distance('(0,0)'::point,'(0,1)'::point)::numeric(20,5); + select geo_distance('(0,30)'::point,'(1,30)'::point)::numeric(20,5); + select geo_distance('(0,30)'::point,'(0,31)'::point)::numeric(20,5); + select geo_distance('(0,60)'::point,'(1,60)'::point)::numeric(20,5); + select geo_distance('(0,60)'::point,'(0,61)'::point)::numeric(20,5); + select geo_distance('(87.6,41.8)'::point,'(106.7,35.1)'::point)::numeric(20,5); + select (geo_distance('(87.6,41.8)'::point,'(106.7,35.1)'::point)*5280.*12.*2.54/100.)::numeric(20,5); + + -- + -- Test getting the distance between two points using the <@> operator. + -- + + select ('(0,0)'::point <@> '(0,0)'::point)::numeric(20,5); + select ('(0,0)'::point <@> '(180,0)'::point)::numeric(20,5); + select ('(0,0)'::point <@> '(0,90)'::point)::numeric(20,5); + select ('(0,0)'::point <@> '(90,0)'::point)::numeric(20,5); + select ('(0,0)'::point <@> '(1,0)'::point)::numeric(20,5); + select ('(0,0)'::point <@> '(0,1)'::point)::numeric(20,5); + select ('(0,30)'::point <@> '(1,30)'::point)::numeric(20,5); + select ('(0,30)'::point <@> '(0,31)'::point)::numeric(20,5); + select ('(0,60)'::point <@> '(1,60)'::point)::numeric(20,5); + select ('(0,60)'::point <@> '(0,61)'::point)::numeric(20,5); + select ('(87.6,41.8)'::point <@> '(106.7,35.1)'::point)::numeric(20,5); + select (('(87.6,41.8)'::point <@> '(106.7,35.1)'::point)*5280.*12.*2.54/100.)::numeric(20,5); + + -- + -- Test getting a bounding box around points. + -- + + select cube_ll_coord(earth_box(ll_to_earth(0,0),112000),1)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),112000),2)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),112000),3)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),112000),1)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),112000),2)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),112000),3)::numeric(20,5); + select cube_ll_coord(earth_box(ll_to_earth(0,0),pi()*earth()),1)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),pi()*earth()),2)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),pi()*earth()),3)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),pi()*earth()),1)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),pi()*earth()),2)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),pi()*earth()),3)::numeric(20,5); + select cube_ll_coord(earth_box(ll_to_earth(0,0),10*earth()),1)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),10*earth()),2)::numeric(20,5), + cube_ll_coord(earth_box(ll_to_earth(0,0),10*earth()),3)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),10*earth()),1)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),10*earth()),2)::numeric(20,5), + cube_ur_coord(earth_box(ll_to_earth(0,0),10*earth()),3)::numeric(20,5); + + -- + -- Test for points that should be in bounding boxes. + -- + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,1))*1.00001) @ + ll_to_earth(0,1); + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.1))*1.00001) @ + ll_to_earth(0,0.1); + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.01))*1.00001) @ + ll_to_earth(0,0.01); + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.001))*1.00001) @ + ll_to_earth(0,0.001); + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.0001))*1.00001) @ + ll_to_earth(0,0.0001); + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0.0001,0.0001))*1.00001) @ + ll_to_earth(0.0001,0.0001); + select earth_box(ll_to_earth(45,45), + earth_distance(ll_to_earth(45,45),ll_to_earth(45.0001,45.0001))*1.00001) @ + ll_to_earth(45.0001,45.0001); + select earth_box(ll_to_earth(90,180), + earth_distance(ll_to_earth(90,180),ll_to_earth(90.0001,180.0001))*1.00001) @ + ll_to_earth(90.0001,180.0001); + + -- + -- Test for points that shouldn't be in bounding boxes. Note that we need + -- to make points way outside, since some points close may be in the box + -- but further away than the distance we are testing. + -- + + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,1))*.57735) @ + ll_to_earth(0,1); + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.1))*.57735) @ + ll_to_earth(0,0.1); + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.01))*.57735) @ + ll_to_earth(0,0.01); + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.001))*.57735) @ + ll_to_earth(0,0.001); + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0,0.0001))*.57735) @ + ll_to_earth(0,0.0001); + select earth_box(ll_to_earth(0,0), + earth_distance(ll_to_earth(0,0),ll_to_earth(0.0001,0.0001))*.57735) @ + ll_to_earth(0.0001,0.0001); + select earth_box(ll_to_earth(45,45), + earth_distance(ll_to_earth(45,45),ll_to_earth(45.0001,45.0001))*.57735) @ + ll_to_earth(45.0001,45.0001); + select earth_box(ll_to_earth(90,180), + earth_distance(ll_to_earth(90,180),ll_to_earth(90.0001,180.0001))*.57735) @ + ll_to_earth(90.0001,180.0001); + + -- + -- Test the recommended constraints. + -- + + select is_point(ll_to_earth(0,0)); + select cube_dim(ll_to_earth(0,0)) <= 3; + select abs(cube_distance(ll_to_earth(0,0), '(0)'::cube) / earth() - 1) < + '10e-12'::float8; + select is_point(ll_to_earth(30,60)); + select cube_dim(ll_to_earth(30,60)) <= 3; + select abs(cube_distance(ll_to_earth(30,60), '(0)'::cube) / earth() - 1) < + '10e-12'::float8; + select is_point(ll_to_earth(60,90)); + select cube_dim(ll_to_earth(60,90)) <= 3; + select abs(cube_distance(ll_to_earth(60,90), '(0)'::cube) / earth() - 1) < + '10e-12'::float8; + select is_point(ll_to_earth(-30,-90)); + select cube_dim(ll_to_earth(-30,-90)) <= 3; + select abs(cube_distance(ll_to_earth(-30,-90), '(0)'::cube) / earth() - 1) < + '10e-12'::float8;