在尝试此问题之前,我已尝试到处寻找问题的解决方案。我的问题是我对数学或统计学不太了解,以便了解任何给定的算法对解决方案都有帮助。
在我的例子中,我看起来像散点图。在笛卡尔坐标平面上随机放置了一堆点。我希望能够在这个平面上绘制一个具有特定半径的圆。 圆圈必须包含可能的最大点数。
我应该采取哪些步骤来计算绘制圆圈的最佳点?
我希望我必须采取一系列步骤,以便弄清楚我应该开始绘制的图形(圆圈的中心点)。如果你有代码,我很擅长破译我不一定知道的语言,但我会在Lua中写这个(不幸的是我无法访问C部分)。
我真的想了解解决方案是如何运作的,所以我要感谢任何来源或解释。仅仅为了您的信息,性能非常重要,但我现在正在寻找任何解决方案。
由于我写这篇文章,我想我还可以问一下我希望我的代码能够执行的其他高级功能。但是当我真正踏上门时,我总能想出这些。
距离圆心更远的点比距离更近的点更接近全重。重量可以简单地是线性函数,其中如果半径是10,则距离中心1仅为全重的10%,并且距离中心2,仅为全重的20%。距离中心10分钟将为您提供100%的重量。
引入时间,圆的中心也是图形上的一个点(此点不是其他点的一部分,不应使用它们计算)。圆心以恒定速度移动,你必须选择一个足够靠近中心的点,因为所有点的所有重量随时间衰减。所以绘制圆圈的速度越快越好。 (这是高度理论化的,我不确定衰变会是什么样的。)
非常感谢您阅读本文并考虑我的问题!我可以提供额外的详细信息或回答您可能遇到的任何问题。
答案 0 :(得分:1)
有一种更快的方法可以找到需要更多数学的最佳圆,并延伸到两个精确点中的第一个。
选择一个覆盖您感兴趣区域的网格,并在此网格中放置1,在此处绘制一个点,将0放在您没有的位置。您现在需要计算网格中每个点的分数。您可以通过将网格中每个点的值乘以一个权重来实现这一点,该权重取决于该点距离您得分的点数,然后将结果相加。这涵盖了您的基本问题(圆圈内的点的权重为1,否则为0)和第一个高级点,其中权重的变化更为渐进。
以这种方式查看问题,您需要一个二维过滤器,您需要将其应用于网格。应用它之后,您只需要在结果中找到最高得分点。以明显的方式执行此操作将非常缓慢,但事实证明,您可以使用快速傅立叶变换来加快这种速度,并且您可以使用数学库来计算它。
如果你没有练习数学或统计学,那么你需要对此进行一个很好的解释 - 比我能做的更好,我很害怕。它完成了很多,但我还没有找到我真正喜欢的解释。您可以查看http://www.analog.com/static/imported-files/tech_docs/dsp_book_Ch24.pdf,http://archive.gamedev.net/archive/reference/programming/features/imageproc/page2.html中也引用了{{3}}。
答案 1 :(得分:0)
这需要大量的计算/数据,但你可以检查每一点,看看点是否在那里。 不是真正的数学,但它的工作......也不是很快。
我不知道您使用什么引擎来测试代码,但我使用的是LOVE2D。如果不是用于可视化您的解决方案的游戏制作,我强烈推荐它。你可以使用别的东西,这只是个人偏好。如果您对任何LOVE功能有疑问,请访问wiki on the love2d website.
function love.load()
points = { { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) }, { math.random( 0, love.graphics.getWidth() ), math.random( 0, love.graphics.getHeight() ) } }
circles = {}
for i = 0, love.graphics.getWidth() do
for ii = 0, love.graphics.getHeight() do
table.insert( circles, { hits = check_points( i, ii, 20, points ), x = i, y = ii } )
end
end
circs = { { circles[1].hits, circles[1].x, circles[1].y } }
largest = circs[1][1]
for i = 1, #circles do
if circles[i].hits >= largest then
if circles[i].hits > largest then
circs = nil
circs = {}
table.insert( circs, { circles[i].hits, circles[i].x, circles[i].y } )
largest = circs[1][1]
elseif circles[i].hits == largest then
local distance = math.sqrt( ( circles[i].x - circs[#circs][2] ) ^ 2 + ( circles[i].y - circs[#circs ][3] ) ^ 2 )
if distance > 40 then
table.insert( circs, { circles[i].hits, circles[i].x, circles[i].y } )
largest = circs[1][1]
end
end
end
end
end
function love.draw()
love.graphics.setColor( 255, 0, 0 )
for i = 1, #circs do
love.graphics.circle( 'fill', circs[i][2], circs[i][3], 20 )
end
love.graphics.setColor( 255, 255, 255 )
for i = 1, #points do
love.graphics.circle( 'fill', points[i][1], points[i][2], 1 )
end
end
function check_points( x, y, r, ... )
local hits = 0
local p = ...
for i = 1, #p do
local distance = math.sqrt( ( x - p[i][1] ) ^ 2 + ( y - p[i][2] ) ^ 2 )
if distance <= r then
hits = hits + 1
end
end
return hits
end
如果有人有更好,更有时间的解决方案,我想知道。我调查了一些事情,但没有真正奏效。
请注意,这个获得所有可能的分组,而不是圆圈。如果您想获得所有圈子,请删除
elseif circles[i].hits == largest then
local distance = math.sqrt( ( circles[i].x - circs[#circs][2] ) ^ 2 + ( circles[i].y - circs[#circs ][3] ) ^ 2 )
if distance > 40 then
table.insert( circs, { circles[i].hits, circles[i].x, circles[i].y } )
largest = circs[1][1]
end
end
并将其替换为
else
table.insert( circs, { circles[i].hits, circles[i].x, circles[i].y } )
largest = circs[1][1]
end
如果你想获得第一个或最后一个,你可以拿出整个
if circles[i].hits >= largest then
if circles[i].hits > largest then
circs = nil
circs = {}
table.insert( circs, { circles[i].hits, circles[i].x, circles[i].y } )
largest = circs[1][1]
elseif circles[i].hits == largest then
local distance = math.sqrt( ( circles[i].x - circs[#circs][2] ) ^ 2 + ( circles[i].y - circs[#circs ][3] ) ^ 2 )
if distance > 40 then
table.insert( circs, { circles[i].hits, circles[i].x, circles[i].y } )
largest = circs[1][1]
end
end
end
并将其替换为
if circles[i].hits >= largest then
circs = nil
circs = {}
table.insert( circs, { circles[i].hits, circles[i].x, circles[i].y } )
largest = circs[1][1]
end
大于或等于会让你获得最后一个,更大的会让你获得第一个。 你可以建立更多,比如让它选择中间而不是左边的圆圈,或类似的东西。但同样,这不是一个真正的算法,而是更多的“扫描和检查”之类的东西。它始终是最佳解决方案,但是......
您还可以将for循环更改为.5或.25或其他内容。你获得的越小,你获得的精确度就越高,而且所需的时间也就越多。