Рассчитать угол между двумя точками широты и долготы - PullRequest
24 голосов
/ 14 октября 2010

Можно ли рассчитать угол между двумя точками широты / долготы?

То, чего я пытаюсь достичь, это знать, куда направляется пользователь. Например, пользователь направляется на север, юг, .... юго-восток и т. Д.

Но у меня есть только две точки (Lng / Ltd)

Thx

Ответы [ 16 ]

1 голос
/ 13 сентября 2017

Для определения курса необходимо рассчитать подшипник.

Чтобы понять подшипник, прочитайте эту статью .

Согласно этой статье (раздел подшипник) формула:

θ = atan2( sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ )
where φ1, λ1 is the start point, 
      φ2, λ2 the end point,
      Δλ is the difference in longitude`

Вот пример того, как вычислить угол (в градусах) между двумя точками, выраженными в широтах / долготах.(сделано в C #)

Допустим, Point - это простой класс с двумя double атрибутами X (для долготы) и Y (для широты).

public double ComputeBearing(Point start,Point end)
{
     var φ1 = start.Y; //latitude 1
     var λ1 = start.X; //longitude 1
     var φ2 = end.Y; //latitude 2
     var λ2 = end.X; //longitude 2

     var y = Math.Sin(this.degreeToRadian(λ2 - λ1)) * Math.Cos(this.degreeToRadian(φ2));
     var x = Math.Cos(this.degreeToRadian(φ1)) * Math.Sin(this.degreeToRadian(φ2)) - Math.Sin(this.degreeToRadian(φ1)) * Math.Cos(this.degreeToRadian(φ2)) * Math.Cos(this.degreeToRadian(λ2 - λ1));

     var θ = Math.Atan2(y, x);
     θ = this.radianToDegree(θ);

     return θ;
}

Использование следующегометоды:

public double degreeToRadian(double angle)
{
    return Math.PI * angle / 180.0;
}

public double radianToDegree(double angle)
{
    return angle * (180.0 / Math.PI);
}

Используя ComputeBearing, вы легко получите угол, выраженный в градусах, который легко использовать в качестве заголовка

1 голос
/ 08 апреля 2017

На случай, если кому-то понадобится PHP код для этой функции:

/**
 * Calculate angle between 2 given latLng
 * @param  float $lat1
 * @param  float $lat2
 * @param  float $lng1
 * @param  float $lng2
 * @return integer
 */
function angle($lat1, $lat2, $lng1, $lng2) {
    $dLon = $lng2 - $lng1;
    $y = sin($dLon) * cos($lat2);
    $x = cos($lat1) * sin($lat2) - sin($lat1) * cos($lat2) * cos($dLon);
    return 360 - ((rad2deg(atan2($y, $x)) + 360) % 360);
}
1 голос
/ 14 августа 2015

Для тех, кто использует C / C ++, ниже приведен протестированный код:

static const auto PI = 3.14159265358979323846, diameterOfEarthMeters = 6371.0 * 2 * 1000;

double degreeToRadian (double degree) { return (degree * PI / 180); };
double radianToDegree (double radian) { return (radian * 180 / PI); };

double CoordinatesToAngle (const double latitude1,
                           const double longitude1,
                           const double latitude2,
                           const double longitude2)
{
  const auto longitudeDifferenceRadians = degreeToRadian(longitude2 - longitude1);
  auto latitude1Radian = degreeToRadian(latitude1),
       latitude2Radian = degreeToRadian(latitude2);

  const auto x = std::cos(latitude1Radian) * std::sin(latitude2Radian) -
                 std::sin(latitude1Radian) * std::cos(latitude2Radian) *
                 std::cos(longitudeDifferenceRadians);
  const auto y = std::sin(longitudeDifferenceRadians) * std::cos(latitude2Radian);

  return radianToDegree(std::atan2(y, x));
}

double CoordinatesToMeters (const double latitude1,
                            const double longitude1,
                            const double latitude2,
                            const double longitude2)
{
  auto latitude1Radian = degreeToRadian(latitude1),
       longitude1Radian = degreeToRadian(longitude1),
       latitude2Radian = degreeToRadian(latitude2),
       longitude2Radian = degreeToRadian(longitude2);
  auto x = std::sin((latitude2Radian - latitude1Radian) / 2),
       y = std::sin((longitude2Radian - longitude1Radian) / 2);

  return diameterOfEarthMeters *
         std::asin(std::sqrt((x * x) +
                             (std::cos(latitude1Radian) * std::cos(latitude2Radian) * y * y)));
}
1 голос
/ 20 мая 2012

Может быть, это то, что вы хотите:

cos(say) = (cosd(90-lat(1))) * (cos(90-lat(2)))
         + (sin(90-lat(1))) * (sind(90-lat(2)) * (cosd(abs(Landa(2)-landa(1)))));
0 голосов
/ 24 сентября 2017

Учитывая Nayanesh Gupte ответ и его комментарии. Я изменил некоторую часть кода и написал его в PHP.

  • широта и долгота преобразованы в радиан внутри функции.

Вот функция:

function angleFromCoordinate($lat1, $long1, $lat2, $long2) {

    $lat1 = deg2rad($lat1);
    $lat2 = deg2rad($lat2);
    $long1 = deg2rad($long1);
    $long2 = deg2rad($long2);

    $dLon = $long2 - $long1;

    $y = sin($dLon) * cos($lat2);
    $x = cos($lat1) * sin($lat2) - sin($lat1) * cos($lat2) * cos($dLon);

    $brng = atan2($y, $x);

    $brng = $brng * 180 / pi();
    $brng = fmod($brng + 360, 360);

    return $brng;
}
0 голосов
/ 12 сентября 2014

Убедитесь, что это прямолинейный подшипник, НЕ большой круговой подшипник, так как начальный подшипник изменяется в зависимости от расстояния

 double angle= Math.min((pbearingf-tbearingf) < 0 ? pbearingf-tbearingf+360:pbearingf-tbearingf, (tbearingf-pbearingf)<0?tbearingf-pbearingf+360:tbearingf-pbearingf);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...