背景需要:
须要实现飞机仿真实时挪动地位,然而提供的数据量较为宏大,而咱们的数据都是通过kafka发送,再由ue4承接数据来做渲染。然而数据量较为宏大,在增大飞行速度的同时渲染比拟吃力,于是想到点位个数压缩,数据推送频率不变来实现。
构思原理:利用普克拉斯算法,通过该点位压缩算法来压缩点的个数
这里提供的数据是excel,我打算把他解决成geosjon格局数据,而后用leaflet加载,判断是否和原数据是否重合。
'''Author: nicoDate: 2023-06-07 10:21:42LastEditTime: 2023-06-07 10:21:46Description: '''import mathimport pandas as pddef 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 coordinatescoords = getData()epsilon = 0.0000009print(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倍,局部特色隐没,然而根本吻合。