Class: Geospatial::Map

Inherits:
Object
  • Object
show all
Defined in:
lib/geospatial/map.rb,
lib/geospatial/map/index.rb

Defined Under Namespace

Classes: Index

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(curve) ⇒ Map



64
65
66
67
68
# File 'lib/geospatial/map.rb', line 64

def initialize(curve)
  @curve = curve
  @points = []
  @bounds = nil
end

Instance Attribute Details

#pointsObject (readonly)

Returns the value of attribute points.



85
86
87
# File 'lib/geospatial/map.rb', line 85

def points
  @points
end

Class Method Details

.for_earth(order = 20) ⇒ Object



60
61
62
# File 'lib/geospatial/map.rb', line 60

def self.for_earth(order = 20)
  self.new(Hilbert::Curve.new(Dimensions.for_earth, order))
end

Instance Method Details

#<<(object) ⇒ Object



103
104
105
106
107
# File 'lib/geospatial/map.rb', line 103

def << object
  @points << point_for_coordinates(object.to_a, object)
  
  return self
end

#boundsObject



74
75
76
77
78
79
80
81
82
83
# File 'lib/geospatial/map.rb', line 74

def bounds
  unless @bounds
    origin = @curve.origin
    size = @curve.size
    
    @bounds = Box.new(origin, size)
  end
  
  return @bounds
end

#countObject



109
110
111
# File 'lib/geospatial/map.rb', line 109

def count
  @points.count
end

#filter_for(region, **options) ⇒ Object



146
147
148
149
150
151
152
153
154
155
# File 'lib/geospatial/map.rb', line 146

def filter_for(region, **options)
  filter = Filter.new
  
  # The filter will coalesce sequential segments of the curve into a single range.
  traverse(region, **options) do |child, prefix, order|
    filter.add(prefix, order)
  end
  
  return filter
end

#hash_for_coordinates(coordinates) ⇒ Object



87
88
89
# File 'lib/geospatial/map.rb', line 87

def hash_for_coordinates(coordinates)
  @curve.map(coordinates)
end

#indexObject

serialize :point, Map.for_earth.index



49
50
51
52
53
54
55
# File 'lib/geospatial/map/index.rb', line 49

def index
  klass = Class.new(Index)
  
  klass.map = self
  
  return klass
end

#orderObject



70
71
72
# File 'lib/geospatial/map.rb', line 70

def order
  @curve.order
end

#point_for_coordinates(coordinates, object = nil) ⇒ Object



95
96
97
# File 'lib/geospatial/map.rb', line 95

def point_for_coordinates(coordinates, object = nil)
  Point.new(self, coordinates, object)
end

#point_for_hash(hash) ⇒ Object



91
92
93
# File 'lib/geospatial/map.rb', line 91

def point_for_hash(hash)
  Point.new(self, @curve.unmap(hash))
end

#point_for_object(object) ⇒ Object



99
100
101
# File 'lib/geospatial/map.rb', line 99

def point_for_object(object)
  Point.new(self, object.to_a, object)
end

#query(region, **options) ⇒ Object



117
118
119
120
121
# File 'lib/geospatial/map.rb', line 117

def query(region, **options)
  filter = filter_for(region, **options)
  
  return filter.apply(@points).map(&:object)
end

#sort!Object



113
114
115
# File 'lib/geospatial/map.rb', line 113

def sort!
  @points.sort_by!(&:hash)
end

#traverse(region, depth: 0) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/geospatial/map.rb', line 123

def traverse(region, depth: 0)
  @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}..."
    
    if region.intersect?(child)
      if order == depth # at bottom
        # puts "at bottom -> found prefix #{prefix.to_s(2)} (#{child.inspect})"
        yield(child, prefix, order); :skip
      elsif region.include?(child)
        # puts "include child -> found prefix #{prefix.to_s(2)} (#{child.inspect})"
        yield(child, prefix, order); :skip
      else
        # puts "going deeper..."
      end
    else
      # puts "out of bounds."
      :skip
    end
  end
end