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

推荐订阅源

Forbes - Security
Forbes - Security
T
Tailwind CSS Blog
Hugging Face - Blog
Hugging Face - Blog
Blog — PlanetScale
Blog — PlanetScale
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
Y
Y Combinator Blog
U
Unit 42
I
InfoQ
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V
Visual Studio Blog
B
Blog RSS Feed
Vercel News
Vercel News
F
Fortinet All Blogs
Know Your Adversary
Know Your Adversary
T
Troy Hunt's Blog
博客园 - 【当耐特】
MongoDB | Blog
MongoDB | Blog
大猫的无限游戏
大猫的无限游戏
A
About on SuperTechFans
Jina AI
Jina AI
小众软件
小众软件
T
Threatpost
有赞技术团队
有赞技术团队
人人都是产品经理
人人都是产品经理
The Hacker News
The Hacker News
T
The Exploit Database - CXSecurity.com
C
CXSECURITY Database RSS Feed - CXSecurity.com
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
酷 壳 – CoolShell
酷 壳 – CoolShell
Scott Helme
Scott Helme
B
Blog
腾讯CDC
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
S
Schneier on Security
N
News and Events Feed by Topic
Microsoft Security Blog
Microsoft Security Blog
K
Kaspersky official blog
G
Google Developers Blog
T
Tor Project blog
PCI Perspectives
PCI Perspectives
S
Secure Thoughts
Google Online Security Blog
Google Online Security Blog
Latest news
Latest news
Google DeepMind News
Google DeepMind News
MyScale Blog
MyScale Blog
罗磊的独立博客

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