Browse files

nice DSL in progress for distance

  • Loading branch information...
1 parent 609b232 commit cb0d3c163839b17b1cbe9fee64ef1ce220e489cb @kristianmandrup committed Feb 25, 2011
View
18 lib/geo_magic/distance.rb
@@ -21,15 +21,21 @@ def initialize distance, unit = nil
end
# select all points within radius
- def select_within points, center
- points.select do |p|
- point.within? center
- end
+ def select_all points
+ GeoMagic::PointsDistance.new self, points, :select
end
# reject all points within radius
- def reject_within points, center
-
+ def reject_all points
+ GeoMagic::PointsDistance.new self, points, :reject
+ end
+
+ [:<, :<=, :>, :>=, :==].each do |op|
+ class_eval %{
+ def #{op} dist_unit
+ in_meters #{op} dist_unit.in_meters
+ end
+ }
end
def * arg
View
12 lib/geo_magic/distance/points_distance.rb
@@ -1,16 +1,22 @@
module GeoMagic
class PointsDistance
- attr_accessor :distance, :points
+ attr_accessor :distance, :points, :mode
- def initialize distance, points
+ def initialize distance, points, mode = :select
raise ArgumentError, "First argument must be a GeoMagic::Distance, was #{distance}" if !distance.kind_of? GeoMagic::Distance
# raise ArgumentError, "First argument must be a collection of GeoMagic::Point, was #{points}" if !points.
self.distance = distance
self.points = points
+ self.mode = mode
end
def near center
- points.select {|point| point.within(distance).of(center) }
+ case mode
+ when :select
+ points.select {|point| point.within(distance).of(center) }
+ else
+ points.reject {|point| point.within(distance).of(center) }
+ end
end
end
end
View
20 lib/geo_magic/distance/unit.rb
@@ -1,3 +1,5 @@
+require 'geo_magic/distance'
+
module GeoMagic
class Distance
class Unit
@@ -9,29 +11,33 @@ def initialize name, number = 0
end
def meters_map
- {:miles => 0.0062,
+ {:miles => 0.00062,
:feet => 32.8,
- :km => 0.01,
+ :km => 0.001,
:meters => 1
}
end
- def in_meters
- meters_map[name.to_sym] * number
+ def in_meters
+ number / meters_map[name.to_sym]
end
def to_meters!
self.number = meters_map[name] * number
end
- [:miles, :feet, :km].each do |unit|
+ def self.units
+ [:miles, :km, :feet, :meters]
+ end
+
+ (units - [:meters]).each do |unit|
class_eval %{
def in_#{unit}
- to_meters * meters_map[#{unit}]
+ in_meters * meters_map[:#{unit}]
end
def to_#{unit}!
- self.number = to_meters * meters_map[#{unit}]
+ self.number = in_meters * meters_map[#{unit}]
self.name = :#{unit}
end
}
View
24 spec/geo_magic/distance/points_distance_spec.rb
@@ -10,11 +10,27 @@
end
context 'Distance vector' do
- subject { GeoMagic::PointsDistance.new 5.km, [@a, @b].to_points }
-
+
+
describe '#near' do
- it "should only select points near center" do
- subject.near(@center).should include(@a)
+ describe 'select' do
+ subject { GeoMagic::PointsDistance.new 5.km, [@a, @b].to_points, :select }
+
+ it "should only select points near center" do
+ res = subject.near(@center)
+ res.should include(@a)
+ res.should_not include(@b)
+ end
+ end
+
+ describe 'reject' do
+ subject { GeoMagic::PointsDistance.new 5.km, [@a, @b].to_points, :reject }
+
+ it "should only select points near center" do
+ res = subject.near(@center)
+ res.should_not include(@a)
+ res.should include(@b)
+ end
end
end
end
View
19 spec/geo_magic/distance/unit_spec.rb
@@ -5,7 +5,24 @@
subject { GeoMagic::Distance::Unit.new :km, 5 }
- its(:number) { should > 0 }
+ its(:number) { should > 0 }
its(:radians_ratio) { should > 0 }
+ its(:in_meters) { should == 5000 }
+ its(:in_feet) { should > 100 }
+ its(:in_km) { should == 5 }
+ its(:in_miles) { should < 5 }
+ end
+
+ context "5km and 7000m" do
+ before do
+ @km = GeoMagic::Distance::Unit.new :km, 5
+ @meters = GeoMagic::Distance::Unit.new :meters, 7000
+ end
+
+ it "should be that 5km is less than 7000m" do
+ (@km < @meters).should be_true
+ (@km > @meters).should be_false
+ (@km == @meters).should be_false
+ end
end
end
View
34 spec/geo_magic/distance_spec.rb
@@ -2,32 +2,36 @@
describe GeoMagic::Distance do
before do
- a = [45.1, 11].to_point
- b = [45.1, 11.1].to_point
- c = [48.1, 12.1].to_point
+ @a = [45.1, 11].to_point
+ @b = [45.1, 11.1].to_point
+ @c = [48.1, 12.1].to_point
@center = [45, 11].to_point
- @points = [a, b, c]
+ @points = [@a, @b, @c]
+ end
+
+ it "should be that 5km is less than 7000m" do
+ (5.km < 7000.meters).should be_true
end
subject { 5.km }
describe 'Select subset of points within distance' do
- describe '#select_within' do
- subject.select_within @points, @center
- end
-
describe '#select_all #near' do
- subject.select_all(@points).near(@center)
+ it "should select points near center" do
+ res = subject.select_all(@points).near(@center)
+ res.should include(@a)
+ res.should_not include(@c)
+ end
end
end
describe 'Reject subset of points within distance' do
- describe '#reject_within' do
- subject.reject_near @points, @center
- end
-
- describe '#reject_all #within' do
- subject.reject_all(@points).near(@center)
+ describe '#reject_all' do
+ it "should select points near center" do
+ res = subject.reject_all(@points).near(@center)
+ res.should_not include(@a)
+ res.should include(@c)
+ end
end
end
end

0 comments on commit cb0d3c1

Please sign in to comment.