PolyUtil
# 概述
PolyUtil
是一个用于处理多边形的工具类,它提供了一些常用的方法,用于多边形裁剪与中心点计算等。
# 源码分析
# 源码实现
PolyUtil
的源码实现如下:
export function clipPolygon(points, bounds, round) {
var clippedPoints,
edges = [1, 4, 2, 8],
i,
j,
k,
a,
b,
len,
edge,
p;
for (i = 0, len = points.length; i < len; i++) {
points[i]._code = LineUtil._getBitCode(points[i], bounds);
}
// for each edge (left, bottom, right, top)
for (k = 0; k < 4; k++) {
edge = edges[k];
clippedPoints = [];
for (i = 0, len = points.length, j = len - 1; i < len; j = i++) {
a = points[i];
b = points[j];
// if a is inside the clip window
if (!(a._code & edge)) {
// if b is outside the clip window (a->b goes out of screen)
if (b._code & edge) {
p = LineUtil._getEdgeIntersection(b, a, edge, bounds, round);
p._code = LineUtil._getBitCode(p, bounds);
clippedPoints.push(p);
}
clippedPoints.push(a);
// else if b is inside the clip window (a->b enters the screen)
} else if (!(b._code & edge)) {
p = LineUtil._getEdgeIntersection(b, a, edge, bounds, round);
p._code = LineUtil._getBitCode(p, bounds);
clippedPoints.push(p);
}
}
points = clippedPoints;
}
return points;
}
export function polygonCenter(latlngs, crs) {
var i, j, p1, p2, f, area, x, y, center;
if (!latlngs || latlngs.length === 0) {
throw new Error("latlngs not passed");
}
if (!LineUtil.isFlat(latlngs)) {
console.warn("latlngs are not flat! Only the first ring will be used");
latlngs = latlngs[0];
}
var centroidLatLng = toLatLng([0, 0]);
var bounds = toLatLngBounds(latlngs);
var areaBounds =
bounds.getNorthWest().distanceTo(bounds.getSouthWest()) *
bounds.getNorthEast().distanceTo(bounds.getNorthWest());
// tests showed that below 1700 rounding errors are happening
if (areaBounds < 1700) {
// getting a inexact center, to move the latlngs near to [0, 0] to prevent rounding errors
centroidLatLng = centroid(latlngs);
}
var len = latlngs.length;
var points = [];
for (i = 0; i < len; i++) {
var latlng = toLatLng(latlngs[i]);
points.push(
crs.project(
toLatLng([
latlng.lat - centroidLatLng.lat,
latlng.lng - centroidLatLng.lng,
])
)
);
}
area = x = y = 0;
// polygon centroid algorithm;
for (i = 0, j = len - 1; i < len; j = i++) {
p1 = points[i];
p2 = points[j];
f = p1.y * p2.x - p2.y * p1.x;
x += (p1.x + p2.x) * f;
y += (p1.y + p2.y) * f;
area += f * 3;
}
if (area === 0) {
// Polygon is so small that all points are on same pixel.
center = points[0];
} else {
center = [x / area, y / area];
}
var latlngCenter = crs.unproject(toPoint(center));
return toLatLng([
latlngCenter.lat + centroidLatLng.lat,
latlngCenter.lng + centroidLatLng.lng,
]);
}
export function centroid(coords) {
var latSum = 0;
var lngSum = 0;
var len = 0;
for (var i = 0; i < coords.length; i++) {
var latlng = toLatLng(coords[i]);
latSum += latlng.lat;
lngSum += latlng.lng;
len++;
}
return toLatLng([latSum / len, lngSum / len]);
}
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
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
# 源码详解
# 多边形形裁剪函数clipPolygon(points,bounds,round)
作用:用矩形边界裁剪多边形,返回裁剪后的顶点数组(基于Sutherland-Hodgman
算法)
关键步骤
预计算点的位编码 为每个顶点标记其相对于边界的方位(左/右/上/下),使用 4 位二进制编码
按顺序处理四条边 依次处理左(
1
)、下(4
)、右(2
)、上(8
)四条边界,逐步裁剪多边形逐边裁剪逻辑 对每条边,遍历多边形的每条边
a-b
,根据顶点位置关系添加交点或保留点:
- Case 1:
a
在内侧,b
在外侧 → 添加交点。 - Case 2:
a
在外侧,b
在内侧 → 添加交点。 - Case 3: 两点均在内侧 → 保留
a
。
# 多边形中心计算polygonCenter(latlngs,crs)
作用:计算多边形的几何中心质心,基于多边形面积加权法
算法原理:
- 坐标平移:将多边形平移到原点附近,减少浮点误差。
- 质心公式: 通过遍历多边形的所有边,累加面积和加权坐标
# 辅助函数centroid(coords)
作用:计算多边形顶点的算术平均中心(非面积加权,仅坐标平均)
对比:
- 算术平均中心:简单平均,不考虑顶点分布密度。
- 面积加权中心:更精确的几何中心,适用于不规则多边形。
# 使用场景
- 地图渲染优化:裁剪不可见部分的多边形,提升性能。
- 信息标注:在多边形中心显示标签或图标。
- 交互计算:判断多边形是否在视野内,或计算聚焦位置。
# 总结
PolyUtil
提供了高效的多边形裁剪与中心点计算方法,在 Leaflet 中广泛应用于地图渲染与交互,实现了高效的多边形几何操作,支撑了复杂地理数据的可视化与交互。
编辑 (opens new window)
上次更新: 2025/04/18, 07:17:03