polylines 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|