📄 canvaspanel.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 + -