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 +7 -0
- data/lib/gps_tools.rb +20 -0
- data/lib/gps_tools/distance.rb +33 -0
- data/lib/gps_tools/geometry.rb +101 -0
- metadata +67 -0
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: []
|