根據經緯度座標計算距離和方向

前段時間由於項目需要,瞭解了一下不同經緯度座標間距離的計算和方向的相關問題,本文理論主要參考下面作者提出的方法,需要訪問原作者內容,請點擊下面的鏈接: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;
}

調用也很簡單,由於項目保密級別較高,此處就不展示如何調用了。

謹以此記錄這個重要的知識點,願本篇文章對您有所幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章