Plane.FormationCreator/Plane.FormationCreator/CalculationLogLatDistance.cs
pxzleo c85a17a324 加入任务整体旋转
加入自动识别RTK航点到达精度为0.6米,碰撞精度为0.5米
2017-08-13 02:17:11 +08:00

372 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Plane.FormationCreator
{
/**
*
* 计算经纬度、距离、方位角
*
* */
public class CalculationLogLatDistance
{
/**
* 地球赤道半径(km)
* */
static public double EARTH_RADIUS = 6378.137;
/**
* 地球每度的弧长(km)
* */
static public double EARTH_ARC = 111.199;
/**
* 转化为弧度(rad)
* */
public static double rad(double d)
{
return d * Math.PI / 180.0;
}
/**
* 求两经纬度距离
*
* @param lon1
* 第一点的经度
* @param lat1
* 第一点的纬度
* @param lon2
* 第二点的经度
* @param lat2
* 第二点的纬度
* @return 两点距离单位km
* */
public static double GetDistanceOne(double lon1, double lat1, double lon2,
double lat2)
{
double r1 = rad(lat1);
double r2 = rad(lon1);
double a = rad(lat2);
double b = rad(lon2);
double s = Math.Acos(Math.Cos(r1) * Math.Cos(a) * Math.Cos(r2 - b)
+ Math.Sin(r1) * Math.Sin(a))
* EARTH_RADIUS;
return s;
}
public static void GetRotatePos(double Centlon, double Centlat,double Angle, double lon_in,
double lat_in, out double lon_out, out double lat_out)
{
double lpDistance = GetDistanceOne(Centlon, Centlat,
lon_in,
lat_in);
MyLatLng mypos1, mypos2;
mypos1 = new CalculationLogLatDistance.MyLatLng(Centlon, Centlat);
mypos2 = new CalculationLogLatDistance.MyLatLng(lon_in , lat_in);
double lpAzimuth = CalculationLogLatDistance.getAngle(mypos1, mypos2);
ConvertDistanceToLogLat(Centlon, Centlat, lpDistance,
lpAzimuth + Angle, out lon_out, out lat_out);
return ;
}
/**
* 求两经纬度距离(google maps源码中)
*
* @param lon1
* 第一点的经度
* @param lat1
* 第一点的纬度
* @param lon2
* 第二点的经度
* @param lat2
* 第二点的纬度
* @return 两点距离单位km
* */
public static double GetDistanceTwo(double lon1, double lat1, double lon2,
double lat2)
{
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lon1) - rad(lon2);
double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2)
+ Math.Cos(radLat1) * Math.Cos(radLat2)
* Math.Pow(Math.Sin(b / 2), 2)));
s = s * EARTH_RADIUS;
return s;
}
/**
* 求两经纬度距离
*
* @param lon1
* 第一点的经度
* @param lat1
* 第一点的纬度
* @param lon2
* 第二点的经度
* @param lat2
* 第二点的纬度
* @return 两点距离单位km
* */
public static double GetDistanceThree(double lon1, double lat1,
double lon2, double lat2)
{
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double radLon1 = rad(lon1);
double radLon2 = rad(lon2);
if (radLat1 < 0)
radLat1 = Math.PI / 2 + Math.Abs(radLat1);// south
if (radLat1 > 0)
radLat1 = Math.PI / 2 - Math.Abs(radLat1);// north
if (radLon1 < 0)
radLon1 = Math.PI * 2 - Math.Abs(radLon1);// west
if (radLat2 < 0)
radLat2 = Math.PI / 2 + Math.Abs(radLat2);// south
if (radLat2 > 0)
radLat2 = Math.PI / 2 - Math.Abs(radLat2);// north
if (radLon2 < 0)
radLon2 = Math.PI * 2 - Math.Abs(radLon2);// west
double x1 = Math.Cos(radLon1) * Math.Sin(radLat1);
double y1 = Math.Sin(radLon1) * Math.Sin(radLat1);
double z1 = Math.Cos(radLat1);
double x2 = Math.Cos(radLon2) * Math.Sin(radLat2);
double y2 = Math.Sin(radLon2) * Math.Sin(radLat2);
double z2 = Math.Cos(radLat2);
double d = Math.Pow((x1 - x2), 2) + Math.Pow((y1 - y2), 2)
+ Math.Pow((z1 - z2), 2);
// // 余弦定理求夹角
// double theta = Math.Acos((2 - d) / 2);
d = Math.Pow(EARTH_RADIUS, 2) * d;
// //余弦定理求夹角
double theta = Math.Acos((2 * Math.Pow(EARTH_RADIUS, 2) - d)
/ (2 * Math.Pow(EARTH_RADIUS, 2)));
double dist = theta * EARTH_RADIUS;
return dist;
}
/**
* 求两经纬度方向角
*
* @param lon1
* 第一点的经度
* @param lat1
* 第一点的纬度
* @param lon2
* 第二点的经度
* @param lat2
* 第二点的纬度
* @return 方位角,角度(单位:°)
* */
public static double GetAzimuth(double lon1, double lat1, double lon2,
double lat2)
{
lat1 = rad(lat1);
lat2 = rad(lat2);
lon1 = rad(lon1);
lon2 = rad(lon2);
double azimuth = Math.Sin(lat1) * Math.Sin(lat2) + Math.Cos(lat1)
* Math.Cos(lat2) * Math.Cos(lon2 - lon1);
azimuth = Math.Sqrt(1 - azimuth * azimuth);
azimuth = Math.Cos(lat2) * Math.Sin(lon2 - lon1) / azimuth;
azimuth = Math.Asin(azimuth) * 180 / Math.PI;
if (Double.IsNaN(azimuth))
{
if (lon1 < lon2)
{
azimuth = 90.0;
}
else {
azimuth = 270.0;
}
}
return azimuth;
}
/**
* 已知一点经纬度A和与另一点B的距离和方位角求B的经纬度(计算结果有误)
*
* @param lon1
* A的经度
* @param lat1
* A的纬度
* @param distance
* AB距离单位
* @param azimuth
* AB方位角
* @return B的经纬度
* */
public static void GetOtherPoint(double lon1, double lat1,
double distance, double azimuth, out double lng2, out double lat2)
{
azimuth = rad(azimuth);
double ab = distance / EARTH_ARC;// AB间弧线长
ab = rad(ab);
double Lat = Math.Asin(Math.Sin(lat1) * Math.Cos(ab) + Math.Cos(lat1)
* Math.Sin(ab) * Math.Cos(azimuth));
double Lon = lon1
+ Math.Asin(Math.Sin(azimuth) * Math.Sin(ab) / Math.Cos(Lat));
// System.out.println(Lon + "," + Lat);
double a = Math.Acos(Math.Cos(90 - lon1) * Math.Cos(ab)
+ Math.Sin(90 - lon1) * Math.Sin(ab) * Math.Cos(azimuth));
double C = Math.Asin(Math.Sin(ab) * Math.Sin(azimuth) / Math.Sin(a));
// System.out.println("c=" + C);
lng2 = lon1 + C;
lat2 = 90 - a;
return ;
}
/**
* 已知一点经纬度A和与另一点B的距离和方位角求B的经纬度
*
* @param lon1
* A的经度
* @param lat1
* A的纬度
* @param distance
* AB距离单位
* @param azimuth
* AB方位角
* @return B的经纬度
* */
public static void ConvertDistanceToLogLat(double lng1, double lat1,
double distance, double azimuth, out double lng2, out double lat2)
{
azimuth = rad(azimuth);
// 将距离转换成经度的计算公式
lng2 = lng1 + (distance * Math.Sin(azimuth))
/ (EARTH_ARC * Math.Cos(rad(lat1)));
// 将距离转换成纬度的计算公式
lat2 = lat1 + (distance * Math.Cos(azimuth)) / EARTH_ARC;
return ;
}
public static MyLatLng getMyLatLng(MyLatLng A, double distance, double angle)
{
double dx = distance * 1000 * Math.Sin((Math.PI / 180) * angle);
double dy = distance * 1000 * Math.Cos((Math.PI / 180) * angle);
double bjd = (dx / A.Ed + A.m_RadLo) * 180.0/ Math.PI;
double bwd = (dy / A.Ec + A.m_RadLa) * 180.0/ Math.PI;
return new MyLatLng(bjd, bwd);
}
/**
* 获取AB连线与正北方向的角度
* @param A A点的经纬度
* @param B B点的经纬度
* @return AB连线与正北方向的角度0~360
*/
public static double getAngle(MyLatLng A, MyLatLng B)
{
double dx = (B.m_RadLo - A.m_RadLo) * A.Ed;
double dy = (B.m_RadLa - A.m_RadLa) * A.Ec;
double angle = 0.0;
angle = Math.Atan(Math.Abs(dx / dy)) * 180.0/ Math.PI;
double dLo = B.m_Longitude - A.m_Longitude;
double dLa = B.m_Latitude - A.m_Latitude;
if (dLo > 0 && dLa <= 0)
{
angle = (90.0- angle) + 90;
}
else if (dLo <= 0 && dLa < 0)
{
angle = angle + 180.0;
}
else if (dLo < 0 && dLa >= 0)
{
angle = (90.0- angle) + 270;
}
if (Double.IsNaN(angle)) angle = 0.0;
return angle;
}
public class MyLatLng
{
static double Rc = 6378137;
static double Rj = 6356725;
public double m_LoDeg, m_LoMin, m_LoSec;
public double m_LaDeg, m_LaMin, m_LaSec;
public double m_Longitude, m_Latitude;
public double m_RadLo, m_RadLa;
public double Ec;
public double Ed;
public MyLatLng(double longitude, double latitude)
{
m_LoDeg = (int)longitude;
m_LoMin = (int)((longitude - m_LoDeg) * 60);
m_LoSec = (longitude - m_LoDeg - m_LoMin / 60.0) * 3600;
m_LaDeg = (int)latitude;
m_LaMin = (int)((latitude - m_LaDeg) * 60);
m_LaSec = (latitude - m_LaDeg - m_LaMin / 60.0) * 3600;
m_Longitude = longitude;
m_Latitude = latitude;
m_RadLo = longitude * Math.PI / 180.0;
m_RadLa = latitude * Math.PI / 180.0;
Ec = Rj + (Rc - Rj) * (90.0- m_Latitude) / 90.0;
Ed = Ec * Math.Cos(m_RadLa);
}
}
}
}