道格拉斯-普克算法

道格拉斯-普克算法(Douglas–Peucker algorithm,亦稱為拉默-道格拉斯-普克算法、疊代適應點算法、分裂與合併算法)是將曲線近似表示為一系列點,並減少點的數量的一種算法。它的優點是具有平移和旋轉不變性,給定曲線與閾值後,抽樣結果一定。

基本介紹

  • 中文名:道格拉斯-普克算法
  • 外文名:Douglas–Peucker algorithm
  • 亦稱為:拉默-道格拉斯-普克算法
  • 提出:1973年
簡要說明,詳細步驟,實現代碼,

簡要說明

道格拉斯-普克算法(Douglas–Peucker algorithm,亦稱為拉默-道格拉斯-普克算法、疊代適應點算法、分裂與合併算法)是將曲線近似表示為一系列點,並減少點的數量的一種算法。該算法的原始類型分別由烏爾斯·拉默(Urs Ramer)於1972年以及大衛·道格拉斯(David Douglas)和托馬斯·普克(Thomas Peucker)於1973年提出,並在之後的數十年中由其他學者予以完善。
算法的基本思路是:對每一條曲線的首末點虛連一條直線,求所有點與直線的距離,並找出最大距離值dmax ,用dmax與限差D相比:若dmax <D,這條曲線上的中間點全部捨去;若dmax ≥D,保留dmax 對應的坐標點,並以該點為界,把曲線分為兩部分,對這兩部分重複使用該方法。

詳細步驟

道格拉斯-普克算法
(1) 在曲線首尾兩點間虛連一條直線,求出其餘各點到該直線的距離,如右圖(1)。
(2)選其最大者與閾值相比較,若大於閾值,則離該直線距離最大的點保留,否則將直線兩端點間各點全部捨去,如右圖(2),第4點保留。
(3)依據所保留的點,將已知曲線分成兩部分處理,重複第1、2步操作,疊代操作,即仍選距離最大者與閾值比較,依次取捨,直到無點可捨去,最後得到滿足給定精度限差的曲線點坐標,如圖(3)、(4)依次保留第6點、第7點,捨去其他點,即完成線的化簡。

實現代碼

packagecom.mapbar.jts;/***ClassPoint.java*/publicclassPoint{    /***點的X坐標*/    privatedoublex = 0;        /***點的Y坐標*/    privatedoubley = 0;    /***點所屬的曲線的索引*/    privateintindex = 0;    publicdoublegetX() {        returnx;    }    publicvoidsetX(doublex) {        this.x = x;    }    publicdoublegetY() {        returny;    }    publicvoidsetY(doubley) {        this.y = y;    }    publicintgetIndex() {        returnindex;    }    publicvoidsetIndex(intindex) {        this.index = index;    }    /***點數據的構造方法*    *@param x *點的X坐標    *@param y *點的Y坐標    *@param index點所屬的曲線的索引    */    publicPoint(doublex, doubley, intindex){        this.x = x;        this.y = y;        this.index = index;    }}packagecom.mapbar.jts;importjava.util.ArrayList;importjava.util.List;importcom.vividsolutions.jts.geom.Coordinate;importcom.vividsolutions.jts.geom.Geometry;importcom.vividsolutions.jts.io.ParseException;importcom.vividsolutions.jts.io.WKTReader;/***ClassDouglas.java*/publicclassDouglas{    /***存儲採樣點數據的鍊表*/    publicList < Point > points = newArrayList < Point > ();    /***控制數據壓縮精度的極差*/    privatestaticfinaldoubleD = 1;    privateWKTReaderreader;    /***構造Geometry**@paramstr*@return*/    publicGeometrybuildGeo(Stringstr)    {        try        {            if (reader == null) {                reader = newWKTReader();            }            returnreader.read(str);        }        catch(ParseExceptione) {            thrownewRuntimeException("buildGeometryError", e);        }    }    /***讀取採樣點*/    publicvoidreadPoint()    {        Geometryg = buildGeo("LINESTRING(14,23,42,66,77,86,95,1010)");        Coordinate[] coords = g.getCoordinates();        for (inti = 0; i < coords.length; i++)        {            Pointp = newPoint(coords[i].x, coords[i].y, i);            points.add(p);        }    }    /***對矢量曲線進行壓縮**@paramfrom*曲線的起始點*@paramto*曲線的終止點*/    publicvoidcompress(Pointfrom, Pointto)    {        /***壓縮算法的開關量*/        booleanswitchvalue = false;        /***由起始點和終止點構成的直線方程一般式的係數*/        System.out.println(from.getY());        System.out.println(to.getY());        doubleA = (from.getY() - to.getY()) / Math.sqrt(Math.pow((from.getY() - to.getY()), 2) + Math.pow((from.getX() - to.getX()), 2));        /***由起始點和終止點構成的直線方程一般式的係數*/        doubleB = (to.getX() - from.getX()) / Math.sqrt(Math.pow((from.getY() - to.getY()), 2) + Math.pow((from.getX() - to.getX()), 2));        /***由起始點和終止點構成的直線方程一般式的係數*/        doubleC = (from.getX() * to.getY() - to.getX() * from.getY()) / Math.sqrt(Math.pow((from.getY() - to.getY()), 2) + Math.pow((from.getX() - to.getX()), 2));        doubled = 0;        doubledmax = 0;        intm = points.indexOf(from);        intn = points.indexOf(to);        if (n == m + 1) return;        Pointmiddle = null;        List < Double > distance = newArrayList < Double > ();        for (inti = m + 1; i < n; ++)        {            d = Math.abs(A * (points.get(i).getX()) + B * (points.get(i).getY()) + C) / Math.sqrt(Math.pow(A, 2) + Math.pow(B, 2));            distance.add(d);        }        dmax = distance.get(0);        for (intj = 1; j < distance.size(); j++)        {            if (distance.get(j) > dmax) dmax = distance.get(j);        }        if (dmax > D) switchvalue = true;        else switchvalue = false;        if (!switchvalue)        {            //刪除Points(m,n)內的坐標            for (inti = m + 1; i < n; i++)            points.get(i).setIndex( - 1);        }        else        {            for (inti = m + 1; i < n; i++)            {                if ((Math.abs(A * (points.get(i).getX()) + B * (points.get(i).getY()) + C) / Math.sqrt(Math.pow(A, 2) + Math.pow(B, 2)) == dmax))                middle = points.get(i);            }            compress(from, middle);            compress(middle, to);        }    }    publicstaticvoidmain(String[] args)    {        Douglasd = newDouglas();        d.readPoint();        d.compress(d.points.get(0), d.points.get(d.points.size() - 1));        for (inti = 0; i < d.points.size(); i++)        {            Pointp = d.points.get(i);            if (p.getIndex() > -1) {                System.out.print(p.getX() + "" + p.getY() + ",");            }        }    }}

相關詞條

熱門詞條

聯絡我們