C#道格拉斯线压缩算法(经纬度坐标抽稀)

Douglas—Peucker算法
是将曲线近似表示为一系列点,并减少点的数量的一种算法。它的优点是具有平移和旋转不变性,给定曲线与阈值后,抽样结果一定。

算法思路:
对每一条曲线的首末点虚连一条直线,求所有点与直线的距离,并找出最大距离值dmax,用dmax与限差D相比:
若dmax<D,这条曲线上的中间点全部舍去;
若dmax≥D,保留dmax对应的坐标点,并以该点为界,把曲线分为两部分,对这两部分重复使用该方法。
传统的道格拉斯算法是采用递归的方法,算法的核心是求点到直线的距离。设置一个距离阈值,当点到线的距离小于该阈值,那么点视为可以删除的点。最后剩下的点即为最终结果

C#道格拉斯线压缩算法(经纬度坐标抽稀)_第1张图片
程序下载:地图投影与抽稀

1、算法输入:inPoint为待处理的点列数据, D为阈值

public class MyPoint
    {
     
        public double x;
        public double y;
    }

public void Do(List<MyPoint> inPoint, double D )
        {
     
       	    int n1 = 0;
            int n2 = inPoint.Count;
            Douglas(inPoint, n1, n2, D);
         }

2、调用Douglas算法,n1, n2分别为首尾点的位置标记

public struct line//记录直线参数的结构
    {
     
        public double k;
        public double b;
    }

	/// 
        /// 求直线斜率与截距
        /// 
        /// 
        /// 
        /// 
        private line parameter(MyPoint p1, MyPoint p2)
        {
     
            double k, b;
            line newcs = new line();
            k = (p2.y - p1.y) / (p2.x - p1.x);
            b = p1.y - k * p1.x;
            newcs.k = k;
            newcs.b = b;
            return newcs;
        }

 	/// 
        /// 求点到直线的距离
        /// 
        /// 
        /// 
        /// 
        private double distance(MyPoint dot, line cs)
        {
     
            double dis = (Math.Abs(cs.k * dot.x - dot.y + cs.b)) / Math.Sqrt(cs.k * cs.k + 1);
            return dis;
        }
List<MyPoint> outPoint = new List<MyPoint>();//保存结果
private void Douglas(List<MyPoint> InPoints, int n1, int n2, double d)
        {
     
            int num = InPoints.Count;
            //List OutPoint = new List();
            int Max = 0;//定义拥有最大距离值的点的编号
            line MyLine = new line();
            MyLine = parameter(InPoints[n1], InPoints[n2 - 1]);  //得到收尾点连线组成的虚线
            double MaxDistance = 0;
            if (d == 0)
            {
     
                outPoint = InPoints;
            }
            else
            {
     
                for (int i = n1 + 1; i < n2 - 1; i++)
                {
     
                    double pDistance = distance(InPoints[i], MyLine);
                    if (pDistance > d && pDistance >= MaxDistance)
                    {
     
                        Max = i;
                        MaxDistance = pDistance;
                    }
                }
                if (Max == 0) //如果最大值距离小于阈值直接返回首位
                {
     
                    outPoint.Add(InPoints[n1]);
                    outPoint.Add(InPoints[n2 - 1]);
                    return;
                }
                else if (n1 + 1 == Max && n2 - 2 != Max)   //第二个点为最大距离
                {
     
                    Douglas(InPoints, Max + 1, n2, d);
                    outPoint.Add(InPoints[n1]);
                }
                else if (n2 - 2 == Max && n1 + 1 != Max)  //倒数第二个点为最大距离
                {
     
                    Douglas(InPoints, 0, Max + 1, d);
                    outPoint.Add(InPoints[n2 - 1]);
                }
                else if (n1 + 1 == Max && n2 - 2 == Max)  //夹中间
                {
     
                    outPoint.Add(InPoints[Max - 1]);
                    outPoint.Add(InPoints[Max]);
                    outPoint.Add(InPoints[Max + 1]);
                    return;
                }
                else
                {
     
                    Douglas(InPoints, n1, Max + 1, d);
                    Douglas(InPoints, Max, n2, d);
                }
            }
        }

调用算法对点坐标压缩
C#道格拉斯线压缩算法(经纬度坐标抽稀)_第2张图片

C#道格拉斯线压缩算法(经纬度坐标抽稀)_第3张图片

你可能感兴趣的:(C#,道格拉斯算法,线压缩)