按预定义的栅格划分区域

时间:2013-04-05 15:32:24

标签: grid erlang

我有一个大网格(在图像上以灰色显示),分为几个块(每个块最大宽度为3个单位)。现在我想用相应的块划分一个区域(在网格上用红色表示)。

enter image description here

举个例子,我想要'阻挡区域'(代表{X,Y,宽度,高度}):

  • A:{2,3,2,1}
  • B:{4,3,3,1}
  • C:{7,3,1,1}
  • D:{2,4,2,3}
  • ...

我所拥有的唯一信息是网格中块的大小(在本例中为3)和区域的尺寸: {2,3,6,5}(= {X,Y,宽度,高度})

有人知道如何以有效的方式做到这一点吗?我想过使用mround来计算块的第一个边界,但这会导致死胡同。提前谢谢!

2 个答案:

答案 0 :(得分:1)

数学看起来有点奇怪,因为你从1,1开始,但这是它的要点,

  1. 分别找到X / Y轴的边界(可通过网格中的块大小划分的数字)
  2. 除了左/右/上/下方框
  3. 之外,所有尺寸都会阻挡,阻挡
  4. 查找这些特殊框的宽度/高度
  5. 将相应尺寸放置到相应的边界
  6. zip two lists
  7. -export([F / 2])。

    f({X,Y,Width, Height}, BlockSize) ->
        % all sizes will be Blocksize, Blocksize except  special cases 
        % left/right most will have Xfd/Xld
        % top/bottom most will have Yfd/Yld
        Xfd = BlockSize - ( ( X - 1) rem BlockSize) , 
        Xld = (X + Width - 1) rem BlockSize,
        Yfd = BlockSize - ( ( Y - 1) rem BlockSize) , 
        Yld = (Y + Height - 1) rem BlockSize,
    
        Xs = divs(X, Width, BlockSize, Xfd),
        Ys = divs(Y, Height, BlockSize, Yfd),
    
        %replace last values
        {Lx, _} = lists:last(Xs),
        Xss = lists:keyreplace(Lx, 1, Xs, {Lx, Xld}),
        {Ly, _} = lists:last(Ys),
        Yss = lists:keyreplace(Ly, 1, Ys, {Ly, Yld}),
    
        R = merge(Xss, Yss),
        io:format("~p~n", [R]).
    
    merge(X, Y) ->
        XY= lists:foldl(fun(Xx, Acc) ->
                lists:foldl(fun(Yy, Acc1) ->
                    [{Xx, Yy} | Acc1]
                 end, Acc, Y) 
        end, [], X),
        lists:map(fun({{Xx, W}, {Yy, H}}) ->
                {Xx, Yy, W, H} 
        end , XY).
    
    divs(X, W, BlockSize, Fd) ->
        R = [{X, Fd}  | [{Xs, BlockSize} || Xs<- lists:seq(X, X + W), (Xs - 1) rem BlockSize =:= 0]],
        lists:sort(sets:to_list(sets:from_list(R))).
    

    >[{7,7,1,1}, {7,4,1,3}, {7,3,1,1}, {4,7,3,1}, {4,4,3,3}, {4,3,3,1}, {2,7,2,1}, {2,4,2,3}, {2,3,2,1}]

答案 1 :(得分:1)

为了我写这篇文章的乐趣。

-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>