日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

170316.道格拉斯-普克算法

發(fā)布時(shí)間:2024/1/17 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 170316.道格拉斯-普克算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

道格拉斯-普克算法

道格拉斯-普克算法 (Douglas–Peucker algorithm,亦稱為拉默-道格拉斯-普克算法、迭代適應(yīng)點(diǎn)算法、分裂與合并算法)是烏爾斯·拉默(Urs Ramer)于1972年以及大衛(wèi)·道格拉斯(David Douglas)和托馬斯·普克(Thomas Peucker)于1973年提出的一種簡化線的一種經(jīng)典算法。

它是通過減少曲線中點(diǎn)的數(shù)量,得出一條盡可能完整的表達(dá)原有曲線的特征的曲線。

一般來講,道格拉斯-普克算法需要一個(gè)極差D,極差D的值越大,證明曲線簡化的越多,反之極差越小,表示簡化的越小

通俗的理解,道格拉斯-普克算法是通過分治策略處理一組曲線,而極差D則可以理解為一個(gè)比較值,或者可以說是一個(gè)臨界點(diǎn),通過對(duì)垂距大于此臨界點(diǎn)的點(diǎn)進(jìn)行保留,對(duì)小于此臨界點(diǎn)的點(diǎn)進(jìn)行刪除,達(dá)到簡化曲線的效果

算法的基本思路是:

對(duì)曲線的首末點(diǎn)虛連一條直線,求此曲線其余所有點(diǎn)到直線的距離(垂距),從中找出最大距離值dmax?,用dmax與限差D相比:若dmax <D,這條曲線上的中間點(diǎn)全部舍去;若dmax ≥D,保留dmax 對(duì)應(yīng)的坐標(biāo)點(diǎn),并以該點(diǎn)為界,把曲線分為兩部分,對(duì)這兩部分重復(fù)使用該方法,當(dāng)曲線無法分為兩部分時(shí)結(jié)束。

具體步驟如下:

(1) 在曲線首尾兩點(diǎn)間虛連一條直線,求出其余各點(diǎn)到該直線的距離。

(2)選其最大者與極差D相比較,若大于極差D,則離該直線距離最大的點(diǎn)保留,否則將直線兩端點(diǎn)間各點(diǎn)全部舍去。

(3)以保留的點(diǎn)為中心,將已知曲線分成兩部分處理,重復(fù)執(zhí)行第1、2步操作,迭代操作,即仍選該直線距離最大者與極差D比較,依次取舍,直到無點(diǎn)可舍去,最后得到滿足給定精度限差為D的曲線點(diǎn)坐標(biāo)

具體的實(shí)現(xiàn)過程如下圖(此圖來自于網(wǎng)絡(luò))

在計(jì)算最大距離的時(shí)候(垂距),一般來講,我們知道三個(gè)點(diǎn)的坐標(biāo),兩個(gè)坐標(biāo)點(diǎn)形成得直線,求另一個(gè)坐標(biāo)點(diǎn)到此直線的距離。

一般來講,行列式算法,海倫公式,向量法,都可以求出面積;

這里介紹下行列式算法:

已知三個(gè)點(diǎn)坐標(biāo)(x1,y1),(x2,y2),(x3,y3)

由此三角形構(gòu)成的面積是|S|注意是S的絕對(duì)值,因?yàn)樽鴺?biāo)的方向不確定。

下面是S的求值

?

求出面積后,用面積公式,得到高(垂距),找出所有點(diǎn)中垂距的最大值與極差D比較。

下面簡要寫出道格拉斯-普克算法的代碼,由于是采用傳統(tǒng)的迭代方法,存在一定的弊端

qt代碼如下:

#include <QPoint> #include <QVector> /** * @brief CPointRarefyOprt::PerpendicularDistance 計(jì)算點(diǎn)到首尾連線間的距離(垂距) * @param Point1 首坐標(biāo) * @param Point2 尾坐標(biāo) * @param Point 要計(jì)算到直線距離的點(diǎn) * @return */ double PerpendicularDistance(const QPoint &Point1, const QPoint &Point2, const QPoint &Point) { //行列式算法的展開 double area = fabsf(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 = sqrtf(pow(Point1.x - Point2.x, 2) + pow(Point1.y - Point2.y, 2)); double height = area / bottom * 2; return height; } /** * @brief DouglasPeuckerReduction 道格拉斯——普克算法 * @param Points 要進(jìn)行簡化的曲線的點(diǎn)列 * @param startPoint 進(jìn)行此算法的曲線開始的點(diǎn)的數(shù)組下標(biāo) * @param endPoint 進(jìn)行此算法的曲線結(jié)束的點(diǎn)的數(shù)組下標(biāo) * @param tolerance 極差D(閾值) * @param resultPoints 得到的簡化的曲線 */ void DouglasPeuckerReduction(QVector<QPoint> Points,int startPoint ,int endPoint, double tolerance,QVector<QPoint> resultPoints) { double maxDistance = 0; //最遠(yuǎn)距離(垂距) int indexFarthest = -1; //最遠(yuǎn)距離點(diǎn)的數(shù)組下標(biāo) if(endPoint-startPoint<=1) { if(endPoint==startPoint) { //endPoint==startPoint相等時(shí),只有一個(gè)點(diǎn)時(shí),所以添加一個(gè)點(diǎn) resultPoints.append(points[startPoint]); } else { //有兩個(gè)點(diǎn)時(shí),添加兩個(gè)點(diǎn) resultPoints.append(points[startPoint]); resultPoints.append(points[endPoint]); } //當(dāng)小于等于兩個(gè)點(diǎn)時(shí),直接返回 return; } for (int index = startPoint; index < endPoint; index++) { double distance = PerpendicularDistance(points[startPoint],points[endPoint],points[index]); if (distance > maxDistance) { //當(dāng)新得到的點(diǎn)的垂距大于之前的最大垂距時(shí),更新最大垂距,并且更新最大垂距點(diǎn)的下標(biāo) maxDistance = distance; indexFarthest = index; } } if (maxDistance > tolerance && indexFarthest != -1) { //對(duì)起始點(diǎn)到最大垂距點(diǎn)之間的點(diǎn)重復(fù)進(jìn)行道格拉斯——普克算法 DouglasPeuckerReduction(points, startPoint,indexFarthest-1, tolerance, resultPoints); //將最大垂距點(diǎn)保留 resultPoints.append(points[indexFarthest]); //對(duì)最大垂距點(diǎn)到結(jié)束點(diǎn)之間的點(diǎn)重復(fù)進(jìn)行道格拉斯——普克算法 DouglasPeuckerReduction(points, indexFarthest+1,endPoint, tolerance, resultPoints); } return; }

//第一次寫博客,以前一直想寫,但總不知道寫些什么,或者感覺想寫的東西太過于簡單,或者感覺想寫的東西自己無法合理的表示
//寫這個(gè)東西用了兩個(gè)多小時(shí),借鑒了一些文檔,但其中還是不免有許多錯(cuò)誤,求指點(diǎn),感激不盡
//或許很簡單,或許很多錯(cuò)誤,但是當(dāng)我鼓足勇氣寫完之后,忽然發(fā)現(xiàn),原來堅(jiān)持寫比什么都重要

轉(zhuǎn)載于:https://www.cnblogs.com/wpch1993/p/6558086.html

總結(jié)

以上是生活随笔為你收集整理的170316.道格拉斯-普克算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。