The problem I’m trying to solve is the following:
In a 2-D space, Given a grid size and a rectangle, calculate the grid cells
occupied (partially or totally) by the rectangle.
By “Grid size” I mean something like: “A 16×16 grid” or “A 32×32 grid”. All grids are centered on the origin of coordinates (0,0).
The rectangle is defined by 4 floats: the left, top, width and height.
The result of this operation is always a rectangle. I’d like to return the coordinates of top-left cell (i.e. 0,0) followed by the number of cells the retangle occupies to the right and down (a bit like width and height, but for cells)
So far I’ve been able to write an algorithm that mostly works. What it does first, is calculating the cell coordinates where a single dot resides in the grid. Then, given the rectangle, I calculate where its top-left and lower-rights corner are on the grid, and then it’s a simple substraction:
-- 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
Notes:
- The source code is Lua, but I will accept solutions in any programming language, as long as they are intelligible.
- The y-coordinate goes “down when increasing”; that’s how a lot of screen systems work. I don’t think that’s significant for this problem, but don’t get confused by that).
In a 16×16 grid, a rectangle on 0,0, with width=10 and height=20, gr will be 0 and gt 1, so _toGrid will return 0,0,1,2 (1 row, two columns, on the 0,0 cell).
The problem happens when the rectangle “touches” (not crosses) either the lower or right side of one cell from inside. In that case, _toGrid returns “one more cell” than I’d like it to.
For example, if I move the previous rectangle to the left 6 pixels (so it is on 10,0), it will be “touching” the left-side border of its containing grid, which goes from 0 to 16. Then gr will be 1, and the returned data will be 0,0,2,2.
I’d like to avoid this, if at all possible. For a rectangle going to 16 “from the left”, I’d like it to remain on the first grid cell. I’d like it to begin “occupying the next cell” as soon as it surpasses 16 – for example when it’s at 16.00000001 .
Also, notice that this only applies to the right and bottom sides. The left and upper sides work as I want them to. For example, a rectangle whose left coordinate is 16, should appear on the “second cell to the right”, not on the first.
I’m sure the solution isn’t complicated, but I’ve been thinking about this for a while now and I don’t seem to find it. Any help will be appreciated.
For the bottom and right hand side, you need to use
ceilinstead offloor. I don’t know any Lua, so this may not be syntactically correct, but you would want something along these lines:Your problem, essentially, is that the function
_toGridis the wrong abstraction for your purpose because it always usesfloor. Apparently, you locked yourself into using that abstraction, which then made it difficult to come up with the right answer.