1

I have different vendors saved with their own latitudinal and longitudinal positions in my database.

I then use google maps to pin point them on a map, however you also have a search function where you can input any address you want with a 5/10/20 km/miles "around".

So for example when i search London and 10 km around, i would expect to get all the vendors from the london returned lat and long + 10km around that point.

right now i have the function worked out with a slight difference (obviously without the radius option)

private function findServicesNearLocation($filter = array(), $lat, $lng) {
    // set radius
    $difference = 0.07;

    // build filter
    $latitude_from = floatval($lat) - $difference;
    $latitude_to = floatval($lat) + $difference;
    $longitude_from = floatval($lng) - $difference;
    $longitude_to = floatval($lng) + $difference;

    $filter[] = "a.gps_latitude >= {$latitude_from}";
    $filter[] = "a.gps_latitude <= {$latitude_to}";
    $filter[] = "a.gps_longitude >= {$longitude_from}";
    $filter[] = "a.gps_longitude <= {$longitude_to}";

    // return services
    return $this->vendors->getVendors(implode(' AND ', $filter));
}

How would i have to change the above function to make an appropriate estimate and to select all the vendors from a specific "10 km around" those lat and long.

Thank you

Highstrike
  • 462
  • 3
  • 14
  • You might want to have a look at [this similar question](http://stackoverflow.com/questions/27928/how-do-i-calculate-distance-between-two-latitude-longitude-points) on SO. – eggyal Apr 25 '12 at 14:45
  • it is not similar, the person had to calculate distance between two points, i have just 1 point in space as lat, long and i need to select all my vendors around that position by 20 km or more – Highstrike Apr 25 '12 at 15:04
  • The principle is the same. But I grant you, your problem extends to how that principle gets applied in your case. – eggyal Apr 25 '12 at 15:05

2 Answers2

1

Look like your are searching on a rectangle, not in a radius.

For that you could use MySQL Spatial Extension and read more about implementation here : Geo-Distance-Search-with-MySQL

But for your information, mongoDB can do that with a simple "SELECT". Give him a position and a range and it's done. More infos : MongoDB Geospatial Indexing

Vivien
  • 1,159
  • 2
  • 14
  • 34
  • while this would probably be the best way to do it, installing an extension is out of the question for the owners are very strict about this, i do however like the following query – Highstrike Apr 25 '12 at 15:16
  • `SELECT destination.*,3956 * 2 * ASIN(SQRT( POWER(SIN((orig.lat -dest.lat) * pi()/180 / 2), 2) +COS(orig.lat * pi()/180) * COS(dest.lat * pi()/180) *POWER(SIN((orig.lon -dest.lon) * pi()/180 / 2), 2) )) asdistance FROM users destination, users originWHERE origin.id=userid and destination.longitude between lon1 and lon2 and destination.latitude between lat1 and lat2 having distance < dist ORDER BY Distance limit 10; ` – Highstrike Apr 25 '12 at 15:17
  • while this would have been my choice as an answer, because of the strict owners i cannot use this, sorry. – Highstrike Apr 25 '12 at 15:17
  • please see http://stackoverflow.com/questions/10318002/20-km-miles-around-a-lat-long/10318226#comment13284159_10318255 – Highstrike Apr 25 '12 at 15:48
1

I think this is an answer to what you are asking. Latitude and longitude degrees are approximately 111km apart, so you can figure that into your math. I hope this is what you are asking.

private function findServicesNearLocation($filter = array(), $lat, $lng, $distanceKilometers=0) {
    // set radius
    $difference = 0.07;
    $distance=$distanceKilometers!=0?ceil($distanceKilometers/111):0;
    // build filter
    $latitude_from = floatval($lat) - $difference - $distance;
    $latitude_to = floatval($lat) + $difference + $distance;
    $longitude_from = floatval($lng) - $difference - $distance;
    $longitude_to = floatval($lng) + $difference + $distance;

    $filter[] = "a.gps_latitude >= {$latitude_from}";
    $filter[] = "a.gps_latitude <= {$latitude_to}";
    $filter[] = "a.gps_longitude >= {$longitude_from}";
    $filter[] = "a.gps_longitude <= {$longitude_to}";

    // return services
    return $this->vendors->getVendors(implode(' AND ', $filter));
}
Tim Withers
  • 12,072
  • 5
  • 43
  • 67
  • 1
    At very least, you should probably introduce [Pythogras' theorem](http://en.wikipedia.org/wiki/Pythagorean_theorem) to get a radius rather than a rectangle... – eggyal Apr 25 '12 at 14:57
  • @eggyal could you help me out with that? – Highstrike Apr 25 '12 at 15:01
  • 1
    @Highstrike: You want `(a.gps_lat-$lat_from)^2 + (a.gps_long-$long_from)^2 <= $distance^2` – eggyal Apr 25 '12 at 15:03
  • @eggyal would i still have to keep the $difference variable? as it once helped me to get vendors near those points but now that i have $distance which could be >= 10 and <= 100 i could probably scratch that right? – Highstrike Apr 25 '12 at 15:12
  • @Highstrike: Indeed, `$difference` is no longer being used. – eggyal Apr 25 '12 at 15:13
  • @Highstrike: By way of clarification, the `$distance` I referred to above is the result of Tim's calculation based on his approximation of 1 degree ~= 111km. – eggyal Apr 25 '12 at 15:18
  • this is the final where condition `$filter[] = "pow(a.gps_latitude - ".floatval($lat).",2) + pow(a.gps_longitude - ".floatval($lng).",2) <= pow({$difference},2)";` where difference is `$difference = (float)($distanceKilometers !=0 ? number_format(($distanceKilometers / 111), 2) : 0.07);` – Highstrike Apr 25 '12 at 15:46
  • 2
    Using 111km as an approximation works fine for longitude, which is mostly invariant, but the length of a degree of latitude changes drastically with longitude. What you really want to use is the Haversine formula (http://en.wikipedia.org/wiki/Haversine_formula). – Ethan Brown Apr 25 '12 at 17:30
  • @EthanBrown help me with an implementation of that formula please? – Highstrike Apr 25 '12 at 22:35