Douglas-Peucker压缩算法

Douglas-Peucker算法(道格拉斯-普克算法)是将曲线近似表示为一系列点,并减少点的数量的一种算法。它的优点是具有平移和旋转不变性,给定曲线与阈值后,抽样结果一定。Douglas—Peucker算法通常用于线状矢量数据压缩、轨迹数据压缩等。

算法步骤

  1. 连接曲线首尾两点A、B形成一条直线AB;
  2. 计算曲线上离该直线段距离最大的点C,计算其与AB的距离d;
  3. 比较该距离与预先给定的阈值threshold的大小,如果小于threshold,则以该直线作为曲线的近似,该段曲线处理完毕。
  4. 如果距离大于阈值,则用点C将曲线分为两段AC和BC,并分别对两段曲线进行步骤[1~3]的处理。
  5. 当所有曲线都处理完毕后,依次连接各个分割点形成折线,作为原曲线的近似。

实现代码

Java实现代码如下,代码引用自JTS库。

class DouglasPeuckerLineSimplifier {
    private Coordinate[] pts;
    private boolean[] usePt;
    private double distanceTolerance;
    private LineSegment seg = new LineSegment();

    public static Coordinate[] simplify(Coordinate[] pts, double distanceTolerance) {
        DouglasPeuckerLineSimplifier simp = new DouglasPeuckerLineSimplifier(pts);
        simp.setDistanceTolerance(distanceTolerance);
        return simp.simplify();
    }

    public DouglasPeuckerLineSimplifier(Coordinate[] pts) {
        this.pts = pts;
    }

    public void setDistanceTolerance(double distanceTolerance) {
        this.distanceTolerance = distanceTolerance;
    }

    public Coordinate[] simplify() {
        this.usePt = new boolean[this.pts.length];

        for(int i = 0; i < this.pts.length; ++i) {
            this.usePt[i] = true;
        }

        this.simplifySection(0, this.pts.length - 1);
        CoordinateList coordList = new CoordinateList();

        for(int i = 0; i < this.pts.length; ++i) {
            if(this.usePt[i]) {
                coordList.add(new Coordinate(this.pts[i]));
            }
        }

        return coordList.toCoordinateArray();
    }

    private void simplifySection(int i, int j) {
        if(i + 1 != j) {
            this.seg.p0 = this.pts[i];
            this.seg.p1 = this.pts[j];
            double maxDistance = -1.0D;
            int maxIndex = i;

            int k;
            for(k = i + 1; k < j; ++k) {
                double distance = this.seg.distance(this.pts[k]);
                if(distance > maxDistance) {
                    maxDistance = distance;
                    maxIndex = k;
                }
            }

            if(maxDistance <= this.distanceTolerance) {
                for(k = i + 1; k < j; ++k) {
                    this.usePt[k] = false;
                }
            } else {
                this.simplifySection(i, maxIndex);
                this.simplifySection(maxIndex, j);
            }

        }
    }
}

猜你喜欢

转载自blog.csdn.net/u011331383/article/details/78066632