AStart.cs
7.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
namespace CtuDeviceLib
{
public class AStart
{
static ILog log = Mushiny.Common.LOGGER;
List<AStartPoint> CloseList;
List<AStartPoint> OpenList;
public const int OBLIQUE = 14;
public const int STEP = 10;
CTUBean pathPlan;
public AStart(CTUBean pathPlan)
{
this.pathPlan = pathPlan;
OpenList = new List<AStartPoint>();
CloseList = new List<AStartPoint>();
}
public AStartPoint FindPath(AStartPoint start, AStartPoint end, List<AStartPoint> barrierPoints = null)
{
OpenList = new List<AStartPoint>();
CloseList = new List<AStartPoint>();
OpenList.Add(start);
while (OpenList.Count != 0)
{
//找出F值最小的点
var tempStart = OpenList.MinPoint();
OpenList.Remove(tempStart);
CloseList.Add(tempStart);
//找出它相邻的点
var surroundPoints = SurrroundPoints(tempStart, barrierPoints);
foreach (AStartPoint point in surroundPoints)
{
if (OpenList.Exists(point))
//计算G值, 如果比原来的大, 就什么都不做, 否则设置它的父节点为当前点,并更新G和F
FoundPoint(tempStart, point);
else if (!CloseList.Exists(point))
//如果它们不在开始列表里, 就加入, 并设置父节点,并计算GHF
NotFoundPoint(tempStart, end, point);
}
if (OpenList.Get(end) != null)
return OpenList.Get(end);
}
return OpenList.Get(end);
}
private void FoundPoint(AStartPoint tempStart, AStartPoint point)
{
var G = CalcG(tempStart, point);
if (G < point.G)
{
point.ParentPoint = tempStart;
point.G = G;
point.CalcF();
}
log.Debug($"寻路算法-在开始列表:{point.Id}");
}
private void NotFoundPoint(AStartPoint tempStart, AStartPoint end, AStartPoint point)
{
point.ParentPoint = tempStart;
point.G = CalcG(tempStart, point);
point.H = CalcH(end, point);
point.CalcF();
OpenList.Add(point);
log.Debug($"寻路算法-{tempStart.Id}->{point.Id}不在开始列表,{point.Id} G=【{point.G}】");
}
private int CalcG(AStartPoint start, AStartPoint point)
{
var dis = start.Landmark.GetDis(point.Id);
// int G = (Math.Abs(point.X - start.X) + Math.Abs(point.Y - start.Y)) == 2 ? STEP : OBLIQUE;
int parentG = point.ParentPoint != null ? point.ParentPoint.G : 0;
return dis + parentG;
}
private int CalcH(AStartPoint end, AStartPoint point)
{
int step = Math.Abs(point.X - end.X) + Math.Abs(point.Y - end.Y);
return step * STEP;
}
/// <summary>
/// 获取某个点周围可以到达的点
/// </summary>
/// <param name="point"></param>
/// <param name="barrierPoints">不可走的点</param>
/// <returns></returns>
public List<AStartPoint> SurrroundPoints(AStartPoint point, List<AStartPoint> barrierPoints)
{
var surroundPoints = new List<AStartPoint>();
if (point.Landmark.Above != null)
{
var p = new AStartPoint(pathPlan.GetPointCode(point.Landmark.Above.Id));
if (!barrierPoints.HasBarrier(p) && pathPlan.IsTwoWay(point.Id, point.Landmark.Above.Id))
surroundPoints.Add(p);
}
if (point.Landmark.Right != null)
{
var p = new AStartPoint(pathPlan.GetPointCode(point.Landmark.Right.Id));
if (!barrierPoints.HasBarrier(p) && pathPlan.IsTwoWay(point.Id, point.Landmark.Right.Id))
surroundPoints.Add(p);
}
if (point.Landmark.Below != null)
{
var p = new AStartPoint(pathPlan.GetPointCode(point.Landmark.Below.Id));
if (!barrierPoints.HasBarrier(p) && pathPlan.IsTwoWay(point.Id, point.Landmark.Below.Id))
surroundPoints.Add(p);
}
if (point.Landmark.Left != null)
{
var p = new AStartPoint(pathPlan.GetPointCode(point.Landmark.Left.Id));
if (!barrierPoints.HasBarrier(p) && pathPlan.IsTwoWay(point.Id, point.Landmark.Left.Id))
surroundPoints.Add(p);
}
return surroundPoints;
}
}
public class AStartPoint
{
public uint Id { get { return Landmark.Id; } }
public AStartPoint ParentPoint { get; set; }
public int F { get; set; } //F=G+H
public int G { get; set; }
public int H { get; set; }
public int X { get { return Landmark.X; } }
public int Y { get { return Landmark.Y; } }
public PointCode Landmark { get; set; }
public AStartPoint(PointCode landmark)
{
Landmark = landmark;
}
public void CalcF()
{
this.F = this.G + this.H;
}
}
//对 List<Point> 的一些扩展方法
public static class ListHelper
{
public static bool Exists(this List<AStartPoint> points, AStartPoint point)
{
if (points == null || points.Count == 0) return false;
foreach (AStartPoint p in points)
if ((p.X == point.X) && (p.Y == point.Y))
return true;
return false;
}
/// <summary>
/// 是否有障碍
/// </summary>
/// <param name="points"></param>
/// <param name="point"></param>
/// <returns></returns>
public static bool HasBarrier(this List<AStartPoint> points, AStartPoint point)
{
if (point == null || point.Landmark == null)
{
return true;
}
if (points == null || points.Count == 0) return false;
foreach (AStartPoint p in points)
if (p.Landmark != null && p.Id == point.Landmark.Id)
return true;
return false;
}
public static AStartPoint MinPoint(this List<AStartPoint> points)
{
points = points.OrderBy(p => p.F).ToList();
return points[0];
}
public static AStartPoint Get(this List<AStartPoint> points, AStartPoint point)
{
foreach (AStartPoint p in points)
if ((p.X == point.X) && (p.Y == point.Y))
return p;
return null;
}
public static void Remove(this List<AStartPoint> points, int x, int y)
{
foreach (AStartPoint point in points)
{
if (point.X == x && point.Y == y)
points.Remove(point);
}
}
}
}