Find closest longitude and latitude in array?

There is no quick and easy way to do that. You have to iterate through all elements and calculate distance between them and starting point, save the result and repeat, saving the result only if it is lower then previous.


Rather using the law of cosines for distance, you can use flat earth approximation. The flat earth equations reduce the number of trig functions in the calculation. The Δlat, Δlon is the difference between your reference point and the test point.

This formula would not be accurate for long distance navigation (thousands of miles) but for this particular problem, you aren't really interested in accurate distance, but who is the closest point to me. This is a simpler formulation that should give you that.

x = Δlon * cos(lat)   // lat/lon are in radians!
y = Δlat
distance = R * sqrt( x² + y² )  // R is radius of the earth; 
                                // typical value is 6371 km

Reference: http://www.movable-type.co.uk/scripts/latlong.html

Distance code

function distanceMeters($lat1, $lon1, $lat2, $lon2) { 
  $x = deg2rad( $lon1 - $lon2 ) * Math.cos( deg2rad( ($lat1+$lat2) /2 ) );
  $y = deg2rad( $lat1 - $lat2 ); 
  $dist = 6371000.0 * Math.sqrt( $x*$x + $y*$y );

  return $dist;
}

function deg2rad(degrees) {
  var pi = Math.PI;
  return degrees * (pi/180);
}

You need to map the distance of each item to the reference point first.

Then you sort the map and then you can tell which has the lowest (or highest if you reverse the search) distance:

$ref = array(49.648881, -103.575312);

$items = array(
    '0' => array('item1','otheritem1details....','55.645645','-42.5323'),
    '1' => array('item1','otheritem1details....','100.645645','-402.5323')
);

$distances = array_map(function($item) use($ref) {
    $a = array_slice($item, -2);
    return distance($a, $ref);
}, $items);

asort($distances);

echo 'Closest item is: ', var_dump($items[key($distances)]);

Output:

Closest item is: array(4) {
  [0]=>
  string(5) "item1"
  [1]=>
  string(21) "otheritem1details...."
  [2]=>
  string(9) "55.645645"
  [3]=>
  string(8) "-42.5323"
}

Take care you have the right order of lat and long.

The distance function (only the header slightly changed and units have been dropped):

function distance($a, $b)
{
    list($lat1, $lon1) = $a;
    list($lat2, $lon2) = $b;

    $theta = $lon1 - $lon2;
    $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
    $dist = acos($dist);
    $dist = rad2deg($dist);
    $miles = $dist * 60 * 1.1515;
    return $miles;
}