geomodel 0.0.1 → 0.0.2

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
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