LineString类
# 概述
在 Openlayers 中,LineString
类是用于表示几何线段的类。这个类继承自 SimpleGeometry
类,关于SimpleGeometry
类可以参考这篇文章,它代表了一条线段或路径,可以由一系列的坐标点组成。LineString
通常用于地图中的路径、线段等几何形状的表示。
# 源码分析
# LineString
类源码实现
LineString
类的实现如下:
class LineString extends SimpleGeometry {
constructor(coordinates, layout) {
super();
this.flatMidpoint_ = null;
this.flatMidpointRevision_ = -1;
this.maxDelta_ = -1;
this.maxDeltaRevision_ = -1;
if (layout !== undefined && !Array.isArray(coordinates[0])) {
this.setFlatCoordinates(layout, coordinates);
} else {
this.setCoordinates(coordinates, layout);
}
}
appendCoordinate(coordinate) {
extend(this.flatCoordinates, coordinate);
this.changed();
}
clone() {
const lineString = new LineString(
this.flatCoordinates.slice(),
this.layout
);
lineString.applyProperties(this);
return lineString;
}
closestPointXY(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance;
}
if (this.maxDeltaRevision_ != this.getRevision()) {
this.maxDelta_ = Math.sqrt(
maxSquaredDelta(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride,
0
)
);
this.maxDeltaRevision_ = this.getRevision();
}
return assignClosestPoint(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride,
this.maxDelta_,
false,
x,
y,
closestPoint,
minSquaredDistance
);
}
forEachSegment(callback) {
return forEachSegment(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride,
callback
);
}
getCoordinateAtM(m, extrapolate) {
if (this.layout != "XYM" && this.layout != "XYZM") {
return null;
}
extrapolate = extrapolate !== undefined ? extrapolate : false;
return lineStringCoordinateAtM(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride,
m,
extrapolate
);
}
getCoordinates() {
return inflateCoordinates(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride
);
}
getCoordinateAt(fraction, dest) {
return interpolatePoint(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride,
fraction,
dest,
this.stride
);
}
getLength() {
return lineStringLength(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride
);
}
getFlatMidpoint() {
if (this.flatMidpointRevision_ != this.getRevision()) {
this.flatMidpoint_ = this.getCoordinateAt(
0.5,
this.flatMidpoint_ ?? undefined
);
this.flatMidpointRevision_ = this.getRevision();
}
return this.flatMidpoint_;
}
getSimplifiedGeometryInternal(squaredTolerance) {
const simplifiedFlatCoordinates = [];
simplifiedFlatCoordinates.length = douglasPeucker(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride,
squaredTolerance,
simplifiedFlatCoordinates,
0
);
return new LineString(simplifiedFlatCoordinates, "XY");
}
getType() {
return "LineString";
}
intersectsExtent(extent) {
return intersectsLineString(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride,
extent
);
}
setCoordinates(coordinates, layout) {
this.setLayout(layout, coordinates, 1);
if (!this.flatCoordinates) {
this.flatCoordinates = [];
}
this.flatCoordinates.length = deflateCoordinates(
this.flatCoordinates,
0,
coordinates,
this.stride
);
this.changed();
}
}
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# LineString
类的构造函数
LineString
类的构造函数接受两个参数坐标数组coordinates
和坐标布局layout
,构造函数内部定义了几个变量,如下:
this.flatMidpoint_
:几何对象(线)的中点,初始值为null
this.flatMidpointRevision_
:中点的修订版本,初始值为-1
this.maxDelta
和this.maxDeltaRevision_
都是用于缓存计算结果和提高性能,当几何对象坐标发生变化时,这些变量都会重新复制,用于下次几何对象发还是呢个变化时进行对比计算,决定是重新计算还是直接返回上次计算的结果
除此之外,构造函数还会判断,若参数layout
存在且坐标数组coordinates
不是一个嵌套数组,则会调用父类SimpleGeometry
类中的setFlatCoordinates
方法,将扁平化坐标数据应用到对象中,设置this.layout
、this.stride
和this.flatCoordinates
;否则调用setCoordinate
方法设置坐标。
# LineString
类的主要方法
LineString
类的主要方法如下:
appendCoordinate
方法:添加一个坐标到几何对象中,调用extend
方法修改this.flatCoordinates
变量,然后调用this.changed
方法clone
方法:复制当前几何对象,实例化LineString
类,然后调用applyProperties
方法应用属性,最后返回实例对象lineString
closestPointXY
方法:接受四个参数,目标点坐标(x,y)
,最近点closestPoint
和最小距离平方minSquaredDistance
;closestPointXY
方法主要修改最近点坐标,然后返回最小距离平方;方法内部会先计算目标点距离包围盒的最短距离的平方,与minSquaredDistance
比较,若minSquaredDistance
更小,则直接将它返回;判断,若几何对象发生了变化,则调用``maxSquaredDelta计算几何对象相邻点坐标的最大距离的平方,将其返回值赋值给
this.maxDelta_,然后更新记录
this.maxDeltaRevision_版本号,最后调用
assignClosestPoint`方法计算最短距离平方并返回,该方法内部还会更新最近点坐标forEachSegment
方法:该方法是对几何对象中的每一个线段应用参数callback
函数,若回调函数callback
有返回值且为真值,则返回该值,跳出循环,否则最后返回false
;getCoordinateAM
方法:获取几何对象在M
处的坐标;getCoordinateAM
方法内部会先判断坐标布局this.layout
是否含有M
,若不包含这个M
属性,则返回null
;判断extrapolate
是否为undefined
,若该参数传值了则取参数值,否则默认为false
;最后调用lineStringCoordinateAtM
方法并返回结果。lineStringCoordinateAtM
方法会根据参数m
推断出几何对象在M
值为m
时的坐标,若该坐标超出了几何对象的范围,且extrapolate
为true
,则返回该坐标,否则返回null
;若该坐标没有超出范围,则返回该坐标。getCoordinates
方法:获取几何对象的坐标,本质上就是调用inflateCoordinates
方法并返回结果。getCoordinateAt
方法:该方法就是返回LineString
上某个特定位置的坐标,接受两个参数fraction
和dest
;fraction
的取值范围是[0,1]
,0
表示几何对象的起点,1
表示几何对象的终点,介于0
和1
时表示线段相对比例处的坐标;dest
是目标数组,用于存放返回的坐标,当其传值时,则该方法会修改dest
参数并返回,若不传,则返回新的坐标数组。方法内部是调用interpolatePoint
方法并返回结果。getLength
方法:计算几何对象的长度,内部是调用lineStringLength
方法并返回结果,实际上就是计算几何对象(线段)相邻坐标的距离然后累加。getFlatMidpoint
方法:方法内部会先判断几何对象是否发生了改变,若未改变,则返回this.flatMidpoint_
,也就是上一次计算结果的缓存;否则会调用this.getCoordinateAt
方法,第一个参数fraction
传0.5
,表示获取线段的中点坐标,然后将该值赋值给this.flatMidpoint_
,修改几何对象中点记录的版本号,最后返回this.flatMidpoint_
。getSimplifiedGeometryInternal
方法:获取线段的简化版,内部就是调用douglasPeucker
算法,获取简化版的几何对象坐标,然后实例化LineString
类并返回实例对象。getType
方法:返回几何对象的类型LineString
intersectsExtent
方法:判断矩形extent
是否与几何对象相交setCoordinates
方法:设置几何对象的坐标this.flatCoordinates
、this.layout
和this.stride
,最后调用this.changed
方法
# 总结
本文主要介绍了LineString
类的源码实现,LinString
类提供了许多实用的方法,比如获取线段长度,线段上指定位置的坐标。