| | |
| | | import java.awt.Font; |
| | | import java.awt.Graphics; |
| | | import java.awt.Graphics2D; |
| | | import java.awt.Image; |
| | | import java.awt.RenderingHints; |
| | | |
| | | import javax.imageio.ImageIO; |
| | | import javax.swing.BorderFactory; |
| | | import javax.swing.JPanel; |
| | | import java.awt.event.MouseWheelEvent; |
| | | import java.awt.event.MouseWheelListener; |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | |
| | | // 可视化面板类 |
| | | class VisualizationPanel extends JPanel { |
| | |
| | | private double scaleFactor = 1.0; // 缩放因子 |
| | | private static final double MIN_SCALE = 0.2; // 最小缩放倍数 |
| | | private static final double MAX_SCALE = 5.0; // 最大缩放倍数 |
| | | private int signalQuality = 0; // 添加信号质量变量 |
| | | |
| | | // 使用支持中文的字体 |
| | | private Font boldFont = new Font("Microsoft YaHei", Font.BOLD, 14); |
| | | private Font normalFont = new Font("Microsoft YaHei", Font.PLAIN, 12); |
| | | private Font titleFont = new Font("Microsoft YaHei", Font.BOLD, 12); |
| | | private Image logoImage; // 添加图片变量 |
| | | |
| | | public VisualizationPanel(AOAFollowSystem parentFrame) { |
| | | this.parentFrame = parentFrame; |
| | | setPreferredSize(new Dimension(400, 400)); |
| | | setBorder(BorderFactory.createTitledBorder(parentFrame.getString("visualization"))); |
| | | |
| | | // 加载图片 |
| | | try { |
| | | logoImage = ImageIO.read(new File("systemfile/1.png")); |
| | | } catch (IOException e) { |
| | | System.err.println("无法加载图片: systemfile/1.png"); |
| | | e.printStackTrace(); |
| | | } |
| | | // 添加鼠标滚轮监听器 |
| | | addMouseWheelListener(new MouseWheelListener() { |
| | | @Override |
| | |
| | | }); |
| | | } |
| | | |
| | | public void updatePosition(int distance, int angle) { |
| | | public void updatePosition(int distance, int angle,int signalQuality) { |
| | | // 优化:只有数据变化时才重绘 |
| | | if (this.distance != distance || this.angle != angle) { |
| | | this.distance = distance; |
| | | // 将角度范围转换为-180到180度,正下方为0度 |
| | | this.angle = normalizeAngle(angle); |
| | | // 直接使用原始角度值,不进行归一化处理 |
| | | this.angle = angle; |
| | | this.signalQuality=signalQuality; |
| | | repaint(); |
| | | } |
| | | } |
| | | |
| | | // 角度归一化方法,将角度转换为-180到180度范围,正下方为0度 |
| | | private int normalizeAngle(int angle) { |
| | | // 首先将角度转换为0-360度范围 |
| | | angle = angle % 360; |
| | | if (angle < 0) { |
| | | angle += 360; |
| | | } |
| | | |
| | | // 将0-360度转换为-180到180度,正下方为0度 |
| | | // 0度对应正下方,90度对应正左方,180/-180度对应正上方,-90度对应正右方 |
| | | int normalizedAngle = angle - 180; |
| | | if (normalizedAngle > 180) { |
| | | normalizedAngle -= 360; |
| | | } else if (normalizedAngle <= -180) { |
| | | normalizedAngle += 360; |
| | | } |
| | | |
| | | return normalizedAngle; |
| | | } |
| | | |
| | | public void setAnchorId(String anchorid) { |
| | |
| | | |
| | | int centerX = getWidth() / 2; |
| | | int centerY = getHeight()/ 2 - 30; |
| | | int maxRadius = (int) (Math.min(centerX, centerY) * scaleFactor - 20); |
| | | int baseRadius = Math.min(centerX, centerY) - 20; // 基础半径(不缩放) |
| | | int maxRadius = (int) (baseRadius * scaleFactor); // 缩放后的半径 |
| | | |
| | | // 设置背景颜色 |
| | | g2d.setColor(new Color(240, 240, 240)); |
| | | g2d.fillRect(0, 0, getWidth(), getHeight()); |
| | | |
| | | // 在左下角绘制图片 |
| | | if (logoImage != null) { |
| | | int imgWidth = logoImage.getWidth(this); |
| | | int imgHeight = logoImage.getHeight(this); |
| | | // 调整图片大小,使其适合面板 |
| | | int scaledWidth =150; // 设置图片宽度 |
| | | int scaledHeight = (int) (imgHeight * (scaledWidth * 1.0 / imgWidth)); // 按比例计算高度 |
| | | g2d.drawImage(logoImage, 5, getHeight() - scaledHeight - 5, scaledWidth, scaledHeight, this); |
| | | } |
| | | |
| | | // 绘制坐标轴 |
| | | g2d.setColor(Color.LIGHT_GRAY); |
| | |
| | | // 绘制角度刻度线 (-180° 到 180°) |
| | | g2d.setColor(new Color(150, 150, 150)); |
| | | for (int i = -180; i <= 180; i += 30) { |
| | | // 转换为弧度,正下方为0度 |
| | | double rad = Math.toRadians(i); |
| | | int x1 = centerX + (int) (maxRadius * Math.sin(rad)); |
| | | int y1 = centerY - (int) (maxRadius * Math.cos(rad)); |
| | | // 转换为数学坐标系的角度(从正东方向开始,逆时针为正) |
| | | double mathAngle = 90 - i; // 导航角度转换为数学角度 |
| | | if (mathAngle < 0) mathAngle += 360; |
| | | |
| | | double rad = Math.toRadians(mathAngle); |
| | | int x1 = centerX + (int) (maxRadius * Math.cos(rad)); |
| | | int y1 = centerY - (int) (maxRadius * Math.sin(rad)); |
| | | g2d.setColor(new Color(100, 100, 100)); |
| | | g2d.drawLine(centerX, centerY, x1, y1); |
| | | |
| | | // 绘制角度标签 |
| | | int labelX = centerX + (int) ((maxRadius + 15) * Math.sin(rad)); |
| | | int labelY = centerY - (int) ((maxRadius + 15) * Math.cos(rad)); |
| | | if (i == -180) { |
| | | continue; |
| | | } |
| | | int labelX = centerX + (int) ((maxRadius + 15) * Math.cos(rad)); |
| | | int labelY = centerY - (int) ((maxRadius + 15) * Math.sin(rad)); |
| | | g2d.setColor(Color.blue); |
| | | g2d.drawString(i + "°", labelX - 10, labelY + 5); |
| | | } |
| | |
| | | for (int i = 1; i <= 5; i++) { |
| | | int radius = maxRadius * i / 5; |
| | | g2d.drawOval(centerX - radius, centerY - radius, radius * 2, radius * 2); |
| | | // 修改:将距离标签显示在圆圈正南方中间 |
| | | String distanceLabel = (int)(i * 200 / scaleFactor) + "cm"; |
| | | // 修改:距离标签不随缩放变化,保持实际距离 |
| | | String distanceLabel = i * 200 + "cm"; |
| | | int labelWidth = g2d.getFontMetrics().stringWidth(distanceLabel); |
| | | g2d.drawString(distanceLabel, centerX - labelWidth / 2, centerY + radius + 15); |
| | | } |
| | |
| | | if (distance > 0) { |
| | | // 根据距离计算缩放比例(最大1000厘米) |
| | | double scaledDistance = Math.min(distance, 1000) * maxRadius / 1000.0; |
| | | double rad = Math.toRadians(angle); |
| | | |
| | | int bX = centerX + (int) (scaledDistance * Math.sin(rad)); |
| | | int bY = centerY - (int) (scaledDistance * Math.cos(rad)); |
| | | |
| | | // 将导航角度转换为数学角度(从正东方向开始,逆时针为正) |
| | | double mathAngle = 90 - angle; // 导航角度转换为数学角度 |
| | | if (mathAngle < 0) mathAngle += 360; |
| | | |
| | | double rad = Math.toRadians(mathAngle); |
| | | int bX = centerX + (int) (scaledDistance * Math.cos(rad)); |
| | | int bY = centerY - (int) (scaledDistance * Math.sin(rad)); |
| | | |
| | | // 绘制连接线 |
| | | g2d.setColor(new Color(0, 100, 200, 150)); |
| | | g2d.drawLine(centerX, centerY, bX, bY); |
| | |
| | | g2d.setFont(boldFont); |
| | | g2d.setColor(Color.RED); |
| | | |
| | | // 计算文本位置(B点正下方) |
| | | int textY = bY + 25; |
| | | g2d.drawString(distanceText, bX - g2d.getFontMetrics().stringWidth(distanceText)/2, textY); |
| | | g2d.drawString(angleText, bX - g2d.getFontMetrics().stringWidth(angleText)/2, textY + 20); |
| | | |
| | | // 恢复原始字体 |
| | | g2d.setFont(normalFont); |
| | | |
| | | // 在面板底部显示距离和角度信息 - 实时获取字符串,不使用缓存 |
| | | g2d.setFont(boldFont); |
| | | // 直接从父框架获取当前语言的字符串 |
| | | g2d.drawString(parentFrame.getString("distance") + distance + "cm", 10, 40); |
| | | g2d.drawString(parentFrame.getString("angle") + angle + "°", 10, 70); |
| | | // 新增:显示信号质量 |
| | | g2d.drawString(parentFrame.getString("signal") + signalQuality, 10, 100); |
| | | g2d.setFont(normalFont); |
| | | g2d.setColor(Color.BLUE); |
| | | g2d.fillOval(bX - 5, bY - 5, 10, 10); |
| | | g2d.fillOval(bX -10, bY -10, 20, 20); |
| | | |
| | | // B点正上方显示设备编号 |
| | | g2d.setFont(titleFont); |
| | | g2d.drawString(tagid, bX - g2d.getFontMetrics().stringWidth(tagid)/2, bY - 15); |
| | | g2d.setColor(Color.BLUE); |
| | | g2d.drawString(tagid, bX - g2d.getFontMetrics().stringWidth(tagid)/2, bY - 25); |
| | | g2d.setFont(normalFont); |
| | | |
| | | // 计算文本位置(B点正下方) |
| | | int textY = bY + 25; |
| | | g2d.setColor(Color.BLUE); |
| | | g2d.drawString(distanceText, bX - g2d.getFontMetrics().stringWidth(distanceText)/2, textY); |
| | | g2d.drawString(angleText, bX - g2d.getFontMetrics().stringWidth(angleText)/2, textY + 20); |
| | | g2d.setFont(normalFont); |
| | | |
| | | |
| | | |
| | | } |
| | | |
| | | // 显示当前缩放比例 |
| | | g2d.setColor(Color.DARK_GRAY); |
| | | g2d.drawString(String.format("缩放: %.1fx", scaleFactor), getWidth() - 80, 20); |
| | | g2d.drawString(String.format("%s: %.1fx", parentFrame.getString("scale"), scaleFactor), getWidth() - 80, 20); |
| | | |
| | | |
| | | } |
| | | |
| | | public void updateLanguage() { |