您有一个很好的解决方案(项->节点索引),用于处理更新方法的常见问题,这些方法是由于需要使用旧的边界框删除并插入新的边界框而产生的。
insert方法是o(ln(n)),但如果项保持在同一节点中,则可以在恒定时间内完成更新。移动到子节点也可以通过将搜索向下移动到当前包含该项的节点来进行优化,并且移动到相邻节点也可以消除某些搜索,因为每个节点都知道其父节点。
我不知道Lua,所以请将下面的代码视为伪代码。
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
我不确定它是否值得上下扫描。尝试可能很有意思,但在一棵很深的树上它才有价值。
findnode方法通过空间位置扫描自查找项所属节点的树。实现可以选择只扫描自节点及其从属节点:
-- 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
…或者使用父节点扫描整个树:
-- 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