You have a nice solution (element → node index) to solve the usual problem with update methods, arising from the need to remove using the old bounding box and insert with a new bounding box.
The insertion method is O (ln (N)), but an update in which the element remains in the same node can be performed in constant time. Navigating to a child of a node can also be optimized by deleting the search to node, currently holding the element, and moving to neighboring nodes can also eliminate some of these searches because each node knows its parent.
I do not know Lua, so please treat the code below as pseudo code.
function QuadTree:update(item) oldNode = root.assignments[item] newNode = oldNode:findNode(item) if (oldNode ~= newNode) then -- if findNode only searches down the tree newNode will be nil if -- the item needs to move to/under an adjacent node. Otherwise the -- next three lines are not needed if (newNode == nil) then newNode = root:findNode(item) end oldNode:remove(item) newNode = newNode:insert(item) end return newNode end
I'm not sure if it is worth scanning both the tree and down. It might be interesting to try, but it is probably worth it in a very deep tree.
The findNode method scans the tree, independently scanning the node to which the element belongs to a spatial location. Implementations can choose to scan only the node itself and its dependents:
-- Returns the node that the item belongs to by spatial location. -- The tree can already contain the item. The item might be indexed using -- an old geometry. -- This method does not create child nodes. function QuadTree:findNode(item) local x,y,w,h = item:getBoundingBox() if( not _contained(x,y,w,h , self:getBoundingBox()) ) then -- Attempted to insert an item on a QuadTree that does not contain it; -- just return return nil end for _,node in ipairs(self.nodes) do if(node:findNode(item) ~= nil) then return node end end return self end
... or to scan the entire tree using parent nodes:
-- Returns the node that the item belongs to by spatial location. -- The tree can already contain the item. The item might be indexed using -- an old geometry. -- This method does not create child nodes. function QuadTree:findNode(item) local x,y,w,h = item:getBoundingBox() if( not _contained(x,y,w,h , self:getBoundingBox()) ) then -- Attempted to insert an item on a QuadTree that does not contain it; -- scan the parent if (parent == nil) then return nil end return parent:findNode(item) end for _,node in ipairs(self.nodes) do if(node:findNode(item) ~= nil) then return node end end return self end