Относительная позиция в PHP между 2 точками (широта / долгота) - PullRequest
2 голосов
/ 18 мая 2010

У меня есть база аэропортов с широтой и долготой для каждой точки.Я хочу запустить скрипт PHP, чтобы найти все аэропорты, которые находятся рядом с данным аэропортом, с их расстоянием и относительным направлением.

Т.е. для аэропорта KLDJ (40-37-02.810N 074-14-40.539W)

Аэропорт поблизости
KJFK - Аэропорт Джона Ф. Кеннеди (21,2 нм к северо-востоку) (40-38-23.104N 073-46-44.132W)

Я использовалкод из http://www.movable -type.co.uk / scripts / latlong.html , чтобы найти расстояние, и попытался использовать его, чтобы найти направление, которое может быть неверным.

//BEARING RHUMB LINE
$phi = log(tan($lat2/2+pi/4)/tan($lat1/2+pi/4));
$distance['bearing'] = (rad2deg(atan2($theta, $phi)) +180) % 360;

Я в основном хочу пройти все точки через этот скрипт и найти расстояние, которое у меня уже есть, но затем направление.(т. е. N, S, W, E, NW, SW, NE, SE)

Ответы [ 3 ]

6 голосов
/ 18 мая 2010

Сильно заимствуя из методов здесь и используя данные из здесь , я собрал этот пример

<?php

$chicago = array(
    'lat' => 41.9
  , 'lng' => 87.65
);

$dallas = array(
    'lat' => 32.73
  , 'lng' => 96.97
);

$ftworth = array(
    'lat' => 32.82
  , 'lng' => 97.35
);

$bearing = getBearingBetweenPoints( $dallas, $chicago );

echo "Bearing: $bearing&deg;<br>";
echo "Direction: " . getCompassDirection( $bearing );

function getBearingBetweenPoints( $point1, $point2 )
{
  return getRhumbLineBearing( $point1['lat'], $point2['lng'], $point2['lat'], $point1['lng'] );
}

function getRhumbLineBearing($lat1, $lon1, $lat2, $lon2) {
  //difference in longitudinal coordinates
  $dLon = deg2rad($lon2) - deg2rad($lon1);

  //difference in the phi of latitudinal coordinates
  $dPhi = log(tan(deg2rad($lat2) / 2 + pi() / 4) / tan(deg2rad($lat1) / 2 + pi() / 4));

  //we need to recalculate $dLon if it is greater than pi
  if(abs($dLon) > pi()) {
    if($dLon > 0) {
      $dLon = (2 * pi() - $dLon) * -1;
    }
    else {
      $dLon = 2 * pi() + $dLon;
    }
  }
  //return the angle, normalized
  return (rad2deg(atan2($dLon, $dPhi)) + 360) % 360;
}

function getCompassDirection( $bearing )
{
  static $cardinals = array( 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N' );
  return $cardinals[round( $bearing / 45 )];
}
1 голос
/ 18 мая 2010

Глядя на другую страницу с того же сайта :

$lat = 0;  // latitude of centre of bounding circle in degrees
$lon = 0;  // longitude of centre of bounding circle in degrees
$rad = 0;  // radius of bounding circle in chosen units

// Choose your unit of measure... 
$r = 6371;  // earth's radius in km
$r = 3959;  // earth's radius in miles
// or
$r = 3440;  // earth's radius in nautical miles

// convert point of origin to radians
$lat = deg2rad($lat);
$lon = deg2rad($lon);

// first-cut bounding box (in radians)
$maxLat = $lat + $rad / $r;
$minLat = $lat - $rad / $r;
// compensate for longitude getting smaller with increasing latitude
$maxLon = ( $lon + $rad / $r ) / cos( $lat );
$minLon = ( $lon - $rad / $r ) / cos( $lat );

в сочетании с запросом:

$query = 'SELECT
  id
, lat
, lon
, ACOS(SIN('.$lat.') * SIN(RADIANS(lat)) + COS('.$lat.') * COS(RADIANS(lat)) * COS(RADIANS(lon) - '. $lon.')) * '.$r.' AS distance
FROM (
   SELECT
     id
   , lat
   , lon
   FROM MyTable
   WHERE 
     RADIANS(lat) > $minLat AND RADIANS(lat) < '.$maxLat.'
    AND 
     RADIANS(lon) > $minLon AND RADIANS(lon) < '.$maxLon.'
) AS FirstCut 
WHERE ACOS(SIN('.$lat.') * SIN(RADIANS(lat)) + COS('.$lat.') * COS(RADIANS(lat)) * COS(RADIANS(lon) - '. $lon.')) * '.$r.' < '.$rad;

Выбирает список мест (и их расстояние от начала вашего круга) в пределах указанного вами ограничительного круга.

Единственное, что осталось сделать, - это рассчитать направление для возвращаемых местоположений. Что можно сделать с вашей формулой ромбической линии.

Выше предполагается, что ваша база данных заполнена координатами в градусах.

Если вы храните свои местоположения в качестве геометрических объектов, вы можете использовать Встроенные пространственные функции MySQL . Хотя я вполне уверен, что MySQL содержит только ограничивающие прямоугольники.

1 голос
/ 18 мая 2010

Вы можете проверить, широта позиции B больше или меньше широты позиции A, чтобы определить, находится ли она на востоке или на западе. То же самое с долготой на север и юг. Наконец, для обнаружения необходим порог, и в этом случае дрейф достаточно велик, чтобы переключиться на промежуточное направление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...