基于c#的道格拉斯-普克 Douglas-Peuker算法

来源:互联网 发布:淘宝卖户外是正品吗 编辑:程序博客网 时间:2024/05/22 02:04
道格拉斯-普克抽稀算法,是将曲线近似表示为一系列点,并减少点的数量的一种算法
该算法实现抽稀的过程是:
1)对曲线的首末点虚连一条直线,求曲线上所有点与直线的距离,并找出最大距离值dmax,用dmax与事先给定的阈值D相比: 
2)若dmax<D,则将这条曲线上的中间点全部舍去;则该直线段作为曲线的近似,该段曲线处理完毕。 

  若dmax≥D,保留dmax对应的坐标点,并以该点为界,把曲线分为两部分,对这两部分重复使用该方法,即重复1),2)步,直到所有dmax均<D,即完成对曲线的抽稀。 

我的思路是利用递归的方法遍历所有的点进行道格拉斯抽稀。

验证数据如图。


其中,黑色的线为原始线状数据,其他颜色为进行抽稀元算时所做辅助线。

准备如下:

 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;">如果倒数第二个点是最大距离点,则以首点和倒数第三点作为参数进行道格拉斯抽稀</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);            }                   }
不同阈值的运行情况如图:


0 0
原创粉丝点击