class GeoTreeModule::MultiTree

See the README file for a description of this class.

Attributes

num_trees[R]

Public Class Methods

new(path,num_trees) click to toggle source

Construct MultiTree @param path directory to store trees within @param num_trees the number of trees to maintain (equivalently, the number of

levels of detail to support)
# File lib/geotree/multitree.rb, line 17
def initialize(path,num_trees)
  @buffer = PtBuffer.new(self)
  @num_trees = num_trees
  raise ArgumentError if File.file?(path)

  @trees = []

  if !File.directory?(path)
    Dir::mkdir(path)
  end

  # Construct trees within this directory
  num_trees.times do |i|
    tp = File.join(path,"tree_#{i}.bin")
    t = GeoTree.open(tp)
    @trees << t
  end

  prepare_details
end

Public Instance Methods

add(data_point) click to toggle source

Add a datapoint to the trees. Does not ensure that a datapoint with this name already exists in the tree, even if it has the same location.

# File lib/geotree/multitree.rb, line 69
def add(data_point)
  raise IllegalStateException if !open?
  @buffer.add(data_point)
end
add_buffered_point(data_point) click to toggle source
# File lib/geotree/multitree.rb, line 112
def add_buffered_point(data_point)
  
  # Determine which is the lowest detail level at which
  # this point is to be found

  stretch = 1.5
  contract = 0.5
  rf = rand() - contract

  wt = data_point.weight & (MAX_POINT_WEIGHT-1)

  randval = (wt + stretch*rf) / MAX_POINT_WEIGHT

  num_trees.times do |ti|
    di = num_trees - 1 - ti

    if ti > 0 && randval < @cutoffs[di]
      break
    end

    tree(di).add_buffered_point(data_point)
  end
end
buffering() click to toggle source
# File lib/geotree/multitree.rb, line 38
def buffering
  @buffer.active
end
buffering=(val) click to toggle source
# File lib/geotree/multitree.rb, line 42
def buffering=(val)
  db = false

  raise IllegalStateException if !open?

  @buffer.active = val
end
close() click to toggle source
# File lib/geotree/multitree.rb, line 54
def close
  raise IllegalStateException if !open?

  # Stop buffering, in case we were, to flush points to tree
  @buffer.active = false

  @trees.each{|t| t.close}
  @trees = nil

end
find(rect, detail) click to toggle source

Find all points intersecting a rectangle. @param rect query rectangle @param detail level of detail, 0…num_trees-1

# File lib/geotree/multitree.rb, line 101
def find(rect, detail)
  raise IllegalStateException if (!open? || @buffer.active)
  tree(detail).find(rect)
end
find_point(df, detail) click to toggle source

Determine if a particular datapoint lies in the tree

# File lib/geotree/multitree.rb, line 107
def find_point(df, detail)
  raise IllegalStateException if (!open? || @buffer.active)
  tree(detail).find(rect)
end
open?() click to toggle source
# File lib/geotree/multitree.rb, line 50
def open?
  @trees != nil
end
remove(data_point) click to toggle source

Remove a datapoint. Returns the datapoint if it was found and removed, otherwise nil. A datapoint will be removed iff both its name and location match the sought point; the weight is ignored.

# File lib/geotree/multitree.rb, line 78
def remove(data_point)

  raise IllegalStateException if  @buffer.active

  removed = nil

  # Start with highest-detail tree, and continue to remove the
  # same point until we reach a tree that doesn't contain it
  @trees.each do |t|
    rem = t.remove(data_point)
    if rem
      removed = true
    else
      break  # assume it's not in any lower detail tree
    end
  end
  removed
end

Private Instance Methods

prepare_details() click to toggle source
# File lib/geotree/multitree.rb, line 138
def prepare_details

  # Cutoffs are indexed by detail level;
  # if the adjusted data point weights are less than the
  # cutoff value, then the point will not appear in that level's tree

  @cutoffs = []

  cmin = -0.3
  m = (1.0) / num_trees

  num_trees.times do |ti|
    dt = num_trees-1-ti
    @cutoffs << (dt+1) * m + cmin
  end
end
tree(detail) click to toggle source
# File lib/geotree/multitree.rb, line 155
def tree(detail)
  @trees[num_trees - 1 - detail]
end