Re: Advice on geolocation
От | Joe Conway |
---|---|
Тема | Re: Advice on geolocation |
Дата | |
Msg-id | 3D41F6B0.5030109@joeconway.com обсуждение исходный текст |
Ответ на | Re: Advice on geolocation (Chris Albertson <chrisalbertson90278@yahoo.com>) |
Список | pgsql-general |
Chris Albertson wrote: > --- Bruno Wolff III <bruno@wolff.to> wrote: > >>On Fri, Jul 26, 2002 at 09:33:53 -0700, >> Chris Albertson <chrisalbertson90278@yahoo.com> wrote: >> >>>I've done quite a bit of this as I used to work on a GIS >>>product. Given to lat,lon pairs it is not hard to find >>>the great circle distance between them. This assumes a >>>spherical Earth but good enough for your purposes as the >>>error will be under a few hundred meters >> >>My concern about this is that it will not be indexable. I suspect, >>but don't >>know, that this won't really be an issue for the small number (~5000) >>points >>of data (especially since I expect other constraints to be used in >>most >>queries). I haven't really followed this entire thread, but FWIW, here is a plpgsql function to get great circle distance given a pair of lat/lons (the Haversine formula). There is also something in contrib (see contrib/earthdistance) to do this, but I've used this on a webhost where I couldn't install my own C libraries. CREATE FUNCTION "geodist" (float8,float8,float8,float8 ) RETURNS float8 AS ' DECLARE lat1 ALIAS FOR $1; lon1 ALIAS FOR $2; lat2 ALIAS FOR $3; lon2 ALIAS FOR $4; dist float8; BEGIN dist := 0.621 * 6371.2 * 2 * atan2( sqrt(abs(0 + pow(sin(radians(lat2)/2 - radians(lat1)/2),2) + cos(radians(lat1)) * cos(radians(lat2)) * pow(sin(radians(lon2)/2 - radians(lon1)/2),2))),sqrt(abs(1 - pow(sin(radians(lat2)/2 - radians(lat1)/2),2) + cos(radians(lat1)) * cos(radians(lat2)) * pow(sin(radians(lon2)/2 - radians(lon1)/2),2)))); return dist; END; ' LANGUAGE 'plpgsql'; I used this for finding US zipcodes within a certain distance of the given zipcode. To improve performance, I also used a "box" around the lat/lon pairs: . . . WHERE abs(z.lat - $lat1d) * 60 * 1.15078 <= $dist and abs(z.long - $lon1d) * 60 * 1.15078 <= $dist and geodist($lat1d,$lon1d,lat,long) <= $dist and z.zip = az.zipcode . . . This limits the data being considered to a square area twice the dimension of your desired distance, and then the distance calc further restricts down to a circle of radius $dist. Hopefully you can get the idea from this snippet. HTH, Joe
В списке pgsql-general по дате отправления: