class Geospatial::Filter
Attributes
ranges[R]
Public Class Methods
new(curve)
click to toggle source
# File lib/geospatial/filter.rb, line 55 def initialize(curve) @ranges = [] @curve = curve end
Public Instance Methods
add(prefix, order)
click to toggle source
# File lib/geospatial/filter.rb, line 62 def add(prefix, order) if last = @ranges.last raise ArgumentError.new("Cannot add non-sequential prefix") unless prefix > last.max end unless last = @ranges.last and last.expand!(prefix, order) @ranges << Range.new(prefix, order) end end
apply(points)
click to toggle source
# File lib/geospatial/filter.rb, line 72 def apply(points) # This is a poor implementation. points.select{|point| @ranges.any?{|range| range.include?(point.hash)}} end
Also aliased as: &
each(depth: 0) { |child, prefix, order| ... }
click to toggle source
# File lib/geospatial/filter.rb, line 83 def each(depth: 0) # TODO using a range tree might allow a significantly improved implementation. @curve.traverse do |child_origin, child_size, prefix, order| child = Box.new(Vector.elements(child_origin), Vector.elements(child_size)) # puts "Considering (order=#{order}) #{child.inspect}..." min = prefix max = prefix | ((1 << (order*2)) - 1) if min_range = find(min) if order == depth # at bottom yield(child, prefix, order); :skip elsif min_range.include?(max) # This range completely contains the current prefix/order yield(child, prefix, order); :skip else # go deeper end elsif max_range = find(max) if order == depth # at bottom yield(child, prefix, order); :skip else # go deeper end elsif sub_range = @ranges.find{|range| range.min >= min && range.max <= max} # go deeper else :skip # out of bounds end end end
find(hash)
click to toggle source
# File lib/geospatial/filter.rb, line 116 def find(hash) @ranges.find{|range| range.include?(hash)} end
include?(point)
click to toggle source
# File lib/geospatial/filter.rb, line 79 def include?(point) @ranges.any?{|range| range.include?(point.hash)} end