道格拉斯-普克抽稀算法,是將曲線近似表示為一系列點,並減少點的數量的一種算法。
Douglas一Peukcer算法由D.Douglas和T.Peueker於1973年提出,簡稱D一P算法,是眼下公認的線狀要素化簡經典算法。現有的線化簡算法中,有相當一部分都是在該算法基礎上進行改進產生的。它的長處是具有平移和旋轉不變性,給定曲線與閡值后,抽樣結果一定。
算法的基本思路是:對每一條曲線的首末點虛連一條直線,求所有點與直線的距離,並找出最大距離值dmax ,用dmax與限差D相比:若dmax < D ,這條曲線上的中間點所有舍去;若dmax ≥D ,保留dmax 相應的坐標點,並以該點為界,把曲線分為兩部分,對這兩部分反復使用該方法。
算法的具體過程如下:
(1) 在曲線首尾兩點間虛連一條直線,求出其余各點到該直線的距離,如圖3(1)。
(2) 選其最大者與閾值相比較,若大於閾值,則離該直線距離最大的點保留,否則將直線兩端點間各點所有舍去,如圖3(2),第4點保留。
(3) 根據所保留的點,將已知曲線分成兩部分處理,反復第1、2步操作,迭代操作,即仍選距離最大者與閾值比較,依次取舍,直到無點可舍去,最后得到滿足給定精度限差的曲線點坐標,如圖3(3)、(4)依次保留第6點、第7點,舍去其它點,即完成線的化簡。
利用遞歸的方法遍歷所有的點進行道格拉斯抽稀。
驗證數據如圖。
其中,黑色的線為原始線狀數據,其他顏色為進行抽稀元算時所做輔助線。
ArrayList myar = new ArrayList();//存入原始數據 ArrayList newar = new ArrayList(); //存入抽稀后的數據 public class canshu//記錄直線參數的類 { public double k; public double b; } public class zuobiao//坐標數據類 { public double x; public double y; } public canshu xielv(zuobiao shou, zuobiao wei)//求斜率 { double k, b; canshu newcs = new canshu(); k = (wei.y - shou.y) / (wei.x - shou.x); b = shou.y - k * shou.x; newcs.k = k; newcs.b = b; return newcs; } public double distance(zuobiao dot,canshu cs)//求點到直線距離 { double dis =(Math.Abs (cs.k * dot.x - dot.y + cs.b)) / Math.Sqrt(cs.k * cs.k + 1); return dis; }
道格拉斯算法如下:
public void Douglas(int number1, int number2) { int max=0;//定義擁有最大距離值的點的編號 canshu myc = new canshu(); myc= xielv((zuobiao)myar[number1], (zuobiao)myar[number2-1]); double maxx = distance((zuobiao)myar[number1+1], myc);//假設第二個點為最大距離點 double yuzhi = Convert.ToInt32(textBox1.Text);//設閾值 for (int i = number1 + 1; i < number2 - 1; i++)//從第二個點遍歷到最后一個點前方的點 { if (distance((zuobiao)myar[i], myc) > yuzhi && distance((zuobiao)myar[i], myc) >= maxx)//找出擁有最大距離的點 { max = i; maxx = distance((zuobiao)myar[i], myc); } } if(max==0)//若不存在最大距離點,則只將首尾點存入arraylist,結束這一次的道格拉斯抽稀 { newar.Add((zuobiao)myar[number2-1]); return; } else if (number1 + 1 == max&&number2-2!=max)//如果第二個點是最大距離點,則以下一個點和尾點作為參數進行道格拉斯抽稀釋 { Douglas(max+1, number2); } else if (number2 - 2 == max&&number1+1!=max)//<span style="font-family: Arial;">如果倒數第二個點是最大距離點,則以首點和倒數第三點作為參數進行道格拉斯抽稀 lt;/span> { Douglas(0, max+1); } else if (number1 + 1 == max && number2 - 2 == max)//如果首點尾點夾住最大距離點,則將最大距離點和尾點存入arraylist { newar.Add((zuobiao)myar[max]); newar.Add((zuobiao)myar[max+1]); return; } else { Douglas(number1, max+1); Douglas(max, number2); } }
不同閾值的運行情況如圖:

轉載:https://blog.csdn.net/u011609113/article/details/39234851