mirror of
https://github.com/appgurueu/modlib.git
synced 2024-11-22 15:23:48 +01:00
Add simple k-d-tree
This commit is contained in:
parent
386f49a6ac
commit
155ab6deb7
1
init.lua
1
init.lua
@ -78,6 +78,7 @@ for _, component in ipairs{
|
|||||||
"quaternion",
|
"quaternion",
|
||||||
"minetest",
|
"minetest",
|
||||||
"trie",
|
"trie",
|
||||||
|
"kdtree",
|
||||||
"heap",
|
"heap",
|
||||||
"ranked_set",
|
"ranked_set",
|
||||||
"b3d"
|
"b3d"
|
||||||
|
54
kdtree.lua
Normal file
54
kdtree.lua
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
local metatable = {__index = getfenv(1)}
|
||||||
|
|
||||||
|
distance = modlib.vector.distance
|
||||||
|
|
||||||
|
--: vectors first vector is used to infer the dimension
|
||||||
|
--: distance (vector, other_vector) -> number, default: modlib.vector.distance
|
||||||
|
function new(vectors, distance)
|
||||||
|
assert(#vectors > 0, "vector list must not be empty")
|
||||||
|
local dimension = #vectors[1]
|
||||||
|
local function builder(vectors, axis)
|
||||||
|
if #vectors == 1 then return { value = vectors[1] } end
|
||||||
|
table.sort(vectors, function(a, b) return a[axis] > b[axis] end)
|
||||||
|
local median = math.floor(#vectors / 2)
|
||||||
|
local next_axis = ((axis + 1) % dimension) + 1
|
||||||
|
return setmetatable({
|
||||||
|
axis = axis,
|
||||||
|
pivot = vectors[median],
|
||||||
|
left = builder({ unpack(vectors, 1, median) }, next_axis),
|
||||||
|
right = builder({ unpack(vectors, median + 1) }, next_axis)
|
||||||
|
}, metatable)
|
||||||
|
end
|
||||||
|
local self = builder(vectors, 1)
|
||||||
|
self.distance = distance
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_nearest_neighbor(self, vector)
|
||||||
|
local min_distance = math.huge
|
||||||
|
local nearest_neighbor
|
||||||
|
local distance_func = self.distance
|
||||||
|
local axis = tree.axis
|
||||||
|
local function visit(tree)
|
||||||
|
if tree.value ~= nil then
|
||||||
|
local distance = distance_func(tree.value, vector)
|
||||||
|
if distance < min_distance then
|
||||||
|
min_distance = distance
|
||||||
|
nearest_neighbor = tree.value
|
||||||
|
end
|
||||||
|
return
|
||||||
|
else
|
||||||
|
local this_side, other_side = tree.left, tree.right
|
||||||
|
if vector[axis] < tree.pivot[axis] then this_side, other_side = other_side, this_side end
|
||||||
|
visit(this_side)
|
||||||
|
if tree.pivot then
|
||||||
|
local dist = math.abs(tree.pivot[axis] - color[axis])
|
||||||
|
if dist <= min_distance then visit(other_side) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
visit(self)
|
||||||
|
return nearest_neighbor, min_distance
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO insertion & deletion + rebalancing
|
Loading…
Reference in New Issue
Block a user