You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.3 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "geocomputation.h"
#include "Stream/ugdefs.h"
#include "erkir/sphericalpoint.h"
GeoComputation::GeoComputation()
{
}
/*@brief 计算两点间球面距离
* @param lon1(-180至180),lat1(-90到90) 经纬度点1(度)
* @param lon2,lat3 经纬度点2(度)
* @return 距离m
*/
double GeoComputation::getSphericalDistance(double lon1, double lat1, double lon2, double lat2)
{
erkir::spherical::Point p1{ lat1, lon1 };
erkir::spherical::Point p2{ lat2, lon2 };
double distance = p1.distanceTo(p2);
return distance;
}
/*@brief 根据起点坐标、方位角、距离,计算另一点坐标。
* startPoint:起始点地理坐标点lat(-90到90)lon(-180,180)
* bearing:方位角(0-360)(度)
* dist:两点之间距离(m)
*/
QPointF GeoComputation::getDestinationPoint(double lon1, double lat1, double bearing, double dist)
{
erkir::spherical::Point p{ lat1, lon1 };
auto dest = p.destinationPoint(dist, bearing); // 51.5135°N, 000.0983°W
QPointF point(dest.longitude().degrees(),dest.latitude().degrees());
return point;
}
/*@brief 根据起点坐标、方位角、距离,计算另一点坐标。
* 使用Vincenty's公式求解,使用WGS-84椭球
* startPoint:起始点地理坐标点lat(-90到90)lon(-180,180)
* bearing:方位角(度)
* dist:两点之间距离(km)
*/
QPointF GeoComputation::computeOffsetGeoPosition(double lon1, double lat1, double bearing, double dist)
{
QPointF endPoint;
//角度转化为弧度
// qreal lon1 = (fmod(startPoint.x()+540,360)-180.0)*PI/180;
lon1 = lon1*PI/180.0;
lat1 = lat1*PI/180.0;
bearing = bearing*PI/180.0;
dist = dist*1000;
//WGS-84椭球参数
double flat = 298.257223563;
double a = 6378137.0;
double b = 6356752.314245;
//开始求解坐标
double f = 1/flat;
double sb = sin(bearing);
double cb = cos(bearing);
double tu1 = (1-f)*tan(lat1);
double cu1 = 1/sqrt((1+tu1*tu1));
double su1 = tu1*cu1;
double s2 = atan2(tu1, cb);
double sa = cu1*sb;
double csa = 1-sa*sa;
double us = csa*(a*a - b*b)/(b*b);
double A = 1+us/16384*(4096+us*(-768+us*(320-175*us)));
double B = us/1024*(256+us*(-128+us*(74-47*us)));
double s1 = dist/(b*A);
double s1p = 2*PI;
double cs1m = 0.0;
double ss1 = 0.0;
double cs1 = 0.0;
double ds1 = 0.0;
while (abs(s1-s1p) > 1e-12)
{
cs1m = cos(2*s2+s1);
ss1 = sin(s1);
cs1 = cos(s1);
ds1 = B*ss1*(cs1m+B/4*(cs1*(-1+2*cs1m*cs1m)- B/6*cs1m*(-3+4*ss1*ss1)*(-3+4*cs1m*cs1m)));
s1p = s1;
s1 = dist/(b*A)+ds1;
}
double t = su1*ss1-cu1*cs1*cb;
double lat2 = atan2(su1*cs1+cu1*ss1*cb, (1-f)*sqrt(sa*sa + t*t));
double l2 = atan2(ss1*sb, cu1*cs1-su1*ss1*cb);
double c = f/16*csa*(4+f*(4-3*csa));
double l = l2-(1-c)*f*sa* (s1+c*ss1*(cs1m+c*cs1*(-1+2*cs1m*cs1m)));
double lon2 = lon1+l;
endPoint.setX(lon2*180/PI);
endPoint.setY(lat2*180/PI);
return endPoint;
}
//显示坐标转地图坐标
UGPoint2D GeoComputation::DPtoMP(UGMap *pMap, const QPoint &point)
{
UGDrawCache &drawing = pMap->GetDrawing()->m_DrawCache;
UGPoint DP(point.x(), point.y());
UGPoint2D LP(0,0);
drawing.DPtoLP(&DP, &LP, 1);
UGPoint2D MP(0, 0);
pMap->GetDrawing()->m_DrawParam.LPtoMP(LP, MP);
return MP;
}