张世豪
6 天以前 5d6d890cfd10466d5d14ff5177adcc888baaa0e4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package bianjie;
 
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.text.DecimalFormat;
import java.util.List;
 
/**
 * 边界长度绘制器
 * 用于在地图上显示地块边界相邻两点之间的距离
 */
public class BoundaryLengthDrawer {
    
    private static final Color LENGTH_TEXT_COLOR = new Color(80, 80, 80); // 灰色文字,与缩放文字颜色一致
    // 不设置字体,使用Graphics2D的默认字体(与缩放文字一致)
    private static final DecimalFormat DISTANCE_FORMAT = new DecimalFormat("0.00");
    
    /**
     * 计算两点之间的距离(米)
     * 
     * @param p1 第一个点
     * @param p2 第二个点
     * @return 距离(米),保留2位小数
     */
    public static double calculateDistance(Point2D.Double p1, Point2D.Double p2) {
        if (p1 == null || p2 == null) {
            return 0.0;
        }
        double dx = p2.x - p1.x;
        double dy = p2.y - p1.y;
        double distance = Math.sqrt(dx * dx + dy * dy);
        return distance;
    }
    
    /**
     * 在地图上绘制边界长度
     * 在相邻两个边界点的中点位置显示距离
     * 
     * @param g2d Graphics2D对象
     * @param boundary 边界点列表
     * @param scale 当前缩放比例
     * @param panelWidth 面板宽度
     * @param panelHeight 面板高度
     * @param translateX X方向平移量
     * @param translateY Y方向平移量
     */
    public static void drawBoundaryLengths(Graphics2D g2d, List<Point2D.Double> boundary, 
                                          double scale, int panelWidth, int panelHeight, 
                                          double translateX, double translateY) {
        if (boundary == null || boundary.size() < 2) {
            return;
        }
        
        // 保存原始变换
        AffineTransform savedTransform = g2d.getTransform();
        
        // 保存当前字体(使用默认字体,与缩放文字一致)
        Font originalFont = g2d.getFont();
        FontMetrics fontMetrics = g2d.getFontMetrics(originalFont);
        g2d.setColor(LENGTH_TEXT_COLOR);
        
        // 判断边界是否闭合
        int totalPoints = boundary.size();
        boolean closed = totalPoints > 2 && arePointsClose(
            boundary.get(0), 
            boundary.get(totalPoints - 1)
        );
        int effectiveCount = closed ? totalPoints - 1 : totalPoints;
        
        // 绘制每相邻两点之间的距离
        for (int i = 0; i < effectiveCount; i++) {
            int nextIndex = (i + 1) % totalPoints;
            Point2D.Double p1 = boundary.get(i);
            Point2D.Double p2 = boundary.get(nextIndex);
            
            // 计算距离(米)
            double distance = calculateDistance(p1, p2);
            if (distance <= 0) {
                continue; // 跳过距离为0的点
            }
            String distanceText = DISTANCE_FORMAT.format(distance) + "m";
            
            // 计算中点位置(世界坐标)
            double midX = (p1.x + p2.x) / 2.0;
            double midY = (p1.y + p2.y) / 2.0;
            
            // 将世界坐标转换为屏幕坐标(使用与MapRenderer相同的转换公式)
            double screenX = (midX + translateX) * scale + panelWidth / 2.0;
            double screenY = (midY + translateY) * scale + panelHeight / 2.0;
            Point2D.Double screenPoint = new Point2D.Double(screenX, screenY);
            
            // 保存当前变换(此时g2d已经是原始变换,不包含视图变换)
            AffineTransform currentTransform = g2d.getTransform();
            
            // 确保使用屏幕坐标系统(不随缩放变化)
            g2d.setTransform(new AffineTransform());
            
            // 计算文字位置(居中显示)
            int textWidth = fontMetrics.stringWidth(distanceText);
            int textHeight = fontMetrics.getHeight();
            int textX = (int)(screenPoint.x - textWidth / 2.0);
            int textY = (int)(screenPoint.y + textHeight / 4.0);
            
            // 绘制距离文字
            g2d.drawString(distanceText, textX, textY);
            
            // 恢复变换
            g2d.setTransform(currentTransform);
        }
        
        // 恢复原始变换
        g2d.setTransform(savedTransform);
    }
    
    /**
     * 检查两个点是否接近(用于判断边界是否闭合)
     * 
     * @param a 第一个点
     * @param b 第二个点
     * @return 如果两点距离小于阈值则返回true
     */
    private static boolean arePointsClose(Point2D.Double a, Point2D.Double b) {
        if (a == null || b == null) {
            return false;
        }
        double dx = a.x - b.x;
        double dy = a.y - b.y;
        double threshold = 0.05; // 5厘米的阈值
        return Math.hypot(dx, dy) <= threshold;
    }
}