Class: Geokdtree::Tree

Inherits:
Object
  • Object
show all
Defined in:
lib/geokdtree/tree.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dimensions) ⇒ Tree

Returns a new instance of Tree.



22
23
24
25
26
27
# File 'lib/geokdtree/tree.rb', line 22

def initialize(dimensions)
  @dimensions = dimensions
  @tree = KdtreePointer.new(C::kd_create(dimensions))
  @data_cache = {}
  @data_id = 0
end

Class Method Details

.distance(pointa, pointb) ⇒ Float

compute the Euclidean distance between 2 points of n dimensions

Parameters:

  • pointa (Array<Float>)

    array of n dimensions of numeric coordinates

  • pointb (Array<Float>)

    array of n dimensions of numeric coordinates

Returns:

  • (Float)

    the Euclidean distance between the 2 points



87
88
89
90
91
92
# File 'lib/geokdtree/tree.rb', line 87

def self.distance(pointa, pointb)
  case k = pointa.size
    when 2 then C::euclidean_distance2(pointa[0].to_f, pointa[1].to_f, pointb[0].to_f, pointb[1].to_f)
    else C::euclidean_distance(allocate_doubles(pointa), allocate_doubles(pointb), k)
  end
end

.geo_distance(pointa, pointb, units = :mi) ⇒ Float

compute the geo distance between 2 points of latitude, longitude

Parameters:

  • pointa (Array<Float>)
    latitude, longitude

    array

  • pointb (Array<Float>)
    latitude, longitude

    array

  • units (Symbol) (defaults to: :mi)

    :mi or :km, default :mi

Returns:

  • (Float)

    the geo distance between the 2 points



99
100
101
# File 'lib/geokdtree/tree.rb', line 99

def self.geo_distance(pointa, pointb, units = :mi)
  C::slc_distance2(pointa[0].to_f, pointa[1].to_f, pointb[0].to_f, pointb[1].to_f, units == :mi ? RADIUS_MI : RADIUS_KM)
end

Instance Method Details

#insert(point, data = nil) ⇒ Tree

insert a point of n dimensions and arbritary associated object

Parameters:

  • point (Array<Float>)

    array of n dimensions of numeric coordinates

  • data (Object) (defaults to: nil)

    arbritary object stored with point

Returns:



33
34
35
36
37
38
39
40
41
42
# File 'lib/geokdtree/tree.rb', line 33

def insert(point, data = nil)
  # here we don't actually pass a pointer to our data but the object numeric key encoded into the pointer
  r = case point.size
    when 2 then C::kd_insert2(@tree, point[0].to_f, point[1].to_f, cache(data))
    when 3 then C::kd_insert3(@tree, point[0].to_f, point[1].to_f, point[2].to_f, cache(data))
    else C::kd_insert(@tree, Tree.allocate_doubles(point), cache(data))
  end     
  raise("error on Tree#insert, code=#{r}") unless r.zero?
  self
end

#nearest(point) ⇒ ResultPoint

find the given point nearest neighbor

Parameters:

  • point (Array<Float>)

    array of n dimensions of numeric coordinates

Returns:

  • (ResultPoint)

    the nearest neighbor, nil if no neighbor



47
48
49
50
51
52
53
54
55
# File 'lib/geokdtree/tree.rb', line 47

def nearest(point)
  set = case point.size
    when 2 then C::kd_nearest2(@tree, point[0].to_f, point[1].to_f)
    when 3 then C::kd_nearest3(@tree, point[0].to_f, point[1].to_f, point[2].to_f)
    else C::kd_nearest(@tree, Tree.allocate_doubles(point))
  end
  return nil if set.null?
  retrieve_results(set).first
end

#nearest_geo_range(point, range, units = :mi) ⇒ Array<ResultPoint>

find all the given point neighbors within the given geo range

Parameters:

  • point (Array<Float>)
    latitude, longitude

    array

  • range (Float)

    range units in miles or kms, default in miles

  • units (Symbol) (defaults to: :mi)

    :mi or :km, default :mi

Returns:

  • (Array<ResultPoint>)

    the point neighbors within range, [] if none



76
77
78
79
80
81
# File 'lib/geokdtree/tree.rb', line 76

def nearest_geo_range(point, range, units = :mi)
 raise("must have 2 dimensions for geo methods") unless @dimensions == 2
 set = C::kd_nearest_geo_range(@tree, point[0].to_f, point[1].to_f, range.to_f, units == :mi ? GEO_UNITS_MI : GEO_UNITS_KM)
 return [] if set.null?
 retrieve_results(set)
end

#nearest_range(point, range) ⇒ Array<ResultPoint>

find all the given point neighbors within the given Euclidean range

Parameters:

  • point (Array<Float>)

    array of n dimensions of numeric coordinates

  • range (Float)

    range units expressed as a Euclidean distance

Returns:

  • (Array<ResultPoint>)

    the point neighbors within range, [] if none



61
62
63
64
65
66
67
68
69
# File 'lib/geokdtree/tree.rb', line 61

def nearest_range(point, range)
  set = case point.size
    when 2 then C::kd_nearest_range2(@tree, point[0].to_f, point[1].to_f, range.to_f)
    when 3 then C::kd_nearest_range3(@tree, point[0].to_f, point[1].to_f, point[2].to_f, range.to_f)
    else C::kd_nearest_range(@tree, Tree.allocate_doubles(point), range.to_f)
  end
  return [] if set.null?
  retrieve_results(set)
end