encoded_polyline 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Brandon Liu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -2,22 +2,33 @@
2
2
 
3
3
  EncodedPolyline implements [Google's algorithm](http://code.google.com/apis/maps/documentation/utilities/polylinealgorithm.html) for compressing arrays of geographic points. The compressed string can then be passed to the Google Maps API.
4
4
  The Maps API limits URL requests to 2048 characters. This library does not enforce this limit on the encoding length.
5
+ This coordinate encoding scheme is also compatible with [MapQuest Platform Services](http://open.mapquestapi.com/common/encodedecode.html), which supports variable decimal precision. The default precision of 5 is appropriate for compatibility with the Google Maps API.
6
+
7
+ ## Installation
8
+
9
+ gem install encoded_polyline
5
10
 
6
11
  ## Examples
7
12
 
8
- An [example map](http://maps.googleapis.com/maps/api/staticmap?size=400x400&sensor=false&path=weight:3|color:blue|enc:~fzz\]_uvsOdX`a@jR~Boe@_XfPZoe@N{N}p@jTqIxCpYvi@?yApz@{r@}HkQ|l@xi@pa@vB{IiHg`@ao@jWxA_Bi_@gN_S|\[zN}s@vy@mQ|c@bd@TyHti@x\]ca@vZ~Di}@mb@`\hPxe@hRky@~Rk`@nq@_p@t_@mUdw@oHaWc@dNus@kVz\[gu@oi@ne@}Yxg@mu@iCo}@mm@gQhMgWtc@}Kxv@x_@gSlWq|@vT{v@q{@_m@jL_Td\]
9
- ) from a 50-point random walk, encoded using the library.
13
+ Using the library with default decimal precision of 5:
14
+
15
+ EncodedPolyline.encode(-179.9832104) # "`~oia@"
16
+ EncodedPolyline.decode("`~oia@") # -179.98321
17
+ EncodedPolyline.encode_points([[37.782,-122.406]]) # "ohreFnlbjV"
18
+ EncodedPolyline.decode_points("ohreFnlbjV") # [[37.782,-122.406]]
10
19
 
11
- Using the library:
20
+ Using the library with explicit decimal precisions:
12
21
 
13
- EncodedPolyline.encode(-179.9832104) # "`~oia@"
14
- EncodedPolyline.decode("`~oia@") # -179.98321
15
- EncodedPolyline.encode_points([[37.782,-122.406]]) # "ohreFnlbjV"
16
- EncodedPolyline.decode_points("ohreFnlbjV") # [[37.782,-122.406]]
22
+ EncodedPolyline.encode(-179.9832104, 7) # "na`|gjB"
23
+ EncodedPolyline.decode("na`|gjB", 7) # -179.9832104
24
+ EncodedPolyline.encode_points([[37.782,-122.406]], 2) # "ckF`|V"
25
+ EncodedPolyline.decode_points("ckF`|V", 2) # [[37.78, -122.41]]
26
+
27
+ It is important to specify the same precision when encoding and decoding. Otherwise, decoded coordinates may be wrong by orders of magnitude.
17
28
 
18
29
  ## Performance
19
30
 
20
- Some of the steps outlined in the algorithm spec are composed together, for speediness. Included is a benchmark that creates a 100-point random walk and encodes/decodes it 10,000 times (1 million points total).
31
+ Included is a benchmark that creates a 100-point random walk, gives you a URL, and encodes/decodes it 10,000 times (1 million points total).
21
32
 
22
33
  Raw length(JSON): 3682 characters
23
34
  Encoded length: 495 characters
@@ -27,7 +38,12 @@ Some of the steps outlined in the algorithm spec are composed together, for spee
27
38
  encoding 9.090000 0.000000 9.090000 ( 9.092519)
28
39
  decoding 16.470000 0.010000 16.480000 ( 16.473547)
29
40
 
30
- ## Known Issues
41
+ ## Contributors
42
+
43
+ [bdon](https://github.com/bdon) - author
44
+
45
+ [anoved](https://github.com/anoved) - explicit precision, MapQuest support
31
46
 
32
- Haven't tested with Ruby 1.9; probably doesn't work.
47
+ ## Copyright
33
48
 
49
+ Copyright (c) 2013 Brandon Liu. See LICENSE for details.
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
8
8
  s.version = EncodedPolyline::VERSION
9
9
  s.authors = ["Brandon Liu"]
10
10
  s.email = "bdon@bdon.org"
11
- s.date = "2011-09-02"
12
- s.description = "Encode an array of coordinates for the Google Static Maps API."
11
+ s.date = "2013-02-20"
12
+ s.description = "Encode an array of coordinates for the Google Static Maps and MapQuest APIs."
13
13
  s.summary = "Encode an array of coordinates"
14
14
  s.homepage = "http://github.com/bdon/encoded_polyline"
15
15
 
@@ -1,6 +1,6 @@
1
1
  class EncodedPolyline
2
- def self.encode(number)
3
- number = (number * 1e5).round
2
+ def self.encode(number, precision=5)
3
+ number = (number * (10 ** precision)).round
4
4
  n = number << 1
5
5
  n = ~n if number < 0
6
6
  str = ""
@@ -11,44 +11,44 @@ class EncodedPolyline
11
11
  return str << (n + 63).chr
12
12
  end
13
13
 
14
- def self.decode_arr(arr)
14
+ def self.decode_arr(arr, precision=5)
15
15
  num = 0
16
16
  arr[0..-2].each_with_index do |elem, i|
17
- num = (num | (((elem[0] - 63) ^ 0x20) << (i * 5)))
17
+ num = (num | (((elem[0].ord - 63) ^ 0x20) << (i * 5)))
18
18
  end
19
- num = (num | ((arr.last[0] - 63) << ((arr.size-1) * 5)))
19
+ num = (num | ((arr.last[0].ord - 63) << ((arr.size-1) * 5)))
20
20
  num = ~num if ((num & 0x1) == 1)
21
21
  num = num >> 1
22
- num = num.to_f / 1e5
22
+ num = num.to_f * (10 ** -precision)
23
23
  return num
24
24
  end
25
25
 
26
- def self.decode(str)
27
- self.decode_arr(str.split(//))
26
+ def self.decode(str, precision=5)
27
+ self.decode_arr(str.split(//), precision)
28
28
  end
29
29
 
30
- def self.encode_points(coordinates)
30
+ def self.encode_points(coordinates, precision=5)
31
31
  output = ""
32
- output << encode(coordinates.first[0])
33
- output << encode(coordinates.first[1])
32
+ output << encode(coordinates.first[0], precision)
33
+ output << encode(coordinates.first[1], precision)
34
34
 
35
35
  (1..coordinates.size-1).each do |i|
36
36
  previous = coordinates[i-1]
37
37
  current = coordinates[i]
38
- output << encode(current[0] - previous[0])
39
- output << encode(current[1] - previous[1])
38
+ output << encode(current[0] - previous[0], precision)
39
+ output << encode(current[1] - previous[1], precision)
40
40
  end
41
41
  return output
42
42
  end
43
43
 
44
- def self.decode_points(str)
44
+ def self.decode_points(str, precision=5)
45
45
  decoded_points = []
46
46
  point_chars = []
47
47
 
48
48
  str.each_char do |char|
49
49
  point_chars << char
50
- if ((char[0] - 63) & 0x20).zero?
51
- decoded_points << decode_arr(point_chars)
50
+ if ((char[0].ord - 63) & 0x20).zero?
51
+ decoded_points << decode_arr(point_chars, precision)
52
52
  point_chars = []
53
53
  end
54
54
  end
@@ -62,4 +62,4 @@ class EncodedPolyline
62
62
  end
63
63
  return coordinates
64
64
  end
65
- end
65
+ end
@@ -1,3 +1,3 @@
1
1
  class EncodedPolyline
2
- VERSION = "0.0.1".freeze
2
+ VERSION = "0.0.2"
3
3
  end
@@ -5,6 +5,10 @@ describe EncodedPolyline, ".encode" do
5
5
  EncodedPolyline.encode(-179.9832104).should == "`~oia@"
6
6
  end
7
7
 
8
+ it "encodes a single point with explicit precision" do
9
+ EncodedPolyline.encode(-179.9832104, 7).should == "na`|gjB"
10
+ end
11
+
8
12
  it "encodes a very slightly negative point" do
9
13
  # Due to precision errors, verify that a negative value that rounds to 0 works.
10
14
  EncodedPolyline.encode(-3e-6).should == "?"
@@ -13,14 +17,18 @@ end
13
17
 
14
18
  describe EncodedPolyline, ".decode" do
15
19
  it "decodes a single point" do
16
- EncodedPolyline.decode('`~oia@').should be_close(-179.9832104, 0.0001)
20
+ EncodedPolyline.decode('`~oia@').should be_within(0.00001).of(-179.9832104)
21
+ end
22
+
23
+ it "decodes a single point with explicit precision" do
24
+ EncodedPolyline.decode("na`|gjB", 7).should be_within(0.0000001).of(-179.9832104)
17
25
  end
18
26
  end
19
27
 
20
28
  def should_be_similar_points(arr1, arr2)
21
29
  arr1.each_with_index do |(x,y),i|
22
- x.should be_close(arr2[i][0], 0.0001)
23
- y.should be_close(arr2[i][1], 0.0001)
30
+ x.should be_within(0.0001).of(arr2[i][0])
31
+ y.should be_within(0.0001).of(arr2[i][1])
24
32
  end
25
33
  end
26
34
 
@@ -33,10 +41,18 @@ describe EncodedPolyline, ".decode_points" do
33
41
  EncodedPolyline.encode_points([[37.782,-122.406]]).should == "ohreFnlbjV"
34
42
  end
35
43
 
44
+ it "encodes a a pair of points with explicit precision" do
45
+ EncodedPolyline.encode_points([[37.782,-122.406]], 2).should == "ckF`|V"
46
+ end
47
+
36
48
  it "should decode" do
37
49
  should_be_similar_points(EncodedPolyline.decode_points(ring_text), ring_points)
38
50
  end
39
51
 
52
+ it "decodes points with explicit precision" do
53
+ should_be_similar_points(EncodedPolyline.decode_points("ckF`|V", 2),[[37.78, -122.41]])
54
+ end
55
+
40
56
  it "encodes points with little variation" do
41
57
  points = [[37.79297, -122.39676],[37.79297, -122.39676],[37.79297, -122.39676]]
42
58
  should_be_similar_points(EncodedPolyline.decode_points(EncodedPolyline.encode_points(points)), points)
metadata CHANGED
@@ -1,62 +1,56 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: encoded_polyline
3
- version: !ruby/object:Gem::Version
4
- hash: 29
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 1
10
- version: 0.0.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Brandon Liu
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-09-02 00:00:00 -07:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2013-02-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: rake
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
33
22
  type: :development
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: rspec
37
23
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
39
33
  none: false
40
- requirements:
34
+ requirements:
41
35
  - - ~>
42
- - !ruby/object:Gem::Version
43
- hash: 25
44
- segments:
45
- - 1
46
- - 3
47
- - 1
36
+ - !ruby/object:Gem::Version
48
37
  version: 1.3.1
49
38
  type: :development
50
- version_requirements: *id002
51
- description: Encode an array of coordinates for the Google Static Maps API.
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.3.1
46
+ description: Encode an array of coordinates for the Google Static Maps and MapQuest
47
+ APIs.
52
48
  email: bdon@bdon.org
53
49
  executables: []
54
-
55
50
  extensions: []
56
-
57
51
  extra_rdoc_files: []
58
-
59
- files:
52
+ files:
53
+ - LICENSE
60
54
  - README.markdown
61
55
  - Rakefile
62
56
  - encoded_polyline.gemspec
@@ -66,40 +60,31 @@ files:
66
60
  - script/benchmark.rb
67
61
  - spec/encoded_polyline/encoded_polyline_spec.rb
68
62
  - spec/spec_helper.rb
69
- has_rdoc: true
70
63
  homepage: http://github.com/bdon/encoded_polyline
71
64
  licenses: []
72
-
73
65
  post_install_message:
74
66
  rdoc_options: []
75
-
76
- require_paths:
67
+ require_paths:
77
68
  - lib
78
- required_ruby_version: !ruby/object:Gem::Requirement
69
+ required_ruby_version: !ruby/object:Gem::Requirement
79
70
  none: false
80
- requirements:
81
- - - ">="
82
- - !ruby/object:Gem::Version
83
- hash: 3
84
- segments:
85
- - 0
86
- version: "0"
87
- required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
76
  none: false
89
- requirements:
90
- - - ">="
91
- - !ruby/object:Gem::Version
92
- hash: 3
93
- segments:
94
- - 0
95
- version: "0"
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
96
81
  requirements: []
97
-
98
82
  rubyforge_project:
99
- rubygems_version: 1.6.2
83
+ rubygems_version: 1.8.23
100
84
  signing_key:
101
85
  specification_version: 3
102
86
  summary: Encode an array of coordinates
103
- test_files:
87
+ test_files:
104
88
  - spec/encoded_polyline/encoded_polyline_spec.rb
105
89
  - spec/spec_helper.rb
90
+ has_rdoc: