C\#기반 다각형 충돌 검출 실례
이전에 프로젝트 에서 다각형 충돌 검 측 문 제 를 만 났 는데 바 이 두,bing,google 을 통 해 현재 있 는 방안 을 발 견 했 습 니 다.장면 커버 가 완전 하지 않 거나 제3자 라 이브 러 리 를 통 해 이 루어 졌 거나(이런 제3자 라 이브 러 리 는 역 컴 파일 이 거의 불가능 합 니 다)프로젝트 에서 제3자 라 이브 러 리 를 사용 하 는 것 을 금지 하고 스스로 이 알고리즘 을 실현 하 였 습 니 다.
장면 은 이렇다.다각형 A 와 다 변형 B 가 두 개 있 는데 다각형 B 가 다 변형 A 안에 있 는 지,즉 다각형 B 가 다각형 A 의 자 다각형 인지 판단 해 야 한다.
B 의 점 은 모두 A 안에 있다A 의 점 은 모두 B 밖 에 있다A 의 선분 과 B 의 선분 은 교차 하지 않 았 다
이어서 실현 하 겠 습 니 다.
첫 번 째 단계:다각형 클래스 만 들 기
1 /// <summary>
2 ///
3 /// </summary>
4 public class Area_Dto
5 {
6 /// <summary>
7 ///
8 /// </summary>
9 public List<Point_Dto> Points { get; set; }
10 /// <summary>
11 ///
12 /// </summary>
13 public List<LineSagement_Dto> LineSagements { get; set; }
14 }
두 번 째 단계:점 클래스 만 들 기
1 /// <summary>
2 ///
3 /// </summary>
4 public class Point_Dto
5 {
6 public Point_Dto(double x, double y)
7 {
8 this.X = x;
9 this.Y = y;
10 }
11 /// <summary>
12 /// X
13 /// </summary>
14 public double X { get; private set; }
15 /// <summary>
16 /// Y
17 /// </summary>
18 public double Y { get; private set; }
19 }
세 번 째 단계:선분 류 만 들 기
1 /// <summary>
2 ///
3 /// </summary>
4 public class LineSagement_Dto
5 {
6 public LineSagement_Dto(Point_Dto start, Point_Dto end)
7 {
8 this.Start = start;
9 this.End = end;
10 GetFuncParam(this);
11 }
12 /// <summary>
13 ///
14 /// </summary>
15 public Point_Dto Start { get; private set; }
16 /// <summary>
17 ///
18 /// </summary>
19 public Point_Dto End { get; private set; }
20 /// <summary>
21 ///
22 /// </summary>
23 public LineType_Enum FunType { get; set; }
24 /// <summary>
25 ///
26 /// Y
27 /// </summary>
28 public List<double> Params { get; set; } = new List<double>();
29 /// <summary>
30 ///
31 /// </summary>
32 public List<Point_Dto> Intersection { get; set; } = new List<Point_Dto>();
33
34 /// <summary>
35 /// , , Y
36 /// </summary>
37 public void GetFuncParam(LineSagement_Dto lineSegment)
38 {
39 double x1 = this.Start.X;
40 double y1 = this.Start.Y;
41 double x2 = this.End.X;
42 double y2 = this.End.Y;
43
44 if (x1 == x2)
45 {
46 //type=2
47 this.FunType = LineType_Enum.XX;
48 this.Params.Add(x1);
49
50 }
51 else if (y1 == y2)
52 {
53 //type=1
54 this.FunType = LineType_Enum.YY;
55 this.Params.Add(y1);
56 }
57 else
58 {
59 //type=3
60 this.FunType = LineType_Enum.XnXYnY;
61 double a = (y2 - y1) / (x2 - x1);//
62 double b = y1 - (x1 * ((y2 - y1) / (x2 - x1)));// Y
63 this.Params.Add(a);
64 this.Params.Add(b);
65 }
66
67 }
68 }
네 번 째 단계:선분 을 만 드 는 형식 매 거 진
/// <summary>
///
/// </summary>
public enum LineType_Enum
{
/// <summary>
///
/// </summary>
XX,
/// <summary>
///
/// </summary>
YY,
/// <summary>
///
/// </summary>
XnXYnY
}
다섯 번 째 단계:다각형 클래스 에 충돌 검출 방법 추가
1 /// <summary>
2 ///
3 /// </summary>
4 public bool CheckIfInArea(Area_Dto area)
5 {
6 if (area.LineSagements == null)
7 {
8 return true;
9 }
10 //
11 foreach (Point_Dto point in this.Points)
12 {
13 if (!point.CheckIfInArea(area))
14 return false;
15 }
16 //
17 foreach (Point_Dto point in area.Points)
18 {
19 if (point.CheckIfInChildArea(this))
20 return false;
21 }
22 //
23 if (WhetherPolygonIntersection(area))
24 {
25 foreach (LineSagement_Dto edg in this.LineSagements)
26 {
27 if (edg.Intersection.Any())
28 {
29 if (edg.FunType == LineType_Enum.XX)
30 {
31 List<Point_Dto> jiaodainList = edg.Intersection.OrderBy(m => m.Y).ToList();
32 for (int i = 0; i < jiaodainList.Count - 1; i++)
33 {
34 Point_Dto start = jiaodainList[i];
35 Point_Dto end = jiaodainList[i + 1];
36 Point_Dto z = new Point_Dto(start.X, start.Y + ((end.Y - start.Y) / 2));
37 if (z.CheckIfInArea(area))
38 {
39 continue;
40 }
41 else
42 {
43 return false;
44 }
45 }
46 }
47 else if (edg.FunType == LineType_Enum.YY)
48 {
49 List<Point_Dto> jiaodainList = edg.Intersection.OrderBy(m => m.X).ToList();
50 for (int i = 0; i < jiaodainList.Count - 1; i++)
51 {
52 Point_Dto start = jiaodainList[i];
53 Point_Dto end = jiaodainList[i + 1];
54 Point_Dto z = new Point_Dto(start.X + ((end.X - start.X) / 2), start.Y);
55 if (z.CheckIfInArea(area))
56 {
57 continue;
58 }
59 else
60 {
61 return false;
62 }
63 }
64 }
65 else if (edg.FunType == LineType_Enum.XnXYnY)
66 {
67 if (edg.Start.Y <= edg.End.Y)
68 {
69 List<Point_Dto> jiaodainList = edg.Intersection.OrderBy(m => m.X).ThenBy(m => m.Y).ToList();
70 for (int i = 0; i < jiaodainList.Count - 1; i++)
71 {
72 Point_Dto start = jiaodainList[i];
73 Point_Dto end = jiaodainList[i + 1];
74 Point_Dto z = new Point_Dto(start.X + ((end.X - start.X) / 2), start.Y + ((end.Y - start.Y) / 2));
75 if (z.CheckIfInArea(area))
76 {
77 continue;
78 }
79 else
80 {
81 return false;
82 }
83 }
84 }
85 else
86 {
87 List<Point_Dto> jiaodainList = edg.Intersection.OrderBy(m => m.X).ThenByDescending(m => m.Y).ToList();
88 for (int i = 0; i < jiaodainList.Count - 1; i++)
89 {
90 Point_Dto start = jiaodainList[i];
91 Point_Dto end = jiaodainList[i + 1];
92 Point_Dto z = new Point_Dto(start.X + ((end.X - start.X) / 2), start.Y - ((start.Y - end.Y) / 2));
93 if (z.CheckIfInArea(area))
94 {
95 continue;
96 }
97 else
98 {
99 return false;
100 }
101 }
102 }
103 }
104 }
105 }
106 }
107 else
108 {
109 return true;
110 }
111 return true;
112 }
STEP 6:점 의 클래스 에 점 과 선분 관 계 를 추가 하 는 판단 방법
1 /// <summary>
2 /// sagement
3 /// :
4 /// sagement
5 /// sagement
6 /// sagement
7 /// </summary>
8 /// <param name="sagement"></param>
9 /// <returns>True: False: </returns>
10 public PointWithLineSagementState_Enum CheckPointInLineSagement(LineSagement_Dto sagement)
11 {
12 double px = this.X;
13 double py = this.Y;
14 //bool flag = false;
15
16
17 Point_Dto pi = sagement.Start;
18 Point_Dto pj = sagement.End;
19 double sx = pi.X; double sy = pi.Y;
20 double tx = pj.X; double ty = pj.Y;
21
22 //
23 bool psTf = (px == sx && py == sy);
24 bool ptTf = (px == tx && py == ty);
25 if (psTf || ptTf)
26 {
27 return PointWithLineSagementState_Enum.VertexOverlap;
28 }
29 switch (sagement.FunType)
30 {
31 case LineType_Enum.XX:
32 if (px == pi.X && ((py <= sy && py >= ty) || (py >= sy && py <= ty)))
33 return PointWithLineSagementState_Enum.OnLineSagement;
34 break;
35 case LineType_Enum.YY:
36 if (py == pi.Y && ((px >= sx && px <= tx) || (px <= sx && px >= tx)))
37 return PointWithLineSagementState_Enum.OnLineSagement;
38 break;
39 case LineType_Enum.XnXYnY:
40 default:
41 break;
42 }
43 //
44 if ((sy < py && ty >= py) || (sy >= py && ty < py))
45 {
46 // Y X
47 double x = sx + (py - sy) * (tx - sx) / (ty - sy);
48 //
49 if (x == px)
50 {
51 return PointWithLineSagementState_Enum.OnLineSagement;
52 }
53 //
54 if (x > px)
55 {
56 return PointWithLineSagementState_Enum.Cross;
57 }
58 }
59 return PointWithLineSagementState_Enum.UnCross;
60 }
61
62 /// <summary>
63 ///
64 /// </summary>
65 public enum PointWithLineSagementState_Enum
66 {
67 /// <summary>
68 ///
69 /// </summary>
70 VertexOverlap,
71 /// <summary>
72 ///
73 /// </summary>
74 Cross,
75 /// <summary>
76 ///
77 /// </summary>
78 UnCross,
79 /// <summary>
80 ///
81 /// </summary>
82 OnLineSagement
83 }
STEP 7:점 의 클래스 에서 자 다각형 을 실현 하 는 점 이 부모 다각형 내 에 있 는 지 판단 하 는 방법
1 /// <summary>
2 ///
3 /// </summary>
4 /// <param name="theArea"> </param>
5 /// <param name="vertexOverlap"> , . </param>
6 /// <returns></returns>
7 public bool CheckIfInArea(Area_Dto theArea)
8 {
9 int cnt = 0;
10 foreach (LineSagement_Dto lineSagement in theArea.LineSagements)
11 {
12 switch (CheckPointInLineSagement(lineSagement))
13 {
14 case PointWithLineSagementState_Enum.Cross:
15 cnt += 1;
16 break;
17 case PointWithLineSagementState_Enum.OnLineSagement:
18 return true;
19 case PointWithLineSagementState_Enum.VertexOverlap:
20 return true;
21 case PointWithLineSagementState_Enum.UnCross:
22 default:
23 break;
24 }
25 }
26 //
27 if (cnt % 2 == 1)
28 {
29 return true;//
30 }
31 else
32 {
33 return false;//
34 }
35 }
STEP 8:점 의 클래스 에서 부 다각형 을 실현 하 는 점 이 자 다각형 내 에 있 는 지 판단 하 는 방법
1 /// <summary>
2 ///
3 /// </summary>
4 /// <param name="theArea"></param>
5 /// <returns></returns>
6 public bool CheckIfInChildArea(Area_Dto theArea)
7 {
8 int cnt = 0;
9 foreach (LineSagement_Dto lineSagement in theArea.LineSagements)
10 {
11 switch (CheckPointInLineSagement(lineSagement))
12 {
13 case PointWithLineSagementState_Enum.Cross:
14 cnt += 1;
15 break;
16 case PointWithLineSagementState_Enum.OnLineSagement:
17 return false;
18 case PointWithLineSagementState_Enum.VertexOverlap:
19 return false;
20 case PointWithLineSagementState_Enum.UnCross:
21 default:
22 break;
23 }
24 }
25 //
26 if (cnt % 2 == 1)
27 {
28 return true;//
29 }
30 else
31 {
32 return false;//
33 }
34 }
9 단계:다각형 클래스 에서 다각형 자체 의 선분 이 다른 다각형 의 모든 선분 과 교차 하 는 방법 을 실현 합 니까?
1 /// <summary>
2 ///
3 /// True:
4 /// False:
5 /// </summary>
6 public bool WhetherPolygonIntersection(Area_Dto father)
7 {
8 List<LineSagement_Dto> childEdgeXfatherEdge_List = new List<LineSagement_Dto>();
9 foreach (LineSagement_Dto edg in this.LineSagements)
10 {
11 Point_Dto a = edg.Start;
12 Point_Dto b = edg.End;
13 foreach (LineSagement_Dto fatherEdge in father.LineSagements)
14 {
15 Point_Dto c = fatherEdge.Start;
16 Point_Dto d = fatherEdge.End;
17
18 double denominator = (b.Y - a.Y) * (d.X - c.X) - (a.X - b.X) * (c.Y - d.Y);
19 // 0 ,
20 if (denominator == 0)
21 {
22 //
23 if (edg.FunType == LineType_Enum.XX)
24 {
25 //
26 if (edg.Start.X == fatherEdge.Start.X)
27 {
28 //
29 if (b.Y > c.Y || a.Y < d.Y)
30 {
31 continue;
32 }
33 //
34 if (a.Y == c.Y && b.Y == d.Y)
35 {
36 continue;
37 }
38 // ( )
39 if (a.Y > c.Y && b.Y <= c.Y && b.Y >= d.Y)
40 {
41 edg.Intersection.Add(c);
42 continue;
43 }
44 // ( )
45 if (a.Y <= c.Y && a.Y >= d.Y && b.Y < d.Y)
46 {
47 edg.Intersection.Add(d);
48 continue;
49 }
50 //
51 if (c.Y >= a.Y && d.Y <= b.Y)
52 {
53 continue;
54 }
55 //
56 if (a.Y >= c.Y && b.Y <= d.Y)
57 {
58 edg.Intersection.Add(c);
59 edg.Intersection.Add(d);
60 continue;
61 }
62 }
63 //
64 else
65 {
66 continue;
67 }
68 }
69
70 //
71 else if (edg.FunType == LineType_Enum.YY)
72 {
73 //
74 if (edg.Start.Y == fatherEdge.Start.Y)
75 {
76 //
77 if (b.X < c.X || a.X > d.X)
78 {
79 continue;
80 }
81 //
82 if (a.X == c.X && b.X == d.X)
83 {
84 continue;
85 }
86 // ( )
87 if (a.X < c.X && b.X >= c.X && b.X <= d.X)
88 {
89 edg.Intersection.Add(c);
90 continue;
91 }
92 // ( )
93 if (b.X > d.X && a.X >= c.X && a.X <= d.X)
94 {
95 edg.Intersection.Add(d);
96 continue;
97 }
98 //
99 if (c.X <= a.X && d.X >= b.X)
100 {
101 continue;
102 }
103 //
104 if (a.X <= c.X && b.X >= d.X)
105 {
106 edg.Intersection.Add(c);
107 edg.Intersection.Add(d);
108 continue;
109 }
110 }
111 //
112 else
113 {
114 continue;
115 }
116 }
117 //
118 else if (edg.FunType == LineType_Enum.XnXYnY)
119 {
120 //
121 if (edg.Params.First().Equals(fatherEdge.Params.First()) && edg.Params.Last().Equals(fatherEdge.Params.Last()))
122 {
123 //
124 if ((a.X < c.X && b.X < c.X)
125 || (a.X > d.X && b.X > d.X))
126 {
127 continue;
128 }
129 //
130 if (a.X == c.X && a.Y == c.Y && b.X == d.X && b.Y == d.Y)
131 {
132 continue;
133 }
134 // ( )
135 if (a.X < c.X && b.X >= c.X && b.X <= d.X)
136 {
137 edg.Intersection.Add(c);
138 continue;
139 }
140 // ( )
141 if (a.X >= c.X && a.X <= d.X && b.X > d.X)
142 {
143 edg.Intersection.Add(d);
144 continue;
145 }
146 //
147 if (a.X >= c.X && a.X <= d.X && b.X >= c.X && b.X <= d.X)
148 {
149 continue;
150 }
151 //
152 if (a.X <= c.X && b.X >= d.X)
153 {
154 edg.Intersection.Add(c);
155 edg.Intersection.Add(d);
156 continue;
157 }
158 }
159 //
160 else
161 {
162 continue;
163 }
164 }
165 }
166 // (x , y)
167 double x = ((b.X - a.X) * (d.X - c.X) * (c.Y - a.Y)
168 + (b.Y - a.Y) * (d.X - c.X) * a.X
169 - (d.Y - c.Y) * (b.X - a.X) * c.X) / denominator;
170 double y = -((b.Y - a.Y) * (d.Y - c.Y) * (c.X - a.X)
171 + (b.X - a.X) * (d.Y - c.Y) * a.Y
172 - (d.X - c.X) * (b.Y - a.Y) * c.Y) / denominator;
173 //
174 if (
175 // 1
176 (x - a.X) * (x - b.X) <= 0 && (y - a.Y) * (y - b.Y) <= 0
177 // 2
178 && (x - c.X) * (x - d.X) <= 0 && (y - c.Y) * (y - d.Y) <= 0)
179 {
180 edg.Intersection.Add(new Point_Dto(x, y));
181 }
182 else
183 {
184 continue;
185 }
186 }
187 }
188 if (this.LineSagements.Where(m => m.Intersection.Any()).Any())
189 {
190 return true;
191 }
192 else
193 {
194 return false;
195 }
196 }
총결산C\#를 기반 으로 한 다각형 충돌 감지 기 사 를 소개 합 니 다.더 많은 C\#다각형 충돌 감지 내용 은 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C#Task를 사용하여 비동기식 작업을 수행하는 방법라인이 완성된 후에 이 라인을 다시 시작할 수 없습니다.반대로 조인(Join)만 결합할 수 있습니다 (프로세스가 현재 라인을 막습니다). 임무는 조합할 수 있는 것이다. 연장을 사용하여 그것들을 한데 연결시키는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.