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

&(points)
Alias for: apply
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