Znajdź najbliższą długość i szerokość geograficzną w tablicy?

Mam długość i szerokość geograficzną jako ciąg znaków w PHP jak poniżej

49.648881
-103.575312

I chcę to wziąć i zajrzeć do tablicy wartości, aby znaleźć najbliższą. Tablica wygląda jak

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

Chcę zwrócić tablicę, która ma najbliższy long i lad. W tym przypadku byłaby to pierwsza (i tak Wiem, że -400 nie jest możliwą wartością).

Czy jest jakiś szybki i łatwy sposób, aby to zrobić? Próbowałem szukać tablicy, ale to nie zadziałało.

Różnica kod

function distance($lat1, $lon1, $lat2, $lon2, $unit) { 

  $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;
  $unit = strtoupper($unit);

  if ($unit == "K") {
    return ($miles * 1.609344); 
  } else if ($unit == "N") {
      return ($miles * 0.8684);
    } else {
        return $miles;
      }
}
Author: Steven, 2012-03-06

4 answers

Musisz najpierw zmapować odległość każdego elementu do punktu odniesienia.

Następnie sortujesz mapę i możesz określić, która ma najniższą (lub najwyższą, jeśli cofniesz wyszukiwanie) odległość:

$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)]);

Wyjście:

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

Uważaj, że masz odpowiednią kolejność lat i długości.

Funkcja odległości (tylko nagłówek nieznacznie się zmienił i jednostki zostały zrzucone):

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;
}
 34
Author: hakre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-06 18:08:43

Raczej używając prawa cosinusów dla odległości, można użyć przybliżenia ziemi płaskiej. Równania ziemi płaskiej zmniejszają liczbę funkcji Tryg w obliczeniach. Δlat, Δlon to różnica między punktem odniesienia a punktem testowym.

Ta formuła nie byłaby dokładna dla nawigacji długodystansowej (tysiące mil), ale w tym konkretnym problemie nie interesuje Cię dokładna odległość, ale kto jest najbliżej mnie. Jest to prostsze preparat, który powinien ci to dać.

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

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

Kod odległości

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;
}
 8
Author: TreyA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-25 18:29:02

Nie ma na to szybkiego i łatwego sposobu. Musisz iterować przez wszystkie elementy i obliczyć odległość między nimi a punktem początkowym, zapisać wynik i powtórzyć, zapisując wynik tylko wtedy, gdy jest niższy niż poprzedni.

 2
Author: dev-null-dweller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-06 17:56:58

Iteruj przez tablicę, porównując wartości z tym, co masz. Jeśli wartość jest mniejsza niż aktualnie przechowywana wartość (lub jeśli nie masz aktualnie przechowywanej wartości), Zapisz tę wartość, w przeciwnym razie wyrzuć ją.

$closest = null;
foreach($array as $key => $value){
    $distance = //compare distance here;
    if ($closest === null || $closest > $distance) {
        $closest = $distance;
    };
};
Oczywiście, będzie to utrudnione przez fakt, że szerokość i Długość geograficzna są na kuli, a długości 179 i -179 są bliższe niż 90 i 179.
 0
Author: Chris Sobolewski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-06 18:24:37