#pragma once
/*****************************************************************//**
 * \file   SARSatelliteSimulationAbstractCls.h
 * \brief  定义SAR卫星仿真整个流程中得抽象模型,并定义一些常用的结构体
 *	主要包含
 * 
 * 1. 卫星坐标状态
 * 2. 卫星天线指向状态（扫描角、指向）
 * 3. 卫星天线方向图（以 以天线指向为0度，Z->Y ： theta , X->Y phi )
 * 4. 卫星参数(频率、带宽、快时间、PRF、Fs)
 * 天线方向图 ： phi=0 与 X轴飞行方向一致，此时 G(phi)>G(theta) 即 G(V)>G(H) 水平极化 
 * 天线方向图 ： phi=90 与 y轴飞行方向一致，此时 G(phi)<G(theta) 即 G(V)<G(H) 垂直极化
 * \author 陈增辉
 * \date   October 2024
 *********************************************************************/
#include "BaseConstVariable.h"
#include "LogInfoCls.h"
#include <QString>
#include <vector>
#include <Eigen/Core>
#include <Eigen/Dense>
#include "GeoOperator.h"

 
/// <summary>
/// 天线方向图的获取
/// 注意这里使用 双线性插值
/// </summary>
class AbstractRadiationPattern {
public:
	AbstractRadiationPattern();
	virtual ~AbstractRadiationPattern();
public:
	virtual double getGain(double theta, double phi);
	virtual std::vector<RadiationPatternGainPoint> getGainList();
	virtual ErrorCode getGain(double& theta, double& phi, double& GainValue);
	virtual ErrorCode getGainLinear(double& theta, double& phi, double& GainValue);
	double getGainLearThetaPhi(double theta, double phi);
	virtual ErrorCode setGain(double theta, double phi, double GainValue);
	virtual ErrorCode RecontructGainMatrix(double threshold=-3);
	virtual std::vector<double> getThetas();
	virtual std::vector<double> getPhis();
	virtual Eigen::MatrixXd getGainMatrix();
	virtual double getMaxTheta();
	virtual double getMinTheta();
	virtual double getMaxPhi();
	virtual double getMinPhi();


private:
	std::vector<RadiationPatternGainPoint> GainMap; // 天线方向图
	std::vector<double> thetas;
	std::vector<double> phis;
	Eigen::MatrixXd GainMatrix;
	double maxGain, maxThetaGain, maxPhiGain;
	double mintheta, maxtheta, minphi, maxphi;
	double EdgethetaMin, EdgethetaMax;
	double EdgeXMin, EdgeXMax;
};




/// <summary>
/// 卫星轨道模型，与姿态控制
/// 如无特别说明，所有角度都是弧度制
/// 如果没有特别说明，卫星天线坐标系参考GF3:
/// 天线展开放方向轴为X轴，
/// X轴定义为： 天线摆动角为0时，卫星飞行方向
/// Z轴定义为纵向，理论上 Z轴应该为天线指向方向
/// H 极化定义为 垂直极化，Z->X 平面
/// V 极化定义为 水平极化，Z->Y 平面
///			     -Z
///				 |
///  [=====]X<---Y---[======]    
///				 _
///				___
///			   _____   
///          _________
///		
/// 
/// 
///			   -Z	
///			   ^	   
///		       |
///		X<-Fly-Y
///		       _
///		      ___
///		    _______
/// 
/// 左右视
///           左视(+）				        右视（-）
///      Z				  Z					            Z		
/// 	 ^				   \						   /
/// 	 |					\						  /
///  x<--O---			 x<--O---				 x<--O---
///      |				     |\    				    /|    
/// 						   \				   /  	
/// 
/// 
///   X=Y x Z          摆动角(-）				    摆动角（+）
///      Z				  Z					            Z		
/// 	 ^				   \						   /
/// 	 |					\						  /
///  y<--X---			 y<--X---				 y<--X---
///      |				     |\    				    /|    
/// 						   \				   /  	
///  注：多普勒时间按照《合成孔径雷达成像算法与实现，cumming》中，前视为 - ，后视为 + 
/// 
/// </summary>
class AbstractSatelliteOribtModel {

public:
	virtual ~AbstractSatelliteOribtModel();

public: // 卫星轨道节点
	virtual SatelliteOribtNode getSatelliteOribtNode(double& timeFromStartTime,bool& antAzAngleFlag); // 获取轨道节点
	virtual ErrorCode getSatelliteOribtNode(double& timeFromStartTime, SatelliteOribtNode& node, bool& antAzAngleFlag); // 获取轨道节点
	virtual ErrorCode getSatelliteAntDirectNormal(SatelliteOribtNode& Rs, Vector3D& Rt, SatelliteAntDirect& antNode); // 计算目标在天线方向图中的位置

public: // 卫星轨道模型的参考时间节点
	virtual void setSatelliteOribtStartTime(long double oribtStartTime);// 设置卫星模型参考时间
	virtual long double  getSatelliteOribtStartTime();// 获取卫星模型参考时间
public: // 入射角相关参数
	virtual void setbeamAngle(double beamAngle,bool RightLook);// 设置波位角

public: // 天线摆动角相关参数
	virtual void setAzAngleRange(double cycletime,double minAzAngle,double maxAzAngle,double referenceAzAngle, double referenceTimeFromStartTime);//方位角变换循环时间 ;方位角变换范围； 特定时间的方位角，用于计算方位角变化情况
	virtual double getAzAngleInCurrentTimeFromStartTime(double& currentTime);// 获取当前时间的 天线摆动角
	virtual ErrorCode getAzAngleInCurrentTimeFromStartTime(double& currentTime, double& AzAngle);// 获取当前时间的 天线摆动角
public: // 定义在原始天线坐标下的天线坐标系的调整，其中仍然定义-Z 轴为 天线指向方向 
	virtual void setAntnnaAxisX(double X,double Y,double Z); // 设置天线X轴指向 
	virtual void setAntnnaAxisY(double X, double Y, double Z); // 设置天线X轴指向
	virtual void setAntnnaAxisZ(double X, double Y, double Z); // 设置天线X轴指向
	virtual ErrorCode getZeroDopplerAntDirect(SatelliteOribtNode& node);// 获取0多普勒天线方向
	virtual ErrorCode getAntnnaDirection( SatelliteOribtNode &node); // 获取天线指向方向
public:
	virtual double getPt();
	virtual double getGri();
	virtual void setPt(double Pt);
	virtual void setGri(double gri);
};




/// <summary>
/// SAR卫星的相关信息
/// 1. 坐标系统为 WGS84，坐标单位是 米，时间单位是： 秒
/// 2. 注意一般来说PRF图像行数相关，Fs 与 图像列数是相关得
/// 3. 
/// </summary>
class AbstractSARSatelliteModel
{
public: // 轨道模型
	virtual SatelliteOribtNode getSatelliteOribtNode(double& timeFromStartTime, bool& antAzAngleFlag);// 设置轨道节点，
	virtual ErrorCode getSatelliteOribtNode(double& timeFromStartTime, SatelliteOribtNode& node, bool& antAzAngleFlag); // 获取轨道节点
	virtual ErrorCode getSatelliteAntDirectNormal(SatelliteOribtNode& Rs, Vector3D& Rt, SatelliteAntDirect& antNode); // 计算目标在天线方向图中的位置
	virtual void	 setSatelliteOribtModel(std::shared_ptr<AbstractSatelliteOribtModel>  model); // 设置轨道模型
public:// 影像成像时间
	virtual void setSARImageStartTime(long double imageStartTime);// 成像开始时间
	virtual void setSARImageEndTime(long double imageEndTime);	  // 成像结束时间
	
	virtual double getSARImageStartTime();
	virtual double getSARImageEndTime();

	virtual double getNearRange(); // 近斜距 -- 快时间门
	virtual void   setNearRange(double NearRange);

	virtual double getFarRange(); // 最远斜距 
	virtual void   setFarRange(double FarRange);

	virtual bool   getIsRightLook() ; // 是否右视
	virtual void   setIsRightLook(bool isR) ;
public: // 成像参数
	virtual void	setCenterFreq(double Freq); // 中心频率
	virtual double	getCenterFreq();

	virtual void	setCenterLamda(double Lamda); // 波长
	virtual double  getCenterLamda();

	virtual void	setBandWidth(double bandwidth); // 带宽范围
	virtual double	getBandWidth();

	virtual QVector<double> getFreqList(); // 获取频点列表
	virtual void setRefphaseRange(double refRange);
	virtual double getRefphaseRange();

	virtual POLARTYPEENUM getPolarType();// 极化类型
	virtual void	setPolarType(POLARTYPEENUM type);
public: // 设置PRF、FS
	virtual void setPRF(double prf); // 方位向采样频率
	virtual double getPRF();

	virtual double getFs(); // 距离向采样频率
	virtual void setFs(double fs);

	virtual double getCenterLookAngle() ;
	virtual void setCenterLookAngle(double angle) ;
public:// 天线方向图
	virtual void setTransformRadiationPattern(std::shared_ptr<AbstractRadiationPattern> radiationPanttern); //  极化发射方向图
 	virtual void setReceiveRadiationPattern(std::shared_ptr<AbstractRadiationPattern> radiationPanttern); // V 极化接收方向图

	virtual std::shared_ptr<AbstractRadiationPattern> getTransformRadiationPattern();// H 极化发射方向图 
	virtual std::shared_ptr<AbstractRadiationPattern> getReceiveRadiationPattern();// V 极化发射方向图 

public:
	virtual double getPt();
	virtual double getGri();
	virtual void setPt(double Pt);
	virtual void setGri(double gri);

private:
	double DopplerParametersReferenceTime;
	std::vector<double> DopplerCentroidCoefficients;
	std::vector<double> DopplerRateValuesCoefficients;

public:
	virtual double getDopplerParametersReferenceTime()  ;
	virtual void   setDopplerParametersReferenceTime(double time)  ;
	virtual std::vector<double> getDopplerCentroidCoefficients()  ;
	virtual void				setDopplerCentroidCoefficients(std::vector<double> DopplerCentroids)  ;
	virtual std::vector<double> getDopplerRateValuesCoefficients()  ;
	virtual void				setDopplerRateValuesCoefficients(std::vector<double>  DopplerRateValues)  ;


};


/** 通用函数 ************************************************************************** */


/// <summary>
/// 从xml文件中读取卫星集合坐标节点
/// </summary>
/// <param name="xmlPath"></param>
/// <param name="nodes"></param>
/// <returns></returns>
ErrorCode ReadSateGPSPointsXML(QString xmlPath, std::vector<SatelliteOribtNode>& nodes);
std::vector<SatelliteOribtNode> FilterSatelliteOribtNode(std::vector<SatelliteOribtNode>& nodes, double startTime, double endTime,long minCount=10);
std::shared_ptr<AbstractRadiationPattern> CreateAbstractRadiationPattern(std::vector<RadiationPatternGainPoint> antPatternPoints);

std::vector<RadiationPatternGainPoint> ReadGainFile(QString antPatternFilePath);


/** 天线方向图文件展示 ********************************************************************** */








/**  多普勒频率计算相关内容 ********************************************************************** */
/**
 * 参考资料
 * 合成孔径雷达成像算法与实现，cumming 洪文译, 第四章 合成孔径的概念
 * 雷达信号处理基础，Mark A.Richards,邢孟道译
 * 合成孔径雷达成像原理，皮亦鸣
 * InSAR原理与应用，刘国祥
 * 弹载SAR回波信号仿真研究，林江红
 * 星载合成孔径雷达原始回波数据模拟研究，吕辉 
 * SAR回波仿真信号生成算法的性能比较研究，韦立登
 * 星载合成孔径雷达影像正射校正方法研究，陈尔学
 * 注：吕辉 多普勒计算公式 与 陈尔学的多普勒计算公式存在差异，中间省略了一些变换过程
 * .
 */

// 多普勒中心频率
double  getDopplerCenterFreq(double &lamda,double &R,Vector3D &Rs,Vector3D &Rt,Vector3D &Vs,Vector3D &Vt);

// 多普勒调频率（斜率）
double  getDopplerFreqRate(double& lamda, double& R, Vector3D& Rs, Vector3D& Rt, Vector3D& Vs, Vector3D& Vt,Vector3D &Ast);














