⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 carnaviview.cpp

📁 手持PDA汽车导航程序源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

	//简单绘制一个"蓝色方块"来表示目的地
	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 + -