geospatial 0.0.1

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
+ SHA1:
3
+ metadata.gz: 2a5d010173b1e91d60be3e2c07e0e89a95ccb000
4
+ data.tar.gz: 5df99174a2639bc48dca1b84f26a149e2c8b3e92
5
+ SHA512:
6
+ metadata.gz: c4eb89aa1b47b77313d8c68abaa95d2d83660b040dead60be19823d69fc5aeb0b4c67d529caf573e677ab4eba7496673c3859797bafc2f0ba0cec3fd52bc31c9
7
+ data.tar.gz: 3177ebab37d176ec50b98db396ce0cb964a071e5f8994ae2d14f1da00d0ca4023a7aac13126cfaca96c5870cbae02d5b0544f321b79bde38793521edaf2057f8
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.simplecov ADDED
@@ -0,0 +1,9 @@
1
+
2
+ SimpleCov.start do
3
+ add_filter "/spec/"
4
+ end
5
+
6
+ if ENV['TRAVIS']
7
+ require 'coveralls'
8
+ Coveralls.wear!
9
+ end
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "2.0"
4
+ - "2.1"
5
+ env: COVERAGE=true
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in geospatial.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # Geospatial
2
+
3
+ Geospatial provides abstractions for dealing with geographical locations efficiently.
4
+
5
+ [![Build Status](https://secure.travis-ci.org/ioquatix/geospatial.png)](http://travis-ci.org/ioquatix/geospatial)
6
+ [![Code Climate](https://codeclimate.com/github/ioquatix/geospatial.png)](https://codeclimate.com/github/ioquatix/geospatial)
7
+ [![Coverage Status](https://coveralls.io/repos/ioquatix/geospatial/badge.svg)](https://coveralls.io/r/ioquatix/geospatial)
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'geospatial'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install geospatial
22
+
23
+ ## Usage
24
+
25
+ ...
26
+
27
+ ## Contributing
28
+
29
+ 1. Fork it
30
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
31
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
32
+ 4. Push to the branch (`git push origin my-new-feature`)
33
+ 5. Create new Pull Request
34
+
35
+ ## License
36
+
37
+ Released under the MIT license.
38
+
39
+ Copyright, 2015, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining a copy
42
+ of this software and associated documentation files (the "Software"), to deal
43
+ in the Software without restriction, including without limitation the rights
44
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45
+ copies of the Software, and to permit persons to whom the Software is
46
+ furnished to do so, subject to the following conditions:
47
+
48
+ The above copyright notice and this permission notice shall be included in
49
+ all copies or substantial portions of the Software.
50
+
51
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
54
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57
+ THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |task|
5
+ task.rspec_opts = ["--require", "simplecov"] if ENV['COVERAGE']
6
+ end
7
+
8
+ task :default => :spec
@@ -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 'geospatial/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "geospatial"
8
+ spec.version = Geospatial::VERSION
9
+ spec.authors = ["Samuel Williams"]
10
+ spec.email = ["samuel.williams@oriontransfer.co.nz"]
11
+ spec.summary = %q{Provides abstractions for dealing with geographical locations efficiently}
12
+ spec.homepage = "https://github.com/ioquatix/geospatial"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "rspec", "~> 3.1.0"
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.6"
23
+ spec.add_development_dependency "rake"
24
+ end
@@ -0,0 +1,106 @@
1
+
2
+ module Geospatial
3
+ class Hilbert
4
+ # Quadrants are numbered 0 to 3, and are in the following order:
5
+ # y
6
+ # 1 | 3 | 2 |
7
+ # 0 | 0 | 1 |
8
+ # 0 1 x
9
+ # The origin is in the lower left, and the most rapidly changing value is along the x axis for the initial rotation.
10
+
11
+ # Four quadrants/rotations, the direction indicates the axis of the final two coordinates (e.g. 2 -> 3) and is for informal use only.
12
+ A = 0 # LEFT
13
+ # | 3 | 2 |
14
+ # | 0 | 1 |
15
+
16
+ B = 1 # DOWN
17
+ # | 1 | 2 |
18
+ # | 0 | 3 |
19
+
20
+ C = 2 # RIGHT
21
+ # | 1 | 0 |
22
+ # | 2 | 3 |
23
+
24
+ D = 3 # UP
25
+ # | 3 | 0 |
26
+ # | 2 | 1 |
27
+
28
+ # This maps the identity rotation/quadrants into their prefix quadrant. The prefix quadrant is the 2 bit number (0 to 3) which identifies along the curve which quadrant the value falls into. This can be computed by looking at how the curve for a given rotation and looking at the correspondence between the identity quadrants and the curve's traversal.
29
+ ROTATE = [
30
+ [A, B, C, D], # A is the identity
31
+ [A, D, C, B], # Map A onto B.
32
+ [C, D, A, B], # Map A onto C.
33
+ [C, B, A, D], # Map A onto D.
34
+ ].freeze
35
+
36
+ # Rotate quadrant by rotation. The provided quadrant is with respect to the Up rotation.
37
+ # Note that this function is self-inverting in the sense that rotate(r, rotate(r, x)) == x.
38
+ def self.rotate(rotation, quadrant)
39
+ ROTATE[rotation][quadrant]
40
+ end
41
+
42
+ # These prefixes are generated by the following graph:
43
+ # Rotation | 0 1 2 3 (Prefix)
44
+ # A | B A A D
45
+ # B | A B B C
46
+ # C | D C C B
47
+ # D | C D D A
48
+ # We can compute this matrix by looking how the given prefix quadrant maps onto a curve one level down the tree, given the current rotation. We identify that colums 1 and 2 are the same as the input so we take advantage of this by mapping only the columns which are different, i.e. for prefix 0 and 3.
49
+
50
+ PREFIX0 = [B, A, D, C].freeze
51
+ PREFIX3 = [D, C, B, A].freeze
52
+
53
+ # Given the current rotation and the prefix quadrant, compute the next rotation one level down the tree.
54
+ def self.next_rotation(rotation, prefix)
55
+ if prefix == 0
56
+ PREFIX0[rotation]
57
+ elsif prefix == 3
58
+ PREFIX3[rotation]
59
+ else
60
+ rotation
61
+ end
62
+ end
63
+
64
+ # Compute which quadrant this bit is in.
65
+ def self.normalized_quadrant(x, y, bit_offset)
66
+ mask = 1 << bit_offset
67
+
68
+ if (y & mask) == 0
69
+ if (x & mask) == 0
70
+ return 0
71
+ else
72
+ return 1
73
+ end
74
+ else
75
+ if (x & mask) == 0
76
+ return 3
77
+ else
78
+ return 2
79
+ end
80
+ end
81
+ end
82
+
83
+ def self.hash(x, y, order)
84
+ result = 0
85
+ # The initial rotation depends on the order:
86
+ rotation = order.even? ? A : B
87
+
88
+ order.downto(0) do |i|
89
+ # This computes the normalized quadrant for the ith bit of x, y:
90
+ quadrant = self.normalized_quadrant(x, y, i)
91
+
92
+ # Given the normalised quadrant, compute the prefix bits for the given quadrant for the given hilbert curve rotation:
93
+ prefix = rotate(rotation, quadrant)
94
+
95
+ # These both do the same thing, not sure which one is faster:
96
+ result = (result << 2) | prefix
97
+ #result |= (rotated << (i * 2))
98
+
99
+ # Given the current rotation and the prefix for the hilbert curve, compute the next rotation one level in:
100
+ rotation = next_rotation(rotation, prefix)
101
+ end
102
+
103
+ return result
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,134 @@
1
+
2
+ module Geospatial
3
+ # This location is specifically relating to a WGS84 coordinate on Earth.
4
+ class Location
5
+ # WGS 84 semi-major axis constant in meters
6
+ WGS84_A = 6378137.0
7
+ # WGS 84 semi-minor axis constant in meters
8
+ WGS84_B = 6356752.3
9
+
10
+ EARTH_RADIUS = (WGS84_A + WGS84_B) / 2.0
11
+
12
+ # WGS 84 eccentricity
13
+ WGS84_E = 8.1819190842622e-2
14
+
15
+ # Radians to degrees multiplier
16
+ R2D = (180.0 / Math::PI)
17
+ D2R = (Math::PI / 180.0)
18
+
19
+ MIN_LATITUDE = -90.0 * D2R
20
+ MAX_LATITUDE = 90 * D2R
21
+ VALID_LATITUDE = MIN_LATITUDE...MAX_LATITUDE
22
+
23
+ MIN_LONGITUDE = -180 * D2R
24
+ MAX_LONGITUDE = 180 * D2R
25
+ VALID_LONGITUDE = MIN_LONGITUDE...MAX_LONGITUDE
26
+
27
+ def initialize(latitude, longitude, altitude = 0)
28
+ @latitude = latitude
29
+ @longitude = longitude
30
+ @altitude = altitude
31
+ end
32
+
33
+ def valid?
34
+ VALID_LATITUDE.include? latitude and VALID_LONGITUDE.include? longitude
35
+ end
36
+
37
+ def to_s
38
+ "#<Location latitude=#{@latitude} longitude=#{@longitude.to_f} altitude=#{@altitude.to_f}>"
39
+ end
40
+
41
+ alias inspect to_s
42
+
43
+ attr :latitude
44
+ attr :longitude
45
+ attr :altitude
46
+
47
+ # http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates
48
+ def bounding_box(distance, radius = EARTH_RADIUS)
49
+ raise ArgumentError.new("Invalid distance or radius") if distance < 0 or radius < 0
50
+
51
+ # angular distance in radians on a great circle
52
+ angular_distance = distance / (radius + self.altitude)
53
+
54
+ min_latitude = (self.latitude * D2R) - angular_distance
55
+ max_latitude = (self.latitude * D2R) + angular_distance
56
+
57
+ if min_latitude > MIN_LAT and max_latitude < MAX_LAT
58
+ longitude_delta = Math::asin(Math::sin(angular_distance) / Math::cos(self.latitude * D2R))
59
+
60
+ min_longitude = (self.longitude * D2R) - longitude_delta
61
+ min_longitude += 2.0 * Math::PI if (min_longitude < MIN_LON)
62
+
63
+ max_longitude = (self.longitude * D2R) + longitude_delta;
64
+ max_longitude -= 2.0 * Math::PI if (max_longitude > MAX_LON)
65
+ else
66
+ # a pole is within the distance
67
+ min_latitude = [min_latitude, MIN_LAT].max
68
+ max_latitude = [max_latitude, MAX_LAT].min
69
+
70
+ min_longitude = MIN_LON
71
+ max_longitude = MAX_LON
72
+ end
73
+
74
+ return {
75
+ :latitude => Range.new(min_latitude * R2D, max_latitude * R2D),
76
+ :longitude => Range.new(min_longitude * R2D, max_longitude * R2D),
77
+ }
78
+ end
79
+
80
+ # Converts latitude, longitude to ECEF coordinate system
81
+ def to_ecef(alt)
82
+ clat = Math::cos(lat * D2R)
83
+ slat = Math::sin(lat * D2R)
84
+ clon = Math::cos(lon * D2R)
85
+ slon = Math::sin(lon * D2R)
86
+
87
+ n = WGS84_A / Math::sqrt(1.0 - WGS84_E * WGS84_E * slat * slat)
88
+
89
+ x = (n + alt) * clat * clon
90
+ y = (n + alt) * clat * slon
91
+ z = (n * (1.0 - WGS84_E * WGS84_E) + alt) * slat
92
+
93
+ return x, y, z
94
+ end
95
+
96
+ def self.from_ecef(x, y, z)
97
+ # Constants (WGS ellipsoid)
98
+ a = WGS84_A
99
+ e = WGS84_E
100
+
101
+ b = Math::sqrt((a*a) * (1.0-(e*e)))
102
+ ep = Math::sqrt(((a*a)-(b*b))/(b*b))
103
+
104
+ p = Math::sqrt((x*x)+(y*y))
105
+ th = Math::atan2(a*z, b*p)
106
+
107
+ lon = Math::atan2(y, x)
108
+ lat = Math::atan2((z+ep*ep*b*(Math::sin(th) ** 3)), (p-e*e*a*(Math::cos(th)**3)))
109
+
110
+ n = a / Math::sqrt(1.0-e*e*(Math::sin(lat) ** 2))
111
+ alt = p / Math::cos(lat)-n
112
+
113
+ return self.new(lat*R2D, lon*R2D, alt)
114
+ end
115
+
116
+ # calculate distance in metres between us and something else
117
+ # ref: http://codingandweb.blogspot.co.nz/2012/04/calculating-distance-between-two-points.html
118
+ def distance_from(other_position)
119
+ rlat1 = self.latitude * D2R
120
+ rlong1 = self.longitude * D2R
121
+ rlat2 = other_position.latitude * D2R
122
+ rlong2 = other_position.longitude * D2R
123
+
124
+ dlon = rlong1 - rlong2
125
+ dlat = rlat1 - rlat2
126
+
127
+ a = Math::sin(dlat/2) ** 2 + Math::cos(rlat1) * Math::cos(rlat2) * Math::sin(dlon/2) ** 2
128
+ c = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1-a))
129
+ d = EARTH_RADIUS * c
130
+
131
+ return d
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,3 @@
1
+ module Geospatial
2
+ VERSION = "0.0.1"
3
+ end
data/lib/geospatial.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "geospatial/version"
2
+
3
+ module Geospatial
4
+ end
@@ -0,0 +1,72 @@
1
+ # Copyright, 2015, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'geospatial/hilbert'
22
+
23
+ module Geospatial::HilbertSpec
24
+ describe Geospatial::Hilbert do
25
+ it "base case should be identity" do
26
+ # The base case for our coordinate system:
27
+ expect(Geospatial::Hilbert.rotate(0, 0)).to be == 0
28
+ expect(Geospatial::Hilbert.rotate(0, 1)).to be == 1
29
+ expect(Geospatial::Hilbert.rotate(0, 2)).to be == 2
30
+ expect(Geospatial::Hilbert.rotate(0, 3)).to be == 3
31
+ end
32
+
33
+ it "rotation is self-inverting" do
34
+ 4.times do |rotation|
35
+ 4.times do |quadrant|
36
+ # rotate(rotation, rotate(rotation, quadrant)) == quadrant
37
+ rotated = Geospatial::Hilbert.rotate(rotation, quadrant)
38
+ expect(Geospatial::Hilbert.rotate(rotation, rotated)).to be == quadrant
39
+ end
40
+ end
41
+ end
42
+
43
+ it "compute the correct hash of order=0" do
44
+ expect(Geospatial::Hilbert.hash(0, 0, 0)).to be == 0
45
+ expect(Geospatial::Hilbert.hash(1, 0, 0)).to be == 1
46
+ expect(Geospatial::Hilbert.hash(1, 1, 0)).to be == 2
47
+ expect(Geospatial::Hilbert.hash(0, 1, 0)).to be == 3
48
+ end
49
+
50
+ it "compute the correct hash of order=1" do
51
+ expect(Geospatial::Hilbert.hash(0, 0, 1)).to be == 0
52
+ expect(Geospatial::Hilbert.hash(1, 0, 1)).to be == 1
53
+ expect(Geospatial::Hilbert.hash(1, 1, 1)).to be == 2
54
+ expect(Geospatial::Hilbert.hash(0, 1, 1)).to be == 3
55
+
56
+ expect(Geospatial::Hilbert.hash(0, 2, 1)).to be == 4
57
+ expect(Geospatial::Hilbert.hash(0, 3, 1)).to be == 5
58
+ expect(Geospatial::Hilbert.hash(1, 3, 1)).to be == 6
59
+ expect(Geospatial::Hilbert.hash(1, 2, 1)).to be == 7
60
+
61
+ expect(Geospatial::Hilbert.hash(2, 2, 1)).to be == 8
62
+ expect(Geospatial::Hilbert.hash(2, 3, 1)).to be == 9
63
+ expect(Geospatial::Hilbert.hash(3, 3, 1)).to be == 10
64
+ expect(Geospatial::Hilbert.hash(3, 2, 1)).to be == 11
65
+
66
+ expect(Geospatial::Hilbert.hash(3, 1, 1)).to be == 12
67
+ expect(Geospatial::Hilbert.hash(2, 1, 1)).to be == 13
68
+ expect(Geospatial::Hilbert.hash(2, 0, 1)).to be == 14
69
+ expect(Geospatial::Hilbert.hash(3, 0, 1)).to be == 15
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,32 @@
1
+ # Copyright, 2015, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'geospatial/location'
22
+
23
+ module Geospatial::LocationSpec
24
+ describe Geospatial::Location do
25
+ it "compute the correct distance between two points" do
26
+ lake_tekapo = Geospatial::Location.new(-43.883, 170.516)
27
+ lake_alex = Geospatial::Location.new(-43.95, 170.45)
28
+
29
+ expect(lake_alex.distance_from(lake_tekapo)).to be_within(10).of(9_130)
30
+ end
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geospatial
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Samuel Williams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-29 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: 3.1.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
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:
56
+ email:
57
+ - samuel.williams@oriontransfer.co.nz
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".simplecov"
65
+ - ".travis.yml"
66
+ - Gemfile
67
+ - README.md
68
+ - Rakefile
69
+ - geospatial.gemspec
70
+ - lib/geospatial.rb
71
+ - lib/geospatial/hilbert.rb
72
+ - lib/geospatial/location.rb
73
+ - lib/geospatial/version.rb
74
+ - spec/geoquery/hilbert_spec.rb
75
+ - spec/geoquery/location_spec.rb
76
+ homepage: https://github.com/ioquatix/geospatial
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.2.2
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: Provides abstractions for dealing with geographical locations efficiently
100
+ test_files:
101
+ - spec/geoquery/hilbert_spec.rb
102
+ - spec/geoquery/location_spec.rb