查找地球坐标(纬度,经度),距离(米)和方位角(角度)

亚姆米林德

我需要以多种方式处理地球坐标。C / C ++中没有函数可以立即执行此操作。
提及以下问题:

  1. Python:获取给定的当前点的纬度/经度,距离和方位
  2. C:给定点(经度,纬度),距离和方位角,如何获取新的经度和纬度

在第一个和可移动类型脚本网站上,我发现以下公式:

查找2个坐标之间的方位角

x = cos(lat1Rad)*sin(lat2Rad) - sin(lat1Rad)*cos(lat2Rad)*cos(lon2Rad-lon1Rad);
y = sin(lon2Rad-lon1Rad) * cos(lat2Rad);
bearing = atan2(y, x);  // In radians; 
// Convert to degrees and for -ve add 360

查找2个坐标之间的距离(米)

PI = 3.14159265358979323846, earthDiameterMeters = 2*6371*1000;
x = sin((lat2Rad-lat1Rad) / 2);
y = sin((lon2Rad-lon1Rad) / 2);
meters = earthDiameterMeters * asin(sqrt(x*x + y*y*cos(lat1Rad)*cos(lat2Rad)));

从坐标+距离+角度查找坐标

meters *= 2 / earthDiameterMeters;
lat2Rad = asin(sin(lat1Rad)*cos(meters) + cos(lat1Rad)*sin(meters)*cos(bearing));
lon2Rad = lon1Rad + atan2(sin(bearing)*sin(meters)*cos(lat1Rad), 
                          cos(meters) - sin(lat1Rad)*sin(lat2Rad));

下面的伪代码应相互验证上述三个方程:

struct Coordinate { double lat, lon; } c1, c2;  
auto degree = FindBearing(c1, c2);
auto meters = FindDistance(c1, c2);
auto cX = FindCoordiante(c1, degree, meters);

现在,实际上答案几乎是正确的,但不是正确的。即cX不等于c2!经度值
始终存在差异0.0005例如

c1 = (12.968460,77.641308)  
c2 = (12.967862,77.653130)  
angle = 92.97         ^^^
distance = 1282.74  
cX = (12.967862,77.653613)
                      ^^^

我对数学的Havesine Forumla不太了解但是我知道的是,从网站fcc.gov上,答案总是正确的。

我究竟做错了什么?

代码仅供参考

虽然语法是C ++,但是所有数学函数都来自C,并且也很容易在C中移植(因此都标记了)

#include<iostream>
#include<iomanip>
#include<cmath>


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

static const double PI = 3.14159265358979323846, earthDiameterMeters = 6371.0 * 2 * 1000;

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

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

  using namespace std;
  const auto x = (cos(latitude1) * sin(latitude2)) -
                 (sin(latitude1) * cos(latitude2) * cos(longitudeDifference));
  const auto y = sin(longitudeDifference) * cos(latitude2);

  const auto degree = radianToDegree(atan2(y, x));
  return (degree >= 0)? degree : (degree + 360);
}

double CoordinatesToMeters (double latitude1,
                            double longitude1,
                            double latitude2,
                            double longitude2)
{
  latitude1 = degreeToRadian(latitude1);
  longitude1 = degreeToRadian(longitude1);
  latitude2 = degreeToRadian(latitude2);
  longitude2 = degreeToRadian(longitude2);

  using namespace std;
  auto x = sin((latitude2 - latitude1) / 2), y = sin((longitude2 - longitude1) / 2);
#if 1
  return earthDiameterMeters * asin(sqrt((x * x) + (cos(latitude1) * cos(latitude2) * y * y)));
#else
  auto value = (x * x) + (cos(latitude1) * cos(latitude2) * y * y);
  return earthDiameterMeters * atan2(sqrt(value), sqrt(1 - value));
#endif
}

std::pair<double,double> CoordinateToCoordinate (double latitude,
                                                 double longitude,
                                                 double angle,
                                                 double meters)
{
  latitude = degreeToRadian(latitude);
  longitude = degreeToRadian(longitude);
  angle = degreeToRadian(angle);
  meters *= 2 / earthDiameterMeters;

  using namespace std;
  pair<double,double> coordinate;

  coordinate.first = radianToDegree(asin((sin(latitude) * cos(meters))
                             + (cos(latitude) * sin(meters) * cos(angle))));
  coordinate.second = radianToDegree(longitude
                    + atan2((sin(angle) * sin(meters) * cos(latitude)),
                    cos(meters) - (sin(latitude) * sin(coordinate.first))));

  return coordinate;
}

int main ()
{
  using namespace std;
  const auto latitude1 = 12.968460, longitude1 = 77.641308,
             latitude2 = 12.967862, longitude2 = 77.653130;

  cout << std::setprecision(10);
  cout << "(" << latitude1 << "," << longitude1 << ") --- "
          "(" << latitude2 << "," << longitude2 << ")\n";

  auto angle = CoordinatesToAngle(latitude1, longitude1, latitude2, longitude2);
  cout << "Angle =  " << angle << endl;

  auto meters = CoordinatesToMeters(latitude1, longitude1, latitude2, longitude2);
  cout << "Meters = " << meters << endl;

  auto coordinate = CoordinateToCoordinate(latitude1, longitude1, angle, meters);
  cout << "Destination = (" << coordinate.first << "," << coordinate.second << ")\n";
}
4566976

CoordinateToCoordinate使用中sin(coordinate.first),已经以度为单位。使用sin(degreeToRadian(coordinate.first))

或更干净一点:

... CoordinateToCoordinate (...)
{
  ...
  coordinate.first = asin((sin(latitude) * cos(meters))
                        + (cos(latitude) * sin(meters) * cos(angle)));
  coordinate.second = longitude + atan2((sin(angle) * sin(meters) * cos(latitude)), 
         cos(meters) - (sin(latitude) * sin(coordinate.first)));

  coordinate.first = radianToDegree(coordinate.first);
  coordinate.second = radianToDegree(coordinate.second);

  return coordinate;
}

这样可以解决问题。现场演示

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

当您知道Java中的经度和纬度时,以米为单位计算距离

从方位角和距离计算纬度和经度

使用Java使用以千米为单位的纬度经度坐标来计算距离

如何用方位角,天顶和平均重量值创建极坐标图?

给定点(纬度,经度),距离和方位角,如何获取新的纬度和经度

计算经度和纬度坐标的中点

计算坐标列表(纬度,经度)之间的地理距离

查找使用纬度和经度之间的距离的SQL返回错误的距离

熊猫-遍历2列(经度和纬度)并找到每个坐标与特定位置之间的距离

测量纬度/经度和utm坐标之间的距离

使用Haversine的距离公式从经度和纬度获取距离

尝试计算纬度和经度给定距离以及从起点开始的方位

如何从enu向量中获得方位角和仰角

边界框具有4个纬度/经度和方位

在设备未平放地面时查找方位角值-Android?

根据距离和方位计算点/坐标

从GPS数据计算距离[经度和纬度]

在Android中使用两个不同点的经度和纬度找到以米为单位的距离

C#方位角和距离计算(使用Vincenty公式)的结果是否为NaN?

如何转换方位角?

三角 - 从方位角和仰角创建的矢量与平面的交集

R中的纬度和经度坐标

在 MATLAB 中创建角度(方位角)数据的半圆图

使用 Neo4J 使用纬度/经度查找距离

C++ 控制台 - 使用方位角和范围的新纬度/经度坐标

在 SVG 中绘制纬度和经度坐标

使用python和gdal从.geotiff中的纬度/经度点查找像素坐标

如何使用谷歌地图JS api从给定的纬度和经度坐标找到半径(比如10米)中的坐标(纬度和经度)

如何计算给定中心和方位角的扇区点的地理坐标