Jinuss's blog Jinuss's blog
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

前端可视化
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 核心基类

  • Control控件篇

  • Geom几何图形篇

    • Geom几何图形篇介绍
    • Geometry基类
    • GeometryCollection类
      • 概述
      • 源码分析
        • GeometryCollection类源码实现
        • GeometryCollection类构造函数
        • GeometryCollection类的方法
      • 总结
    • SimpleGeometry类
    • Point类
    • MultiPoint类
    • LinearRing类
    • Polygon类
    • MultiPolygon类
    • LineString类
    • MultiLineString类
    • Circle类
  • Layer图层篇

  • Renderer篇

  • Feature篇

  • style样式篇

  • 《Openlayers源码》笔记
  • Geom几何图形篇
东流
2024-12-24
目录

GeometryCollection类

# 概述

本文主要介绍GeometryCollection类,GeometryCollection类继承于Geometry类,关于Geometry类,参考这篇文章

GeometryCollection类就是一组几何对象的集合.

# 源码分析

# GeometryCollection类源码实现

GeometryCollection类源码实现如下:

class GeometryCollection extends Geometry {
  constructor(geometries) {
    super();
    this.geometries_ = geometries;
    this.changeEventKeys_ = [];
    this.listenGeometriesChange_();
  }
  unlistenGeometriesChange_() {
    this.changeEventsKeys_.forEach(unlistenByKey);
    this.changeEventsKeys_.length = 0;
  }
  listenGeometriesChange_() {
    const geometries = this.geometries_;
    for (let i = 0, ii = geometries.length; i < ii; ++i) {
      this.changeEventsKeys_.push(
        listen(geometries[i], EventType.CHANGE, this.changed, this)
      );
    }
  }
  clone() {
    const geometryCollection = new GeometryCollection(
      cloneGeometries(this.geometries_)
    );
    geometryCollection.applyProperties(this);
    return geometryCollection;
  }
  closestPointXY(x, y, closestPoint, minSquaredDistance) {
    if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {
      return minSquaredDistance;
    }
    const geometries = this.geometries_;
    for (let i = 0, ii = geometries.length; i < ii; ++i) {
      minSquaredDistance = geometries[i].closestPointXY(
        x,
        y,
        closestPoint,
        minSquaredDistance
      );
    }
    return minSquaredDistance;
  }
  containsXY(x, y) {
    const geometries = this.geometries_;
    for (let i = 0, ii = geometries.length; i < ii; ++i) {
      if (geometries[i].containsXY(x, y)) {
        return true;
      }
    }
    return false;
  }
  computeExtent(extent) {
    createOrUpdateEmpty(extent);
    const geometries = this.geometries_;
    for (let i = 0, ii = geometries.length; i < ii; ++i) {
      extend(extent, geometries[i].getExtent());
    }
    return extent;
  }
  getGeometries() {
    return cloneGeometries(this.geometries_);
  }
  getGeometriesArray() {
    return this.geometries_;
  }
  getGeometriesArrayRecursive() {
    /** @type {Array<Geometry>} */
    let geometriesArray = [];
    const geometries = this.geometries_;
    for (let i = 0, ii = geometries.length; i < ii; ++i) {
      if (geometries[i].getType() === this.getType()) {
        geometriesArray = geometriesArray.concat(
          geometries[i].getGeometriesArrayRecursive()
        );
      } else {
        geometriesArray.push(geometries[i]);
      }
    }
    return geometriesArray;
  }
  getSimplifiedGeometry(squaredTolerance) {
    if (this.simplifiedGeometryRevision !== this.getRevision()) {
      this.simplifiedGeometryMaxMinSquaredTolerance = 0;
      this.simplifiedGeometryRevision = this.getRevision();
    }
    if (
      squaredTolerance < 0 ||
      (this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
        squaredTolerance < this.simplifiedGeometryMaxMinSquaredTolerance)
    ) {
      return this;
    }

    const simplifiedGeometries = [];
    const geometries = this.geometries_;
    let simplified = false;
    for (let i = 0, ii = geometries.length; i < ii; ++i) {
      const geometry = geometries[i];
      const simplifiedGeometry =
        geometry.getSimplifiedGeometry(squaredTolerance);
      simplifiedGeometries.push(simplifiedGeometry);
      if (simplifiedGeometry !== geometry) {
        simplified = true;
      }
    }
    if (simplified) {
      const simplifiedGeometryCollection = new GeometryCollection(
        simplifiedGeometries
      );
      return simplifiedGeometryCollection;
    }
    this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
    return this;
  }
  getType() {
    return "GeometryCollection";
  }
  intersectsExtent(extent) {
    const geometries = this.geometries_;
    for (let i = 0, ii = geometries.length; i < ii; ++i) {
      if (geometries[i].intersectsExtent(extent)) {
        return true;
      }
    }
    return false;
  }
  isEmpty() {
    return this.geometries_.length === 0;
  }
  rotate(angle, anchor) {
    const geometries = this.geometries_;
    for (let i = 0, ii = geometries.length; i < ii; ++i) {
      geometries[i].rotate(angle, anchor);
    }
    this.changed();
  }
  scale(sx, sy, anchor) {
    if (!anchor) {
      anchor = getCenter(this.getExtent());
    }
    const geometries = this.geometries_;
    for (let i = 0, ii = geometries.length; i < ii; ++i) {
      geometries[i].scale(sx, sy, anchor);
    }
    this.changed();
  }
  setGeometries(geometries) {
    this.setGeometriesArray(cloneGeometries(geometries));
  }
  setGeometriesArray(geometries) {
    this.unlistenGeometriesChange_();
    this.geometries_ = geometries;
    this.listenGeometriesChange_();
    this.changed();
  }
  applyTransform(transformFn) {
    const geometries = this.geometries_;
    for (let i = 0, ii = geometries.length; i < ii; ++i) {
      geometries[i].applyTransform(transformFn);
    }
    this.changed();
  }
  translate(deltaX, deltaY) {
    const geometries = this.geometries_;
    for (let i = 0, ii = geometries.length; i < ii; ++i) {
      geometries[i].translate(deltaX, deltaY);
    }
    this.changed();
  }
  disposeInternal() {
    this.unlistenGeometriesChange_();
    super.disposeInternal();
  }
}
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
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
161
162
163
164
165
166
167
168
169
170
171
172
173

# GeometryCollection类构造函数

GeometryCollection类构造函数接受一个参数geometries,geometries是一个包含多个几何对象数组,该参数会赋给全局变量this.geometries_,然后初始化一个变量this.changeEventsKeys_为空数组,最后调用this.listenGeometriesChange_方法.

# GeometryCollection类的方法

GeometryCollection类的方法主要是对几何对象的一些操作,会去遍历this.geometries_变量,逐一进行操作.GeometryCollection类中的主要方法如下:

  • listenGeometriesChange_方法:该方法在构造函数中就会被调用,其核心逻辑就是循环遍历this.geometries_,调用listen方法注册每个几何对象的change事件监听,注册事件返回的keys值保存在全局变量this.changeEventsKeys_中.listen方法的实现可以参考这篇文章

  • unlistenGeometriesChange_方法:用于取消监听,重置this.changeEventKeys_为空数组,解绑方法unlistenByKey同样是在event.js中实现的.

  • clone方法:clone方法会返回一个新的几何对象集合,其内部会先调用cloneGeometries方法去clone每一个Geometry,然后实例化GeometryCollection类,再会调用applyProperties去应用this,applyProperties方法是在Object类中实现的,主要就是复制属性.

  • closestPointXY方法:用于获取对几何对象稽核最近的点坐标,以及修改并获取最短距离;方法接受四个参数目标点坐标x``y,最近点坐标以及最短距离,会先调用closestSquaredDistanceXY获取目标坐标点到边界范围的平方距离,若最短距离大于该参数最短平方距离,则返回参数minSquaredDistance;然后遍历this.geometries_,调用每一个几何对象的closestPointXY方法,修改最近点坐标和最短距离;最后返回最短距离

  • containsXY方法:同样地也是遍历this.geometries_,调用几何对象的containsXY方法;containsXY方法就是判断点是否在几何对象集合的边界上,返回一个布尔值。

  • computeExtent方法:获取几何对象集合的边界范围

  • getGeometries方法:获取几何对象集合的副本,调用cloneGeometries方法

  • getGeometriesArray方法:获取几何对象集合数组

  • getGeometriesArrayRecursive方法:将嵌套的几何对象(如子集合)展平成一个平坦的数组,即若几何对象数组中的数组项也是一个数组,那么就会递归调用它的getGeometriesArrayRecursive方法。

  • getSimplifiedGeometry方法:该方法就是用于简化几何,采用了Douglas-Peucker算法。这个算法常用于简化折线几何,减少点的数量,同时尽可能保持原始几何形状的准确性。简化通过一个容差值来控制简化的程度,容差值越大,简化的结果就越简单。getSimplifiedGeometry方法会先检查修订号,若当前几何对象的修订号与上次简化的修订号不一致这说明几何对象已经发生了变化,需要重新计算简化后的几何对象;然后会检查容差值,若容差值小于0或者小于已经记录的最大容差值,则不需要重新计算,直接返回当前对象;然后初始化一个空数组,simplifiedGeometries用于存储简化后的几何对象,再遍历this.geometries_,调用每个几何对象的getSimplifiedGeometry方法,简化每一个几何对象;若简化后的实例对象不等于原始对象,则将simplified赋值为true,然后实例化GeometryCollection类,生成一个几何对象集合实例并返回;若简化后的实例对象与原始对象相同,一个几何对象也没有被简化,则返回当前对象this.

  • getType方法:获取类型,返回GeometryCollection

  • intersectsExtent方法:遍历this.geometries_,然后调用每个几何对象的intersectsExtent方法,判断几何对象是否与extent相交;若有一个几何对象和extent相交则返回true;若一个都不相交,则返回false。

  • isEmpty方法:判断几何对象集合是否为空,返回一个布尔值。

  • rotate方法:遍历this.geometries_,然后调用每个几何对象的rotate方法,最后调用this.changed方法

  • scale方法:遍历this.geometries_,然后调用每个几何对象的scale方法,最后调用this.changed方法

  • setGeometries方法:会先调用cloneGeometries方法clone每个几何对象,然后调用this.setGeometriesArray方法

  • setGeometriesArray方法:会调用this.unlistenGeometriesChange_取消监听,然后设置this.geometries_,再调用this.listenGeometriesChange_方法注册监听,最后调用this.changed方法

  • applyTransform方法:遍历this.geometries_,然后调用每个几何对象的applyTransform方法,最后调用this.changed方法

  • translate方法:遍历this.geometries_,然后调用每个几何对象的translate方法,最后调用this.changed方法

  • disposeInternal方法:清理函数,调用this.unlistenGeometriesChange_取消监听,再调用父类的disposeInternal方法

# 总结

本文介绍了GeometryCollection类的源码实现,由此可以清晰理解GeometryCollection类主要还是一组多个对几何对象进行平移、旋转和缩放转换以及空间关系的判断等等。

编辑 (opens new window)
上次更新: 2024/12/24, 08:22:27
Geometry基类
SimpleGeometry类

← Geometry基类 SimpleGeometry类→

最近更新
01
GeoJSON
05-08
02
Circle
04-15
03
CircleMarker
04-15
更多文章>
Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式