]> git.openstreetmap.org Git - rails.git/blobdiff - app/models/concerns/geo_record.rb
Convert some model mixins to concerns
[rails.git] / app / models / concerns / geo_record.rb
diff --git a/app/models/concerns/geo_record.rb b/app/models/concerns/geo_record.rb
new file mode 100644 (file)
index 0000000..06049c2
--- /dev/null
@@ -0,0 +1,59 @@
+require "delegate"
+
+module GeoRecord
+  extend ActiveSupport::Concern
+
+  # Ensure that when coordinates are printed that they are always in decimal degrees,
+  # and not e.g. 4.0e-05
+  # Unfortunately you can't extend Numeric classes directly (e.g. `Coord < Float`).
+  class Coord < DelegateClass(Float)
+    def initialize(obj)
+      super(obj)
+    end
+
+    def to_s
+      format("%.7f", self)
+    end
+  end
+
+  # This scaling factor is used to convert between the float lat/lon that is
+  # returned by the API, and the integer lat/lon equivalent that is stored in
+  # the database.
+  SCALE = 10000000
+
+  included do
+    scope :bbox, ->(bbox) { where(OSM.sql_for_area(bbox)) }
+    before_save :update_tile
+  end
+
+  # Is this node within -90 >= latitude >= 90 and -180 >= longitude >= 180
+  # * returns true/false
+  def in_world?
+    return false if lat < -90 || lat > 90
+    return false if lon < -180 || lon > 180
+
+    true
+  end
+
+  def update_tile
+    self.tile = QuadTile.tile_for_point(lat, lon)
+  end
+
+  def lat=(l)
+    self.latitude = (l * SCALE).round
+  end
+
+  def lon=(l)
+    self.longitude = (l * SCALE).round
+  end
+
+  # Return WGS84 latitude
+  def lat
+    Coord.new(latitude.to_f / SCALE)
+  end
+
+  # Return WGS84 longitude
+  def lon
+    Coord.new(longitude.to_f / SCALE)
+  end
+end