void CPage_Node_Phase::DrawLink(CPaintDC* pDC,GDPoint pt_from, GDPoint pt_to,int NumberOfLanes, double theta, int lane_width)
{
	CPoint DrawPoint[4];

	//then offset
	int link_offset = lane_width;

	pt_from.x += link_offset* cos(theta-PI/2.0f);
	pt_to.x += link_offset* cos(theta-PI/2.0f);

	pt_from.y += link_offset* sin(theta-PI/2.0f);
	pt_to.y += link_offset* sin(theta-PI/2.0f);

	DrawPoint[0] = NPtoSP(pt_from);
	DrawPoint[1] = NPtoSP(pt_to);

	link_offset = min(5,NumberOfLanes)*lane_width ;
	pt_from.x += link_offset* cos(theta-PI/2.0f);
	pt_to.x += link_offset* cos(theta-PI/2.0f);

	pt_from.y += link_offset* sin(theta-PI/2.0f);
	pt_to.y += link_offset* sin(theta-PI/2.0f);

	DrawPoint[2] = NPtoSP(pt_to);
	DrawPoint[3] = NPtoSP(pt_from);

	pDC->Polygon(DrawPoint, 4);

}
void CPage_Node_Lane::DrawLinkPinPoint(CPaintDC *pDC, LinkRecord *pRecord, bool bOriginAngle /* = true */)
{
	GDPoint cntPoint,lefttop,bottomright;
	CRect centerRect;
	int nR5 = m_Para.nR5;
	int nDis = m_Para.nLaneWidth;
	double theta = bOriginAngle ? pRecord->dTheta : pRecord->dNormTheta;
	int i = (pRecord->nChnlNum+pRecord->nLaneNum+pRecord->nPcktNum + 1) / 2 ;

	if ( pRecord->nIO == 1)
	{
		nDis = -1 * nDis;
	}
	cntPoint.x	= nR5 * cos(theta) + i * nDis * cos(theta-PI/2.0f);
	cntPoint.y	= nR5 * sin(theta) + i * nDis * sin(theta-PI/2.0f);
	
	int nRadius2 = m_Para.nPinPointRadius;
	lefttop.x = cntPoint.x - nRadius2;
	lefttop.y = cntPoint.y - nRadius2;
	bottomright.x = cntPoint.x + nRadius2;
	bottomright.y = cntPoint.y + nRadius2;
	
	centerRect = CRect(NPtoSP(lefttop),NPtoSP(bottomright));
	pDC->Ellipse(centerRect);
}
void CPage_Node_Lane::DrawCentroidRadicalLines(CPaintDC *pDC, CRect PlotRect,bool bOriginAngle/*=true*/)
{
	CPen blackPen(PS_SOLID,0,RGB(0,0,0));
	CPen greyPen(PS_SOLID,2,RGB(128,128,128));
	CPen lanePen(PS_SOLID,1,RGB(0,0,0));
	CPen laneSelectedPen(PS_SOLID,2,RGB(255,0,0));

	CBrush  greyBrush(RGB(128,128,128)); 
	CBrush  whiteBrush(RGB(255,255,255)); 
	CBrush  redBrush(RGB(255,0,0)); 

	pDC->SetBkMode(TRANSPARENT);
	CPen *pOldPen = pDC->SelectObject(&blackPen);
	CBrush* pOldBrush = pDC->SelectObject(&whiteBrush);
	pDC->Rectangle(PlotRect);

	GDPoint cntPoint,lefttop,bottomright;
	CRect centerRect;

	cntPoint.x = 0.0;
	cntPoint.y = 0.0;
	int nRadius2 = m_Para.nCentroidRadius;
	lefttop.x = cntPoint.x - nRadius2;
	lefttop.y = cntPoint.y - nRadius2;
	bottomright.x = cntPoint.x + nRadius2;
	bottomright.y = cntPoint.y + nRadius2;
	
	pDC->SelectObject(&greyPen);
	pDC->SelectObject(&greyBrush);
	centerRect = CRect(NPtoSP(lefttop),NPtoSP(bottomright));
	pDC->Ellipse(centerRect);

	for(int i=0;i<m_LinkData.size();i++)
	{
		LinkRecord *pRecord = m_LinkData[i];
		pDC->SelectObject(&greyPen);
		DrawRadicalLine(pDC,pRecord,bOriginAngle);
		pDC->SelectObject(&lanePen);
		pDC->SelectObject(&greyBrush);
		DrawLanes(pDC,pRecord,bOriginAngle);
		pDC->SelectObject(&blackPen);
		if (pRecord->nLinkID == m_nSelectedLinkID)
			pDC->SelectObject(&redBrush);
		DrawLinkPinPoint(pDC,pRecord,bOriginAngle);
	}

	// draw selected link pin point

	pDC->SelectObject(pOldPen);
	pDC->SelectObject(pOldBrush);
	
}
void CPage_Node_Lane::DrawRadicalLine(CPaintDC *pDC, LinkRecord *pRecord,bool bOriginAngle /* = true*/)
{
	GDPoint p1,p2;
	int nR1 = m_Para.nR1;
	int nR2 = m_Para.nR2;
	double theta = bOriginAngle ? pRecord->dTheta : pRecord->dNormTheta;

	p1.x	= nR1 * cos(theta);
	p1.y	= nR1 * sin(theta);
	
	p2.x	= nR2 * cos(theta);
	p2.y	= nR2 * sin(theta);

	pDC->MoveTo(NPtoSP(p1));
	pDC->LineTo(NPtoSP(p2));
}
int CPage_Node_Lane::FindClickedLink(CPoint pt,bool bOriginAngle /* = true */)
{
	int nRtLinkID = -1;
	for(int j=0;j<m_LinkData.size();j++)
	{
		LinkRecord* pRecord = m_LinkData[j];
		GDPoint cntPoint,lefttop,bottomright;
		CRect centerRect;
		int nR5 = m_Para.nR5;
		int nDis = m_Para.nLaneWidth;
		double theta = bOriginAngle ? pRecord->dTheta : pRecord->dNormTheta;
		int i = (pRecord->nChnlNum+pRecord->nLaneNum+pRecord->nPcktNum + 1) / 2 ;

		if ( pRecord->nIO == 1)
		{
			nDis = -1 * nDis;
		}
		cntPoint.x	= nR5 * cos(theta) + i * nDis * cos(theta-PI/2.0f);
		cntPoint.y	= nR5 * sin(theta) + i * nDis * sin(theta-PI/2.0f);
		
		int nRadius2 = m_Para.nPinPointRadius;
		lefttop.x = cntPoint.x - nRadius2;
		lefttop.y = cntPoint.y - nRadius2;
		bottomright.x = cntPoint.x + nRadius2;
		bottomright.y = cntPoint.y + nRadius2;
		
		centerRect = CRect(NPtoSP(lefttop),NPtoSP(bottomright));
		centerRect.NormalizeRect();
		if ( centerRect.PtInRect(pt) )
		{
			nRtLinkID = pRecord->nLinkID;
			break;
		}
	}
	return nRtLinkID;
}
void CPage_Node_Phase::DrawMovements(CPaintDC* pDC,CRect PlotRect, bool bPhaseWindow =false)
{

	m_MovementBezierVector.clear();

	CPen NormalPen(PS_SOLID,2,RGB(0,0,0));
	CPen TimePen(PS_DOT,1,RGB(0,0,0));

	CPen DASHPen(PS_SOLID,1,RGB(255,178,102));

	CPen DataPen(PS_SOLID,0,RGB(0,0,0));
	CPen SelectedPen(PS_SOLID,3,RGB(255,0,0));
	CPen SelectedPhasePen(PS_SOLID,4,RGB(0,0,255));

	CBrush  WhiteBrush(RGB(255,255,255)); 

	pDC->SetBkMode(TRANSPARENT);
	pDC->SelectObject(&DataPen);
	pDC->SelectObject(&WhiteBrush);

	pDC->Rectangle (PlotRect);

	CString str;

	if(bPhaseWindow == true )
	{
		str.Format("Phase %d",m_SelectedPhaseNumber);
		pDC->TextOutA(PlotRect.left+10,PlotRect.top +5,str);


	}


	CBrush  BrushLinkBand(RGB(152,245,255)); 
	pDC->SelectObject(&BrushLinkBand);

	DTANode* pNode  = m_pDoc->m_NodeNoMap [m_CurrentNodeID];

	int node_size = 10;
	int node_set_back = 50;

	int link_length = 100;
	int lane_width = 10;
	int text_length = link_length+ 20;

	str.Format("%d",m_CurrentNodeNumber);

	if(bPhaseWindow == false || m_SelectedPhaseNumber == 1)
		pDC->TextOutA( PlotRect.CenterPoint().x-5, PlotRect.CenterPoint().y-5,str);

	for (unsigned int i=0;i< pNode->m_MovementDataMap["ALLDAY"].m_MovementVector .size();i++)
	{
		DTANodeMovement movement = pNode->m_MovementDataMap["ALLDAY"].m_MovementVector[i];

		if( m_pDoc->m_hide_non_specified_movement_on_freeway_and_ramp && movement.bNonspecifiedTurnDirectionOnFreewayAndRamps && i != m_SelectedMovementIndex)
			continue;



		DTALink* pInLink  = m_pDoc->m_LinkNoMap [movement.IncomingLinkNo];
		DTALink* pOutLink  = m_pDoc->m_LinkNoMap [movement.OutgoingLinkNo ];

		GDPoint p1, p2, p3;
		// 1: fetch all data
		p1  = m_pDoc->m_NodeNoMap[movement.in_link_from_node_id ]->pt;
		p2  = m_pDoc->m_NodeNoMap[movement.in_link_to_node_id ]->pt;
		p3  = m_pDoc->m_NodeNoMap[movement.out_link_to_node_id]->pt;

		double DeltaX = p2.x - p1.x ;
		double DeltaY = p2.y - p1.y ;
		double theta = atan2(DeltaY, DeltaX);

		GDPoint p1_new, p2_new, p3_new;
		GDPoint p1_text, p3_text;
		GDPoint pt_movement[3];


		// 2. set new origin
		p2_new.x = (-1)*node_set_back*cos(theta);  
		p2_new.y = (-1)*node_set_back*sin(theta);


		int link_mid_offset  = (pInLink->m_NumberOfLanes/2 +1)*lane_width;  // mid

		pt_movement[0].x = p2_new.x + link_mid_offset* cos(theta-PI/2.0f);
		pt_movement[0].y = p2_new.y + link_mid_offset* sin(theta-PI/2.0f);

		// 3 determine the control point for  PolyBezier
		float control_point_ratio = 0;
		if(movement.movement_turn == DTA_Through ) 
		{
			control_point_ratio = 0;
		}else if(movement.movement_turn == DTA_LeftTurn ) 
		{
			control_point_ratio = 1.2;
		}else
		{
			control_point_ratio = 0.5;
		}

		pt_movement[1].x = pt_movement[0].x + node_set_back*control_point_ratio*cos(theta);
		pt_movement[1].y = pt_movement[0].y + node_set_back*control_point_ratio*sin(theta);


		if(bPhaseWindow == true)
		{
			link_length = 1;
			text_length = node_set_back+10;
		}

		p1_new.x = (-1)*link_length*cos(theta);
		p1_new.y = (-1)*link_length*sin(theta);


		p1_text.x= (-1)*(text_length)*cos(theta);
		p1_text.y= (-1)*(text_length)*sin(theta);

		// 4: draw from node name

		str.Format("%d",m_pDoc->m_NodeNoMap [movement.in_link_from_node_id]->m_NodeNumber );


		if(p1_text.y < -50)
			p1_text.y +=10;

		CPoint pt_text = NPtoSP(p1_text);

		if(bPhaseWindow == false  || m_SelectedPhaseNumber == 1)
		{
			pDC->SetTextColor(RGB(0,0,255));
			pDC->TextOutA(pt_text.x-10,pt_text.y,str);
			pDC->SetTextColor(RGB(0,0,0));
		}

		if(bPhaseWindow == false)
			DrawLink(pDC,p1_new,p2_new,pInLink->m_NumberOfLanes,theta,lane_width);

		////////////////////////////////////////////
		//5: outgoing link
		DeltaX = p3.x - p2.x ;
		DeltaY = p3.y - p2.y ;
		theta = atan2(DeltaY, DeltaX);

		// set new origin
		p2_new.x = node_set_back*cos(theta);  
		p2_new.y = node_set_back*sin(theta);

		link_mid_offset  = (pOutLink->m_NumberOfLanes/2+1)*lane_width;
		pt_movement[2].x = p2_new.x + link_mid_offset* cos(theta-PI/2.0f);
		pt_movement[2].y = p2_new.y + link_mid_offset* sin(theta-PI/2.0f);


		p3_new.x = link_length*cos(theta);
		p3_new.y = link_length*sin(theta);

		p3_text.x= text_length*cos(theta);
		p3_text.y= text_length*sin(theta);

		if(bPhaseWindow == false)
			DrawLink(pDC,p2_new,p3_new,pOutLink->m_NumberOfLanes,theta,lane_width);

		DTALink * pRevLink = NULL; //reversed link
		unsigned long ReversedLinkKey = m_pDoc->GetLinkKey(pOutLink->m_ToNodeID, pOutLink->m_FromNodeID);

		int reversed_link_id = 0;
		if ( m_pDoc->m_NodeNotoLinkMap.find ( ReversedLinkKey) == m_pDoc->m_NodeNotoLinkMap.end())
		{
			str.Format("%d",m_pDoc->m_NodeNoMap [movement.out_link_to_node_id ]->m_NodeNumber );

			if(p3_text.y < -50)
				p3_text.y +=10;

			pt_text = NPtoSP(p3_text);

			if(bPhaseWindow == false  || m_SelectedPhaseNumber == 1)
				pDC->TextOutA(pt_text.x-10,pt_text.y,str);

		}



		// draw movement 

		CPoint Point_Movement[4];



		if(i == m_SelectedMovementIndex)
		{
			pDC->SelectObject(&SelectedPen);
		}
		else
		{
			//if(m_ListCtrl.GetItemText (i,4).Find("Prohibited") != -1) 			// select prohibited movement pen: 
			//	pDC->SelectObject(&g_PenProhibitedMovement);
			//else
			//	pDC->SelectObject(&NormalPen);
		}

		if(movement.movement_turn == DTA_LeftTurn )
		{
			float weight = 0.9;
			pt_movement[1].x = (1-weight)*(pt_movement[0].x + pt_movement[2].x)/2 +0*weight;
			pt_movement[1].y = (1-weight)*(pt_movement[0].y + pt_movement[2].y)/2 +0*weight;
		}

		Point_Movement[0]= NPtoSP(pt_movement[0]);
		Point_Movement[1]= NPtoSP(pt_movement[1]);
		Point_Movement[2]= NPtoSP(pt_movement[1]);
		Point_Movement[3]= NPtoSP(pt_movement[2]);

		Point_Movement[0]= NPtoSP(pt_movement[0]);
		Point_Movement[1]= NPtoSP(pt_movement[1]);
		Point_Movement[2]= NPtoSP(pt_movement[1]);
		Point_Movement[3]= NPtoSP(pt_movement[2]);

		MovementBezier element(Point_Movement[0], Point_Movement[1],Point_Movement[3]);

		m_MovementBezierVector.push_back (element);

		if(m_bHideRightTurnMovement &&( pNode->m_MovementDataMap["ALLDAY"].m_MovementVector[i].movement_turn == DTA_RightTurn ||  pNode->m_MovementDataMap["ALLDAY"].m_MovementVector[i].movement_turn == DTA_RightTurn2))
			continue;

		bool bMovementIncluded = false;

		if(m_SelectedPhaseNumber >=1)
		{
			bMovementIncluded = m_pDoc->IfMovementIncludedInPhase(m_CurrentNodeNumber ,m_pDoc->m_TimingPlanVector [ m_SelectedTimingPlanNo].timing_plan_name,m_SelectedPhaseNumber, movement.in_link_from_node_id,movement.out_link_to_node_id );
		}

		if(m_SelectedPhaseNumber <=0 ||  /* all phases*/
			m_SelectedPhaseNumber>=1 && ( bMovementIncluded == true || m_bPhasingDataEditMode) )  // seleted phase
		{


			pDC->SelectObject(&NormalPen);

			if(m_SelectedPhaseNumber>=1 && m_bPhasingDataEditMode)
			{
				if(  bMovementIncluded == true)
					pDC->SelectObject(&NormalPen);
				else
					pDC->SelectObject(&DASHPen);

			}

			if(i == m_SelectedMovementIndex && m_bPhasingDataEditMode)
			{
				pDC->SelectObject(&SelectedPen);
			}

			//overwrite
			if(i == m_SelectedMovementIndex)
			{
				pDC->SelectObject(&SelectedPen);
			}

			pDC->PolyBezier(Point_Movement,4);

			bool bShowArrow = false;

			if(m_SelectedPhaseNumber>=1 &&  bMovementIncluded == true)
			{
				bShowArrow = true;

			}
			if(bShowArrow)
			{
				CPoint FromPoint = Point_Movement[2] ; 
				CPoint ToPoint = Point_Movement[3];


				CPoint arrow_pts[3];
				double slopy = atan2((double)(FromPoint.y - ToPoint.y), (double)(FromPoint.x - ToPoint.x));
				double cosy = cos(slopy);
				double siny = sin(slopy);   
				double display_length  = sqrt((double)(FromPoint.y - ToPoint.y)*(FromPoint.y - ToPoint.y)+(double)(FromPoint.x - ToPoint.x)*(FromPoint.x - ToPoint.x));
				double arrow_size = min(10,display_length/3.0);

				if(arrow_size>0.2)
				{

					arrow_pts[0] = ToPoint;
					arrow_pts[1].x = ToPoint.x + (int)(arrow_size * cosy - (arrow_size / 2.0 * siny) + 0.5);
					arrow_pts[1].y = ToPoint.y + (int)(arrow_size * siny + (arrow_size / 2.0 * cosy) + 0.5);
					arrow_pts[2].x = ToPoint.x + (int)(arrow_size * cosy + arrow_size / 2.0 * siny + 0.5);
					arrow_pts[2].y = ToPoint.y - (int)(arrow_size / 2.0 * cosy - arrow_size * siny + 0.5);

					pDC->Polygon(arrow_pts, 3);

				}
			}



		}
		//restore pen
		pDC->SelectObject(&DataPen);

	}
}
Esempio n. 7
0
void CPage_Node_LaneTurn::DrawMovements(CPaintDC* pDC,CRect PlotRect)
{

	m_MovementBezierVector.clear();

	CPen NormalPen(PS_SOLID,2,RGB(0,0,0));
	CPen TimePen(PS_DOT,1,RGB(0,0,0));
	CPen DataPen(PS_SOLID,0,RGB(0,0,0));
	CPen SelectedPen(PS_SOLID,4,RGB(255,0,0));
	CPen SelectedPhasePen(PS_SOLID,4,RGB(0,0,255));

	CBrush  WhiteBrush(RGB(255,255,255)); 

	pDC->SetBkMode(TRANSPARENT);
	pDC->SelectObject(&DataPen);
	pDC->SelectObject(&WhiteBrush);

	pDC->Rectangle (PlotRect);

	CBrush  BrushLinkBand(RGB(152,245,255)); 
	pDC->SelectObject(&BrushLinkBand);

		DTANode* pNode  = m_pDoc->m_NodeIDMap [m_CurrentNodeID];

		int node_size = 10;
		int node_set_back = 50;

		int link_length = 150;
		int lane_width = 10;
		int text_length = link_length+ 20;

		CString str;
		str.Format("%d",m_CurrentNodeName);

		pDC->TextOutA( PlotRect.CenterPoint().x-5, PlotRect.CenterPoint().y-5,str);


	for (unsigned int i=0;i< pNode->m_MovementVector .size();i++)
	{
		DTANodeMovement movement = pNode->m_MovementVector[i];
		DTALink* pInLink  = m_pDoc->m_LinkNoMap [movement.IncomingLinkID];
		DTALink* pOutLink  = m_pDoc->m_LinkNoMap [movement.OutgoingLinkID ];

		GDPoint p1, p2, p3;
		// 1: fetch all data
		p1  = m_pDoc->m_NodeIDMap[movement.in_link_from_node_id ]->pt;
		p2  = m_pDoc->m_NodeIDMap[movement.in_link_to_node_id ]->pt;
		p3  = m_pDoc->m_NodeIDMap[movement.out_link_to_node_id]->pt;
		
		double DeltaX = p2.x - p1.x ;
		double DeltaY = p2.y - p1.y ;
		double theta = atan2(DeltaY, DeltaX);

		GDPoint p1_new, p2_new, p3_new;
		GDPoint p1_text, p3_text;
		GDPoint pt_movement[3];


		// 2. set new origin
		p2_new.x = (-1)*node_set_back*cos(theta);  
		p2_new.y = (-1)*node_set_back*sin(theta);


		int link_mid_offset  = (pInLink->m_NumberOfLanes/2 +1)*lane_width;  // mid
		
		pt_movement[0].x = p2_new.x + link_mid_offset* cos(theta-PI/2.0f);
		pt_movement[0].y = p2_new.y + link_mid_offset* sin(theta-PI/2.0f);

		// 3 determine the control point for  PolyBezier
		float control_point_ratio = 0;
		if(movement.movement_turn == DTA_Through ) 
		{
		control_point_ratio = 0;
		}else if(movement.movement_turn == DTA_LeftTurn ) 
		{
			control_point_ratio = 1.2;
		}else
		{
			control_point_ratio = 0.5;
		}
		pt_movement[1].x = pt_movement[0].x + node_set_back*control_point_ratio*cos(theta);
		pt_movement[1].y = pt_movement[0].y + node_set_back*control_point_ratio*sin(theta);
		p1_new.x = (-1)*link_length*cos(theta);
		p1_new.y = (-1)*link_length*sin(theta);


		p1_text.x= (-1)*(text_length)*cos(theta);
		p1_text.y= (-1)*(text_length)*sin(theta);

		// 4: draw from node name
		str.Format("%d",m_pDoc->m_NodeIDtoNameMap [movement.in_link_from_node_id]);
		if(p1_text.y < -50)
			p1_text.y +=10;

		CPoint pt_text = NPtoSP(p1_text);

		pDC->TextOutA(pt_text.x-10,pt_text.y,str);

		DrawLink(pDC,p1_new,p2_new,pInLink->m_NumberOfLanes,theta,lane_width);

////////////////////////////////////////////
		//5: outgoing link
		DeltaX = p3.x - p2.x ;
		DeltaY = p3.y - p2.y ;
		theta = atan2(DeltaY, DeltaX);

		// set new origin
		p2_new.x = node_set_back*cos(theta);  
		p2_new.y = node_set_back*sin(theta);

		link_mid_offset  = (pOutLink->m_NumberOfLanes/2+1)*lane_width;
		pt_movement[2].x = p2_new.x + link_mid_offset* cos(theta-PI/2.0f);
		pt_movement[2].y = p2_new.y + link_mid_offset* sin(theta-PI/2.0f);


		p3_new.x = link_length*cos(theta);
		p3_new.y = link_length*sin(theta);

		p3_text.x= text_length*cos(theta);
		p3_text.y= text_length*sin(theta);


		//draw to node name
		str.Format("%d",m_pDoc->m_NodeIDtoNameMap [movement.out_link_to_node_id]);

		if(p3_text.y < -100)
			p3_text.y +=10;

		pt_text = NPtoSP(p3_text);


		pDC->TextOutA(pt_text.x-10 ,pt_text.y,str);

		DrawLink(pDC,p2_new,p3_new,pOutLink->m_NumberOfLanes,theta,lane_width);


		// draw movement 

		CPoint Point_Movement[4];


		if(i == m_SelectedMovementIndex)
			pDC->SelectObject(&SelectedPen);
		else
			pDC->SelectObject(&NormalPen);



		Point_Movement[0]= NPtoSP(pt_movement[0]);
		Point_Movement[1]= NPtoSP(pt_movement[1]);
		Point_Movement[2]= NPtoSP(pt_movement[1]);
		Point_Movement[3]= NPtoSP(pt_movement[2]);



		Point_Movement[0]= NPtoSP(pt_movement[0]);
		Point_Movement[1]= NPtoSP(pt_movement[1]);
		Point_Movement[2]= NPtoSP(pt_movement[1]);
		Point_Movement[3]= NPtoSP(pt_movement[2]);

		MovementBezier element(Point_Movement[0], Point_Movement[1],Point_Movement[3]);
		
		m_MovementBezierVector.push_back (element);


		pDC->PolyBezier(Point_Movement,4);

		//restore pen
		pDC->SelectObject(&DataPen);

	}
}
void CPage_Node_Lane::DrawOneLane(CPaintDC *pDC, LinkRecord *pRecord, int nLaneNum,int nArrowType,bool bOriginAngle/*=true*/)
{
	GDPoint p1,p2,prl;
	int nR1 = m_Para.nR3;
	int nR2 = m_Para.nR4;
	int nDis= m_Para.nLaneWidth;
	int nRL	= m_Para.nRL;
	double theta = bOriginAngle ? pRecord->dTheta : pRecord->dNormTheta;
	int i = pRecord->nChnlNum + pRecord->nLaneNum + pRecord->nPcktNum +1 - nLaneNum;

	if ( pRecord->nIO == 1)
	{
		nDis = -1 * nDis;
	}
	p1.x	= (nR1+m_Para.nAL4) * cos(theta) + i * nDis * cos(theta-PI/2.0f);
	p1.y	= (nR1+m_Para.nAL4) * sin(theta) + i * nDis * sin(theta-PI/2.0f);
	
	p2.x	= nR2 * cos(theta) + i * nDis * cos(theta-PI/2.0f);
	p2.y	= nR2 * sin(theta) + i * nDis * sin(theta-PI/2.0f);

	prl.x	= nRL * cos(theta) + i * nDis * cos(theta-PI/2.0f);
	prl.y	= nRL * sin(theta) + i * nDis * sin(theta-PI/2.0f);

	pDC->MoveTo(NPtoSP(p2));
	pDC->LineTo(NPtoSP(p1));

	CPoint pLaneNum = NPtoSP(prl);
	
	CString str;
	str.Format("%d",nLaneNum);
	pDC->TextOutA(pLaneNum.x,pLaneNum.y,str);

	// draw arrow
	if (nArrowType >= 4)
	{// thru arrow
		GDPoint pTop,pLeft,pRight;
		CPoint arrow[3];
		int nALength = m_Para.nALength;
		float fAHalf = m_Para.fAWidth;
		pTop.x		= (nR1-nALength) * cos(theta) + i * nDis * cos(theta-PI/2.0f);
		pTop.y		= (nR1-nALength) * sin(theta) + i * nDis * sin(theta-PI/2.0f);
		pLeft.x		= nR1 * cos(theta) + (i-fAHalf) * nDis * cos(theta-PI/2.0f);
		pLeft.y		= nR1 * sin(theta) + (i-fAHalf) * nDis * sin(theta-PI/2.0f);
		pRight.x	= nR1 * cos(theta) + (i+fAHalf) * nDis * cos(theta-PI/2.0f);
		pRight.y	= nR1 * sin(theta) + (i+fAHalf) * nDis * sin(theta-PI/2.0f);

		pDC->MoveTo(NPtoSP(p1));
		pDC->LineTo(NPtoSP(pTop));

		arrow[0]	= NPtoSP(pTop);
		arrow[1]	= NPtoSP(pLeft);
		arrow[2]	= NPtoSP(pRight);
		pDC->Polygon(arrow,3);

		nArrowType -= 4;
	}
	if (nArrowType == 1)
	{// left turn arrow
		GDPoint pTop,pLeft,pRight,pBrunch;
		CPoint arrow[3];
		pTop.x		= (nR1+m_Para.nAL1) * cos(theta) + (i-m_Para.fAL2) * nDis * cos(theta-PI/2.0f);
		pTop.y		= (nR1+m_Para.nAL1) * sin(theta) + (i-m_Para.fAL2) * nDis * sin(theta-PI/2.0f);
		pRight.x	= (nR1+m_Para.nAL2) * cos(theta) + (i-m_Para.fAL1) * nDis * cos(theta-PI/2.0f);
		pRight.y	= (nR1+m_Para.nAL2) * sin(theta) + (i-m_Para.fAL1) * nDis * sin(theta-PI/2.0f);
		pLeft.x		= (nR1+m_Para.nAL3) * cos(theta) + (i-m_Para.fAL3) * nDis * cos(theta-PI/2.0f);
		pLeft.y		= (nR1+m_Para.nAL3) * sin(theta) + (i-m_Para.fAL3) * nDis * sin(theta-PI/2.0f);
		//pBrunch.x	= (nR1+m_Para.nAL4) * cos(theta) + i * nDis * cos(theta-PI/2.0f);
		//pBrunch.y	= (nR1+m_Para.nAL4) * sin(theta) + i * nDis * sin(theta-PI/2.0f);

		pDC->MoveTo(NPtoSP(p1));
		pDC->LineTo(NPtoSP(pTop));

		arrow[0]	= NPtoSP(pTop);
		arrow[1]	= NPtoSP(pLeft);
		arrow[2]	= NPtoSP(pRight);
		pDC->Polygon(arrow,3);
		
	}
	if (nArrowType == 2)
	{// right turn arrow
		GDPoint pTop,pLeft,pRight,pBrunch;
		CPoint arrow[3];
		pTop.x		= (nR1+m_Para.nAL1) * cos(theta) + (i+m_Para.fAL2) * nDis * cos(theta-PI/2.0f);
		pTop.y		= (nR1+m_Para.nAL1) * sin(theta) + (i+m_Para.fAL2) * nDis * sin(theta-PI/2.0f);
		pRight.x	= (nR1+m_Para.nAL2) * cos(theta) + (i+m_Para.fAL1) * nDis * cos(theta-PI/2.0f);
		pRight.y	= (nR1+m_Para.nAL2) * sin(theta) + (i+m_Para.fAL1) * nDis * sin(theta-PI/2.0f);
		pLeft.x		= (nR1+m_Para.nAL3) * cos(theta) + (i+m_Para.fAL3) * nDis * cos(theta-PI/2.0f);
		pLeft.y		= (nR1+m_Para.nAL3) * sin(theta) + (i+m_Para.fAL3) * nDis * sin(theta-PI/2.0f);
		//pBrunch.x	= (nR1+m_Para.nAL4) * cos(theta) + i * nDis * cos(theta-PI/2.0f);
		//pBrunch.y	= (nR1+m_Para.nAL4) * sin(theta) + i * nDis * sin(theta-PI/2.0f);

		pDC->MoveTo(NPtoSP(p1));
		pDC->LineTo(NPtoSP(pTop));

		arrow[0]	= NPtoSP(pTop);
		arrow[1]	= NPtoSP(pLeft);
		arrow[2]	= NPtoSP(pRight);
		pDC->Polygon(arrow,3);
	}
}