Ramer-Douglas-Peucker Algorithm

1. 参考文献

https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm


2. 算法实现

#include 
#include 
#include 

// 参考资料:
// https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
// 功能: 实现Ramer-Douglas-Peucker Algorithm
// Author: HSW
// Date: 2018-01-26
// 修改记录;
//
using namespace std;

typedef struct stPoint
{
    double x;
    double y;
    int    isSaved; // 是否为曲线拟合的保留点

    stPoint()
    {
        x = 0;
        y = 0;
        isSaved = 0;
    }
}stPoint;

double perpendicularDistance(stPoint curPoint, double A, double B, double C)
{
    double distance = (A * curPoint.x + B * curPoint.y + C) / sqrt(A * A + B * B);
    return distance < 0 ? -distance : distance;
}

// DouglasPeucker 算法
int DouglasPeucker(vector& Points, int Start, int End, double epsilon)
{
    double dMax = 0;
    int index = 0;
    int iter;

    // 直线方程: Ax + By + C = 0
    double A, B, C;
    if(Points[Start].x == Points[End].x)
    {// 垂直x轴的直线
        A = 1;
        B = 0;
        C = -Points[Start].x;
    }
    else
    {// 常规直线
        A = Points[End].y - Points[Start].y;     // y1 - y0
        B = -(Points[End].x - Points[Start].x);  // -(x1 - x0)
        C = Points[Start].y * (-B)  - Points[Start].x * A;
    }
    for(iter = Start + 1; iter <  End; ++iter)
    {
        // 点到直线的垂直距离
        double distance = perpendicularDistance(Points[iter], A, B, C);
        if(distance > dMax)
        {
            dMax = distance;
            index = iter;
        }
    }

    if(dMax > epsilon)
    {
        cout << "dMax Distance Index = " << index << endl;
        DouglasPeucker(Points, Start, index, epsilon);
        DouglasPeucker(Points, index, End, epsilon);
    }
    else
    {
        (Points[Start]).isSaved = 1;
        (Points[End]).isSaved = 1;
    }
    return 0;
}

int main()
{
    vector Points;
    stPoint tmpPoint;
    tmpPoint.x = 1;
    tmpPoint.y = 1;
    Points.push_back(tmpPoint);
    tmpPoint.x = 2;
    tmpPoint.y = 2;
    Points.push_back(tmpPoint);
    tmpPoint.x = 2.5;
    tmpPoint.y = 2.8;
    Points.push_back(tmpPoint);
    tmpPoint.x = 2;
    tmpPoint.y = 1.8;
    Points.push_back(tmpPoint);
    tmpPoint.x = 2.1;
    tmpPoint.y = 2.2;
    Points.push_back(tmpPoint);
    tmpPoint.x = 2.7;
    tmpPoint.y = 2.9;
    Points.push_back(tmpPoint);
    tmpPoint.x = 3;
    tmpPoint.y = 3;
    DouglasPeucker(Points, 0, Points.size() - 1, 0.5);
    int iter;
    for(iter = 0; iter < Points.size(); ++iter)
    {
        cout << "Points[" << iter << "] = " << Points[iter].isSaved << endl;
    }
    return 0;
}

你可能感兴趣的:(算法实现,c++,RDP算法)