源码分析之Openlayers中GeometryCollection类

概述

本文主要介绍GeometryCollection类,GeometryCollection类继承于Geometry类,关于Geometry类,参考这篇文章源码分析之Openlayers中Geometry基类介绍

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

源码分析

GeometryCollection类源码实现

GeometryCollection类源码实现如下:

js 复制代码
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();
  }
}

GeometryCollection类构造函数

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

GeometryCollection类的方法

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

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

  • 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类主要还是一组多个对几何对象进行平移、旋转和缩放转换以及空间关系的判断等等。

相关推荐
Jinuss6 天前
源码分析之Openlayers中OverviewMap鹰眼控件
openlayers
Jinuss7 天前
源码分析之Openlayers中ZoomSlider滑块缩放控件
openlayers
Jinuss7 天前
源码分析之Openlayers中MousePosition鼠标位置控件
openlayers
小彭努力中7 天前
38.在 Vue 3 中使用 OpenLayers 导出地图为 PDF
前端·javascript·vue.js·深度学习·pdf·openlayers
小彭努力中9 天前
32.在 Vue 3 中上传 KML 文件并在地图上显示
前端·javascript·vue.js·深度学习·openlayers
小彭努力中11 天前
29.在Vue 3中使用OpenLayers读取WKB数据并显示图形
前端·javascript·vue.js·深度学习·openlayers
Jinuss13 天前
源码分析之Openlayers中的Zoom缩放控件
openlayers
小彭努力中14 天前
26.使用 Vue 3 + OpenLayers 加载远程 Shapefile 数据并显示图形
前端·javascript·vue.js·arcgis·openlayers
小彭努力中19 天前
16.在 Vue 3 中使用 OpenLayers 实现自定义地图缩放控件
前端·javascript·vue.js·arcgis·openlayers