laptimer-geometry 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Geometry do
4
+ it "should calculate the distance using the Earth radius Nelson Piquet" do
5
+ point1 = {:x => -47.900648, :y => -15.772954}
6
+ point2 = {:x => -47.900365, :y => -15.772869}
7
+ point3 = {:x => -47.90025, :y => -15.772835}
8
+ Geometry.calculate_spherical_distance(point1, point2).should be_true
9
+ Geometry.calculate_spherical_distance(point1, point3).should be_true
10
+ end
11
+
12
+ it "should find the exact distance between 2 points on the earth" do
13
+ point1 = {:x => -47.900331, :y => -15.77284}
14
+ point2 = {:x => -47.897064, :y => -15.77171}
15
+ distance = Geometry.calculate_spherical_distance(point1, point2)
16
+ distance.should be_within(0.001).of(0.372) # in Km
17
+ end
18
+ end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require File.expand_path('../../src/geometry', __FILE__)
3
2
 
4
3
  describe Line do
5
4
  before do
@@ -112,14 +111,6 @@ describe Line do
112
111
  flag_line.intercept_line_segment?(segment1).should be_false
113
112
  end
114
113
 
115
- it "should calculate the distance using the Earth radius Nelson Piquet" do
116
- point1 = {:x => -47.900648, :y => -15.772954}
117
- point2 = {:x => -47.900365, :y => -15.772869}
118
- point3 = {:x => -47.90025, :y => -15.772835}
119
- Geometry.calculate_distance(point1, point2).should be_true
120
- Geometry.calculate_distance(point1, point3).should be_true
121
- end
122
-
123
114
  it "should find the crossing segment with some real coordinates - Aut. Nelson Piquet" do
124
115
  flag_line = Line.new({:x => -47.900333, :y => -15.772656, }, {:x => -47.900148, :y => -15.773056})
125
116
  segment1 = Line.new({:x => -47.900648, :y => -15.772954}, {:x =>-47.899923, :y => -15.772683})
@@ -1,129 +1,34 @@
1
1
  module Geometry
2
2
  include Math
3
3
  extend Math
4
+
5
+ # Earth radius near Equator Line
6
+ EARTH_RADIUS = 6378
4
7
 
5
- def distance(point1, point2)
6
- x1 = (point1[:x] > 0) ? point1[:x] : (point1[:x]*-1 )
7
- x2 = (point2[:x] > 0) ? point2[:x] : (point2[:x]*-1 )
8
- y1 = (point1[:y] > 0) ? point1[:y] : (point1[:y]*-1 )
9
- y2 = (point2[:y] > 0) ? point2[:y] : (point2[:y]*-1 )
10
- hypot x1 - x2, y1 - y2
8
+ def euclidean_distance(point1, point2)
9
+ hypot point1[:x] - point2[:x], point1[:y] - point2[:y]
11
10
  end
12
11
 
13
- def calculate_distance(point1, point2)
14
- x1 = point1[:x] * Math::PI / 180
15
- x2 = point2[:x] * Math::PI / 180
16
- y1 = point1[:y] * Math::PI / 180
17
- y2 = point2[:y] * Math::PI / 180
18
-
19
- s = sin(y2)*sin(y1)+(cos(y2)*cos(y1)*cos(x2 - x1))
20
- rad_distance = acos(s)
21
- degree_distance = rad_distance/(Math::PI/180)
22
- earth_radius = 6378
23
- distance_km = earth_radius*degree_distance
24
- distance_km
25
- end
26
-
27
- module_function :distance
28
- module_function :calculate_distance
29
- end
30
-
31
- class Line
32
- include Math
33
- def initialize(pointA, pointB)
34
- @a, @b, @c = nil, nil, nil
35
- @gradient = nil
36
- @linear = nil
37
- @pointA = pointA
38
- @pointB = pointB
39
- calculate_gradient
40
- calculate_linear
41
- end
42
-
43
- def pointA
44
- @pointA
45
- end
46
-
47
- def pointB
48
- @pointB
49
- end
50
-
51
- def gradient(ac = nil)
52
- if ac.nil?
53
- @gradient
54
- else
55
- @gradient = ac
56
- end
57
-
58
- @gradient
59
- end
60
-
61
- # m(x2-x1) - y2 + y1 = 0
62
- def include?(point)
63
- result = @gradient * (point[:x] - @pointA[:x]) - point[:y] + @pointA[:y]
64
- if(result == 0)
65
- true
66
- else
67
- false
68
- end
69
- end
12
+ def calculate_spherical_distance(point1, point2)
13
+ x1 = deg_2_rad(point1[:x])
14
+ x2 = deg_2_rad(point2[:x])
15
+ y1 = deg_2_rad(point1[:y])
16
+ y2 = deg_2_rad(point2[:y])
70
17
 
71
- def intercept?(line)
72
- (intercept_at(line).nil? == true) ? false : true
73
- end
74
18
 
75
- def intercept_at(line)
76
- if @gradient != line.gradient
77
- x = calculate_x_from_two_lines(self, line)
78
- y = (@gradient*x.to_f) + @linear
79
-
80
- new_point = { :x => sprintf('%.6f',x).to_f, :y => sprintf('%.6f',y).to_f}
81
- return new_point
82
- end
83
-
84
- return nil
85
- end
86
-
87
- def linear_touch
88
- @linear
89
- end
90
-
91
- def intercept_line_segment?(line)
92
-
93
- # verify the distance
94
- if intercept?(line)
95
- interception_point = intercept_at(line)
96
-
97
- distance_segment = Geometry.calculate_distance(line.pointA, line.pointB)
98
- distance_A_line_segment = Geometry.calculate_distance(line.pointA, interception_point)
99
- distance_B_line_segment = Geometry.calculate_distance(line.pointB, interception_point)
100
-
101
- if distance_A_line_segment > distance_segment
102
- return false
103
- elsif distance_B_line_segment > distance_segment
104
- return false
105
- else
106
- return true
107
- end
108
- end
109
-
110
- return false
111
- end
112
-
113
- private
114
- def calculate_gradient
115
- @gradient = (@pointB[:y] - @pointA[:y]) / (@pointB[:x] - @pointA[:x]).to_f
116
- end
19
+ dlon = x2 - x1
20
+ dlat = y2 - y1
21
+ a = (sin(dlat/2))**2 + cos(y1) * cos(y2) * (sin(dlon/2))**2
22
+ c = 2 * atan2( sqrt(a), sqrt(1-a) )
23
+ d = 6378 * c
24
+ end
117
25
 
118
- def calculate_linear
119
- @linear = nil
120
- if not @gradient.nil?
121
- @linear = @pointA[:y].to_f - (@gradient * @pointA[:x].to_f )
122
- end
123
- @linear
124
- end
26
+ def deg_2_rad(deg)
27
+ rad = deg * Math::PI/180;
28
+ rad
29
+ end
125
30
 
126
- def calculate_x_from_two_lines(line1, line2)
127
- (line2.linear_touch - line1.linear_touch) / (line1.gradient - line2.gradient)
128
- end
31
+ module_function :euclidean_distance
32
+ module_function :deg_2_rad
33
+ module_function :calculate_spherical_distance
129
34
  end
@@ -0,0 +1,98 @@
1
+ class Line
2
+ def initialize(pointA, pointB)
3
+ @a, @b, @c = nil, nil, nil
4
+ @gradient = nil
5
+ @linear = nil
6
+ @pointA = pointA
7
+ @pointB = pointB
8
+ calculate_gradient
9
+ calculate_linear
10
+ end
11
+
12
+ def pointA
13
+ @pointA
14
+ end
15
+
16
+ def pointB
17
+ @pointB
18
+ end
19
+
20
+ def gradient(ac = nil)
21
+ if ac.nil?
22
+ @gradient
23
+ else
24
+ @gradient = ac
25
+ end
26
+
27
+ @gradient
28
+ end
29
+
30
+ # m(x2-x1) - y2 + y1 = 0
31
+ def include?(point)
32
+ result = @gradient * (point[:x] - @pointA[:x]) - point[:y] + @pointA[:y]
33
+ if(result == 0)
34
+ true
35
+ else
36
+ false
37
+ end
38
+ end
39
+
40
+ def intercept?(line)
41
+ (intercept_at(line).nil? == true) ? false : true
42
+ end
43
+
44
+ def intercept_at(line)
45
+ if @gradient != line.gradient
46
+ x = calculate_x_from_two_lines(self, line)
47
+ y = (@gradient*x.to_f) + @linear
48
+
49
+ new_point = { :x => sprintf('%.6f',x).to_f, :y => sprintf('%.6f',y).to_f}
50
+ return new_point
51
+ end
52
+
53
+ return nil
54
+ end
55
+
56
+ def linear_touch
57
+ @linear
58
+ end
59
+
60
+ def intercept_line_segment?(line)
61
+
62
+ # verify the distance
63
+ if intercept?(line)
64
+ interception_point = intercept_at(line)
65
+
66
+ distance_segment = Geometry.calculate_spherical_distance(line.pointA, line.pointB)
67
+ distance_A_line_segment = Geometry.calculate_spherical_distance(line.pointA, interception_point)
68
+ distance_B_line_segment = Geometry.calculate_spherical_distance(line.pointB, interception_point)
69
+
70
+ if distance_A_line_segment > distance_segment
71
+ return false
72
+ elsif distance_B_line_segment > distance_segment
73
+ return false
74
+ else
75
+ return true
76
+ end
77
+ end
78
+
79
+ return false
80
+ end
81
+
82
+ private
83
+ def calculate_gradient
84
+ @gradient = (@pointB[:y] - @pointA[:y]) / (@pointB[:x] - @pointA[:x]).to_f
85
+ end
86
+
87
+ def calculate_linear
88
+ @linear = nil
89
+ if not @gradient.nil?
90
+ @linear = @pointA[:y].to_f - (@gradient * @pointA[:x].to_f )
91
+ end
92
+ @linear
93
+ end
94
+
95
+ def calculate_x_from_two_lines(line1, line2)
96
+ (line2.linear_touch - line1.linear_touch) / (line1.gradient - line2.gradient)
97
+ end
98
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: laptimer-geometry
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Eduardo Marques
@@ -15,10 +15,10 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-10-03 00:00:00 Z
18
+ date: 2011-10-14 00:00:00 Z
19
19
  dependencies: []
20
20
 
21
- description: " laptimer-geometry is a gem created to help the coordinates calculations used in a laptimer software.\n"
21
+ description: " laptimer-geometry is a gem created to help the coordinate calculations used in laptimer software.\n v0.0.2 \n - Added a new method to calculate distance between two geographic points\n - Improved the accuracy of the distance calculation\n"
22
22
  email: edhana@gmail.com
23
23
  executables: []
24
24
 
@@ -28,8 +28,8 @@ extra_rdoc_files: []
28
28
 
29
29
  files:
30
30
  - src/geometry.rb
31
- - src/lap_counter.rb
32
- - spec/lap_counter_spec.rb
31
+ - src/line.rb
32
+ - spec/geometry_spec.rb
33
33
  - spec/line_spec.rb
34
34
  homepage: http://github.com/edhana/laptimer-geometry
35
35
  licenses: []
@@ -65,5 +65,5 @@ signing_key:
65
65
  specification_version: 3
66
66
  summary: Implementation of basic 2D geometry algorithms, to help with a lap timer system written in Ruby
67
67
  test_files:
68
- - spec/lap_counter_spec.rb
68
+ - spec/geometry_spec.rb
69
69
  - spec/line_spec.rb
@@ -1,8 +0,0 @@
1
- require 'spec_helper'
2
- require File.expand_path('../../src/lap_counter', __FILE__)
3
-
4
- describe LapCounter do
5
- it "should find a straight segment witch is valid" do
6
- true.should be_true
7
- end
8
- end
@@ -1,2 +0,0 @@
1
- class LapCounter
2
- end