道格拉斯-普克抽稀算法

道格拉斯-普克抽稀算法

目的

用來(lái)對(duì)大量冗余的圖形數(shù)據(jù)點(diǎn)進(jìn)行壓縮以提取必要的數(shù)據(jù)點(diǎn)。

過(guò)程

先將一條曲線首尾點(diǎn)虛連一條直線,求其余各點(diǎn)到該直線的距離,取其最大者與規(guī)定的臨界值相比較,若小于臨界值,則將直線兩端間各點(diǎn)全部舍去,否則將離該直線距離最大的點(diǎn)保留,并將原線條分成兩部分,對(duì)每部分線條再實(shí)施該抽稀過(guò)程,直到結(jié)束。

抽稀結(jié)果點(diǎn)數(shù)隨選取限差臨界值的增大而減少,應(yīng)用時(shí)應(yīng)根據(jù)精度來(lái)選取限差臨界值,以獲得最好的效果。

一個(gè)十分突出的優(yōu)點(diǎn)

一個(gè)十分突出的優(yōu)點(diǎn),即它是一個(gè)整體算法,通過(guò)準(zhǔn)確刪除小彎曲上的定點(diǎn),能夠在整體上有效地保持線要素的形態(tài)特征。

正是因?yàn)榈栏窭?普克法具有這樣突出的優(yōu)點(diǎn),所以已經(jīng)在線要素地自動(dòng)制圖中得到了較廣泛的應(yīng)用。

C++代碼實(shí)現(xiàn)

/*
 *  計(jì)算點(diǎn)到直線的距離
 */
double PerpendicularDistance(CPoint Point1, CPoint Point2, CPoint Point)
{
    //Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)|   *Area of triangle
    //Base = v((x1-x2)2+(x1-x2)2)                               *Base of Triangle*
    //Area = .5*Base*H                                          *Solve for height
    //Height = Area/.5/Base

    double 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));
    double bottom = sqrt(pow(Point1.x - Point2.x, 2) + pow(Point1.y - Point2.y, 2));
    double height = area / bottom * 2;

    return height;

}

/*
 *  將要保留的點(diǎn)添加到pointIndexsToKeep中
 */
void DouglasPeuckerReduction(vector<CPoint>points, int firstPoint, int lastPoint, double tolerance, list<int> &pointIndexsToKeep)
{
    double maxDistance = 0;
    int indexFarthest = 0;
    
    for (int index = firstPoint; index < lastPoint; index++)
    {
        double distance = PerpendicularDistance
            (points[firstPoint], points[lastPoint], points[index]);
        if (distance > maxDistance)
        {
            maxDistance = distance;
            indexFarthest = index;
        }
    }

    if (maxDistance > tolerance && indexFarthest != 0)
    {
        //Add the largest point that exceeds the tolerance
        pointIndexsToKeep.push_back(indexFarthest);
    
        DouglasPeuckerReduction(points, firstPoint, 
        indexFarthest, tolerance, pointIndexsToKeep);
        
        DouglasPeuckerReduction(points, indexFarthest, 
        lastPoint, tolerance, pointIndexsToKeep);
    }
}

/*
 *  對(duì)一組點(diǎn)進(jìn)行抽稀
 */
vector<CPoint> DouglasPeucker(vector<CPoint> &Points, double Tolerance)
{
    if (Points.empty() || (Points.size() < 3))
    return Points;

    int firstPoint = 0;
    int lastPoint = Points.size() - 1;
    list<int> pointIndexsToKeep ;

    //Add the first and last index to the keepers
    pointIndexsToKeep.push_back(firstPoint);
    pointIndexsToKeep.push_back(lastPoint);

    //The first and the last point cannot be the same
    while (Points[firstPoint]==(Points[lastPoint]))
    {
        lastPoint--;
    }

    DouglasPeuckerReduction(Points, firstPoint, lastPoint, 
    Tolerance, pointIndexsToKeep);

    vector<CPoint> returnPoints ;
    pointIndexsToKeep.sort();
    list<int>::iterator theIterator;
    for( theIterator = pointIndexsToKeep.begin(); theIterator != pointIndexsToKeep.end(); theIterator++ )
    {
        returnPoints.push_back(Points[*theIterator]);
    }

    return returnPoints;
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1、抽稀 通俗點(diǎn)講,直接舉個(gè)栗子吧:我們知道運(yùn)動(dòng)軌跡實(shí)際上是由很多個(gè)經(jīng)緯度坐標(biāo)連接而成。那么我們是否需要將所有運(yùn)動(dòng)...
    _菜鳥猿閱讀 12,091評(píng)論 4 14
  • 世界好小,時(shí)間好巧 聽(tīng)舍友說(shuō)有人會(huì)很搞笑 我覺(jué)得那可能是打嗨了王者榮耀 畢竟人群之中戰(zhàn)友難找 不對(duì)吧 應(yīng)該是門前駐...
    一如笑歸去閱讀 268評(píng)論 0 1
  • 喝下你藏好的毒 還有人喝 也不一定都是毒藥 看誰(shuí)給吧 看給誰(shuí)吧 沒(méi)毛病 這很重要 周瑜打黃蓋的話就沒(méi)辦法了 一個(gè)愿...
    Pancras閱讀 220評(píng)論 0 0
  • don't try to do the impossible
    小綠植物閱讀 138評(píng)論 0 0
  • 函數(shù)的聲明 函數(shù)的形式為: 如Kotlin的主函數(shù) 其中返回值類型Unit代碼無(wú)返回值,可以省略不寫,所以主函數(shù)可...
    chaychan閱讀 475評(píng)論 0 0