zoukankan      html  css  js  c++  java
  • 判断点是否在多边形之内的方法

     一.按角度 (转帖:hustcybyhy0611。特此感谢)

    1.将多边形的N个顶点与待判断点相连组成一条直线,根据直线的倾斜角将这个N个顶点按照顺时针(或逆时针)的顺序排序. 
    2.求相邻两个顶点与待判断点边线的两条直线的顺时针方向的夹角,如果对握有的顶点,这个夹角小于180度,则这个点位于多边形内部. 
    这个问题与求平面点集的凸包类似。(此方法不太适合凹多边形)

    先写一个辅助类:

    [c-sharp] view plaincopy
    1. public class Line : IComparable<Line>  
    2.     {  
    3.         #region Members  
    4.   
    5.         private PointF start;  
    6.         private PointF end;  
    7.  
    8.         #endregion  
    9.  
    10.         #region Constructors  
    11.   
    12.         public Line(PointF start, PointF end)  
    13.         {  
    14.             this.start = start;  
    15.             this.end = end;  
    16.         }  
    17.  
    18.         #endregion  
    19.  
    20.         #region Properties  
    21.   
    22.         public PointF Start  
    23.         {  
    24.             get  
    25.             {  
    26.                 return start;  
    27.             }  
    28.             set  
    29.             {  
    30.                 start = value;  
    31.             }  
    32.         }  
    33.   
    34.         public PointF End  
    35.         {  
    36.             get  
    37.             {  
    38.                 return end;  
    39.             }  
    40.             set  
    41.             {  
    42.                 end = value;  
    43.             }  
    44.         }  
    45.   
    46.         public double Angle  
    47.         {  
    48.             get  
    49.             {  
    50.                 double dX = End.X - Start.X;  
    51.                 double dY = End.Y - Start.Y;  
    52.   
    53.                 double angle = Math.Atan(dY / dX) * 180 / Math.PI;  
    54.   
    55.                 if (dX < 0)  
    56.                 {  
    57.                     angle += 180;  
    58.                 }  
    59.   
    60.                 if (angle < 0)  
    61.                 {  
    62.                     angle += 360;  
    63.                 }  
    64.   
    65.                 return angle;  
    66.             }  
    67.         }  
    68.  
    69.         #endregion  
    70.  
    71.         #region Functions  
    72.   
    73.         public double IncludedAngleWith(Line line)  
    74.         {  
    75.             double angle = line.Angle;  
    76.             if (angle < this.Angle)  
    77.             {  
    78.                 angle += 360;  
    79.             }  
    80.   
    81.             return angle - this.Angle;  
    82.         }  
    83.   
    84.         public int CompareTo(Line line)  
    85.         {  
    86.             if (this.Angle < line.Angle)  
    87.             {  
    88.                 return -1;  
    89.             }  
    90.             else if (this.Angle == line.Angle)  
    91.             {  
    92.                 return 0;  
    93.             }  
    94.             else  
    95.             {  
    96.                 return 1;  
    97.             }  
    98.         }  
    99.  
    100.         #endregion  
    101.     }  

    下面是判断算法:

    [c-sharp] view plaincopy
    1. public bool Contains(PointF[] vertexArray, PointF point)  
    2.         {  
    3.             Line[] lineArray = new Line[vertexArray.Length];  
    4.             for (int index = 0; index < vertexArray.Length; index++)  
    5.             {  
    6.                 if (vertexArray[index] == point)        //判断点与顶点重合  
    7.                 {  
    8.                     return false;  
    9.                 }  
    10.   
    11.                 lineArray[index] = new Line(point, vertexArray[index]);  
    12.             }  
    13.   
    14.             Array.Sort(lineArray);  
    15.   
    16.             for (int index = 0; index < lineArray.Length - 1; index++)  
    17.             {  
    18.                 if (lineArray[index].IncludedAngleWith(lineArray[index + 1]) >= 180)  
    19.                 {  
    20.                     return false;  
    21.                 }  
    22.             }  
    23.   
    24.             if (lineArray[lineArray.Length - 1].IncludedAngleWith(lineArray[0]) >= 180)  
    25.             {  
    26.                 return false;  
    27.             }  
    28.   
    29.             return true;  
    30.         }  

    测试代码:

    [c-sharp] view plaincopy
    1. string str = "124.89874,46.6286V124.9001,46.62973V124.90287,46.62741V124.90409,46.62783V124.90334,46.63028V124.9055,46.63044V124.90629,46.62796V124.90775,46.62792V124.90868,46.63011V124.91089,46.62931V124.90943,46.62751V124.91182,46.62706V124.91257,46.62905V124.91506,46.62812V124.91281,46.6268V124.91459,46.62619V124.91557,46.6277V124.91708,46.62586V124.91468,46.6257V124.91497,46.62477V124.91703,46.62384V124.91497,46.62261V124.91356,46.62387V124.91309,46.62194V124.91506,46.62232V124.91511,46.62081V124.91286,46.62097V124.91271,46.62029V124.91482,46.61975V124.91398,46.61833V124.91187,46.61942V124.91117,46.61872V124.91075,46.61701V124.90746,46.61714V124.90976,46.61878V124.90639,46.61868V124.90559,46.61717V124.90142,46.61772V124.90498,46.61888V124.90212,46.61946V124.90085,46.61807V124.89921,46.61952V124.90151,46.62013V124.90109,46.62152V124.89813,46.62013V124.8979,46.62223V124.90067,46.622V124.90001,46.62351V124.89663,46.62281V124.89663,46.62441V124.89917,46.62445V124.89903,46.62545V124.89588,46.62567V124.89584,46.62702V124.89903,46.62638V124.89982,46.62725";  
    2.             string[] s1 = str.Split('V');  
    3.   
    4.             PointF[] ps = new PointF[s1.Length];  
    5.             for (int i = 0; i < s1.Length; i++)  
    6.             {  
    7.                 string[] s2 = s1[i].Split(',');  
    8.                 PointF pf = new PointF(float.Parse(s2[0]), float.Parse(s2[1]));  
    9.                 ps[i] = pf;  
    10.             }  
    11.   
    12.             float f1=0;     
    13.             float f2=0;  
    14.   
    15.             if (this.Contains(ps, new PointF(f1,f2)))  
    16.             {  
    17.                 MessageBox.Show("在范围内");  
    18.             }  
    19.             else  
    20.             {  
    21.                 MessageBox.Show("不在范围内");  
    22.             }  

    二.用c#内置函数:(面对复杂的多边形处理上可能不太好)

    [c-sharp] view plaincopy
    1. string str = "124.89874,46.6286V124.9001,46.62973V124.90287,46.62741V124.90409,46.62783V124.90334,46.63028V124.9055,46.63044V124.90629,46.62796V124.90775,46.62792V124.90868,46.63011V124.91089,46.62931V124.90943,46.62751V124.91182,46.62706V124.91257,46.62905V124.91506,46.62812V124.91281,46.6268V124.91459,46.62619V124.91557,46.6277V124.91708,46.62586V124.91468,46.6257V124.91497,46.62477V124.91703,46.62384V124.91497,46.62261V124.91356,46.62387V124.91309,46.62194V124.91506,46.62232V124.91511,46.62081V124.91286,46.62097V124.91271,46.62029V124.91482,46.61975V124.91398,46.61833V124.91187,46.61942V124.91117,46.61872V124.91075,46.61701V124.90746,46.61714V124.90976,46.61878V124.90639,46.61868V124.90559,46.61717V124.90142,46.61772V124.90498,46.61888V124.90212,46.61946V124.90085,46.61807V124.89921,46.61952V124.90151,46.62013V124.90109,46.62152V124.89813,46.62013V124.8979,46.62223V124.90067,46.622V124.90001,46.62351V124.89663,46.62281V124.89663,46.62441V124.89917,46.62445V124.89903,46.62545V124.89588,46.62567V124.89584,46.62702V124.89903,46.62638V124.89982,46.62725";  
    2.             string[] s1 = str.Split('V');  
    3.   
    4.             PointF[] ps = new PointF[s1.Length];  
    5.             for (int i = 0; i < s1.Length; i++)  
    6.             {  
    7.                 string[] s2 = s1[i].Split(',');  
    8.                 PointF pf = new PointF(float.Parse(s2[0]), float.Parse(s2[1]));  
    9.                 ps[i] = pf;  
    10.             }  
    11.   
    12.   
    13.   
    14.             System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();  
    15.               
    16.             Region r = new Region();  
    17.   
    18.             gp.Reset();  
    19.             gp.AddPolygon(ps);  
    20.             r.MakeEmpty();  
    21.             r.Union(gp);  
    22.   
    23.             float f1=0;     
    24.             float f2=0;  
    25.               
    26.             if (r.IsVisible(new PointF(f1,f2)))  
    27.             {  
    28.                 MessageBox.Show("在范围内");  
    29.             }  
    30.             else  
    31.             {  
    32.                 MessageBox.Show("不在范围内");  
    33.             }  

    三.射线法判断(本人感觉这个方法较好)

    [c-sharp] view plaincopy
    1. public int isLeft(Point P0, Point P1,Point P2)  
    2. {  
    3.     int abc= ((P1.X - P0.X) * (P2.Y - P0.Y) - (P2.X - P0.X) * (P1.Y - P0.Y));  
    4.     return abc;  
    5.                                                   
    6. }  
    7.   
    8. private bool PointInFences(Point pnt1, Point[] fencePnts)  
    9. {  
    10.   
    11.     int wn = 0,j=0; //wn 计数器 j第二个点指针  
    12.     for (int i = 0; i < fencePnts.Length; i++)  
    13.     {//开始循环  
    14.              if (i == fencePnts.Length - 1)  
    15.                  j = 0;//如果 循环到最后一点 第二个指针指向第一点  
    16.              else  
    17.                  j = j + 1; //如果不是 ,则找下一点  
    18.   
    19.   
    20.         if (fencePnts[i].Y <= pnt1.Y) // 如果多边形的点 小于等于 选定点的 Y 坐标  
    21.         {  
    22.             if (fencePnts[j].Y > pnt1.Y) // 如果多边形的下一点 大于于 选定点的 Y 坐标  
    23.             {  
    24.                 if (isLeft(fencePnts[i], fencePnts[j], pnt1) > 0)  
    25.                 {  
    26.                     wn++;  
    27.                 }  
    28.             }  
    29.         }  
    30.         else  
    31.         {  
    32.             if (fencePnts[j].Y <= pnt1.Y)  
    33.             {  
    34.                 if (isLeft(fencePnts[i], fencePnts[j], pnt1) < 0)  
    35.                 {  
    36.                     wn--;  
    37.                 }  
    38.             }  
    39.         }  
    40.     }  
    41.     if (wn == 0)  
    42.         return false;  
    43.     else  
    44.         return true;  

    From: http://blog.csdn.net/lqh_it/article/details/4667394

  • 相关阅读:
    java Object类是可以接收集合类型的
    java.lang.String中[ "张飞"+1+1 ] 和 [ "张飞"+(1+1) ]
    AFL Fuzz入门
    [转载]linux与grep
    linux下安装clamav
    [转载]Linux连续执行多条命令
    [转载]linux下各文件夹的结构说明及用途介绍
    [转载]linux常用命令
    [转载]Ubuntu 16.04 蓝屏解决方案
    pycharm修改python版本
  • 原文地址:https://www.cnblogs.com/yuxuetaoxp/p/2526581.html
Copyright © 2011-2022 走看看