geodesy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5895d5c7c414ff0ead805f95cafa9bd69580c9cc
4
+ data.tar.gz: de52ebeb588d32fe325d6fe2597796ae8843e87e
5
+ SHA512:
6
+ metadata.gz: 6ccd58b4bf1bfae19720d938e49ab57337686b4881e0793f8b4978802c8ac4a8116e6f2b33d5704147ffb34a6b5d89837944d27e29264c8beefcb779d7400116
7
+ data.tar.gz: ab3c1e4bccdfb2f6e911ac94b790ba65ddf00aeab7fd570df0251bfd6b11bf86eaf6cb3af90123d4947762033959ea147468b7b5feeab6d2309a1abf8a221add
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+ ruby '2.2.0'
3
+
4
+ # Specify your gem's dependencies in geodesy.gemspec
5
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Robert Evans
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # Geodesy
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << "test"
6
+ t.test_files = FileList['test/**/**/*_test.rb']
7
+ t.verbose = true
8
+ end
9
+
10
+ task :default => 'test'
data/geodesy.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'geodesy/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "geodesy"
8
+ spec.version = Geodesy::VERSION
9
+ spec.authors = ["Robert Evans"]
10
+ spec.email = ["robert@codewranglers.org"]
11
+ spec.summary = %q{Some simple Geo-Calculations}
12
+ spec.description = %q{Simple Geo-Calculations}
13
+ spec.homepage = "http://www.codewranglers.org"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "minitest"
24
+ end
@@ -0,0 +1,32 @@
1
+
2
+ module Geodesy
3
+ class Bearing
4
+ using FloatExtension
5
+
6
+ attr_reader :starting_point, :ending_point
7
+
8
+ #
9
+ # start_point is a Geodesy::Coordinates
10
+ # end_point is a Geodesy::Coordinates
11
+ #
12
+ def initialize(start_point, end_point)
13
+ @starting_point = start_point
14
+ @ending_point = end_point
15
+ end
16
+
17
+ def calculate
18
+ start_lat_in_radians = starting_point.lat.to_radians
19
+ end_lat_in_radians = ending_point.lat.to_radians
20
+ delta = (ending_point.lng.angle - starting_point.lng.angle).to_radians
21
+
22
+ # formula: http://mathforum.org/library/drmath/view/55417.html
23
+ y = Math.sin(delta) * Math.cos(end_lat_in_radians)
24
+ x = ( Math.cos(start_lat_in_radians) * Math.sin(end_lat_in_radians) ) -
25
+ ( Math.sin(start_lat_in_radians) * Math.cos(end_lat_in_radians) * Math.cos(delta) )
26
+ z = Math.atan2(y, x)
27
+
28
+ ( z.to_degrees + 360 ) % 360
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,42 @@
1
+
2
+ module Geodesy
3
+ COMPASS_POINTS = %w[N NE E SE S SW W NW]
4
+ EARTH_RADIUS = 6371.0
5
+ KM_TO_MI = 0.621371192
6
+ DEGREES_PER_RADIAN = 57.2957795
7
+ YARDS_PER_METER = 1.09361
8
+ METERS_TO_YARDS = 0.9144
9
+
10
+ module Conversions
11
+ extend self
12
+
13
+ def kilometers_to_miles
14
+ KM_TO_MI
15
+ end
16
+
17
+ def miles_to_kilometers
18
+ 1.0 / KM_TO_MI
19
+ end
20
+
21
+ def meters_to_yards
22
+ METERS_TO_YARDS
23
+ end
24
+
25
+ def yards_to_meters
26
+ YARDS_PER_METER
27
+ end
28
+
29
+ def feet_to_yards
30
+ 3
31
+ end
32
+
33
+ def yards_to_feet
34
+ 3
35
+ end
36
+
37
+ def feet_to_inches
38
+ 12
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,16 @@
1
+ require_relative 'latitude'
2
+ require_relative 'longitude'
3
+
4
+ module Geodesy
5
+ class Coordinates
6
+ attr_reader :lat, :lng, :altitude, :radius
7
+
8
+ def initialize(lat, lng, altitude = nil)
9
+ @lat = Geodesy::Latitude.new(lat)
10
+ @lng = Geodesy::Longitude.new(lng)
11
+ @altitude = altitude
12
+ @radius = Geodesy::EARTH_RADIUS # in kilometers
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,40 @@
1
+
2
+ module FloatExtension
3
+ refine Float do
4
+
5
+ # Assumes degrees to radians
6
+ def to_radians
7
+ self * Math::PI / 180
8
+ end
9
+
10
+ # assumes radians to degrees
11
+ def to_degrees
12
+ self * 180 / Math::PI
13
+ end
14
+
15
+ def to_kilometers(miles)
16
+ miles * Geodesy::Conversions.miles_to_kilometers
17
+ end
18
+
19
+ def to_miles(kilometers)
20
+ kilometers * Geodesy::Conversions.kilometers_to_miles
21
+ end
22
+
23
+ def to_meters(yards)
24
+ yards * Geodesy::Conversions.yards_to_meters
25
+ end
26
+
27
+ def to_yards(meters)
28
+ meters * Geodesy::Conversions.meters_to_yards
29
+ end
30
+
31
+ def to_feet(yards)
32
+ yards * Geodesy::Conversions.yards_to_feet
33
+ end
34
+
35
+ def to_inches(feet)
36
+ feet * Geodesy::Conversions.feet_to_inches
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,44 @@
1
+ #
2
+ # Will return a coordinate based on a starting point, the bearing,
3
+ # and the distance.
4
+ #
5
+ module Geodesy
6
+ class Destination
7
+ using FloatExtension
8
+
9
+ attr_reader :starting_point, :distance, :bearing, :radius
10
+
11
+ #
12
+ # StartingPoint is a Coordinate Object
13
+ # Bearing is a Float Object
14
+ # Distance is an Integer or Float Object - default units: meters
15
+ #
16
+ def initialize(starting_point, bearing, distance)
17
+ @starting_point = starting_point
18
+ @radius = Geodesy::EARTH_RADIUS
19
+ @bearing = bearing
20
+ @distance = distance
21
+ end
22
+
23
+ def calculate
24
+ angular_distance = distance / radius
25
+ bearing_to_radians = bearing.to_radians
26
+ lat_radians = starting_point.lat.to_radians
27
+ lng_radians = starting_point.lng.to_radians
28
+
29
+ x = Math.asin(
30
+ ( Math.sin(lat_radians) * Math.cos(angular_distance) ) +
31
+ ( Math.cos(lat_radians) * Math.sin(angular_distance) * Math.cos(bearing_to_radians) )
32
+ )
33
+ y = lng_radians + Math.atan2(
34
+ Math.sin(bearing_to_radians) * Math.sin(angular_distance) * Math.cos(lat_radians),
35
+ Math.cos(angular_distance) - Math.sin(lat_radians) * Math.sin(x)
36
+ )
37
+ # normalize y to -180°..+180°
38
+ z = ( y + 3 * Math::PI ) % ( 2 * Math::PI ) - Math::PI
39
+
40
+ Coordinates.new( x.to_degrees, z.to_degrees )
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,17 @@
1
+
2
+ module Geodesy
3
+ class Latitude
4
+ using FloatExtension
5
+
6
+ attr_reader :angle
7
+
8
+ def initialize(lat)
9
+ @angle = lat
10
+ end
11
+
12
+ def to_radians
13
+ angle.to_radians
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+
2
+ module Geodesy
3
+ class Longitude
4
+ using FloatExtension
5
+
6
+ attr_reader :angle
7
+
8
+ def initialize(lng)
9
+ @angle = lng
10
+ end
11
+
12
+ def to_radians
13
+ angle.to_radians
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Geodesy
2
+ VERSION = "0.0.1"
3
+ end
data/lib/geodesy.rb ADDED
@@ -0,0 +1,45 @@
1
+ require "geodesy/version"
2
+ require 'geodesy/conversions'
3
+ require 'geodesy/core_ext/float_extension'
4
+ require 'geodesy/coordinates'
5
+ require 'geodesy/bearing'
6
+ require 'geodesy/destination'
7
+
8
+
9
+ module Geodesy
10
+ extend self
11
+
12
+ #
13
+ # starting is an array of [ lat, lng ]
14
+ # ending is an array of [ lat, lng ]
15
+ #
16
+ ### Returns
17
+ #
18
+ # It returns a floating point number
19
+ #
20
+ def bearing(starting, ending)
21
+ Bearing.new(
22
+ Coordinates.new(*starting),
23
+ Coordinates.new(*ending)
24
+ ).calculate
25
+ end
26
+
27
+
28
+ #
29
+ # starting is an array of [ lat, lng ]
30
+ # bearing is a float
31
+ # distance is an integer or float - units: meters
32
+ #
33
+ ### Returns
34
+ #
35
+ # It returns a Coordinates Object
36
+ #
37
+ def final_coordinate(starting, bearing, distance = 10)
38
+ Destination.new(
39
+ Coordinates.new(*starting),
40
+ bearing,
41
+ distance
42
+ ).calculate
43
+ end
44
+
45
+ end
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+
3
+ module Geodesy
4
+ class BearingTest < Minitest::Test
5
+
6
+ def tee_point
7
+ @tee_point ||= Coordinates.new(33.27254375003685, -117.2873803284383)
8
+ end
9
+
10
+ def green_point
11
+ @green_point ||= Coordinates.new(33.269139395705295, -117.28715699010904)
12
+ end
13
+
14
+
15
+ def test_initialization
16
+ bearing = Bearing.new(tee_point, green_point)
17
+
18
+ assert_equal tee_point, bearing.starting_point
19
+ assert_equal green_point, bearing.ending_point
20
+ end
21
+
22
+
23
+ def test_calculation
24
+ bearing = Bearing.new(tee_point, green_point)
25
+
26
+ assert_equal 176.86038830369012, bearing.calculate
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ require 'test_helper'
2
+
3
+ class CoordinatesTest < Minitest::Test
4
+ def lat
5
+ @lat ||= Geodesy::Latitude.new(33.26926373135873)
6
+ end
7
+
8
+ def lng
9
+ @lng ||= Geodesy::Longitude.new(-117.2871651469912)
10
+ end
11
+
12
+ def test_initialization
13
+ coord = Geodesy::Coordinates.new(33.26926373135873,
14
+ -117.2871651469912)
15
+
16
+ assert_equal lat.angle, coord.lat.angle
17
+ assert_equal lng.angle, coord.lng.angle
18
+ assert_nil coord.altitude
19
+ assert_equal Geodesy::EARTH_RADIUS, coord.radius
20
+ end
21
+
22
+ end
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+
3
+ module Geodesy
4
+ class DestinationTest < Minitest::Test
5
+
6
+ def starting_point
7
+ @starting_points ||= Coordinates.new(33.269139395705295,
8
+ -117.28715699010904)
9
+ end
10
+
11
+ def bearing
12
+ 176.86038830369012
13
+ end
14
+
15
+
16
+ def test_initialization
17
+ dest = Destination.new(starting_point, bearing, 20)
18
+
19
+ assert_equal starting_point, dest.starting_point
20
+ assert_equal bearing, dest.bearing
21
+ assert_equal 20, dest.distance
22
+ assert_equal 6371.0, dest.radius
23
+ end
24
+
25
+
26
+ def test_calculate
27
+ dest = Destination.new(starting_point, bearing, 20)
28
+
29
+ assert_equal 33.08954448933676, dest.calculate.lat.angle
30
+ assert_equal -117.27539907324454, dest.calculate.lng.angle
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ class Point
4
+ using FloatExtension
5
+
6
+ attr_reader :lat, :lng
7
+
8
+ def initialize(point)
9
+ @lat, @lng = *point
10
+ end
11
+
12
+ def lat_to_radians
13
+ lat.to_radians
14
+ end
15
+
16
+ def lng_to_radians
17
+ lng.to_radians
18
+ end
19
+
20
+
21
+ def to_degrees(radians)
22
+ radians.to_degrees
23
+ end
24
+
25
+ end
26
+
27
+ class FloatExtensionTest < Minitest::Test
28
+ def point
29
+ @point ||= Point.new([33.26926373135873, -117.2871651469912])
30
+ end
31
+
32
+ def test_initialization
33
+ assert_equal 33.26926373135873, point.lat
34
+ assert_equal -117.2871651469912, point.lng
35
+ end
36
+
37
+
38
+ def test_radians
39
+ assert_equal 0.5806581918265441, point.lat_to_radians
40
+ assert_equal -2.0470472021453356, point.lng_to_radians
41
+ end
42
+
43
+
44
+ def test_degrees
45
+ assert_equal 33.269263731358734, point.to_degrees(point.lat_to_radians)
46
+ assert_equal point.lng, point.to_degrees(point.lng_to_radians).round(13)
47
+ end
48
+
49
+ end
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+
3
+ class GeodesyTest < Minitest::Test
4
+ def starting_point
5
+ [ 33.27254375003685,
6
+ -117.2873803284383 ]
7
+ end
8
+
9
+ def ending_point
10
+ [ 33.269139395705295,
11
+ -117.28715699010904]
12
+ end
13
+
14
+ def bearing
15
+ 176.86038830369012
16
+ end
17
+
18
+
19
+ def test_bearing
20
+ assert_equal bearing,
21
+ Geodesy.bearing(starting_point,
22
+ ending_point)
23
+ end
24
+
25
+
26
+ def test_final_coordinate
27
+ final_coord = Geodesy.final_coordinate(
28
+ ending_point,
29
+ bearing,
30
+ 20
31
+ )
32
+
33
+ assert_equal 33.08954448933676,
34
+ final_coord.lat.angle
35
+
36
+ assert_equal -117.27539907324454,
37
+ final_coord.lng.angle
38
+ end
39
+
40
+ end
@@ -0,0 +1,18 @@
1
+ require 'test_helper'
2
+
3
+ class LatitudeTest < Minitest::Test
4
+
5
+ def lat
6
+ 33.26926373135873
7
+ end
8
+
9
+ def test_initialization
10
+ assert_equal lat, Geodesy::Latitude.new(lat).angle
11
+ end
12
+
13
+ def test_radians
14
+ assert_equal 0.5806581918265441,
15
+ Geodesy::Latitude.new(lat).to_radians
16
+ end
17
+
18
+ end
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+
3
+ class LongitudeTest < Minitest::Test
4
+
5
+ def lng
6
+ -117.2871651469912
7
+ end
8
+
9
+ def test_initialization
10
+ assert_equal lng,
11
+ Geodesy::Longitude.new(lng).angle
12
+ end
13
+
14
+ def test_radians
15
+ assert_equal -2.0470472021453356,
16
+ Geodesy::Longitude.new(lng).to_radians
17
+ end
18
+
19
+ end
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'geodesy'
3
+ require 'minitest/autorun'
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geodesy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Robert Evans
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Simple Geo-Calculations
56
+ email:
57
+ - robert@codewranglers.org
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - geodesy.gemspec
68
+ - lib/geodesy.rb
69
+ - lib/geodesy/bearing.rb
70
+ - lib/geodesy/conversions.rb
71
+ - lib/geodesy/coordinates.rb
72
+ - lib/geodesy/core_ext/float_extension.rb
73
+ - lib/geodesy/destination.rb
74
+ - lib/geodesy/latitude.rb
75
+ - lib/geodesy/longitude.rb
76
+ - lib/geodesy/version.rb
77
+ - test/bearing_test.rb
78
+ - test/coordinates_test.rb
79
+ - test/destination_test.rb
80
+ - test/float_extension_test.rb
81
+ - test/geodesy_test.rb
82
+ - test/latitude_test.rb
83
+ - test/longitude_test.rb
84
+ - test/test_helper.rb
85
+ homepage: http://www.codewranglers.org
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.4.5
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: Some simple Geo-Calculations
109
+ test_files:
110
+ - test/bearing_test.rb
111
+ - test/coordinates_test.rb
112
+ - test/destination_test.rb
113
+ - test/float_extension_test.rb
114
+ - test/geodesy_test.rb
115
+ - test/latitude_test.rb
116
+ - test/longitude_test.rb
117
+ - test/test_helper.rb
118
+ has_rdoc: