📄 carnaviview.cpp
字号:
//简单绘制一个"蓝色方块"来表示目的地
pntDraw = m_pntTo;
m_MapWnd.GetDrawParam()->MapToClient( &pntDraw, 1 );
pDC->FillSolidRect( pntDraw.x-5, pntDraw.y-5, 10, 10, RGB(0,0,255) );
}
//}}路径分析
void CCarNaviView::OnTimer(UINT nIDEvent)
{
if( nIDEvent == TIMER_SIMULATION )
{//模拟导航
NaviSimulate();
}
else if( nIDEvent == TIMER_REAL )
{//真是导航
NaviReal();
}
CView::OnTimer(nIDEvent);
}
//{{GPS相关
void CCarNaviView::OnGpsOpen()
{
//如果已经打开过,就先关闭,然后再打开
if( m_bGPSOpened )
{
m_GPSReceiver.Close();
}
// 假定GPS设备参数为: 4800, 8, N, 1
CSeCommPortInfo CommPortInfo;
//CommPortInfo.dwBaudRate = 4800; //波特率 4800
CommPortInfo.dwBaudRate = 9600; //波特率 9600
CommPortInfo.btDataBits = 8; //数据位 8
CommPortInfo.btParity = SE_PARITY_NONE; //校验位 N
CommPortInfo.btStopBits = SE_STOPBITS_1; //停止位 1
// 假定PDA使用COM4为GPS设备的连接端口
CommPortInfo.btCommPort = 4; //端口位 COM4
// 假定GPS设备输出 NMEA0183 协议数据, 则选用NMEA0183协议解析器
CSeGPS::Type nPaserType = CSeGPS::NMEA0183;
m_bGPSOpened = m_GPSReceiver.Open( CommPortInfo, nPaserType );
if( m_bGPSOpened )
{
AfxMessageBox( _T("连接GPS成功!") );
//如果连接成功, 则设置Timer时间
//SetTimer();
}
else
{
AfxMessageBox( _T("连接GPS失败!") );
}
}
void CCarNaviView::OnGpsClose()
{
//关闭GPS设备
if( m_bGPSOpened )
{
m_GPSReceiver.Close();
}
}
void CCarNaviView::OnGpsShowData()
{
//如果打开成功了才有可能取出解析好的GPS数据
if( m_bGPSOpened )
{
//如果获取数据成功, 就用某一种方式来表现他
if( m_GPSReceiver.GetData( m_GPSData ) )
{
//在这里,简单用一个字符串来表现。
//在具体的应用中,可以用一个对话框来显示各项GPS数据
//从GPS解析出来的经纬度数据以 0.01 秒为单位
long nLongitudeDu = m_GPSData.dwLongitude / 360000;
long nLongitudeFen = ( m_GPSData.dwLongitude % 360000 ) / 6000;
long nLongitudeMiao = ( m_GPSData.dwLongitude % 360000 ) % 6000;
long nLatitudeDu = m_GPSData.dwLatitude / 360000;
long nLatitudeFen = ( m_GPSData.dwLatitude % 360000 ) / 6000;
long nLatitudeMiao = ( m_GPSData.dwLatitude % 360000 ) % 6000;
//从GPS解析出来的速度以 厘米/小时 为单位 --> 在此转为 米/秒
double dSpeed = m_GPSData.dwSpeed / 100.0 / 3600;
//从GPS解析出来的角度以 0.01度 为单位 --> 在此转为 度
double dDirection = m_GPSData.wBearing / 100.0;
CString strGPSMsg;
strGPSMsg.Format( _T(" 经度=%d:%d:%d\n 纬度=%d:%d:%d\n 速度=%.2f\n 方向=%.2f\n 可见卫星数=%d\n"),
nLongitudeDu, nLongitudeFen, nLongitudeMiao,
nLatitudeDu, nLatitudeFen, nLatitudeMiao,
dSpeed, dDirection, m_GPSData.btSatellites );
AfxMessageBox( strGPSMsg );
}
}
}
void CCarNaviView::OnGpsShowSatStatus()
{
//如果打开成功了才有可能取出解析好的GPS数据
if( m_bGPSOpened )
{
//如果获取数据成功, 就用某一种方式来表现他
BYTE btSatCount = 0;
if( m_GPSReceiver.GetSatellitesData( m_GPSSatData, 12, btSatCount ) )
{
//在这里,简单用一个字符串来表现。
//在具体的应用中,可以用一个对话框来显示各个卫星的状态图
CString strGPSMsg( _T("编号,方位角,高度角,信噪比\n" ) );
if( btSatCount > 0 )
{
CString strSatMsg;
for( BYTE i=0; i<btSatCount; i++ )
{
strSatMsg.Format( _T(" %d, %d, %d, %d\n"),
m_GPSSatData[i].btSatelliteID, m_GPSSatData[i].nAzimuth,
m_GPSSatData[i].btElevation, m_GPSSatData[i].nSignal );
strGPSMsg += strSatMsg;
}
}
else
{
strGPSMsg = _T("没有可用卫星");
}
AfxMessageBox( strGPSMsg );
}
}
}
void CCarNaviView::OnGpsShowOnMap()
{
//如果打开成功了才有可能取出解析好的GPS数据
if( m_bGPSOpened )
{
//如果获取数据成功, 就用某一种方式来表现他
if( m_GPSReceiver.GetData( m_GPSData ) )
{
//在这里,简单用一个字符串来表现。
//在具体的应用中,可以用一个对话框来显示各项GPS数据
//从GPS解析出来的经纬度数据以 0.01 秒为单位, 在此转成 与 数据源坐标系统一直的单位 0.001秒
m_pntGPS.x = m_GPSData.dwLongitude * 10;
m_pntGPS.y = m_GPSData.dwLatitude * 10;
m_bShowGPSonMap = !m_bShowGPSonMap;
//刷新地图
m_MapWnd.SetCenter( m_pntGPS );
m_MapWnd.Refresh();
}
else
{
AfxMessageBox( _T("读不到GPS数据") );
}
}
else
{
AfxMessageBox( _T("没有打开GPS设备") );
}
}
void CCarNaviView::OnUpdateGpsShowOnMap(CCmdUI* pCmdUI)
{
//在选中的菜单项上打勾以做标识
pCmdUI->SetCheck( m_bShowGPSonMap );
}
void CCarNaviView::DrawGPSonMap( CDC *pDC )
{
CPoint pntDraw( m_pntGPS );
//转换成屏幕坐标
m_MapWnd.GetDrawParam()->MapToClient( &pntDraw, 1 );
//在这里,简单绘制一个"红色方块"来表现。
//在具体的应用中,可以用一个有意义的图标来显示
pDC->FillSolidRect( pntDraw.x-3, pntDraw.y-3, 6, 6, RGB( 0, 255, 0 ) );
//显示导航信息
if( m_strNaviInfo.GetLength() > 0 )
{
CRect rc( 5, 30, 155, 50 );
pDC->DrawText( m_strNaviInfo, &rc, 0 );
}
}
//}}GPS相关
//================================================================================
//{{导航相关
void CCarNaviView::OnNaviReal()
{
if( m_arrArcIDs.GetSize() > 0 )
{
m_bNaviReal = !m_bNaviReal; //模拟导航
if( m_bNaviReal )
{
m_bNaviSimulate = false; //真实导航
//开始导航
StartNavigate();
}
else
{
KillTimer( TIMER_SIMULATION );
KillTimer( TIMER_REAL );
}
}
else
{
AfxMessageBox( _T("没有路径!") );
}
}
void CCarNaviView::OnUpdateNaviReal(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck( m_bNaviReal );
}
void CCarNaviView::OnNaviSimulate()
{
if( m_arrArcIDs.GetSize() > 0 )
{
m_bNaviSimulate = !m_bNaviSimulate; //模拟导航
if( m_bNaviSimulate )
{
m_bNaviReal = false; //真实导航
//开始导航
StartNavigate();
}
else
{
KillTimer( TIMER_SIMULATION );
KillTimer( TIMER_REAL );
}
}
else
{
AfxMessageBox( _T("没有路径!") );
}
}
void CCarNaviView::OnUpdateNaviSimulate(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck( m_bNaviSimulate );
}
void CCarNaviView::StartNavigate()
{
//======================================
//{{初始化导航变量
m_nCurArcID = -3;
m_dDistanceToTurn = 0;
m_dAngleToTurn = 0;
m_nNextArcID = -3;
m_dDistanceToNext = 0;
m_dAngleToNext = 0;
m_nNextNodeID = -3;
//}}初始化导航变量
//{{构造导航路径
m_Navigator.MakePath( m_PathAnalyst.GetDatasetNetwork(),
(long *)m_arrArcIDs.GetData(), m_arrArcIDs.GetSize(),
(long *)m_arrNodeIDs.GetData(), m_arrNodeIDs.GetSize() );
//}}构造导航路径
if( m_bNaviSimulate )
{//模拟导航需要提取路经点
//清空原来的值
m_arrSimulatePoints.RemoveAll();
m_nGPSPointIndex = 0;
m_nGPSPointCount = 0;
//{{沿着导航路线采集模拟点
CPoint* pPoints = NULL;
long nPointCount = 0;
m_Navigator.GetPath( pPoints, nPointCount );
CSeGeoLine geoLine;
geoLine.Make( pPoints, nPointCount );
CSeGeoLine geoResampleLine;
//10.0m/s == 36km/h
geoLine.ResampleEquidistantly( geoResampleLine, 20.0, true, 1.0, 6238245 );
m_nGPSPointCount = geoResampleLine.GetPointCount();
m_arrSimulatePoints.SetSize( m_nGPSPointCount );
memcpy( m_arrSimulatePoints.GetData(), geoResampleLine.GetPoints(),
sizeof( CSePoint2D ) * m_nGPSPointCount );
delete []pPoints;
pPoints = NULL;
//}}沿着导航路线采集模拟点
SetTimer( TIMER_SIMULATION, 500, NULL);
}
else
{//真实导航
SetTimer( TIMER_REAL, 1000, NULL );
}
m_bShowGPSonMap = true;
}
//真是导航
void CCarNaviView::NaviReal()
{
if( m_GPSReceiver.GetData( m_GPSData ) && m_GPSData.btQualityIndicator > 0 )
{
CPoint pntCar;
//纬度:传进来的是0.01秒。我们的是0.001秒乘以10就行了
pntCar.x = m_GPSData.dwLatitude*10;
//经度:传进来的是0.01秒。我们的是0.001秒乘以10就行了
pntCar.y = m_GPSData.dwLongitude*10;
//行走方向, 北偏东的角度,传进来的是0.01度,这个不用太精确
double dBearing = m_GPSData.wBearing * PI / 18000.0;
//导航吧
Navigate( pntCar, dBearing );
}
}
//模拟导航
void CCarNaviView::NaviSimulate()
{
if( m_nGPSPointIndex < m_nGPSPointCount-1 )
{
//计算偏转角度
double dBearing = PI / 2 - atan2( m_arrSimulatePoints[m_nGPSPointIndex+1].y -
m_arrSimulatePoints[m_nGPSPointIndex].y,
m_arrSimulatePoints[m_nGPSPointIndex+1].x -
m_arrSimulatePoints[m_nGPSPointIndex].x );
if( dBearing < 0 )
{
dBearing += PI * 2;
}
//导航
Navigate( m_arrSimulatePoints[m_nGPSPointIndex], dBearing );
m_nGPSPointIndex++;
}
else
{
//最后一个点了
if( m_nGPSPointCount > 0 )
{
Navigate( m_arrSimulatePoints[m_nGPSPointIndex-1], 0 );
}
m_nGPSPointIndex = 0;
KillTimer( TIMER_SIMULATION );
}
}
//导航处理
bool CCarNaviView::Navigate( CPoint& pntCar, double dBearing )
{
//导航处理
DWORD dwRet = m_Navigator.Navigate( pntCar );
if( dwRet == NAV_OK )
{//正常导航....
//导航信息
long nCurArcID = -2;
long nNextArcID = -2;
long nNextNodeID = -2;
//获取导航信息
if( m_Navigator.GetRouteInfo( nCurArcID, m_dDistanceToTurn, m_dAngleToTurn,
nNextArcID, m_dDistanceToNext, m_dAngleToNext, nNextNodeID ) )
{
if( m_nNextArcID == -1 )
{//在最后一个路段上
}
else
{
CString strDirection( _T("右") );
if( m_dAngleToTurn < 0 )
{
m_dAngleToTurn = -m_dAngleToTurn;
strDirection = _T("左");
}
//简单用一个字符串表示"导航信息", 实际应用实可以用一些图标来表示
m_strNaviInfo.Format( _T("前方%.2f米%s转%.2f度"), m_dDistanceToTurn, strDirection, m_dAngleToTurn );
}
}
m_pntGPS = pntCar;
m_MapWnd.Refresh();
return true;
}
else if( dwRet == NAV_WRONG_DIRECTION )
{//方相反了
m_strNaviInfo = _T("方相反了");
m_pntGPS = pntCar;
m_MapWnd.Refresh();
}
else if( dwRet == NAV_WRONG_POSITION )
{//偏离航道
m_strNaviInfo = _T("偏离航道");
m_pntGPS = pntCar;
//调整出发点, 吧当前位置为做出发点
m_pntFrom = pntCar;
m_MapWnd.SetCenter( m_pntFrom );
//重新进行路径分析吧, 实际应用中, 应该判断连续 N 次偏离航道后才重新开始计算路径
PathAnalysing();
//重新开始导航
StartNavigate();
//刷新地图
m_MapWnd.Refresh();
return false;
}
return false;
}
//}}导航相关
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -