M
Marcin Raczkowski
Hello.
I started playing with ruby kD-Trees implementation, an thoughts?
# to be extended to allow for searching / parasing nodes
class KDTree
attr_reader :root
def initialize(points)
@root = KDNode.new.parse(points)
end
def add_node(point)
@root.add(point)
end
end
# pretty standard tree node
class KDNode
attr_reader :left, :right
attr_reader :location
def initialize(location=nil, left=nil, right=nil)
@location = location
@left = left
@right = right
end
# parse list of points and build nodes
def parse(points, depth = 0)
@depth = depth # save depth for this node for removing
@dim = points[0].length # dimension based on point dimensions
axis = depth % @dim
points = points.sort_by{|point| point[axis]} # sorting by axis
half = points.length / 2 # algoithm suggest using median
# but in reality we don't need median value
# we just need to cut it in half
@location = points[half] # here we can store just index
@left = KDNode.parse(points[0..half-1], depth+1) unless half < 1
@right = KDNode.parse(points[half+1..-1], depth+1) unless half+1 >=
points.length
end
# add leaf to node, adding nodes will make tree unbalanced
def add(point, depth = 0)
@dim = point.length
axis = depth % @dim
if @location[axis] < point[axis]
@left ? @left.add(point) : @left = KDNode.new(point)
else
@right ? @right.add(point) : @right = KDNode.new(point)
end
end
# remove node from tree
def remove
self.parse(@left.to_a + @right.to_a, @depth)
# no idea if it should be @depth or @depth + 1
end
# list all leafs including this node
def to_a
@left.to_a + [@location] + @right.to_a
end
end
I'm thinking about storing only indexes in leaves, and storing point
list in kD-Tree.
any suggestions?
I started playing with ruby kD-Trees implementation, an thoughts?
# to be extended to allow for searching / parasing nodes
class KDTree
attr_reader :root
def initialize(points)
@root = KDNode.new.parse(points)
end
def add_node(point)
@root.add(point)
end
end
# pretty standard tree node
class KDNode
attr_reader :left, :right
attr_reader :location
def initialize(location=nil, left=nil, right=nil)
@location = location
@left = left
@right = right
end
# parse list of points and build nodes
def parse(points, depth = 0)
@depth = depth # save depth for this node for removing
@dim = points[0].length # dimension based on point dimensions
axis = depth % @dim
points = points.sort_by{|point| point[axis]} # sorting by axis
half = points.length / 2 # algoithm suggest using median
# but in reality we don't need median value
# we just need to cut it in half
@location = points[half] # here we can store just index
@left = KDNode.parse(points[0..half-1], depth+1) unless half < 1
@right = KDNode.parse(points[half+1..-1], depth+1) unless half+1 >=
points.length
end
# add leaf to node, adding nodes will make tree unbalanced
def add(point, depth = 0)
@dim = point.length
axis = depth % @dim
if @location[axis] < point[axis]
@left ? @left.add(point) : @left = KDNode.new(point)
else
@right ? @right.add(point) : @right = KDNode.new(point)
end
end
# remove node from tree
def remove
self.parse(@left.to_a + @right.to_a, @depth)
# no idea if it should be @depth or @depth + 1
end
# list all leafs including this node
def to_a
@left.to_a + [@location] + @right.to_a
end
end
I'm thinking about storing only indexes in leaves, and storing point
list in kD-Tree.
any suggestions?