python實現geojson軌跡數據抽稀——道格拉斯-普克算法

背景:現有多個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)

#算法邏輯:

  1. 確定起終點
  2. 計算起終點之間所有點到起終點組成線段的距離
  3. 設定閾值,若最大距離小於閾值,則去除中間所有點,反之,以最大距離對應的點爲界,分別對左半部分和右半部分從第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()

測試結果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章