erlang的a*寻路之双A*寻路

1. 先说下环境:
a.我们是slg大地图寻路,地图尺寸是10001000.
b.2D地图,没有高度的概念.
c.忽略人物模型大小,默认只要路径联通即能通过.
d.只做静态障碍的寻路(比如资源点,山脉河流等),不做动态障碍的寻路(玩家主城,怪物等)
2. 在说下大致思路:(请先看图)
在这里插入图片描述
a.将地图切分成50
50等大小的400个大格子(绿色的方格子,黑色的线条是山脉,河流等等障碍物)

	b.每个大格子根据情况,配置可以通过的路点(红色的空心点),预先计算好路点之间的距离.
	
			注意,不需要计算每个路点到其他所有路点之间的距离,值需要计算他附近几个连同的路点即可(主要是考虑到内存问题,如果忽略内存问题,此种方式可以大大提高寻路效率).
			
			服务器端只负责寻找出经过了那些路点,至于路点之间怎么走,是客户端的配置文件规定的.
			
	c.		假设需要从A点到F点,那么需要计算A点L1路点之间的具体路径,这部分使用A*寻路,
			路点L1到L7之间,也是用A*寻路,这部分就只是寻路大格子.
			L7到F之间,也使用A*寻路即可.
			总结一下,最坏的情况下采用三段寻路,两种A*,首位段采用具体坐标点的A*寻路,中间段采用A*大格子路点寻路.
			其他情况都是这种情况的子集,比如C到D,就是只有首段寻路,C到E是首位两段寻路.

3.上代码了
area_search.erl模块

%%%===================模块描述(开始)=====================
%% 寻路
%%%===================模块描述(结束)=====================
-module(area_search).
%%%=======================STATEMENT====================
-time("2018/8/24 10:45").
%%%=======================EXPORT=======================
-export([init_obstacles/0, search/4, a_star/4]).
%%%=======================INCLUDE======================
-include("../include/area_search.hrl").
%%%=======================RECORD=======================
%%%=======================DEFINE=======================
-define(PATH_LAYER, path_layer).
%%%=================EXPORTED FUNCTIONS=================
%% ----------------------------------------------------
%% 初始化各个区块的障碍点
%% ----------------------------------------------------
init_obstacles() ->
    {BMinX, BMaxX, BMinY, BMAxY} = map_lib:map_border(0),%获取地图的边界值:{X最小值,X最大值,Y最小值,Y最大值}
    area_search_lib:load_obstacles(BMinY div ?AREA_SIZE, BMinX div ?AREA_SIZE, BMaxX div ?AREA_SIZE, BMinY div ?AREA_SIZE, BMAxY div ?AREA_SIZE),
    area_search_lib:load_connect_mesh(),
    area_search_lib:load_mesh().
%% ----------------------------------------------------
%% 寻路
%% ----------------------------------------------------
search(FromX, FromY, TargetX, TargetY) ->
    {StartPath1, MidPath1, EndPath1} = case area_search_lib:check_layer(FromX, FromY, TargetX, TargetY) of
                                           0 ->%同区块,只计算当前区块的寻路
                                               {a_star(FromX, FromY, TargetX, TargetY), [], []};
                                           {{EnterX, EnterY}, {ExitX, ExitY}} ->%私有连接点
                                               {_, Mesh} = zm_config:get(?CFG_AREA_SEARCH, mesh),
                                               MidPath = area_mesh:search(Mesh, {EnterX, EnterY}, {ExitX, ExitY}),%中间段的路径
                                               {a_star(FromX, FromY, EnterX, EnterY), MidPath, a_star(ExitX, ExitY, TargetX, TargetY)};
                                           {EnterX, EnterY} when is_integer(EnterX) ->%通用连接点
                                               {a_star(FromX, FromY, EnterX, EnterY), [], a_star(EnterX, EnterY, TargetX, TargetY)}
                                       end,
    area_search_lib:init_path({FromX, FromY}, {TargetX, TargetY}, StartPath1, MidPath1, EndPath1).


%%%===================LOCAL FUNCTIONS==================
%% ----------------------------------------------------
%% 点位A*寻路
%% ----------------------------------------------------
a_star(FromX, FromY, TargetX, TargetY) ->
    erase(),%%清除该线程的数据字段数据
    case area_search_lib:near_points(FromX, FromY) of
        [] ->
            "no_path";
        Subs ->
            [begin
                 H = area_search_lib:get_h(PointX, PointY, TargetX, TargetY),
                 F = H + Weight,
                 Point = area_search_lib:init_point(PointX, PointY, FromX, FromY, F, H),
                 area_search_lib:put_open({PointX, PointY}, F, Point)
             end || {{PointX, PointY}, Weight} <- Subs],
            put({FromX, FromY}, area_search_lib:init_point(FromX, FromY, -1, -1)),
            [{FromX, FromY} | a_star_(TargetX, TargetY)]
    end.
a_star_(TargetX, TargetY) ->
    case area_search_lib:get_opens() of
        [] ->
            "point_not_connect";
        Opens ->
            FPoint = get({element(1, hd(Opens)), ?KEY_OPEN}),
            {FX, FY} = FPoint#point.point,
            case area_search_lib:check(TargetX, TargetY, FPoint, area_search_lib:near_points(FX, FY)) of
                {'end', Point} ->
                    area_search_lib:back(Point, [{TargetX, TargetY}]);
                'null' ->
                    case length(area_search_lib:get_opens()) > 0 of
                        true ->
                            put({FX, FY}, FPoint),
                            area_search_lib:del_open({FX, FY}),
                            a_star_(TargetX, TargetY);
                        _ ->
                            area_search_lib:back(FPoint, [{TargetX, TargetY}])
                    end
            end
    end.




area_mesh.erl模块


```java
%%%===================模块描述(开始)=====================
%% 网格寻路
%%%===================模块描述(结束)=====================
-module(area_mesh).
%%%=======================STATEMENT====================
-copyright('youkia,www.youkia.net').
-author('lb,lb@youkia.net').
-time("2020/3/25 16:47").
%%%=======================EXPORT=======================
-export([new/1, insert_vertex/3, add_edge/4, search/3, get_vertex/3]).
%%%=======================INCLUDE======================
-include("../include/area_search.hrl").
%%%=======================RECORD=======================
%%%=======================DEFINE=======================
%%%=================EXPORTED FUNCTIONS=================
%% ----------------------------------------------------
%% 新建网格
%% ----------------------------------------------------
new(Type) ->
    ets:new(?MODULE, [Type, {read_concurrency, true}]).
%% ----------------------------------------------------
%% 更新顶点
%% ----------------------------------------------------
insert_vertex(Ets, Vertex, V) ->
    ets:insert(Ets, {Vertex, V}).
%% ----------------------------------------------------
%% 获取顶点的值
%% ----------------------------------------------------
get_vertex(Ets, Vertex, Default) ->
    case ets:lookup(Ets, Vertex) of
        [] ->
            Default;
        [{_, V}] ->
            V
    end.
%% ----------------------------------------------------
%% 新增边
%% ----------------------------------------------------
add_edge(Ets, V1, V2, Weight) ->
    case ets:lookup(Ets, V1) of
        [] ->
            ets:insert(Ets, {V1, [{V2, Weight}]});
        [{_, L}] ->
            ets:insert(Ets, {V1, [{V2, Weight} | lists:keydelete(V2, 1, L)]})
    end.
%% ----------------------------------------------------
%% 网格寻路
%% ----------------------------------------------------
search(Ets, {FromX, FromY}, {TargetX, TargetY}) ->
    erase(),%%清除该线程的数据字段数据
    case area_search_lib:connect_point(Ets, {FromX, FromY}) of
        [] ->
            "mesh_no_path";
        Subs ->
            [begin
                 H = area_search_lib:get_h(PointX, PointY, TargetX, TargetY),
                 F = H + Weight,
                 area_search_lib:put_open({PointX, PointY}, F, area_search_lib:init_point(PointX, PointY, FromX, FromY, F, H))
             end || {{PointX, PointY}, Weight} <- Subs],
            put({FromX, FromY}, area_search_lib:init_point(FromX, FromY, -1, -1)),
            [{FromX, FromY} | search_(Ets, TargetX, TargetY)]
    end.
%%%===================LOCAL FUNCTIONS==================
%% ----------------------------------------------------
%% 最短路径
%% ----------------------------------------------------
search_(Ets, TargetX, TargetY) ->
    FPoint = get({element(1, hd(area_search_lib:get_opens())), ?KEY_OPEN}),
    {FX, FY} = FPoint#point.point,
    case area_search_lib:check(TargetX, TargetY, FPoint, area_search_lib:connect_point(Ets, {FX, FY})) of
        {'end', Point} ->
            area_search_lib:back(Point, [{TargetX, TargetY}]);
        'null' ->
            case length(area_search_lib:get_opens()) > 0 of
                true ->
                    put({FX, FY}, FPoint),
                    area_search_lib:del_open({FX, FY}),
                    search_(Ets, TargetX, TargetY);
                _ ->
                    'no_path_connect'
            end
    end.



area_search_lib.erl模块

%%%===================模块描述(开始)=====================
%% 区域寻路辅助方法
%%%===================模块描述(结束)=====================
-module(area_search_lib).
%%%=======================STATEMENT====================
-copyright('youkia,www.youkia.net').
-author('lb,lb@youkia.net').
-time("2019/8/1 16:34").
%%%=======================EXPORT=======================
-export([near_points/2, init_point/4, init_point/6, get_h/4, check_layer/4, distance/4, distance/2, init_path/5]).
-export([load_connect_mesh/0, load_mesh/0, load_obstacles/5, ets_name/2, get_layer/2]).
-export([put_open/3, get_opens/0, del_open/1, check/4, back/2, connect_point/2, xy_to_point/2]).
%%%=======================INCLUDE======================
-include("../include/area_search.hrl").
%%%=======================RECORD=======================
%%%=======================DEFINE=======================
%%%=================EXPORTED FUNCTIONS=================
%% ----------------------------------------------------
%% 加载每个区块的障碍点
%% ----------------------------------------------------
load_obstacles(StartY, X, MaxX, Y, MaxY) when Y >= MaxY ->
    if
        X >= MaxX ->
            Fun = fun
                      ({Point, _}) ->
                          PX = Point bsr 16,
                          PY = Point band ((1 bsl 16) - 1),
                          ets:insert(area_search_lib:ets_name(PX, PY), {{PX, PY}, 1})
                  end,
            lists:foreach(Fun, zm_config:get(map_path_obstacle_0));
        true ->
            load_obstacles(StartY, X + 1, MaxX, StartY, MaxY)
    end;
load_obstacles(StartY, X, MaxX, Y, MaxY) ->
    Ets = ets:new(ets_name(X * ?AREA_SIZE, Y * ?AREA_SIZE), [named_table, {read_concurrency, true}, public]),
    ets:insert(Ets, {?BORDER, {X * ?AREA_SIZE, (X + 1) * ?AREA_SIZE, Y * ?AREA_SIZE, (Y + 1) * ?AREA_SIZE}}),%写入区块的边界值
    load_obstacles(StartY, X, MaxX, Y + 1, MaxY).
%% ----------------------------------------------------
%% 加载连通图
%% ----------------------------------------------------
load_connect_mesh() ->
    %%连通矩阵配置文件
    case file:open(?FILE_ARRAY, [read]) of
        {ok, IO} ->
            Fun = fun
                      ({Y, IO1}) ->
                          case file:read_line(IO1) of
                              {ok, Line} ->
                                  zm_config:set(?CFG_AREA_SEARCH, {{Y, connect}, list_to_tuple([list_to_integer(S) || S <- string:tokens(hd(string:tokens(Line, "\n")), ",")])}),
                                  {Y + 1, IO1};
                              Other ->
                                  {break, Other}
                          end
                  end,
            z_lib:while(Fun, {0, IO});
        Error ->
            z_log:warn(?MODULE, ?FUNCTION_NAME, "_read_file_error", [Error])
    end,
    %%连通类型对应的连同点
    case file:open(?FILE_ENTER, [read]) of
        {ok, EnterIO} ->
            Fun2 = fun
                       (EnterIO1) ->
                           case file:read_line(EnterIO1) of
                               {ok, Line} ->
                                   [StrType, StrEnter] = string:tokens(Line, ":"),
                                   zm_config:set(?CFG_AREA_SEARCH, {{list_to_integer(StrType), ?ENTER},
                                                                    lists:sort([list_to_integer(S) || S <- string:tokens(hd(string:tokens(StrEnter, "\n")), ",")])}),
                                   EnterIO1;
                               Other ->
                                   {break, Other}
                           end
                   end,
            z_lib:while(Fun2, EnterIO);
        Error2 ->
            z_log:warn(?MODULE, ?FUNCTION_NAME, "enter_read_file_error", [Error2])
    end.
%% ----------------------------------------------------
%% 加载路点网格
%% ----------------------------------------------------
load_mesh() ->
    Mesh = area_mesh:new(protected),
    Fun2 = fun
               ({Point, Weight}) ->
                   Band = (1 bsl 16) - 1,
                   X1 = Point bsr (16 * 3),
                   Y1 = (Point bsr (16 * 2)) band Band,
                   X2 = (Point bsr (16 * 1)) band Band,
                   Y2 = Point band Band,
                   Ets = area_search_lib:ets_name(X1, Y1),
                   area_mesh:add_edge(Mesh, {X1, Y1}, {X2, Y2}, Weight),
                   area_mesh:add_edge(Mesh, {X2, Y2}, {X1, Y1}, Weight),
                   [begin
                        case ets:lookup(Ets, ?ENTER) of
                            [] ->
                                ets:insert(Ets, {?ENTER, [{X, Y}]});
                            [{_, L}] ->
                                ets:insert(Ets, {?ENTER, [{X, Y} | lists:delete({X, Y}, L)]})
                        end
                    end || {X, Y} <- [{X1, Y1}, {X2, Y2}]]
           end,
    lists:foreach(Fun2, zm_config:get(map_path_0)),
    zm_config:set(?CFG_AREA_SEARCH, {mesh, Mesh}).%找个地方缓存网格

%% ----------------------------------------------------
%% 初始化路径
%% ----------------------------------------------------
init_path({FromX, FromY}, {ToX, ToY}, StartPath, MidPath, EndPath) ->
    {BinStart, D1} = encode_points(StartPath),
    {BinEnd, D2} = encode_points(EndPath),
    MidPath1 = [xy_to_point(X, Y) || {X, Y} <- MidPath],
    pro_map:init_path(xy_to_point(FromX, FromY), xy_to_point(ToX, ToY), BinStart, BinEnd, MidPath1, D1 + D2).
%% ----------------------------------------------------
%% xy转坐标点
%% ----------------------------------------------------
xy_to_point(X, Y) ->
    (X bsl 16) bor Y.
%% ----------------------------------------------------
%% 路径回溯
%% ----------------------------------------------------
back(Point, Result) ->
    if
        Point#point.parent =:= {-1, -1} ->
            Result;
        true ->
            Parent = get(Point#point.parent),
            back(Parent, [Point#point.point | Result])
    end.
%% ----------------------------------------------------
%% 寻路检查
%% ----------------------------------------------------
check(_, _, _, []) ->
    'null';
check(TargetX, TargetY, Parent, [{{TargetX, TargetY}, _} | _]) ->
    {'end', Parent};
check(TargetX, TargetY, Parent, [{{X, Y}, Weight} | SubPoints]) ->
    case get({X, Y}) of
        undefined ->
            {ParentX, ParentY} = Parent#point.point,
            case get({{X, Y}, ?KEY_OPEN}) of
                undefined ->%%不在,计算GHF,存入开启列表中
                    H = area_search_lib:get_h(X, Y, TargetX, TargetY),
                    if
                        H == 0 ->
                            {'end', Parent};
                        true ->%存入open列表中
                            F = Parent#point.f + Weight + H,
                            put_open({X, Y}, F, area_search_lib:init_point(X, Y, ParentX, ParentY, F, H)),
                            check(TargetX, TargetY, Parent, SubPoints)
                    end;
                OldPoint ->%%在开启列表中,检查以当前节点为父节点,F是否更优
                    H = area_search_lib:get_h(X, Y, TargetX, TargetY),
                    if
                        H == 0 ->
                            {'end', Parent};
                        H < OldPoint#point.h ->
                            F = H + Parent#point.f + Weight,
                            put_open({X, Y}, F, OldPoint#point{f = F, h = H, parent = {ParentX, ParentY}}),
                            check(TargetX, TargetY, Parent, SubPoints);
                        true ->
                            check(TargetX, TargetY, Parent, SubPoints)
                    end
            end;
        _ ->%%关闭列表中忽略
            check(TargetX, TargetY, Parent, SubPoints)
    end.

%% ----------------------------------------------------
%%获取连接的点
%%==>[{point,weight},...]
%% ----------------------------------------------------
connect_point(Ets, Point) ->
    case ets:lookup(Ets, Point) of
        [] ->
            [];
        [{_, L}] ->
            L
    end.
%% ----------------------------------------------------
%%保存开放列表
%% ----------------------------------------------------
put_open(XY, F, Point) ->
    case put({XY, ?KEY_OPEN}, Point) of
        undefined ->
            put(?KEY_OPEN_LIST, lists:keysort(2, [{XY, F} | get_opens()]));
        _ ->
            put(?KEY_OPEN_LIST, lists:keysort(2, [{XY, F} | lists:keydelete(XY, 1, get_opens())]))
    end.
%% ----------------------------------------------------
%%获取开放列表(F值排序)
%% ----------------------------------------------------
get_opens() ->
    case get(?KEY_OPEN_LIST) of
        undefined ->
            [];
        L ->
            L
    end.
%% ----------------------------------------------------
%%从开放列表中删除坐标
%% ----------------------------------------------------
del_open(XY) ->
    case erase({XY, ?KEY_OPEN}) of
        undefined ->
            ok;
        _ ->
            put(?KEY_OPEN_LIST, lists:keydelete(XY, 1, get_opens()))
    end.
%% ----------------------------------------------------
%% 障碍ets表
%% ----------------------------------------------------
ets_name(X, Y) ->
    list_to_atom(lists:concat(["path_obstacles_", X div ?AREA_SIZE, "_", Y div ?AREA_SIZE])).

%% ----------------------------------------------------
%%  连通层级检查
%% ==>0(直接A*)|{X,Y}(通用连同点)|{{X,Y},{X,Y}}(私有连同点)
%% ----------------------------------------------------
check_layer(FromX, FromY, ToX, ToY) ->
    FromLayer = get_layer(FromX, FromY),
    ToLayer = get_layer(ToX, ToY),
    if
        FromLayer andalso ToLayer ->%连通层级相同,直接A*寻路
            0;
        true ->%连通层级不同,大格子寻路
            {_, FromEnters} = zm_config:get(?CFG_AREA_SEARCH, {FromLayer, ?ENTER}),
            {_, ToEnters} = zm_config:get(?CFG_AREA_SEARCH, {ToLayer, ?ENTER}),
            select_enter({FromX, FromY}, {ToX, ToY}, [point_to_xy(Point) || Point <- FromEnters], [point_to_xy(Point) || Point <- ToEnters])
    end.
%% ----------------------------------------------------
%%  计算h值
%% ----------------------------------------------------
get_h(X, Y, X, TargetY) ->%同一X坐标
    abs(Y - TargetY);
get_h(X, Y, TargetX, Y) ->%同一Y坐标
    abs(X - TargetX);
get_h(X, Y, TargetX, TargetY) ->%勾股定理算H值
    distance(X, Y, TargetX, TargetY).
%% ----------------------------------------------------
%%  获得一个节点的所有可用子节点及其权重
%%  ==>[{{X,Y},Weight},....]
%% ----------------------------------------------------
near_points(X, Y) ->
    Ets = area_search_lib:ets_name(X, Y),
    [{_, {XMin, XMax, YMin, YMax}}] = ets:lookup(Ets, ?BORDER),
    %得出当前坐标点周围八个点的坐标以及权重
    Points = [{X1 + X, Y1 + Y, W} || {X1, Y1, W} <- ?AROUND],
    near_points_(Ets, Points, XMin, XMax, YMin, YMax, []).
near_points_(_, [], _, _, _, _, Result) ->
    Result;
near_points_(Ets, [{X, Y, Weight} | Points], XMin, XMax, YMin, YMax, Result) ->
    case ets:lookup(Ets, {X, Y}) of
        [] ->%非障碍点
            if
                X < XMin orelse X >= XMax orelse Y < YMin orelse Y >= YMax ->
                    near_points_(Ets, Points, XMin, XMax, YMin, YMax, Result);
                true ->
                    near_points_(Ets, Points, XMin, XMax, YMin, YMax, [{{X, Y}, Weight} | Result])
            end;
        _ ->
            near_points_(Ets, Points, XMin, XMax, YMin, YMax, Result)
    end.

%% ----------------------------------------------------
%% 初始化一个坐标点
%% ----------------------------------------------------
init_point(X, Y, ParentX, ParentY) ->
    #point{point  = {X, Y},
           f      = 0,
           h      = 0,
           parent = {ParentX, ParentY}
    }.
%% ----------------------------------------------------
%% 初始化一个坐标点
%% ----------------------------------------------------
init_point(X, Y, ParentX, ParentY, F, H) ->
    #point{point  = {X, Y},
           f      = F,
           h      = H,
           parent = {ParentX, ParentY}
    }.
%%%===================LOCAL FUNCTIONS==================
%% ----------------------------------------------------
%%  获得层级
%% ----------------------------------------------------
get_layer(X, Y) ->
    {_, Array} = zm_config:get(?CFG_AREA_SEARCH, {Y, connect}),
    element(X + 1, Array).
%% ----------------------------------------------------
%%  距离计算
%% ----------------------------------------------------
distance({SX, XY}, {EX, EY}) ->
    distance(SX, XY, EX, EY).
distance(SX, XY, EX, EY) ->
    XV = abs(SX - EX),
    YV = abs(XY - EY),
    trunc(math:sqrt(XV * XV + YV * YV) * 15).
%% ----------------------------------------------------
%% 获得两个邻接大格子的出入口
%% ----------------------------------------------------
select_enter(From, To, List1, List2) ->
    case near_enter(From, To, List1, List2, [], [], []) of
        {FromDistance, ToDistance, []} ->
            {element(1, hd(lists:keysort(2, FromDistance))), element(1, hd(lists:keysort(2, ToDistance)))};
        {_, _, CommonDistance} ->
            element(1, hd(lists:keysort(2, CommonDistance)))
    end.
%%获得两个邻接大格子的出入口
near_enter(_, _, [], [], FromDistance, ToDistance, CommonDistance) ->
    {FromDistance, ToDistance, CommonDistance};
near_enter(From, To, [E | FromEnters], [E | ToEnter], FromDistance, ToDistance, CommonDistance) ->%有相同的入口
    near_enter(From, To, FromEnters, ToEnter, FromDistance, ToDistance, [{E, area_search_lib:distance(From, E) + area_search_lib:distance(To, E)} | CommonDistance]);
near_enter(From, To, [FE | FromEnters], [TE | ToEnter], FromDistance, ToDistance, CommonDistance) ->%有相同的入口
    if
        FE < TE ->
            near_enter(From, To, FromEnters, [TE | ToEnter], [{FE, area_search_lib:distance(From, FE) + area_search_lib:distance(To, FE)} | FromDistance],
                       ToDistance, CommonDistance);
        true ->
            near_enter(From, To, [FE | FromEnters], ToEnter, FromDistance,
                       [{TE, area_search_lib:distance(From, TE) + area_search_lib:distance(To, TE)} | ToDistance], CommonDistance)
    end;
near_enter(From, To, [], Enter, FromDistance, ToDistance, CommonDistance) ->
    R = [{E, area_search_lib:distance(From, E) + area_search_lib:distance(To, E)} || E <- Enter],
    {FromDistance, R ++ ToDistance, CommonDistance};
near_enter(From, To, Enter, [], FromDistance, ToDistance, CommonDistance) ->
    R = [{E, area_search_lib:distance(From, E) + area_search_lib:distance(To, E)} || E <- Enter],
    {R ++ FromDistance, ToDistance, CommonDistance}.


%将点位压缩成二进制
encode_points([]) ->
    {<<>>, 0};
encode_points([{X1, Y1} | Points]) ->
    encode_points({X1, Y1}, Points).

encode_points({X, Y}, [{X1, Y1} | Points]) ->
    {Direction, Weight} = direction(X1 - X, Y1 - Y),
    encode_points({X1, Y1}, Points, Direction, 1, <<>>, Weight).
encode_points(_, [], Direction, Times, Bin, SumWeight) ->
    {init_bin(Direction, Times, Bin), trunc(SumWeight)};
encode_points({X, Y}, [{X1, Y1} | Points], Direction, Times, Bin, SumWeight) ->
    {Direction1, Weight} = direction(X1 - X, Y1 - Y),
    if
        Direction1 =:= Direction ->
            encode_points({X1, Y1}, Points, Direction, Times + 1, Bin, SumWeight + Weight);
        true ->
            encode_points({X1, Y1}, Points, Direction1, 1, init_bin(Direction, Times, Bin), SumWeight + Weight)
    end.
%%[{-1, -1, 14}, {0, -1, 10}, {1, -1, 14}, {-1, 0, 10}, {1, 0, 10}, {-1, 1, 14}, {0, 1, 10}, {1, 1, 14}]
direction(XR, YR) when XR =:= -1 andalso YR =:= -1 ->%左下方
    {0, 14};
direction(XR, YR) when XR =:= 0 andalso YR =:= -1 ->%正下方
    {1, 10};
direction(XR, YR) when XR =:= 1 andalso YR =:= -1 ->%右下方
    {2, 14};
direction(XR, YR) when XR =:= -1 andalso YR =:= 0 ->%正左方
    {3, 10};
direction(XR, YR) when XR =:= 1 andalso YR =:= 0 ->%正右方
    {4, 10};
direction(XR, YR) when XR =:= -1 andalso YR =:= 1 ->%右上方
    {5, 14};
direction(XR, YR) when XR =:= 0 andalso YR =:= 1 ->%正上方
    {6, 10};
direction(XR, YR) when XR =:= 1 andalso YR =:= 1 ->%右上方
    {7, 17}.

init_bin(D, T, Bin) ->
    if
        T > 31 ->
            init_bin(D, T - 31, <<Bin/binary, <<31:5, D:3>>/binary>>);
        true ->
            <<Bin/binary, <<T:5, D:3>>/binary>>
    end.

point_to_xy(Point) ->
    {Point bsr 16,
     Point band 65535}.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值