作者:生命的无言 | 来源:互联网 | 2022-11-18 19:50
我有一个基本代表一个屏幕的坐标系.
我有任意数量的职位.例如:
population = [
{x: 100.44, 200.54},
{x: 123.45, 678.9},
{x: 1300.23, 435.81},
{x: 462.23, 468.37},
{x: 956.58, 385.38},
];
我正在寻找一种找到最无人居住点的算法.
白色迷你圆圈代表人口和红色Xs标记点,对我来说似乎非常无人居住:
我的目标是运行一个动画,随机将所有这些白色迷你圆圈移动到随机方向,一旦圆圈离开屏幕,它就会被传送到最无人居住的地点,这样大空空间的数量就会减少.
我试图通过计算从每个整数坐标到每个圆的距离之和,然后选择具有最高距离和的坐标来实现这一点.仅此一点似乎已经非常耗费CPU,但我注意到这个算法会使圆圈传送到我的坐标系的边界.所以我还添加了从每个整数坐标到每个边界整数坐标的距离之和.那时,脚本基本上冻结了.所以这绝对不是正确的方法.
我的想法已经不多了.我想我不需要一个完美的算法,而是一个在精度和性能之间保持平衡的算法.最后,我希望能够在1920x1080画布上每秒多次运行该算法,其中大约有80个这样的小环.理想情况下,算法会有一个参数来调整精度,从而调整它使用的CPU时间.
这是我上面提到的方法.我注释掉导致脚本冻结的行:
let circles = [
{x: 60.44, y: 190.54},
{x: 103.45, y: 18.9},
{x: 390.23, y: 135.81},
{x: 302.23, y: 28.37},
{x: 56.58, y: 85.38},
]
function getDistance(p1, p2) {
return Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2)
}
function drawCircle(ctx,x,y,r,c) {
ctx.beginPath()
ctx.arc(x, y, r, 0, 2 * Math.PI, false)
ctx.fillStyle = c
ctx.fill()
}
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext("2d")
let highestDistanceSum = 0
let coordWithHighestDistanceSum
for (let x=0; x highestDistanceSum) {
coordWithHighestDistanceSum = canvasCoord
highestDistanceSum = distanceSum
}
}
}
for (let p of circles) {
drawCircle(ctx, p.x, p.y, 3, 'black')
}
drawCircle(ctx, coordWithHighestDistanceSum.x, coordWithHighestDistanceSum.y, 5, 'red')
1> AVAVT..:
(因为它是黑色画布上的白点,我会称之为白点星,以便于区分)
首先,您的解决方案似乎不符合您的标准.你不需要与所有恒星的距离最大的点.你需要距离它最近的恒星最远的点.
详细说来,比如说这样的情况,中心有一颗恒星,距离中心有一定距离的大量恒星:
"最大距离和"方法可能会在红色圆圈的某个位置给出一个点(它太靠近甚至与中心星重叠),而你想要的更像是绿色圆圈中的某些东西:
考虑到这一点:
首先,我们应该将屏幕划分为合理大小的正方形,我们将从这些正方形构建距离图,以找到与任何恒星距离最远的那个.
"合理大小"的部分在性能方面非常重要.您使用的是1920x1080分辨率,这在我看来太精细了.为了获得足够令人愉悦的结果,48x30甚至32x20的分辨率就足够了.
要实际构建距离图,我们可以简单地使用广度优先搜索.我们将所有星星的位置转换为网格坐标,并将其用作BFS的起始位置.
结果将是这样的:
这里还有一个很大的问题:最红的广场位于最底层!
边缘和角落方形比中心坐标具有"欺骗"优势,因为一侧没有星形(甚至是三角形,角形方块).因此角落和边缘正方形很可能与任何恒星的距离最大.
你的艺术作品在视觉上是不是很令人愉悦?所以我们可以通过过滤掉某个填充内的结果来作弊.幸运的是,BFS的结果默认排序,因此我们可以迭代结果,直到找到适合所需区域的结果.
以下是带注释的完整代码.即使可以看到距离图,整个过程也需要20ms,对于webgl片来说应该足够了(运行@ max 30fps~33ms /帧)
这个解决方案还将处理几个星星在同一帧移出界限的罕见情况.在这种情况下,只需从BFS的结果中获取几个不同的坐标.