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

  • Renderer篇

  • Feature篇

  • style样式篇

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

LineString类

# 概述

在 Openlayers 中,LineString 类是用于表示几何线段的类。这个类继承自 SimpleGeometry 类,关于SimpleGeometry类可以参考这篇文章,它代表了一条线段或路径,可以由一系列的坐标点组成。LineString 通常用于地图中的路径、线段等几何形状的表示。

# 源码分析

# LineString类源码实现

LineString类的实现如下:

class LineString extends SimpleGeometry {
  constructor(coordinates, layout) {
    super();
    this.flatMidpoint_ = null;
    this.flatMidpointRevision_ = -1;
    this.maxDelta_ = -1;
    this.maxDeltaRevision_ = -1;
    if (layout !== undefined && !Array.isArray(coordinates[0])) {
      this.setFlatCoordinates(layout, coordinates);
    } else {
      this.setCoordinates(coordinates, layout);
    }
  }
  appendCoordinate(coordinate) {
    extend(this.flatCoordinates, coordinate);
    this.changed();
  }
  clone() {
    const lineString = new LineString(
      this.flatCoordinates.slice(),
      this.layout
    );
    lineString.applyProperties(this);
    return lineString;
  }
  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_,
      false,
      x,
      y,
      closestPoint,
      minSquaredDistance
    );
  }
  forEachSegment(callback) {
    return forEachSegment(
      this.flatCoordinates,
      0,
      this.flatCoordinates.length,
      this.stride,
      callback
    );
  }
  getCoordinateAtM(m, extrapolate) {
    if (this.layout != "XYM" && this.layout != "XYZM") {
      return null;
    }
    extrapolate = extrapolate !== undefined ? extrapolate : false;
    return lineStringCoordinateAtM(
      this.flatCoordinates,
      0,
      this.flatCoordinates.length,
      this.stride,
      m,
      extrapolate
    );
  }
  getCoordinates() {
    return inflateCoordinates(
      this.flatCoordinates,
      0,
      this.flatCoordinates.length,
      this.stride
    );
  }

  getCoordinateAt(fraction, dest) {
    return interpolatePoint(
      this.flatCoordinates,
      0,
      this.flatCoordinates.length,
      this.stride,
      fraction,
      dest,
      this.stride
    );
  }

  getLength() {
    return lineStringLength(
      this.flatCoordinates,
      0,
      this.flatCoordinates.length,
      this.stride
    );
  }

  getFlatMidpoint() {
    if (this.flatMidpointRevision_ != this.getRevision()) {
      this.flatMidpoint_ = this.getCoordinateAt(
        0.5,
        this.flatMidpoint_ ?? undefined
      );
      this.flatMidpointRevision_ = this.getRevision();
    }
    return this.flatMidpoint_;
  }

  getSimplifiedGeometryInternal(squaredTolerance) {
    const simplifiedFlatCoordinates = [];
    simplifiedFlatCoordinates.length = douglasPeucker(
      this.flatCoordinates,
      0,
      this.flatCoordinates.length,
      this.stride,
      squaredTolerance,
      simplifiedFlatCoordinates,
      0
    );
    return new LineString(simplifiedFlatCoordinates, "XY");
  }

  getType() {
    return "LineString";
  }

  intersectsExtent(extent) {
    return intersectsLineString(
      this.flatCoordinates,
      0,
      this.flatCoordinates.length,
      this.stride,
      extent
    );
  }

  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();
  }
}
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

# LineString类的构造函数

LineString类的构造函数接受两个参数坐标数组coordinates和坐标布局layout,构造函数内部定义了几个变量,如下:

  • this.flatMidpoint_:几何对象(线)的中点,初始值为null

  • this.flatMidpointRevision_:中点的修订版本,初始值为-1

  • this.maxDelta和this.maxDeltaRevision_都是用于缓存计算结果和提高性能,当几何对象坐标发生变化时,这些变量都会重新复制,用于下次几何对象发还是呢个变化时进行对比计算,决定是重新计算还是直接返回上次计算的结果

除此之外,构造函数还会判断,若参数layout存在且坐标数组coordinates不是一个嵌套数组,则会调用父类SimpleGeometry类中的setFlatCoordinates方法,将扁平化坐标数据应用到对象中,设置this.layout、this.stride和this.flatCoordinates;否则调用setCoordinate方法设置坐标。

# LineString类的主要方法

LineString类的主要方法如下:

  • appendCoordinate方法:添加一个坐标到几何对象中,调用extend方法修改this.flatCoordinates变量,然后调用this.changed方法

  • clone方法:复制当前几何对象,实例化LineString类,然后调用applyProperties方法应用属性,最后返回实例对象lineString

  • closestPointXY方法:接受四个参数,目标点坐标(x,y),最近点closestPoint和最小距离平方minSquaredDistance;closestPointXY方法主要修改最近点坐标,然后返回最小距离平方;方法内部会先计算目标点距离包围盒的最短距离的平方,与minSquaredDistance比较,若minSquaredDistance更小,则直接将它返回;判断,若几何对象发生了变化,则调用``maxSquaredDelta计算几何对象相邻点坐标的最大距离的平方,将其返回值赋值给this.maxDelta_,然后更新记录this.maxDeltaRevision_版本号,最后调用assignClosestPoint`方法计算最短距离平方并返回,该方法内部还会更新最近点坐标

  • forEachSegment方法:该方法是对几何对象中的每一个线段应用参数callback函数,若回调函数callback有返回值且为真值,则返回该值,跳出循环,否则最后返回false;

  • getCoordinateAM方法:获取几何对象在M处的坐标;getCoordinateAM方法内部会先判断坐标布局this.layout是否含有M,若不包含这个M属性,则返回null;判断extrapolate是否为undefined,若该参数传值了则取参数值,否则默认为false;最后调用lineStringCoordinateAtM方法并返回结果。lineStringCoordinateAtM方法会根据参数m推断出几何对象在M值为m时的坐标,若该坐标超出了几何对象的范围,且extrapolate为true,则返回该坐标,否则返回null;若该坐标没有超出范围,则返回该坐标。

  • getCoordinates方法:获取几何对象的坐标,本质上就是调用inflateCoordinates方法并返回结果。

  • getCoordinateAt方法:该方法就是返回LineString上某个特定位置的坐标,接受两个参数fraction和dest;fraction的取值范围是[0,1],0表示几何对象的起点,1表示几何对象的终点,介于0和1时表示线段相对比例处的坐标;dest是目标数组,用于存放返回的坐标,当其传值时,则该方法会修改dest参数并返回,若不传,则返回新的坐标数组。方法内部是调用interpolatePoint方法并返回结果。

  • getLength方法:计算几何对象的长度,内部是调用lineStringLength方法并返回结果,实际上就是计算几何对象(线段)相邻坐标的距离然后累加。

  • getFlatMidpoint方法:方法内部会先判断几何对象是否发生了改变,若未改变,则返回this.flatMidpoint_,也就是上一次计算结果的缓存;否则会调用this.getCoordinateAt方法,第一个参数fraction传0.5,表示获取线段的中点坐标,然后将该值赋值给this.flatMidpoint_,修改几何对象中点记录的版本号,最后返回this.flatMidpoint_。

  • getSimplifiedGeometryInternal方法:获取线段的简化版,内部就是调用douglasPeucker算法,获取简化版的几何对象坐标,然后实例化LineString类并返回实例对象。

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

  • intersectsExtent方法:判断矩形extent是否与几何对象相交

  • setCoordinates方法:设置几何对象的坐标this.flatCoordinates、this.layout和this.stride,最后调用this.changed方法

# 总结

本文主要介绍了LineString类的源码实现,LinString类提供了许多实用的方法,比如获取线段长度,线段上指定位置的坐标。

编辑 (opens new window)
上次更新: 2024/12/30, 02:08:27
MultiPolygon类
MultiLineString类

← MultiPolygon类 MultiLineString类→

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