判断点是否在多边形内——射线法

  1 //判断射线与也线段是否相交, 相交返回1,不相交返回0,在边上返回-1
2 int IsIntersectant( CPoint ptStart, CPoint ptEnd, CPoint pd )
3 {
4 double tempx = 0;
5 double tempy = 0;
6 //记录多边形边的端点坐标;
7 double startx = ptStart.x;
8 double starty = ptStart.y;
9 double endx = ptEnd.x;
10 double endy = ptEnd.y;
11
12 double maxX = startx;
13 double minX = endx;
14 if (startx<endx)
15 {
16 minX = startx;
17 maxX = endx;
18 }
19
20 //保证开始点在下(y坐标大),作为下端点
21 if(starty<endy)
22 {
23 double temp=starty;
24 starty=endy;
25 endy=temp;
26 temp=startx;
27 startx=endx;
28 endx=temp;
29 }
30
31 //首先排除没有交点的情况
32 if((pd.y>starty && pd.y>endy) || (pd.y<starty && pd.y<endy)) //水平射线在该直线段的上下两端之外
33 {
34 return 0;
35 }
36 if(pd.x>startx && pd.x>endx) //水平射线的起点在该直线段的右边
37 {
38 return 0;
39 }
40
41 //如果是水平线段,在线段上返回-1,否则返回0
42 if (starty ==endy)
43 {
44 if (pd.x<=maxX&&pd.x>=minX)
45 {
46 return -1;
47 }
48 return 0;
49 }
50
51 //判断点pd是否是多边形边上的点,通过距离判断
52 tempx = pd.x - startx;
53 tempy = pd.y - starty;
54 double dStartToX = sqrt(tempx*tempx+tempy*tempy);
55
56 tempx = pd.x - endx;
57 tempy = pd.y - endy;
58 double dXToEnd = sqrt(tempx*tempx+tempy*tempy);
59
60 tempx = startx - endx;
61 tempy = starty - endy;
62 double dStarToEnd = sqrt(tempx*tempx+tempy*tempy);
63
64 if (dStarToEnd == (dStartToX + dXToEnd))
65 {
66 return -1;
67 }
68
69 //h_x记录点pd(x,y)引水平线与直线段所在直线的交点x坐标(直线坐标y=kx+b)
70 double h_x=(pd.y-starty)*(endx-startx)/(endy-starty)+startx;
71
72 if(pd.x>h_x)//pd点在交点的右边,则射线与线段不相交
73 {
74 return 0;
75 }
76 if(pd.y==starty) //水平射线与直线段的上端点相交,不计交点,只考虑与直线段的下端点相交
77 {
78 return 0;
79 }
80
81 return 1;
82
83 }
84 BOOL PtInPolygon( CPoint *ptList, int ptCount, CPoint pd )
85 {
86 if (ptCount<3)
87 {
88 return FALSE;
89 }
90
91 int cross_num = 0;
92 int iFlag = 0;
93 //从点pd,向右引水平射线
94
95 for(int i=0;i<ptCount-1;i++)
96 {
97 iFlag = IsIntersectant(ptList[i], ptList[i+1], pd);
98 if (iFlag < 0)
99 {
100 return TRUE;
101 }
102 else
103 {
104 cross_num += iFlag;
105 }
106 }
107
108 //末端点与首端点连接线
109 iFlag = IsIntersectant(ptList[ptCount-1], ptList[0], pd);
110 if (iFlag < 0)
111 {
112 return TRUE;
113 }
114 else
115 {
116 cross_num += iFlag;
117 }
118
119 if(cross_num%2==1) //交点个数为奇
120 {
121 return TRUE;
122 }
123 else if(cross_num%2==0) //交点个数为偶
124 {
125 return FALSE;
126 }
127
128 return FALSE;
129
130 }
原文地址:https://www.cnblogs.com/hbf369/p/2281559.html