Class: KnnBall::Ball
- Inherits:
-
Object
- Object
- KnnBall::Ball
- Defined in:
- lib/knnball/ball.rb
Overview
This class represents a ball in the tree.
The value of this ball will be its center while its radius is the distance between the center and the most far sub-ball.
Instance Attribute Summary collapse
-
#dimension ⇒ Object
Returns the value of attribute dimension.
-
#left ⇒ Object
Returns the value of attribute left.
-
#right ⇒ Object
Returns the value of attribute right.
-
#value ⇒ Object
Returns the value of attribute value.
Instance Method Summary collapse
- #center ⇒ Object
-
#complete? ⇒ Boolean
Return true if this ball has a left and a right ball.
- #count ⇒ Object
-
#distance(coordinates) ⇒ Object
Compute euclidien distance.
-
#initialize(value, dimension = 1, left = nil, right = nil) ⇒ Ball
constructor
A new instance of Ball.
-
#leaf? ⇒ Boolean
Retrieve true if this is a leaf ball.
- #nearest(target, min) ⇒ Object
-
#quick_distance(coordinates) ⇒ Object
Quickly compute a distance using Manhattan.
-
#to_a ⇒ Object
Generate an Array from this Ball.
-
#to_h ⇒ Object
Generate a Hash from this Ball instance.
Constructor Details
#initialize(value, dimension = 1, left = nil, right = nil) ⇒ Ball
Returns a new instance of Ball.
21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/knnball/ball.rb', line 21 def initialize(value, dimension = 1, left = nil, right = nil) unless (value.respond_to?(:include?) && value.respond_to?(:[])) raise ArgumentError.new("Value must at least respond to methods include? and [].") end unless (value.include?(:point)) raise ArgumentError.new("value must contains :point key but has only #{value.keys.inspect}") end @value = value @right = right @dimension = dimension @left = left end |
Instance Attribute Details
#dimension ⇒ Object
Returns the value of attribute dimension.
17 18 19 |
# File 'lib/knnball/ball.rb', line 17 def dimension @dimension end |
#left ⇒ Object
Returns the value of attribute left.
17 18 19 |
# File 'lib/knnball/ball.rb', line 17 def left @left end |
#right ⇒ Object
Returns the value of attribute right.
17 18 19 |
# File 'lib/knnball/ball.rb', line 17 def right @right end |
#value ⇒ Object
Returns the value of attribute value.
17 18 19 |
# File 'lib/knnball/ball.rb', line 17 def value @value end |
Instance Method Details
#center ⇒ Object
34 35 36 |
# File 'lib/knnball/ball.rb', line 34 def center value[:point] end |
#complete? ⇒ Boolean
Return true if this ball has a left and a right ball
103 104 105 |
# File 'lib/knnball/ball.rb', line 103 def complete? ! (@left.nil? || @right.nil?) end |
#count ⇒ Object
91 92 93 |
# File 'lib/knnball/ball.rb', line 91 def count 1 + (left.nil? ? 0 : left.count) + (right.nil? ? 0 : right.count) end |
#distance(coordinates) ⇒ Object
Compute euclidien distance.
78 79 80 81 |
# File 'lib/knnball/ball.rb', line 78 def distance(coordinates) coordinates = coordinates.center if coordinates.respond_to?(:center) Math.sqrt([center, coordinates].transpose.map {|a,b| (b - a)**2}.reduce {|d1,d2| d1 + d2}) end |
#leaf? ⇒ Boolean
Retrieve true if this is a leaf ball.
A leaf ball has no sub_balls.
98 99 100 |
# File 'lib/knnball/ball.rb', line 98 def leaf? @left.nil? && @right.nil? end |
#nearest(target, min) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/knnball/ball.rb', line 38 def nearest(target, min) result = nil d = [quick_distance(target), min[0]].min if d < min[0] min[0] = d result = self end # determine if we need to dive into sub tree dp = (center[dimension-1] - target[dimension-1]).abs new_result = nil if(dp < min[0]) # must dive into both left and right unless(left.nil?) new_result = left.nearest(target, min) result = new_result unless new_result.nil? end unless right.nil? new_result = right.nearest(target, min) result = new_result unless new_result.nil? end else # only need to dive in one if(target[dimension-1] < center[dimension-1]) unless(left.nil?) new_result = left.nearest(target, min) end else unless(right.nil?) new_result = right.nearest(target, min) end end result = new_result unless new_result.nil? end return result end |
#quick_distance(coordinates) ⇒ Object
Quickly compute a distance using Manhattan
84 85 86 87 88 89 |
# File 'lib/knnball/ball.rb', line 84 def quick_distance(coordinates) distance(coordinates) # coordinates = coordinates.center if coordinates.respond_to?(:center) # [center, coordinates].transpose.map {|a,b| (b - a)**2}.reduce {|d1,d2| d1 + d2} # [center, coordinates].transpose.map {|a,b| (b - a).abs}.reduce {|d1,d2| d1 + d2} end |
#to_a ⇒ Object
Generate an Array from this Ball.
index 0 contains the value object, index 1 contains the left ball or nil, index 2 contains the right ball or nil.
112 113 114 115 116 117 118 |
# File 'lib/knnball/ball.rb', line 112 def to_a if leaf? [@value, nil, nil] else [@value, (@left.nil? ? nil : @left.to_a), (@right.nil? ? nil : @right.to_a)] end end |
#to_h ⇒ Object
Generate a Hash from this Ball instance.
The generated instance contains keys :id, :left and :right
123 124 125 126 127 128 129 |
# File 'lib/knnball/ball.rb', line 123 def to_h if leaf? {:value => @value, :left => nil, :right => nil} else {:value => @value, :left => (@left.nil? ? nil : @left.to_h), :right => (@right.nil? ? nil : @right.to_h)} end end |