quadtree 1.0.7 → 1.0.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 93b38a02013f5c97126e742d2262be25f388e4c1
4
- data.tar.gz: 82bb915f6bddf1f6c1f187cbaf5a3a6eb3a47b0d
2
+ SHA256:
3
+ metadata.gz: 3196d863c8fc7af5fe94d18fe481408c3ec38e008bdc5f778c8d1ea5125d8486
4
+ data.tar.gz: 971b02c0527fc9023d1fb04a50aaf4091129c933c4b937f8095c6624fc251424
5
5
  SHA512:
6
- metadata.gz: f18c67ee620d739ddda87a0550f06eb770bb512a7781a0f1d534bdb3cbc51ee1d39fab47e96af94b2d7e75ad298d3b85bdc98ddb48d102efc53fe62be6233397
7
- data.tar.gz: 3265235a06f9b067928906086849cca271a78eba0eec2efa48b6e4b6a1e065f006fa8d9274501724101c84e1ba0b69c7687eeac317312bd367f12bf4e7772381
6
+ metadata.gz: 2140f02c514b1fc60fc9c2202065bdf6e9a9811efafd632a0b1b58e93eabdcc622f6d548e377c2a3b524a02dcca53a330100ab10c3c0fe9a38822ce405cfb7b0
7
+ data.tar.gz: ddc469e27f0f8c156687ad99810a73edbf54ceb15eaa7cd1f260073c7a9d308d1add9047cec4c0547c5c59d7319920d994b34cdb91f7da69d9f1b06bbb408661
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018 Jan Lindblom
3
+ Copyright (c) 2022 Jan Lindblom (janlindblom@fastmail.fm)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # Quadtree
2
2
 
3
- ![Build Status](https://codebuild.us-east-1.amazonaws.com/badges?uuid=eyJlbmNyeXB0ZWREYXRhIjoidk1aMm1Ya212SjRsU1pVdWNVZ2FRTDVPUXlVM2NsY0dWU2UxL1dEUlh2VTdxdURhcmxRK1JDTGg5OXJxeURKeFRiZXV5VEtTbmRBZCt6bTdDTms1Rm5ZPSIsIml2UGFyYW1ldGVyU3BlYyI6ImlUamttMGtUckZRT0tvM0EiLCJtYXRlcmlhbFNldFNlcmlhbCI6MX0%3D&branch=master)
4
- [![Bitbucket Pipelines](https://img.shields.io/bitbucket/pipelines/janlindblom/ruby-quadtree.png)](https://bitbucket.org/janlindblom/ruby-quadtree)
5
3
  [![Gem](https://img.shields.io/gem/v/quadtree.png)](https://rubygems.org/gems/quadtree)
6
4
  [![Documentation](https://img.shields.io/badge/docs-rdoc.info-yellow.png)](http://www.rubydoc.info/gems/quadtree/frames)
7
5
 
@@ -17,11 +15,15 @@ gem 'quadtree'
17
15
 
18
16
  And then execute:
19
17
 
20
- $ bundle
18
+ ```bash
19
+ bundle
20
+ ```
21
21
 
22
22
  Or install it yourself as:
23
23
 
24
- $ gem install quadtree
24
+ ```bash
25
+ gem install quadtree
26
+ ```
25
27
 
26
28
  ## Usage
27
29
 
@@ -56,12 +58,12 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
56
58
 
57
59
  ## Contributing
58
60
 
59
- Bug reports and pull requests are welcome on Bitbucket at https://bitbucket.org/janlindblom/ruby-quadtree. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
61
+ Bug reports and pull requests are welcome on Github at <https://github.com/janlindblom/ruby-quadtree>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
60
62
 
61
63
  ## License
62
64
 
63
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
65
+ The gem is available as open source under the terms of the [MIT License](https://github.com/janlindblom/ruby-quadtree/blob/master/LICENSE.txt).
64
66
 
65
67
  ## Code of Conduct
66
68
 
67
- Everyone interacting in the Quadtree project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/quadtree/blob/master/CODE_OF_CONDUCT.md).
69
+ Everyone interacting in the Quadtree project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/janlindblom/ruby-quadtree/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile CHANGED
@@ -18,14 +18,21 @@ spec = Gem::Specification.new do |s|
18
18
  s.email = ["janlindblom@fastmail.fm"]
19
19
 
20
20
  s.summary = %q{Quadtrees in Ruby.}
21
- s.homepage = "https://bitbucket.org/janlindblom/ruby-quadtree"
21
+ s.homepage = "https://github.com/janlindblom/ruby-quadtree"
22
22
  s.license = "MIT"
23
23
 
24
24
  s.files = `git ls-files -z`.split("\x0").reject do |f|
25
- f.match(%r{^(bin|test|spec|features)/}) ||
25
+ f.match(%r{^(bin|test|spec|features|.github)/}) ||
26
26
  f == ".travis.yml" ||
27
+ f == ".gitignore" ||
28
+ f == ".editorconfig" ||
29
+ f == ".rspec" ||
27
30
  f == "bitbucket-pipelines.yml" ||
28
- f == "buildspec.yml"
31
+ f == "buildspec.yml" ||
32
+ f == ".gitlab-ci.yml" ||
33
+ f == ".rubocop.yml" ||
34
+ f == ".rubocop_todo.yml" ||
35
+ f == "Jenkinsfile"
29
36
  end
30
37
  s.bindir = "exe"
31
38
  s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -33,14 +40,15 @@ spec = Gem::Specification.new do |s|
33
40
 
34
41
  s.required_ruby_version = '>= 2.3.0'
35
42
 
36
- s.add_development_dependency "bundler", "~> 1.14"
37
- s.add_development_dependency "rake", "~> 10.0"
38
- s.add_development_dependency "rspec", "~> 3.0"
39
- s.add_development_dependency "pry", "~> 0.11"
43
+ s.add_development_dependency "bundler", "~> 2"
44
+ s.add_development_dependency "rake", "~> 13"
45
+ s.add_development_dependency "rspec", "~> 3"
46
+ s.add_development_dependency "pry", "~> 0.14"
40
47
  s.add_development_dependency "yard", "~> 0.9"
41
- s.add_development_dependency "simplecov", "~> 0.16"
42
- s.add_development_dependency "rubocop", "~> 0.54"
43
- s.add_runtime_dependency "version", "~> 1.1"
48
+ s.add_development_dependency "simplecov", "~> 0.21"
49
+ s.add_development_dependency "rspec_junit_formatter", "~> 0.6"
50
+ s.add_development_dependency "rubocop", "~> 1"
51
+ s.add_runtime_dependency "version", "~> 1"
44
52
  end
45
53
 
46
54
  Rake::VersionTask.new do |task|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.7
1
+ 1.0.9
@@ -1,108 +1,155 @@
1
- module Quadtree
2
- # Axis-aligned bounding box with half dimension and center.
3
- class AxisAlignedBoundingBox
4
-
5
- # Center {Point} of this instance.
6
- #
7
- # @return [Point] the {Point} marking the center of this instance.
8
- attr_accessor :center
9
-
10
- # Half dimension of this instance (distance from the center {Point} to the
11
- # edge).
12
- #
13
- # @return [Float] distance from the center {Point} to the edge.
14
- attr_accessor :half_dimension
15
-
16
- # @param center [Point]
17
- # @param half_dimension [Float]
18
- def initialize(center, half_dimension)
19
- @center = center
20
- @half_dimension = half_dimension.to_f
21
- end
22
-
23
- # Check if this instance contains a given {Point}.
24
- #
25
- # @param point [Point] the {Point} to check for.
26
- # @return [Boolean] +true+ if given {Point} is contained, +false+
27
- # otherwise.
28
- def contains_point?(point)
29
- if point.x >= self.center.x - self.half_dimension &&
30
- point.x <= self.center.x + self.half_dimension
31
- if point.y >= self.center.y - self.half_dimension &&
32
- point.y <= self.center.y + self.half_dimension
33
- return true
34
- end
35
- end
36
- false
37
- end
38
-
39
- # Check if this instance intersects with another instance.
40
- #
41
- # @param other [AxisAlignedBoundingBox] the other instance to check for.
42
- # @return [Boolean] +true+ if these intersects, +false+ otherwise.
43
- def intersects?(other)
44
- other_lt_corner = Point.new(other.left, other.top)
45
- other_rt_corner = Point.new(other.right, other.top)
46
- other_lb_corner = Point.new(other.left, other.bottom)
47
- other_rb_corner = Point.new(other.right, other.bottom)
48
-
49
- [
50
- other_lt_corner,
51
- other_rt_corner,
52
- other_lb_corner,
53
- other_rb_corner
54
- ].each do |corner|
55
- return true if self.contains_point?(corner)
56
- end
57
- false
58
- end
59
-
60
- # Get the X coordinate of the left edge of this instance.
61
- #
62
- # @return [Float] the X coordinate of the left edge of this instance.
63
- def left
64
- @center.x - @half_dimension
65
- end
66
-
67
- # Get the X coordinate of the right edge of this instance.
68
- #
69
- # @return [Float] the X coordinate of the right edge of this instance.
70
- def right
71
- @center.x + @half_dimension
72
- end
73
-
74
- # Get the Y coordinate of the top edge of this instance.
75
- #
76
- # @return [Float] the Y coordinate of the top edge of this instance.
77
- def top
78
- @center.y + @half_dimension
79
- end
80
-
81
- # Get the Y coordinate of the bottom edge of this instance.
82
- #
83
- # @return [Float] the Y coordinate of the bottom edge of this instance.
84
- def bottom
85
- @center.y - @half_dimension
86
- end
87
-
88
- # Get the width of this instance.
89
- #
90
- # @return [Float]
91
- def width
92
- span
93
- end
94
-
95
- # Get the height of this instance.
96
- #
97
- # @return [Float]
98
- def height
99
- span
100
- end
101
-
102
- private
103
-
104
- def span
105
- @half_dimension * 2
106
- end
107
- end
108
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Quadtree
4
+ # Axis-aligned bounding box with half dimension and center.
5
+ class AxisAlignedBoundingBox
6
+ # Center {Point} of this instance.
7
+ #
8
+ # @return [Point] the {Point} marking the center of this instance.
9
+ attr_accessor :center
10
+
11
+ # Half dimension of this instance (distance from the center {Point} to the
12
+ # edge).
13
+ #
14
+ # @return [Float] distance from the center {Point} to the edge.
15
+ attr_accessor :half_dimension
16
+
17
+ # @param center [Point]
18
+ # @param half_dimension [Float]
19
+ def initialize(center, half_dimension)
20
+ @center = center
21
+ @half_dimension = half_dimension.to_f
22
+ end
23
+
24
+ #
25
+ # Create a Hash for this {AxisAlignedBoundingBox}.
26
+ #
27
+ # @return [Hash] Hash representation of this {AxisAlignedBoundingBox}.
28
+ #
29
+ def to_h
30
+ {
31
+ 'center': center.to_h,
32
+ 'half_dimension': half_dimension
33
+ }
34
+ end
35
+
36
+ #
37
+ # Create a Hash for this {AxisAlignedBoundingBox}.
38
+ #
39
+ # @return [Hash] Hash representation of this {AxisAlignedBoundingBox}.
40
+ #
41
+ def to_hash
42
+ to_h
43
+ end
44
+
45
+ #
46
+ # Create a JSON String representation of this {AxisAlignedBoundingBox}.
47
+ #
48
+ # @return [String] JSON String of this {AxisAlignedBoundingBox}.
49
+ #
50
+ def to_json(*_args)
51
+ require 'json'
52
+ to_h.to_json
53
+ end
54
+
55
+ #
56
+ # Create a String for this {AxisAlignedBoundingBox}.
57
+ #
58
+ # @return [String] String representation of this {AxisAlignedBoundingBox}.
59
+ #
60
+ def to_s
61
+ to_h.to_s
62
+ end
63
+
64
+ #
65
+ # Construct a {AxisAlignedBoundingBox} from a JSON String.
66
+ #
67
+ # @param [String] json_data input JSON String.
68
+ #
69
+ # @return [AxisAlignedBoundingBox] the {AxisAlignedBoundingBox} contained in the JSON String.
70
+ #
71
+ def self.from_json(json_data)
72
+ new(Point.from_json(json_data['center']), json_data['half_dimension'])
73
+ end
74
+
75
+ # Check if this instance contains a given {Point}.
76
+ #
77
+ # @param point [Point] the {Point} to check for.
78
+ # @return [Boolean] +true+ if given {Point} is contained, +false+
79
+ # otherwise.
80
+ def contains_point?(point)
81
+ if point.x >= center.x - half_dimension &&
82
+ point.x <= center.x + half_dimension
83
+ if point.y >= center.y - half_dimension &&
84
+ point.y <= center.y + half_dimension
85
+ return true
86
+ end
87
+ end
88
+ false
89
+ end
90
+
91
+ # Check if this instance intersects with another instance.
92
+ #
93
+ # @param other [AxisAlignedBoundingBox] the other instance to check for.
94
+ # @return [Boolean] +true+ if these intersects, +false+ otherwise.
95
+ def intersects?(other)
96
+ other_lt_corner = Point.new(other.left, other.top)
97
+ other_rt_corner = Point.new(other.right, other.top)
98
+ other_lb_corner = Point.new(other.left, other.bottom)
99
+ other_rb_corner = Point.new(other.right, other.bottom)
100
+
101
+ [other_lt_corner, other_rt_corner, other_lb_corner, other_rb_corner].each do |corner|
102
+ return true if contains_point?(corner)
103
+ end
104
+ false
105
+ end
106
+
107
+ # Get the X coordinate of the left edge of this instance.
108
+ #
109
+ # @return [Float] the X coordinate of the left edge of this instance.
110
+ def left
111
+ @center.x - @half_dimension
112
+ end
113
+
114
+ # Get the X coordinate of the right edge of this instance.
115
+ #
116
+ # @return [Float] the X coordinate of the right edge of this instance.
117
+ def right
118
+ @center.x + @half_dimension
119
+ end
120
+
121
+ # Get the Y coordinate of the top edge of this instance.
122
+ #
123
+ # @return [Float] the Y coordinate of the top edge of this instance.
124
+ def top
125
+ @center.y + @half_dimension
126
+ end
127
+
128
+ # Get the Y coordinate of the bottom edge of this instance.
129
+ #
130
+ # @return [Float] the Y coordinate of the bottom edge of this instance.
131
+ def bottom
132
+ @center.y - @half_dimension
133
+ end
134
+
135
+ # Get the width of this instance.
136
+ #
137
+ # @return [Float]
138
+ def width
139
+ span
140
+ end
141
+
142
+ # Get the height of this instance.
143
+ #
144
+ # @return [Float]
145
+ def height
146
+ span
147
+ end
148
+
149
+ private
150
+
151
+ def span
152
+ @half_dimension * 2
153
+ end
154
+ end
155
+ end
@@ -1,107 +1,161 @@
1
- module Quadtree
2
- # Simple coordinate object to represent points in some space.
3
- class Point
4
-
5
- # The X coordinate of this instance.
6
- # @return [Float, Integer] X coordinate.
7
- attr_accessor :x
8
-
9
- # The Y coordinate of this instance.
10
- # @return [Float, Integer] Y coordinate.
11
- attr_accessor :y
12
-
13
- # Optional payload attached to this instance.
14
- # @return [Object] payload attached to this instance.
15
- attr_accessor :data
16
-
17
- # @param x [Float, Integer] X coordinate.
18
- # @param y [Float, Integer] Y coordinate.
19
- # @param data [Object] payload payload attached to this instance
20
- # (optional).
21
- # @raise [UnknownTypeError] if one or more input parameters (+x+ and +y+)
22
- # has the wrong type.
23
- def initialize(x, y, data=nil)
24
-
25
- self.x = get_typed_numeric(x)
26
- self.y = get_typed_numeric(y)
27
-
28
- self.data = data unless data.nil?
29
- end
30
-
31
- # This will calculate distance to another {Point}, given that they are
32
- # both in the same 2D space.
33
- #
34
- # @param other [Point] the other {Point}.
35
- # @return [Float] the distance to the other {Point}.
36
- def distance_to(other)
37
- Math.sqrt((other.x - self.x) ** 2 + (other.y - self.y) ** 2)
38
- end
39
-
40
- # This will calculate distance to another {Point} using the Haversine
41
- # formula. This means that it will treat {#x} as longitude and {#y} as
42
- # latitude!
43
- #
44
- # a = sin²(Δφ/2) + cos φ_1 ⋅ cos φ_2 ⋅ sin²(Δλ/2)
45
- #
46
- # c = 2 ⋅ atan2( √a, √(1−a) )
47
- #
48
- # d = R ⋅ c
49
- #
50
- # where φ is latitude, λ is longitude, R is earth’s radius (mean
51
- # radius = 6 371 km);
52
- # note that angles need to be in radians to pass to trig functions!
53
- #
54
- # @param other [Point] the other {Point}.
55
- # @return [Float] the distance, in meters, to the other {Point}.
56
- def haversine_distance_to(other)
57
- # earth's radius
58
- r = 6371 * 1000.0
59
- # coverting degrees to radians
60
- lat1 = self.y * (Math::PI / 180.0)
61
- lat2 = other.y * (Math::PI / 180.0)
62
- dlat = (other.y - self.y) * (Math::PI / 180.0)
63
- dlon = (other.x - self.x) * (Math::PI / 180.0)
64
-
65
- # a = sin²(Δφ/2) + cos φ_1 ⋅ cos φ_2 ⋅ sin²(Δλ/2)
66
- a = Math.sin(dlat / 2.0) * Math.sin(dlat / 2.0) +
67
- Math.cos(lat1) * Math.cos(lat2) *
68
- Math.sin(dlon / 2.0) * Math.sin(dlon / 2.0)
69
- # c = 2 ⋅ atan2( √a, √(1−a) )
70
- c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
71
- # d = R ⋅ c
72
- return r * c
73
- end
74
-
75
- private
76
-
77
- def get_typed_numeric(any_input)
78
- typed_output = nil
79
- # Try integer first since float will parse integers too
80
- return get_integer(any_input) unless get_integer(any_input).nil?
81
- # Try Float next
82
- return get_float(any_input) unless get_float(any_input).nil?
83
-
84
- raise UnknownTypeError.new "Unknown type for parameter: #{any_input.class}"
85
-
86
- #typed_output
87
- end
88
-
89
- def get_integer(any_input)
90
- return Integer(any_input) if any_input.is_a? String
91
- return any_input if any_input.is_a? Integer
92
-
93
- nil
94
- rescue
95
- nil
96
- end
97
-
98
- def get_float(any_input)
99
- return Float(any_input) if any_input.is_a? String
100
- return any_input if any_input.is_a? Float
101
-
102
- nil
103
- rescue
104
- nil
105
- end
106
- end
107
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Quadtree
4
+ # Simple coordinate object to represent points in some space.
5
+ class Point
6
+ # The X coordinate of this instance.
7
+ # @return [Float, Integer] X coordinate.
8
+ attr_accessor :x
9
+
10
+ # The Y coordinate of this instance.
11
+ # @return [Float, Integer] Y coordinate.
12
+ attr_accessor :y
13
+
14
+ # Optional payload attached to this instance.
15
+ # @return [Object] payload attached to this instance.
16
+ attr_accessor :data
17
+
18
+ # @param x [Float, Integer] X coordinate.
19
+ # @param y [Float, Integer] Y coordinate.
20
+ # @param data [Object] payload payload attached to this instance
21
+ # (optional).
22
+ # @raise [UnknownTypeError] if one or more input parameters (+x+ and +y+)
23
+ # has the wrong type.
24
+ def initialize(x, y, data = nil)
25
+ self.x = get_typed_numeric(x)
26
+ self.y = get_typed_numeric(y)
27
+
28
+ self.data = data unless data.nil?
29
+ end
30
+
31
+ #
32
+ # Create a Hash for this {Point}.
33
+ #
34
+ # @return [Hash] Hash representation of this {Point}.
35
+ #
36
+ def to_h
37
+ {
38
+ 'x': x,
39
+ 'y': y,
40
+ 'data': process_data(data)
41
+ }
42
+ end
43
+
44
+ #
45
+ # Create a Hash for this {Point}.
46
+ #
47
+ # @return [Hash] Hash representation of this {Point}.
48
+ #
49
+ def to_hash
50
+ to_h
51
+ end
52
+
53
+ #
54
+ # Create a JSON String representation of this {Point}.
55
+ #
56
+ # @return [String] JSON String of this {Point}.
57
+ #
58
+ def to_json(*_args)
59
+ require 'json'
60
+ to_h.to_json
61
+ end
62
+
63
+ #
64
+ # Create a String for this {Point}.
65
+ #
66
+ # @return [String] String representation of this {Point}.
67
+ #
68
+ def to_s
69
+ to_h.to_s
70
+ end
71
+
72
+ #
73
+ # Construct a {Quadtree::Point} from a JSON String.
74
+ #
75
+ # @param [String] json_data input JSON String.
76
+ #
77
+ # @return [Quadtree::Point] the {Quadtree::Point} contained in the JSON String.
78
+ #
79
+ def self.from_json(json_data)
80
+ new(json_data['x'], json_data['y'], json_data['data'])
81
+ end
82
+
83
+ # This will calculate distance to another {Point}, given that they are
84
+ # both in the same 2D space.
85
+ #
86
+ # @param other [Point] the other {Point}.
87
+ # @return [Float] the distance to the other {Point}.
88
+ def distance_to(other)
89
+ Math.sqrt((other.x - x)**2 + (other.y - y)**2)
90
+ end
91
+
92
+ # This will calculate distance to another {Point} using the Haversine
93
+ # formula. This means that it will treat {#x} as longitude and {#y} as
94
+ # latitude!
95
+ #
96
+ # a = sin²(Δφ/2) + cos φ_1 ⋅ cos φ_2 ⋅ sin²(Δλ/2)
97
+ #
98
+ # c = 2 ⋅ atan2( √a, √(1−a) )
99
+ #
100
+ # d = R ⋅ c
101
+ #
102
+ # where φ is latitude, λ is longitude, R is earth’s radius (mean
103
+ # radius = 6 371 km);
104
+ # note that angles need to be in radians to pass to trig functions!
105
+ #
106
+ # @param other [Point] the other {Point}.
107
+ # @return [Float] the distance, in meters, to the other {Point}.
108
+ def haversine_distance_to(other)
109
+ lat1 = y * (Math::PI / 180.0)
110
+ lat2 = other.y * (Math::PI / 180.0)
111
+ dlat = (other.y - y) * (Math::PI / 180.0)
112
+ dlon = (other.x - x) * (Math::PI / 180.0)
113
+
114
+ # a = sin²(Δφ/2) + cos φ_1 ⋅ cos φ_2 ⋅ sin²(Δλ/2)
115
+ a = calculate_haversine_a(lat1, lat2, dlat, dlon)
116
+ # c = 2 ⋅ atan2( √a, √(1−a) )
117
+ c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
118
+ # d = R ⋅ c
119
+ 6371 * 1000.0 * c
120
+ end
121
+
122
+ private
123
+
124
+ def calculate_haversine_a(lat1, lat2, dlat, dlon)
125
+ Math.sin(dlat / 2.0) * Math.sin(dlat / 2.0) +
126
+ Math.cos(lat1) * Math.cos(lat2) *
127
+ Math.sin(dlon / 2.0) * Math.sin(dlon / 2.0)
128
+ end
129
+
130
+ def process_data(data)
131
+ data.nil? || data.is_a?(Array) || data.is_a?(String) || data.is_a?(Numeric) ? data : data.to_h
132
+ end
133
+
134
+ def get_typed_numeric(any_input)
135
+ # Try integer first since float will parse integers too
136
+ return get_integer(any_input) unless get_integer(any_input).nil?
137
+ # Try Float next
138
+ return get_float(any_input) unless get_float(any_input).nil?
139
+
140
+ raise UnknownTypeError, "Unknown type for parameter: #{any_input.class}"
141
+ end
142
+
143
+ def get_integer(any_input)
144
+ return Integer(any_input) if any_input.is_a? String
145
+ return any_input if any_input.is_a? Integer
146
+
147
+ nil
148
+ rescue StandardError
149
+ nil
150
+ end
151
+
152
+ def get_float(any_input)
153
+ return Float(any_input) if any_input.is_a? String
154
+ return any_input if any_input.is_a? Float
155
+
156
+ nil
157
+ rescue StandardError
158
+ nil
159
+ end
160
+ end
161
+ end