You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
GCS-GISControlDlg-for-981A-.../DlgLightRegion.cpp

2304 lines
63 KiB
C++

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.

// DlgLightRegion.cpp : 实现文件
//
#include "stdafx.h"
#include "DlgLightRegion.h"
#include "afxdialogex.h"
#include "MapElevation.h"
#include<io.h>
MapElevation m_mapElevation2;
HWND g_hwndDlgLight = nullptr;
//计算地球上两点间的斜率(假定地球是圆的)
double CalSlopeBetweenTwoPoint(const double fromPtLon, const double fromPtLat, const float fromPtAlt, const double endPtLon, const double endPtLat, const float endPtAlt)
{
double _distance = 0.0;
CalculateTwoPtsDistance(_distance,fromPtLon,fromPtLat,endPtLon,endPtLat,3);
//考虑大气折射等原因地球半径乘以系数4/3作为等效半径
double _radiusEarth = 6371137.0 * 4/3;
//求解两点在地球表面的投影点连成的弧线对应的圆心角,单位为弧度
double _centralAngle = _distance/_radiusEarth;
double _slope = 0.0,d1 = 0.0, d2 = 0.0;
//从起始点处水平看向终点处,能看到的终点的高度
double _compareAlt = ((_radiusEarth + fromPtAlt)/cos(_centralAngle) - _radiusEarth);
//斜率为正
if ( _compareAlt < endPtAlt)
{
_compareAlt = endPtAlt - _compareAlt;
d1 = _compareAlt * cos(_centralAngle);
d2 = (_radiusEarth + fromPtAlt) * tan(_centralAngle) + _compareAlt * sin(_centralAngle);
_slope = d1/d2;
}
else //斜率为负
{
_compareAlt = _compareAlt - endPtAlt;
d1 = _compareAlt * cos(_centralAngle);
d2 = (_radiusEarth + fromPtAlt) * tan(_centralAngle) - _compareAlt * sin(_centralAngle);
_slope = -d1/d2;
}
return _slope;
}
//已知地球A点经纬度高以及B点和A点连线相对于水平方向的斜率求B点的高度
double CalAltFromSlope(const double fromPtLon, const double fromPtLat, const float fromPtAlt, const double endPtLon, const double endPtLat,const double slope)
{
double _distance = 0.0;
CalculateTwoPtsDistance(_distance,fromPtLon,fromPtLat,endPtLon,endPtLat,3);
//考虑大气折射等原因地球半径乘以系数4/3作为等效半径
double _radiusEarth = 6371137.0 * 4/3;
//求解两点在地球表面的投影点连成的弧线对应的圆心角,单位为弧度
double _centralAngle = _distance/_radiusEarth;
double endPtAlt = 0.0;
if (slope > 0.0)
{
endPtAlt = (_radiusEarth + fromPtAlt) * tan(_centralAngle) * slope / (cos(_centralAngle)-(sin(_centralAngle)*slope));
endPtAlt = ((_radiusEarth + fromPtAlt)/cos(_centralAngle) - _radiusEarth) + endPtAlt;
}
else
{
endPtAlt = (_radiusEarth + fromPtAlt) * tan(_centralAngle) * (-slope) / (cos(_centralAngle)+(sin(_centralAngle)*(-slope)));
endPtAlt = ((_radiusEarth + fromPtAlt)/cos(_centralAngle) - _radiusEarth) - endPtAlt;
}
return endPtAlt;
}
/*-------------------------------------------------------------------------------------------------------------
说明:可视域分析
-------------------------------------------------------------------------------------------------------------*/
//可视域分析线程开启标志
volatile bool m_bRunRegion = false;
double g_dGroundLonTemp = 0.0; //地面站经度
double g_dGroundLatTemp = 0.0; //地面站纬度
float g_fGroundAltTemp = 0.0; //地面站高度
int g_iFlightAlt = 0; //飞行高度
int g_iRegionRadius = 0; //分析半径
int g_iAnalysisStep = 0; //分析角度
//线程函数,处理可视域分析
void ThreadFuncLightRegion()
{
while(m_bRunRegion)
{
//依次完成地面站0~360度方向的通视分析每执行一次分析1度
if ((g_iAnalysisStep >= 0) && (g_iAnalysisStep < 360))
{
if (false == AnalysisLightRegion(g_iAnalysisStep,g_iRegionRadius))
{
//高程信息不全,终止分析
g_iAnalysisStep = -1;
m_bRunRegion = false;
//发送消息到对话框,提示高程信息不全
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)1,(LPARAM)-1);
continue ;
}
else
{
//发送消息到对话框,更新可视域分析进度
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)1,(LPARAM)g_iAnalysisStep);
}
g_iAnalysisStep++;
}
else if (360 == g_iAnalysisStep)
{
//终止分析
g_iAnalysisStep = -1;
g_structPointNotVisible[360] = g_structPointNotVisible[0];
//通视分析后,需要将最外侧的圆逆时针逐个加入不可视区域图层,这样才能形成一个闭合的不可视区域
for (int i=360;i>=0;i--)
{
structPoint _structPoint;
CalculatePtCoordinate(_structPoint.lon,_structPoint.lat,g_dGroundLonTemp,g_dGroundLatTemp,i,g_iRegionRadius*1000,3);
g_structPointNotVisible[720 - i + 1] = _structPoint;
}
//发送到地图,绘制可视域
::PostMessage(g_mapHwnd,WM_SHOW_NOTVISIBLE,0,0);
::PostMessage(g_mapHwnd,WM_SHOW_ISVISIBLE,0,0);
m_bRunRegion = false;
}
Sleep(10);
}
}
//给定飞行高度进行通视分析并在地图上标绘可视域iAngle 角度iRadius 距离
bool AnalysisLightRegion(int iAngle, int iRadius)
{
double dTanMaxAngle = 0.0; //最小通视角度
double fMinLightAlt = 0.0; //最小通视高度
//采样点位置
double interPolLon = 0.0, interPolLat = 0.0;
float interPolHight = 0.0;
//中间变量
double _tempAngle = 0.0; //当前点与地面站的连线 与水平方向的夹角
structPoint _structPoint;
//以60为采样间距计算插值个数
int interPolDis = 60;
int interPolNum = (iRadius*1000)/interPolDis;
for(int i = 1; i <= interPolNum; i++)
{
CalculatePtCoordinate(interPolLon, interPolLat, g_dGroundLonTemp, g_dGroundLatTemp, iAngle, i*interPolDis, 3);
//获取采样点的高程
if(!m_mapElevation2.getElevation(interPolHight, interPolLon, interPolLat))
{
//未获取到高程值
return false;
}
_tempAngle = CalSlopeBetweenTwoPoint(g_dGroundLonTemp, g_dGroundLatTemp, g_fGroundAltTemp, interPolLon, interPolLat, interPolHight);
dTanMaxAngle = max(_tempAngle,dTanMaxAngle);
fMinLightAlt = (float)CalAltFromSlope(g_dGroundLonTemp, g_dGroundLatTemp, g_fGroundAltTemp, interPolLon, interPolLat, dTanMaxAngle);
//给定飞行高度,判断是否可通视,若遇到第一个不通视的点,认为此点是通视与不通视的分割点,直接返回
if (g_iFlightAlt < fMinLightAlt)
{
_structPoint.lon = interPolLon;
_structPoint.lat = interPolLat;
g_structPointVisible[iAngle] = _structPoint;
g_structPointNotVisible[iAngle] = _structPoint;
return true;
}
}
CalculatePtCoordinate(_structPoint.lon,_structPoint.lat,g_dGroundLonTemp,g_dGroundLatTemp,iAngle,g_iRegionRadius*1000,3);
g_structPointVisible[iAngle] = _structPoint;
g_structPointNotVisible[iAngle] = _structPoint;
return true;
}
/*-------------------------------------------------------------------------------------------------------------
说明:实时通视检测
-------------------------------------------------------------------------------------------------------------*/
//实时通视检测线程开启标志
volatile bool m_bRunDetect = false;
double g_dRealTime_GCSlon = 0.0; //地面站经度
double g_dRealTime_GCSlat = 0.0; //地面站纬度
float g_fRealTime_GCSalt = 0.0f; //地面站高度
double g_dRealTime_UavAlt = 0.0; //无人机高度
double g_dRealTime_AngToGCS = 0.0; //地面站-飞机方位
double g_dRealTime_DisToGCS = 0.0; //地面站-飞机距离
double g_dRealTime_MinAngle = 0.0;
double g_dRealTime_AngleDiff = 0.0;
int g_iRealTime_CurStep = -1;
int g_iPointNumInLayer = 0; //实时通视检测中分析的点数
//线程函数,处理实时通视检测
void ThreadFuncRealTimeDetection()
{
while(m_bRunDetect)
{
if (-1 == g_iRealTime_CurStep)
{
continue;
}
if (g_iRealTime_CurStep <= 12)
{
if (false == AnalysisVisiArea(g_dRealTime_UavAlt, g_dRealTime_MinAngle+g_iRealTime_CurStep*g_dRealTime_AngleDiff, g_dRealTime_DisToGCS-3000, g_dRealTime_DisToGCS+3000, g_dRealTime_GCSlon, g_dRealTime_GCSlat))
{
g_iRealTime_CurStep = -1;
//发送消息到对话框,提示高程信息不全
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)2,(LPARAM)-1);
continue;
}
g_iRealTime_CurStep++;
}
if (g_iRealTime_CurStep == (12 + 1))
{
g_iRealTime_CurStep++;
}
if (g_iRealTime_CurStep == (12 + 2))
{
for (int i=0; i<=12;i++)
{
g_iPointNumInLayer++;
structPoint _structPoint;
CalculatePtCoordinate(_structPoint.lon, _structPoint.lat, g_dRealTime_GCSlon, g_dRealTime_GCSlat, g_dRealTime_MinAngle+(12-i)*g_dRealTime_AngleDiff, g_dRealTime_DisToGCS-3000, 3);
//插入可视图层
g_structPointVisiReal[g_iPointNumInLayer] = _structPoint;
CalculatePtCoordinate(_structPoint.lon, _structPoint.lat, g_dRealTime_GCSlon, g_dRealTime_GCSlat, g_dRealTime_MinAngle+(12-i)*g_dRealTime_AngleDiff, g_dRealTime_DisToGCS+3000, 3);
//插入不可视图层
g_structPointNotVisiReal[g_iPointNumInLayer] = _structPoint;
}
g_iRealTime_CurStep++;
}
if (g_iRealTime_CurStep == (12 + 3))
{
//清除实时可视域绘制图层
::PostMessage(g_mapHwnd,WM_SHOW_VISI_DELETE,0,0);
//绘制实时不可视域图层
::PostMessage(g_mapHwnd,WM_SHOW_NOTVISI_REALTIME,(WPARAM)g_iPointNumInLayer,0);
g_iRealTime_CurStep++;
}
if (g_iRealTime_CurStep == (12 + 4))
{
//绘制实时可视域图层
::PostMessage(g_mapHwnd,WM_SHOW_VISI_REALTIME,(WPARAM)g_iPointNumInLayer,0);
g_iRealTime_CurStep = -1;
}
Sleep(10);
}
}
//给定角度和距离范围,进行通视检测
bool AnalysisVisiArea(double uavAlt, double dAngle, double dDistanceMin, double dDistanceMax, double lonGCS, double latGCS)
{
double dTanMaxAngle = 0.0; //最小通视角度
double fMinLightAlt = 0.0; //最小通视高度
//采样点位置
double interPolLon = 0.0, interPolLat = 0.0;
float interPolHight = 0.0;
//中间变量
double _tempAngle = 0.0; //当前点与地面站的连线 与水平方向的夹角
structPoint _structPoint;
//以30为采样间距计算插值个数
int interPolDis = 30;
int interPolNum = (int)(floor((double)(dDistanceMax/interPolDis)));
for(int i = 1; i <= interPolNum; i++)
{
CalculatePtCoordinate(interPolLon, interPolLat, lonGCS, latGCS, dAngle, i*interPolDis, 3);
//获取采样点的高程
if(!m_mapElevation2.getElevation(interPolHight, interPolLon, interPolLat))
{
//未获取到高程值
return false;
}
_tempAngle = CalSlopeBetweenTwoPoint(lonGCS, latGCS, g_fRealTime_GCSalt, interPolLon, interPolLat, interPolHight);
dTanMaxAngle = max(_tempAngle,dTanMaxAngle);
fMinLightAlt = (float)CalAltFromSlope(lonGCS, latGCS, g_fRealTime_GCSalt, interPolLon, interPolLat, dTanMaxAngle);
//给定飞行高度,判断是否可通视,若遇到第一个不通视的点,认为此点是通视与不通视的分割点,直接返回
if (uavAlt < fMinLightAlt)
{
if ((i*interPolDis) < dDistanceMin)
{
CalculatePtCoordinate(interPolLon, interPolLat, lonGCS, latGCS, dAngle, dDistanceMin, 3);
_structPoint.lon = interPolLon;
_structPoint.lat = interPolLat;
//插入可视与不可视图层
g_iPointNumInLayer++;
g_structPointVisiReal[g_iPointNumInLayer] = _structPoint;
g_structPointNotVisiReal[g_iPointNumInLayer] = _structPoint;
return true;
}
else
{
_structPoint.lon = interPolLon;
_structPoint.lat = interPolLat;
//插入可视与不可视图层
g_iPointNumInLayer++;
g_structPointVisiReal[g_iPointNumInLayer] = _structPoint;
g_structPointNotVisiReal[g_iPointNumInLayer] = _structPoint;
return true;
}
}
}
CalculatePtCoordinate(interPolLon, interPolLat, lonGCS, latGCS, dAngle, dDistanceMax, 3);
_structPoint.lon = interPolLon;
_structPoint.lat = interPolLat;
//插入可视与不可视图层
g_iPointNumInLayer++;
g_structPointVisiReal[g_iPointNumInLayer] = _structPoint;
g_structPointNotVisiReal[g_iPointNumInLayer] = _structPoint;
return true;
}
/*-------------------------------------------------------------------------------------------------------------
说明:实时碰撞检测
-------------------------------------------------------------------------------------------------------------*/
//实时碰撞检测线程开启标志
volatile bool m_bRunCrash = false;
bool g_bCrashDetection = false;
double g_dCrashUavLon = 0.0;
double g_dCrashUavLat = 0.0;
float g_fCrashUavAlt = 0.0f;
//线程函数,处理实时碰撞检测
void ThreadFuncRealTimeCrash()
{
while(m_bRunCrash)
{
if (true == g_bCrashDetection)
{
//采样点位置
double interPolLon = 0.0, interPolLat = 0.0;
float interPolHight = 0.0;
//0到360方向依次分析飞机半径为3km内的高程信息
for (int i=0;i<360;i++)
{
for (int j=0;j<=20;j++)
{
CalculatePtCoordinate(interPolLon, interPolLat, g_dCrashUavLon, g_dCrashUavLat, i, j*150, 3);
//获取采样点的高程
if(!m_mapElevation2.getElevation(interPolHight, interPolLon, interPolLat))
{
//未获取到高程值
g_bCrashDetection = false;
m_bRunCrash = false;
BCGPMessageBox(_T("高程信息不全!"));
break;
}
if ((20 == j) || (interPolHight > (g_fCrashUavAlt - 200))) //200米为考虑GPS高度与DEM高程差等之后给出的余量
{
g_structPointCrashReal[i].lon = interPolLon;
g_structPointCrashReal[i].lat = interPolLat;
break;
}
}
}
//为避免关闭线程时,线程内语句尚未执行完,从而停止检测后,依然会执行到此处
if (true == g_bCrashDetection)
{
//绘制碰撞检测后的结果
::PostMessage(g_mapHwnd,WM_SHOW_CRASH_REALTIME,1,0);
g_bCrashDetection = false;
}
}
}
}
/*-------------------------------------------------------------------------------------------------------------
说明:航线通视分析
-------------------------------------------------------------------------------------------------------------*/
//航线通视分析线程开启标志
volatile bool m_bRunRoute = false;
double g_dRoute_GCSlon = 0.0; //地面站经度
double g_dRoute_GCSlat = 0.0; //地面站纬度
float g_fRoute_GCSalt = 0.0f; //地面站高度
#pragma pack(1)
typedef struct _PTSTRUCT
{
unsigned char/*BYTE*/ lineID; //航线号
unsigned char/*BYTE*/ ptID; //航点号
double lon; //经度
double lat; //纬度
short alt; //高度
unsigned char/*BYTE*/ speed; //速度
char taskCharacter; //任务特征字
char lineCharacter; //航路特征字
}PtStruct;
#pragma pack()
PtStruct pts[257]; //航线的航线信息
int g_iWayPointNum; //航线的航点个数
int g_iCurWaypoint; //当前在分析的航点号
int g_iTotalInterNum = 0; //航线中的插值总点数
int g_totalLinePtNum; //航线中已分析的插值点数
int g_iInterNumSec = 0; //航段中的插值点数
double *g_ptrArraySeries1 = nullptr; //航线上各点的高程值
double *g_ptrArraySeries2 = nullptr; //航线上各点的最小通视高度
int *g_ptrArraySeries3 = nullptr; //航点所设置的高度
//线程函数,处理航线通视分析
void ThreadFuncAnalysisRoute()
{
while (m_bRunRoute)
{
for (int i=0;i<(g_iWayPointNum-1);i++)
{
//航点高程
g_ptrArraySeries3[i] = g_totalLinePtNum;
double _dLineSecDis, _dLineSecDir; //航段两点的距离和方向
//计算航段起点和终点的水平距离和方位角
CalculateTwoPtsDistanceAzimuth(_dLineSecDis, _dLineSecDir, pts[i].lon, pts[i].lat, pts[i+1].lon,pts[i+1].lat, 3);
//以100米为间距计算插值个数
g_iInterNumSec = (int)(floor(_dLineSecDis/100));
for (int j=0;j<=g_iInterNumSec;j++)
{
//插值点位置
double interPolLon = 0.0, interPolLat = 0.0;
float interPolHight = 0.0;
CalculatePtCoordinate(interPolLon, interPolLat, pts[i].lon, pts[i].lat, _dLineSecDir, j*100, 3);
//获取插值点的高程
if(!m_mapElevation2.getElevation(interPolHight, interPolLon, interPolLat))
{
//发送消息到对话框,提示高程信息不全
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)3,(LPARAM)-1);
//关闭线程
m_bRunRoute = false;
g_iInterNumSec = 0;
g_iWayPointNum = 0;
g_iCurWaypoint = 0;
g_iTotalInterNum = 0;
g_totalLinePtNum = 0;
continue ;
}
g_ptrArraySeries1[g_totalLinePtNum] = interPolHight;
//获取最小通视高度
float _minVisiAlt = CalculateVisibleAlt(interPolLon, interPolLat);
if (_minVisiAlt > 0.1f)
{
g_ptrArraySeries2[g_totalLinePtNum] = _minVisiAlt;
}
else
{
//关闭线程
m_bRunRoute = false;
g_iInterNumSec = 0;
g_iWayPointNum = 0;
g_iCurWaypoint = 0;
g_iTotalInterNum = 0;
g_totalLinePtNum = 0;
continue ;
}
g_totalLinePtNum++;
//发送消息到对话框,更新分析进度
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)3,(LPARAM)1);
}
}
if (true == m_bRunRoute)
{
//航点高程
g_ptrArraySeries3[g_iWayPointNum-1] = g_totalLinePtNum-1;
//关闭线程
m_bRunRoute = false;
//完成航线分析,发送消息到对话框,绘制分析结果,并提示分析完成
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)3,(LPARAM)-2);
}
}
}
//给定某点的经度、纬度,计算该点相对于地面站的最小通视高度
float CalculateVisibleAlt(const double& lon, const double& lat)
{
//计算两个点间的水平距离和方位角
double dis = 0.0, angle = 0.0;
CalculateTwoPtsDistanceAzimuth(dis, angle, g_dRoute_GCSlon, g_dRoute_GCSlat, lon, lat, 3);
//以30米为间距计算插值个数
int interPolDis = 30;
int interPolNum = (int)floor(dis/interPolDis);
//插值点位置计算
double interPolLon = 0.0, interPolLat = 0.0;
float interPolHight = 0.0;
double _dTanMaxAngle = 0.0;
float _fMinLightAlt = 0.0f;
double _tempAngle = 0.0;
for(int i = 1; i <= interPolNum; i++)
{
CalculatePtCoordinate(interPolLon, interPolLat, g_dRoute_GCSlon, g_dRoute_GCSlat, angle, i*interPolDis, 3);
if(!m_mapElevation2.getElevation(interPolHight, interPolLon, interPolLat))
{
//发送消息到对话框,提示高程信息不全
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)3,(LPARAM)-1);
return 0.0f;
}
_tempAngle = CalSlopeBetweenTwoPoint(g_dRoute_GCSlon, g_dRoute_GCSlat, g_fRoute_GCSalt, interPolLon, interPolLat, interPolHight);
_dTanMaxAngle = max(_tempAngle,_dTanMaxAngle);
_fMinLightAlt = (float)CalAltFromSlope(g_dRoute_GCSlon, g_dRoute_GCSlat, g_fRoute_GCSalt, interPolLon, interPolLat, _dTanMaxAngle);
}
return _fMinLightAlt;
}
/*-------------------------------------------------------------------------------------------------------------
说明:实时视线通视分析
-------------------------------------------------------------------------------------------------------------*/
//实时视线通视分析线程开启标志
volatile bool m_bRunRealTimeLOS = false;
bool g_bHandlingLOS = false;
double *g_ptrArrayLight1 = nullptr;
double *g_ptrArrayLight2 = nullptr;
int g_iTotalAnalyNum = 0;
double g_dLightGCSlon; //地面站经度
double g_dLightGCSlat; //地面站纬度
float g_fLightGCSAlt; //地面站高度(地面站处的高程加上方舱高度)
double g_dLightAngle; //地面站-飞机方位
double g_dLightDis; //地面站-飞机距离
double g_dLightUavAlt; //飞机高度
float g_fUavLosAlt; //飞机距离处的通视高度
//线程函数,处理实时视线通视分析
void ThreadFuncAnalysisLOS()
{
while(m_bRunRealTimeLOS)
{
if (true == g_bHandlingLOS)
{
//插值点位置
double interPolLon = 0.0, interPolLat = 0.0;
float interPolHight = 0.0f;
g_iTotalAnalyNum = (int)(g_dLightDis/30);
if (g_ptrArrayLight1 != nullptr)
{
delete[] g_ptrArrayLight1;
g_ptrArrayLight1 = nullptr;
}
g_ptrArrayLight1 = new double[g_iTotalAnalyNum + 1];
g_ptrArrayLight2 = new double[g_iTotalAnalyNum + 1];
memset(g_ptrArrayLight1, 0, sizeof(double) * (g_iTotalAnalyNum + 1));
memset(g_ptrArrayLight2, 0, sizeof(double) * (g_iTotalAnalyNum + 1));
g_ptrArrayLight1[0] = g_fLightGCSAlt;
g_ptrArrayLight2[0] = g_fLightGCSAlt;
double _dTanMaxSlope = -1000.0; //最大斜率
float _fMinLOSAlt = 0.0; //最小通视高度
double _tempSlope = 0.0; //当前点与地面站的连线的斜率
for (int i=1;i<=g_iTotalAnalyNum;i++)
{
//获取插值点经纬度
CalculatePtCoordinate(interPolLon, interPolLat, g_dLightGCSlon, g_dLightGCSlat, g_dLightAngle, i*30, 3);
//获取插值点高程值
if(!m_mapElevation2.getElevation(interPolHight, interPolLon, interPolLat))
{
//发送消息到对话框,提示高程信息不全
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)4,(LPARAM)-1);
//关闭线程
m_bRunRealTimeLOS = false;
continue ;
}
g_ptrArrayLight1[i] = interPolHight;
_tempSlope = CalSlopeBetweenTwoPoint(g_dLightGCSlon, g_dLightGCSlat, g_fLightGCSAlt, interPolLon, interPolLat, interPolHight);
//若当前点-地面站的斜率,小于之前所有点中的最大值,则当前点-地面站可以通视的斜率取最大值
_dTanMaxSlope = max(_tempSlope,_dTanMaxSlope);
//计算当前插值点可以通视的最小高度
_fMinLOSAlt = (float)CalAltFromSlope(g_dLightGCSlon, g_dLightGCSlat, g_fLightGCSAlt, interPolLon, interPolLat, _dTanMaxSlope);
g_ptrArrayLight2[i] = _fMinLOSAlt;
}
g_fUavLosAlt = _fMinLOSAlt;
//完成实时通视分析,发送消息到对话框,绘制分析结果
::SendMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)4,(LPARAM)-2);
g_bHandlingLOS = false;
}
}
}
/*-------------------------------------------------------------------------------------------------------------
说明:通视等高线分析
-------------------------------------------------------------------------------------------------------------*/
//通视等高线分析线程开启标志
volatile bool m_bRunContour = false;
double g_dGroundLonCountour = 0.0; //地面站经度
double g_dGroundLatCountour = 0.0; //地面站纬度
float g_fGroundAltCountour = 0.0; //地面站高度
float g_fLastLightAlt = 0.0f;
int g_iMaxLosAlt = 8000;
//线程函数,处理通视等高线分析
void ThreadFuncAnalysisContour()
{
while (m_bRunContour)
{
for (int i=0;i<360;i++)
{
g_fLastLightAlt = g_fGroundAltCountour;
if (false == AnalysisContourLine(i))
{
//发送消息到对话框,提示高程信息不全
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)5,(LPARAM)-1);
//终止线程
m_bRunContour = false;
break;
}
else
{
//发送消息到对话框,提示进度
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)5,(LPARAM)i);
}
//线程已终止
if (false == m_bRunContour)
{
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)5,(LPARAM)-3);
break;
}
}
if (true == m_bRunContour)
{
//发送消息到对话框,提示分析完成
::PostMessage(g_hwndDlgLight,WM_SEND_UPDATEDIALOG,(WPARAM)5,(LPARAM)-2);
//终止线程
m_bRunContour = false;
}
}
}
//通视等高线分析并在地图上标绘等高线iAngle 角度
bool AnalysisContourLine(int iAngle)
{
double _dTanMaxAngle = 0.0; //最小通视角度
float _fMinLightAlt = 0.0; //最小通视高度
//采样点位置
double interPolLon = 0.0, interPolLat = 0.0;
float interPolHight = 0.0;
//中间变量
double _tempAngle = 0.0; //当前点与地面站的连线 与水平方向的夹角
int _iStep = 1;
while (_fMinLightAlt < g_iMaxLosAlt)
{
CalculatePtCoordinate(interPolLon, interPolLat, g_dGroundLonCountour, g_dGroundLatCountour, iAngle, _iStep*30, 3); //30为采样间距
//获取采样点的高程
if(!m_mapElevation2.getElevation(interPolHight, interPolLon, interPolLat))
{
//未获取到高程值
return false;
}
_tempAngle = CalSlopeBetweenTwoPoint(g_dGroundLonCountour, g_dGroundLatCountour, g_fGroundAltCountour, interPolLon, interPolLat, interPolHight);
_dTanMaxAngle = max(_tempAngle,_dTanMaxAngle);
_fMinLightAlt = (float)CalAltFromSlope(g_dGroundLonCountour, g_dGroundLatCountour, g_fGroundAltCountour, interPolLon, interPolLat, _dTanMaxAngle);
if (true == m_bRunContour)
{
//添加点到通视等高线图层
InsertPtToContourLine(_fMinLightAlt, interPolLon, interPolLat);
}
_iStep++;
}
return true;
}
//添加点到通视等高线图层
void InsertPtToContourLine(float _fLightAlt, double _dPtLon, double _dPtLat)
{
for (int i = 1;i<=20;i++)
{
if ((g_fLastLightAlt < (500*i)) && (_fLightAlt > (500*i)))
{
structPoint _pt;
_pt.lon = _dPtLon;
_pt.lat = _dPtLat;
//添加点到通视等高线图层
::SendMessage(g_mapHwnd,WM_ADD_LINELAYER,WPARAM(&_pt),LPARAM(i));
g_fLastLightAlt = _fLightAlt;
return;
}
}
}
// CDlgLightRegion 对话框
IMPLEMENT_DYNAMIC(CDlgLightRegion, CBCGPDialog)
CDlgLightRegion::CDlgLightRegion(CWnd* pParent /*=NULL*/)
: CBCGPDialog(CDlgLightRegion::IDD, pParent)
{
EnableVisualManagerStyle(TRUE, TRUE);
m_dGroundLon = 107.4203869;
m_dGroundLat = 37.8544731;
m_fGroudAlt = 0.0f;
m_dCabinHgt = 4.0;
m_iFlightAlt = 3500;
m_iRegionRadius = 30;
m_bRTlight = FALSE;
m_pLine1 = nullptr;
m_strokeStyle.SetDashStyle(CBCGPStrokeStyle::BCGP_DASH_STYLE_DOT);
m_pTextTip = nullptr;
m_bRealTime_Visi = FALSE;
m_bRealTime_Crash = FALSE;
m_iMaxLosAlt = 8000;
m_iFightRegion = 280;
}
CDlgLightRegion::~CDlgLightRegion()
{
m_bRunRegion = false;
m_bRunDetect = false;
m_bRunRoute = false;
m_bRunRealTimeLOS = false;
m_bRunCrash = false;
if (g_ptrArraySeries1 != nullptr)
{
delete[] g_ptrArraySeries1;
g_ptrArraySeries1 = nullptr;
}
if (g_ptrArraySeries2 != nullptr)
{
delete[] g_ptrArraySeries2;
g_ptrArraySeries2 = nullptr;
}
if (g_ptrArraySeries3 != nullptr)
{
delete[] g_ptrArraySeries3;
g_ptrArraySeries3 = nullptr;
}
if (g_ptrArrayLight1 != nullptr)
{
delete[] g_ptrArrayLight1;
g_ptrArrayLight1 = nullptr;
}
if (g_ptrArrayLight2 != nullptr)
{
delete[] g_ptrArrayLight2;
g_ptrArrayLight2 = nullptr;
}
}
void CDlgLightRegion::DoDataExchange(CDataExchange* pDX)
{
CBCGPDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CONTAINER_ALTCHART, m_wndChart);
DDX_Text(pDX, IDC_EDIT_GROUND_LON, m_dGroundLon);
DDX_Text(pDX, IDC_EDIT_GROUND_LAT, m_dGroundLat);
DDX_Text(pDX, IDC_EDIT_BASEALT, m_iFlightAlt);
DDX_Text(pDX, IDC_EDIT_REGIONRADIUS, m_iRegionRadius);
DDX_Check(pDX, IDC_CHECK_REALTIME, m_bRealTime_Visi);
DDX_Check(pDX, IDC_CHECK_RT_DETECTION, m_bRealTime_Crash);
DDX_Text(pDX, IDC_EDIT_CABINALT, m_dCabinHgt);
DDX_Check(pDX, IDC_CHECK_RT_LIGHT, m_bRTlight);
DDX_Control(pDX, IDC_GAUGE_PROMPT_LINE, m_LineTextContainer);
DDX_Control(pDX, IDC_GAUGE_PROMPT_REGION, m_RegionTextContainer);
DDX_Control(pDX, IDC_GAUGE_PROMPT_CONTOUR, m_ContourTextContainer);
DDX_Text(pDX, IDC_EDIT_MAXLOSALT, m_iMaxLosAlt);
DDX_Text(pDX, IDC_EDIT_FIGHTRADIUS, m_iFightRegion);
DDV_MinMaxInt(pDX, m_iFightRegion, 0, 500);
}
BEGIN_MESSAGE_MAP(CDlgLightRegion, CBCGPDialog)
ON_WM_TIMER()
ON_WM_SIZE()
ON_BN_CLICKED(IDC_BUTTON_DRAWPOINT, &CDlgLightRegion::OnBnClickedButtonDrawPoint)
ON_BN_CLICKED(IDC_BUTTON_REGIONANAYLSIS, &CDlgLightRegion::OnBnClickedButtonRegionAnaylsis)
ON_BN_CLICKED(IDC_CHECK_REALTIME, &CDlgLightRegion::OnBnClickedCheckRealtime)
ON_BN_CLICKED(IDC_BUTTON_REGIONDELETE, &CDlgLightRegion::OnBnClickedButtonRegionDelete)
ON_BN_CLICKED(IDC_CHECK_RT_LIGHT, &CDlgLightRegion::OnBnClickedCheckRtLight)
ON_BN_CLICKED(IDC_BUTTON_LOADROUTE, &CDlgLightRegion::OnBnClickedButtonLoadRoute)
ON_BN_CLICKED(IDC_BUTTON_SAVEIMAGE, &CDlgLightRegion::OnBnClickedButtonSaveImage)
ON_BN_CLICKED(IDC_BUTTON_STOPROUTE, &CDlgLightRegion::OnBnClickedButtonStopRoute)
ON_BN_CLICKED(IDC_BUTTON_CONTOURLINE, &CDlgLightRegion::OnBnClickedButtonContourline)
ON_BN_CLICKED(IDC_BUTTON_CONTOURDELETE, &CDlgLightRegion::OnBnClickedButtonContourDelete)
ON_MESSAGE(WM_SEND_UPDATEDIALOG, &CDlgLightRegion::OnSendUpdateDialog)
ON_BN_CLICKED(IDC_BUTTON_SELECTPTINMAP, &CDlgLightRegion::OnBnClickedButtonSelectPtInMap)
ON_BN_CLICKED(IDC_BUTTON_CLEARLINELAYER, &CDlgLightRegion::OnBnClickedButtonClearLineLayer)
ON_BN_CLICKED(IDC_BUTTON_GETALTVALUE, &CDlgLightRegion::OnBnClickedButtonGetAltValue)
ON_BN_CLICKED(IDC_BUTTON_REVERSE, &CDlgLightRegion::OnBnClickedButtonReverse)
ON_REGISTERED_MESSAGE(BCGM_ON_CHART_MOUSE_DOWN, OnMouseDown)
ON_BN_CLICKED(IDC_BUTTON_CLEARRESULT, &CDlgLightRegion::OnBnClickedButtonClearResult)
ON_BN_CLICKED(IDC_CHECK_RT_DETECTION, &CDlgLightRegion::OnBnClickedCheckRtDetection)
ON_BN_CLICKED(IDC_BUTTON_DRAWFIGHT, &CDlgLightRegion::OnBnClickedButtonDrawFight)
ON_BN_CLICKED(IDC_BUTTON_DELETEFIGHT, &CDlgLightRegion::OnBnClickedButtonDeleteFight)
ON_BN_CLICKED(IDC_BUTTON_GETDEMREGION, &CDlgLightRegion::OnBnClickedButtonGetDemRegion)
END_MESSAGE_MAP()
// CDlgLightRegion 消息处理程序
BOOL CDlgLightRegion::OnInitDialog()
{
CBCGPDialog::OnInitDialog();
g_hwndDlgLight = this->GetSafeHwnd();
CenterWindow();
pChart = m_wndChart.GetChart();
ASSERT_VALID(pChart);
//Release模式下曲线背景会变白在此设置颜色
#ifdef DEBUG
//pChart->SetColors(CBCGPChartTheme::CT_DEFAULT);
#else
pChart->SetColors(CBCGPChartTheme::CT_DEFAULT, TRUE);
#endif
//设置放大缩小方式
pChart->SetZoomScrollConfig(BCGPChartMouseConfig::ZSO_WHEEL_PAN, BCGPChartFormatSelection::ST_VERT_AXIS_ONLY);
pChart->SetSelectionType(BCGPChartFormatSelection::ST_VERT_AXIS_ONLY);
//曲线使能鼠标跟踪
pChart->EnableMouseTrackingMode(
BCGPChartHitInfo::HIT_DATA_POINT |
BCGPChartHitInfo::HIT_DATA_LABEL |
BCGPChartHitInfo::HIT_AXIS |
BCGPChartHitInfo::HIT_AXIS_NAME |
BCGPChartHitInfo::HIT_CHART_AREA |
BCGPChartHitInfo::HIT_LEGEND |
BCGPChartHitInfo::HIT_TITLE |
BCGPChartHitInfo::HIT_DIAGRAM |
BCGPChartHitInfo::HIT_DATA_TABLE |
BCGPChartHitInfo::HIT_ALL_ELEMENTS);
//设置:当鼠标移动到曲线上,会显示当前点的信息
CBCGPInfoTipOptions infoTipOptions;
infoTipOptions.m_StemLocation = CBCGPPopupWindow::BCGPPopupWindowStemLocation_BottomCenter;
m_wndChart.EnableInfoTip(TRUE, &infoTipOptions);
pXAxis = pChart->GetChartAxis(BCGP_CHART_X_PRIMARY_AXIS);
pYAxis = pChart->GetChartAxis(BCGP_CHART_Y_PRIMARY_AXIS);
//创建曲线1绘制高程信息
pSeries1 = pChart->CreateSeries(_T("DEM Alt"), CBCGPColor(), BCGP_CT_DEFAULT, BCGPChartArea);
//创建曲线2绘制最小通视高度
pSeries2 = pChart->CreateSeries(_T("LOS Alt"), CBCGPColor(CBCGPColor::OrangeRed), BCGP_CT_DEFAULT, BCGPChartLine);
pSeries2->SetSeriesLineWidth(2);
//创建曲线3绘制无人机位置
pSeries3 = pChart->CreateSeries(_T("UAV Alt"), CBCGPColor(CBCGPColor::LimeGreen), BCGP_CT_DEFAULT, BCGPChartLine);
BCGPChartFormatSeries style = pSeries3->GetSeriesFormat();
style.m_curveType = BCGPChartFormatSeries::CCT_NO_LINE;
pSeries3->SetSeriesFormat(style);
pSeries3->ShowMarker(TRUE, 0);
pSeries3->SetMarkerSize(4, 0);
/*pSeries3->ShowDataLabel(TRUE,0);
pSeries3->SetDataLabelAngle(60, 0);
pSeries3->SetDataLabelDataFormat(_T("%.1f"),0);*/
pChart->SetDirty(TRUE, TRUE);
m_wndChart.RedrawWindow();
//初始化可视域分析提示文字显示仪表
InitRegionTextContainer();
//初始化航线通视分析提示文字显示仪表
InitLineTextContainer();
//初始化通视等高线分析提示文字显示仪表
InitContourTextContainer();
return TRUE;
}
void CDlgLightRegion::OnSize(UINT nType, int cx, int cy)
{
CBCGPDialog::OnSize(nType, cx, cy);
//图表控件随对话框大小变化而变化
if (m_wndChart.GetSafeHwnd())
{
CRect rect;
GetClientRect(&rect);
CRect rectChart;
m_wndChart.GetWindowRect(rectChart);
ScreenToClient(rectChart);
rectChart.right = rect.right - 5;
rectChart.bottom = rect.bottom - 5;
m_wndChart.MoveWindow(&rectChart,TRUE);
}
}
//初始化可视域分析提示文字显示仪表
void CDlgLightRegion::InitRegionTextContainer()
{
CBCGPVisualContainer* pContainer = m_RegionTextContainer.GetVisualContainer();
ASSERT_VALID(pContainer);
pContainer->SetFillBrush(CBCGPBrush());
pContainer->SetOutlineBrush(CBCGPBrush());
CBCGPBrush m_arBrushes(CBCGPColor::AliceBlue);
m_pRegionTTextIndicator = new CBCGPTextGaugeImpl(_T("进度提示"), m_arBrushes, pContainer);
CBCGPTextFormat m_TextFormat = m_pRegionTTextIndicator->GetTextFormat();
m_TextFormat.SetFontSize(15);
m_TextFormat.SetTextAlignment(CBCGPTextFormat::BCGP_TEXT_ALIGNMENT_CENTER);
m_TextFormat.SetTextVerticalAlignment(CBCGPTextFormat::BCGP_TEXT_ALIGNMENT_CENTER);
m_pRegionTTextIndicator->SetTextFormat(m_TextFormat);
CBCGPRect rect = pContainer->GetRect();
m_pRegionTTextIndicator->SetRect(rect);
m_RegionTextContainer.RedrawWindow();
}
//初始化航线通视分析提示文字显示仪表
void CDlgLightRegion::InitLineTextContainer()
{
CBCGPVisualContainer* pContainer = m_LineTextContainer.GetVisualContainer();
ASSERT_VALID(pContainer);
pContainer->SetFillBrush(CBCGPBrush());
pContainer->SetOutlineBrush(CBCGPBrush());
CBCGPBrush m_arBrushes(CBCGPColor::AliceBlue);
m_pLineTextIndicator = new CBCGPTextGaugeImpl(_T("进度提示"), m_arBrushes, pContainer);
CBCGPTextFormat m_TextFormat = m_pLineTextIndicator->GetTextFormat();
m_TextFormat.SetFontSize(15);
m_TextFormat.SetTextAlignment(CBCGPTextFormat::BCGP_TEXT_ALIGNMENT_CENTER);
m_TextFormat.SetTextVerticalAlignment(CBCGPTextFormat::BCGP_TEXT_ALIGNMENT_CENTER);
m_pLineTextIndicator->SetTextFormat(m_TextFormat);
CBCGPRect rect = pContainer->GetRect();
m_pLineTextIndicator->SetRect(rect);
m_LineTextContainer.RedrawWindow();
}
//初始化通视等高线分析提示文字显示仪表
void CDlgLightRegion::InitContourTextContainer()
{
CBCGPVisualContainer* pContainer = m_ContourTextContainer.GetVisualContainer();
ASSERT_VALID(pContainer);
pContainer->SetFillBrush(CBCGPBrush());
pContainer->SetOutlineBrush(CBCGPBrush());
CBCGPBrush m_arBrushes(CBCGPColor::AliceBlue);
m_pContourTextIndicator = new CBCGPTextGaugeImpl(_T("进度提示"), m_arBrushes, pContainer);
CBCGPTextFormat m_TextFormat = m_pContourTextIndicator->GetTextFormat();
m_TextFormat.SetFontSize(15);
m_TextFormat.SetTextAlignment(CBCGPTextFormat::BCGP_TEXT_ALIGNMENT_CENTER);
m_TextFormat.SetTextVerticalAlignment(CBCGPTextFormat::BCGP_TEXT_ALIGNMENT_CENTER);
m_pContourTextIndicator->SetTextFormat(m_TextFormat);
CBCGPRect rect = pContainer->GetRect();
m_pContourTextIndicator->SetRect(rect);
m_ContourTextContainer.RedrawWindow();
}
//接收其他线程来的消息,更新对话框内容
afx_msg LRESULT CDlgLightRegion::OnSendUpdateDialog(WPARAM wParam, LPARAM lParam)
{
if (1 == (int)wParam) //可视域分析
{
if (-1 == int(lParam))
{
m_pRegionTTextIndicator->SetText(_T("高程不全!"));
m_RegionTextContainer.RedrawWindow();
GetDlgItem(IDC_BUTTON_REGIONANAYLSIS)->EnableWindow(TRUE);
}
else
{
CString str;
str.Format(_T("%d%%"),(int)(((int)lParam+1) * 100 / 360));
m_pRegionTTextIndicator->SetText(str);
m_RegionTextContainer.RedrawWindow();
if (359 == int(lParam))
{
GetDlgItem(IDC_BUTTON_REGIONANAYLSIS)->EnableWindow(TRUE);
}
}
}
else if (2 == (int)wParam) //实时通视检测
{
if (-1 == int(lParam))
{
BCGPMessageBox(_T("高程信息不全!"));
}
}
else if (3 == (int)wParam) //航线通视分析
{
if (-1 == int(lParam))
{
//未获取到高程值
m_pLineTextIndicator->SetText(_T("高程不全!"));
m_LineTextContainer.RedrawWindow();
}
else if (-2 == int(lParam))
{
for (int i=0;i<g_iTotalInterNum;i++)
{
pSeries1->AddDataPoint(g_ptrArraySeries1[i],i);
pSeries2->AddDataPoint(g_ptrArraySeries2[i],i);
}
//航点的高程
for (int i=0;i<g_iWayPointNum;i++)
{
pSeries3->AddDataPoint(pts[i].alt,g_ptrArraySeries3[i]);
pSeries1->ShowDataLabel(TRUE,g_ptrArraySeries3[i]);
pSeries1->SetDataLabelAngle(0, g_ptrArraySeries3[i]);
pSeries1->ShowMarker(TRUE, g_ptrArraySeries3[i]);
pSeries1->SetMarkerSize(4, g_ptrArraySeries3[i]);
CString str;
str.Format(_T("%d-%d"),pts[i].lineID,pts[i].ptID);
pSeries1->SetDataLabelDataFormat(str,g_ptrArraySeries3[i]);
}
pChart->SetAutoDisplayRange(TRUE, TRUE);
pChart->SetDirty(TRUE, TRUE);
m_wndChart.RedrawWindow();
m_pLineTextIndicator->SetText(_T("分析完成!"));
m_LineTextContainer.RedrawWindow();
}
else if (1 == int(lParam))
{
if (g_iTotalInterNum > 0)
{
CString str;
str.Format(_T("%d%%"),(g_totalLinePtNum)*100/g_iTotalInterNum);
m_pLineTextIndicator->SetText(str);
m_LineTextContainer.RedrawWindow();
}
}
}
else if (4 == (int)wParam) //实时视线分析
{
if (-1 == int(lParam)) //未获取到高程值
{
m_bRTlight = FALSE;
UpdateData(FALSE);
GetDlgItem(IDC_BUTTON_LOADROUTE)->EnableWindow(TRUE);
BCGPMessageBox(_T("高程信息不全!"));
}
else if (-2 == int(lParam)) //分析完成
{
pSeries1->AddDataPoint(g_ptrArrayLight1[0],0.0);
pSeries2->AddDataPoint(g_ptrArrayLight2[0],0.0);
for (int i=1;i<=g_iTotalAnalyNum;i++)
{
pSeries1->AddDataPoint(g_ptrArrayLight1[i],i*30);
pSeries2->AddDataPoint(g_ptrArrayLight2[i],i*30);
}
//在Chart上更新无人机的位置距离和高度
pSeries3->AddDataPoint(g_dLightUavAlt,30*g_iTotalAnalyNum);
pSeries3->ShowMarker(TRUE, 30*g_iTotalAnalyNum);
pSeries3->SetMarkerSize(4, 30*g_iTotalAnalyNum);
pChart->RemoveAllChartObjects();
//连接无人机高度和最小通视高度
m_pLine1 = pChart->AddChartLineObject(30*g_iTotalAnalyNum, g_dLightUavAlt, 30*g_iTotalAnalyNum, g_fUavLosAlt, CBCGPBrush(CBCGPColor::Tomato), 1.5, &m_strokeStyle);
CString str;
str.Format(_T("%.1fm"),g_dLightUavAlt - g_fUavLosAlt);
//显示无人机高度和最小通视高度的差值
m_pTextTip = nullptr;
m_pTextTip = new CBCGPChartTextObject(pChart, str, 30*g_iTotalAnalyNum, min(g_dLightUavAlt,g_fUavLosAlt) + abs(g_dLightUavAlt - g_fUavLosAlt)/2,
CBCGPBrush(CBCGPColor::White), CBCGPBrush(), CBCGPBrush(CBCGPColor::Tomato), 30, 90, TRUE);
pChart->AddChartObject(m_pTextTip);
pChart->SetAutoDisplayRange(TRUE, TRUE);
pChart->SetDirty(TRUE, TRUE);
m_wndChart.RedrawWindow();
}
}
else if (5 == (int)wParam) //通视等高线分析
{
if (int(lParam) >= 0)
{
//进度提示
CString str;
str.Format(_T("%d%%"),(int)((int(lParam)+1) * 100 / 360));
m_pContourTextIndicator->SetText(str);
m_ContourTextContainer.RedrawWindow();
}
else if (-1 == int(lParam)) //未获取到高程值
{
m_pContourTextIndicator->SetText(_T("高程信息不全!"));
m_ContourTextContainer.RedrawWindow();
GetDlgItem(IDC_BUTTON_CONTOURLINE)->EnableWindow(TRUE);
}
else if (-2 == int(lParam))
{
m_pContourTextIndicator->SetText(_T("分析完成!"));
m_ContourTextContainer.RedrawWindow();
GetDlgItem(IDC_BUTTON_CONTOURLINE)->EnableWindow(TRUE);
}
else if (-3 == int(lParam))
{
//清除通视等高线分析结果
OnBnClickedButtonContourDelete();
}
}
return 0;
}
//在地图上标绘地面站位置
void CDlgLightRegion::OnBnClickedButtonDrawPoint()
{
UpdateData(TRUE);
::SendMessage(g_mapHwnd,WM_SHOW_POINTINMAP,0,0);
//获取地面站的高程信息
float ptAlt = 0.0f;
if(!m_mapElevation2.getElevation(ptAlt, m_dGroundLon, m_dGroundLat))
{
ptAlt = 0.0f;
}
CString str;
str.Format(_T("%.1f"),ptAlt);
GetDlgItem(IDC_EDIT_GROUND_ALT)->SetWindowText(str);
}
/*-------------------------------------------------------------------------------------------------------------
说明:可视域分析
-------------------------------------------------------------------------------------------------------------*/
//点击“可视域分析”按钮
void CDlgLightRegion::OnBnClickedButtonRegionAnaylsis()
{
UpdateData(TRUE);
//获取地面站高程信息
if(!m_mapElevation2.getElevation(g_fGroundAltTemp, m_dGroundLon, m_dGroundLat))
{
//未获取到高程值
BCGPMessageBox(_T("地面站处无高程信息!"));
return ;
}
else
{
//地面站位置的高度在地面站高程的基础上加上方舱高度
g_fGroundAltTemp += (float)m_dCabinHgt;
if (g_fGroundAltTemp > m_iFlightAlt)
{
BCGPMessageBox(_T("飞行高度应大于地面站高度!"));
return ;
}
}
//清除可视域绘制图层
::SendMessage(g_mapHwnd,WM_SEND_CLEARSHAPE,0,0);
GetDlgItem(IDC_BUTTON_REGIONANAYLSIS)->EnableWindow(FALSE);
g_dGroundLonTemp = m_dGroundLon;
g_dGroundLatTemp = m_dGroundLat;
g_iFlightAlt = m_iFlightAlt;
g_iRegionRadius = m_iRegionRadius;
g_iAnalysisStep = 0;
//开启线程
hThreadRegion = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFuncLightRegion, NULL, 0, &ThreadIDRegion);
m_bRunRegion = true;
}
//清除可视域分析结果
void CDlgLightRegion::OnBnClickedButtonRegionDelete()
{
//关闭线程
m_bRunRegion = false;
//清除可视域绘制图层
::SendMessage(g_mapHwnd,WM_SEND_CLEARSHAPE,0,0);
GetDlgItem(IDC_BUTTON_REGIONANAYLSIS)->EnableWindow(TRUE);
}
/*------------------------------------------------------------------------------------------------------------
说明:实时通视检测
-------------------------------------------------------------------------------------------------------------*/
//选中实时通视检测
void CDlgLightRegion::OnBnClickedCheckRealtime()
{
UpdateData(TRUE);
if (TRUE == m_bRealTime_Visi)
{
//清除实时可视域绘制图层
::SendMessage(g_mapHwnd,WM_SHOW_VISI_DELETE,0,0);
g_iRealTime_CurStep = -1;
//开启线程
hThreadDetect = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFuncRealTimeDetection, NULL, 0, &ThreadIDDetect);
m_bRunDetect = true;
}
else
{
//关闭线程
m_bRunDetect = false;
//清除实时可视域绘制图层
::SendMessage(g_mapHwnd,WM_SHOW_VISI_DELETE,0,0);
}
}
//地图上实时绘制检测区域
void CDlgLightRegion::DrawVisiAreaRealTime(double uavAlt, double distanceToGCS, double angleToGCS, double lonGCS, double latGCS)
{
//若未选中实时通视检测
if (FALSE == m_bRealTime_Visi)
{
return ;
}
//当实时检测已终止
if (-1 == g_iRealTime_CurStep)
{
//地面站-飞机距离小于5km不进行实时检测
if (distanceToGCS < 5000.0)
{
m_bRealTime_Visi = FALSE;
UpdateData(FALSE);
//关闭线程
m_bRunDetect = false;
BCGPMessageBox(_T("地面站-飞机距离过短!"));
//清除实时可视域绘制图层
::SendMessage(g_mapHwnd,WM_SHOW_VISI_DELETE,0,0);
return ;
}
//获取地面站高程信息
if(!m_mapElevation2.getElevation(g_fRealTime_GCSalt, lonGCS, latGCS))
{
m_bRealTime_Visi = FALSE;
UpdateData(FALSE);
//关闭线程
m_bRunDetect = false;
//未获取到高程值
BCGPMessageBox(_T("地面站处无高程信息!"));
//清除实时可视域绘制图层
::SendMessage(g_mapHwnd,WM_SHOW_VISI_DELETE,0,0);
return ;
}
//地面站位置的高度在地面站高程的基础上加上方舱高度
g_fRealTime_GCSalt += (float)m_dCabinHgt;
double _tempAngle = (asin(3000.0/distanceToGCS) * 57.295779513082322864647721871733665466308593750000);
double _tempMinAngle = angleToGCS - _tempAngle;
if (_tempMinAngle < 0)
{
_tempMinAngle += 360.0;
}
g_dRealTime_GCSlon = lonGCS;
g_dRealTime_GCSlat = latGCS;
g_dRealTime_UavAlt = uavAlt;
g_dRealTime_AngToGCS = angleToGCS;
g_dRealTime_DisToGCS = distanceToGCS;
g_dRealTime_MinAngle = _tempMinAngle;
g_dRealTime_AngleDiff = _tempAngle/6.0;
//开始绘制实时可视域
g_iRealTime_CurStep = 0;
g_iPointNumInLayer = -1;
}
}
/*------------------------------------------------------------------------------------------------------------
说明:实时碰撞检测
-------------------------------------------------------------------------------------------------------------*/
//选中实时碰撞检测
void CDlgLightRegion::OnBnClickedCheckRtDetection()
{
UpdateData(TRUE);
if (TRUE == m_bRealTime_Crash)
{
g_bCrashDetection = false;
//开启线程
hThreadCrash = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFuncRealTimeCrash, NULL, 0, &ThreadIDCrash);
m_bRunCrash = true;
}
else
{
g_bCrashDetection = false;
//关闭线程
m_bRunCrash = false;
//清除碰撞检测后的结果
::PostMessage(g_mapHwnd,WM_SHOW_CRASH_REALTIME,0,0);
}
}
//地图上实时在无人机周边检测高程
void CDlgLightRegion::DrawCrashAreaRealTime(double uavAlt, double uavLon, double uavLat)
{
//若未选中实时碰撞检测
if (FALSE == m_bRealTime_Crash)
{
return ;
}
if (false == g_bCrashDetection)
{
g_dCrashUavLon = uavLon;
g_dCrashUavLat = uavLat;
g_fCrashUavAlt = (float)uavAlt;
g_bCrashDetection = true;
}
}
/*------------------------------------------------------------------------------------------------------------
说明:实时视线分析
-------------------------------------------------------------------------------------------------------------*/
//选中实时视线分析
void CDlgLightRegion::OnBnClickedCheckRtLight()
{
UpdateData(TRUE);
if (TRUE == m_bRTlight)
{
GetDlgItem(IDC_BUTTON_LOADROUTE)->EnableWindow(FALSE);
//两点通视分析时隐藏了pSeries3实时视线分析时需要显示
pChart->ShowSeries(TRUE, 2);
//设置曲线3类型为NO_LINE
BCGPChartFormatSeries style = pSeries3->GetSeriesFormat();
style.m_curveType = BCGPChartFormatSeries::CCT_NO_LINE;
pSeries3->SetSeriesFormat(style);
pSeries3->ShowMarker(TRUE, 0);
pSeries3->SetMarkerSize(4, 0);
pSeries3->m_strSeriesName = _T("UAV Alt");
//开启线程
hThreadLight = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFuncAnalysisLOS, NULL, 0, &ThreadIDLight);
m_bRunRealTimeLOS = true;
}
else
{
g_bHandlingLOS = false;
//关闭线程
m_bRunRealTimeLOS = false;
pSeries1->RemoveAllDataPoints();
pSeries2->RemoveAllDataPoints();
pSeries3->RemoveAllDataPoints();
pChart->RemoveAllChartObjects();
pChart->SetDirty(TRUE, TRUE);
m_wndChart.RedrawWindow();
GetDlgItem(IDC_BUTTON_LOADROUTE)->EnableWindow(TRUE);
}
}
//实时视线分析,地面站-飞机连线,绘制图表
void CDlgLightRegion::AnalysisRealTime(double uavAlt, double distanceToGCS, double angleToGCS, double lonGCS, double latGCS)
{
//若未选中实时视线分析,返回
if (FALSE == m_bRTlight)
{
return ;
}
if (false == g_bHandlingLOS)
{
pSeries1->RemoveAllDataPoints();
pSeries2->RemoveAllDataPoints();
pSeries3->RemoveAllDataPoints();
g_dLightGCSlon = lonGCS; //地面站经度
g_dLightGCSlat = latGCS; //地面站纬度
g_dLightAngle = angleToGCS; //地面站-飞机方位
g_dLightDis = distanceToGCS; //地面站-飞机距离
g_dLightUavAlt = uavAlt; //飞机高度
//获取地面站所在位置高程值
if(!m_mapElevation2.getElevation(g_fLightGCSAlt, g_dLightGCSlon, g_dLightGCSlat))
{
//未获取到高程值,取消实时视线分析
m_bRTlight = FALSE;
UpdateData(FALSE);
//关闭线程
m_bRunRealTimeLOS = false;
GetDlgItem(IDC_BUTTON_LOADROUTE)->EnableWindow(TRUE);
BCGPMessageBox(_T("高程信息不全!"));
return ;
}
//地面站位置的高度在地面站高程的基础上加上方舱的高度
g_fLightGCSAlt += (float)m_dCabinHgt;
g_bHandlingLOS = true;
}
}
/*-------------------------------------------------------------------------------------------------------------
说明:航线通视分析
-------------------------------------------------------------------------------------------------------------*/
//加载航线
void CDlgLightRegion::OnBnClickedButtonLoadRoute()
{
UpdateData(TRUE);
//弹出文件对话框
CFileDialog dlg(true, NULL, NULL,OFN_HIDEREADONLY, _T("(*.txt)|*.txt||"), NULL);
if (dlg.DoModal() == IDOK)
{
CString strFile = dlg.GetPathName();
int ptNum = 0;
//初始化航线的航点数据
memset(pts, 0, sizeof(PtStruct)*257);
FILE *fpReadFlyLine;
int err;
err = fopen_s(&fpReadFlyLine,strFile.GetBuffer(), "r");
strFile.ReleaseBuffer();
if (fpReadFlyLine != NULL)
{
while (!feof(fpReadFlyLine))
{
//航路文件是否导入正确的标识
int redFlag = fscanf_s(fpReadFlyLine, "%d, %d, %lf, %lf, %d, %d, %02X, %02X\n", &pts[ptNum].lineID,&pts[ptNum].ptID,
&pts[ptNum].lon, &pts[ptNum].lat, &pts[ptNum].alt, &pts[ptNum].speed, &pts[ptNum].taskCharacter, &pts[ptNum].lineCharacter);
if (redFlag != 8) //航路文件不对,返回
{
//关闭文件
fclose(fpReadFlyLine);
return ;
}
if (0 != pts[ptNum].ptID)
{
ptNum ++;
}
}
//关闭文件
fclose(fpReadFlyLine);
//航路点个数的有效范围为[0,255]共256个
//检测的有效范围为【2,256】
if ((ptNum>257) || (ptNum<2))
{
return ;
}
//对单个航点的数据进行检查
for (int i=0; i<ptNum; i++)
{
if ( (pts[i].ptID<0) || (pts[i].ptID>255)
|| (pts[i].lon<-180) || (pts[i].lon>180)
|| (pts[i].lat<-90) || (pts[i].lat>90)
|| (pts[i].alt<-500) || (pts[i].alt>10000)
|| (pts[i].speed<0) || (pts[i].speed>100)
|| (pts[i].taskCharacter<0) || (pts[i].taskCharacter>255)
|| (pts[i].lineCharacter<0) || (pts[i].lineCharacter>255) )
{
return ;
}
}
//对航点的航线编号进行严格检查
//当存在航线编号不一样时返回false
int ptLineID = pts[0].lineID;
for (int i=1; i<ptNum; i++)
{
if (ptLineID != pts[i].lineID)
{
return ;
}
}
//对航线的航点编号进行严格检查判断规则为起点为1依次递增1
//当存在航点编号不符合规则时,返回
if (pts[0].ptID != 1)
{
return ;
}
int toComparePtId = pts[0].ptID + 1;
for (int i=1; i<ptNum; i++)
{
if (pts[i].ptID != toComparePtId)
{
return ;
}
else
{
toComparePtId++;
}
}
//显示航线
//::SendMessage(g_mapHwnd, WM_SHOW_LINE, pts[0].lineID, 0);
pts[ptNum] = pts[0];
g_iWayPointNum = ptNum + 1;
g_totalLinePtNum = 0;
pSeries1->RemoveAllDataPoints();
pSeries2->RemoveAllDataPoints();
pSeries3->RemoveAllDataPoints();
//两点通视分析时隐藏了pSeries3航线通视分析时需要显示
pChart->ShowSeries(TRUE, 2);
//设置曲线3类型为曲线
BCGPChartFormatSeries style = pSeries3->GetSeriesFormat();
style.m_curveType = BCGPChartFormatSeries::CCT_LINE;
pSeries3->SetSeriesFormat(style);
pSeries3->m_strSeriesName = _T("Pt Alt");
pSeries3->ShowMarker(FALSE);
m_pLineTextIndicator->SetText(_T("正在分析!"));
m_LineTextContainer.RedrawWindow();
//计算航线分析时总共需要分析的点数
g_iTotalInterNum = 0;
for (int i=0;i<ptNum;i++)
{
double _dis;
if (i != (ptNum-1))
{
CalculateTwoPtsDistance(_dis, pts[i].lon, pts[i].lat, pts[i+1].lon, pts[i+1].lat, 3);
}
else
{
CalculateTwoPtsDistance(_dis, pts[i].lon, pts[i].lat, pts[0].lon, pts[0].lat, 3);
}
g_iTotalInterNum += (int)(_dis/100) + 1;
}
if (g_ptrArraySeries1 != nullptr)
{
delete[] g_ptrArraySeries1;
g_ptrArraySeries1 = nullptr;
}
g_ptrArraySeries1 = new double[g_iTotalInterNum];
memset(g_ptrArraySeries1,0,sizeof(double) * g_iTotalInterNum);
if (g_ptrArraySeries2 != nullptr)
{
delete[] g_ptrArraySeries2;
g_ptrArraySeries2 = nullptr;
}
g_ptrArraySeries2 = new double[g_iTotalInterNum];
memset(g_ptrArraySeries2,0,sizeof(double) * g_iTotalInterNum);
if (g_ptrArraySeries3 != nullptr)
{
delete[] g_ptrArraySeries3;
g_ptrArraySeries3 = nullptr;
}
g_ptrArraySeries3 = new int[g_iWayPointNum];
memset(g_ptrArraySeries3,0,sizeof(int) * g_iWayPointNum);
//获取地面站位置
g_dRoute_GCSlon = m_dGroundLon; //地面站经度
g_dRoute_GCSlat = m_dGroundLat; //地面站纬度
//获取插值点的高程
if(!m_mapElevation2.getElevation(g_fRoute_GCSalt, g_dRoute_GCSlon, g_dRoute_GCSlat))
{
//未获取到高程值
BCGPMessageBox(_T("地面站处无高程信息!"));
return ;
}
//地面站位置的高度在地面站高程的基础上加上方舱高度
g_fRoute_GCSalt += (float)m_dCabinHgt;
//开启线程
hThreadRoute = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFuncAnalysisRoute, NULL, 0, &ThreadIDRoute);
m_bRunRoute = true;
}
else //空文件航点数为0
{
BCGPMessageBox(_T( "空文件!" ));
return ;
}
}
}
//停止航线分析
void CDlgLightRegion::OnBnClickedButtonStopRoute()
{
//关闭线程
m_bRunRoute = false;
g_iInterNumSec = 0;
g_iWayPointNum = 0;
g_iCurWaypoint = 0;
g_iTotalInterNum = 0;
g_totalLinePtNum = 0;
m_pLineTextIndicator->SetText(_T(""));
m_LineTextContainer.RedrawWindow();
pSeries1->RemoveAllDataPoints();
pSeries2->RemoveAllDataPoints();
pSeries3->RemoveAllDataPoints();
pChart->SetDirty(TRUE, TRUE);
m_wndChart.RedrawWindow();
}
//保存航线通视分析结果
void CDlgLightRegion::OnBnClickedButtonSaveImage()
{
CFileDialog dlg (FALSE, _T("bmp"), _T(""), OFN_HIDEREADONLY,
_T("Bitmap Files (*.bmp)|*.bmp|Png Files (*.png)|*.png|All Files (*.*)|*.*||"), this);
if (dlg.DoModal () == IDOK)
{
m_wndChart.ExportToFile(dlg.GetPathName ());
}
}
//清除航线通视分析结果
void CDlgLightRegion::OnBnClickedButtonClearResult()
{
//关闭线程
m_bRunRoute = false;
g_iInterNumSec = 0;
g_iWayPointNum = 0;
g_iCurWaypoint = 0;
g_iTotalInterNum = 0;
g_totalLinePtNum = 0;
m_pLineTextIndicator->SetText(_T(""));
m_LineTextContainer.RedrawWindow();
pSeries1->RemoveAllDataPoints();
pSeries2->RemoveAllDataPoints();
pSeries3->RemoveAllDataPoints();
pChart->SetDirty(TRUE, TRUE);
m_wndChart.RedrawWindow();
//清除航线上的点的标绘图层
::SendMessage(g_mapHwnd, WM_DRAW_LINEPOINT, 0, 0);
}
LRESULT CDlgLightRegion::OnMouseDown(WPARAM /*wp*/, LPARAM lp)
{
BCGPChartHitInfo* pHitInfo = (BCGPChartHitInfo*)lp;
switch (pHitInfo->m_hitInfo)
{
case BCGPChartHitInfo::HIT_DIAGRAM:
CBCGPPoint pt = pHitInfo->m_ptHit;
double dblX = pXAxis->ValueFromPoint(pt);
double dblY = pYAxis->ValueFromPoint(pt);
if (g_ptrArraySeries3 != nullptr && g_iWayPointNum > 2)
{
for (int i=0;i<(g_iWayPointNum-1);i++)
{
if ((dblX >= g_ptrArraySeries3[i]) && (dblX < g_ptrArraySeries3[i+1]))
{
double azAngle = 0;
CalculateTwoPtsAzimuth(azAngle,pts[i].lon, pts[i].lat,pts[i+1].lon,pts[i+1].lat,3);
structPoint _structPoint;
CalculatePtCoordinate(_structPoint.lon, _structPoint.lat, pts[i].lon, pts[i].lat, azAngle, (dblX-g_ptrArraySeries3[i]) * 100, 3);
//发送到地图,标绘曲线上的点在地图上对应的点
::SendMessage(g_mapHwnd, WM_DRAW_LINEPOINT, (WPARAM)&_structPoint, 1);
return 0;
}
}
}
break;
}
return 0;
}
/*-------------------------------------------------------------------------------------------------------------
说明:通视等高线
-------------------------------------------------------------------------------------------------------------*/
//通视等高线分析
void CDlgLightRegion::OnBnClickedButtonContourline()
{
UpdateData(TRUE);
//获取地面站高程信息
if(!m_mapElevation2.getElevation(m_fGroudAlt, m_dGroundLon, m_dGroundLat))
{
//未获取到高程值
BCGPMessageBox(_T("地面站处无高程信息!"));
return ;
}
else
{
//地面站位置的高度在地面站高程的基础上加上方舱高度
m_fGroudAlt += (float)m_dCabinHgt;
}
g_dGroundLonCountour = m_dGroundLon;
g_dGroundLatCountour = m_dGroundLat;
g_fGroundAltCountour = m_fGroudAlt;
if (m_iMaxLosAlt < m_fGroudAlt)
{
BCGPMessageBox(_T("最大高度不允许小于地面站高度!"));
return ;
}
if (m_iMaxLosAlt > 10000)
{
BCGPMessageBox(_T("最大高度不允许超过10000"));
return ;
}
g_iMaxLosAlt = m_iMaxLosAlt;
GetDlgItem(IDC_BUTTON_CONTOURLINE)->EnableWindow(FALSE);
//清除通视等高线绘制图层
::SendMessage(g_mapHwnd,WM_DEL_LINELAYER,0,0);
//开启线程
hThreadContour = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFuncAnalysisContour, NULL, 0, &ThreadIDContour);
m_bRunContour = true;
}
//清除通视等高线
void CDlgLightRegion::OnBnClickedButtonContourDelete()
{
//关闭线程
m_bRunContour = false;
::SendMessage(g_mapHwnd,WM_DEL_LINELAYER,0,0);
GetDlgItem(IDC_BUTTON_CONTOURLINE)->EnableWindow(TRUE);
m_pContourTextIndicator->SetText(_T(""));
m_ContourTextContainer.RedrawWindow();
}
/*-------------------------------------------------------------------------------------------------------------
说明:两点间的通视分析
-------------------------------------------------------------------------------------------------------------*/
//坐标输入分析,根据输入的经纬度获取高程及通视高度
void CDlgLightRegion::OnBnClickedButtonGetAltValue()
{
CString str;
double _ptLon = 0.0, _ptLat = 0.0;
//获取目标点的经度和纬度
GetDlgItem(IDC_EDIT_POINT_LON)->GetWindowText(str);
_ptLon = atof(str);
GetDlgItem(IDC_EDIT_POINT_LAT)->GetWindowText(str);
_ptLat = atof(str);
if ((_ptLon == 0) || (_ptLat == 0) || (_ptLon > 180) || (_ptLon < -180) || (_ptLat > 90) || (_ptLat < -90))
{
BCGPMessageBox(_T("坐标无效!"));
return ;
}
//获取高程
float ptAlt = 0.0f;
if(!m_mapElevation2.getElevation(ptAlt, _ptLon, _ptLat))
{
ptAlt = 0.0f;
}
str.Format(_T("%.1f"),ptAlt);
GetDlgItem(IDC_EDIT_POINT_ALT)->SetWindowText(str);
structPoint _tempPoint;
_tempPoint.lon = _ptLon;
_tempPoint.lat = _ptLat;
//发送到地图,完成标绘
::SendMessage(g_mapHwnd,WM_SEND_REGIONTOGIS,(WPARAM)3,(LPARAM)&_tempPoint);
//通视分析
LosBetweenTwoPoints();
}
//在地图上选点,获取高程并进行通视分析
void CDlgLightRegion::OnBnClickedButtonSelectPtInMap()
{
::SendMessage(g_mapHwnd,WM_SEND_REGIONTOGIS,(WPARAM)1,0);
}
//在对话框里显示选择点的坐标和高程
void CDlgLightRegion::ShowPointPosition(double ptLon, double ptLat)
{
CString str;
str.Format(_T("%.7f"),ptLon);
GetDlgItem(IDC_EDIT_POINT_LON)->SetWindowText(str);
str.Format(_T("%.7f"),ptLat);
GetDlgItem(IDC_EDIT_POINT_LAT)->SetWindowText(str);
//获取高程
float ptAlt = 0.0f;
if(!m_mapElevation2.getElevation(ptAlt, ptLon, ptLat))
{
ptAlt = 0.0f;
}
str.Format(_T("%.1f"),ptAlt);
GetDlgItem(IDC_EDIT_POINT_ALT)->SetWindowText(str);
}
//两点间通视分析
void CDlgLightRegion::LosBetweenTwoPoints()
{
UpdateData(TRUE);
//获取地面站的高程
float _fGroundAlt = 0.0f;
if(!m_mapElevation2.getElevation(_fGroundAlt, m_dGroundLon, m_dGroundLat))
{
//未获取到高程值
BCGPMessageBox(_T("高程信息不全!"));
return ;
}
//地面站位置的高度在地面站高程的基础上加上方舱高度
_fGroundAlt += (float)m_dCabinHgt;
pChart->ShowSeries(FALSE,2);
pSeries1->RemoveAllDataPoints();
pSeries2->RemoveAllDataPoints();
CString str;
double _ptLon = 0.0, _ptLat = 0.0;
//获取目标点的经度和纬度
GetDlgItem(IDC_EDIT_POINT_LON)->GetWindowText(str);
_ptLon = atof(str);
GetDlgItem(IDC_EDIT_POINT_LAT)->GetWindowText(str);
_ptLat = atof(str);
//计算地面站和目标点的距离和方位
double dis = 0.0,angle = 0.0;
CalculateTwoPtsDistanceAzimuth(dis, angle, m_dGroundLon, m_dGroundLat, _ptLon, _ptLat, 3);
double _dTanMaxSlope = -1000.0; //最大斜率
double _fMinLOSAlt = 0.0; //最小通视高度
double _tempSlope = 0.0; //当前点与地面站的连线的斜率
//采样点位置
double interPolLon = 0.0, interPolLat = 0.0;
float interPolHight = 0.0;
//以30为采样间距计算插值个数
int interPolDis = 30;
int interPolNum = (int)(dis/interPolDis);
for(int i = 0; i <= interPolNum; i++)
{
CalculatePtCoordinate(interPolLon, interPolLat, m_dGroundLon, m_dGroundLat, angle, i*interPolDis, 3);
//获取采样点的高程
if(!m_mapElevation2.getElevation(interPolHight, interPolLon, interPolLat))
{
//未获取到高程值
BCGPMessageBox(_T("高程信息不全!"));
return ;
}
//计算该点与地面站连线的斜率
_tempSlope = CalSlopeBetweenTwoPoint(m_dGroundLon, m_dGroundLat, _fGroundAlt, interPolLon, interPolLat, interPolHight);
//与前面所有点的最大斜率比较,取最大值
_dTanMaxSlope = max(_tempSlope,_dTanMaxSlope);
//计算该点的最小通视高度
_fMinLOSAlt = (float)CalAltFromSlope(m_dGroundLon, m_dGroundLat, _fGroundAlt, interPolLon, interPolLat, _dTanMaxSlope);
pSeries1->AddDataPoint(interPolHight,i*interPolDis);
pSeries2->AddDataPoint(_fMinLOSAlt,i*interPolDis);
}
pChart->SetAutoDisplayRange(TRUE, TRUE);
pChart->SetDirty(TRUE, TRUE);
m_wndChart.RedrawWindow();
//显示最小通视高度
str.Format(_T("%.1f"),_fMinLOSAlt);
GetDlgItem(IDC_EDIT_POINT_LOS)->SetWindowText(str);
}
//清除地面站与目标点连线,以及分析结果
void CDlgLightRegion::OnBnClickedButtonClearLineLayer()
{
//清除目标点和连线图层
::SendMessage(g_mapHwnd,WM_SEND_REGIONTOGIS,(WPARAM)2,0);
//清除分析结果图标
pSeries1->RemoveAllDataPoints();
pSeries2->RemoveAllDataPoints();
pSeries3->RemoveAllDataPoints();
m_wndChart.RedrawWindow();
}
//反向通视分析
void CDlgLightRegion::OnBnClickedButtonReverse()
{
UpdateData(TRUE);
CString str;
double _ptLon = 0.0, _ptLat = 0.0;
//获取目标点的经度和纬度
GetDlgItem(IDC_EDIT_POINT_LON)->GetWindowText(str);
_ptLon = atof(str);
GetDlgItem(IDC_EDIT_POINT_LAT)->GetWindowText(str);
_ptLat = atof(str);
//获取地面站的高程
float _fGroundAlt = 0.0f;
if(!m_mapElevation2.getElevation(_fGroundAlt, _ptLon, _ptLat))
{
//未获取到高程值
BCGPMessageBox(_T("高程信息不全!"));
return ;
}
//地面站位置的高度在地面站高程的基础上加上方舱高度
_fGroundAlt += (float)m_dCabinHgt;
pChart->ShowSeries(FALSE,2);
pSeries1->RemoveAllDataPoints();
pSeries2->RemoveAllDataPoints();
//计算地面站和目标点的距离和方位
double dis = 0.0,angle = 0.0;
CalculateTwoPtsDistanceAzimuth(dis, angle, _ptLon, _ptLat, m_dGroundLon, m_dGroundLat, 3);
double _dTanMaxSlope = -1000.0; //最大斜率
double _fMinLOSAlt = 0.0; //最小通视高度
double _tempSlope = 0.0; //当前点与地面站的连线的斜率
//采样点位置
double interPolLon = 0.0, interPolLat = 0.0;
float interPolHight = 0.0;
//以30为采样间距计算插值个数
int interPolDis = 30;
int interPolNum = (int)(dis/interPolDis);
for(int i = 0; i <= interPolNum; i++)
{
CalculatePtCoordinate(interPolLon, interPolLat, _ptLon, _ptLat, angle, i*interPolDis, 3);
//获取采样点的高程
if(!m_mapElevation2.getElevation(interPolHight, interPolLon, interPolLat))
{
//未获取到高程值
BCGPMessageBox(_T("高程信息不全!"));
return ;
}
//计算该点与地面站连线的斜率
_tempSlope = CalSlopeBetweenTwoPoint(_ptLon, _ptLat, _fGroundAlt, interPolLon, interPolLat, interPolHight);
//与前面所有点的最大斜率比较,取最大值
_dTanMaxSlope = max(_tempSlope,_dTanMaxSlope);
//计算该点的最小通视高度
_fMinLOSAlt = (float)CalAltFromSlope(_ptLon, _ptLat, _fGroundAlt, interPolLon, interPolLat, _dTanMaxSlope);
pSeries1->AddDataPoint(interPolHight,i*interPolDis);
pSeries2->AddDataPoint(_fMinLOSAlt,i*interPolDis);
}
pChart->SetAutoDisplayRange(TRUE, TRUE);
pChart->SetDirty(TRUE, TRUE);
m_wndChart.RedrawWindow();
}
//标绘作战范围
void CDlgLightRegion::OnBnClickedButtonDrawFight()
{
UpdateData(TRUE);
structPoint _structPoint;
_structPoint.lon = m_dGroundLon;
_structPoint.lat = m_dGroundLat;
//发送到地图,绘制作战范围
::SendMessage(g_mapHwnd, WM_SEND_DRAWFIGHT, WPARAM(&_structPoint), LPARAM(m_iFightRegion*1000));
}
//清除作战范围
void CDlgLightRegion::OnBnClickedButtonDeleteFight()
{
::SendMessage(g_mapHwnd, WM_SEND_DRAWFIGHT, 0, 0);
}
//标绘高程数据区域
void CDlgLightRegion::OnBnClickedButtonGetDemRegion()
{
CString _DEMpath = GetSoftwareCurrentDirectory() + _T("\\ElevationData");
//文件句柄
long hFile = 0;
//文件信息
struct _finddata_t fileinfo;
string p;
if((hFile = _findfirst(p.assign(_DEMpath.GetBuffer()).append("\\*").c_str(),&fileinfo)) != -1)
{
int _fileNum = 0;
char fileName[3];
structPoint _structPoint;
char _flag;
do
{
if((fileinfo.attrib & _A_SUBDIR))
{
;
}
else
{
//处理遍历到的文件名
memset(fileName,0,3);
memset(&_structPoint,0,sizeof(structPoint));
//纬度
memcpy(fileName, fileinfo.name+8, 2);
_structPoint.lat = atof(fileName);
memcpy(&_flag, fileinfo.name+7, 1);
if ('S' == _flag)
{
_structPoint.lat = 0 - _structPoint.lat;
}
//经度
memcpy(fileName, fileinfo.name+11, 3);
_structPoint.lon = atof(fileName);
memcpy(&_flag, fileinfo.name+10, 1);
if ('W' == _flag)
{
_structPoint.lon = 0 - _structPoint.lon;
}
_fileNum++;
::SendMessage(g_mapHwnd, WM_SEND_DRAWDEMREGION, WPARAM(&_structPoint), LPARAM(_fileNum));
}
}while(_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
_DEMpath.ReleaseBuffer();
}