Douglas一Peukcer算法由D.Douglas和T.Peueker于1973年提出,簡(jiǎn)稱D一P算法,是目前公認(rèn)的線狀要素化簡(jiǎn)經(jīng)典算法?,F(xiàn)有的線化簡(jiǎn)算法中,有相當(dāng)一部分都是在該算法基礎(chǔ)上進(jìn)行改進(jìn)產(chǎn)生的。它的優(yōu)點(diǎn)是具有平移和旋轉(zhuǎn)不變性,給定曲線與閡值后,抽樣結(jié)果一定。本章線化簡(jiǎn)重點(diǎn)講解該算法。 算法的基本思路是:對(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ù)使用該方法。 算法的詳細(xì)步驟如下: (1) 在曲線首尾兩點(diǎn)間虛連一條直線,求出其余各點(diǎn)到該直線的距離,如圖3(1)。 (2) 選其最大者與閾值相比較,若大于閾值,則離該直線距離最大的點(diǎn)保留,否則將直線兩端點(diǎn)間各點(diǎn)全部舍去,如圖3(2),第4點(diǎn)保留。 (3) 依據(jù)所保留的點(diǎn),將已知曲線分成兩部分處理,重復(fù)第1、2步操作,迭代操作,即仍選距離最大者與閾值比較,依次取舍,直到無點(diǎn)可舍去,最后得到滿足給定精度限差的曲線點(diǎn)坐標(biāo),如圖3(3)、(4)依次保留第6點(diǎn)、第7點(diǎn),舍去其他點(diǎn),即完成線的化簡(jiǎn)。 既然今天有時(shí)間,就多寫幾篇博文算了,也為了明天出去玩好好放松一下。 GIS領(lǐng)域的同志都知道,傳統(tǒng)的道格拉斯-普克算法都是遞歸實(shí)現(xiàn)。然而有時(shí)候遞歸的層次太深的話會(huì)出現(xiàn)棧溢出的情況。在此,介紹一種非遞歸的算法。 要將遞歸算法改為非遞歸算法,一般情況下分為兩種場(chǎng)景。第一種是問題定義是遞歸的,如階乘、斐波那契數(shù)列等,對(duì)于這類問題,改為遞歸算法很簡(jiǎn)單,直接用迭代來做。另外一種是過程是遞歸的,如本文的道格拉斯-普克算法,對(duì)于這類問題呢,一般是用棧(stack)來記錄中間結(jié)果,最后得到結(jié)果。 為了保證極值點(diǎn)的不被舍去,將曲線在彎曲極值點(diǎn)分為兩段處理,彎曲極值點(diǎn)通過中間點(diǎn)與相鄰兩個(gè)頂點(diǎn)的角度度量。然而傳統(tǒng)的Douglas-Peucker算法一般在計(jì)算過程中沒有考慮到記錄中間最大的距離的節(jié)點(diǎn),造成循環(huán)時(shí)間長(zhǎng)、遞歸嵌套層次太深,從而影響了程序的運(yùn)行效率。本文提出一種結(jié)合棧數(shù)據(jù)結(jié)構(gòu)的分段Douglas-Peucker算法,它從曲線的一端出發(fā),首先將第一個(gè)點(diǎn)和最后一個(gè)點(diǎn)作為改進(jìn)的Douglas-Peucker算法的工作區(qū)間,然后判斷最遠(yuǎn)點(diǎn)的距離是否大于閾值,這樣完成線要素的綜合化簡(jiǎn)。改進(jìn)D-P算法的具體步驟如下: (1)尋找曲線曲率最大的點(diǎn),將曲線以此點(diǎn)為界一分為二分成兩部分,對(duì)于每一部分都有點(diǎn)列 。然后分別處理這兩段曲線。 (2)對(duì)于第一段曲線,有矢量的離散點(diǎn)序列 ,設(shè) 并且 ,連接 組成一條線段。生成一個(gè)棧 ,將 點(diǎn)入棧 。 (3)在 之間的點(diǎn)中尋找與 線段距離最大的點(diǎn),記為 。 (4)判斷 點(diǎn)到 的距離是否小于閾值,若否,則設(shè) ,并將 加入到特征點(diǎn)序列,將 壓入棧 ,用線段連接 ,回到(3)。若是,執(zhí)行第(5)步。 (5)判斷 是否等于 的棧頂元素,若否,則設(shè) 、 , 表示棧頂,用線段連接 ,回到(3)。若是,執(zhí)行(6)。 (6)判斷 是否等于 ,若否,則設(shè) 、 ( 表示 的棧頂?shù)南乱稽c(diǎn)),用線段連接 ,棧頂元素出棧,回到(3)。 (7)當(dāng)棧為空時(shí),第一段曲線計(jì)算結(jié)束。處理第二段曲線,重復(fù)(1)~(7)。 改進(jìn)算法的程序流程圖如下圖所示。 圖 改進(jìn)Douglas-Peucker流程圖
本文提出的改進(jìn)算法雖然在編程上面比較復(fù)雜,但是能夠減少中間重復(fù)循環(huán)的次數(shù)。有了上面的流程圖之后,那么代碼就相對(duì)簡(jiǎn)單了。
[cpp]
view plain
copy
代碼不是完整的,其中有調(diào)用到了另外一個(gè)函數(shù),就是找曲線中離曲線兩端點(diǎn)的直線的距離的最大值點(diǎn),這個(gè)過程很簡(jiǎn)單,就不講了,還有自己定義的一些數(shù)據(jù)結(jié)構(gòu),本文只是講解這一種算法的思想,其中算法描述部分由公式,原文是在word中編輯的,如果看不懂就直接看流程圖還清晰點(diǎn)。 |
|