views:

44

answers:

2

I have a list of about 60 stores with physical addresses and geocodes. I would like to make a simple interface where a user can enter a zip code, or city and state, or even a street address and have the list sort in order of proximity to the entered address. This is a very common feature of websites as I understand.

My plan to do this is to use the Google Maps API to find the geocode of the entered location and use the Pythagorean Theorem to calculate the distance from each location and sort the list by the distances and return the result (or maybe the top 5 of the result set...).

Is this the correct way to do this? Is there a more optimal method or a function built-in the Google Maps API that will do this? Since this is something so common, I would imagine there has been tried and tested in many ways and there are probably several correct answers. I am just looking for some advice if I am going about this the correct way.

Thank you.

+1  A: 

I found this link a while back when I was researching something similar. It uses .NET but the principles would apply to any language/framework.

Store Locator: Help customers find you with Google Maps

The key part of the solution is using the Haversine Formula to find the distance between two points specified as longitude and latitude. There's a C# implementation of this formula linked to in the above article here:

Distance between locations using latitude and longitude (CodeProject)

A bit more rooting around revealed:

Calculate Distance Between Two Points on a Globe in 9 Different Languages

Kev
+2  A: 

The Pythagorean Theorem will not be enough. The curve of the Earth makes this so. It requires a bit of Euclidian geometry. The formula and a simple implementation for finding the distance between two points on Earth - as the bird flies and not actual travel distance - is (in PHP):

// pass the latitudes and longitudes in as degrees
function getDistance($lat1,$long1,$lat2,$long2)
{
    $r = 3963.1; //3963.1 statute miles; 3443.9 nautical miles; 6378 km
    $pi = pi();

    // convert the degrees to radians
    $lat1 = $lat1*($pi/180);
    $lat2 = $lat2*($pi/180);
    $long1 = $long1*($pi/180);
    $long2 = $long2*($pi/180);

    $ret = (acos(cos($lat1)*cos($long1)*cos($lat2)*cos($long2) + cos($lat1)*sin($long1)*cos($lat2)*sin($long2) + sin($lat1)*sin($lat2)) * $r) ;
    return $ret;
}

You could incorporate a version of this in your code. In addition here is a possible (untested) function that is a derivative of another one I have used for MySQL.

DELIMITER $$

DROP FUNCTION IF EXISTS `FindDist` $$
CREATE FUNCTION `FindDist` (lt1 DOUBLE,lg1 DOUBLE,lt2 DOUBLE,lg2 DOUBLE) RETURNS DOUBLE
DETERMINISTIC
BEGIN
    DECLARE dist,eradius DOUBLE;

    SET eradius=3963.1;
    SET dist=Acos(Cos(lt1) * Cos(lg1) * Cos(lt2) * Cos(lg2) + Cos(lt1) * Sin(lg1) * Cos(lt2) * Sin(lg2) + Sin(lt1) * Sin(lt2)) * eradius;
    RETURN dist;
END $$

DELIMITER ;
Buggabill