// designsurveylinedlg.cpp : 实现文件
//

#include "stdafx.h"
#include "designsurveylinedlg.h"
#include "afxdialogex.h"


// DesignSurveyLineDlg 对话框

IMPLEMENT_DYNAMIC(DesignSurveyLineDlg, CBCGPDialog)

DesignSurveyLineDlg::DesignSurveyLineDlg(CWnd* pParent /*=NULL*/)
	: CBCGPDialog(DesignSurveyLineDlg::IDD, pParent)
{
	EnableVisualManagerStyle(TRUE, TRUE);

	bDrawRegion = false;

	lineID = 1;//测绘航线号
}

DesignSurveyLineDlg::~DesignSurveyLineDlg()
{
}

void DesignSurveyLineDlg::DoDataExchange(CDataExchange* pDX)
{
	CBCGPDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_BTN_SAVEREGION, m_btnSaveRegion);
}


BEGIN_MESSAGE_MAP(DesignSurveyLineDlg, CBCGPDialog)
	ON_BN_CLICKED(IDC_BTN_INPUTREGION, &DesignSurveyLineDlg::OnBnClickedBtnInputregion)
	ON_BN_CLICKED(IDC_BTN_DRAWREGION, &DesignSurveyLineDlg::OnBnClickedBtnDrawregion)
	ON_BN_CLICKED(IDC_BTN_SAVEREGION, &DesignSurveyLineDlg::OnBnClickedBtnSaveregion)
	ON_BN_CLICKED(IDC_BTN_BINDLINE, &DesignSurveyLineDlg::OnBnClickedBtnBindline)
	ON_BN_CLICKED(IDC_BTN_CALCULATELINE, &DesignSurveyLineDlg::OnBnClickedBtnCalculateline)
	ON_WM_CLOSE()
	ON_BN_CLICKED(IDC_BTN_CALCULATETIME, &DesignSurveyLineDlg::OnBnClickedBtnCalculatetime)
END_MESSAGE_MAP()

BOOL DesignSurveyLineDlg::OnInitDialog()
{
	CBCGPDialog::OnInitDialog();
	CenterWindow();
	GetDlgItem( IDC_BTN_CALCULATELINE )->EnableWindow( false );
	GetDlgItem( IDC_BTN_CALCULATETIME )->EnableWindow( false );
	SetDlgItemText(IDC_EDIT_FLYSPEED,"10");
	SetDlgItemText(IDC_EDIT_EXTERNALLENGTH,"0");

	return TRUE;
}

//提取没有后缀名的文件名
CString DesignSurveyLineDlg::extractFileName(CString fileName)
{
	// 查找最后一个点的位置
	int dotIndex = fileName.ReverseFind(_T('.'));

	// 如果找到了点,并且点不是第一个字符
	if (dotIndex != -1)
	{
		// 提取文件名,不包括后缀
		CString fileNameWithoutExtension = fileName.Left(dotIndex);
		return fileNameWithoutExtension;
	}
	else
	{
		// 如果没有找到点,说明没有后缀,直接显示文件名
		return fileName;
	}
}

//设置航测区域
void DesignSurveyLineDlg::SetSurveyRegion(const vector<double>& lons,const vector<double>& lats)
{
	surveyRegionLons.clear();
	surveyRegionLats.clear();
	for (int i=0;i<lons.size();++i)
	{
		surveyRegionLons.push_back(lons[i]);
		surveyRegionLats.push_back(lats[i]);
	}
	GetDlgItem( IDC_BTN_CALCULATELINE )->EnableWindow( true );
}

//计算测绘航线
void DesignSurveyLineDlg::calculateSurveyLine(double lineInterval,vector<double>&surveyLineLons,vector<double>& surveyLineLats,double outLength)
{
	vector<double> recLons;
	vector<double> recLats;
	TopologicalAnalysis analysis;
	GeoCompute geocompute;
	//计算外包矩形
	//analysis.GetBoundingBoxVertices(surveyRegionLons,surveyRegionLats,recLons,recLats);

	int startPt1 = analysis.getLineWithPolygonMinWidth(surveyRegionLons,surveyRegionLats);
	recLons.push_back(surveyRegionLons[startPt1]);
	recLons.push_back(surveyRegionLons[startPt1+1]);
	recLats.push_back(surveyRegionLats[startPt1]);
	recLats.push_back(surveyRegionLats[startPt1+1]);
	double flyAngle;//飞行航向
	CalculateTwoPtsAzimuth(flyAngle,surveyRegionLons[startPt1],surveyRegionLats[startPt1],surveyRegionLons[startPt1+1],surveyRegionLats[startPt1+1],3);
	//计算偏移航向
	Line2D line;
	line.p1.x = surveyRegionLons[startPt1];
	line.p1.y = surveyRegionLats[startPt1];
	line.p2.x = surveyRegionLons[startPt1 + 1];
	line.p2.y = surveyRegionLats[startPt1 + 1];
	Point2D p; //直线的下一个顶点
	if (startPt1+1 == (surveyRegionLons.size()-1)) //直线为多边形最后一条边
	{
		p.x = surveyRegionLons[1];
		p.y = surveyRegionLats[1];
	}
	else 
	{
		p.x = surveyRegionLons[startPt1 + 2];
		p.y = surveyRegionLats[startPt1 + 2];
	}
	int ptPos = analysis.pointPosition(p,line);
	if (ptPos == 1) //左侧
	{
		int i = (flyAngle + 270)/360;
		flyAngle = (flyAngle + 270) - 360*i;
	}
	else if(ptPos == -1) //右侧
	{
		int i = (flyAngle + 90)/360;
		flyAngle = (flyAngle + 90) - 360*i;
	}

	double lon1,lat1,lon2,lat2;
	//第一条切割线为航线间隔一半
	geocompute.computeOffsetGeoPosition(recLons[0],recLats[0],flyAngle,lineInterval/2000,lon1,lat1);
	geocompute.computeOffsetGeoPosition(recLons[1],recLats[1],flyAngle,lineInterval/2000,lon2,lat2);
	Point2D pt1,pt2;
	pt1.x = lon1;
	pt1.y = lat1;
	pt2.x = lon2;
	pt2.y = lat2;
	vector<Point2D> result;
	//交点个数
	int nCrossPt = analysis.linePolygonIntersections(pt1,pt2,surveyRegionLons,surveyRegionLats,result);

	while(nCrossPt>1){
		//平移切割线
		geocompute.computeOffsetGeoPosition(lon1,lat1,flyAngle,lineInterval/1000,lon1,lat1);
		geocompute.computeOffsetGeoPosition(lon2,lat2,flyAngle,lineInterval/1000,lon2,lat2);
		pt1.x = lon1;
		pt1.y = lat1;
		pt2.x = lon2;
		pt2.y = lat2;
		//计算交点
		nCrossPt = analysis.linePolygonIntersections(pt1,pt2,surveyRegionLons,surveyRegionLats,result);

	}
	
	int nlinePts = result.size();
	if (nlinePts%2!=0)
	{
		nlinePts--;
	}
	//计算外扩航点
	if (nlinePts>1 && outLength>0)
	{
		double angle;
		CalculateTwoPtsAzimuth(angle,result[0].x,result[0].y,result[1].x,result[1].y,3);
		//计算外扩航向
		double outAngle1,outAngle2;
		outAngle2 = angle;
		int n = (angle + 180)/360;
		outAngle1 = (angle + 180) - 360*n;
		geocompute.computeOffsetGeoPosition(result[1].x,result[1].y,outAngle2,outLength/1000,lon2,lat2);
		result[1].x = lon2;
		result[1].y = lat2;
		for (int i=2;i<nlinePts;i+=2)
		{
			geocompute.computeOffsetGeoPosition(result[i].x,result[i].y,outAngle1,outLength/1000,lon1,lat1);
			geocompute.computeOffsetGeoPosition(result[i+1].x,result[i+1].y,outAngle2,outLength/1000,lon2,lat2);
			result[i].x = lon1;
			result[i].y = lat1;
			result[i+1].x = lon2;
			result[i+1].y = lat2;
		}
	}
	//串联交点
	int j = 0;
	for (int i=0;i<nlinePts;i+=2)
	{
		if (j == 1)
		{
			surveyLineLons.push_back(result[i+1].x);
			surveyLineLons.push_back(result[i].x);
			surveyLineLats.push_back(result[i+1].y);
			surveyLineLats.push_back(result[i].y);
			j = 0;
			continue;
		}
		else if (j==0)
		{
			surveyLineLons.push_back(result[i].x);
			surveyLineLons.push_back(result[i+1].x);
			surveyLineLats.push_back(result[i].y);
			surveyLineLats.push_back(result[i+1].y);
			j=1;
			continue;
		}
	}
}

//保存测绘航线
void DesignSurveyLineDlg::saveSurveyLine(const vector<double>&surveyLineLons,const vector<double>& surveyLineLats,double height)
{
	//写航线
	CString filename;
	CString strRouteFileDir = GetSoftwareCurrentDirectory() + _T("\\Route\\") + _T("测绘航线\\");
	//测绘航线文件夹不存在则创建
	if (!SearchDirectory(strRouteFileDir))  
	{
		CreateDirectory(strRouteFileDir);
	}

	TCHAR s[10000];
	s[0]=0;
	CString defaultName = g_regionFileName + "-测绘航线.txt";
	CFileDialog dlg(FALSE, _T(".txt"), defaultName);
	dlg.m_ofn.lpstrTitle=_T("保存测绘航线文件");
/*
	dlg.m_ofn.lpstrFile=s;
	dlg.m_ofn.nMaxFile=sizeof(s)/sizeof(TCHAR);*/

	TCHAR filter[500]=_T("测绘航线文件(*.txt)\0*.txt\0");
	dlg.m_ofn.lpstrFilter=filter;
	dlg.m_ofn.Flags|=OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY|OFN_CREATEPROMPT;
	dlg.m_ofn.lpstrInitialDir = strRouteFileDir;

	if (IDOK == dlg.DoModal())
	{
		filename = dlg.GetPathName();
		g_linePathName = filename;
		g_lineFileName = extractFileName(dlg.GetFileName());

		FILE* fp = fopen(filename,"w");
		int iLineNum = lineID;
		fprintf(fp,"%d, 0, %.7f, %.7f, %.2f, 0, 00, 03\n", iLineNum, 0.0, 0.0, 0.0);
		int i = 0;
		for (i;i<surveyLineLons.size()-1;++i)
		{
			fprintf(fp,"%d, %d, %.7f, %.7f, %.2f, 0, 00, 03\n", iLineNum,i+1, surveyLineLons[i], surveyLineLats[i], height);
		}
		fprintf(fp,"%d, %d, %.7f, %.7f, %.2f, 0, 02, 01\n", iLineNum,i+1, surveyLineLons[i], surveyLineLats[i], height);
		fclose(fp);
	}else
	{
		return;
	}

}

//保存航测区域
bool DesignSurveyLineDlg::saveSurveyRegion(const vector<double>&surveyRegionLons,const vector<double>& surveyRegionLats)
{
	//写航线
	CString filename;
	CString strRouteFileDir = GetSoftwareCurrentDirectory() + _T("\\Route\\") + _T("测绘航线\\");
	//测绘航线文件夹不存在则创建
	if (!SearchDirectory(strRouteFileDir))  
	{
		CreateDirectory(strRouteFileDir);
	}

	TCHAR s[10000];
	s[0]=0;
	CFileDialog dlg(FALSE, _T(".route"), _T("测绘区域1.route"));
	dlg.m_ofn.lpstrTitle=_T("保存测绘区域文件");
/*
	dlg.m_ofn.lpstrFile=s;
	dlg.m_ofn.nMaxFile=sizeof(s)/sizeof(TCHAR);*/

	TCHAR filter[500]=_T("测绘区域文件(*.route)\0*.route\0");
	dlg.m_ofn.lpstrFilter=filter;
	dlg.m_ofn.Flags|=OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY|OFN_CREATEPROMPT;
	dlg.m_ofn.lpstrInitialDir = strRouteFileDir;

	if (IDOK == dlg.DoModal())
	{
		filename = dlg.GetPathName();
		g_regionPathName = filename;
		g_regionFileName = extractFileName(dlg.GetFileName());

		FILE* fp = fopen(filename,"w");
		int iLineNum = lineID;
		fprintf(fp,"%d, 0, %.7f, %.7f, %.2f, 0, 00, 03\n", iLineNum, 0.0, 0.0, 0.0);
		int i = 0;
		for (i;i<surveyRegionLons.size()-2;++i)
		{
			fprintf(fp,"%d, %d, %.7f, %.7f, %.2f, 0, 00, 03\n", iLineNum,i+1, surveyRegionLons[i], surveyRegionLats[i], 0.0);
		}
		fprintf(fp,"%d, %d, %.7f, %.7f, %.2f, 0, 03, 01\n", iLineNum,i+1, surveyRegionLons[i], surveyRegionLats[i], 0.0);
		fclose(fp);
		return true;
	}else
	{
		return false;
	}
}
// DesignSurveyLineDlg 消息处理程序

//导入航测区
void DesignSurveyLineDlg::OnBnClickedBtnInputregion()
{
	//写航线
	CString filename;
	CString strRouteFileDir = GetSoftwareCurrentDirectory() + _T("\\Route\\") + _T("测绘航线\\");
	
	TCHAR s[10000];
	s[0]=0;
	CFileDialog dlg(TRUE);
	dlg.m_ofn.lpstrTitle=_T("打开航测区域文件");
	dlg.m_ofn.lpstrFile=s;
	dlg.m_ofn.nMaxFile=sizeof(s)/sizeof(TCHAR);

	TCHAR filter[500]=_T("航测区域文件(*.txt)\0*.txt\0所有文件(*.*)\0*.*\0");
	dlg.m_ofn.lpstrFilter=filter;
	dlg.m_ofn.Flags|=OFN_HIDEREADONLY;
	dlg.m_ofn.lpstrInitialDir = strRouteFileDir;

	// 显示对话框并获取用户的选择
	if (dlg.DoModal() == IDOK)
	{
		// 获取选择的文件路径
		CString filePath = dlg.GetPathName();
		g_regionPathName = filePath;
		g_regionFileName = extractFileName(dlg.GetFileName());

		char* path = filePath.GetBuffer();
		//发送消息到主程序,进行显示
		if (g_mapHwnd != NULL)
		{
			::SendMessage(g_mapHwnd, WM_SEND_SHOWSURVEYREGION, (WPARAM)path, 0);
		}
		GetDlgItem( IDC_BTN_CALCULATELINE )->EnableWindow( true );
	}
	else
	{
		return;
	}
}

//绘制航测区
void DesignSurveyLineDlg::OnBnClickedBtnDrawregion()
{
	bDrawRegion = true;
}

//保存航测区
void DesignSurveyLineDlg::OnBnClickedBtnSaveregion()
{
	m_btnSaveRegion.EnableWindow(false);
	if (saveSurveyRegion(surveyRegionLons,surveyRegionLats))
	{
		char* path = g_regionPathName.GetBuffer();
		//发送消息到主程序,进行标绘
		if (g_mapHwnd != NULL)
		{
			::SendMessage(g_mapHwnd, WM_SEND_SHOWSURVEYREGION, (WPARAM)path, 0);
		}
	}
	m_btnSaveRegion.EnableWindow(true);
}

//装订测绘航线
void DesignSurveyLineDlg::OnBnClickedBtnBindline()
{
	//发送消息到主程序,进行标绘
	if (g_mapHwnd != NULL)
	{
		::SendMessage(g_mapHwnd, WM_BIND_SURVEYLINE, (WPARAM)lineID, 0);
	}
}

//生成航测航线
void DesignSurveyLineDlg::OnBnClickedBtnCalculateline()
{
	if (surveyRegionLats.size()<3)
	{
		BCGPMessageBox("航测区域无效或缺少航测区域!");
		return;
	}

	CString cstr;
	GetDlgItemText(IDC_EDIT_HEIGHT,cstr);
	double height = _ttof(cstr);
	if (height<=0||height>500)
	{
		BCGPMessageBox("航高范围为(0,500]m!");
		return;
	}
	GetDlgItemText(IDC_EDIT_LINEINTERVAL,cstr);
	double lineInterval = _ttof(cstr);
	if (lineInterval < 1 )
	{
		BCGPMessageBox("航线间隔必须大于1m");
		return;
	}

	GetDlgItemText(IDC_EDIT_EXTERNALLENGTH,cstr);
	double outLength = _ttof(cstr);
	if (outLength < 0 )
	{
		BCGPMessageBox("外扩长度必须大于0m");
		return;
	}

	g_Height = height;
	//测绘航线坐标
	vector<double> surveyLineLons;
	vector<double> surveyLineLats;
	//计算航测航线
	calculateSurveyLine(lineInterval,surveyLineLons,surveyLineLats,outLength);
	//保存航测航线
	saveSurveyLine(surveyLineLons,surveyLineLats,height);
	//发送消息到主程序,进行标绘
	if (g_mapHwnd != NULL)
	{
		char* path = g_linePathName.GetBuffer();
		::SendMessage(g_mapHwnd, WM_SEND_SHOWSURVEYLINE, (WPARAM)path, 0);
	}

	//计算航程
	g_RouteLength = calculateRouteLength(surveyLineLons,surveyLineLats);
	cstr.Format("%d",int(g_RouteLength));
	cstr += "m";
	((CStatic*)GetDlgItem(IDC_TXT_ROUTELENGTH))->SetWindowTextA(cstr);

	GetDlgItem( IDC_BTN_CALCULATETIME )->EnableWindow( true );
}

void DesignSurveyLineDlg::OnClose()
{
	CBCGPDialog::OnClose();

	//发送消息到主程序,进行显示
	if (g_mapHwnd != NULL)
	{
		::SendMessage(g_mapHwnd, WM_CLEAR_TMPSURVEYFEATURE, 0, 0);
	}
}

//计算航程(m)
double DesignSurveyLineDlg::calculateRouteLength(const vector<double>&surveyLineLons,const vector<double>& surveyLineLats)
{
	double sum = 0;
	for (int i=0;i<surveyLineLons.size()-1;++i)
	{
		double dist;
		CalculateTwoPtsDistance(dist,surveyLineLons[i],surveyLineLats[i],surveyLineLons[i+1],surveyLineLats[i+1],3);
		sum += dist;
	}
	return sum;
}

//航时计算
void DesignSurveyLineDlg::OnBnClickedBtnCalculatetime()
{
	CString cstr;
	GetDlgItemText(IDC_EDIT_FLYSPEED,cstr);
	double speed = _ttof(cstr);
	if (speed<1||speed>15)
	{
		BCGPMessageBox("飞行速度为[1,15]m/s!");
		return;
	}

	int flyTime = g_RouteLength / speed;
	int hours = flyTime/3600;
	flyTime %= 3600; // 剩余秒数
	int minutes = flyTime / 60; // 剩余秒数除以60得到分钟数
	int seconds = flyTime % 60; // 最后剩余的秒数
	cstr.Format("%d时%d分%d秒",hours,minutes,seconds);
	((CStatic*)GetDlgItem(IDC_TXT_FLYTIME))->SetWindowTextA(cstr);
}