在网格中的矩形 - 我需要边缘情况的帮助

我要解决的问题如下:

在二维空间中,给定网格大小和矩形,计算矩形占用的网格单元格(部分或全部)。

所谓“网格大小”,指的是“16x16网格”或“32x32网格”之类的东西。所有网格都以坐标原点(0,0)为中心。

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

该操作的结果始终为矩形。我想返回左上角单元格(即0,0)的坐标,其后是矩形向右和向下所占的单元格数(有点像宽度和高度,但是针对单元格)

到目前为止,我已经能够编写一个大部分有效的算法。首先,它会计算单个点位于网格中的单元格坐标。然后,给定矩形,我计算其左上和右下角在网格上的位置,然后进行简单的减法:

- 给定一个世界坐标,返回包含其的单元格的坐标 
local function _toGrid(wx, wy)
  return math.floor(wx / __cellSize), math.floor(wy / __cellSize)
end

- 给定世界坐标中的矩形,返回包含它的网格坐标的矩形 
- 返回左上角单元格的x、y坐标,向右和向下所占的单元格数。
local function _toGridBox(l, t, w, h)
  local gl,gt = _toGrid(l, t)      -- 左上角网格坐标
  local gr,gb = _toGrid(l+w, t+h)  -- 底部右侧网格坐标
  return gl, gt, gr-gl+1, gb-gt+1  -- 返回左上,右边的单元格数,下面的单元格数
end

注:

  • 源代码是Lua,但是我将接受任何编程语言的解决方案,只要它们是可理解的。
  • 当增加时,y坐标会“向下”,这是很多屏幕系统的工作方式。我认为这对于这个问题并不重要,但不要因此而感到困惑)。

在16x16网格中,一个矩形位于0,0,width=10和height=20, gr将为0, gt将为1,所以_toGrid将返回0,0,1,2(在0,0单元格上的1行两列)。

当矩形从内部“接触”(而不是穿过)单元格的下部或右部时,问题出现了。在这种情况下, _toGrid返回的单元格比我想要的多“一个”。

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

如果可能的话,我想尽量避免这种情况。对于从左侧到16的矩形,我希望它仍然停留在第一个网格单元格上。一旦超过16,例如当它在16.00000001时,我希望它开始“占用下一个单元格”。

此外,请注意,这仅适用于右侧和底部。左侧和上侧的工作方式与我想要的一样。例如,其左侧坐标为16的矩形应出现在“右侧第二个单元格”上,而不是第一个。

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

点赞
用户134877
用户134877

对于底部和右侧,您需要使用 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  -- 返回顶部、左侧、向右单元格数量和向下单元格数量
end

您的问题本质上是 _toGrid 函数对于您的目的而言是错误的抽象,因为它始终使用 floor。显然,您将自己锁定在使用该抽象中,这就使得很难找到正确的答案。

2012-08-13 08:18:31