前段時間由於項目需要,瞭解了一下不同經緯度座標間距離的計算和方向的相關問題,本文理論主要參考下面作者提出的方法,需要訪問原作者內容,請點擊下面的鏈接:https://www.cnblogs.com/zhoug2020/p/8993750.html
此處我採用的也是Haversine formula公式來計算球面上任意兩個座標間的距離。
定義的類如下:
DistanceBetweenLonAndLat.h
#include <math.h>
#define M_PI 3.14159265358979323846
#define EARTH_RADIUS 6371.0
class DistanceBetweenLonAndLat
{
public:
DistanceBetweenLonAndLat();
~DistanceBetweenLonAndLat();
protected:
double HaverSin(double thera);
double ConvertDegreesToRadians(double degrees);
double ConvertRadiansToDegrees(double radian);
double get_distance(double lon1, double lat1, double lon2, double lat2);
int get_angle(double lon1, double lat1, double lon2, double lat2);
int AngleSpecification(int angle);
};
具體實現的方法如下:
#include "DistanceBetweenLonAndLat.h"
DistanceBetweenLonAndLat::DistanceBetweenLonAndLat()
{
}
DistanceBetweenLonAndLat::~DistanceBetweenLonAndLat()
{
}
double DistanceBetweenLonAndLat::HaverSin(double thera)
{
double v = sin(thera / 2);
return v * v;
}
//角度轉換爲弧度
double DistanceBetweenLonAndLat::ConvertDegreesToRadians(double degrees)
{
return degrees * M_PI / 180;
}
//弧度轉換爲角度
double DistanceBetweenLonAndLat::ConvertRadiansToDegrees(double radian)
{
return radian * 180.0 / M_PI;
}
//計算兩個經緯度座標間的距離(單位:米)
//參數:lon1爲經度1;lat1爲緯度1;lon2爲經度2;lat2爲緯度2
double DistanceBetweenLonAndLat::get_distance(double lon1, double lat1, double lon2, double lat2)
{
lat1 = ConvertDegreesToRadians(lat1);
lon1 = ConvertDegreesToRadians(lon1);
lat2 = ConvertDegreesToRadians(lat2);
lon2 = ConvertDegreesToRadians(lon2);
double vLon = fabs(lon1 - lon2);
double vLat = fabs(lat1 - lat2);
double h = HaverSin(vLat) + cos(lat1) * cos(lat2) * HaverSin(vLon);
double distance = 2 * EARTH_RADIUS * asin(sqrt(h));
return distance * 1000;
}
//兩個經緯度間連線與正北方向的夾角
//參數:lon1爲經度1;lat1爲緯度1;lon2爲經度2;lat2爲緯度
double DistanceBetweenLonAndLat::get_angle(double lon1, double lat1, double lon2, double lat2)
{
double x = lat1 - lat2;
double y = lon1 - lon2;
int angle = -1;
if (y == 0 && x > 0)
angle = 0;
if (y == 0 && x < 0)
angle = 180;
if (x == 0 && y > 0)
angle = 90;
if (x == 0 && y < 0)
angle = 270;
if (angle == -1)
{
double dislon = get_distance(lon1, lat2, lon2, lat2);
double dislat = get_distance(lon2, lat1, lon2, lat2);
if (x > 0 && y > 0)
angle = atan2(dislon, dislat) / M_PI * 180;
if (x < 0 && y > 0)
angle = atan2(dislat, dislon) / M_PI * 180 + 90;
if (x < 0 && y < 0)
angle = atan2(dislon, dislat) / M_PI * 180 + 180;
if (x > 0 && y < 0)
angle = atan2(dislat, dislon) / M_PI * 180 + 270;
}
return angle;
}
//將角度限制在[0,360),0--北,90--東,180--南,270--西;與指南針一致
int DistanceBetweenLonAndLat::AngleSpecification(int angle)
{
int curAngle;
if (angle < 0)
{
curAngle = (angle + 360) % 360;
}
else {
curAngle = angle % 360;
}
return curAngle;
}
調用也很簡單,由於項目保密級別較高,此處就不展示如何調用了。
謹以此記錄這個重要的知識點,願本篇文章對您有所幫助。