Geometry基类
# 概述
在上一篇文章中提到Geometry
类是继承于 Openlayers 中的BaseObject
类(参考).而Geometry
类通常情况下也是作为一个抽象基类,作为Geom
几何图形的基类或父类,不会在应用中去实例化它.Geometry
类回去注册几何对象实例的监听.当几何对象发生改变时,会收到通知,进而进行其它处理.
# 源码分析
# Geometry
类的源码实现
Geometry
类的源码实现如下:
class Geometry extends BaseObject {
constructor() {
super()
this.extent_=createEmpty()
this.extentRevision_=-1;
this.simplifiedGeometryMaxMinSquaredTolerance = 0;
this.simplifiedGeometryRevision = 0;
this.simplifyTransformedInternal = memoizeOne(
(revision, squaredTolerance, transform) => {
if (!transform) {
return this.getSimplifiedGeometry(squaredTolerance);
}
const clone = this.clone();
clone.applyTransform(transform);
return clone.getSimplifiedGeometry(squaredTolerance);
},
);
}
simplifyTransformed(squaredTolerance, trnasform) {}
clone() {
return abstract();
}
closestPointXY(x, y, closestPoint, minSquaredDistance) {
return abstract()
}
containXY(x,y){
const corrd=this.getClosetPoint([x,y]);
return coord[0] ===x && coord[1] ===y
}
getClosestPoint(point,closestPoint){
closestPoint= closestPoint ? closestPoint:[NaN,NaN];
this.closestPointXY(point[0],point[1],closestPoint,Infinity)
return closestPoint;
}
intersectsCoordinate(coordinate){
return this.containsXY(coordinate[0],coordinate[1])
}
computeExtent(extent){
return abstract()
}
getExtent(extent){
if(this.extentRevision_!this.getRevision()){
const extent=this.computeExtent(this.extent_);
if(isNaN(extent[0])||isNaN(extent[1])){
createOrUpdateEmpty(extent)
}
this.extentRevision_=this.getRevision();
}
return returnOrUpdate(this.extent_,extent)
}
rotate(angle,anchor){
abstract()
}
scale(xs,xy,anchor){
abstract()
}
simplify(tolerance){
return this.getSimplifiedGeometry(tolerance * tolerance)
}
getSimplifiedGeometry(squaredTolerance){
return abstract();
}
getType(){
return abstract();
}
applyTransform(transformFn){
abstract()
}
intersectsExtent(extent){
return abstract()
}
translate(deltaX,deltaY){
abstract()
}
transform(source,destination){
const tmpTransform=createTransform()
const sourceProj=getProjection(source);
const transformFn= sourceProj.getUnits()=='tile-pixels'
?function (inCoordinates,outCoordinates,stride){
const pixelExtent=sourceProj.getExtent();
const projectedExtent = sourceProj.getWorldExtent();
const scale=getHeight(projectedExtent)/getHeight(pixelExtent);
composeTransform(tmpTransform,projectedExtent[0],projectedExtent[3]),scale,-scale,0,0,0);
transform2D(inCoordinates,0,inCoordinates.length,stride,tmpTransform,outCoordinates);
return getTransform(sourceProj,destination)(inCoordinates,outCoordinates,stride)
}
: getTransform(sourceProj,destination);
this.appyTransform(transformFn)
return this;
}
}
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
# Geometry
类构造函数
Geometry
类的构造函数中调用createEmpty
方法返回了一个数组[Infinity, Infinity, -Infinity, -Infinity]
给this.extent_
,this.extent_
表示的是几何对象的边界范围;然后初始化this.extentRevision_
为-1
,这个变量是用来记录边界范围的更改次数(修订版本);再初始化this.simplifiedGeometryMaxMinSquaredTolerance
变量即几何对象的最大最小平方公差为0
,初始化this.simplifiedGeometryRevision
为0
,记录几何对象的变化次数;调用memoizeOne
方法用于获取几何对象的转换和简化版本,返回值赋给this.simplifyTransformedInternal
.
memoizeOne
方法主要就是包装并返回一个函数,它会记录函数第一次被调用时的返回值,参数以及this
,当函数再次被调用时,它会拿新的参数和this
与记录上一次的参数和this
作比较,若他们相同,则直接返回上一次的返回值;否则执行函数,并再次记录下返回值,参数和this
用于下一次被调用时作比较.
# Geometry
类的方法
Geometry
类中定义了一些方法,其中有许多未实现,只是定义了,实现的是基础核心的方法,如下:
simplifyTransformed
方法:接受两个参数squaredTolerance
平方公差和transform
转换函数,内部就是调用this.simplifyTransformedInternal
方法并返回结果clone
方法:未实现,用于复制几何对象closestPointXY
方法:未实现,用于比较一个目标点与几何对象中的点之间的距离,并更新最近点的坐标,返回更小的距离containsXY
方法:接受一个坐标x
和y
,然后调用this.getClosestPoint
获取最近点坐标,判断参数坐标是不是与最近点坐标相同getClosestPoint
方法:接受两个坐标,目标点坐标和最近点坐标,其中若最近点坐标不存在,则赋值为[NaN,NaN]
,然后调用this.closestPointXY
更新最近点坐标并返回intersectsCoordinate
方法:接受一个点坐标,然后调用this.containsXY
并返回;该方法就是用于判断点是否在几何对象的边界上;computeExtent
方法:未实现,用于计算边界范围getExtent
方法:用于获取边界范围;内部会调用this.getRevision
方法获取revision_
,它们都是在Observable
类中定义的,Observable
类就是BaseObject
类的父类,关于Observable
类可以参考;当获取到的revision
和this.extentRevision_
不等时,会调用this.computeExtent
计算边界范围,然后判断,若计算得到的extent
不存在,则调用createOrUpdateEmpty
创建一个边界范围,然后更新this.extentRevision_
的值,最后调用returnOrUpdate
得到边界范围并返回.rotate
方法:未实现,该方法就是给定一个坐标值,然后旋转几何对象,这个操作会修改几何对象的坐标scale
方法:未实现,该方法用于对几何对象进行缩放,同样地,会修改几何对象的坐标值simplify
方法:未实现,该方法用于创建一个几何对象的简化版本getSimplifiedGeometry
方法:未实现,该方法用于获取几何对象的简化版getType
方法:未实现,该方法用于获取几何对象的类型applyTransform
方法:未实现,该方法用于对几何对象的坐标应用transform
函数进行转换,intersectsExtent
方法:未实现,该方法用于判断几何对象与参数extent
范围是否相交translate
方法:该方法用于对几何对象进行平移,同样地,会修改几何对象的坐标值transform
方法:该方法目的是将几何对象的坐标从一个投影系转换到另一个投影系.接受两个参数source
源投影和destination
目标投影;先是调用getProjection
获取源投影source
的投影对象,然后判断,若投影对象的单位类型是栅格投影,就获取源投影的像素范围pixelExtent
和projectedExtent
投影范围,通过它们计算一个缩放比例scale
,然后调用composeTransform
构建一个转换矩阵tmpTransform
,用于像素坐标转换到投影坐标.然后调用transform2D
,通过转换矩阵tmpTransform
将输入坐标inCoordinates
转化为目标坐标outCoordinates
,再调用getTransform
获取坐标转换函数,该函数就是用于将坐标从源投影转换到目标投影;若投影对象的单位类型不是栅格投影,则直接使用getTransform
获取转换函数;最后调用this.applyTransform
将得到的transformFn
作为变换函数应用到几何对象上,对几何对象的所有点坐标进行转换.
# 总结
Openlayers 中的 Geometry
类是所有几何类型的基础类,通过继承它的子类,可以表示不同类型的几何对象。Geometry
类提供了丰富的方法来操作几何数据,如坐标变换、几何计算、空间关系判断等.