| 12
 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
 
 | -module(a_sweep_trace2).-export([
 generate_route/8
 , generate_route/7
 , generate_route/5
 , expand_points/2
 ]).
 
 %% 八个方向  走九宫格
 -define(EXPAND_POINTS_8(X, Y), [
 {X - 1, Y}, {X - 1, Y - 1},
 {X, Y - 1}, {X + 1, Y - 1},
 {X + 1, Y}, {X + 1, Y + 1},
 {X, Y + 1}, {X - 1, Y + 1}
 ]).
 
 %% 六个方向  走六宫格(地图为蜂窝六边形)
 -define(EXPAND_POINTS_6(X, Y), [
 {X, Y + 1}, {X + 1, Y},
 {X + 1, Y - 1}, {X, Y - 1},
 {X - 1, Y}, {X - 1, Y + 1}
 ]).
 
 %% 四个方向  走十字
 -define(EXPAND_POINTS_4(X, Y), [
 {X - 1, Y}, {X + 1, Y},
 {X, Y + 1}, {X, Y - 1}
 ]).
 
 %% 障碍物
 -define(BLOCKS, [{3, 4}, {4, 3}, {3, 2}, {1, 2}]).
 
 
 %% 扩展查找的点
 -record(point, {
 x = 0 :: integer(),   %% 当前点位X
 y = 0 :: integer(),   %% 当前点位Y
 g = 0 :: integer(),   %% G = 走过的步数
 h = 0 :: integer(),   %% H = 曼哈顿距离
 f = 0 :: integer(),   %% F = G + H
 p_x = 0 :: integer(), %% 前一个位置
 p_y = 0 :: integer()  %% 前一个位置
 }).
 
 expand_points(X, Y) ->
 ?EXPAND_POINTS_4(X, Y).
 
 -define(DEBUG(F), io:format("##[~w~w:~w] " ++ F ++ "~n", [self(), ?MODULE, ?LINE])).
 -define(DEBUG(F, A), io:format("##[~w~w:~w] " ++ F ++ "~n", [self(), ?MODULE, ?LINE | A])).
 
 %% a_sweep_trace2:generate_route(1,3,5,2,1).
 
 %% [{2,3},{3,3},{4,3},{4,2},{5,2}] 没有墙
 %% [{2,3},{2,2},{2,1},{3,1},{4,1},{4,2},{5,2}] 有墙
 generate_route(StartX, StartY, TargetX, TargetY, SceneId) ->
 generate_route(StartX, StartY, TargetX, TargetY, SceneId, 50, 50).
 
 generate_route(StartX, StartY, TargetX, TargetY, SceneId, MaxTraceRangeX, MaxTraceRangeY) ->
 generate_route(StartX, StartY, TargetX, TargetY, SceneId, MaxTraceRangeX, MaxTraceRangeY, 0).
 
 generate_route(StartX, StartY, TargetX, TargetY, SceneId, MaxTraceRangeX, MaxTraceRangeY, Flying) ->
 %% 初始化开始点坐标
 CostH = calculate_cost(StartX, StartY, TargetX, TargetY),
 CostG = 0,
 OpenPoints = [#point{x = StartX, y = StartY, g = CostG, h = CostH, f = CostG + CostH}],
 %% 目标点坐标
 case search(OpenPoints, [], #point{x = TargetX, y = TargetY}, SceneId, MaxTraceRangeX, MaxTraceRangeY, Flying) of
 false ->
 false;
 {Point, ResultOpenPoints, ResultClosePoints} ->
 Solution = generate_solution(Point, [], ResultClosePoints ++ ResultOpenPoints),
 PosList = [{LX, LY} || #point{x = LX, y = LY} <- Solution],
 PosList
 end.
 
 %% 查找目标点
 %% param: OpenPoints 扩充列表,closePoints 已遍历列表,TargetPoint 目标点
 search([], _ClosePoints, _TargetPoint, _SceneId, _MaxTraceRangeX, _MaxTraceRangeY, _Flying) ->
 false;
 search(OpenPoints, ClosePoints, TargetPoint, SceneId, MaxTraceRangeX, MaxTraceRangeY, Flying) ->
 ?DEBUG("OpenPoints:~p end", [OpenPoints]),
 [Point | NewOpenPoints] = lists:keysort(#point.f, OpenPoints),
 NewClosePoints = [Point | ClosePoints],
 case is_target(Point, TargetPoint) of
 true ->
 {Point, NewOpenPoints, NewClosePoints};
 false ->
 %% 未找到,
 AddOpenPoints = expand(NewOpenPoints, NewClosePoints, Point, TargetPoint, SceneId, MaxTraceRangeX, MaxTraceRangeY, Flying),
 %% 坐标点扩充
 search(AddOpenPoints ++ NewOpenPoints, NewClosePoints, TargetPoint, SceneId, MaxTraceRangeX, MaxTraceRangeY, Flying)
 end.
 
 %% 坐标点扩充
 expand(OpenPoints, ClosePoints, #point{x = X, y = Y, g = G}, #point{x = TargetX, y = TargetY}, SceneId, MaxTraceRangeX, MaxTraceRangeY, Flying) ->
 CostG = G + 1,
 lists:foldl(fun({X1, Y1}, AccIn) ->
 case is_blocked(X1, Y1, TargetX, TargetY, SceneId, MaxTraceRangeX, MaxTraceRangeY, Flying) of
 true ->
 AccIn;
 false ->
 case lists:any(fun(#point{x = OpentX, y = OpentY}) ->
 (OpentX == X1 andalso OpentY == Y1) end, OpenPoints) of
 false ->
 case lists:any(fun(#point{x = CloseX, y = CloseY}) ->
 (CloseX == X1 andalso CloseY == Y1) end, ClosePoints) of
 false ->
 CostH = calculate_cost(X1, Y1, TargetX, TargetY),
 [#point{x = X1, y = Y1, g = CostG, h = CostH, f = CostH + CostG, p_x = X, p_y = Y} | AccIn];
 true ->
 %% 已在 close 列表 中不加
 AccIn
 end;
 true ->
 %% 已在 opent 列表 中不加
 AccIn
 end
 end
 end, [], ?EXPAND_POINTS_4(X, Y)).
 
 %% 生成结果列表
 generate_solution(Point = #point{p_x = X, p_y = Y}, SolutionPoints, Points) ->
 %% 找到终点前面的格子A 找到格子A前面的格子B 找到格子B前面的格子C
 PPoints = [Info || Info = #point{x = X2, y = Y2} <- Points, X2 == X, Y2 == Y],
 case PPoints of
 [] ->
 SolutionPoints;
 [One] ->
 generate_solution(One, [Point | SolutionPoints], lists:delete(One, Points));
 [NewPoint | _] = Tmp ->
 %% 一般来说不会走到这里来
 ?DEBUG("Tmp:~p end", [Tmp]),
 generate_solution(NewPoint, [Point | SolutionPoints], lists:delete(NewPoint, Points))
 end.
 
 %% 权重计算
 calculate_cost(X1, Y1, X2, Y2) ->
 ((X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2)).
 
 %% 是否到达目标点了,到达目标周围点就可以了
 is_target(#point{x = StartX, y = StartY}, #point{x = TargetX, y = TargetY}) ->
 StartX == TargetX andalso StartY == TargetY.
 %%	abs(StartX - TargetX) =< 1 andalso abs(StartY - TargetY) =<1.
 
 
 %% 检查是否是边界或者障碍物 {3,3},  {5,2}
 is_blocked(X, Y, TargetX, TargetY, _SceneId, MaxTraceRangeX, MaxTraceRangeY, _Flying) ->
 case abs(TargetX - X) > MaxTraceRangeX orelse
 abs(TargetY - Y) > MaxTraceRangeY of
 true ->
 %% 在查找范围外,作为阻档处理
 true;
 false ->
 %% 在查找范围内
 lists:member({X, Y}, ?BLOCKS)
 end.
 
 
 |