laptimer-geometry 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/spec/geometry_spec.rb +18 -0
- data/spec/line_spec.rb +0 -9
- data/src/geometry.rb +23 -118
- data/src/line.rb +98 -0
- metadata +8 -8
- data/spec/lap_counter_spec.rb +0 -8
- data/src/lap_counter.rb +0 -2
@@ -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
|
data/spec/line_spec.rb
CHANGED
@@ -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})
|
data/src/geometry.rb
CHANGED
@@ -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
|
6
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
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
|
-
|
127
|
-
|
128
|
-
|
31
|
+
module_function :euclidean_distance
|
32
|
+
module_function :deg_2_rad
|
33
|
+
module_function :calculate_spherical_distance
|
129
34
|
end
|
data/src/line.rb
ADDED
@@ -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:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
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-
|
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
|
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/
|
32
|
-
- spec/
|
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/
|
68
|
+
- spec/geometry_spec.rb
|
69
69
|
- spec/line_spec.rb
|
data/spec/lap_counter_spec.rb
DELETED
data/src/lap_counter.rb
DELETED