Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

various improvements

  • Loading branch information...
commit b002f694482a552e2b040887d68aca600f9d0862 1 parent 29c16b5
@kristianmandrup authored
View
1  lib/geo_magic.rb
@@ -4,6 +4,7 @@ module GeoMagic
end
require 'sugar-high/arguments'
+require 'active_support/inflector'
require 'geo_magic/core_ext'
require 'geo_magic/remote'
View
44 lib/geo_magic/distance.rb
@@ -17,6 +17,30 @@ def initialize distance, unit = nil
raise ArgumentError, "Invalid unit: #{unit} - must be one of #{GeoMagic::Distance.units}" if !GeoMagic::Distance.units.include?(unit.to_sym)
@unit = unit.to_sym
end
+
+ # select all points within radius
+ def select_within points, center
+
+ end
+
+ # reject all points within radius
+ def reject_within points, center
+
+ end
+
+ def multiply arg
+ case arg
+ when Fixnum
+ self.distance *= arg
+ else
+ raise ArgumentError, "Argument must be a Fixnum" if !arg.kind_of?
+ end
+ end
+
+ def radius center, type = :circular
+ raise ArgumentError, "Radius type must be one of: #{self.class.valid_radius_types}, was: #{type}" if !self.class.valid_radius_type? type
+ GeoMagic::Radius.send :"create_#{type}", center, self
+ end
def [] key
method = :"delta_#{key}"
@@ -24,6 +48,14 @@ def [] key
Distance.send "in_#{key}", send(method)
end
+ def self.valid_radius_type? type
+ valid_radius_types.include? type
+ end
+
+ def self.valid_radius_types
+ [:circular, :rectangular]
+ end
+
GeoMagic::Distance.units.each do |unit|
class_eval %{
def #{unit}
@@ -32,6 +64,18 @@ def #{unit}
}
end
+ def conversion
+ unit.radians_ratio
+ end
+
+ def in_radians
+ distance * conversion
+ end
+
+ def to_s
+ "distance: #{distance} #{unit}"
+ end
+
protected
# delta between the two points in miles
View
44 lib/geo_magic/distance/vector.rb
@@ -2,17 +2,57 @@ module GeoMagic
class Distance
class Vector
attr_accessor :lat_distance, :long_distance
-
+
+ # should be Distance objects!
def initialize lat_distance, long_distance
+ raise ArgumentError "lat and long distance arguments must be instances of GeoMagic::Distance" if ![long_distance, lat_distance].kinds_of? GeoMagic::Distance
@lat_distance = lat_distance
@long_distance = long_distance
end
+ def multiply arg
+ factors = case arg
+ when Fixnum
+ [arg, arg]
+ when Hash
+ [factor(arg, [:lat, :latitude]), factor(arg, [:long, :longitude])]
+ else
+ raise ArgumentError, "Argument must be a Fixnum or a Hash specifying factor to multiply latitude and/or longitude with" if !arg.kind_of?
+ end
+ multiply_lat factors.first
+ multiply_long factors.last
+ end
+
+ def multiply_lat arg
+ raise ArgumentError, "Argument must be a Fixnum" if !arg.kind_of? Fixnum
+ self.lat_distance *= arg
+ end
+
+ def multiply_long arg
+ raise ArgumentError, "Argument must be a Fixnum" if !arg.kind_of? Fixnum
+ self.long_distance *= arg
+ end
+
+ def radius center
+ GeoMagic::Radius.send :"create_rectangular", center, self
+ end
+
# should create distance vector from 2 points
- def create_from *args
+ def self.create_from *args
# extract points
# calc distance
end
+
+ def to_s
+ "distances: (lat: #{lat_distance}, long: #{long_distance})"
+ end
+
+ protected
+
+ def factor hash, symbols
+ s = symbols.select {|s| hash[s].kind_of? Fixnum }
+ s.empty? ? 1 : hash[s]
+ end
end
end
end
View
30 lib/geo_magic/point.rb
@@ -6,13 +6,22 @@ module GeoMagic
class Point
extend ClassMethods
extend Conversion
- extend Random
+ include Random
+ include GeoMagic::PointConverter
attr_accessor :latitude, :longitude
- def initialize latitude, longitude
- @latitude = latitude
- @longitude = longitude
+ def initialize *args
+ points = case args.size
+ when 2
+ args
+ when 1
+ to_point args
+ else
+ raise ArgumentError, "Must be array of numbers or Hash of latitude, longitude"
+ end
+ @latitude = points.first
+ @longitude = points.last
end
# factory method
@@ -27,6 +36,11 @@ def self.create_from *args
end
new latitude, longitude
end
+
+ def move dlat, dlong
+ @latitude += dlat
+ @longitude += dlong
+ end
def to_point_hash mode= :long
case mode
@@ -45,5 +59,13 @@ def to_location
def to_s
"(lat: #{latitude}, long: #{longitude})"
end
+
+ protected
+
+ def extract_from_hash hash
+ raise ArgumentError, "single argument must be a hash" if !hash.kind_of? Hash
+
+ end
+
end
end
View
5 lib/geo_magic/point/conversion.rb
@@ -21,6 +21,7 @@ def to_point
when nil
nil
when Array
+ return self.first.extend(GeoMagic::Point::Conversion).to_point if self.first.kind_of? Hash
self.map(&:to_f)
else
return [self.lat, self.lng] if self.respond_to? :lat
@@ -39,12 +40,12 @@ module PointConverter
def to_point v
return v if v.kind_of? Fixnum
- v.extend(Mongoid::Geo::Point).to_point
+ v.extend(GeoMagic::Point::Conversion).to_point
end
def to_points v
return v if v.kind_of? Fixnum
- v.extend(Mongoid::Geo::Point).to_points
+ v.extend(GeoMagic::Point::Conversion).to_points
end
end
end
View
8 lib/geo_magic/point/map_points.rb
@@ -5,8 +5,12 @@ module MapPoints
def rad
{:km => 6371, :miles => 3956, :feet => 20895592, :meters => 6371000}
end
-
- def within_distance dist_obj, options = {:precision => :lowest}
+
+ def within_radius radius_obj, options = {:precision => :lowest}
+ end
+
+ # todo: should make radius from distance!
+ def within_distance dist_obj, options = {:precision => :lowest}
calc_method = get_proc(options[:precision] || :normal)
from_loc = get_location get_dist_obj(options[:from])
View
37 lib/geo_magic/point/random.rb
@@ -1,27 +1,36 @@
+require 'geo_magic/util/normalizer'
+
module GeoMagic
class Point
- module Random
+ module Random
def move_random distance
- conversion = distance.unit.radians_ratio
-
- max_radius_rad = dist.distance
- range = (max_radius_rad * normalize).to_i
-
- dlong = (get_random_radiant(range) / normalize)
- dlat = (get_random_radiant(range) / normalize)
-
- @latitude += dlat
- @longitude += dlong
+ move random_deltas(range)
end
def create_random_at dist_lat, dist_long
- dlat = (get_random_radiant(range) / normalize) * conversion
-
- GeoMagic::Point.new dist.latitude + dlat, dist.longitude + dlong
+ r = range(distance)
+ dlat = random_delta(r) * conversion
+ dlong = random_delta(r) * conversion
+ GeoMagic::Point.new latitude + dlat, longitude + dlong
end
protected
+ include GeoMagic::Normalizer
+
+ # TODO: Should normalize according to unit, normalize should thus be part of distance or unit!?
+ def range distance
+ normalize(distance.in_radians)
+ end
+
+ def random_deltas range
+ [random_delta(range), random_delta(range)]
+ end
+
+ def random_delta range
+ denormalize(get_random_radiant(range))
+ end
+
def get_random_radiant(range)
GeoMagic::Radius.get_random_radiant(range)
end
View
36 lib/geo_magic/radius.rb
@@ -3,10 +3,44 @@
module GeoMagic
class Radius < Point
- def initialize latitude, longitude
+ def initialize arg
super
end
+ def self.types
+ [:circular, :rectangular, :square]
+ end
+
+ types.each do |name|
+ class_eval %{
+ def create_#{name} center, distance
+ #{GeoMagic::name.to_s.classify}Radius.new center, distance
+ end
+ }
+ end
+
+ def double
+ raise "Must be implemented by subclass. Should simply double the radius of the shape"
+ end
+
+ def halve
+ raise "Must be implemented by subclass. Should simply halve the radius of the shape"
+ end
+
+ def multiply arg
+ raise "Must be implemented by subclass. Should multiply size by a given factor"
+ end
+
+ # select all points within radius
+ def select_within points
+ raise "Must be implemented by subclass"
+ end
+
+ # reject all points within radius
+ def reject_within points
+ raise "Must be implemented by subclass"
+ end
+
def random_point_within
raise "Must be implemented by subclass"
end
View
10 lib/geo_magic/radius/circular.rb
@@ -4,9 +4,19 @@ class CircularRadius < Radius
def initialize center, distance
super center
+ raise ArgumentError, "#{self.class} distance must be a Distance" if !distance.kind_of? GeoMagic::Distance
@distance = distance
end
+ def multiply arg
+ raise ArgumentError, "Argument must be a Fixnum" if !arg.kind_of? Fixnum
+ self.distance *= arg
+ end
+
+ def to_s
+ "#{super}, #{distance}"
+ end
+
# Factory
def random_point_within
max_radius_rad = dist.distance
View
22 lib/geo_magic/radius/rectangular.rb
@@ -1,12 +1,18 @@
module GeoMagic
- class RectangularRadius
- attr_accessor :center, :vector
+ class RectangularRadius < Radius
+ attr_accessor :center, :vector_distance
- def initialize center, vector
+ def initialize center, vector_distance
super center
- @vector = vector
+ raise ArgumentError, "#{self.class} radius distance must be a Distance::Vector with lat and long distance" if !vector_distance.kind_of? GeoMagic::Distance::Vector
+ @vector_distance = vector_distance
end
+ def multiply arg
+ self.vector_distance.multiply arg
+ self
+ end
+
def create_from *args
case args.size
when 1
@@ -21,12 +27,16 @@ def create_from *args
end
end
+ def to_s
+ "#{super}, #{vector_distance}"
+ end
+
def lat_distance
- vector.lat_distance
+ vector_distance.lat_distance
end
def long_distance
- vector.long_distance
+ vector_distance.long_distance
end
# Factory
View
29 lib/geo_magic/radius/square.rb
@@ -4,9 +4,22 @@ class SquareRadius < Radius
def initialize center, distance
super center
+ raise ArgumentError, "#{self.class} distance must be a Distance" if !distance.kind_of? GeoMagic::Distance
@distance = distance
end
+ def multiply arg
+ case arg
+ when Fixnum
+ self.distance.multiply arg
+ self
+ when Hash
+ radius_from_factors [factor(arg, [:lat, :latitude]), factor(arg, [:long, :longitude])]
+ else
+ raise ArgumentError, "Argument must be a Fixnum or a Hash specifying factor to multiply latitude and/or longitude with" if !arg.kind_of?
+ end
+ end
+
# Factory
def random_point_within
conversion = GeoMagic::Distance.radians_ratio(distance.unit)
@@ -34,6 +47,22 @@ def random_points_within number
res << point
res
end
+ end
+
+ def to_s
+ "#{super}, #{distance}"
+ end
+
+ protected
+
+ def radius_from_factors factors
+ if factors.all_same?
+ self.distance.multiply factors.first
+ self
+ else
+ rectangle = GeoMagic::RectangularRadius.create_from self
+ rectangle.multiply arg
+ end
end
end
end
View
4 lib/geo_magic/vector.rb
@@ -8,6 +8,10 @@ def initialize p0, p1
@p1 = p1
end
+ def create_at center, vector
+ new center, center.move(vector)
+ end
+
def length type = nil
case type
when nil
View
13 spec/geo_magic/point/random_spec.rb
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+describe GeoMagic::Point::Random do
+ describe '#move_random' do
+ it "should move point to a random locationwithin 5 km" do
+ point = GeoMagic::Point.new -10, 20
+ puts point.methods.sort.grep /mov/
+ new_point = point.move_random 5.km
+ puts point.inspect
+ puts new_point.inspect
+ end
+ end
+end
View
16 spec/geo_magic/radius/circular_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe GeoMagic::CircularRadius do
+ describe '#new' do
+ let(:center) do
+ {:lat => 40, :long => 11}
+ end
+
+ let(:distance) { 3.2 }
+
+ it "should create a new circular radius" do
+ circle = GeoMagic::CircularRadius.new center, distance
+ puts circle.inspect
+ end
+ end
+end
View
18 spec/geo_magic/radius/rectangular_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+describe GeoMagic::RectangularRadius do
+ describe '#new' do
+ let(:center) do
+ {:lat => 40, :long => 11}
+ end
+
+ let(:vector_distance) do
+ {:lat => 1.2, :long => 0.4}
+ end
+
+ it "should create a new rectangular radius" do
+ rect = GeoMagic::RectangularRadius.new center, vector_distance
+ puts rect.inspect
+ end
+ end
+end
View
16 spec/geo_magic/radius/square_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe GeoMagic::SquareRadius do
+ describe '#new' do
+ let(:center) do
+ {:lat => 40, :long => 11}
+ end
+
+ let(:distance) { 0.5.km }
+
+ it "should create a new square radius" do
+ square = GeoMagic::SquareRadius.new center, distance
+ puts square.inspect
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.