为了好玩,我写了这个。
-module(cluster).
-compile([export_all]).
-record(point, {x,y}).
-record(area, {x,y,w,h}).
area2points(A) ->
[#point{x=X,y=Y} ||
X <- lists:seq(A#area.x, A#area.x+ A#area.w-1),
Y <- lists:seq(A#area.y, A#area.y+ A#area.h-1)].
points2area([]) -> empty;
points2area(L) ->
lists:foldl(fun(P,Acc) -> fromcorner(P,Acc) end, area(),L).
area() -> #area{}.
area(X,Y,W,H) -> #area{x=X,y=Y,w=W,h=H}.
point() -> #point{}.
point(X,Y) -> #point{x=X,y=Y}.
fromcorner(#point{x=X,y=Y},#area{x=undefined,y=undefined}) ->
#area{x=X,y=Y,w=1,h=1};
fromcorner(#point{x=X,y=Y},#area{x=Xa,y=Ya,w=W,h=H}) ->
{Xmin,Wn} = case X < Xa of
true -> {X,Xa + W - X};
false -> {Xa,max(W, X+1-Xa)}
end,
{Ymin,Hn} = case Y < Ya of
true -> {Y,Ya + H - Y};
false -> {Ya,max(H, Y+1-Ya)}
end,
#area{x=Xmin,y=Ymin,w=Wn,h=Hn}.
split(A,L) ->
LA = area2points(A),
[points2area(lists:filter(fun(P) -> lists:member(P,LA) end ,area2points(X))) || X <- L].
test() ->
Z1 = area(1,1,3,3),
Z2 = area(4,1,3,3),
Z3 = area(7,1,3,3),
Z4 = area(1,4,3,3),
Z5 = area(4,4,3,3),
Z6 = area(7,4,3,3),
Z7 = area(1,7,3,3),
Z8 = area(4,7,3,3),
Z9 = area(7,7,3,3),
World = [Z1,Z2,Z3,Z4,Z5,Z6,Z7,Z8,Z9],
A = area(2,3,6,5),
split(A,World).
76> make:all().
Recompile: ../src/cluster
up_to_date
77> l(cluster).
{module,cluster}
78> cluster:test().
[{area,2,3,2,1},
{area,4,3,3,1},
{area,7,3,1,1},
{area,2,4,2,3},
{area,4,4,3,3},
{area,7,4,1,3},
{area,2,7,2,1},
{area,4,7,3,1},
{area,7,7,1,1}]
79>