geomodel 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b8914e3d585af5281290b7a854cb1eec6d7a566c
4
- data.tar.gz: 30b52b4cb9989bf752dbe9fb426f71607ef5858c
3
+ metadata.gz: 90db919642b9d8269c289645bf18195b8efeb665
4
+ data.tar.gz: 1278b9035c58e080d225e81aebc38ac7cf1a4b22
5
5
  SHA512:
6
- metadata.gz: b170a8372a165c3bdad452588f7ffad1174996b448076f8a139bd0ee48bd83924ef1a4420734d9c98f8106239ce2fb601d0cd525350a4b692662f68847d61e80
7
- data.tar.gz: 13298af29d84898c152475a74ffc11d917507224a5f2a36b5e2cd3bc0c6e4e0e18fbca99366c8c545771c0076e5daf02421d53d2200d92e2ec2d1a63e6cda41f
6
+ metadata.gz: 3f471cead361f81bfa870db73eb9ad372f177cf77e6dfb329be0b8fce036e3dc16020f650ae384a7a5a5c9ddeb845058016477512aa95cd368d87fb9b150c9e6
7
+ data.tar.gz: 17bc0e26b4f43181c3cb22cf398714fb65457bab4ddc495ae4928aba532f095eef9d8b5e6f303252ec5907283bd89ab06885dd6c7c0ffc49739aa90500831862
@@ -1,2 +1,5 @@
1
1
  ### 0.0.1 (January 2, 2014)
2
- * Initial release - Straight port from Python, Java and JS implementations
2
+ * Initial release - Straight port from Python, Java and JS implementations
3
+
4
+ ### 0.0.2 (January 5, 2014)
5
+ * Upped the test coverage (which revealed some pretty blatant bugs)
data/README.md CHANGED
@@ -68,10 +68,13 @@ indexed and filtered by either conformance to a bounding box or by proximity
68
68
  # Approach
69
69
 
70
70
  This Ruby implementation of GeoModel is based on the Python, Java and JavaScript implementations.
71
- It's implemented as class level methods contained modules and a few datatype classes. So the 'model'
72
- part isn't quite there and I don't really see a need for it. Since the library is meant to be use in
73
- Non-Relational/Non-ORM environmets, binding the functions/methods to a model does not make much sense.
71
+ It's implemented as class level methods contained within modules and a few datatype classes. So the
72
+ 'model' part isn't quite there and I don't really see a need for it. Since the library is meant to
73
+ be use in Non-Relational/Non-ORM environmets, binding the functions/methods to a model does not make
74
+ much sense.
75
+
74
76
  The model part was mostly implemented in the other libraries to bind directly to Google App Engine.
77
+ The idea here is to make it backend/db independent and use callbacks to integrate with the backend.
75
78
 
76
79
  # References
77
80
 
@@ -100,7 +103,7 @@ Or install it yourself as:
100
103
  Currently, only single-point entities and two types of basic geospatial queries
101
104
  on those entities are supported.
102
105
 
103
- ### Representing your locations
106
+ ### Representing your Locations
104
107
 
105
108
  You'll need a class to hold a geolocation. It assumes that an "entity" has a unique
106
109
  "id" (specific field can be configure), a latitude/longitude combination stored in
@@ -125,6 +128,21 @@ flw_spire = Entity.new
125
128
  flw_spire.id = 'Flatiron'
126
129
  flw_spire.location = Geomodel::Types::Point.new(33.633406, -111.916803)
127
130
  flw_spire.geocells = Geomodel::GeoCell.generate_geocells(flw_spire.location)
131
+
132
+ puts flw_spire.geocells
133
+ # 8
134
+ # 8d
135
+ # 8da
136
+ # 8daa
137
+ # 8daab
138
+ # 8daab6
139
+ # 8daab66
140
+ # 8daab666
141
+ # 8daab6668
142
+ # 8daab66684
143
+ # 8daab66684e
144
+ # 8daab66684e4
145
+ # 8daab66684e4d
128
146
  ```
129
147
 
130
148
  ### Bounding Box Queries
@@ -147,7 +165,7 @@ result_set = my_db.query('SELECT * WHERE location_geocells IN (?)', query_geocel
147
165
  matches = Geomodel.filter_result_set_by_bounding_box(bounding_box, result_set)
148
166
  ```
149
167
 
150
- ### proximity (nearest-n) queries
168
+ ### Proximity (nearest-n) Queries
151
169
 
152
170
  Find nearby locations given a location (lat & lon) and a radius in meters:
153
171
 
@@ -189,4 +207,4 @@ distances = results.map(&:last)
189
207
 
190
208
  ## License
191
209
 
192
- MIT License
210
+ MIT License
@@ -84,7 +84,7 @@ module Geomodel
84
84
  while !cur_geocells.empty?
85
85
  closest_possible_next_result_dist = sorted_edge_distances[0]
86
86
 
87
- next if max_distance and closest_possible_next_result_dist > max_distance
87
+ next if max_distance && closest_possible_next_result_dist > max_distance
88
88
 
89
89
  cur_geocells_unique = cur_geocells - searched_cells.to_a
90
90
 
@@ -267,7 +267,7 @@ module Geomodel
267
267
  cell_adj_arr = cell.split(//) # Split the geocell string characters into a list.
268
268
  i = cell_adj_arr.size - 1
269
269
 
270
- while i >= 0 && (dx != 0 or dy != 0)
270
+ while i >= 0 && (dx != 0 || dy != 0)
271
271
  x, y = subdiv_xy(cell_adj_arr[i])
272
272
 
273
273
  # Horizontal adjacency.
@@ -339,24 +339,25 @@ module Geomodel
339
339
  if between_w_e
340
340
  if between_n_s
341
341
  # Inside the geocell.
342
- return [Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(bbox.south, point.lon)),
343
- Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(bbox.north, point.lon)),
344
- Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(point.lat, bbox.east)),
345
- Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(point.lat, bbox.west))].min
342
+
343
+ return [Geomodel::Math.distance(point, Geomodel::Types::Point.new(bbox.south, point.lon)),
344
+ Geomodel::Math.distance(point, Geomodel::Types::Point.new(bbox.north, point.lon)),
345
+ Geomodel::Math.distance(point, Geomodel::Types::Point.new(point.lat, bbox.east)),
346
+ Geomodel::Math.distance(point, Geomodel::Types::Point.new(point.lat, bbox.west))].min
346
347
  else
347
- return [Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(bbox.south, point.lon)),
348
- Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(bbox.north, point.lon))].min
348
+ return [Geomodel::Math.distance(point, Geomodel::Types::Point.new(bbox.south, point.lon)),
349
+ Geomodel::Math.distance(point, Geomodel::Types::Point.new(bbox.north, point.lon))].min
349
350
  end
350
351
  else
351
352
  if between_n_s
352
- return [Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(point.lat, bbox.east)),
353
- Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(point.lat, bbox.west))]
353
+ return [Geomodel::Math.distance(point, Geomodel::Types::Point.new(point.lat, bbox.east)),
354
+ Geomodel::Math.distance(point, Geomodel::Types::Point.new(point.lat, bbox.west))].min
354
355
  else
355
356
  # TODO(romannurik): optimize
356
- return [Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(bbox.south, bbox.east)),
357
- Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(bbox.north, bbox.east)),
358
- Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(bbox.south, bbox.west)),
359
- Geocoder::GeoMath.distance(point, Geomodel::Types::Point.new(bbox.north, bbox.west))]
357
+ return [Geomodel::Math.distance(point, Geomodel::Types::Point.new(bbox.south, bbox.east)),
358
+ Geomodel::Math.distance(point, Geomodel::Types::Point.new(bbox.north, bbox.east)),
359
+ Geomodel::Math.distance(point, Geomodel::Types::Point.new(bbox.south, bbox.west)),
360
+ Geomodel::Math.distance(point, Geomodel::Types::Point.new(bbox.north, bbox.west))].min
360
361
  end
361
362
  end
362
363
  end
@@ -444,7 +445,7 @@ module Geomodel
444
445
  # For example, the immediate children of 'a' are 'a0', 'a1', ..., 'af'.
445
446
  #
446
447
  def self.children(cell)
447
- GEOCELL_ALPHABET.map { |chr| cell + chr }
448
+ GEOCELL_ALPHABET.split(//).map { |chr| cell + chr }
448
449
  end
449
450
 
450
451
  # Returns the (x, y) of the geocell character in the 4x4 alphabet grid.
@@ -8,7 +8,7 @@ module Geomodel::Types
8
8
  #
9
9
  class Point
10
10
 
11
- attr_reader :latitude, :longitude
11
+ attr_accessor :latitude, :longitude
12
12
 
13
13
  alias_method :lat, :latitude
14
14
  alias_method :lon, :longitude
@@ -1,3 +1,3 @@
1
1
  module Geomodel
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -58,6 +58,26 @@ describe 'Geomodel::GeoCell' do
58
58
  expect(all_adjacents.size).to eq(8)
59
59
  end
60
60
 
61
+ it "can determine adjacency left and bottom of parent cell" do
62
+ cells = {
63
+ "8e6187fe6187fa" => ["8e6187fe618d45", "8e6187fe618d50", "8e6187fe618d51", "8e6187fe6187fb", "8e6187fe6187f9", "8e6187fe6187f8", "8e6187fe6187ed", "8e6187fe6187ef"],
64
+ "8e6187fe618d45" => ["8e6187fe618d46", "8e6187fe618d47", "8e6187fe618d52", "8e6187fe618d50", "8e6187fe6187fa", "8e6187fe6187ef", "8e6187fe6187ee", "8e6187fe618d44"]
65
+ }
66
+ cells.each do |cell, adjacents|
67
+ expect(Geomodel::GeoCell.all_adjacents(cell)).to eq(adjacents)
68
+ end
69
+ end
70
+
71
+ it "cam calculate the immediate children of a given geocell" do
72
+ expect(Geomodel::GeoCell.children("8e6187fe6187f")).
73
+ to eq(
74
+ %w(8e6187fe6187f0 8e6187fe6187f1 8e6187fe6187f2 8e6187fe6187f3
75
+ 8e6187fe6187f4 8e6187fe6187f5 8e6187fe6187f6 8e6187fe6187f7
76
+ 8e6187fe6187f8 8e6187fe6187f9 8e6187fe6187fa 8e6187fe6187fb
77
+ 8e6187fe6187fc 8e6187fe6187fd 8e6187fe6187fe 8e6187fe6187ff)
78
+ )
79
+ end
80
+
61
81
  it "can determine collinearity" do
62
82
  cell = Geomodel::GeoCell.compute(Geomodel::Types::Point.new(37, -122), 14)
63
83
 
@@ -109,6 +129,30 @@ describe 'Geomodel::GeoCell' do
109
129
  expect(geocells).to include("9aa228a8b3b00")
110
130
  end
111
131
 
132
+ it "can calculate that the shortest distance between a point and a geocell bounding boxfor the point is effectively zero" do
133
+ point = Geomodel::Types::Point.new(40.7407092, -73.9894039)
134
+ cell = "9ac7be064ea77"
135
+ expect(Geomodel::GeoCell.point_distance(cell, point)).to be_within(0.2).of(0.0)
136
+ end
137
+
138
+ it "can calculate the shortest distance between a point outside a geocell and the geocell" do
139
+ point = Geomodel::Types::Point.new(40.7425610, -73.9922670)
140
+ cell = "9ac7be064ea77"
141
+ expect(Geomodel::GeoCell.point_distance(cell, point)).to be_within(0.2).of(317.2)
142
+ end
143
+
144
+ it "can calculate the shortest distance between a point between north and south (but not between east and west) of a geocell bounding box" do
145
+ point = Geomodel::Types::Point.new(40.740710, -74.025537)
146
+ cell = "9ac7be064ea77"
147
+ expect(Geomodel::GeoCell.point_distance(cell, point)).to be_within(0.2).of(3047.3)
148
+ end
149
+
150
+ it "can calculate the shortest distance between a point between east and west (but not between north and south) of a geocell bounding box" do
151
+ point = Geomodel::Types::Point.new(40.740720, -73.989403)
152
+ cell = "9ac7be064ea77"
153
+ expect(Geomodel::GeoCell.point_distance(cell, point)).to be_within(0.2).of(0.99)
154
+ end
155
+
112
156
  # TODO implement these tests!
113
157
 
114
158
  # @Test
@@ -54,12 +54,39 @@ describe 'Geomodel::Types' do
54
54
  expect(box_a).to eq(box_b)
55
55
  end
56
56
 
57
- it "can be created with north below south" do
57
+ it "can't be created with north below south" do
58
58
  box = Geomodel::Types::Box.new(37, -122, 34, -125)
59
59
 
60
60
  expect { box.north = 32 }.to raise_error
61
61
  expect { box.south = 39 }.to raise_error
62
62
  end
63
+
64
+ it "can be created with south below north" do
65
+ box = Geomodel::Types::Box.new(37, -122, 34, -125)
66
+
67
+ expect { box.north = 39 }.to_not raise_error
68
+ expect { box.south = 32 }.to_not raise_error
69
+ end
70
+
71
+ it "can be set the values for north, east, south and west" do
72
+ box = Geomodel::Types::Box.new(37, -122, 34, -125)
73
+
74
+ expect { box.north = 39 }.to_not raise_error
75
+ expect { box.south = 32 }.to_not raise_error
76
+ expect { box.east = -123 }.to_not raise_error
77
+ expect { box.west = -126 }.to_not raise_error
78
+
79
+ expect(box.north).to eq(39)
80
+ expect(box.south).to eq(32)
81
+ expect(box.east).to eq(-123)
82
+ expect(box.west).to eq(-126)
83
+ end
84
+
85
+ it "returns a suitable string representation" do
86
+ box = Geomodel::Types::Box.new(37, -122, 34, -125)
87
+
88
+ expect(box.to_s).to eq('(37, -122, 34, -125)')
89
+ end
63
90
 
64
91
  end
65
92
  end
@@ -7,7 +7,9 @@ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
7
7
  SimpleCov::Formatter::HTMLFormatter,
8
8
  Coveralls::SimpleCov::Formatter
9
9
  ]
10
- SimpleCov.start
10
+ SimpleCov.start do
11
+ add_filter "/spec/"
12
+ end
11
13
 
12
14
  require 'rubygems'
13
15
  require 'pry'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geomodel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Sam-Bodden
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-02 00:00:00.000000000 Z
11
+ date: 2014-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: geocoder