你要求的,你得到它
我有一个小提琴 here,它可能会进行近乎最佳的平铺。
不过,这太丑了。
这让我想起了我的一些客户坚持涉足详细规格而不是停留在功能要求级别:)。
算法的核心在这里:
compute: function ()
{
function try_size (x1, x2, y1, y2, w, h, y)
{
var d = Math.sqrt((this.w+this.h)/this.n);
var delta = 10*d;
var n = 0;
while ((delta > 1e-12) || (n < this.n))
{
var res = {};
if (y < (d/2-this.d))
{
res.x1 = res.x2 = res.y1 = 0;
res.y2 = Math.floor ((h-y-this.d)/d);
res.c1 = true;
}
else if (y > (h-d+2*this.d))
{
res.x1 = res.x2 = res.y2 = 0;
res.y1 = Math.floor ((y-this.d)/d);
res.c2 = true;
}
else
{
res.y1 = Math.floor((y1-d/2)/d);
res.y2 = Math.floor((y2-d/2)/d);
res.x1 = Math.floor ((x1-this.d/2)/d);
res.x2 = Math.floor ((x2-this.d/2)/d);
}
res.w = Math.floor ((w+this.d)/d);
n = res.x1+res.x2+res.w*(res.y1+res.y2);
d += n > this.n ? delta : -delta;
if (delta > 1e-12) delta /=2;
}
res.d = d;
res.s = d-2*this.d;
return res;
}
这个想法是定期平铺矩形,除了中心点周围的带。此带的水平和垂直变体被尝试保留最大的正方形大小。
我猜一个最佳解决方案不会使乐队围绕中心点居中,但鉴于结果看起来很糟糕,我认为这不值得:)
(只是一个概念证明;一些边缘情况处理不当)。
compute: function ()
{
var d = Math.sqrt((this.w+this.h)/this.n);
var delta = 100*d;
while ((delta > 1e-12) || (res.n < this.n))
{
var res = {};
res.x = Math.floor ((this.w-this.x%d)/d);
res.y = Math.floor ((this.h-this.y%d)/d);
res.n = res.x * res.y;
d += res.n > this.n ? delta : -delta;
if (delta > 1e-12) delta /=2;
}
res.d = d;
res.s = d-2*this.d;
res.a = 0;
this.res = res;
},
移动参考点仍然会导致正方形大小摆动。
不过,作为图形效果可能会很有趣。