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 +7 -0
 - data/.gitignore +22 -0
 - data/.rspec +2 -0
 - data/.simplecov +9 -0
 - data/.travis.yml +5 -0
 - data/Gemfile +4 -0
 - data/README.md +57 -0
 - data/Rakefile +8 -0
 - data/geospatial.gemspec +24 -0
 - data/lib/geospatial/hilbert.rb +106 -0
 - data/lib/geospatial/location.rb +134 -0
 - data/lib/geospatial/version.rb +3 -0
 - data/lib/geospatial.rb +4 -0
 - data/spec/geoquery/hilbert_spec.rb +72 -0
 - data/spec/geoquery/location_spec.rb +32 -0
 - metadata +102 -0
 
    
        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
    
    
    
        data/.simplecov
    ADDED
    
    
    
        data/.travis.yml
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,57 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Geospatial
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Geospatial provides abstractions for dealing with geographical locations efficiently.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            [](http://travis-ci.org/ioquatix/geospatial)
         
     | 
| 
      
 6 
     | 
    
         
            +
            [](https://codeclimate.com/github/ioquatix/geospatial)
         
     | 
| 
      
 7 
     | 
    
         
            +
            [](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
    
    
    
        data/geospatial.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 '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
         
     | 
    
        data/lib/geospatial.rb
    ADDED
    
    
| 
         @@ -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
         
     |