C#判断点的位置(区域内或外)

开发 后端
本文介绍了c# 判断点的位置的三种方法及其图形算法,供大家参考。

C#判断点的位置方法一 

  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;  
  45.        } 

C#判断点的位置方法二——c#内置函数:

  1. GraphicsPath myGraphicsPath = new GraphicsPath();   
  2. Region myRegion=new Region();                
  3. myGraphicsPath.Reset();  
  4. Point inputponint = new Point(inputx, inputy);  
  5.  
  6. myGraphicsPath.AddPolygon(points);//points);  
  7.  
  8. myRegion.MakeEmpty();  
  9.  
  10. myRegion.Union(myGraphicsPath);     
  11. //返回判断点是否在多边形里  
  12. bool myPoint= myRegion.IsVisible(inputponint);  
  13. this.lblx.Text = myPoint.ToString(); 

图形算法:

1,面积法。就是看所有边和目标点组成的三角形面积和是否等于总的多边形面积,如果相等,则在内部。反之在外部。这种方法计算量较大,用到的主要计算是查乘。

2,夹角和法。参见三楼,判断所有边和目标点的夹角和是否为360度。计算量比上面这种方法稍微小点,用到主要是点乘和求模计算。

3,引射线法。就是从该点出发引一条射线,看这条射线和所有边的交点数目。如果有奇数个交点,则说明在内部,如果有偶数个交点,则说明在外部。这是所有方法中计算量最小的方法,在光线追踪算法中有大量的应用。

在C#中的话,有一个Region类,可以直接调用IsVisible判断是否在这个区域内部,我估计内部的实现应该是上面说的第三种方法。主要看你的需求是哪种输入了,如果在C#中,你完全可以用Region类来隐藏内部实现。

C#判断点的位置的另外一种解决方法:

1.已知点point(x,y)和多边形Polygon(x1,y1;x2,y2;….xn,yn;);

2.以point为起点,以无穷远为终点作平行于X轴的直线line(x,y; -∞,y);

3.循环取得(for(i=0;i< n;i++))多边形的每一条边side(xi,yi;xi+1,yi+1),且判断是否平行于X轴,如果平行continue,否则,i++;

4. 同时判断point(x,y)是否在side上,如果是,则返回1(点在多边形

上),否则继续下面的判断;

5.判断线side与line是否有交点,如果有则count++,否则,i++。

6.判断交点的总数,如果为奇数则返回0(点在多边形内),偶数则返回2(点在多边形外)。

代码:

  1. /* 射线法判断点q与多边形polygon的位置关系,要求polygon为简单多边形,顶点逆时针排列  
  2.  
  3. 如果点在多边形内: 返回0  
  4.  
  5. 如果点在多边形边上: 返回1  
  6.  
  7. 如果点在多边形外: 返回2  
  8.  
  9. */ 
  10.  
  11. const double INFINITY = 1e10;  
  12.  
  13. const double ESP = 1e-5;  
  14.  
  15. const int MAX_N = 1000;  
  16.  
  17.  
  18. struct Point {  
  19.  
  20. double x, y;  
  21.  
  22. };  
  23.  
  24. struct LineSegment {  
  25.  
  26. Point pt1, pt2;  
  27.  
  28. };  
  29.  
  30. typedef vector< Point> Polygon;  
  31.  
  32.  
  33. // 计算叉乘 |P0P1| × |P0P2|  
  34.  
  35. double Multiply(Point p1, Point p2, Point p0)  
  36.  
  37. {  
  38.  
  39. return ( (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y) );  
  40.  
  41. }  
  42.  
  43. // 判断线段是否包含点point  
  44.  
  45. bool IsOnline(Point point, LineSegment line)  
  46.  
  47. {  
  48.  
  49. return( ( fabs(Multiply(line.pt1, line.pt2, point)) <  ESP ) &&  
  50.  
  51. ( ( point.x - line.pt1.x ) * ( point.x - line.pt2.x ) < = 0 ) &&  
  52.  
  53. ( ( point.y - line.pt1.y ) * ( point.y - line.pt2.y ) < = 0 ) );  
  54.  
  55. }  
  56.  
  57. // 判断线段相交  
  58.  
  59. bool Intersect(LineSegment L1, LineSegment L2)  
  60.  
  61. {  
  62.  
  63. return( (max(L1.pt1.x, L1.pt2.x) >= min(L2.pt1.x, L2.pt2.x)) &&  
  64.  
  65. (max(L2.pt1.x, L2.pt2.x) >= min(L1.pt1.x, L1.pt2.x)) &&  
  66.  
  67. (max(L1.pt1.y, L1.pt2.y) >= min(L2.pt1.y, L2.pt2.y)) &&  
  68.  
  69. (max(L2.pt1.y, L2.pt2.y) >= min(L1.pt1.y, L1.pt2.y)) &&  
  70.  
  71. (Multiply(L2.pt1, L1.pt2, L1.pt1) * Multiply(L1.pt2, L2.pt2, L1.pt1) >= 0) &&  
  72.  
  73. (Multiply(L1.pt1, L2.pt2, L2.pt1) * Multiply(L2.pt2, L1.pt2, L2.pt1) >= 0)  
  74.  
  75. );  
  76.  
  77. }  
  78.  
  79. // 判断点在多边形内  
  80.  
  81. bool InPolygon(const Polygon& polygon, Point point)  
  82.  
  83. {  
  84.  
  85. int n = polygon.size();  
  86.  
  87. int count = 0;  
  88.  
  89. LineSegment line;  
  90.  
  91. line.pt1 = point;  
  92.  
  93. line.pt2.y = point.y;  
  94.  
  95. line.pt2.x = - INFINITY;  
  96.  
  97.  
  98. forint i = 0; i <  n; i++ ) {  
  99.  
  100. // 得到多边形的一条边  
  101.  
  102. LineSegment side;  
  103.  
  104. side.pt1 = polygon[i];  
  105.  
  106. side.pt2 = polygon[(i + 1) % n];  
  107.  
  108.  
  109. if( IsOnline(point, side) ) {  
  110.  
  111. return1 ;  
  112.  
  113. }  
  114.  
  115.  
  116. // 如果side平行x轴则不作考虑  
  117.  
  118. if( fabs(side.pt1.y - side.pt2.y) <  ESP ) {  
  119.  
  120. continue;  
  121.  
  122. }  
  123.  
  124.  
  125. if( IsOnline(side.pt1, line) ) {  
  126.  
  127. if( side.pt1.y > side.pt2.y ) count++;  
  128.  
  129. else if( IsOnline(side.pt2, line) ) {  
  130.  
  131. if( side.pt2.y > side.pt1.y ) count++;  
  132.  
  133. else if( Intersect(line, side) ) {  
  134.  
  135. count++;  
  136.  
  137. }  
  138.  
  139. }  
  140.  
  141.  
  142. if ( count % 2 == 1 ) {return 0;}  
  143.  
  144. else { return 2;}  
  145.  
  146. }  
  147.  

【编辑推荐】

  1. C#代码与#函数相互调用问题集锦
  2. 如何使用泛型达到代码重用的目的
  3. 线性链表测试方法简介
  4. 创建一个简单的线性链表
  5. C#事件模型的一个实例
责任编辑:book05 来源: cnblogs
相关推荐

2017-09-18 08:53:28

编程语言ERP补丁管理

2021-12-14 11:42:49

勒索软件恶意软件安全

2009-08-28 15:38:49

C#实现断点续传

2009-09-23 09:36:34

C#数组

2022-03-06 20:02:21

监听视频播放

2021-08-30 07:49:32

Javascript西瓜视频

2009-09-09 10:32:12

C# CheckBox

2009-08-17 07:58:00

C#删除文件目录

2024-01-15 00:40:43

C#Java编译器

2009-09-07 05:40:16

C#窗体位置C#窗体大小

2009-09-01 18:35:53

C#判断文件存在

2010-11-08 15:47:01

SQL Server外

2010-11-11 13:51:36

SQL Server内

2009-08-25 17:15:50

C#隐藏C#重写C#重载

2018-07-26 08:36:35

Azure Funct编程Chef

2009-09-02 18:28:00

C#鼠标位置

2018-04-13 06:46:43

无服务器单元测试IT云

2024-04-02 09:26:07

C#中文数字编程语言

2013-05-16 15:08:33

2009-09-03 18:55:08

C#判断浏览器
点赞
收藏

51CTO技术栈公众号