追寻我心

记录点点滴滴,追随自我风格!
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

计算坐标点是否在任意多边形、圆内

Posted on 2013-08-30 17:04  追寻我心  阅读(656)  评论(0)    收藏  举报

计算坐标点是否在多边形、圆内

 

 

 

方法类:

 public class Polygon
    {
        public Polygon(){}
        private readonly PointF[] _vertices;

        /// <summary>  
        ///     Creates a new instance of the <see cref="Polygon"/> class with the specified vertices.  
        /// </summary>  
        /// <param name="vertices">  
        ///     An array of <see cref="PointF"/> structures representing the points between the sides of the polygon.  
        /// </param>  
        public Polygon(PointF[] vertices)
        {
            _vertices = vertices;
        }

        

        /// <summary>  
        ///     Determines if the specified <see cref="PointF"/> if within this polygon.  
        /// </summary>  
        /// <remarks>  
        ///     This algorithm is extremely fast, which makes it appropriate for use in brute force algorithms.  
        /// </remarks>  
        /// <param name="point">  
        ///     The point containing the x,y coordinates to check.  
        /// </param>  
        /// <returns>  
        ///     <c>true</c> if the point is within the polygon, otherwise <c>false</c>  
        /// </returns>  
        public bool PointInPolygon(PointF point)
        {
            var j = _vertices.Length - 1;
            var oddNodes = false;

            for (var i = 0; i < _vertices.Length; i++)
            {
                if (_vertices[i].Y < point.Y && _vertices[j].Y >= point.Y || _vertices[j].Y < point.Y && _vertices[i].Y >= point.Y)
                {
                    if (_vertices[i].X + (point.Y - _vertices[i].Y) / (_vertices[j].Y - _vertices[i].Y) * (_vertices[j].X - _vertices[i].X) < point.X)
                    {
                        oddNodes = !oddNodes;
                    }
                }
                j = i;
            }

            return oddNodes;
        }


        static double DEF_PI = 3.14159265359; // PI
        static double DEF_2PI = 6.28318530712; // 2*PI
        static double DEF_PI180 = 0.01745329252; // PI/180.0
        static double DEF_R = 6370693.5; // radius of earth

        /// <summary>
        /// 计算两点间的距离
        /// </summary>
        /// <param name="lon1">坐标1经度</param>
        /// <param name="lat1">坐标1纬度</param>
        /// <param name="lon2">坐标2经度</param>
        /// <param name="lat2">坐标2纬度</param>
        /// <returns></returns>
        public double GetLongDistance(double lon1, double lat1, double lon2, double lat2)
        {
            double ew1, ns1, ew2, ns2;
            double distance;

            // 角度转换为弧度
            ew1 = lon1 * DEF_PI180;
            ns1 = lat1 * DEF_PI180;
            ew2 = lon2 * DEF_PI180;
            ns2 = lat2 * DEF_PI180;

            // 求大圆劣弧与球心所夹的角(弧度)
            distance = Math.Sin(ns1) * Math.Sin(ns2) + Math.Cos(ns1) * Math.Cos(ns2) * Math.Cos(ew1 - ew2);

            // 调整到[-1..1]范围内,避免溢出
            if (distance > 1.0)
                distance = 1.0;
            else if (distance < -1.0)
                distance = -1.0;
            // 求大圆劣弧长度
            distance = DEF_R * Math.Acos(distance);
            return distance;
        }

        /// <summary>
        /// 计算点是否在圆内
        /// </summary>
        /// <param name="point">比较坐标点</param>
        /// <param name="roundCenterPoint">圆中心点</param>
        /// <param name="r">圆半径</param>
        /// <returns>True False</returns>
        public bool PointInRound(PointF point, PointF roundCenterPoint, double r)
        {
            //两点之间的距离
            var distance = GetLongDistance(point.X, point.Y, roundCenterPoint.X, roundCenterPoint.Y);
            return distance < r;
        }

 

调用:

//测试多边形
var vertices = new PointF[4]  
                           {  
                                new PointF(1, 3),  
                               new PointF(1, 1),  
                               new PointF(4, 1),  
                               new PointF(4, 3)  
                            };  
 
 var p = new Polygon(vertices);  
 var isIn=p.PointInPolygon(new PointF(2,2));


//测试圆
 var p = new Polygon();
 var isOk = p.PointInRound(new PointF(float.Parse("120.784584"), float.Parse("31.287565")), new PointF(float.Parse("120.782357"), float.Parse("31.28633")), 154.8930217136462);
        

 

参考:
http://www.ytechie.com/2009/08/determine-if-a-point-is-contained-within-a-polygon.html

http://alienryderflex.com/polygon/

http://erich.realtimerendering.com/ptinpoly/

http://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/