simorthoprogram/simorthoprogram-orth_s_sar-.../baseTool.h

397 lines
11 KiB
C++
Raw Permalink Blame History

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.

#pragma once
///
/// 基本类、基本函数
///
//#define EIGEN_USE_MKL_ALL
//#define EIGEN_VECTORIZE_SSE4_2
//#include <mkl.h>
//#include <mkl.h>
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <time.h>
#include <string>
#include <omp.h>
#include <complex>
#include <gdal.h>
#include <gdal_priv.h>
#include <gdalwarper.h>
#include <ogrsf_frmts.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/eigen.hpp>
#include <opencv2/features2d.hpp>
#include <fstream>
using namespace std;
using namespace Eigen;
#define PI_180 180/3.141592653589793238462643383279
#define T180_PI 3.141592653589793238462643383279/180
#define LIGHTSPEED 299792458
#define Radians2Degrees(Radians) Radians*PI_180
#define Degrees2Radians(Degrees) Degrees*T180_PI
const double PI = 3.141592653589793238462643383279;
const double epsilon = 0.000000000000001;
const double pi = 3.14159265358979323846;
const double d2r = pi / 180;
const double r2d = 180 / pi;
const double a = 6378137.0; //椭球长半轴
const double ae = 6378137.0; //椭球长半轴
const double ee= 0.0818191910428;// 第一偏心率
const double f_inverse = 298.257223563; //扁率倒数
const double b = a - a / f_inverse;
const double eSquare = (a * a - b * b) / (a * a);
const double e = sqrt(eSquare);
const double earth_Re = 6378136.49;
const double earth_Rp = (1 - 1 / f_inverse) * earth_Re;
const double earth_We = 0.000072292115;
///////////////////////////////////// 运行时间打印 //////////////////////////////////////////////////////////
std::string getCurrentTimeString();
std::string getCurrentShortTimeString();
/////////////////////////////// 基本图像类 //////////////////////////////////////////////////////////
/// <summary>
/// 三维向量,坐标表达
/// </summary>
struct Landpoint // 点 SAR影像的像素坐标
{
/// <summary>
/// 经度x
/// </summary>
double lon; // 经度x lon pixel_col
/// <summary>
/// 纬度y
/// </summary>
double lat; // 纬度y lat pixel_row
/// <summary>
/// 高度z
/// </summary>
double ati; // 高程z ati pixel_time
};
struct Point_3d {
double x;
double y;
double z;
};
Landpoint operator +(const Landpoint& p1, const Landpoint& p2);
Landpoint operator -(const Landpoint& p1, const Landpoint& p2);
bool operator ==(const Landpoint& p1, const Landpoint& p2);
Landpoint operator *(const Landpoint& p, double scale);
/// <summary>
/// 向量A,B的夹角,角度
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns>角度制 0-360度逆时针</returns>
double getAngle(const Landpoint& a, const Landpoint& b);
/// <summary>
/// 点乘
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <returns></returns>
double dot(const Landpoint& p1, const Landpoint& p2);
double getlength(const Landpoint& p1);
Landpoint crossProduct(const Landpoint& a, const Landpoint& b);
struct DemBox {
double min_lat; //纬度
double min_lon;//经度
double max_lat;//纬度
double max_lon;//经度
};
/// <summary>
/// gdalImage图像操作类
/// </summary>
class gdalImage
{
public: // 方法
gdalImage(string raster_path);
~gdalImage();
void setHeight(int);
void setWidth(int);
void setTranslationMatrix(Eigen::MatrixXd gt);
void setData(Eigen::MatrixXd);
Eigen::MatrixXd getData(int start_row, int start_col, int rows_count, int cols_count, int band_ids);
void saveImage(Eigen::MatrixXd,int start_row,int start_col, int band_ids);
void saveImage();
void setNoDataValue(double nodatavalue,int band_ids);
int InitInv_gt();
Landpoint getRow_Col(double lon, double lat);
Landpoint getLandPoint(double i, double j, double ati);
double mean(int bandids=1);
double max(int bandids=1);
double min(int bandids=1);
GDALRPCInfo getRPC();
Eigen::MatrixXd getLandPoint(Eigen::MatrixXd points);
Eigen::MatrixXd getHist(int bandids);
public:
string img_path; // 图像文件
int height; // 高
int width; // 宽
int band_num;// 波段数
int start_row;//
int start_col;//
int data_band_ids;
Eigen::MatrixXd gt; // 变换矩阵
Eigen::MatrixXd inv_gt; // 逆变换矩阵
Eigen::MatrixXd data;
string projection;
};
gdalImage CreategdalImage(string img_path, int height, int width, int band_num, Eigen::MatrixXd gt, std::string projection, bool need_gt=true);
void clipGdalImage(string in_path, string out_path, DemBox box, double pixelinterval);
int ResampleGDAL(const char* pszSrcFile, const char* pszOutFile, double* gt, int new_width, int new_height, GDALResampleAlg eResample);
int ResampleGDALs(const char* pszSrcFile, int band_ids, GDALRIOResampleAlg eResample=GRIORA_Bilinear);
/////////////////////////////// 基本图像类 结束 //////////////////////////////////////////////////////////
string Convert(float Num);
std::string JoinPath(const std::string& path, const std::string& filename);
////////////////////////////// 坐标部分基本方法 //////////////////////////////////////////
/// <summary>
/// 将经纬度转换为地固参心坐标系
/// </summary>
/// <param name="XYZP">经纬度点--degree</param>
/// <returns>投影坐标系点</returns>
Landpoint LLA2XYZ(const Landpoint& LLA);
Eigen::MatrixXd LLA2XYZ(Eigen::MatrixXd landpoint);
/// <summary>
/// 将地固参心坐标系转换为经纬度
/// </summary>
/// <param name="XYZ">固参心坐标系</param>
/// <returns>经纬度--degree</returns>
Landpoint XYZ2LLA(const Landpoint& XYZ);
////////////////////////////// 坐标部分基本方法 //////////////////////////////////////////
/// <summary>
/// 计算地表坡度向量
/// </summary>
/// <param name="p0">固参心坐标系</param>
/// <param name="p1">固参心坐标系</param>
/// <param name="p2">固参心坐标系</param>
/// <param name="p3">固参心坐标系</param>
/// <param name="p4">固参心坐标系</param>
/// <returns>向量角度</returns>
//Landpoint getSlopeVector(Landpoint& p0, Landpoint& p1, Landpoint& p2, Landpoint& p3, Landpoint& p4, Eigen::MatrixXd UTC, double xp, double yp, double dut1, double dat);
Landpoint getSlopeVector(const Landpoint& p0, const Landpoint& p1, const Landpoint& p2, const Landpoint& p3, const Landpoint& p4);
////////////////////////////// 插值 ////////////////////////////////////////////
complex<double> Cubic_Convolution_interpolation(double u,double v,Eigen::MatrixX<complex<double>> img);
complex<double> Cubic_kernel_weight(double s);
double Bilinear_interpolation(Landpoint p0, Landpoint p11, Landpoint p21, Landpoint p12, Landpoint p22);
inline float cross2d(Point_3d a, Point_3d b) { return a.x * b.y - a.y * b.x; }
inline Point_3d operator-(Point_3d a, Point_3d b) {
return Point_3d{ a.x - b.x, a.y - b.y, a.z - b.z };
};
inline Point_3d operator+(Point_3d a, Point_3d b) {
return Point_3d{ a.x + b.x, a.y +b.y, a.z + b.z };
};
inline double operator/(Point_3d a, Point_3d b) {
return sqrt(pow(a.x,2)+ pow(a.y, 2))/sqrt(pow(b.x, 2)+ pow(b.y, 2));
};
inline bool onSegment(Point_3d Pi, Point_3d Pj, Point_3d Q)
{
if ((Q.x - Pi.x) * (Pj.y - Pi.y) == (Pj.x - Pi.x) * (Q.y - Pi.y) //叉乘
//保证Q点坐标在pi,pj之间
&& min(Pi.x, Pj.x) <= Q.x && Q.x <= max(Pi.x, Pj.x)
&& min(Pi.y, Pj.y) <= Q.y && Q.y <= max(Pi.y, Pj.y))
return true;
else
return false;
}
inline Point_3d invBilinear(Point_3d p, Point_3d a, Point_3d b, Point_3d c, Point_3d d)
{
Point_3d res ;
Point_3d e = b - a;
Point_3d f = d - a;
Point_3d g = a - b + c - d;
Point_3d h = p - a;
double k2 = cross2d(g, f);
double k1 = cross2d(e, f) + cross2d(h, g);
double k0 = cross2d(h, e);
double u, v;
// if edges are parallel, this is a linear equation
if (abs(k2) < 0.001)
{
v = -k0 / k1;
u = (h.x - f.x *v) / (e.x + g.x *v);
p.z = a.z + (b.z - a.z) * u + (d.z - a.z) * v + (a.z - b.z + c.z - d.z) * u * v;
return p;
}
// otherwise, it's a quadratic
else
{
float w = k1 * k1 - 4.0 * k0 * k2;
if (w < 0.0){
// 可能在边界上
if (onSegment(a, b, p)) {
Point_3d tt = b - a;
Point_3d ttpa = p - a;
double scater=ttpa / tt;
if(scater<0||scater>1){ return { -9999,-9999,-9999 }; }
p.z = a.z + scater * tt.z;
return p;
}
else if (onSegment(b, c, p)) {
Point_3d tt = c-b;
Point_3d ttpa = p - b;
double scater = ttpa / tt;
if (scater < 0 || scater>1) { return { -9999,-9999,-9999 }; }
p.z = b.z + scater * tt.z;
return p;
}
else if (onSegment(c, d, p)) {
Point_3d tt = d-c;
Point_3d ttpa = p - c;
double scater = ttpa / tt;
if (scater < 0 || scater>1) { return { -9999,-9999,-9999 }; }
p.z = c.z + scater * tt.z;
return p;
}
else if (onSegment(d, a, p)) {
Point_3d tt = a-d;
Point_3d ttpa = p - d;
double scater = ttpa / tt;
if (scater < 0 || scater>1) { return { -9999,-9999,-9999 }; }
p.z = d.z + scater * tt.z;
return p;
}
return { -9999,-9999,-9999 };
}
else {
w = sqrt(w);
float ik2 = 0.5 / k2;
float v = (-k1 - w) * ik2;
float u = (h.x - f.x * v) / (e.x + g.x * v);
if (u < 0.0 || u>1.0 || v < 0.0 || v>1.0)
{
v = (-k1 + w) * ik2;
u = (h.x - f.x * v) / (e.x + g.x * v);
}
p.z = a.z + (b.z - a.z) * u + (d.z - a.z) * v + (a.z - b.z + c.z - d.z) * u * v;
return p;
}
}
p.z = a.z + (b.z - a.z) * u + (d.z - a.z) * v + (a.z - b.z + c.z - d.z) * u * v;
return p;
}
//
// WGS84 到J2000 坐标系的变换
// 参考网址https://blog.csdn.net/hit5067/article/details/116894616
// 资料网址http://celestrak.org/spacedata/
// 参数文件:
// a. Earth Orientation Parameter 文件: http://celestrak.org/spacedata/EOP-Last5Years.csv
// b. Space Weather Data 文件: http://celestrak.org/spacedata/SW-Last5Years.csv
// 备注上述文件是自2017年-五年内
/**
在wgs84 坐标系转到J2000 坐标系 主要 涉及到坐标的相互转换。一般给定的WGS坐标为 给定时刻的 t ,BLH
转换步骤:
step 1: WGS 84 转换到协议地球坐标系
step 2: 协议地球坐标系 转换为瞬时地球坐标系
step 3: 瞬时地球坐标系 转换为 瞬时真天球坐标系
step 4: 瞬时真天球坐标系 转到瞬时平天球 坐标系
step 5: 瞬时平天球坐标系转换为协议天球坐标系J2000
**/
inline double sind(double degree) {
return sin(degree * d2r);
}
inline double cosd(double d) {
return cos(d * d2r);
}
/*
class WGS84_J2000
{
public:
WGS84_J2000();
~WGS84_J2000();
public:
// step1 WGS 84 转换到协议地球坐标系。
static Eigen::MatrixXd WGS84TECEF(Eigen::MatrixXd WGS84_Lon_lat_ait);
//step 2 协议地球坐标系 转换为瞬时地球坐标系
static Eigen::MatrixXd ordinateSingleRotate(int axis, double angle_deg);
// step 3 瞬时地球坐标系 转换为 瞬时真天球坐标系
// xyz= ordinateSingleRotate('z',-gst_deg)*earthFixedXYZ;
static int utc2gst(Eigen::MatrixXd UTC, double dUT1, double dAT, double& gst_deg, double& JDTDB);
// step 4 瞬时真天球坐标系 转到瞬时平天球 坐标系
static int nutationInLongitudeCaculate(double JD, double& epthilongA_deg, double& dertaPthi_deg, double& dertaEpthilong_deg, double& epthilong_deg);
// step5 瞬时平天球坐标系转换为协议天球坐标系J2000函数中 JDTDB 为给定时刻 的地球动力学时对应的儒略日,其计算方法由步骤三中的函数给出。
// xyz=ordinateSingleRotate('Z',zetaA)*ordinateSingleRotate('y',-thitaA)*ordinateSingleRotate('z',zA)*xyz;
static int precessionAngle(double JDTDB, double& zetaA, double& thitaA, double& zA);
// YMD2JD 同时 YMD2JD函数为 年月日转换为儒略日,具体说明 见公元纪年法(儒略历-格里高历转儒略日_${王小贱}的博客-CSDN博客_年积日计算公式
static double YMD2JD(double y, double m, double d);
static Eigen::MatrixXd WGS842J2000(Eigen::MatrixXd BLH_deg_m, Eigen::MatrixXd UTC, double xp, double yp, double dut1, double dat);
static Landpoint WGS842J2000(Landpoint LBH_deg_m, Eigen::MatrixXd UTC, double xp, double yp, double dut1, double dat);
public:
static std::string EOP_File_Path;
static std::string Space_Weather_Data;
// IAU2000模型有77项11列
static Eigen::Matrix<double, 77, 11> IAU2000ModelParams;
};
*/