geospatial 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 91eeac2469ee68ea87e60650e5c909a25e9af3cd
4
- data.tar.gz: 712f71a592a0e803111c4380ebb78bd7a691f1e7
2
+ SHA256:
3
+ metadata.gz: 7e053b1210f1e0fa945a2e07de86aa8c211cf77e792298c849f209a73e7a34c1
4
+ data.tar.gz: bcb46dc6b66f6b532a95006ee1013df86833492bc8486bdbde7ff7c4ac088639
5
5
  SHA512:
6
- metadata.gz: 9bdb1fa1003101a6cd58be330b2730e75b7aeb64140297512ffa595f59e62874b101293b922d726b2974fe3378be002f96445fe21e582481b192fd337973ec71
7
- data.tar.gz: f67b819573274641c82c356ada6b2c58275b6f612af20117145d595aa9b73ad78f5b408809da374be98d3bead97e0d50237aa3fb107d920040f1003baa9a12ee
6
+ metadata.gz: ed146165687208fde777a2ef91bd523b8a1a6ab8f9c4a3691828708c08aa4e450be46b639a0c8ac1b668b131db15c87901b4739bc50d9cd66c69bdf7e80f6aec
7
+ data.tar.gz: 9c7f1051fd9f06cb87281ba32b89e8cddedbb64e735817d777220a96690ba90aae4a4ea0d851a0f86407a5a2f2e3d7ebb2d65d3cb9aadc166e62933cd927b378
data/README.md CHANGED
@@ -14,6 +14,8 @@ We had a need to query a database of places efficiently using SQLite. We did som
14
14
 
15
15
  After researching geospatial hashing algorithms, I found [this blog post](http://blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves) and decided to implement a geospatial hash using the Hilbert curve. This library exposes a fast indexing and querying mechanism based on Hilbert curves, for points on a map, which can be integrated into a database or other systems as required.
16
16
 
17
+ The design of this library is inspired by [Space-Filling Curves in Scala](https://github.com/cne1x/sfseize), which exposes curves as composable mathematical hash functions.
18
+
17
19
  For another solution to this problem, Google uses [S2 Geometry](http://blog.christianperone.com/2015/08/googles-s2-geometry-on-the-sphere-cells-and-hilbert-curve/) which is a more specific implementation designed for geospatial indexes only.
18
20
 
19
21
  ## Installation
@@ -88,6 +88,10 @@ module Geospatial
88
88
  yield(Vector[@origin[0], max[1]])
89
89
  end
90
90
 
91
+ def center
92
+ @origin + (@size/2)
93
+ end
94
+
91
95
  # This yields the midpoints of the four sides of the box.
92
96
  def midpoints
93
97
  return to_enum(:midpoints) unless block_given?
@@ -0,0 +1,69 @@
1
+ #
2
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
3
+ #
4
+ # This file is part of the "geospatial" project and is released under the MIT license.
5
+ #
6
+
7
+ module Geospatial
8
+ # This location is specifically relating to a WGS84 coordinate on Earth.
9
+ class Histogram
10
+ def initialize(min = 0, max = 1, scale = 0.1)
11
+ @min = min
12
+ @max = max
13
+ @scale = scale
14
+
15
+ @count = ((@max - @min) / @scale).ceil
16
+ @bins = [0] * @count
17
+ @offset = 0
18
+ @scale = scale
19
+ end
20
+
21
+ attr :bins
22
+
23
+ attr :offset
24
+ attr :scale
25
+
26
+ def add(value, amount = 1)
27
+ index = ((value - @min) / @scale).floor
28
+
29
+ if @bins[index]
30
+ @bins[index] += amount
31
+ else
32
+ @bins[index] = amount
33
+ end
34
+
35
+ return self
36
+ end
37
+
38
+ def peaks
39
+ @bins.each_with_index
40
+ end
41
+
42
+ def offset(index)
43
+ @min + (index * @scale)
44
+ end
45
+
46
+ def inspect
47
+ buffer = String.new("\#<#{self.class}")
48
+
49
+ @bins.each_with_index do |bin, index|
50
+ buffer << "\n#{offset(index).to_s.rjust(8)}: #{bin}"
51
+ end
52
+
53
+ buffer << "\n>"
54
+ end
55
+ end
56
+
57
+ class RadialHistogram < Histogram
58
+ def initialize(center, min = -180, max = 180, scale = 10)
59
+ super(min, max, scale)
60
+
61
+ @center = center
62
+ end
63
+
64
+ def add(point, value = 1)
65
+ super(point.bearing_from(@center), value)
66
+ end
67
+ end
68
+
69
+ end
@@ -158,6 +158,18 @@ module Geospatial
158
158
  return d
159
159
  end
160
160
 
161
+ def bearing_from(other)
162
+ lon1 = other.longitude * D2R
163
+ lat1 = other.latitude * D2R
164
+ lon2 = self.longitude * D2R
165
+ lat2 = self.latitude * D2R
166
+
167
+ return Math::atan2(
168
+ Math::sin(lon2 - lon1) * Math::cos(lat2),
169
+ Math::cos(lat1) * Math::sin(lat2) - Math::sin(lat1) * Math::cos(lat2) * Math::cos(lon2-lon1)
170
+ ) * R2D
171
+ end
172
+
161
173
  def - other
162
174
  Distance.new(self.distance_from(other))
163
175
  end
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Geospatial
22
- VERSION = "1.6.0"
22
+ VERSION = "1.7.0"
23
23
  end
@@ -21,15 +21,43 @@
21
21
  require 'geospatial/location'
22
22
 
23
23
  RSpec.describe Geospatial::Location do
24
- let(:lake_tekapo) {Geospatial::Location.new(170.53, -43.89)}
25
- let(:lake_alex) {Geospatial::Location.new(170.45, -43.94)}
24
+ context 'new zealand lakes' do
25
+ let(:lake_tekapo) {Geospatial::Location.new(170.53, -43.89)}
26
+ let(:lake_alex) {Geospatial::Location.new(170.45, -43.94)}
27
+
28
+ it "should compute the correct distance between two points" do
29
+ expect(lake_alex.distance_from(lake_tekapo)).to be_within(100).of(8_500)
30
+ end
31
+
32
+ it "should format nicely" do
33
+ expect("#{lake_alex}").to be == "Geospatial::Location[170.45, -43.94]"
34
+ end
35
+ end
26
36
 
27
- it "compute the correct distance between two points" do
28
- expect(lake_alex.distance_from(lake_tekapo)).to be_within(100).of(8_500)
37
+ context 'points on equator' do
38
+ let(:west) {Geospatial::Location.new(-10, 0)}
39
+ let(:east) {Geospatial::Location.new(10, 0)}
40
+
41
+ it "should compute the bearing between two points" do
42
+ expect(east.bearing_from(west)).to be_within(0.1).of(90)
43
+ end
44
+
45
+ it "should compute the bearing between two points" do
46
+ expect(west.bearing_from(east)).to be_within(0.1).of(-90)
47
+ end
29
48
  end
30
49
 
31
- it "should format nicely" do
32
- expect("#{lake_alex}").to be == "Geospatial::Location[170.45, -43.94]"
50
+ context 'points on same latitude' do
51
+ let(:north) {Geospatial::Location.new(0, 10)}
52
+ let(:south) {Geospatial::Location.new(0, -10)}
53
+
54
+ it "should compute the bearing between two points" do
55
+ expect(north.bearing_from(south)).to be_within(0.1).of(0)
56
+ end
57
+
58
+ it "should compute the bearing between two points" do
59
+ expect(south.bearing_from(north)).to be_within(0.1).of(180)
60
+ end
33
61
  end
34
62
  end
35
63
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geospatial
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-24 00:00:00.000000000 Z
11
+ date: 2018-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -76,6 +76,7 @@ files:
76
76
  - lib/geospatial/filter.rb
77
77
  - lib/geospatial/hilbert.rb
78
78
  - lib/geospatial/hilbert/curve.rb
79
+ - lib/geospatial/histogram.rb
79
80
  - lib/geospatial/index.rb
80
81
  - lib/geospatial/interleave.rb
81
82
  - lib/geospatial/location.rb
@@ -119,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
120
  version: '0'
120
121
  requirements: []
121
122
  rubyforge_project:
122
- rubygems_version: 2.6.10
123
+ rubygems_version: 2.7.7
123
124
  signing_key:
124
125
  specification_version: 4
125
126
  summary: Provides abstractions for dealing with geographical locations efficiently