转:C# 判断某点在否在某区域内,在多边形内。求两个坐标点间的距离

转自https://blog.csdn.net/e_wsq/article/details/7536158,代码挺全的

可以判断某个点是否在区域内,用于区域管理

 

  private void button1_Click(object sender, EventArgs e)
        {

            string[] _point = txt_lan.Text.Trim().Split(new char[] { ',' });
            double lng = Convert.ToDouble(_point[0]);
            double lat = Convert.ToDouble(_point[1]);
            point point = new point(lng, lat);//要判断的坐标

            if (listBox1.Items.Count > 0)
            {
                //区域坐标集
                polygon = new point[listBox1.Items.Count];
                for (int i = 0; i < listBox1.Items.Count; i++)
                {
                    string[] temV = listBox1.Items[i].ToString().Trim().Split(new char[] { ',' });
                    polygon[i] = new point(double.Parse(temV[0]), double.Parse(temV[1]));
                }
            }
            point ne = new point(0, 0), sw = new point(0, 0);
            FindAppointDirection(polygon, ref ne, ref sw);//找东北 西南坐标
            if (isPointInRect(ne, sw, point))
            {
                bool fuck = CalculationAlgorithm(polygon, point);
                if (fuck)
                {
                    label3.Text = "目标点在几何图形中";
                }
                else
                {
                    label3.Text = "目标点不在几何图形中";
                }

            }
            else
            {
                label3.Text = "目标点不在几何图形中";
            }

        }


        #region 
        /// <summary>
        /// 区域坐标集
        /// </summary>
        point[] polygon = new point[] {
            new point(119.331244,26.036914),
            new point(119.332699,26.037166),
            new point(119.331675,26.035672),
            new point(119.332843,26.035916),
            new point(119.332861,26.036395)
            };

        public bool CalculationAlgorithm(point[] polygon, point p)
        {
            #region 
            point[] pts = polygon;//获取多边形点
            //112.58464,26.909432
            int N = pts.Length;
            var boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
            var intersectCount = 0;//cross points count of x 
            var precision = 2e-10; //浮点类型计算时候与0比较时候的容差
            point p1, p2;//neighbour bound vertices
            p1 = pts[0];//left vertex        
            for (var i = 1; i <= N; ++i)
            {//check all rays            
                if (p.Equals(p1))
                {
                    return boundOrVertex;//p is an vertex
                }

                p2 = pts[i % N];//right vertex            
                if (p.lat < Math.Min(p1.lat, p2.lat) || p.lat > Math.Max(p1.lat, p2.lat))
                {//ray is outside of our interests                
                    p1 = p2;
                    continue;//next ray left point
                }

                if (p.lat > Math.Min(p1.lat, p2.lat) && p.lat < Math.Max(p1.lat, p2.lat))
                {//ray is crossing over by the algorithm (common part of)
                    if (p.lng <= Math.Max(p1.lng, p2.lng))
                    {//x is before of ray                    
                        if (p1.lat == p2.lat && p.lng >= Math.Min(p1.lng, p2.lng))
                        {//overlies on a horizontal ray
                            return boundOrVertex;
                        }

                        if (p1.lng == p2.lng)
                        {//ray is vertical                        
                            if (p1.lng == p.lng)
                            {//overlies on a vertical ray
                                return boundOrVertex;
                            }
                            else
                            {//before ray
                                ++intersectCount;
                            }
                        }
                        else
                        {//cross point on the left side                        
                            var xinters = (p.lat - p1.lat) * (p2.lng - p1.lng) / (p2.lat - p1.lat) + p1.lng;//cross point of lng                        
                            if (Math.Abs(p.lng - xinters) < precision)
                            {//overlies on a ray
                                return boundOrVertex;
                            }

                            if (p.lng < xinters)
                            {//before ray
                                ++intersectCount;
                            }
                        }
                    }
                }
                else
                {//special case when ray is crossing through the vertex                
                    if (p.lat == p2.lat && p.lng <= p2.lng)
                    {//p crossing over p2                    
                        var p3 = pts[(i + 1) % N]; //next vertex                    
                        if (p.lat >= Math.Min(p1.lat, p3.lat) && p.lat <= Math.Max(p1.lat, p3.lat))
                        {//p.lat lies between p1.lat & p3.lat
                            ++intersectCount;
                        }
                        else
                        {
                            intersectCount += 2;
                        }
                    }
                }
                p1 = p2;//next ray left point
            }
            if (intersectCount % 2 == 0)
            {//偶数在多边形外
                return false;
            }
            else
            { //奇数在多边形内
                return true;
            }
            #endregion
        }
      

        /// <summary>
        /// 判断点是否在矩形内
        /// </summary>
        /// <param name="ne"></param>
        /// <param name="sw"></param>
        /// <param name="Tagrtpoint"></param>
        /// <returns></returns>
        bool isPointInRect(point ne, point sw, point Tagrtpoint)
        {
            //西南脚点 point sw = new point(112.579325, 26.898023);
            //东北  point ne = new point(26.915291, 112.608287);
            return (Tagrtpoint.lng >= sw.lng && Tagrtpoint.lng <= ne.lng && Tagrtpoint.lat >= sw.lat && Tagrtpoint.lat <= ne.lat);
        }
        /// <summary>
        /// 找东西南北经方向 简单说找东北 西南 坐标做一个矩形判断
        /// </summary>
        void FindAppointDirection(point[] polygon, ref point ne, ref point sw)
        {

            double[] iArrarylat = new double[polygon.Length];
            double[] iArrarylng = new double[polygon.Length];
            for (int i = 0; i < polygon.Length; i++)
            {
                iArrarylat[i] = polygon[i].lat;
                iArrarylng[i] = polygon[i].lng;
            }
            Array.Sort(iArrarylat);
            Array.Sort(iArrarylng);
            ne.lat = iArrarylat[polygon.Length - 1];
            ne.lng = iArrarylng[polygon.Length - 1];
            sw.lat = iArrarylat[0];
            sw.lng = iArrarylng[0];
        }
        public class point
        {
            public double lng;
            public double lat;
            public point(double lng, double lat)
            {
                this.lat = lat;
                this.lng = lng;
            }
        }


        /// <summary>
        /// 判断点是否在多边形内.
        /// ----------原理----------
        /// 注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,
        /// 如果P在多边形外部,则交点个数必为偶数(0也在内)。
        /// </summary>
        /// <param name="checkPoint">要判断的点</param>
        /// <param name="polygonPoints">多边形的顶点</param>
        /// <returns></returns>
        public static bool IsInPolygon(PointF checkPoint, List<PointF> polygonPoints)
        {
            bool inside = false;
            int pointCount = polygonPoints.Count;
            PointF p1, p2;
            for (int i = 0, j = pointCount - 1; i < pointCount; j = i, i++)//第一个点和最后一个点作为第一条线,之后是第一个点和第二个点作为第二条线,之后是第二个点与第三个点,第三个点与第四个点...
            {
                p1 = polygonPoints[i];
                p2 = polygonPoints[j];
                if (checkPoint.Y < p2.Y)
                {//p2在射线之上
                    if (p1.Y <= checkPoint.Y)
                    {//p1正好在射线中或者射线下方
                        if ((checkPoint.Y - p1.Y) * (p2.X - p1.X) > (checkPoint.X - p1.X) * (p2.Y - p1.Y))//斜率判断,在P1和P2之间且在P1P2右侧
                        {
                            //射线与多边形交点为奇数时则在多边形之内,若为偶数个交点时则在多边形之外。
                            //由于inside初始值为false,即交点数为零。所以当有第一个交点时,则必为奇数,则在内部,此时为inside=(!inside)
                            //所以当有第二个交点时,则必为偶数,则在外部,此时为inside=(!inside)
                            inside = (!inside);
                        }
                    }
                }
                else if (checkPoint.Y < p1.Y)
                {
                    //p2正好在射线中或者在射线下方,p1在射线上
                    if ((checkPoint.Y - p1.Y) * (p2.X - p1.X) < (checkPoint.X - p1.X) * (p2.Y - p1.Y))//斜率判断,在P1和P2之间且在P1P2右侧
                    {
                        inside = (!inside);
                    }
                }
            }
            return inside;

        }
        #endregion

 

 #region 求两点坐标间的距离

 

        private void button4_Click(object sender, EventArgs e)
        {
            string[] tmV = txt_Point1.Text.Trim().Split(new char[] { ',' });
            string[] tmV2 = txt_Point2.Text.Trim().Split(new char[] { ',' });
            double _JL = GetDistance(double.Parse(tmV[1]), double.Parse(tmV[0]), double.Parse(tmV2[1]), double.Parse(tmV2[0]));

            txt_JL.Text = _JL.ToString();
        }

        //地球半径,单位米
        private const double EARTH_RADIUS = 6378137;

        /// <summary>
        /// 计算两点位置的距离,返回两点的距离,单位:米
        /// 该公式为GOOGLE提供,误差小于0.2米
        /// </summary>
        /// <param name="lng1">第一点经度</param>
        /// <param name="lat1">第一点纬度</param>        
        /// <param name="lng2">第二点经度</param>
        /// <param name="lat2">第二点纬度</param>
        /// <returns></returns>
        public  double GetDistance(double lng1, double lat1, double lng2, double lat2)
        {
            double radLat1 = Rad(lat1);
            double radLng1 = Rad(lng1);
            double radLat2 = Rad(lat2);
            double radLng2 = Rad(lng2);
            double a = radLat1 - radLat2;
            double b = radLng1 - radLng2;
            double result = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2))) * EARTH_RADIUS;
            return result;
        }

        /// <summary>
        /// 经纬度转化成弧度
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        private  double Rad(double d)
        {
            return (double)d * Math.PI / 180d;
        }
        #endregion

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值