app/models/location.rb
# typed: strict
# frozen_string_literal: true
class Location
extend T::Sig
sig { returns(Float) }
attr_accessor :lat
sig { returns(Float) }
attr_accessor :lng
sig { params(lat: Float, lng: Float).void }
def initialize(lat:, lng:)
@lat = lat
@lng = lng
end
sig { params(lat: T.nilable(Float), lng: T.nilable(Float)).returns(T.nilable(Location)) }
def self.build(lat:, lng:)
Location.new(lat:, lng:) if lat && lng
end
# Value returned is in metres
sig { params(loc: Location).returns(Float) }
def distance_to(loc)
loc1 = Geokit::LatLng.new(lat, lng)
loc2 = Geokit::LatLng.new(loc.lat, loc.lng)
loc1.distance_to(loc2, units: :kms) * 1000.0
end
sig { params(loc: Location).returns(Float) }
def heading_to(loc)
loc1 = Geokit::LatLng.new(lat, lng)
loc2 = Geokit::LatLng.new(loc.lat, loc.lng)
loc1.heading_to(loc2)
end
# Distance given is in metres
sig { params(bearing: Float, distance: Float).returns(Location) }
def endpoint(bearing, distance)
loc = Geokit::LatLng.new(lat, lng)
p = loc.endpoint(bearing, distance / 1000.0, units: :kms)
Location.new(lat: p.lat, lng: p.lng)
end
sig { returns(String) }
def to_s
"#{lat},#{lng}"
end
end