GIS 二维常见算法-入门篇

来源:互联网 发布:远视 眼镜 知乎 编辑:程序博客网 时间:2024/06/10 00:03

处理点与线的关系,线与线的关系的算法等等,如有错误,欢迎指正。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace PointLinePositionRelation{    #region Entity    /// <summary>    /// Entity Point    /// </summary>    public class Point    {        public Point(double x, double y)        {            this.x = x;            this.y = y;        }        private double x;        public double X        {            get { return x; }            set { x = value; }        }        private double y;        public double Y        {            get { return y; }            set { y = value; }        }    }    /// <summary>    /// Entity of line    /// </summary>    public class Line    {        public Line()        {        }        public Line(List<Point> _points)        {            this.points = _points;        }        private List<Point> points = new List<Point>();        public List<Point> Points        {            get { return points; }        }        public bool AddPoint(Point p)        {            bool success = false;            if (!points.Contains(p))            {                points.Add(p);                success = true;            }            return success;        }        public bool RemovePoint(Point p)        {            bool success = false;            if (points.Contains(p))            {                points.Remove(p);                success = true;            }            return success;        }        public bool UpdatePoint(Point src_p, Point tar_p)        {            bool success = false;            if (points.Contains(src_p))            {                src_p.X = tar_p.X;                src_p.Y = tar_p.Y;                success = true;            }            return success;        }    }    /// <summary>    /// Position Status    /// </summary>    enum Position    {        LEFT = 0,        RIGHT = 1,        ON_K = 2,        UP = 3,        DOWN = 4,        ON = 5,        ERROE = 6    }    #endregion    #region Function    public static class PointLineAlgorithems    {        #region Algorithems        /// <summary>        /// return the traingle degree         /// </summary>        /// <param name="tupe"></param>        /// tuple item1:the first point        /// tuple item2:the last point        /// tuple item3:the middle point        /// <returns></returns>        public static double GetTraingleDegree(Tuple<Point, Point, Point> tupe)        {            double distance1 = GetDistance(tupe.Item1, tupe.Item2);            double distance2 = GetDistance(tupe.Item1, tupe.Item3);            double distance3 = GetDistance(tupe.Item2, tupe.Item3);            return Math.Acos(Math.Pow(distance1,2)+Math.Pow(distance2,2)-Math.Pow(distance3,2)/2*distance1*distance2);        }        /// <summary>        /// to judage point and line position        /// </summary>        /// <param name="l"></param>        /// <param name="p"></param>        /// <returns></returns>        public static string JudgePointLineRelation(Line l, Point p)        {            //y = kx + b            //the k of line combine with two points            double k;            //the b of line             double b;            //the result             string POSITION = string.Empty;            //this function is to deal with one point with a line with two points            //if line point is not 2,you should split to two or more lines with             //two points,so here we return string.Empty            if (l.Points.Count != 2 || p == null) return string.Empty;            //if the X value of two points are the same            //wo can not get k,then we can deal it as follows            if (l.Points[0].X == l.Points[1].X)            {                if (p.X > l.Points[0].X) POSITION = "LEFT";                else if (p.X < l.Points[0].X) POSITION = "RIGHT";                else if (p.X == l.Points[0].X) POSITION = "ON";                //else POSITION = "ERROR_K";            }            //if the k is not zero,we can deal it as follows            else            {                k = (l.Points[0].Y - l.Points[1].Y) / (l.Points[0].X - l.Points[1].X);                b = ((l.Points[0].X * l.Points[1].Y) - (l.Points[0].Y * l.Points[1].X)) / (l.Points[0].X - l.Points[1].X);                if (p.Y > k * p.X + b) POSITION = "UP";                else if (p.Y < k * p.X + b) POSITION = "DOWN";                else if (p.Y == k * p.X + b) POSITION = "ON";                //else POSITION = "ERROR_N";            }            return POSITION;        }        /// <summary>        /// to judage if two line clips        /// </summary>        /// <param name="src"></param>        /// <param name="tar"></param>        /// <returns></returns>        public static int? JudageLinesRelation(Line src, Line tar)        {            //if point count of line is less then 2,we do not             //deal with this            if (src.Points.Count < 2 || tar.Points.Count < 2)                return null;            Point p = null;            Line l = null;            string flag = string.Empty;            //falg of clip,if not clip 1,else 0            int? clip = 1;            for (int i = 0; i < src.Points.Count; i++)            {                //the first loop point                p = new Point(src.Points[i].X, src.Points[i].Y);                //the loop for tar line                for (int j = 0; j + 1 < tar.Points.Count; j++)                {                    //temp line with two points                    l = new Line();                    l.AddPoint(tar.Points[j]);                    l.AddPoint(tar.Points[j + 1]);                    //if the value of flag is Null or Empty,means flag has not been given value                    if (string.IsNullOrEmpty(flag))                        flag = JudgePointLineRelation(l, p);                    else                    {                        //if the new point position is not the same as the old point,the two line cliped                        //there is no need to contine the loop,we change the flag value to 0(means two line cliped)                        if (flag != JudgePointLineRelation(l, p))                        {                            clip = 0;                            break;                        }                    }                }            }            return clip;        }        /// <summary>        /// get distance of two points        /// </summary>        /// <param name="src"></param>        /// <param name="tar"></param>        /// <returns></returns>        public static double GetDistance(Point src, Point tar)        {            if (src.X == tar.X && src.Y == tar.Y) return 0;            return Math.Sqrt(Math.Pow(Math.Abs(src.X - tar.X), 2) + Math.Pow(Math.Abs(src.Y - tar.Y), 2));        }        /// <summary>        /// To get min distance of two lines        /// </summary>        /// <param name="src"></param>        /// <param name="tar"></param>        /// <returns></returns>        public static Tuple<double?, int?, int?> CalcMinDistance(Line src, Line tar)        {            //if the point count less than 2,we do not think it is a line.            if (src.Points.Count < 2 || tar.Points.Count < 2) return null;            //if the two line cliped,we do not deal with this situation            if (0 == JudageLinesRelation(src, tar)) return null;            #region Params            //the min distance point src_index            int? src_index = null;            //the min distance point tar_index            int? tar_index = null;            //the temp value to keep the distance            double? temp = null;            //the min distance            double dist = 0;            #endregion            //loop for the src line            for (int i = 0; i < src.Points.Count; i++)            {                //loop for tar line                for (int j = 0; j < tar.Points.Count; j++)                {                    //the distance                     dist = GetDistance(src.Points[i], tar.Points[j]);                    //if the temp has not been given value                    if (null == temp)                    {                        temp = dist;                        src_index = i;                        tar_index = j;                    }                    else                    {                        //if the new value < temp,then keep the min value                        if (temp > dist)                        {                            temp = dist;                            src_index = i;                            tar_index = j;                        }                    }                }            }            return new Tuple<double?, int?, int?>(temp, src_index, tar_index);        }        /// <summary>        /// to judage the two line direction        /// </summary>        /// <param name="src_line"></param>        /// <param name="tar_line"></param>        /// <returns></returns>        public static bool? JudageLineDirection(Line src_line, Line tar_line)        {            //if the point count of line less than 2,we do not deal with this            if (src_line.Points.Count < 2 || tar_line.Points.Count < 2)                return null;            //the boolean flag,if the two line are the same direction,then true            //else the flag will be false.Note:if the exception has occoured            //the value null will be returned            bool flag = false;            //the line temp value.            //Note:this line is not always represent the min distance line            Line line = null;            //the temp value to recored the result that the position of point on             //src_line position and temp line(mostly min distance line)             string src_temp = string.Empty;            //the temp value to recored the result that the position of point on             //tar_line position and temp line(mostly min distance line)             string tar_temp = string.Empty;            //the temp tuple value that recored the min distance line information            //item1:min distance value            //item2:the index of the point on src_line            //item3:the index of the point on tar_line            Tuple<double?, int?, int?> tuple = CalcMinDistance(src_line, tar_line);            //if the min diatance information is not null            if (tuple != null)            {                //the index of src_line or tar_line type is int?,if index has not been given value                //the value will be null,else will be the index of point,which combine the min distance line                if (tuple.Item2.HasValue && tuple.Item3.HasValue)                {                    #region different situation                    //if the index of point which combine the min distance line is less than count                    if ((tuple.Item2.Value < src_line.Points.Count - 1) && (tuple.Item2.Value < tar_line.Points.Count - 1))                    {                        line = new Line(new List<Point> { src_line.Points[tuple.Item2.Value], tar_line.Points[tuple.Item3.Value] });                        src_temp = JudgePointLineRelation(line, src_line.Points[tuple.Item2.Value + 1]);                        tar_temp = JudgePointLineRelation(line, tar_line.Points[tuple.Item3.Value + 1]);                    }                    //if the index of point of src_line equals count-1                    else if (tuple.Item2.Value == src_line.Points.Count - 1)                    {                        line = new Line(new List<Point> { src_line.Points[tuple.Item2.Value - 1], tar_line.Points[tuple.Item3.Value] });                        src_temp = JudgePointLineRelation(line, src_line.Points[tuple.Item2.Value]);                        tar_temp = JudgePointLineRelation(line, tar_line.Points[tuple.Item3.Value + 1]);                    }                    //if the index of point of tar_line equals count-1                    else if (tuple.Item3.Value == tar_line.Points.Count - 1)                    {                        line = new Line(new List<Point> { src_line.Points[tuple.Item2.Value], tar_line.Points[tuple.Item3.Value - 1] });                        src_temp = JudgePointLineRelation(line, src_line.Points[tuple.Item2.Value + 1]);                        tar_temp = JudgePointLineRelation(line, tar_line.Points[tuple.Item3.Value]);                    }                    //both of them are equals count - 1                    else                    {                        line = new Line(new List<Point> { src_line.Points[tuple.Item2.Value], tar_line.Points[tuple.Item3.Value] });                        src_temp = JudgePointLineRelation(line, src_line.Points[tuple.Item2.Value - 1]);                        tar_temp = JudgePointLineRelation(line, tar_line.Points[tuple.Item3.Value - 1]);                    }                    #endregion                }                else                {                    //if did not get min distance information,return null                    return null;                }                //if the result are different,different direction                //else the same direction                if ((src_temp != tar_temp) && (src_temp != "ON" && tar_temp != "ON"))                {                    flag = false;                }                else                {                    flag = true;                }            }            return flag;        }        #endregion    }    #endregion}


0 0
原创粉丝点击