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类
    • SimpleGeometry类
    • Point类
    • MultiPoint类
    • LinearRing类
    • Polygon类
    • MultiPolygon类
    • LineString类
    • MultiLineString类
      • 概述
      • 源码分析
        • MultiLineString类的源码实现
        • MultiLineString类的构造函数
        • MultiLineString类的主要方法
      • 总结
    • Circle类
  • Layer图层篇

  • Renderer篇

  • Feature篇

  • style样式篇

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

MultiLineString类

# 概述

在 Openlayers 中,MultiLineString类用于创建多个线段,和LineString类类似(可参考这篇文字。MultiLineString类也是继承于SimpleGeometry类,关于该类,可以参考。

本文主要介绍MultiLineString类的源码实现和原理。

# 源码分析

# MultiLineString类的源码实现

class MultiLineString extends SimpleGeometry {
  constructor(coordinates, layout, ends) {
    super();
    this.ends_ = [];
    this.maxDelta_ = -1;
    this.maxDeltaRevision_ = -1;

    if (Array.isArray(coordinates[0])) {
      this.setCoordinates(coordinates, layout);
    } else if (layout !== undefined && ends) {
      this.setFlatCoordinates(layout, coordinates);
      this.ends_ = ends;
    } else {
      const lineStrings = coordinates;
      const flatCoordinates = [];
      const ends = [];
      for (let i = 0, ii = lineStrings.length; i < ii; ++i) {
        const lineString = lineStrings[i];
        extend(flatCoordinates, lineString.getFlatCoordinates());
        ends.push(flatCoordinates.length);
      }
      const layout =
        lineStrings.length === 0
          ? this.getLayout()
          : lineStrings[0].getLayout();
      this.setFlatCoordinates(layout, flatCoordinates);
      this.ends_ = ends;
    }
  }
  appendLineString(lineString) {
    extend(this.flatCoordinates, lineString.getFlatCoordinates().slice());
    this.ends_.push(this.flatCoordinates.length);
    this.changed();
  }
  clone() {
    const multiLineString = new MultiLineString(
      this.flatCoordinates.slice(),
      this.layout,
      this.ends_.slice()
    );
    multiLineString.applyProperties(this);
    return multiLineString;
  }
  closestPointXY(x, y, closestPoint, minSquaredDistance) {
    if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {
      return minSquaredDistance;
    }
    if (this.maxDeltaRevision_ != this.getRevision()) {
      this.maxDelta_ = Math.sqrt(
        arrayMaxSquaredDelta(
          this.flatCoordinates,
          0,
          this.ends_,
          this.stride,
          0
        )
      );
      this.maxDeltaRevision_ = this.getRevision();
    }
    return assignClosestArrayPoint(
      this.flatCoordinates,
      0,
      this.ends_,
      this.stride,
      this.maxDelta_,
      false,
      x,
      y,
      closestPoint,
      minSquaredDistance
    );
  }
  getCoordinateAtM(m, extrapolate, interpolate) {
    if (
      (this.layout != "XYM" && this.layout != "XYZM") ||
      this.flatCoordinates.length === 0
    ) {
      return null;
    }
    extrapolate = extrapolate !== undefined ? extrapolate : false;
    interpolate = interpolate !== undefined ? interpolate : false;
    return lineStringsCoordinateAtM(
      this.flatCoordinates,
      0,
      this.ends_,
      this.stride,
      m,
      extrapolate,
      interpolate
    );
  }
  getCoordinates() {
    return inflateCoordinatesArray(
      this.flatCoordinates,
      0,
      this.ends_,
      this.stride
    );
  }
  getEnds() {
    return this.ends_;
  }
  getLineString(index) {
    if (index < 0 || this.ends_.length <= index) {
      return null;
    }
    return new LineString(
      this.flatCoordinates.slice(
        index === 0 ? 0 : this.ends_[index - 1],
        this.ends_[index]
      ),
      this.layout
    );
  }
  getFlatMidpoints() {
    const midpoints = [];
    const flatCoordinates = this.flatCoordinates;
    let offset = 0;
    const ends = this.ends_;
    const stride = this.stride;
    for (let i = 0, ii = ends.length; i < ii; ++i) {
      const end = ends[i];
      const midpoint = interpolatePoint(
        flatCoordinates,
        offset,
        end,
        stride,
        0.5
      );
      extend(midpoints, midpoint);
      offset = end;
    }
    return midpoints;
  }
  getSimplifiedGeometryInternal(squaredTolerance) {
    const simplifiedFlatCoordinates = [];
    const simplifiedEnds = [];
    simplifiedFlatCoordinates.length = douglasPeuckerArray(
      this.flatCoordinates,
      0,
      this.ends_,
      this.stride,
      squaredTolerance,
      simplifiedFlatCoordinates,
      0,
      simplifiedEnds
    );
    return new MultiLineString(simplifiedFlatCoordinates, "XY", simplifiedEnds);
  }
  getType() {
    return "MultiLineString";
  }
  intersectsExtent(extent) {
    return intersectsLineStringArray(
      this.flatCoordinates,
      0,
      this.ends_,
      this.stride,
      extent
    );
  }
  setCoordinates(coordinates, layout) {
    this.setLayout(layout, coordinates, 2);
    if (!this.flatCoordinates) {
      this.flatCoordinates = [];
    }
    const ends = deflateCoordinatesArray(
      this.flatCoordinates,
      0,
      coordinates,
      this.stride,
      this.ends_
    );
    this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];
    this.changed();
  }
}
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
174
175
176
177

# MultiLineString类的构造函数

MultiLineString类的构造函数接受三个参数:坐标数组coordinates、坐标布局方式layout和每个线段的结束点ends;构造函数内部还定义了两个变量this.maxDelta_和this.maxDeltaRevision_用于记录几何对象的修订版本号,在几何对象进行重新计算和渲染时用于判断是否使用缓存,可以提高性能,它们初始值都是为-1;构造函数会判断参数coordinates是否为一个二维数组,若是,则调用this.setCoordinates方法设置坐标;否则,判断参数layout和ends,若它们都传值了,则调用this.setFlatCoordinates方法;否则认为coordinates表示的是多个线段的数组;然后循环遍历它,将每个线段的坐标数据添加到变量flatCoordinates中,并且将每个线段的坐标长度添加到ends中,最后调用this.setFlatCoordinates方法,设置坐标。

# MultiLineString类的主要方法

MultiLineString类的主要方法如下:

  • appendLineString方法:向当前几何对象中添加一条线段,参数lineString是LineString类的实例,内部就是会调用lineString.getFlatCoordinates获取参数线段的坐标,然后将它添加到this.flatCoordinates中,更新this.ends_的值,最后调用this.changed方法

  • clone方法:复制几何对象,实例化MultiLineString类,调用applyProperties方法应用属性,最后返回实例对象。

  • closestPointXY方法: 接受四个参数,给定点的x、y、最近点closestPoint和最小距离平方minSquaredDistance;closestPointXY方法内部会先调用closestSquaredDistanceXY计算给定点与包围盒的最小距离的平方,将之与minSquaredDistance的大小进行对比,若minSquaredDistance较小,则返回它;否则,判断几何对象是否发生了改变,若未改变,则使用之前的this.maxDelta_调用assignClosestArrayPoint方法计算最小距离平方并返回,并且更新最近点坐标closestPoint;若改变了,则调用arrayMaxSquaredDelta方法计算几何对象相邻两点坐标的最大距离,将其赋值给this.maxDelta_,更新this.maxDeltaRevision_的值,最后调用assignClosestArrayPoint方法。

  • getCoordinateAtM方法:使用线性插值返回几何对象在属性为M处的坐标,如果不存在,则返回null e

  • getCoordinates方法:返回坐标数据,内部就是调用inflateCoordinatesArray方法将扁平化一维数组this.flatCoordinates转为多维数组并返回。

  • getEnds方法:返回this.ends值,即返回所有线段的结束点

  • getLineString方法:接受一个参数index,判断参数index是否合法;然后截取this.flatCoordinates实例化LineString类并返回实例对象。

  • getLineStrings方法:返回几何对象的所有线段,通过遍历this.ends截取this.flatCoordinates,然后实例化LineString类,最后返回包含所有线段的lineStrings数组。

  • getFlatMidpoints方法:返回所有线段的中点,核心方法是interpolatePoint获取每条线段的中点,然后将其放入数组midpoints中,最后返回。

  • getSimplifiedGeometryInternal方法:该方法用于获取几何对象的简化版,内部也是调用douglasPeucker算法进行简化几何对象,获取简化对象的坐标数据,然后传入获取的坐标数据 实例化MultiLineString类,最后返回实例。

  • getType方法:返回几何对象的类型,MultiLineString

  • intersectsExtent方法:判断矩形extent是否与几何对象相交,内部调用的是intersectsLineStringArray方法并返回其结果;

  • setCoordinates方法:设置坐标this.flatCoordinates,坐标布局方式this.layout以及步幅this.stride

# 总结

本文介绍了MultiLineString类的源码实现,说白了就是多线段几何对象,很多方法都和LineString类相似。

编辑 (opens new window)
上次更新: 2024/12/30, 07:02:38
LineString类
Circle类

← LineString类 Circle类→

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