mirror of
https://github.com/vrld/HC.git
synced 2024-11-18 12:54:23 +00:00
Spatial hash to use number instead of table arguments
This commit is contained in:
parent
ce4b8011da
commit
e03ea9b0a2
12
init.lua
12
init.lua
@ -92,7 +92,7 @@ local function new_shape(self, shape)
|
||||
self._current_shape_id = self._current_shape_id + 1
|
||||
self._active_shapes[self._current_shape_id] = shape
|
||||
self._shape_ids[shape] = self._current_shape_id
|
||||
self._hash:insert(shape, {x=x1,y=y1}, {x=x2,y=y2})
|
||||
self._hash:insert(shape, x1,y1, x2,y2)
|
||||
shape._groups = {}
|
||||
|
||||
local hash = self._hash
|
||||
@ -101,24 +101,24 @@ local function new_shape(self, shape)
|
||||
local x1,y1,x2,y2 = self:bbox()
|
||||
move(self, ...)
|
||||
local x3,y3,x4,y4 = self:bbox()
|
||||
hash:update(self, {x=x1,y=y1}, {x=x2,y=y2}, {x=x3,y=y3}, {x=x4,y=y4})
|
||||
hash:update(self, x1,y1, x2,y2, x3,y3, x4,y4)
|
||||
end
|
||||
|
||||
function shape:rotate(...)
|
||||
local x1,y1,x2,y2 = self:bbox()
|
||||
rotate(self, ...)
|
||||
local x3,y3,x4,y4 = self:bbox()
|
||||
hash:update(self, {x=x1,y=y1}, {x=x2,y=y2}, {x=x3,y=y3}, {x=x4,y=y4})
|
||||
hash:update(self, x1,y1, x2,y2, x3,y3, x4,y4)
|
||||
end
|
||||
|
||||
function shape:neighbors()
|
||||
local x1,y1, x2,y2 = self:bbox()
|
||||
return pairs(hash:getNeighbors(self, {x=x1,y=y1}, {x=x2,y=y2}))
|
||||
return pairs(hash:getNeighbors(self, x1,y1, x2,y2))
|
||||
end
|
||||
|
||||
function shape:_removeFromHash()
|
||||
local x1,y1, x2,y2 = self:bbox()
|
||||
hash:remove(shape, {x=x1,y=y1}, {x=x2,y=y2})
|
||||
hash:remove(shape, x1,y1, x2,y2)
|
||||
end
|
||||
|
||||
return shape
|
||||
@ -199,7 +199,7 @@ end
|
||||
-- get list of shapes at point (x,y)
|
||||
function HC:shapesAt(x, y)
|
||||
local shapes = {}
|
||||
for s in pairs(self._hash:cell{x=x,y=y}) do
|
||||
for s in pairs(self._hash:cellAt(x,y)) do
|
||||
if s:contains(x,y) then
|
||||
shapes[#shapes+1] = s
|
||||
end
|
||||
|
127
spatialhash.lua
127
spatialhash.lua
@ -33,108 +33,101 @@ if not (common and common.class and common.instance) then
|
||||
require(_PACKAGE .. '.class')
|
||||
end
|
||||
|
||||
-- transparent cell accessor methods
|
||||
-- cells = {[0] = {[0] = <>, [1] = <>, ... }, [1] = {...}, ...}
|
||||
local cells_meta = {}
|
||||
function cells_meta.__newindex(tbl, key, val)
|
||||
local cell = rawget(tbl, key.x)
|
||||
if not cell then
|
||||
rawset(tbl, key.x, {[key.y] = val})
|
||||
else
|
||||
rawset(cell, key.y, val)
|
||||
end
|
||||
end
|
||||
|
||||
function cells_meta.__index(tbl, key)
|
||||
local cell = rawget(tbl, key.x)
|
||||
if not cell then
|
||||
local ret = setmetatable({}, {__mode = "kv"})
|
||||
cell = {[key.y] = ret}
|
||||
rawset(tbl, key.x, cell)
|
||||
return ret
|
||||
end
|
||||
|
||||
local ret = rawget(cell, key.y)
|
||||
if not ret then
|
||||
ret = setmetatable({}, {__mode = "kv"})
|
||||
rawset(cell, key.y, ret)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local Spatialhash = {}
|
||||
function Spatialhash:init(cell_size)
|
||||
self.cell_size = cell_size or 100
|
||||
self.cells = setmetatable({}, cells_meta)
|
||||
self.cells = {}
|
||||
end
|
||||
|
||||
function Spatialhash:cellCoords(v)
|
||||
return {x=floor(v.x / self.cell_size), y=floor(v.y / self.cell_size)}
|
||||
function Spatialhash:cellCoords(x,y)
|
||||
return floor(x / self.cell_size), floor(y / self.cell_size)
|
||||
end
|
||||
|
||||
function Spatialhash:cell(v)
|
||||
return self.cells[ self:cellCoords(v) ]
|
||||
function Spatialhash:cell(i,k)
|
||||
local row = rawget(self.cells, i)
|
||||
if not row then
|
||||
row = {}
|
||||
rawset(self.cells, i, row)
|
||||
end
|
||||
|
||||
local cell = rawget(row, k)
|
||||
if not cell then
|
||||
cell = setmetatable({}, {__mode = "kv"})
|
||||
rawset(row, k, cell)
|
||||
end
|
||||
|
||||
return cell
|
||||
end
|
||||
|
||||
function Spatialhash:insert(obj, ul, lr)
|
||||
local ul = self:cellCoords(ul)
|
||||
local lr = self:cellCoords(lr)
|
||||
for i = ul.x,lr.x do
|
||||
for k = ul.y,lr.y do
|
||||
rawset(self.cells[{x=i,y=k}], obj, obj)
|
||||
function Spatialhash:cellAt(x,y)
|
||||
return self:cell(self:cellCoords(x,y))
|
||||
end
|
||||
|
||||
function Spatialhash:insert(obj, x1, y1, x2, y2)
|
||||
x1, y1 = self:cellCoords(x1, y1)
|
||||
x2, y2 = self:cellCoords(x2, y2)
|
||||
for i = x1,x2 do
|
||||
for k = y1,y2 do
|
||||
rawset(self:cell(i,k), obj, obj)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Spatialhash:remove(obj, ul, lr)
|
||||
function Spatialhash:remove(obj, x1, y1, x2,y2)
|
||||
-- no bbox given. => must check all cells
|
||||
if not ul or not lr then
|
||||
for _,cell in pairs(self.cells) do
|
||||
rawset(cell, obj, nil)
|
||||
if not (x1 and y1 and x2 and y2) then
|
||||
for _,row in pairs(self.cells) do
|
||||
for _,cell in pairs(row) do
|
||||
rawset(cell, obj, nil)
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local ul = self:cellCoords(ul)
|
||||
local lr = self:cellCoords(lr)
|
||||
-- else: remove only from bbox
|
||||
for i = ul.x,lr.x do
|
||||
for k = ul.y,lr.y do
|
||||
rawset(self.cells[{x=i,y=k}], obj, nil)
|
||||
x1,y1 = self:cellCoords(x1,y1)
|
||||
x2,y2 = self:cellCoords(x2,y2)
|
||||
for i = x1,x2 do
|
||||
for k = y1,y2 do
|
||||
rawset(self:cell(i,k), obj, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- update an objects position
|
||||
function Spatialhash:update(obj, ul_old, lr_old, ul_new, lr_new)
|
||||
local ul_old, lr_old = self:cellCoords(ul_old), self:cellCoords(lr_old)
|
||||
local ul_new, lr_new = self:cellCoords(ul_new), self:cellCoords(lr_new)
|
||||
function Spatialhash:update(obj, old_x1,old_y1, old_x2,old_y2, new_x1,new_y1, new_x2,new_y2)
|
||||
old_x1, old_y1 = self:cellCoords(old_x1, old_y1)
|
||||
old_x2, old_y2 = self:cellCoords(old_x2, old_y2)
|
||||
|
||||
if ul_old.x == ul_new.x and ul_old.y == ul_new.y and
|
||||
lr_old.x == lr_new.x and lr_old.y == lr_new.y then
|
||||
new_x1, new_y1 = self:cellCoords(new_x1, new_y1)
|
||||
new_x2, new_y2 = self:cellCoords(new_x2, new_y2)
|
||||
|
||||
if old_x1 == new_x1 and old_y1 == new_y1 and
|
||||
old_x2 == new_x2 and old_y2 == new_y2 then
|
||||
return
|
||||
end
|
||||
|
||||
for i = ul_old.x,lr_old.x do
|
||||
for k = ul_old.y,lr_old.y do
|
||||
rawset(self.cells[{x=i,y=k}], obj, nil)
|
||||
for i = old_x1,old_x2 do
|
||||
for k = old_y1,old_y2 do
|
||||
rawset(self:cell(i,k), obj, nil)
|
||||
end
|
||||
end
|
||||
for i = ul_new.x,lr_new.x do
|
||||
for k = ul_new.y,lr_new.y do
|
||||
rawset(self.cells[{x=i,y=k}], obj, obj)
|
||||
for i = new_x1,new_x2 do
|
||||
for k = new_y1,new_y2 do
|
||||
rawset(self:cell(i,k), obj, obj)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Spatialhash:getNeighbors(obj, ul, lr)
|
||||
local ul = self:cellCoords(ul)
|
||||
local lr = self:cellCoords(lr)
|
||||
function Spatialhash:getNeighbors(obj, x1,y1, x2,y2)
|
||||
x1,y1 = self:cellCoords(x1,y1)
|
||||
x2,y2 = self:cellCoords(x2,y2)
|
||||
|
||||
local set = {}
|
||||
for i = ul.x,lr.x do
|
||||
for k = ul.y,lr.y do
|
||||
local cell = self.cells[{x=i,y=k}] or {}
|
||||
for other,_ in pairs(cell) do
|
||||
for i = x1,x2 do
|
||||
for k = y1,y2 do
|
||||
local cell = self:cell(i,k)
|
||||
for other in pairs(cell) do
|
||||
rawset(set, other, other)
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user