Find closest longitude and latitude in array?

后端 未结 4 1702
情深已故
情深已故 2020-12-12 23:04

I have a longitude and latitude as a string in PHP like below

49.648881
-103.575312

And I want to take that and look in an array of values

相关标签:
4条回答
  • 2020-12-12 23:22

    Iterate through the array, comparing values to what you have. If the value is smaller than your currently stored value (or if you don't have a currently stored value), store that value instead, otherwise throw it away.

    $closest = null;
    foreach($array as $key => $value){
        $distance = //compare distance here;
        if ($closest === null || $closest > $distance) {
            $closest = $distance;
        };
    };
    

    Of course, this will be made more difficult by the fact that latitude and longitude are on a sphere, and longitudes 179 and -179 are closer than 90 and 179.

    0 讨论(0)
  • 2020-12-12 23:24

    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 ) * cos( deg2rad( ($lat1+$lat2) /2 ) );
      $y = deg2rad( $lat1 - $lat2 ); 
      $dist = 6371000.0 * sqrt( $x*$x + $y*$y );
    
      return $dist;
    }
    
    0 讨论(0)
  • 2020-12-12 23:25

    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;
    }
    
    0 讨论(0)
  • 2020-12-12 23:42

    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.

    0 讨论(0)
提交回复
热议问题