我正在研究算法,正在寻找最佳的解决方案,以找到网格中可以添加矩形的所有位置。
我编写了简单的测试:
test('Based on layout elements getting highlighting positions where we can drop element', () => {
const layoutElements = [
{
row: 3,
column: 2,
width: 2,
height: 1,
},
{
row: 3,
column: 4,
width: 1,
height: 3,
},
{
row: 4,
column: 1,
width: 1,
height: 2,
},
];
const highlightingPositions = getHighlightingLayoutDropPositions({
draggedElWidth: 2,
draggedElHeight: 2,
layoutWidth: 4,
layoutHeight: 5,
layoutElements
});
expect(highlightingPositions.length).toEqual(12);
});
可视化将是:
强力解决方案将是遍历每个单元并检查N x M的范围,其中| M是拖动元素的大小。有没有人有更好的方法呢?有什么例子吗?
答案 0 :(得分:1)
根据我先前对该问题的评论,使用第二个答案在Bin Packing Js implementation using box rotation for best fit处的算法,您可以将所有空块都喂入堆,然后运行unionAll
获得可用的矩形单元格块区域。 (请注意,x1 / y1坐标表示(x1-x0),而(y1-y0)表示要定义的单元/块的大小)。使用问题中的可视化内容作为示例数据,使用所有可用的单个单元格填充堆,然后调用“ unionAll” ...
x = new Packer(4,5);
x.heap = [{x0:1, y0:1, x1:2, y1:2}, // All are w:1, h:1
{x0:2, y0:1, x1:3, y1:2},
{x0:3, y0:1, x1:4, y1:2},
{x0:4, y0:1, x1:5, y1:2},
{x0:1, y0:2, x1:2, y1:3},
{x0:2, y0:2, x1:3, y1:3},
{x0:3, y0:2, x1:4, y1:3},
{x0:4, y0:2, x1:5, y1:3},
{x0:1, y0:3, x1:2, y1:4},
{x0:2, y0:4, x1:3, y1:5},
{x0:2, y0:5, x1:3, y1:6},
{x0:3, y0:4, x1:4, y1:5},
{x0:3, y0:5, x1:4, y1:6}]
x.unionAll();
console.log(x);
...导致堆减少到...
heap: Array(3)
0: {x0: 1, y0: 1, x1: 5, y1: 3} // w:4, h:2
1: {x0: 1, y0: 1, x1: 2, y1: 4} // w:1, h:3
2: {x0: 2, y0: 4, x1: 4, y1: 6} // w:2, h:2
...表示可用的单元格块。请注意,heap [0]和heap [1]重叠,因为该算法只是查找要使用的最大可用矩形区域。
然后,如果您打算将元素放入网格中,并且需要知道还剩下哪些单元格,则可以使用adjustHeap
方法重新计算可用空间。假设您从第3列第2行开始添加了一个大小为2个水平单元格的矩形,从上方继续...
x.adjustHeap({x0:3, y0:2, x1:5, y1:3}); // w:2, h:1
console.log(x);
..导致...的堆...
heap: Array(4)
0: {x0: 1, y0: 1, x1: 2, y1: 4} // w:1, h:3
1: {x0: 2, y0: 4, x1: 4, y1: 6} // w:2, h:2
2: {x0: 1, y0: 1, x1: 5, y1: 2} // w:4, h:1
3: {x0: 1, y0: 1, x1: 3, y1: 3} // w:2, h:2
再次,请注意生成的矩形的重叠部分,因为此功能是为了简化寻找所需大小的矩形区域的过程。
一些注意事项:
Packer
中的所有功能都是必需的。Packer
界面的布局方式并不热衷,但是为了2D Bin Packer问题,通常将其保留原样。如果在我的一个项目中使用它,我会将其转换为一个类。 x0,y0,x1,y1
定义单元格的方式充满了兴趣。如果您重新设计算法以使用x,y
(单元格块的起源)和w,h
(单元格块的宽度和高度),则可能会更容易。