惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Secure Thoughts
Security Latest
Security Latest
Simon Willison's Weblog
Simon Willison's Weblog
O
OpenAI News
GbyAI
GbyAI
L
LINUX DO - 最新话题
A
Arctic Wolf
T
Tor Project blog
G
GRAHAM CLULEY
I
InfoQ
博客园_首页
IT之家
IT之家
The Register - Security
The Register - Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Proofpoint News Feed
The GitHub Blog
The GitHub Blog
Blog — PlanetScale
Blog — PlanetScale
N
Netflix TechBlog - Medium
K
Kaspersky official blog
博客园 - 三生石上(FineUI控件)
S
SegmentFault 最新的问题
U
Unit 42
PCI Perspectives
PCI Perspectives
量子位
P
Palo Alto Networks Blog
S
Securelist
T
Troy Hunt's Blog
博客园 - 【当耐特】
Recorded Future
Recorded Future
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
S
Security Affairs
Engineering at Meta
Engineering at Meta
T
The Blog of Author Tim Ferriss
博客园 - 聂微东
罗磊的独立博客
N
News and Events Feed by Topic
人人都是产品经理
人人都是产品经理
B
Blog RSS Feed
NISL@THU
NISL@THU
C
Cisco Blogs
T
Threatpost
有赞技术团队
有赞技术团队
Forbes - Security
Forbes - Security
Hugging Face - Blog
Hugging Face - Blog
Last Week in AI
Last Week in AI
T
The Exploit Database - CXSecurity.com
Cloudbric
Cloudbric
Cyberwarzone
Cyberwarzone
Google DeepMind News
Google DeepMind News
C
Cyber Attacks, Cyber Crime and Cyber Security

zouyaoji's Blog

重启:从 Cesium 到“技术伙伴”协作时代 | zouyaoji's Blog Cesium - 加载高德实时栅格路况图层 | zouyaoji's Blog 全栈开发学习:Vue2+Koa2 开发前后端分离项目一(登陆验证) | zouyaoji's Blog 让我们对地形动动手脚 | zouyaoji's Blog JavaScript面向对象编程总结 | zouyaoji's Blog Visual Studio Code 插件扩展推荐 | zouyaoji's Blog 2017小结 | zouyaoji's Blog
Cesium - 距离、面积、高度量算 | zouyaoji's Blog
zouyaoji,370681295@qq.com · 2019-12-21 · via zouyaoji's Blog

前言

近期工作之余都在继续开发个人开源项目 vue-cesium ,在最近学习中发现自己之前码的代码不太优雅,不太精炼,所以花不少时间重构了第二版,获益匪浅。其中就发现之前做的量算功能结果不太合适,尤其是面积量算,看网上很少有正确的思路,所以在这儿记录核心代码,详细请移步 GitHub 查看,欢迎提 Issue、PR,顺便小手点个 Star 也可以。vue-cesium 在 2.0.3 版本将会优化量算组件,在线体验地址: https://zouyaoji.top/vue-cesium/#/zh/tool/vc-measuring

距离量算

之前用的是 Cartesian3.distance 计算两点之间的距离,但这是不合适的,原因是 Cartesian3.distance 计算的是两点之间的直线距离,忽略了地球曲率,不太合理,应该改为量算测地距离(GeodesicDistance)。代码如下:

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





getDistance (positions) {

let distance = 0
for (let i = 0; i < positions.length - 1; i++) {



let s = this.getGeodesicDistance(positions[i], positions[i + 1])
distance = distance + s
}
return distance
},






getGeodesicDistance (pointOne, pointTwo) {
const { Ellipsoid, EllipsoidGeodesic } = Cesium
const pickedPointCartographic = Ellipsoid.WGS84.cartesianToCartographic(
pointOne
)
const lastPointCartographic = Ellipsoid.WGS84.cartesianToCartographic(
pointTwo
)
const geodesic = new EllipsoidGeodesic(
pickedPointCartographic,
lastPointCartographic
)
return geodesic.surfaceDistance
}

面积量算

之前用的是将笛卡尔坐标数组转经纬度然后构造 turf 的多边形对象,用 @turf/area 计算多边形面积,这很好,本身并没有问题,但美中不足的是这个实际上计算的是三维面投影到二维表名的投影面积,没有考虑高度。近期我才 GET 到正确的解决思路是将多边形分解成多个三角形,这点 Cesium 直接轻松做到,然后用海伦公式计算面积。话不多说,上代码:

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





getProjectedArea (positions) {
const { Cartographic, Math: CesiumMath } = Cesium
let array = []
for (let i = 0, len = positions.length; i < len; i++) {
let cartographic = Cartographic.fromCartesian(positions[i])
let longitude = CesiumMath.toDegrees(cartographic.longitude).toFixed(6)
let latitude = CesiumMath.toDegrees(cartographic.latitude).toFixed(6)
array.push({ x: longitude, y: latitude })
}
let arrs = []
let tems = []
arrs.push(tems)
for (let i = 0, len = array.length; i < len; i++) {
tems.push([array[i].x, array[i].y])
}
let polygons = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: arrs
}
},
{
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: [[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]]
}
}
]
}
return area(polygons)
},





getSurfaceArea (positions) {
if (positions.length < 3) {
return 0
}
const { Cartesian3, EllipsoidTangentPlane, Ellipsoid, Math: CesiumMath, PolygonGeometryLibrary, PolygonHierarchy, VertexFormat } = Cesium
const perPositionHeight = true

const tangentPlane = EllipsoidTangentPlane.fromPoints(
positions,
Ellipsoid.WGS84
)
const polygons = PolygonGeometryLibrary.polygonsFromHierarchy(
new PolygonHierarchy(positions),
tangentPlane.projectPointsOntoPlane.bind(tangentPlane),
!perPositionHeight,
Ellipsoid.WGS84
)

const geom = PolygonGeometryLibrary.createGeometryFromPositions(
Ellipsoid.WGS84,
polygons.polygons[0],
CesiumMath.RADIANS_PER_DEGREE,
perPositionHeight,
VertexFormat.POSITION_ONLY
)

if (geom.indices.length % 3 !== 0 || geom.attributes.position.values.length % 3 !== 0) {

return 0
}
const coords = []
for (let i = 0; i < geom.attributes.position.values.length; i += 3) {
coords.push(
new Cartesian3(
geom.attributes.position.values[i],
geom.attributes.position.values[i + 1],
geom.attributes.position.values[i + 2]
)
)
}
let area = 0
for (let i = 0; i < geom.indices.length; i += 3) {
const ind1 = geom.indices[i]
const ind2 = geom.indices[i + 1]
const ind3 = geom.indices[i + 2]

const a = Cartesian3.distance(coords[ind1], coords[ind2])
const b = Cartesian3.distance(coords[ind2], coords[ind3])
const c = Cartesian3.distance(coords[ind3], coords[ind1])


const s = (a + b + c) / 2.0
area += Math.sqrt(s * (s - a) * (s - b) * (s - c))
}
return area
}

三角测量

三角测量的代码没啥说的,直接移步 Github 查看吧。

The End!

版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 zouyaoji's Blog