【測繪程式設計試題集】 試題06 軌跡資料壓縮演算法

staHuri發表於2018-10-19

資料

P0,107.605,137.329
P1,122.274,169.126
P2,132.559,179.311
P3,153.324,184.276
P4,171.884,174.654
P5,186.408,168.634
P6,196.566,145.204
P7,200.549,127.877
P8,211.391,118.179
P9,216.318,116.547
P10,225.197,122.796
P11,231.064,135.459
P12,240.835,143.398
P13,254.630,144.933
P14,265.055,158.761
P15,271.004,159.660
P16,274.474,173.979

問題

問題6-1

問題6-2

import math

# 壓縮結果
Compressed = list()


class Point(object):
    def __init__(self, id, x, y):
        self.id = id
        self.x = x
        self.y = y


def read_m(path):
    m = []
    with open(path, 'r') as f:
        for i in f.readlines():
            aa = i.replace('\n', '').split(",")
            p = Point(aa[0], eval(aa[1]), eval(aa[2]))
            m.append(p)

    return m


def calc_height(point1, point2, point):
    """
    計算高
    :param point1: Point
    :param point2: Point
    :param point: Point
    :return:
    """
    area = abs(0.5 * (point1.x * point2.y + point2.x *
                      point.y + point.x * point1.y - point2.x * point1.y - point.x *
                      point2.y - point1.x * point.y))

    bottom = math.sqrt(
        math.pow(point1.x - point2.x, 2) + math.pow(point1.y - point2.y, 2)
    )

    height = area / bottom * 2
    return height


def DPmain(pointList, tolerance):
    """
    主要執行結果
    :param pointList: Point 列表
    :param tolerance: 容差
    :return:
    """
    if pointList == None or pointList.__len__() < 3:
        return pointList

    firspoint = 0
    lastPoint = len(pointList) - 1

    Compressed.append(pointList[firspoint])
    Compressed.append(pointList[lastPoint])

    while (pointList[firspoint] == pointList[lastPoint]):
        lastPoint -= 1
    DouglasPeucker(pointList, firspoint, lastPoint, tolerance)



def DouglasPeucker(pointList, firsPoint, lastPoint, tolerance):
    """
    計算通過的內容
    DP演算法
    :param pointList: 點列表
    :param firsPoint: 第一個點
    :param lastPoint: 最後一個點
    :param tolerance: 容差
    :return:
    """
    maxDistance = 0.0
    indexFarthest = 0
    for i in range(firsPoint, lastPoint):
        distance = calc_height(pointList[firsPoint], pointList[lastPoint], pointList[i])
        if (distance > maxDistance):
            maxDistance = distance
            indexFarthest = i

    if maxDistance > tolerance and indexFarthest != 0:
        Compressed.append(pointList[indexFarthest])
        DouglasPeucker(pointList, firsPoint, indexFarthest, tolerance)
        DouglasPeucker(pointList, indexFarthest, lastPoint, tolerance)


if __name__ == '__main__':
    a = read_m("軌跡.txt")
    print(a.__len__())
    # for item in a:
    #     print(item.id, item.x, item.y)
    DPmain(a, 8)
    for i in Compressed:
        print("{},{},{}".format(i.id, i.x, i.y))

結果

P0,107.605,137.329
P16,274.474,173.979
P9,216.318,116.547
P3,153.324,184.276
P1,122.274,169.126
P5,186.408,168.634
P7,200.549,127.877

原始圖
在這裡插入圖片描述
壓縮圖
在這裡插入圖片描述

相關文章