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

道格拉斯-普克抽稀算法,是将曲线近似表示为一系列点,并减少点的数量的一种算法
该算法实现抽稀的过程是:
1)对曲线的首末点虚连一条直线,求曲线上所有点与直线的距离,并找出最大距离值dmax,用dmax与事先给定的阈值D相比: 
2)若dmax

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

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

验证数据如图。

基于c#的道格拉斯-普克 Douglas-Peuker算法_第1张图片

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

准备如下:

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

基于c#的道格拉斯-普克 Douglas-Peuker算法_第2张图片

基于c#的道格拉斯-普克 Douglas-Peuker算法_第3张图片基于c#的道格拉斯-普克 Douglas-Peuker算法_第4张图片

你可能感兴趣的:(c#,计算机图形学)