polylines 0.0.1 → 0.4.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: da58528bb3a57978f8dc73763bcebd2dd09d64cac7f6c64f6dffc33cdcc9a1c1
4
+ data.tar.gz: a0869fe420b3721e367374e163c2b396655efbb47b1a6c50b8864943a162a191
5
+ SHA512:
6
+ metadata.gz: b8745bf6f073c0894590884508f587448fdda56a9e24e8c2a09649f7477cd2eab1602e85c2754eb43242e43bc7748d8eb703aa948d68c9959ac546f7363dbe42
7
+ data.tar.gz: 9dc0c56d23b52261c03443a6f0b9a1a6e96fcb2c7f5b20ff1246853e69370c0fea4d1a35614a95deaccdb6f5a125fc8f4bb165f459da55f4c41a2074b950ae70
@@ -1,24 +1,34 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polylines (0.0.1)
4
+ polylines (0.4.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
8
8
  specs:
9
- diff-lcs (1.1.2)
10
- rspec (2.4.0)
11
- rspec-core (~> 2.4.0)
12
- rspec-expectations (~> 2.4.0)
13
- rspec-mocks (~> 2.4.0)
14
- rspec-core (2.4.0)
15
- rspec-expectations (2.4.0)
16
- diff-lcs (~> 1.1.2)
17
- rspec-mocks (2.4.0)
9
+ diff-lcs (1.4.4)
10
+ rake (10.0.2)
11
+ rspec (3.10.0)
12
+ rspec-core (~> 3.10.0)
13
+ rspec-expectations (~> 3.10.0)
14
+ rspec-mocks (~> 3.10.0)
15
+ rspec-core (3.10.0)
16
+ rspec-support (~> 3.10.0)
17
+ rspec-expectations (3.10.0)
18
+ diff-lcs (>= 1.2.0, < 2.0)
19
+ rspec-support (~> 3.10.0)
20
+ rspec-mocks (3.10.0)
21
+ diff-lcs (>= 1.2.0, < 2.0)
22
+ rspec-support (~> 3.10.0)
23
+ rspec-support (3.10.0)
18
24
 
19
25
  PLATFORMS
20
26
  ruby
21
27
 
22
28
  DEPENDENCIES
23
29
  polylines!
24
- rspec (= 2.4.0)
30
+ rake
31
+ rspec (= 3.10.0)
32
+
33
+ BUNDLED WITH
34
+ 2.1.4
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2011 Josh Clayton
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # Polylines
2
+
3
+ ## Easily handle Google polylines
4
+
5
+ ## Install
6
+
7
+ Install with Rubygems:
8
+
9
+ gem install polylines
10
+
11
+ ## Usage
12
+
13
+ To encode an array of latitude/longitude pairs:
14
+
15
+ >> Polylines::Encoder.encode_points([[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]])
16
+ => "_p~iF~ps|U_ulLnnqC_mqNvxq`@"
17
+
18
+ To decode a polyline into an array of latitude/longitude pairs:
19
+
20
+ >> Polylines::Decoder.decode_polyline("_p~iF~ps|U_ulLnnqC_mqNvxq`@")
21
+ => [[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]]
22
+
23
+ I wrote this to follow the steps outlined in http://code.google.com/apis/maps/documentation/utilities/polylinealgorithm.html.
24
+
25
+ ## License
26
+
27
+ Please see LICENSE
28
+
29
+ ## Author
30
+
31
+ Written by Josh Clayton
@@ -1,5 +1,6 @@
1
+ require "polylines/base"
2
+ require "polylines/encoder"
3
+ require "polylines/decoder"
4
+
1
5
  module Polylines
2
- autoload :Base, "polylines/base"
3
- autoload :Encoder, "polylines/encoder"
4
- autoload :Decoder, "polylines/decoder"
5
6
  end
@@ -6,11 +6,11 @@ module Polylines
6
6
  @current_value = current_value
7
7
  end
8
8
 
9
- def step_2
9
+ def step_2(precision = 1e5)
10
10
  @negative = current_value < 0 if encoding?
11
11
 
12
- encode! { (current_value * 1e5).round }
13
- decode! { current_value.to_f/1e5 }
12
+ encode! { (current_value * precision).round }
13
+ decode! { current_value.to_f/precision }
14
14
  end
15
15
 
16
16
  def step_3
@@ -37,6 +37,8 @@ module Polylines
37
37
  numbers.unshift(current_value & 0x1f)
38
38
  @current_value >>= 5
39
39
  end
40
+
41
+ numbers << 0 if numbers.empty?
40
42
  end
41
43
  end
42
44
 
@@ -87,16 +89,18 @@ module Polylines
87
89
  self.is_a?(Polylines::Decoder)
88
90
  end
89
91
 
90
- def self.transform_to_array_of_lat_lng_and_deltas(value)
92
+ def self.transform_to_array_of_lat_lng_and_deltas(value, precision = 1e5)
91
93
  if self == Polylines::Encoder
92
94
  delta_latitude, delta_longitude = 0, 0
93
95
 
94
- return value.inject([]) do |polyline, (latitude, longitude)|
96
+ shifted_values = value.map{|tuple| tuple.map{|val| (val * precision).round } }
97
+ deltas = shifted_values.inject([]) do |polyline, (latitude, longitude)|
95
98
  polyline << latitude - delta_latitude
96
99
  polyline << longitude - delta_longitude
97
100
  delta_latitude, delta_longitude = latitude, longitude
98
101
  polyline
99
102
  end
103
+ return deltas.map{|val| val.to_f/precision }
100
104
  end
101
105
 
102
106
  if self == Polylines::Decoder
@@ -110,7 +114,7 @@ module Polylines
110
114
  end
111
115
 
112
116
  charset
113
- end.map {|charset| decode(charset) }
117
+ end.map {|charset| decode(charset, precision) }
114
118
  end
115
119
  end
116
120
  end
@@ -1,12 +1,13 @@
1
1
  module Polylines
2
2
  class Decoder < Base
3
- def self.decode_polyline(polyline)
4
- points_with_deltas = transform_to_array_of_lat_lng_and_deltas(polyline)
3
+ def self.decode_polyline(polyline, precision = 1e5)
4
+ points_with_deltas = transform_to_array_of_lat_lng_and_deltas(polyline,
5
+ precision)
5
6
 
6
7
  [].tap do |points|
7
8
  points << [points_with_deltas.shift, points_with_deltas.shift]
8
9
 
9
- while points_with_deltas.any?
10
+ while points_with_deltas.size > 1
10
11
  points << [
11
12
  points.last[0] + points_with_deltas.shift,
12
13
  points.last[1] + points_with_deltas.shift
@@ -15,7 +16,7 @@ module Polylines
15
16
  end
16
17
  end
17
18
 
18
- def self.decode(string)
19
+ def self.decode(string, precision = 1e5)
19
20
  self.new(string).tap do |decoding|
20
21
  decoding.step_11
21
22
  decoding.step_10
@@ -25,7 +26,7 @@ module Polylines
25
26
  decoding.step_5
26
27
  decoding.step_4
27
28
  decoding.step_3
28
- decoding.step_2
29
+ decoding.step_2 precision
29
30
  end.current_value
30
31
  end
31
32
  end
@@ -1,13 +1,13 @@
1
1
  module Polylines
2
2
  class Encoder < Base
3
- def self.encode_points(points)
4
- points_with_deltas = transform_to_array_of_lat_lng_and_deltas(points)
5
- points_with_deltas.map {|point| encode(point) }.join
3
+ def self.encode_points(points, precision = 1e5)
4
+ points_with_deltas = transform_to_array_of_lat_lng_and_deltas(points, precision)
5
+ points_with_deltas.map {|point| encode(point, precision) }.join
6
6
  end
7
7
 
8
- def self.encode(number)
8
+ def self.encode(number, precision = 1e5)
9
9
  self.new(number).tap do |encoding|
10
- encoding.step_2
10
+ encoding.step_2 precision
11
11
  encoding.step_3
12
12
  encoding.step_4
13
13
  encoding.step_5
@@ -1,3 +1,3 @@
1
1
  module Polylines
2
- VERSION = "0.0.1"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -16,5 +16,6 @@ Gem::Specification.new do |s|
16
16
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
17
  s.require_paths = ["lib"]
18
18
 
19
- s.add_development_dependency("rspec", "2.4.0")
19
+ s.add_development_dependency("rspec", "3.10.0")
20
+ s.add_development_dependency("rake")
20
21
  end
@@ -2,15 +2,52 @@ require "spec_helper"
2
2
 
3
3
  describe Polylines::Decoder, ".decode" do
4
4
  it "decodes a single point" do
5
- Polylines::Decoder.decode("`~oia@").should be_within(0.00001).of(-179.9832104)
5
+ expect(Polylines::Decoder.decode("`~oia@")).to be_within(0.00001).of(-179.9832104)
6
+ end
7
+
8
+ it "decodes a single point with 1e6 precision" do
9
+ expect(Polylines::Decoder.decode("ruhhvI", 1e6)).to be_within(0.000001).of(-179.9832104)
6
10
  end
7
11
  end
8
12
 
9
13
  describe Polylines::Decoder, ".decode_polyline" do
10
- let(:polyline) { "_p~iF~ps|U_ulLnnqC_mqNvxq`@" }
11
- let(:points) { [[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]] }
14
+ let(:points) { [[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]] }
15
+
16
+ context "with default precision" do
17
+ it "decodes a polyline correctly" do
18
+ polyline = "_p~iF~ps|U_ulLnnqC_mqNvxq`@"
19
+
20
+ expect(Polylines::Decoder.decode_polyline(polyline)).to eq points
21
+ end
22
+ end
23
+
24
+ context "with 1e6 precision" do
25
+ it "decodes a polyline correctly" do
26
+ polyline = "_izlhA~rlgdF_{geC~ywl@_kwzCn`{nI"
27
+
28
+ expect(Polylines::Decoder.decode_polyline(polyline, 1e6)).to eq points
29
+ end
30
+ end
31
+ end
12
32
 
33
+ describe Polylines::Decoder, ".decode_polyline with points that were close together" do
13
34
  it "decodes a polyline correctly" do
14
- Polylines::Decoder.decode_polyline(polyline).should == points
35
+ points = [[41.35222, -86.04563], [41.35222, -86.04544]]
36
+
37
+ expect(Polylines::Decoder.decode_polyline("krk{FdxdlO?e@")).to eq points
38
+ end
39
+
40
+ it "decodes a polyline correctly with 1e6 precision" do
41
+ points = [[41.352217, -86.045630], [41.352217, -86.045437]]
42
+
43
+ expect(Polylines::Decoder.decode_polyline("q`}zmAzzxbcD?aK", 1e6)).to eq points
44
+ end
45
+ end
46
+
47
+ describe Polylines::Decoder, ".decode_polyline with a value that previously broke" do
48
+ it "decodes a polyline correctly" do
49
+ value = "kbdoH{ioqCoF_j@Lwc@lC{BhNoMzCuJbEm]?wKkBaQmD}EqM_GwFiBfCge@zE_K~SaTdT`L|Da\\\\xJsX|EyJtQgPpXuRjKAtJqBfM[pn@g^nF}G??"
50
+
51
+ expect(Polylines::Decoder.decode_polyline(value).length).to eq 27
15
52
  end
16
53
  end
@@ -2,15 +2,52 @@ require "spec_helper"
2
2
 
3
3
  describe Polylines::Encoder, ".encode" do
4
4
  it "encodes a single point" do
5
- Polylines::Encoder.encode(-179.9832104).should == "`~oia@"
5
+ expect(Polylines::Encoder.encode(-179.9832104)).to eq "`~oia@"
6
+ end
7
+
8
+ it "encodes a single point with 1e6 precision" do
9
+ expect(Polylines::Encoder.encode(-179.9832104, 1e6)).to eq "ruhhvI"
6
10
  end
7
11
  end
8
12
 
9
13
  describe Polylines::Encoder, ".encode_points" do
10
- let(:polyline) { "_p~iF~ps|U_ulLnnqC_mqNvxq`@" }
11
- let(:points) { [[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]] }
14
+ let(:points) { [[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]] }
15
+
16
+ context "with default precision" do
17
+ it "encodes points correctly" do
18
+ polyline = "_p~iF~ps|U_ulLnnqC_mqNvxq`@"
19
+
20
+ expect(Polylines::Encoder.encode_points(points)).to eq polyline
21
+ end
22
+ end
23
+
24
+ context "with 1e6 precsion" do
25
+ it "encodes points correctly" do
26
+ polyline = "_izlhA~rlgdF_{geC~ywl@_kwzCn`{nI"
27
+
28
+ expect(Polylines::Encoder.encode_points(points, 1e6)).to eq polyline
29
+ end
30
+ end
31
+ end
12
32
 
33
+ describe Polylines::Encoder, ".encode_points that are very close together" do
13
34
  it "encodes points correctly" do
14
- Polylines::Encoder.encode_points(points).should == polyline
35
+ points = [[41.3522171071184, -86.0456299662023], [41.3522171071183, -86.0454368471533]]
36
+
37
+ expect(Polylines::Encoder.encode_points(points)).to eq "krk{FdxdlO?e@"
38
+ end
39
+
40
+ it "encodes points correctly with 1e6 precision" do
41
+ points = [[41.3522171071184, -86.0456299662023], [41.3522171071183, -86.0454368471533]]
42
+
43
+ expect(Polylines::Encoder.encode_points(points, 1e6)).to eq "q`}zmAzzxbcD?aK"
44
+ end
45
+ end
46
+
47
+ describe Polylines::Encoder, ".encode_points with same results as google's api" do
48
+ it "encodes without rounding errors" do
49
+ points = [[39.13594499,-94.4243478], [39.13558757,-94.4243471]]
50
+
51
+ expect(Polylines::Encoder.encode_points(points)).to eq "svzmFdgi_QdA?"
15
52
  end
16
53
  end
@@ -1,7 +1,3 @@
1
1
  require "rubygems"
2
2
  require "bundler/setup"
3
-
4
3
  require "polylines"
5
- #
6
- # RSpec.configure do |config|
7
- # end
metadata CHANGED
@@ -1,50 +1,55 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: polylines
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 1
9
- version: 0.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Josh Clayton
13
8
  autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
-
17
- date: 2011-02-19 00:00:00 -05:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
11
+ date: 2020-12-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
21
14
  name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.10.0
20
+ type: :development
22
21
  prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - "="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 2
30
- - 4
31
- - 0
32
- version: 2.4.0
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.10.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
33
34
  type: :development
34
- version_requirements: *id001
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
35
41
  description:
36
- email:
42
+ email:
37
43
  - joshua.clayton@gmail.com
38
44
  executables: []
39
-
40
45
  extensions: []
41
-
42
46
  extra_rdoc_files: []
43
-
44
- files:
45
- - .gitignore
47
+ files:
48
+ - ".gitignore"
46
49
  - Gemfile
47
50
  - Gemfile.lock
51
+ - LICENSE
52
+ - README.markdown
48
53
  - Rakefile
49
54
  - lib/polylines.rb
50
55
  - lib/polylines/base.rb
@@ -55,39 +60,29 @@ files:
55
60
  - spec/polylines/decoder_spec.rb
56
61
  - spec/polylines/encoder_spec.rb
57
62
  - spec/spec_helper.rb
58
- has_rdoc: true
59
- homepage: ""
63
+ homepage: ''
60
64
  licenses: []
61
-
65
+ metadata: {}
62
66
  post_install_message:
63
67
  rdoc_options: []
64
-
65
- require_paths:
68
+ require_paths:
66
69
  - lib
67
- required_ruby_version: !ruby/object:Gem::Requirement
68
- none: false
69
- requirements:
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
70
72
  - - ">="
71
- - !ruby/object:Gem::Version
72
- segments:
73
- - 0
74
- version: "0"
75
- required_rubygems_version: !ruby/object:Gem::Requirement
76
- none: false
77
- requirements:
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
78
77
  - - ">="
79
- - !ruby/object:Gem::Version
80
- segments:
81
- - 0
82
- version: "0"
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
83
80
  requirements: []
84
-
85
- rubyforge_project:
86
- rubygems_version: 1.3.7
81
+ rubygems_version: 3.1.4
87
82
  signing_key:
88
- specification_version: 3
83
+ specification_version: 4
89
84
  summary: Easily handle Google polylines
90
- test_files:
85
+ test_files:
91
86
  - spec/polylines/decoder_spec.rb
92
87
  - spec/polylines/encoder_spec.rb
93
88
  - spec/spec_helper.rb