RasterProcessTool/BaseCommonLibrary/BaseTool/GeoOperator.cpp

501 lines
13 KiB
C++
Raw Normal View History

2024-12-24 02:50:25 +00:00
#include "stdafx.h"
#include "GeoOperator.h"
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <time.h>
////#include <mkl.h>
#include <string>
#include <omp.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <gdal.h>
#include <gdal_priv.h>
#include <gdalwarper.h>
//#include <ogr_geos.h>
#include <ogrsf_frmts.h> //#include "ogrsf_frmts.h"
#include <fstream>
#include <proj.h>
#include "GeoOperator.h"
2025-04-17 19:30:28 +00:00
#include <ogr_spatialref.h> // OGRSpatialReference <20><><EFBFBD>ڿռ<DABF><D5BC>ο<EFBFBD>ת<EFBFBD><D7AA>
#include <gdal_alg.h> // <20><><EFBFBD><EFBFBD> GDALWarp <20><><EFBFBD><EFBFBD>
#include <ogr_spatialref.h>
2024-12-24 02:50:25 +00:00
Landpoint operator +(const Landpoint& p1, const Landpoint& p2)
{
return Landpoint{ p1.lon + p2.lon,p1.lat + p2.lat,p1.ati + p2.ati };
}
Landpoint operator -(const Landpoint& p1, const Landpoint& p2)
{
return Landpoint{ p1.lon - p2.lon,p1.lat - p2.lat,p1.ati - p2.ati };
}
bool operator ==(const Landpoint& p1, const Landpoint& p2)
{
return p1.lat == p2.lat && p1.lon == p2.lon && p1.ati == p2.ati;
}
Landpoint operator *(const Landpoint& p, double scale)
{
return Landpoint{
p.lon * scale,
p.lat * scale,
p.ati * scale
};
}
Landpoint LLA2XYZ(const Landpoint& LLA) {
double L = LLA.lon * d2r;
double B = LLA.lat * d2r;
double H = LLA.ati;
double sinB = sin(B);
double cosB = cos(B);
//double N = a / sqrt(1 - e * e * sin(B) * sin(B));
double N = a / sqrt(1 - eSquare * sinB * sinB);
Landpoint result = { 0,0,0 };
result.lon = (N + H) * cosB * cos(L);
result.lat = (N + H) * cosB * sin(L);
//result.z = (N * (1 - e * e) + H) * sin(B);
result.ati = (N * (1 - 1 / f_inverse) * (1 - 1 / f_inverse) + H) * sinB;
return result;
}
void LLA2XYZ(const Landpoint& LLA, Point3& XYZ)
{
double L = LLA.lon * d2r;
double B = LLA.lat * d2r;
double H = LLA.ati;
double sinB = sin(B);
double cosB = cos(B);
//double N = a / sqrt(1 - e * e * sin(B) * sin(B));
double N = a / sqrt(1 - eSquare * sinB * sinB);
Landpoint result = { 0,0,0 };
XYZ.x = (N + H) * cosB * cos(L);
XYZ.y = (N + H) * cosB * sin(L);
//result.z = (N * (1 - e * e) + H) * sin(B);
XYZ.z = (N * (1 - 1 / f_inverse) * (1 - 1 / f_inverse) + H) * sinB;
}
Eigen::MatrixXd LLA2XYZ(Eigen::MatrixXd landpoint)
{
landpoint.col(0) = landpoint.col(0).array() * d2r; // lon
landpoint.col(1) = landpoint.col(1).array() * d2r; // lat
Eigen::MatrixXd sinB = (landpoint.col(1).array().sin());//lat
Eigen::MatrixXd cosB = (landpoint.col(1).array().cos());//lat
Eigen::MatrixXd N = a / ((1 - sinB.array().pow(2) * eSquare).array().sqrt());
Eigen::MatrixXd result(landpoint.rows(), 3);
result.col(0) = (N.array() + landpoint.col(2).array()) * cosB.array() * Eigen::cos(landpoint.col(0).array()).array(); //x
result.col(1) = (N.array() + landpoint.col(2).array()) * cosB.array() * Eigen::sin(landpoint.col(0).array()).array(); //y
result.col(2) = (N.array() * (1 - 1 / f_inverse) * (1 - 1 / f_inverse) + landpoint.col(2).array()) * sinB.array(); //z
return result;
}
Landpoint XYZ2LLA(const Landpoint& XYZ) {
double tmpX = XYZ.lon;//
double temY = XYZ.lat;//
double temZ = XYZ.ati;
double curB = 0;
double N = 0;
double sqrtTempXY = sqrt(tmpX * tmpX + temY * temY);
double calB = atan2(temZ, sqrtTempXY);
int counter = 0;
double sinCurB = 0;
while (abs(curB - calB) * r2d > epsilon && counter < 25)
{
curB = calB;
sinCurB = sin(curB);
N = a / sqrt(1 - eSquare * sinCurB * sinCurB);
calB = atan2(temZ + N * eSquare * sinCurB, sqrtTempXY);
counter++;
}
Landpoint result = { 0,0,0 };
result.lon = atan2(temY, tmpX) * r2d;
result.lat = curB * r2d;
result.ati = temZ / sinCurB - N * (1 - eSquare);
return result;
}
void XYZ2BLH_FixedHeight(double x, double y, double z,double ati, Landpoint& point) {
const double a = 6378137.0; // WGS84<38><34><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
const double f = 1.0 / 298.257223563;
const double e2 = 2 * f - f * f; // <20><>һƫ<D2BB><C6AB><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD>
// <20><><EFBFBD><EFBFBD><E3BEAD>L (<28><><EFBFBD><EFBFBD>)
const double L_rad = std::atan2(y, x);
point.lon = L_rad * 180.0 / M_PI; // תΪ<D7AA><CEAA>
const double p = std::sqrt(x * x + y * y);
const double H = ati; // ʹ<><CAB9><EFBFBD><EFBFBD>֪<EFBFBD>߶<EFBFBD>
// <20><>ʼγ<CABC>ȹ<EFBFBD><C8B9><EFBFBD><E3A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD>߶<EFBFBD>H<EFBFBD><48>
double B_rad = std::atan2(z, p * (1 - e2 * (a / (a + H))));
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>γ<EFBFBD><CEB3>B<EFBFBD><42><EFBFBD>̶<EFBFBD>H<EFBFBD><48>
for (int i = 0; i < 10; ++i) { // <20><>֪Hʱ<48><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
const double sin_B = std::sin(B_rad);
const double N = a / std::sqrt(1 - e2 * sin_B * sin_B);
const double delta = e2 * N / (N + H); // <20>߶ȹ̶<C8B9>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
const double B_new = std::atan2(z, p * (1 - delta));
if (std::abs(B_new - B_rad) < 1e-9) {
B_rad = B_new;
break;
}
B_rad = B_new;
}
point.lat = B_rad * 180.0 / M_PI; // <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
// <20><><EFBFBD>ȷ<EFBFBD>Χ<EFBFBD><CEA7><EFBFBD><EFBFBD> [-180<38><30>, 180<38><30>]
point.lon = std::fmod(point.lon + 360.0, 360.0);
if (point.lon > 180.0) point.lon -= 360.0;
point.ati = ati;
}
2024-12-24 02:50:25 +00:00
double getAngle(const Landpoint& a, const Landpoint& b)
{
double c = dot(a, b) / (getlength(a) * getlength(b));
if (a.lon * b.lat - a.lat * b.lon >= 0) {
return acos(c > 1 ? 1 : c < -1 ? -1 : c) * r2d;
}
else {
return 360 - acos(c > 1 ? 1 : c < -1 ? -1 : c) * r2d;
}
}
double dot(const Landpoint& p1, const Landpoint& p2)
{
return p1.lat * p2.lat + p1.lon * p2.lon + p1.ati * p2.ati;
}
double getlength(const Landpoint& p1) {
return sqrt(dot(p1, p1));
}
Landpoint crossProduct(const Landpoint& a, const Landpoint& b) {
return Landpoint{
a.lat * b.ati - a.ati * b.lat,//x
a.ati * b.lon - a.lon * b.ati,//y
a.lon * b.lat - a.lat * b.lon//z
};
}
float cross2d(Point3 a, Point3 b)
{
return a.x * b.y - a.y * b.x;
}
Point3 operator -(Point3 a, Point3 b)
{
return Point3{ a.x - b.x, a.y - b.y, a.z - b.z };
}
Point3 operator +(Point3 a, Point3 b)
{
return Point3{ a.x + b.x, a.y + b.y, a.z + b.z };
}
double operator /(Point3 a, Point3 b)
{
return sqrt(pow(a.x, 2) + pow(a.y, 2)) / sqrt(pow(b.x, 2) + pow(b.y, 2));
}
Landpoint getSlopeVector(const Landpoint& p0, const Landpoint& p1, const Landpoint& p2, const Landpoint& p3, const Landpoint& p4,bool inLBH) {
Landpoint n0, n1, n2, n3, n4;
if (inLBH) {
n0 = LLA2XYZ(p0);
n1 = LLA2XYZ(p1);
n2 = LLA2XYZ(p2);
n3 = LLA2XYZ(p3);
n4 = LLA2XYZ(p4);
}
else {
n0 = p0;
n1 = p1;
n2 = p2;
n3 = p3;
n4 = p4;
}
Landpoint n01 = n1 - n0, n02 = n2 - n0, n03 = n3 - n0, n04 = n4 - n0;
// <20><>n01Ϊ<31><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Landpoint np01 = p1 - p0, np02 = p2 - p0, np03 = p3 - p0, np04 = p4 - p0;
double a2 = getAngle(Landpoint{ np01.lon,np01.lat,0 }, Landpoint{ np02.lon,np02.lat,0 });// 01->02
double a3 = getAngle(Landpoint{ np01.lon,np01.lat,0 }, Landpoint{ np03.lon,np03.lat,0 });// 01->03
double a4 = getAngle(Landpoint{ np01.lon,np01.lat,0 }, Landpoint{ np04.lon,np04.lat,0 });// 01->04
//qDebug() << a2 << "\t" << a3 << "\t" << a4 << endl;
a2 = 360 - a2;
a3 = 360 - a3;
a4 = 360 - a4;
Landpoint N, W, S, E;
N = n01;
if (a2 >= a3 && a2 >= a4) {
W = n02;
if (a3 >= a4) {
S = n03;
E = n04;
}
else {
S = n04;
E = n03;
}
}
else if (a3 >= a2 && a3 >= a4) {
W = n03;
if (a2 >= a4) {
S = n02;
E = n04;
}
else {
S = n04;
E = n02;
}
}
else if (a4 >= a2 && a4 >= a3)
{
W = n04;
if (a2 >= a3) {
S = n02;
E = n03;
}
else {
S = n03;
E = n02;
}
}
return (crossProduct(N, W) + crossProduct(W, S) + crossProduct(S, E) + crossProduct(E, N)) * 0.25;
}
double distance(const Vector3D& p1, const Vector3D& p2)
{
double dx = p1.x - p2.x;
double dy = p1.y - p2.y;
double dz = p1.z - p2.z;
return std::sqrt(dx * dx + dy * dy + dz * dz);
}
double pointToLineDistance(const Vector3D& point, const Vector3D& linePoint, const Vector3D& lineDirection)
{
Vector3D pointToLine = { point.x - linePoint.x, point.y - linePoint.y, point.z - linePoint.z };
// 计算点到直线的投影点的位<E79A84><E4BD8D>?
double t = (pointToLine.x * lineDirection.x + pointToLine.y * lineDirection.y + pointToLine.z * lineDirection.z) /
(lineDirection.x * lineDirection.x + lineDirection.y * lineDirection.y + lineDirection.z * lineDirection.z);
// 计算投影<E68A95><E5BDB1>?
Vector3D projection = { linePoint.x + t * lineDirection.x, linePoint.y + t * lineDirection.y, linePoint.z + t * lineDirection.z };
// 计算点到直线的距<E79A84><E8B79D>?
return distance(point, projection);
}
Vector3D operator+(const Vector3D& p1, const Vector3D& p2)
{
return Vector3D{ p1.x + p2.x,p1.y + p2.y,p1.z + p2.z };
}
Vector3D operator-(const Vector3D& p1, const Vector3D& p2)
{
return Vector3D{ p1.x - p2.x,p1.y - p2.y,p1.z - p2.z };
}
bool operator==(const Vector3D& p1, const Vector3D& p2)
{
return p1.x == p2.x && p1.y == p2.y && p1.z == p2.z;
}
Vector3D operator*(const Vector3D& p, double scale)
{
return Vector3D{
p.x * scale,
p.y * scale,
p.z * scale
};
}
Vector3D operator*(double scale, const Vector3D& p)
{
return Vector3D{
p.x * scale,
p.y * scale,
p.z * scale
};
}
double getAngle(const Vector3D& a, const Vector3D& b)
{
double c = dot(a, b) / (getlength(a) * getlength(b));
if (a.x * b.y - a.y * b.x >= 0) {
return acos(c > 1 ? 1 : c < -1 ? -1 : c) * r2d;
}
else {
return 360 - acos(c > 1 ? 1 : c < -1 ? -1 : c) * r2d;
}
}
double getCosAngle(const Vector3D& a, const Vector3D& b)
{
double c = dot(a, b) / (getlength(a) * getlength(b));
return acos(c > 1 ? 1 : c < -1 ? -1 : c) * r2d;
}
double dot(const Vector3D& p1, const Vector3D& p2)
{
return p1.y * p2.y + p1.x * p2.x + p1.z * p2.z;
}
double getlength(const Vector3D& p1)
{
return std::sqrt(std::pow(p1.x, 2) + std::pow(p1.y, 2) + std::pow(p1.z, 2));
}
Vector3D crossProduct(const Vector3D& a, const Vector3D& b)
{
return Vector3D{
a.y * b.z - a.z * b.y,//x
a.z * b.x - a.x * b.z,//y
a.x * b.y - a.y * b.x//z
};
}
/// <summary>
/// n1
/// n4 n0 n2
/// n3
/// </summary>
Vector3D getSlopeVector(const Vector3D& n0, const Vector3D& n1, const Vector3D& n2, const Vector3D& n3, const Vector3D& n4)
{
Vector3D n01 = n1 - n0, n02 = n2 - n0, n03 = n3 - n0, n04 = n4 - n0;
return (crossProduct(n01, n04) + crossProduct(n04, n03) + crossProduct(n03, n02) + crossProduct(n02, n01)) * 0.25;
}
SphericalCoordinates cartesianToSpherical(const CartesianCoordinates& cartesian)
{
SphericalCoordinates spherical;
spherical.r = std::sqrt(cartesian.x * cartesian.x + cartesian.y * cartesian.y + cartesian.z * cartesian.z);
spherical.theta = std::acos(cartesian.z / spherical.r);
spherical.phi = std::atan2(cartesian.y, cartesian.x);
return spherical;
}
CartesianCoordinates sphericalToCartesian(const SphericalCoordinates& spherical)
{
CartesianCoordinates cartesian;
cartesian.x = spherical.r * std::sin(spherical.theta) * std::cos(spherical.phi);
cartesian.y = spherical.r * std::sin(spherical.theta) * std::sin(spherical.phi);
cartesian.z = spherical.r * std::cos(spherical.theta);
return cartesian;
}
double getlocalIncAngle(Landpoint& satepoint, Landpoint& landpoint, Landpoint& slopeVector) {
Landpoint Rsc = satepoint - landpoint; // AB=B-A
//double R = getlength(Rsc);
2025-02-25 05:18:19 +00:00
//qDebug() << R << endl;
2024-12-24 02:50:25 +00:00
double angle = getAngle(Rsc, slopeVector);
if (angle >= 180) {
return 360 - angle;
}
else {
return angle;
}
}
double getlocalIncAngle(Vector3D& satepoint, Vector3D& landpoint, Vector3D& slopeVector){
Vector3D Rsc = satepoint - landpoint; // AB=B-A
//double R = getlength(Rsc);
2025-02-25 05:18:19 +00:00
//qDebug() << R << endl;
2024-12-24 02:50:25 +00:00
double angle = getAngle(Rsc, slopeVector);
if (angle >= 180) {
return 360 - angle;
}
else {
return angle;
}
}
2025-04-17 19:30:28 +00:00
bool BASECONSTVARIABLEAPI ConvertResolutionToDegrees(int sourceEPSG, double resolutionMeters, double refLon, double refLat, double& degreePerPixelX, double& degreePerPixelY){
// <20><>ʼ<EFBFBD><CABC>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>ƽ<EFBFBD><C6BD>ͶӰ<CDB6><D3B0><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>WGS84 <20><>γ<EFBFBD>ȣ<EFBFBD>
OGRSpatialReference sourceSRS, targetSRS;
sourceSRS.importFromEPSG(sourceEPSG); // Դ<><D4B4><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>ȷ EPSG
targetSRS.importFromEPSG(4326); // Ŀ<><C4BF>Ϊ WGS84 <20><>γ<EFBFBD><CEB3>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>γ<EFBFBD><CEB3> -> ƽ<><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
OGRCoordinateTransformation* toPlane = OGRCreateCoordinateTransformation(&targetSRS, &sourceSRS);
if (!toPlane) return false;
// <20><><EFBFBD>ο<EFBFBD><CEBF>γ<E3BEAD><CEB3>ת<EFBFBD><D7AA>Ϊƽ<CEAA><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double x = refLon, y = refLat;
if (!toPlane->Transform(1, &x, &y)) {
OGRCoordinateTransformation::DestroyCT(toPlane);
return false;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -> <20><>γ<EFBFBD><CEB3>
OGRCoordinateTransformation* toGeo = OGRCreateCoordinateTransformation(&sourceSRS, &targetSRS);
if (!toGeo) {
OGRCoordinateTransformation::DestroyCT(toPlane);
return false;
}
// <20><><EFBFBD><EFBFBD><E3B6AB><EFBFBD>ֱ<EFBFBD><D6B1>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD>ȱ仯<C8B1><E4BBAF><EFBFBD><EFBFBD>
double eastX = x + resolutionMeters, eastY = y;
double eastLon = eastX, eastLat = eastY;
if (!toGeo->Transform(1, &eastLon, &eastLat)) {
OGRCoordinateTransformation::DestroyCT(toPlane);
OGRCoordinateTransformation::DestroyCT(toGeo);
return false;
}
degreePerPixelX = (eastLon - refLon) / resolutionMeters; // <20><><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD>ÿ<EFBFBD>׶<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><E3B1B1><EFBFBD>ֱ<EFBFBD><D6B1>ʣ<EFBFBD>γ<EFBFBD>ȱ仯<C8B1><E4BBAF><EFBFBD><EFBFBD>
double northX = x, northY = y + resolutionMeters;
double northLon = northX, northLat = northY;
if (!toGeo->Transform(1, &northLon, &northLat)) {
OGRCoordinateTransformation::DestroyCT(toPlane);
OGRCoordinateTransformation::DestroyCT(toGeo);
return false;
}
degreePerPixelY = (northLat - refLat) / resolutionMeters; // γ<>ȷ<EFBFBD><C8B7><EFBFBD>ÿ<EFBFBD>׶<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
// <20>ͷ<EFBFBD><CDB7><EFBFBD>Դ
OGRCoordinateTransformation::DestroyCT(toPlane);
OGRCoordinateTransformation::DestroyCT(toGeo);
return true;
}