gps_tools 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f34883d049d7636e5425c8e21baa8b2d3db4329cbc5e0e19e5a68fdae380b2ee
4
+ data.tar.gz: e1bfa8b3b062c361c6137231262003e368d4b33a5855a7faa48217bcc5d6bb86
5
+ SHA512:
6
+ metadata.gz: db5312a54634fd9acea85c51f20789f463dcf952dc4e22d4cc4a249699866d84107abad20cb359b0d770aed11bf4841105faaf8cf39c757aabbc9293287ba201
7
+ data.tar.gz: f8d2e305358eeffd2acd3e1530ac2c9a0bde6f0a07d2dac3309bcdc24b1e00bd0c672708352d243c1374a576e7092291b205899cd54aa4f5ea5d59c38df9b4b6
data/lib/gps_tools.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'gps_tools/distance'
2
+ require 'gps_tools/geometry'
3
+
4
+ class GPSTools
5
+ ##
6
+ # Returns the distance in miles (unit = "mile"), kilometers (unit = "km"), or nautical miles (unit = "nm")
7
+ # between two gps coordinates, coord1 and coord2
8
+ def self.distance(coord1, coord2, unit = "mile")
9
+ distance_tool = Distance.new(unit)
10
+ return distance_tool.get_distance(coord1[0], coord1[1], coord2[0], coord2[1])
11
+ end
12
+
13
+ ##
14
+ # Returns a boolean that identifies if a given gps coordinate, coord, is within
15
+ # a given polygon (array of [lat, lng])
16
+ def self.in_polygon?(polygon, coord)
17
+ geometry = Geometry.new()
18
+ return geometry.in_polygon?(polygon, coord)
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ class Distance
2
+ def initialize(unit = "mile")
3
+ @unit = unit
4
+ case @unit
5
+ when "mile"
6
+ @earth_radius = 3958.8
7
+ when "km"
8
+ @earth_radius = 6378
9
+ when "nm"
10
+ @earth_radius = 3440.1
11
+ end
12
+ end
13
+
14
+ def get_distance(coord1, coord2)
15
+ lat1 = coord1[0]
16
+ long1 = coord1[1]
17
+ lat2 = coord2[0]
18
+ long2 = coord2[1]
19
+
20
+ lat_diff = lat2 - lat1
21
+ long_diff = long2 - long1
22
+
23
+ a = Math.sin(degrees_to_radians(lat_diff)/2) * Math.sin(degrees_to_radians(lat_diff)/2) + Math.sin(degrees_to_radians(long_diff)/2) * Math.sin(degrees_to_radians(long_diff)/2) * Math.cos(degrees_to_radians(lat1)) * Math.cos(degrees_to_radians(lat2))
24
+ c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
25
+
26
+ return @earth_radius * c
27
+ end
28
+
29
+ private
30
+ def degrees_to_radians(degrees)
31
+ degrees * Math::PI / 180
32
+ end
33
+ end
@@ -0,0 +1,101 @@
1
+ class Geometry
2
+ def in_radius?(radius, center, coord)
3
+ distance = Distance.new.get_distance(center, coord)
4
+ distance <= radius
5
+ end
6
+
7
+ def in_polygon?(polygon, coord)
8
+ n = polygon.length
9
+
10
+ # Polygon must have at least 3 points
11
+ if n < 3
12
+ return false
13
+ end
14
+
15
+ extreme_point = [10000, coord[1]]
16
+
17
+ intersections = 0
18
+ i = 0
19
+
20
+ while i < n do
21
+ if i == n -1
22
+ next_point = polygon[0]
23
+ else
24
+ next_point = polygon[i+1]
25
+ end
26
+
27
+ if intersect?(polygon[i], next_point, coord, extreme_point)
28
+
29
+ # Special case - catches case where point is on an edge
30
+ # if lies on an edge, return true right away
31
+ if orientation(polygon[i], coord, next_point) == 0 && on_segment(polygon[i], coord, next_point)
32
+ return true
33
+ end
34
+
35
+ intersections += 1
36
+ end
37
+ i += 1
38
+ end
39
+
40
+ # If odd number of intersections, we're good, if even, outside of polygon
41
+ intersections % 2 == 1
42
+ end
43
+
44
+ private
45
+ def max(a, b)
46
+ a > b ? a : b
47
+ end
48
+
49
+ def min(a, b)
50
+ a > b ? b : a
51
+ end
52
+
53
+ # Checks if point q is on the line between point p and point r
54
+ def on_segment(p, q, r)
55
+ q[0] <= max(p[0], r[0]) && q[0] >= min(p[0], r[0]) && q[1] <= max(p[1], r[1]) && q[1] >= min(p[1], r[1])
56
+ end
57
+
58
+
59
+ # Determine how three points are oriented relative to each other in given order
60
+ # 0 => colinear
61
+ # 1 => clockwise
62
+ # 2 => counter-clockwise
63
+ def orientation(p, q, r)
64
+ val = ((q[1] - p[1]) * (r[0] - q[0])) - ((q[0] - p[0]) * (r[1] - q[1]))
65
+
66
+ # If above calculation is exactly 0, the three points must be colinear
67
+ if val == 0
68
+ return 0
69
+ else
70
+ # Positive value from above calculation means oriented clockwise
71
+ if val > 0
72
+ return 1
73
+ # PNegative value from above calculation means oriented counter-clockwise
74
+ else
75
+ return 2
76
+ end
77
+ end
78
+ end
79
+
80
+ # Check if two lines (p1q1 and p2q2) intersect
81
+ # This is used to determine if a point is within a polygon
82
+ def intersect?(p1, q1, p2, q2)
83
+ # We need to look at 4 different orientations to determine intersection
84
+ o1 = orientation(p1, q1, p2)
85
+ o2 = orientation(p1, q1, q2)
86
+ o3 = orientation(p2, q2, p1)
87
+ o4 = orientation(p2, q2, q1)
88
+
89
+ # General case - if these two pairs are both unequal, we know we have an intersection
90
+ if o1 != o2 && o3 != o4
91
+ return true
92
+ end
93
+
94
+ # Edge cases
95
+ if (o1 == 0 && on_segment(p1, p2, q1)) || (o2 == 0 && on_segment(p1, q2, q1)) || (o3 == 0 && on_segment(p2, p1, q2)) || (o4 == 0 && on_segment(p2, q1, q2))
96
+ return true
97
+ end
98
+
99
+ return false
100
+ end
101
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gps_tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dave Van Fleet
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-08-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: Library of tools for gps coordinates. Useful for quickly calculating
28
+ distances, calculating if location is within specified polygon or radius, etc.
29
+ email: dvfleet413@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - lib/gps_tools.rb
35
+ - lib/gps_tools/distance.rb
36
+ - lib/gps_tools/geometry.rb
37
+ homepage: https://rubygems.org/gems/gps_tools
38
+ licenses:
39
+ - MIT
40
+ metadata: {}
41
+ post_install_message:
42
+ rdoc_options:
43
+ - "-m"
44
+ - README.rdoc
45
+ - "-x"
46
+ - lib/(?!gps_tools.rb).*
47
+ - lib/gps_tools.rb
48
+ - LICENSE
49
+ - README.rdoc
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.2.3
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: Library of tools for gps coordinates.
67
+ test_files: []