#pragma once
#include "BaseTool.h"
///
/// 
//#define EIGEN_USE_MKL_ALL
//#define EIGEN_VECTORIZE_SSE4_2
//#include <mkl.h>

#include "referenceHeader.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"


#include "baseTool.h"
using namespace std;
using namespace Eigen;
 



QString getCurrentTimeString() {
	struct tm ConversionTime;
	std::time_t t = std::time(NULL);
	char mbstr[100];
	_localtime64_s(&ConversionTime, &t);
	std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %H:%M:%S", &ConversionTime);
	QString strTime = mbstr;
	return strTime;
}

QString getCurrentShortTimeString() {
	struct tm ConversionTime;
	std::time_t t = std::time(NULL);
	char mbstr[100];
	_localtime64_s(&ConversionTime, &t);
	std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %H:%M:%S", &ConversionTime);
	QString strTime = mbstr;
	return strTime;
}

std::vector<QString> splitString(const QString& str, char delimiter)
{
	QStringList tokens = str.split(delimiter);
	return convertQStringListToStdVector(tokens);
}


complex<double> Cubic_Convolution_interpolation(double u, double v, Eigen::MatrixX<complex<double>> img)
{
	if (img.rows() != 4 || img.cols() != 4) {
		throw exception("the size of img's block is not right");
	}
	// 斤拷锟斤拷模锟斤拷
	Eigen::MatrixX<complex<double>> wrc(1, 4);// 使锟斤拷 complex<double> 斤拷锟斤拷要原斤拷为锟剿伙拷取值
	Eigen::MatrixX<complex<double>> wcr(4, 1);//
	for (int i = 0; i < 4; i++) {
		wrc(0, i) = Cubic_kernel_weight(u + 1 - i); // u+1,u,u-1,u-2
		wcr(i, 0) = Cubic_kernel_weight(v + 1 - i);
	}

	Eigen::MatrixX<complex<double>> interValue = wrc * img * wcr;
	return interValue(0, 0);
}

complex<double> Cubic_kernel_weight(double s)
{
	s = abs(s);
	if (s <= 1) {
		return complex<double>(1.5 * s * s * s - 2.5 * s * s + 1, 0);
	}
	else if (s <= 2) {
		return complex<double>(-0.5 * s * s * s + 2.5 * s * s - 4 * s + 2, 0);
	}
	else {
		return complex<double>(0, 0);
	}
}

/// <summary>
///  p11  p12 -- x 
///    p0(u,v)
///  p21  p22
///   |
///   y
/// p11(0,0)
/// p21(0,1)
/// P12(1,0)
/// p22(1,1)
/// </summary>
/// <param name="p0">x,y,z</param>
/// <param name="p1">x,y,z</param>
/// <param name="p2">x,y,z</param>
/// <param name="p3">x,y,z</param>
/// <param name="p4">x,y,z</param>
/// <returns></returns>
double Bilinear_interpolation(Landpoint p0, Landpoint p11, Landpoint p21, Landpoint p12, Landpoint p22)
{

	return	p11.ati * (1 - p0.lon) * (1 - p0.lat) +
		p12.ati * p0.lon * (1 - p0.lat) +
		p21.ati * (1 - p0.lon) * p0.lat +
		p22.ati * p0.lon * p0.lat;
}



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;
}

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;
}

double sind(double degree)
{
	return sin(degree * d2r);
}

double cosd(double d)
{
	return cos(d * d2r);
}


string Convert(float Num)
{
	ostringstream oss;
	oss << Num;
	string str(oss.str());
	return str;
}
 
QString JoinPath(const QString& path, const QString& filename)
{
	QDir dir(path);

	// Ensure the path ends with the appropriate separator
	if (!QDir::isAbsolutePath(path))
		dir.makeAbsolute();

	return dir.filePath(filename);
}
std::vector<QString> convertQStringListToStdVector(const QStringList& qStringList)
{
	std::vector<QString> stdVector;

	for (const QString& str : qStringList) {
		stdVector.push_back(str);
	}

	return stdVector;
};