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

📄 canvaspanel.java

📁 赛车程序:先对赛道和赛车建立模型
💻 JAVA
字号:
/**
 * 
 */
package cn.tsinghua.ag5.CarModel;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.geom.Line2D.Double;
import java.awt.image.*;

import javax.swing.*;

import cn.tsinghua.ag5.CarModel.*;
/**
 * @author wfq
 *
 */
public class CanvasPanel extends JPanel implements ActionListener
{
	public static DynModel s_cars[];
	public static CtrlStrategy s_ctrl[];
	
	public static boolean s_isGlobal = false;
	public static int s_width = 800;
	public static int s_height = 768;
	//缩放比例
	private static double s_zoom = 15;	//估计值
	private static double s_sZoom;
	
	//重要部件
	private static Timer s_Timer;
	private static GeneralPath s_relRoad;
//	private double tmp;
	
	//绘图常数
	private static final int s_sLW = 6;	//Line width in global map
	private static final int s_sDotRadius = 5;
	private static final float s_mLW = 10;
	private static final float s_dash[] = {100, 180}; 
	private static final float s_sideLW = 14;
	private static final float s_roadWidth = 5;	//米, 半边的路宽
	
	private static int s_leaderPosX;
	private static int s_leaderPosY;

	double m_yExcur;	//不可随便用
	double m_xExcur;	//不可随便用

	/**
	 * 
	 */
	public CanvasPanel() {
		super();
		// TODO Auto-generated constructor stub
		
		this.setBackground(Color.white);
		this.setSize(s_width, s_height);
	}

	public void paintComponent( Graphics p_g)
	{
		super.paintComponent(p_g);
		
		Graphics2D g2d = (Graphics2D) p_g;
		
		if(!MyGUI.s_isRoadCreated)
			throw new Error("The road hasn't been generated!");
		s_leaderPosX = s_width / 2;
		s_leaderPosY = 2* s_height / 3;
		
		double t_width;
		double t_height;
		double t_x = 0;
		double t_y = 0;
		
		if(s_isGlobal)
		{
			t_height = s_height / (GeogInfo.getMaxTop() - GeogInfo.getMaxBottom());
			t_width = s_width / (GeogInfo.getMaxRight() - GeogInfo.getMaxLeft());
			
			//乘以s_sZoom即可
			s_sZoom = t_height < t_width ? t_height : t_width;
			
			//以左上为基准点,平移整个路段,计算由绝对坐标到屏幕坐标的偏移量
			m_yExcur = GeogInfo.getMaxTop() * s_sZoom;	//- GeogInfo.getMaxTop() * s_sZoom;
			m_xExcur = - GeogInfo.getMaxLeft() * s_sZoom;
			//X在乘以zoom后,再加上该偏移就是屏幕坐标, Y要乘以负zoom,再加上偏移。
			
			for(RoadParts i : GeogInfo.s_road)
			{
				if(i.strCur)
				{
					g2d.setPaint(Color.darkGray);
					g2d.setStroke(new BasicStroke(s_sLW));
					g2d.draw(new Line2D.Double(i.startX * s_sZoom + m_xExcur, - i.startY * 
							s_sZoom + m_yExcur, i.endX * s_sZoom + m_xExcur, - i.endY * s_sZoom + m_yExcur));
					
				}else
				{
					g2d.setColor(Color.darkGray);
					t_x = (i.centerX - i.curRadius) * s_sZoom + m_xExcur;
					t_y = -(i.centerY + i.curRadius) * s_sZoom + m_yExcur;
					t_width = 2 * i.curRadius * s_sZoom;
					t_height = 2 * i.curRadius * s_sZoom;
					double t_start = toDegree(i.centerX, i.centerY, i.startX, i.startY);
					double t_extent = i.turn ? i.angle : - i.angle;
					
					g2d.setStroke(new BasicStroke(s_sLW));
					g2d.draw(new Arc2D.Double(t_x, t_y, t_width, t_height, t_start, t_extent, Arc2D.OPEN));
				}
			}
			
			g2d.setColor(Color.red);
			for(DynModel i : s_cars)
			{
				t_x = i.getLocationX() * s_sZoom + m_xExcur - s_sDotRadius;
				t_y = - i.getLocationY() * s_sZoom + m_yExcur - s_sDotRadius;
				g2d.fill(new Ellipse2D.Double(t_x, t_y, 2 * s_sDotRadius, 2 * s_sDotRadius));
			}
//			System.out.println(t_x);
//			System.out.println(t_y);
//			System.out.println(s_sZoom);
			
		}else
		{
//			MyGUI.s_carImage.paintIcon(this, g, s_leaderPosX - MyGUI.s_carImage.getIconWidth() / 2, 
//					s_leaderPosY - MyGUI.s_carImage.getIconHeight() / 2);
			
			BufferedImage t_image[] = new BufferedImage[DynModel.s_carNum - 1];
			
			AffineTransformOp t_tOP;
			
			m_xExcur = s_leaderPosX - s_cars[0].getLocationX() * s_zoom;
			m_yExcur = s_leaderPosY + s_cars[0].getLocationY() * s_zoom;
			//x乘以zoom 加偏移,y乘以负zoom,加偏移
			
/*			for(int i = 1; i < DynModel.s_carNum ; i++)
			{
				BufferedImage t_ti;
				
				AffineTransform t_transf = AffineTransform.getRotateInstance(s_cars[0].getTheta() 
						- s_cars[i].getTheta(), MyGUI.s_carImage.getWidth(null) / 2, 
						MyGUI.s_carImage.getHeight(null) / 2);
				t_tOP = new AffineTransformOp(t_transf, AffineTransformOp.TYPE_BILINEAR);
				
				t_image[i] = new BufferedImage(MyGUI.s_carImage.getWidth(null), 
						MyGUI.s_carImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
				t_ti = new BufferedImage(MyGUI.s_carImage.getWidth(null), 
						MyGUI.s_carImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
				Graphics2D t_g2 = t_ti.createGraphics();
				
				t_g2.drawImage(MyGUI.s_carImage, 0, 0, null);
				t_tOP.filter(t_ti, t_image[i]);
			}*/
			
//			if(s_relRoad == null)
//			{
//				s_relRoad = new GeneralPath();
//				
//				
//				
//			}
			//更改地图的偏移量,跟更改屏幕的基准点是一样的
//			g2d.translate(s_leaderPosX, s_leaderPosY);
			//相当在每个点上又加了s_leaderPosX, s_leaderPosY, 所以要减去
//			t_xExcur = - s_cars[0].getLocationX() * s_zoom;
//			t_yExcur = s_cars[0].getLocationY() * s_zoom;
			//这又相当于计算相对于首车中心的坐标了
			
			//小车拐的方向为多少度,g2d就拐多少,然后再重绘地图
			g2d.rotate(s_cars[0].getTheta() - Math.PI / 2, s_leaderPosX, s_leaderPosY);
			//仍然按照原偏移进行地图重绘
			
			//画地图
			for(RoadParts i : GeogInfo.s_road)
			{
				if(i.strCur)
				{
					//画中线
					g2d.setColor(Color.darkGray);
					g2d.setStroke(new BasicStroke(s_mLW, BasicStroke.CAP_BUTT, 
							BasicStroke.JOIN_ROUND, 10, s_dash, 0));
					g2d.draw(new Line2D.Double(i.startX * s_zoom + m_xExcur, 
							- i.startY * s_zoom + m_yExcur, i.endX * s_zoom + m_xExcur, - 
							i.endY * s_zoom + m_yExcur));
					
					//画路边
					double t_strAng, t_x1, t_x2, t_y1, t_y2;
					
					g2d.setColor(Color.lightGray);
					g2d.setStroke(new BasicStroke(s_sideLW));
					t_strAng = Math.atan2(i.endY - i.startY, i.endX - i.startX);
						
					t_x1 = (i.startX + s_roadWidth * Math.cos(t_strAng + Math.PI / 2)) * s_zoom + m_xExcur;
					t_y1 = (i.startY + s_roadWidth * Math.sin(t_strAng + Math.PI / 2)) * - s_zoom + m_yExcur;
					t_x2 = (i.endX + s_roadWidth * Math.cos(t_strAng + Math.PI / 2)) * s_zoom + m_xExcur;
					t_y2 = (i.endY + s_roadWidth * Math.sin(t_strAng + Math.PI / 2)) * - s_zoom + m_yExcur;
					
					g2d.draw(new Line2D.Double(t_x1, t_y1, t_x2, t_y2));
					
					t_x1 = (i.startX + s_roadWidth * Math.cos(t_strAng - Math.PI / 2)) * s_zoom + m_xExcur;
					t_y1 = (i.startY + s_roadWidth * Math.sin(t_strAng - Math.PI / 2)) * - s_zoom + m_yExcur;
					t_x2 = (i.endX + s_roadWidth * Math.cos(t_strAng - Math.PI / 2)) * s_zoom + m_xExcur;
					t_y2 = (i.endY + s_roadWidth * Math.sin(t_strAng - Math.PI / 2)) * - s_zoom + m_yExcur;
					
					g2d.draw(new Line2D.Double(t_x1, t_y1, t_x2, t_y2));
					
				}else
				{
					//画中线
					g2d.setColor(Color.darkGray);
					g2d.setStroke(new BasicStroke(s_mLW, BasicStroke.CAP_BUTT, 
							BasicStroke.JOIN_ROUND, 10, s_dash, 0));
					t_x = (i.centerX - i.curRadius) * s_zoom + m_xExcur;
					t_y = (i.centerY + i.curRadius) * - s_zoom + m_yExcur;
					t_width = i.curRadius * 2 * s_zoom;
					t_height = i.curRadius * 2 * s_zoom;
					double t_start = toDegree(i.centerX, i.centerY, i.startX, i.startY);
					double t_extent = i.turn ? i.angle : - i.angle;
					
					g2d.draw(new Arc2D.Double(t_x, t_y, t_width, t_height, t_start, t_extent, Arc2D.OPEN));
					
					//画路边
					g2d.setColor(Color.lightGray);
					g2d.setStroke(new BasicStroke(s_sideLW));
//					if(i.turn)
//					{
					//左转左边或右转右边
					t_x = (i.centerX - i.curRadius + s_roadWidth) * s_zoom + m_xExcur;
					t_y = (i.centerY + i.curRadius - s_roadWidth) * - s_zoom + m_yExcur;
					t_width = (i.curRadius - s_roadWidth) * 2 * s_zoom;
					t_height = t_width;

					g2d.draw(new Arc2D.Double(t_x, t_y, t_width, t_height, t_start, t_extent, Arc2D.OPEN));

					//左转右边或右转左边
					t_x = (i.centerX - i.curRadius - s_roadWidth) * s_zoom + m_xExcur;
					t_y = (i.centerY + i.curRadius + s_roadWidth) * - s_zoom + m_yExcur;
					t_width = (i.curRadius + s_roadWidth) * 2 * s_zoom;
					t_height = t_width;

					g2d.draw(new Arc2D.Double(t_x, t_y, t_width, t_height, t_start, t_extent, Arc2D.OPEN));
					
				}
			}
			
			//画小车,按照其位置贴图
/*			for(int i = 1; i < DynModel.s_carNum; i++)
			{
				t_x = s_cars[i].getLocationX() * s_zoom + m_xExcur;
				t_y = s_cars[i].getLocationY() * - s_zoom + m_yExcur;
				
				g2d.drawImage(t_image[i], (int)Math.round(t_x - t_image[i].getHeight(this) / 2), 
						(int)Math.round(t_y - t_image[i].getWidth(this) / 2), this);
			}*/
			
			//画完了再转回来
			g2d.rotate( Math.PI / 2 - s_cars[0].getTheta(), s_leaderPosX, s_leaderPosY);
			//此处画图有问题
			g2d.drawImage(MyGUI.s_carImage, s_leaderPosX - MyGUI.s_carImage.getHeight(this) / 4, 
					s_leaderPosY - MyGUI.s_carImage.getWidth(this) / 2, this);
		}
	}
	
	public void actionPerformed( ActionEvent actionEvent)
	{
		//先更新各个模块
		if(s_cars == null || s_cars[0] == null)	
			throw new Error("Initialize Dynamic Models first!\n"); 
		
		//先车再控制量
//		s_cars[0].update();
//		s_ctrl[0].update();
		for(int i = 0; i < DynModel.s_carNum; i++)
		{
			s_cars[i].update();
			s_ctrl[i].update();
		}
		
		repaint();

		//为了好看
		MyGUI.s_steer.setSteer(- 2 * s_cars[0].getDelta());
		MyGUI.s_steer.repaint();
		
		MyGUI.s_toUpdate[0].setLength(Math.hypot(s_cars[0].getVX(),s_cars[0].getVY()));
		MyGUI.s_toUpdate[1].setLength(s_cars[0].getFaif() > 0 ? s_cars[0].getFaif() : 0);
		MyGUI.s_toUpdate[2].setLength(s_cars[0].getFaif() < 0 ? - s_cars[0].getFaif() : 0);
		for(JPanel i : MyGUI.s_toUpdate)
		{
			i.repaint();
		}
//		MyGUI.s_panel.repaint();
		
	}

	public void startCanvas()
	{
		if(s_Timer == null)	//throw new Error("Panel: Unexpected Timer error!\n");
		{
			s_Timer = new Timer((int)MyGUI.s_emStep * 1000, this);
			s_Timer.start();
		}
	}
	
	public void pauseCanvas()
	{
		s_Timer.stop();
	}
	
	public void resumeCanvas()
	{
		s_Timer.start();
	}
//	
//	private double cvtX(double p_rawCoordinate)
//	{
//		return p_rawCoordinate * 
//	}
	
	/**
	 * 返回当前角度的度数	0 -> 360
	 * @param p_x0
	 * @param p_y0
	 * @param p_x
	 * @param p_y
	 * @return
	 */
	public double toDegree(double p_x0, double p_y0, double p_x, double p_y)
	{
		double t_radian  = Math.atan2(p_y - p_y0, p_x - p_x0);
		return t_radian < 0 ? (t_radian / Math.PI) * 180 + 360 : (t_radian / Math.PI) * 180;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -