#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& x_dist,QVector& z_diff) { const UGPoint3D* pts3D1 = line3D.GetPoints(); // QVector z_diff; //高度余量 // QVector 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(tmp); QVector y; QVector 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;igetSphericalDistance(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)); } }