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

Returns a new instance of 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

#curveObject (readonly)

Returns the value of attribute curve.



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

def curve
  @curve
end

#pointsObject (readonly)

Returns the value of attribute points.



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

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



105
106
107
108
109
# File 'lib/geospatial/map.rb', line 105

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

#boundsObject



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

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

#countObject



111
112
113
# File 'lib/geospatial/map.rb', line 111

def count
  @points.count
end

#filter_for(*regions, **options) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/geospatial/map.rb', line 148

def filter_for(*regions, **options)
  filter = Filter.new(@curve)
  
  regions.each do |region|
    # 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
  end
  
  return filter
end

#hash_for_coordinates(coordinates) ⇒ Object



89
90
91
# File 'lib/geospatial/map.rb', line 89

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



72
73
74
# File 'lib/geospatial/map.rb', line 72

def order
  @curve.order
end

#point_for_coordinates(coordinates, object = nil) ⇒ Object



97
98
99
# File 'lib/geospatial/map.rb', line 97

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

#point_for_hash(hash) ⇒ Object



93
94
95
# File 'lib/geospatial/map.rb', line 93

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

#point_for_object(object) ⇒ Object



101
102
103
# File 'lib/geospatial/map.rb', line 101

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

#query(region, **options) ⇒ Object



119
120
121
122
123
# File 'lib/geospatial/map.rb', line 119

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

#sort!Object



115
116
117
# File 'lib/geospatial/map.rb', line 115

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

#traverse(region, depth: 0) ⇒ Object



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

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