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.

192 lines
5.9 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;
}
//获取几何对象长度
double GeoComputation::getGeometryLength(UGGeometry *geometry)
{
int type = geometry->GetType();
double sum = 0;
switch (type) {
case UGGeometry::GeoLine:
{
UGGeoLine* line = (UGGeoLine*)geometry;
const UGPoint2D* pts = line->GetPoints();
double x1 = pts->x;
double y1 = pts->y;
double x2,y2;
for (int i = 1; i < line->GetPointCount(); ++i)
{
pts++;
x2 = pts->x;
y2 = pts->y;
sum += this->getSphericalDistance(x1,y1,x2,y2);
x1 = x2;
y1 = y2;
}
}
break;
default:
break;
}
return sum;
}
//计算高度余量
void GeoComputation::getAlititudeDiff(UGGeoLine3D line3D,UGDatasetRasterPtr dem,QVector<double>& x_dist,QVector<double>& z_diff)
{
const UGPoint3D* pts3D1 = line3D.GetPoints();
// QVector<double> z_diff; //高度余量
// QVector<double> x_dist; //距离累计量
double dist_sum = 0;
for (int i = 0; i < line3D.GetPointCount()-1; ++i)
{
//多线段分解为单线段进行剖面分析
UGPoint2D pt0 = UGPoint2D(pts3D1->x,pts3D1->y);
int z0 = pts3D1->z;
pts3D1++;
UGPoint2D pt1 = UGPoint2D(pts3D1->x,pts3D1->y);
int z1 = pts3D1->z;
UGGeoLine line;
line.Make(pt0,pt1);
//进行剖面分析
// UGDatasetPtr tmp = m_pWorkspace->GetDataSource(0)->GetDataset(Translator::QStr2UGStr(demName));
// UGDatasetRasterPtr dem = dynamic_pointer_cast<UGDatasetRaster>(tmp);
QVector<double> y;
QVector<QPointF> vec_pt;
geoAnalysisMag.SurfaceProfile_Parallel(dem,&line,y,vec_pt);
if(i==0)//折线起点
{
x_dist.append(0);
z_diff.append(z0-y.at(0));
}
double d0 = this->getSphericalDistance(pt0.x,pt0.y,pt1.x,pt1.y);
for(int i=1;i<y.count()-1;i++) //计算内插点的海拔高度
{
double d1 = this->getSphericalDistance(pt0.x,pt0.y,vec_pt.at(i).x(),vec_pt.at(i).y());
double z_pt = z0 + (z1-z0)*(d1/d0); //插值点高度
// vec_z.append(z_pt);
// dist_sum += sqrt(d1*d1+z_pt*z_pt);
z_diff.append(z_pt - y.at(i)); //高度余量
x_dist.append(dist_sum + sqrt(d1*d1+z_pt*z_pt)); //距离累计
}
x_dist.append(dist_sum + sqrt(d0*d0+(z1-z0)*(z1-z0)));
z_diff.append(z1-y.at(y.count()-1));
dist_sum += sqrt(d0*d0+(z1-z0)*(z1-z0));
}
}