gpt4 book ai didi

javascript - 尝试通过遍历循环来创建 x 个随机矩形 - 但没有重叠

转载 作者:行者123 更新时间:2023-12-01 16:16:19 24 4
gpt4 key购买 nike

这个让我难住了。这更像是一个数学/逻辑问题,然后是一个特定的 JS 问题,但我正在处理的是 JS,并且在某些时候我需要将生成的逻辑转换为代码....

我正在尝试在 Canvas 上创建 X 数量的非重叠矩形和/或随机大小的正方形,以实现类似于此示例图像的效果:

enter image description here

(我想要创建的盒子数量可以从 10 到 100 不等。显然需要的盒子越多,它们就必须越小)

我有一个 JS Fiddle我一直在尝试不同的想法,但这个问题的逻辑一直离我远去......

我不想要的是经典的斐波那契螺旋盒模式。我希望随机性能在某种程度上解决这个问题,但我也有想法,我可以每次搜索存储线的数组以找到最长的线,并从该线上的随机点开始。

我目前正尝试在随机点将 Canvas 切成两半,然后将该线添加到数组中。然后根据第一条线的坐标绘制另一条线,然后也存储该线,依此类推……我将坐标存储在这样的对象数组中:

function storeLine(startX, startY, endX, endY, array) {
array.push({
start : {
x: startX,
y: startY
},
end : {
x: endX,
y: endY
}
});
}

但我很快就遇到了问题,因为我在整个 x 轴上绘制的第一条线总是最长的线,而我只是得到了很多细框。

在一个完美的世界中,我的最终结果会包含诸如盒子总数和最小 x/y 比率这样的变量,这样我就可以(以某种方式>)选择倾向于更多纵向或更多横向盒子,这样我就可以调整并不断再生,直到我得到我喜欢的结果。

无论如何,我不知道如何继续,或者即使我走在正确的道路上。如果有人有关于继续我目前的道路的想法或更好的方法来解决这个问题,我将永远感激您!

注意:在检查了我的问题之后,我认为斐波那契盒模式可以作为起点,但不知何故我仍然需要制作更大的初始盒被分开,这样当我想要更多的盒子总数时,我不会一直得到越来越小的盒子……无论如何,只是一个随机的想法,如果它给其他人一个想法的 Spark 。

其他想法:Voronoi 模式也很棒,但我的数学技能甚至不知道从哪里开始

最佳答案

这主意不错!

您可以将其视为盒子中的盒子(也像树)。这些盒子有自己的坐标和大小。盒子可以在盒子里面,所以要做到这一点,你可以选择一个维度来分割(水平或垂直),然后分成任意多个盒子。然后在每个盒子中,您可以添加更多盒子,等等。最后,为了绘制线条,您只需为盒子配备绘制它们自己的能力(并告诉它们的盒子自己绘制)。

下面是一些执行此操作的 JS。你可以很容易地玩你想做多少嵌套。有点棘手并且可能需要一些调整的事情是确定如何将空间分成大致均匀的盒子(随机稍微不同)。我所做的将空间分成 n 框的方法是从可用空间的大小 1/n 开始,然后随机稍微微调它。如果您只使用 remaining*Math.random(),大多数情况下您最终会得到非常窄的框。

// probably play around with this to get better splitting
// maybe split near a mouse click
let splitDimension = (l, n) => {
let splits = [];
let remaining = l;
let x = 0;
for (let i=0; i<n-1; i++) {
let r = Math.random();
let seg = remaining * (1/n);
let s = seg + 0.75*(0.5-r)*seg
splits.push([x, s]);
x += s;
remaining -= s;
}
// add the last bit
splits.push([x, remaining])
return splits;
};
// the main idea
class Box {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.boxes = [];

}

draw(ctx) {
ctx.beginPath();
ctx.rect(this.x, this.y, this.w, this.h);
ctx.stroke();
this.boxes.forEach(box => {
box.draw(ctx)
});
}

addBoxes(n, dim) {
let splits;
if (dim == "x") {
// split on width
splits = splitDimension(this.w, n)
// turn the splits into new boxes
this.boxes = splits.map(([x,w]) => {
return new Box(this.x+x, this.y, w, this.h)
});
} else {
// split over height
splits = splitDimension(this.h, n);
this.boxes = splits.map(([y,h]) => {
return new Box(this.x, this.y+y, this.w, h);
})
}
}
}
let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
// let's make some boxes!
let bigBox = new Box(0,0,canvas.width,canvas.height);
bigBox.addBoxes(2, "y");
// now add boxes on boxes on boxes
bigBox.boxes.forEach(box => {
box.addBoxes(3, "x");
// also more boxes
box.boxes.forEach(boxBox => {
boxBox.addBoxes(2, "y");
});
});
// now draw the boxes!
bigBox.draw(ctx);

关于javascript - 尝试通过遍历循环来创建 x 个随机矩形 - 但没有重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63707669/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com