app/models/active_road/street_number.rb
module ActiveRoad
class StreetNumber < ActiveRoad::Base
serialize :tags, ActiveRecord::Coders::Hstore
attr_accessible :objectid, :tags, :number, :geometry, :physical_road_id, :location_on_road
validates_uniqueness_of :objectid
validates_presence_of :number, :stored_geometry
belongs_to :physical_road, :class_name => "ActiveRoad::PhysicalRoad"
def road
@road or physical_road
end
def road=(road)
@road ||= road
end
before_validation :compute_locate_on_road, :on => :create
def stored_geometry
read_attribute :geometry
end
def geometry
stored_geometry or computed_geometry
end
def computed_geometry
road.at estimated_location_on_road
end
def location_on_road
stored_location_on_road or estimated_location_on_road
end
def stored_location_on_road
read_attribute :location_on_road
end
def compute_locate_on_road
if stored_location_on_road.nil? and stored_geometry
self.location_on_road = road.geometry.locate_point(stored_geometry)
end
end
# TODO rename into estimated_location_on_road
def estimated_location_on_road
if previous and self.next
number_ratio = (number.to_i - previous.number.to_i) / (self.next.number.to_i - previous.number.to_i).to_f
previous.location_on_road + number_ratio * (self.next.location_on_road - previous.location_on_road)
end
end
def previous
@previous ||= road.numbers.find :first, :conditions => ["number < ?", number], :limit => 1, :order => "number desc"
end
def next
@next ||= road.numbers.find :first, :conditions => ["number > ?", number], :limit => 1, :order => "number"
end
def number
Number.new read_attribute(:number)
end
class Number < String
alias_method :numeric_value, :to_i
def suffix
gsub(/^[0-9]+/,'')
end
def +(value)
self.class.new "#{numeric_value+value}#{suffix}"
end
def -(value)
self.class.new "#{numeric_value-value}#{suffix}"
end
end
end
end