python Douglas–Peucker algorithm压缩GPS轨迹

原文为JS版本,见JS版本

这里将其转成python版本,如下:

from geog import distance
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np

class Douglas_Peuker:
    "Douglas–Peucker algorithm压缩轨迹"

    def __init__(self, traj, dMax=5):
        
        print('原始轨迹长度:', len(traj))
        plt.figure()  # 画图
        plt.subplot(1, 2, 1)  # 画图
        plt.plot(np.array(traj)[:,0], np.array(traj)[:,1], 'r-')
        plt.title('init_traj')
        traj = [[i, x[0], x[1]] for i, x in enumerate(traj)]
        douglasPecker_traj = self.douglasPecker(traj, dMax)
        print('压缩后轨迹长度:', len(douglasPecker_traj))
        plt.subplot(1, 2, 2)  # 画图
        plt.plot(np.array(douglasPecker_traj)[:, 0], np.array(douglasPecker_traj)[:, 1], 'b-')
        plt.title('douglasPecker_traj')
        plt.show()
        plt.close()

    def douglasPecker(self, coordinate, dMax):
        """

        :param coordinate: 原始轨迹
        :param dMax: 允许最大距离误差
        :return: douglasResult 抽稀后的轨迹
        """
        result = self.compressLine(coordinate, [], 0, len(coordinate)-1, dMax)
        result.append(coordinate[0])
        result.append(coordinate[-1])
        result = pd.DataFrame(result, columns=['myIndex', 'lat', 'lng'])
        result.sort_values(by=['myIndex'], inplace=True)
        result.reset_index(drop=True, inplace=True)
        return result.loc[:, ['lat', 'lng']].values.tolist()

    def compressLine(self, coordinate, result, start, end, dMax):
        "递归方式压缩轨迹"
        if start<end:
            maxDist = 0
            currentIndex = 0
            startPoint = coordinate[start][1:]
            endPoint = coordinate[end][1:]
            for i in range(start+1, end):
                currentDist = self.disToSegment(startPoint, endPoint, coordinate[i][1:])
                if currentDist>maxDist:
                    maxDist = currentDist
                    currentIndex = i
            if maxDist>=dMax:
                # 将当前点加入到过滤数组中
                result.append(coordinate[currentIndex])
                # 将原来的线段以当前点为中心拆成两段,分别进行递归处理
                self.compressLine(coordinate, result, start, currentIndex, dMax)
                self.compressLine(coordinate, result, currentIndex, end, dMax)
        return result

    def disToSegment(self, start, end, center):
        "计算垂距,用海伦公式计算面积"
        a = distance(start, end)
        b = distance(start, center)
        c = distance(end, center)
        p = (a+b+c) / 2
        s = np.sqrt(abs(p*(p-a)*(p-b)*(p-c)))
        return s*2/a

if __name__=='__main__':
    "traj是一个二维数组格式的经纬度列表,lng在前,lat在后"
    Douglas_Peuker(traj, dMax=5)

结果:

原始轨迹长度: 167
压缩后轨迹长度: 129

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值