# kristianmandrup/geo_magic

nice DSL in progress for distance

1 parent 609b232 commit cb0d3c163839b17b1cbe9fee64ef1ce220e489cb committed Feb 25, 2011
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
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
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 }
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
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
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