Math 网格中的矩形-我需要边缘案例方面的帮助

Math 网格中的矩形-我需要边缘案例方面的帮助,math,language-agnostic,lua,Math,Language Agnostic,Lua,我试图解决的问题如下: In a 2-D space, Given a grid size and a rectangle, calculate the grid cells occupied (partially or totally) by the rectangle. “网格大小”的意思是“16x16网格”或“32x32网格”。所有栅格均以坐标原点(0,0)为中心 矩形由4个浮点数定义:左侧、顶部、宽度和高度 此操作的结果始终为矩形。我想返回左上角单元格的坐标(即0,0),然后返回重角向

我试图解决的问题如下:

In a 2-D space, Given a grid size and a rectangle, calculate the grid cells
occupied (partially or totally) by the rectangle.
“网格大小”的意思是“16x16网格”或“32x32网格”。所有栅格均以坐标原点(0,0)为中心

矩形由4个浮点数定义:左侧、顶部、宽度和高度

此操作的结果始终为矩形。我想返回左上角单元格的坐标(即0,0),然后返回重角向右和向下占据的单元格数量(有点像宽度和高度,但对于单元格)

到目前为止,我已经能够编写出一个基本有效的算法。它首先要做的是计算网格中单个点所在的单元坐标。然后,给定矩形,我计算它的左上角和右下角在网格上的位置,然后它是一个简单的减法:

-- given a world coordinate, return the coordinates of the cell that would contain it
local function _toGrid(wx, wy)
  return math.floor(wx / __cellSize), math.floor(wy / __cellSize)
end

-- given a box in world coordinates, return a box in grid coordinates that contains it
-- returns the x,y coordinates of the top-left cell, the number of cells to the right and the number of cells down.
local function _toGridBox(l, t, w, h)
  local gl,gt = _toGrid(l, t)      -- top left grid corner
  local gr,gb = _toGrid(l+w, t+h)  -- bottom-right grid corner
  return gl, gt, gr-gl+1, gb-gt+1  -- return top,left,cells to the right, cells to bottom
end
注:

  • 源代码是Lua,但我接受任何编程语言的解决方案,只要它们是可理解的
  • y坐标“增加时下降”;许多屏幕系统就是这样工作的。我不认为这对这个问题有什么意义,但请不要对此感到困惑)
在16x16网格中,0,0上的矩形,宽度
为10,高度
为20,
gr
将为0,而
gt
1,因此
\u toGrid
将返回0,0,1,2(0,0单元格上有一行两列)

当矩形从内部“接触”(而不是交叉)一个单元格的下方或右侧时,就会出现问题。在这种情况下,
\u toGrid
返回的单元格比我希望的多“一个”

例如,如果我将上一个矩形向左移动6个像素(因此它位于10,0),它将“接触”其包含网格的左侧边界,从0到16。然后
gr
将为1,返回的数据将为0,0,2,2

如果可能的话,我想避免这种情况。对于一个从左边到16英寸的矩形,我希望它保持在第一个网格单元上。我希望它一旦超过16就开始“占据下一个单元格”——例如,当它达到16.00000001时

另外,请注意,这仅适用于右侧和底部。左边和上面的工作,因为我希望他们。例如,坐标为16的矩形应显示在“右侧的第二个单元格”上,而不是第一个单元格上


我确信解决方案并不复杂,但我已经思考了一段时间,似乎没有找到它。任何帮助都将不胜感激。

对于底部和右侧,您需要使用
ceil
而不是
floor
。我不知道任何Lua,所以这在语法上可能不正确,但您可能希望遵循以下几点:

local function _toGridBox(l, t, w, h)
  local gl = math.floor(l / _cellSize)
  local gt = math.floor(t / _cellSize)
  local gr = math.ceil((l+w) / _cellSize)
  local gb = math.ceil((t+h) / _cellSize)
  return gl, gt, gr-gl, gb-gt  -- return top,left,cells to the right, cells to bottom
end

从本质上讲,您的问题在于函数
\u toGrid
对于您的目的来说是错误的抽象,因为它总是使用
地板
。显然,您将自己锁定在使用该抽象中,这使您很难找到正确的答案。

对于底部和右侧,您需要使用
ceil
而不是
floor
。我不知道任何Lua,所以这在语法上可能不正确,但您可能希望遵循以下几点:

local function _toGridBox(l, t, w, h)
  local gl = math.floor(l / _cellSize)
  local gt = math.floor(t / _cellSize)
  local gr = math.ceil((l+w) / _cellSize)
  local gb = math.ceil((t+h) / _cellSize)
  return gl, gt, gr-gl, gb-gt  -- return top,left,cells to the right, cells to bottom
end

从本质上讲,您的问题在于函数
\u toGrid
对于您的目的来说是错误的抽象,因为它总是使用
地板
。显然,你将自己锁定在使用这种抽象概念上,这使得你很难找到正确的答案。

为什么这个问题上有四种不同的语言标签?@Nicolas-“我接受任何编程语言的解决方案”对,但这并不能解释为什么你只调用了其他三种语言。我们有“任何语言”问题的标签;它被称为“语言不可知论”
@nicolasbolas,这很公平。我已经重新标记了这个问题(顺便说一句,你可以自己做)为什么否决票?这是我见过的写得最好的问题之一……为什么这个问题上有四个不同的语言标签?@Nicolas-“我接受任何编程语言的解决方案”对,但这并不能解释为什么你只调用了其他三种语言。我们有“任何语言”问题的标签;它被称为“语言不可知论”
@nicolasbolas,这很公平。我已经重新标记了这个问题(顺便说一句,你可以自己做)为什么否决票?这是我看过的最好的书面问题之一,所以…嗨,谢谢你的回答。你说得对,我被“精神禁锢”了。我尝试过你的解决方案(做了一些小改动,我希望你不介意我编辑一下你的答案),它似乎工作得很好。今晚我会做更多的测试,如果我看不到更多的问题,我会接受你的答案。@kikito没有关于编辑的问题,相反,这是我的想法。很高兴它有帮助!在我的主程序上尝试了一下,似乎成功了。再次感谢!嗨,谢谢你的回答。你说得对,我被“精神禁锢”了。我尝试过你的解决方案(做了一些小改动,我希望你不介意我编辑一下你的答案),它似乎工作得很好。今晚我会做更多的测试,如果我看不到更多的问题,我会接受你的答案。@kikito没有关于编辑的问题,相反,这是我的想法。很高兴它有帮助!在我的主程序上尝试了一下,似乎成功了。再次感谢!