polylines 0.0.1
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.
- data/.gitignore +3 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +24 -0
- data/Rakefile +12 -0
- data/lib/polylines.rb +5 -0
- data/lib/polylines/base.rb +117 -0
- data/lib/polylines/decoder.rb +32 -0
- data/lib/polylines/encoder.rb +22 -0
- data/lib/polylines/version.rb +3 -0
- data/polylines.gemspec +20 -0
- data/spec/polylines/decoder_spec.rb +16 -0
- data/spec/polylines/encoder_spec.rb +16 -0
- data/spec/spec_helper.rb +7 -0
- metadata +93 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
polylines (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
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)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
polylines!
|
24
|
+
rspec (= 2.4.0)
|
data/Rakefile
ADDED
data/lib/polylines.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
module Polylines
|
2
|
+
class Base
|
3
|
+
attr_reader :current_value, :negative
|
4
|
+
|
5
|
+
def initialize(current_value)
|
6
|
+
@current_value = current_value
|
7
|
+
end
|
8
|
+
|
9
|
+
def step_2
|
10
|
+
@negative = current_value < 0 if encoding?
|
11
|
+
|
12
|
+
encode! { (current_value * 1e5).round }
|
13
|
+
decode! { current_value.to_f/1e5 }
|
14
|
+
end
|
15
|
+
|
16
|
+
def step_3
|
17
|
+
return unless negative
|
18
|
+
encode! { ~(current_value * -1) + 1 }
|
19
|
+
decode! { ~(current_value - 1) * -1 }
|
20
|
+
end
|
21
|
+
|
22
|
+
def step_4
|
23
|
+
encode! { current_value << 1 }
|
24
|
+
decode! { current_value >> 1 }
|
25
|
+
end
|
26
|
+
|
27
|
+
def step_5
|
28
|
+
return unless negative
|
29
|
+
encode! { ~current_value }
|
30
|
+
decode! { ~current_value }
|
31
|
+
end
|
32
|
+
|
33
|
+
def step_6
|
34
|
+
encode! do
|
35
|
+
[].tap do |numbers|
|
36
|
+
while current_value > 0 do
|
37
|
+
numbers.unshift(current_value & 0x1f)
|
38
|
+
@current_value >>= 5
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
decode! do
|
44
|
+
current_value.map {|chunk| "%05b" % chunk }.join.tap do |val|
|
45
|
+
@negative = val[-1, 1] == "1"
|
46
|
+
end.to_i(2)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def step_7
|
51
|
+
encode! { current_value.reverse }
|
52
|
+
decode! { current_value.reverse }
|
53
|
+
end
|
54
|
+
|
55
|
+
def step_8
|
56
|
+
encode! { current_value[0..-2].map {|item| item | 0x20 } << current_value.last }
|
57
|
+
decode! { current_value[0..-2].map {|item| item ^ 0x20 } << current_value.last }
|
58
|
+
end
|
59
|
+
|
60
|
+
def step_10
|
61
|
+
encode! { current_value.map {|value| value + 63 } }
|
62
|
+
decode! { current_value.map {|value| value - 63 } }
|
63
|
+
end
|
64
|
+
|
65
|
+
def step_11
|
66
|
+
encode! { current_value.map(&:chr).join }
|
67
|
+
decode! { current_value.split(//).map {|char| char.unpack("U").first } }
|
68
|
+
end
|
69
|
+
|
70
|
+
def encode!
|
71
|
+
if encoding?
|
72
|
+
@current_value = yield
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def decode!
|
77
|
+
if decoding?
|
78
|
+
@current_value = yield
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def encoding?
|
83
|
+
self.is_a?(Polylines::Encoder)
|
84
|
+
end
|
85
|
+
|
86
|
+
def decoding?
|
87
|
+
self.is_a?(Polylines::Decoder)
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.transform_to_array_of_lat_lng_and_deltas(value)
|
91
|
+
if self == Polylines::Encoder
|
92
|
+
delta_latitude, delta_longitude = 0, 0
|
93
|
+
|
94
|
+
return value.inject([]) do |polyline, (latitude, longitude)|
|
95
|
+
polyline << latitude - delta_latitude
|
96
|
+
polyline << longitude - delta_longitude
|
97
|
+
delta_latitude, delta_longitude = latitude, longitude
|
98
|
+
polyline
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
if self == Polylines::Decoder
|
103
|
+
set = []
|
104
|
+
return value.split(//).inject([]) do |charset, char|
|
105
|
+
set << char
|
106
|
+
|
107
|
+
if ((char.unpack("U").first - 63) & 0x20).zero?
|
108
|
+
charset << set.join
|
109
|
+
set = []
|
110
|
+
end
|
111
|
+
|
112
|
+
charset
|
113
|
+
end.map {|charset| decode(charset) }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Polylines
|
2
|
+
class Decoder < Base
|
3
|
+
def self.decode_polyline(polyline)
|
4
|
+
points_with_deltas = transform_to_array_of_lat_lng_and_deltas(polyline)
|
5
|
+
|
6
|
+
[].tap do |points|
|
7
|
+
points << [points_with_deltas.shift, points_with_deltas.shift]
|
8
|
+
|
9
|
+
while points_with_deltas.any?
|
10
|
+
points << [
|
11
|
+
points.last[0] + points_with_deltas.shift,
|
12
|
+
points.last[1] + points_with_deltas.shift
|
13
|
+
]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.decode(string)
|
19
|
+
self.new(string).tap do |decoding|
|
20
|
+
decoding.step_11
|
21
|
+
decoding.step_10
|
22
|
+
decoding.step_8
|
23
|
+
decoding.step_7
|
24
|
+
decoding.step_6
|
25
|
+
decoding.step_5
|
26
|
+
decoding.step_4
|
27
|
+
decoding.step_3
|
28
|
+
decoding.step_2
|
29
|
+
end.current_value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Polylines
|
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
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.encode(number)
|
9
|
+
self.new(number).tap do |encoding|
|
10
|
+
encoding.step_2
|
11
|
+
encoding.step_3
|
12
|
+
encoding.step_4
|
13
|
+
encoding.step_5
|
14
|
+
encoding.step_6
|
15
|
+
encoding.step_7
|
16
|
+
encoding.step_8
|
17
|
+
encoding.step_10
|
18
|
+
encoding.step_11
|
19
|
+
end.current_value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/polylines.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "polylines/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "polylines"
|
7
|
+
s.version = Polylines::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Josh Clayton"]
|
10
|
+
s.email = ["joshua.clayton@gmail.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{Easily handle Google polylines}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_development_dependency("rspec", "2.4.0")
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Polylines::Decoder, ".decode" do
|
4
|
+
it "decodes a single point" do
|
5
|
+
Polylines::Decoder.decode("`~oia@").should be_within(0.00001).of(-179.9832104)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
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]] }
|
12
|
+
|
13
|
+
it "decodes a polyline correctly" do
|
14
|
+
Polylines::Decoder.decode_polyline(polyline).should == points
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Polylines::Encoder, ".encode" do
|
4
|
+
it "encodes a single point" do
|
5
|
+
Polylines::Encoder.encode(-179.9832104).should == "`~oia@"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
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]] }
|
12
|
+
|
13
|
+
it "encodes points correctly" do
|
14
|
+
Polylines::Encoder.encode_points(points).should == polyline
|
15
|
+
end
|
16
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
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
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Josh Clayton
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-02-19 00:00:00 -05:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
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
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
description:
|
36
|
+
email:
|
37
|
+
- joshua.clayton@gmail.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- .gitignore
|
46
|
+
- Gemfile
|
47
|
+
- Gemfile.lock
|
48
|
+
- Rakefile
|
49
|
+
- lib/polylines.rb
|
50
|
+
- lib/polylines/base.rb
|
51
|
+
- lib/polylines/decoder.rb
|
52
|
+
- lib/polylines/encoder.rb
|
53
|
+
- lib/polylines/version.rb
|
54
|
+
- polylines.gemspec
|
55
|
+
- spec/polylines/decoder_spec.rb
|
56
|
+
- spec/polylines/encoder_spec.rb
|
57
|
+
- spec/spec_helper.rb
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: ""
|
60
|
+
licenses: []
|
61
|
+
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
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:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
requirements: []
|
84
|
+
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 1.3.7
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: Easily handle Google polylines
|
90
|
+
test_files:
|
91
|
+
- spec/polylines/decoder_spec.rb
|
92
|
+
- spec/polylines/encoder_spec.rb
|
93
|
+
- spec/spec_helper.rb
|