概述
在 OpenLayers 中,LinearRing
类用于表示封闭的线段集合(即多段线)形成的环状路径。LinearRing
是 SimpleGeometry
的子类,继承自几何图形类。它通常用于描述多边形的外边界或孔洞边界,本质上它就是一个封闭的线段路径,首尾点必须是重合的,形成一个封闭环。
本文主要介绍LinearRing
类的源码实现和原理。
源码分析
LinearRing
类源码实现
class LinearRing extends SimpleGeometry {
constructor(coordinates, layout) {
super();
this.maxDelta_ = -1;
this.maxDeltaRevision_ = -1;
if (layout !== undefined && !Array.isArray(coordinates[0])) {
this.setFlatCoordinates(layout, coordinates);
} else {
this.setCoordinates(coordinates, layout);
}
}
clone() {
return new LinearRing(this.flatCoordinates.slice(), this.layout);
}
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_,
true,
x,
y,
closestPoint,
minSquaredDistance
);
}
getArea() {
return linearRingArea(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride
);
}
getCoordinates() {
return inflateCoordinates(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride
);
}
getSimplifiedGeometryInternal(squaredTolerance) {
const simplifiedFlatCoordinates = [];
simplifiedFlatCoordinates.length = douglasPeucker(
this.flatCoordinates,
0,
this.flatCoordinates.length,
this.stride,
squaredTolerance,
simplifiedFlatCoordinates,
0
);
return new LinearRing(simplifiedFlatCoordinates, "XY");
}
getType() {
return "LinearRing";
}
intersectsExtent(extent) {
return false;
}
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();
}
}
LinearRing
类的构造函数
LinearRing
类的构造函数中定义了两个变量this.maxDelta_
和this.maxDeltaRevision_
,这两个变量都与优化和性能相关,在LinearRing
类的管理和更新时,可以避免不必要的计算,具体如下
this.maxDelta_
:该变量通常用于控制几何形状的精度或处理几何更新时的变化阈值。初始值为-1
,表示初始、未定义的状态,还没有设置具体的最大变化量;实际的值通常是在更新几何图形时进行设定;当几何图形的顶点发生变化时,this.maxDelta_
会用来判断这些变化是否超出阈值,若没有,这不会触发重新渲染或计算的操作;this.maxDeltaRevision_
:初始值也是-1
,该变量是用于跟踪几何图形修订版本的变量。它存储了上次更新时的修订版本号,用于判断当前几何形状是否发生了变化。每当几何形状的顶点或属性更新时,this.maxDeltaRevision_
会被更新。如果当前版本与上次的版本不一致,可能会触发一些操作,比如重新计算、重新渲染或者优化缓存等。该变量有助于优化性能,因为在很多情况下,OpenLayers 需要检查对象是否发生了变化。如果当前修订版本与上次的修订版本一致,那么可以跳过一些不必要的操作。
除了定义上述两个变量外,LinearRing
类还会判断构造函数的第二个参数layout
是否存在,若不存在,且参数coordinates
的第一个值不是数组,则调用父类SimpleGeometry
类中的this.setFlatCoordinates
方法;否则调用this.setCoordinates
方法,二者都是会设置this.layout
、this.stride
和this.flatCoordinates
的值。
LinearRing
类的主要方法
LinearRing
类的主要方法如下:
-
clone
方法:用于克隆一个LinearRing
几何对象,内部就是实例化LinearRing
类并返回实例。 -
closestPointXY
方法:接受四个参数,目标点坐标x
、y
、最近点坐标closestPoint
和最短距离平方minSquaredDistance
;首先会判断,若minSquaredDistance
小于目标点离包围盒的距离(该距离是调用closetSquaredDistanceXY
方法计算),则返回minSquaredDistance
;然后调用this.getRevision()
方法获取几何对象的修改次数,若该次数不等于this.maxDeltaRevision_
,则调用maxSquaredDelta
方法计算几何对象相邻点之间的最大平方距离并将其平方根赋值给this.maxDelta_
,并调用this.getRevision()
将返回值赋值给this.maxDeltaRevision_
;最后调用assignClosePoint
方法并返回,assignClosePoint
方法就是寻找一组坐标点中离给定点(x, y)
最近的点,并返回该点的平方距离。该方法是计算几何中点之间最近距离的一种实现,特别适用于路径、线段、或者多边形边界等几何结构,常用于计算点到线的最近距离,或者优化几何数据结构。所以closestPointXY
同Point
类的同名方法作用一样,修改最近点坐标并返回最短距离 -
getArea
方法:获取几何对象的面积,内部是调用linearRingArea
方法,该方法的原理是使用**Shoelace
定理**(或高斯面积公式)计算多边形的面积。 -
getCoordinates
方法:获取几何对象的坐标,内部是调用inflateCoordinates
方法 -
getSimplifiedGeometryInternal
方法:内部方法,获取简化的几何对象,接受一个参数squaredTolerance
,该参数表示一个距离阈值的平方,用于控制在多大程度上可以去除多余的点,即控制简化的精度,值越大,去除的点更多;内部利用了Douglas-Peucker
算法来对多边形进行简化。 -
getType
方法:获取几何对象的类型,返回LinearRing
类 -
intersectsExtent
方法:返回false
-
setCoordinates
方法:设置坐标,主要还是赋值,内部会调用deflateCoordinates
方法修改三个变量this.stride
、this.layout
和this.flatCoordinates
,最后会调用this.changed
方法
总结
本文介绍了LinearRing
类的源码实现,LinearRing
类通常情况下实例化后不会直接被渲染,而是在Polygon
类中用于构建多边形。