背景需要:
须要实现飞机仿真实时挪动地位,然而提供的数据量较为宏大,而咱们的数据都是通过 kafka 发送,再由 ue4 承接数据来做渲染。然而数据量较为宏大,在增大飞行速度的同时渲染比拟吃力,于是想到点位个数压缩,数据推送频率不变来实现。
构思原理:利用普克拉斯算法,通过该点位压缩算法来压缩点的个数
这里提供的数据是 excel,我打算把他解决成 geosjon 格局数据,而后用 leaflet 加载,判断是否和原数据是否重合。
'''
Author: nico
Date: 2023-06-07 10:21:42
LastEditTime: 2023-06-07 10:21:46
Description:
'''
import math
import pandas as pd
def douglas_peucker(coords, epsilon):
# 找到间隔端点最远的点
dmax = 0
index = 0
for i in range(1, len(coords)-1):
d = distance(coords[i], coords[0], coords[-1])
if d > dmax:
index = i
dmax = d
# 如果最大间隔大于阈值,则递归地对两个子段进行解决
if dmax > epsilon:
results1 = douglas_peucker(coords[:index+1], epsilon)
results2 = douglas_peucker(coords[index:], epsilon)
# 将后果合并
return results1[:-1] + results2
else:
# 如果最大间隔小于阈值,则保留该段的终点和起点
return [coords[0], coords[-1]]
def distance(p, p1, p2):
# 计算点到线段的间隔
x0, y0 = p
x1, y1 = p1
x2, y2 = p2
dx = x2 - x1
dy = y2 - y1
if dx == 0 and dy == 0:
return math.sqrt((x0 - x1)**2 + (y0 - y1)**2)
else:
t = ((x0 - x1) * dx + (y0 - y1) * dy) / (dx*dx + dy*dy)
if t < 0:
px, py = x1, y1
elif t > 1:
px, py = x2, y2
else:
px, py = x1 + t*dx, y1 + t*dy
return math.sqrt((x0 - px)**2 + (y0 - py)**2)
# 示例用法
def getData():
# 读取 Excel 数据到 DataFrame
df = pd.read_excel('data.xlsx')
# 将经纬度转换为坐标点
coordinates = []
for index, row in df.iterrows():
coordinates.append([row['lat'], row['lon']])
return coordinates
coords = getData()
epsilon = 0.0000009
print(len(coords))
simplified_coords = douglas_peucker(coords, epsilon)
new_list = [[sublist[1], sublist[0]] for sublist in simplified_coords]
print(len(new_list),new_list)
simplified_geojson = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates":new_list
}
}
]
}
# 将 GeoJSON 写入文件
with open('chouxi10.json', 'w') as f:
f.write(str(simplified_geojson))
原作者地址:https://segmentfault.com/u/yourena_c
这里我用 leaflet 来测试造成的 geojson 是否和未解决的元数据合乎,所以经纬度对位也同时做了解决。
<!DOCTYPE html>
<html>
<head>
<title>Leaflet GeoJSON Example</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.bootcdn.net/ajax/libs/leaflet/1.9.3/leaflet.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/leaflet/1.9.3/leaflet.min.css" rel="stylesheet">
<script src="./chouxi1.js"></script>
<script src="./chouxi2.js"></script>
<script src="./chouxi4.js"></script>
<script src="./chouxi10.js"></script>
</head>
<body>
<div id="mapid" style="height: 500px;"></div>
<script>
var mymap = L.map('mapid').setView([39.519334,116.437151], 19);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: 'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors'
}).addTo(mymap);
var myStyle = {
"color": "#ff0000",
"weight": 15,
"opacity": 1
};
var myStyle2 = {
"color": "#00FF00",
"weight": 10,
"opacity": 1
};
var myStyle4 = {
"color": "#800000",
"weight": 5,
"opacity": 1
};
var myStyle10 = {
"color": "#00FF00",
"weight": 1,
"opacity": 1
};
console.log(geoData);
L.geoJSON(geoData, {style: myStyle}).addTo(mymap);
L.geoJSON(geoData2, {style: myStyle2}).addTo(mymap);
L.geoJSON(geoData4, {style: myStyle4}).addTo(mymap);
L.geoJSON(geoData10, {style: myStyle10}).addTo(mymap);
</script>
</body>
</html>
最初后果是抽稀 10 倍,局部特色隐没,然而根本吻合。