背景:現有多個geojson文件,內容爲某時段汽車的行駛軌跡,以經緯度的座標保存,需要將其進行壓縮重新保存爲geojson
geojson格式:
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
"properties": {"prop0": "value0"}
}]
}
詳見官網:https://www.oschina.net/translate/geojson-spec?cmp
抽稀算法:道格拉斯-普克法(Douglas-Peucker algorithm)
#算法邏輯:
- 確定起終點
- 計算起終點之間所有點到起終點組成線段的距離
- 設定閾值,若最大距離小於閾值,則去除中間所有點,反之,以最大距離對應的點爲界,分別對左半部分和右半部分從第2步遞歸計算
python實現:
# -*- coding:utf-8 -*-
"""
道格拉斯算法的實現
"""
import math
import json
import numpy as np
import matplotlib.pyplot as plt
class Point:
"""點類"""
x = 0.0
y = 0.0
index = 0 # 點在線上的索引
tag = False # 是否保留該點,默認都不保留
def __init__(self, x, y, index):
self.x = x
self.y = y
self.index = index
self.tag = False
# 全局變量
Points = []
def Recursion(Start, End):
# 保留起終點
Start.tag = True
End.tag = True
# 判斷是否相鄰或重疊
if Start.index >= End.index - 1:
return
# 直線方程係數Ax+By+C=0
A = Start.y - End.y
B = End.x - Start.x
C = Start.x * End.y - End.x * Start.y
# 計算中間點到直線的距離並保存
distance = []
for i in range(Start.index + 1, End.index):
# 點到之間距離公式,保證分母不爲0
d = abs(A * Points[i].x + B * Points[i].y + C) / (math.sqrt(A**2 + B**2)+0.0000000001)
distance.append(d)
# 此處座標系爲wgs84地理座標系,0.0001大約爲10米
if max(distance) > 0.0001:
Recursion(Start,Points[distance.index(max(distance))+Start.index+1])
Recursion(Points[distance.index(max(distance))+Start.index+1],End)
if __name__ == '__main__':
# 總共有100個geojson文件,循環讀取
for i in range(1,100):
# 爲每一個geojson文件初始化Point和result爲空
Points = []
result = []
with open(r'C:\Users\Administration\Desktop\geo%d.json' % i, 'r') as file:
content = json.load(file)
coords = content['features'][0]['geometry']['coordinates']
# 初始化自定義Point類
for j in range(len(coords)):
Points.append(Point(coords[j][0],coords[j][1],j))
# 壓縮
Recursion(Points[0],Points[-1])
# 獲取結果
for j in range(len(Points)):
if Points[j].tag:
result.append([Points[j].x, Points[j].y])
# 保存至新的geojson
with open(r'C:\Users\Administration\Desktop\New_geo%d.json%d.json' % i, 'w') as fw:
linestring = dict({"type": "LineString", "coordinates": result})
json.dump(linestring, fw)
# 查看進度
print(i)
# 結果圖形的繪製,抽稀之前
# fig = plt.figure()
# a1 = fig.add_subplot(121)
# dx = []
# dy = []
# for i in range(len(coords)):
# dx.append(coords[i][0])
# dy.append(coords[i][1])
# a1.plot(dx, dy, color='g', linestyle='-', marker='+')
# 抽稀之後
# dx1 = []
# dy1 = []
# a2 = fig.add_subplot(122)
# for p in result:
# dx1.append(p[0])
# dy1.append(p[1])
# a2.plot(dx1, dy1, color='r', linestyle='-', marker='+')
# plt.show()