Skip to content

Commit f2db2fe

Browse files
committed
Tests for kd-tree, it still seems semi-broken
1 parent e26bd6a commit f2db2fe

File tree

4 files changed

+20055
-18
lines changed

4 files changed

+20055
-18
lines changed

lib/containers/kd_tree.rb

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
1010
First, put the points into the tree:
1111
12-
kd = Containers::KDTree.new([ [4, 3], [3, 4], [-1, 2], [6, 4], [3, -5], [-2, -5] ])
12+
kdtree = Containers::KDTree.new( {0 => [4, 3], 1 => [3, 4], 2 => [-1, 2], 3 => [6, 4],
13+
4 => [3, -5], 5 => [-2, -5] })
1314
1415
Then, query on the tree:
1516
16-
puts kd.find_nearest([0, 0], 2) => [[0, 6], [0, 3]]
17+
puts kd.find_nearest([0, 0], 2) => [[5, 2], [9, 1]]
18+
19+
The result is an array of [distance, id] pairs. There seems to be a bug in this version.
1720
1821
Note that the point queried on does not have to exist in the tree. However, if it does exist,
1922
it will be returned.
@@ -23,21 +26,30 @@
2326
class Containers::KDTree
2427
Node = Struct.new(:id, :coords, :left, :right)
2528

29+
# Points is a hash of id => [coord, coord] pairs.
2630
def initialize(points)
27-
@root = build_tree(points)
31+
raise "must pass in a hash" unless points.kind_of?(Hash)
32+
@dimensions = points[ points.keys.first ].size
33+
@root = build_tree(points.to_a)
34+
@nearest = []
35+
end
36+
37+
# Find k closest points to given coordinates
38+
def find_nearest(target, k_nearest)
2839
@nearest = []
40+
nearest(@root, target, k_nearest, 0)
2941
end
3042

31-
# Build a kd-tree
43+
# points is an array
3244
def build_tree(points, depth=0)
3345
return if points.empty?
34-
35-
axis = depth % 2
36-
37-
points.sort! { |a, b| a[1][axis] <=> b[1][axis] }
46+
47+
axis = depth % @dimensions
48+
49+
points.sort! { |a, b| a.last[axis] <=> b.last[axis] }
3850
median = points.size / 2
39-
40-
node = Node.new(points[median][0], points[median][1], nil, nil)
51+
52+
node = Node.new(points[median].first, points[median].last, nil, nil)
4153
node.left = build_tree(points[0...median], depth+1)
4254
node.right = build_tree(points[median+1..-1], depth+1)
4355
node
@@ -65,14 +77,9 @@ def check_nearest(nearest, node, target, k_nearest)
6577
end
6678
private :check_nearest
6779

68-
# Find k closest points to given coordinates
69-
def find_nearest(target, k_nearest)
70-
@nearest = []
71-
nearest(@root, target, k_nearest, 0)
72-
end
73-
80+
# Recursively find nearest coordinates, going down the appropriate branch as needed
7481
def nearest(node, target, k_nearest, depth)
75-
axis = depth % 2
82+
axis = depth % @dimensions
7683

7784
if node.left.nil? && node.right.nil? # Leaf node
7885
@nearest = check_nearest(@nearest, node, target, k_nearest)

0 commit comments

Comments
 (0)