nayutaya-googlemaps-polyline 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+
2
+ # googlemaps-polyline
3
+
4
+ googlemaps-polylineは、Google Maps APIのエンコード化ポリラインを取り扱う
5
+ ためのライブラリです。
6
+ ポリラインのエンコード、デコードを行うことができます。
7
+
8
+ ## インストール
9
+
10
+ $ gem install nayutaya-googlemaps-polyline
@@ -0,0 +1,70 @@
1
+
2
+ require "rake/testtask"
3
+ require "lib/googlemaps_polyline/version"
4
+
5
+ PACKAGE_NAME = "nayutaya-googlemaps-polyline"
6
+ PACKAGE_VERSION = GoogleMapsPolyline::VERSION
7
+
8
+ task :default => :test
9
+
10
+ Rake::TestTask.new do |test|
11
+ test.libs << "test"
12
+ test.test_files = Dir.glob("test/**/*_test.rb")
13
+ test.verbose = true
14
+ end
15
+
16
+ namespace :version do
17
+ desc "show current version"
18
+ task :show do
19
+ puts(PACKAGE_VERSION)
20
+ end
21
+
22
+ desc "bump version"
23
+ task :bump do
24
+ cur_version = PACKAGE_VERSION
25
+ next_version = cur_version.succ
26
+ puts("#{cur_version} -> #{next_version}")
27
+
28
+ filename = File.join(File.dirname(__FILE__), "lib", "googlemaps_polyline", "version.rb")
29
+ File.open(filename, "wb") { |file|
30
+ file.puts(%|# coding: utf-8|)
31
+ file.puts(%||)
32
+ file.puts(%|module GoogleMapsPolyline|)
33
+ file.puts(%| VERSION = "#{next_version}"|)
34
+ file.puts(%|end|)
35
+ }
36
+ end
37
+ end
38
+
39
+ namespace :gem do
40
+ desc "generate gemspec"
41
+ task :spec do
42
+ require "erb"
43
+
44
+ src = File.open("#{PACKAGE_NAME}.gemspec.erb", "rb") { |file| file.read }
45
+ erb = ERB.new(src, nil, "-")
46
+
47
+ files = Dir.glob("**/*").
48
+ select { |s| File.file?(s) }.
49
+ reject { |s| /\.gem\z/ =~ s }.
50
+ reject { |s| /\Anbproject\// =~ s }
51
+
52
+ test_files = Dir.glob("test/**").
53
+ select { |s| File.file?(s) }
54
+
55
+ File.open("#{PACKAGE_NAME}.gemspec", "wb") { |file|
56
+ file.write(erb.result(binding))
57
+ }
58
+ end
59
+
60
+ desc "build gem"
61
+ task :build do
62
+ sh "gem build #{PACKAGE_NAME}.gemspec"
63
+ end
64
+
65
+ desc "push gem"
66
+ task :push do
67
+ target = "#{PACKAGE_NAME}-#{PACKAGE_VERSION}.gem"
68
+ sh "gem push #{target}"
69
+ end
70
+ end
@@ -0,0 +1,4 @@
1
+ # coding: utf-8
2
+
3
+ require "googlemaps_polyline/version"
4
+ require "googlemaps_polyline/core"
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+
3
+ require "googlemaps_polyline/encoder"
4
+ require "googlemaps_polyline/decoder"
5
+
6
+ module GoogleMapsPolyline
7
+ def self.encode_points_and_levels(points, levels)
8
+ encoded_points = Encoder.new(StringIO.new).encode_points(points).string
9
+ encoded_levels = Encoder.new(StringIO.new).encode_levels(levels).string
10
+ return encoded_points, encoded_levels
11
+ end
12
+
13
+ def self.encode_polyline_1e5(records)
14
+ points = records.map { |record| record[0..1] }
15
+ levels = records.map { |record| record[2] }
16
+ return self.encode_points_and_levels(points, levels)
17
+ end
18
+
19
+ def self.encode_polyline(records)
20
+ records_1e5 = records.map { |lat, lng, level| [(lat * 1e5).to_i, (lng * 1e5).to_i, level] }
21
+ return self.encode_polyline_1e5(records_1e5)
22
+ end
23
+
24
+ def self.decode_points_and_levels(points, levels)
25
+ decoded_points = Decoder.new(StringIO.new(points)).decode_points
26
+ decoded_levels = Decoder.new(StringIO.new(levels)).decode_levels
27
+ return decoded_points, decoded_levels
28
+ end
29
+
30
+ def self.decode_polyline_1e5(points, levels)
31
+ decoded_points, decoded_levels = self.decode_points_and_levels(points, levels)
32
+ return decoded_points.zip(decoded_levels).map { |a| a.flatten }
33
+ end
34
+
35
+ def self.decode_polyline(points, levels)
36
+ records = self.decode_polyline_1e5(points, levels)
37
+ return records.map { |lat, lng, level| [lat.to_f / 1e5, lng.to_f / 1e5, level] }
38
+ end
39
+ end
@@ -0,0 +1,73 @@
1
+ # coding: utf-8
2
+
3
+ module GoogleMapsPolyline
4
+ class Decoder
5
+ def initialize(io)
6
+ @io = io
7
+ end
8
+
9
+ attr_reader :io
10
+
11
+ def decode_points
12
+ points = []
13
+
14
+ until @io.eof?
15
+ lat = read_point(@io)
16
+ lng = read_point(@io)
17
+
18
+ unless points.empty?
19
+ lat += points.last[0]
20
+ lng += points.last[1]
21
+ end
22
+
23
+ points << [lat, lng]
24
+ end
25
+
26
+ return points
27
+ end
28
+
29
+ def decode_levels
30
+ levels = []
31
+
32
+ until @io.eof?
33
+ levels << read_level(@io)
34
+ end
35
+
36
+ return levels
37
+ end
38
+
39
+ private
40
+
41
+ def read_point(io)
42
+ codes = []
43
+
44
+ while (char = io.read(1))
45
+ code = char.unpack("C")[0] - 63
46
+ codes << (code & ~0x20)
47
+ break if code & 0x20 == 0
48
+ end
49
+
50
+ raise(ArgumentError) unless (1..6).include?(codes.size)
51
+
52
+ bin = codes.map { |c| '%05b' % c }.reverse.join("")
53
+
54
+ negative = (bin.slice!(-1, 1) == "1")
55
+
56
+ num = bin.to_i(2)
57
+ num *= -1 if negative
58
+ num += -1 if negative
59
+
60
+ return num
61
+ end
62
+
63
+ def read_level(io)
64
+ case io.read(1)
65
+ when "?" then return 0
66
+ when "@" then return 1
67
+ when "A" then return 2
68
+ when "B" then return 3
69
+ else raise(ArgumentError)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,64 @@
1
+ # coding: utf-8
2
+
3
+ module GoogleMapsPolyline
4
+ class Encoder
5
+ def initialize(io)
6
+ @io = io
7
+ end
8
+
9
+ attr_reader :io
10
+
11
+ def encode_points(points)
12
+ plat, plng = 0, 0
13
+ points.each { |lat, lng|
14
+ @io.write(pack_point(lat - plat))
15
+ @io.write(pack_point(lng - plng))
16
+ plat, plng = lat, lng
17
+ }
18
+
19
+ return @io
20
+ end
21
+
22
+ def encode_levels(levels)
23
+ levels.each { |level|
24
+ @io.write(pack_level(level))
25
+ }
26
+
27
+ return @io
28
+ end
29
+
30
+ private
31
+
32
+ def pack_point(num)
33
+ negative = (num < 0)
34
+ if negative
35
+ num -= -1
36
+ num *= -1
37
+ end
38
+
39
+ num <<= 1
40
+ num |= 1 if negative
41
+
42
+ codes = []
43
+
44
+ begin
45
+ code = (num & 0b11111) + 63
46
+ num >>= 5
47
+ code += 0x20 if num > 0
48
+ codes << code
49
+ end while num > 0
50
+
51
+ return codes.pack("C*")
52
+ end
53
+
54
+ def pack_level(level)
55
+ case level
56
+ when 0 then return "?"
57
+ when 1 then return "@"
58
+ when 2 then return "A"
59
+ when 3 then return "B"
60
+ else raise(ArgumentError)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,5 @@
1
+ # coding: utf-8
2
+
3
+ module GoogleMapsPolyline
4
+ VERSION = "0.0.1"
5
+ end
@@ -0,0 +1,44 @@
1
+
2
+ Gem::Specification.new do |s|
3
+ s.specification_version = 2
4
+ s.required_rubygems_version = Gem::Requirement.new(">= 0")
5
+ s.required_ruby_version = Gem::Requirement.new(">= 1.8.6")
6
+
7
+ s.name = "nayutaya-googlemaps-polyline"
8
+ s.version = "0.0.1"
9
+ s.date = "2010-03-23"
10
+
11
+ s.authors = ["Yuya Kato"]
12
+ s.email = "yuyakato@gmail.com"
13
+
14
+ s.summary = "Google Maps Polyline Utility"
15
+ s.description = "Polyline Encoder/Decoder for Google Maps API"
16
+ s.homepage = "http://github.com/nayutaya/googlemaps-polyline/"
17
+
18
+ s.rubyforge_project = nil
19
+ s.has_rdoc = false
20
+ s.require_paths = ["lib"]
21
+
22
+ s.files = [
23
+ "lib/googlemaps_polyline/core.rb",
24
+ "lib/googlemaps_polyline/decoder.rb",
25
+ "lib/googlemaps_polyline/encoder.rb",
26
+ "lib/googlemaps_polyline/version.rb",
27
+ "lib/googlemaps_polyline.rb",
28
+ "nayutaya-googlemaps-polyline.gemspec",
29
+ "nayutaya-googlemaps-polyline.gemspec.erb",
30
+ "Rakefile",
31
+ "README.md",
32
+ "test/core_test.rb",
33
+ "test/decoder_test.rb",
34
+ "test/encoder_test.rb",
35
+ "test/test_helper.rb",
36
+ ]
37
+ s.test_files = [
38
+ "test/core_test.rb",
39
+ "test/decoder_test.rb",
40
+ "test/encoder_test.rb",
41
+ "test/test_helper.rb",
42
+ ]
43
+ s.extra_rdoc_files = []
44
+ end
@@ -0,0 +1,33 @@
1
+
2
+ Gem::Specification.new do |s|
3
+ s.specification_version = 2
4
+ s.required_rubygems_version = Gem::Requirement.new(">= 0")
5
+ s.required_ruby_version = Gem::Requirement.new(">= 1.8.6")
6
+
7
+ s.name = <%= PACKAGE_NAME.dump %>
8
+ s.version = <%= PACKAGE_VERSION.dump %>
9
+ s.date = <%= Time.now.strftime("%Y-%m-%d").dump %>
10
+
11
+ s.authors = ["Yuya Kato"]
12
+ s.email = "yuyakato@gmail.com"
13
+
14
+ s.summary = "Google Maps Polyline Utility"
15
+ s.description = "Polyline Encoder/Decoder for Google Maps API"
16
+ s.homepage = "http://github.com/nayutaya/googlemaps-polyline/"
17
+
18
+ s.rubyforge_project = nil
19
+ s.has_rdoc = false
20
+ s.require_paths = ["lib"]
21
+
22
+ s.files = [
23
+ <%- files.each { |path| -%>
24
+ <%= path.dump %>,
25
+ <%- } -%>
26
+ ]
27
+ s.test_files = [
28
+ <%- test_files.each { |path| -%>
29
+ <%= path.dump %>,
30
+ <%- } -%>
31
+ ]
32
+ s.extra_rdoc_files = []
33
+ end
@@ -0,0 +1,76 @@
1
+ # coding: utf-8
2
+
3
+ require "test_helper"
4
+ require "googlemaps_polyline/core"
5
+
6
+ class CoreTest < Test::Unit::TestCase
7
+ def setup
8
+ @mod = GoogleMapsPolyline
9
+ end
10
+
11
+ def test_encode_points_and_levels
12
+ points, levels = @mod.encode_points_and_levels([[0, 0]], [3])
13
+ assert_equal("??", points)
14
+ assert_equal("B", levels)
15
+ end
16
+
17
+ def test_encode_polyline_1e5__1
18
+ points, levels = @mod.encode_polyline_1e5([[0, 0, 3]])
19
+ assert_equal("??", points)
20
+ assert_equal("B", levels)
21
+ end
22
+
23
+ def test_encode_polyline_1e5__1
24
+ points, levels = @mod.encode_polyline_1e5(
25
+ [[1, 2, 3], [2, 4, 2], [3, 8, 1], [4, 16, 0], [5, 32, 3]])
26
+ assert_equal("ACACAGAOA_@", points)
27
+ assert_equal("BA@?B", levels)
28
+ end
29
+
30
+ def test_encode_polyline
31
+ points, levels = @mod.encode_polyline(
32
+ [[34.69025, 135.19501, 3], [34.69363, 135.50192, 3]])
33
+ assert_equal("amvrEygdxXcTe}z@", points)
34
+ assert_equal("BB", levels)
35
+ end
36
+
37
+ def test_decode_points_and_levels
38
+ expected = [[[0, 0]], [3]]
39
+ assert_equal(
40
+ expected,
41
+ @mod.decode_points_and_levels("??", "B"))
42
+ end
43
+
44
+ def test_decode_polyline_1e5__1
45
+ expected = [[0, 0, 3]]
46
+ assert_equal(
47
+ expected,
48
+ @mod.decode_polyline_1e5("??", "B"))
49
+ end
50
+
51
+ def test_decode_polyline_1e5__2
52
+ expected = [[1, 2, 3], [2, 4, 2], [3, 8, 1], [4, 16, 0], [5, 32, 3]]
53
+ assert_equal(
54
+ expected,
55
+ @mod.decode_polyline_1e5("ACACAGAOA_@", "BA@?B"))
56
+ end
57
+
58
+ def test_decode_polyline
59
+ expected = [[34.69025, 135.19501, 3], [34.69363, 135.50192, 3]]
60
+ assert_equal(
61
+ expected,
62
+ @mod.decode_polyline("amvrEygdxXcTe}z@", "BB"))
63
+ end
64
+
65
+ def test_encode_and_decode
66
+ srand(0)
67
+ points1 = 20.times.map { [rand(180 * 1e5) - 90 * 1e5, rand(360 * 1e5) - 180 * 1e5] }.map { |lat, lng| [lat.to_i, lng.to_i] }
68
+ levels1 = [3] + 18.times.map { rand(4) } + [3]
69
+
70
+ points2, levels2 = @mod.encode_points_and_levels(points1, levels1)
71
+ points3, levels3 = @mod.decode_points_and_levels(points2, levels2)
72
+
73
+ assert_equal(points1, points3)
74
+ assert_equal(levels1, levels3)
75
+ end
76
+ end
@@ -0,0 +1,88 @@
1
+ # coding: utf-8
2
+
3
+ require "test_helper"
4
+ require "googlemaps_polyline/decoder"
5
+ require "stringio"
6
+
7
+ class DecoderTest < Test::Unit::TestCase
8
+ def setup
9
+ @klass = GoogleMapsPolyline::Decoder
10
+ end
11
+
12
+ def test_initialize
13
+ io = sio
14
+ encoder = @klass.new(io)
15
+ assert_same(io, encoder.io)
16
+ end
17
+
18
+ def test_decode_points__1
19
+ assert_equal(
20
+ [[0, 0]],
21
+ @klass.new(sio("??")).decode_points)
22
+ end
23
+
24
+ def test_decode_points__2
25
+ assert_equal(
26
+ [[0, 0], [0, 0]],
27
+ @klass.new(sio("????")).decode_points)
28
+ end
29
+
30
+ def test_decode_points__3
31
+ assert_equal(
32
+ [[1, 0]],
33
+ @klass.new(sio("A?")).decode_points)
34
+ end
35
+
36
+ def test_decode_points__4
37
+ assert_equal(
38
+ [[0, 1]],
39
+ @klass.new(sio("?A")).decode_points)
40
+ end
41
+
42
+ def test_decode_points__5
43
+ assert_equal(
44
+ [[1, 1], [1, 1]],
45
+ @klass.new(sio("AA??")).decode_points)
46
+ end
47
+
48
+ def test_decode_points__6
49
+ assert_equal(
50
+ [[1, 2], [2, 4], [3, 8], [4, 16], [5, 32]],
51
+ @klass.new(sio("ACACAGAOA_@")).decode_points)
52
+ end
53
+
54
+ def test_decode_levels
55
+ assert_equal(
56
+ [0, 1, 2, 3],
57
+ @klass.new(sio("?@AB")).decode_levels)
58
+ end
59
+
60
+ def test_read_point
61
+ decoder = @klass.new(sio)
62
+ read_point = proc { |io| decoder.instance_eval { read_point(io) } }
63
+ assert_equal( 0, read_point[sio("?")])
64
+ assert_equal( 1, read_point[sio("A")])
65
+ assert_equal( -1, read_point[sio("@")])
66
+ assert_equal( 12345678, read_point[sio("{sopV")])
67
+ assert_equal(-12345678, read_point[sio("zsopV")])
68
+ assert_equal( 18000000, read_point[sio("_gsia@")])
69
+ assert_equal(-18000000, read_point[sio("~fsia@")])
70
+ assert_raise(ArgumentError) { read_point[sio("")] }
71
+ end
72
+
73
+ def test_read_level
74
+ decoder = @klass.new(sio)
75
+ read_level = proc { |io| decoder.instance_eval { read_level(io) } }
76
+ assert_equal(0, read_level[sio("?")])
77
+ assert_equal(1, read_level[sio("@")])
78
+ assert_equal(2, read_level[sio("A")])
79
+ assert_equal(3, read_level[sio("B")])
80
+ assert_raise(ArgumentError) { read_level[sio("")] }
81
+ end
82
+
83
+ private
84
+
85
+ def sio(string = nil)
86
+ return StringIO.new(string || "")
87
+ end
88
+ end
@@ -0,0 +1,97 @@
1
+ # coding: utf-8
2
+
3
+ require "test_helper"
4
+ require "googlemaps_polyline/encoder"
5
+ require "stringio"
6
+
7
+ class EncoderTest < Test::Unit::TestCase
8
+ def setup
9
+ @klass = GoogleMapsPolyline::Encoder
10
+ @encoder = @klass.new(sio)
11
+ end
12
+
13
+ def test_initialize
14
+ io = sio
15
+ encoder = @klass.new(io)
16
+ assert_same(io, encoder.io)
17
+ end
18
+
19
+ def test_encode_points__1
20
+ assert_equal(
21
+ "",
22
+ @encoder.encode_points([]).string)
23
+ end
24
+
25
+ def test_encode_points__2
26
+ assert_equal(
27
+ "??",
28
+ @encoder.encode_points([[0, 0]]).string)
29
+ end
30
+
31
+ def test_encode_points__3
32
+ assert_equal(
33
+ "????",
34
+ @encoder.encode_points([[0, 0], [0, 0]]).string)
35
+ end
36
+
37
+ def test_encode_points__4
38
+ assert_equal(
39
+ "A?",
40
+ @encoder.encode_points([[1, 0]]).string)
41
+ end
42
+
43
+ def test_encode_points__5
44
+ assert_equal(
45
+ "?A",
46
+ @encoder.encode_points([[0, 1]]).string)
47
+ end
48
+
49
+ def test_encode_points__6
50
+ assert_equal(
51
+ "AA??",
52
+ @encoder.encode_points([[1, 1], [1, 1]]).string)
53
+ end
54
+
55
+ def test_encode_points__7
56
+ assert_equal(
57
+ "ACACAGAOA_@",
58
+ @encoder.encode_points([[1, 2], [2, 4], [3, 8], [4, 16], [5, 32]]).string)
59
+ end
60
+
61
+ def test_encode_levels
62
+ assert_equal(
63
+ "?@AB",
64
+ @encoder.encode_levels([0, 1, 2, 3]).string)
65
+ end
66
+
67
+ def test_pack_point
68
+ pack_point = proc { |num| @encoder.instance_eval { pack_point(num) } }
69
+ assert_equal("?" , pack_point[ 0])
70
+ assert_equal("A" , pack_point[ 1])
71
+ assert_equal("@" , pack_point[ -1])
72
+ assert_equal("{sopV" , pack_point[ 12345678])
73
+ assert_equal("zsopV" , pack_point[-12345678])
74
+ assert_equal("_gsia@", pack_point[ 18000000])
75
+ assert_equal("~fsia@", pack_point[-18000000])
76
+ end
77
+
78
+ def test_pack_level
79
+ pack_level = proc { |level| @encoder.instance_eval { pack_level(level) } }
80
+ assert_equal("?", pack_level[0])
81
+ assert_equal("@", pack_level[1])
82
+ assert_equal("A", pack_level[2])
83
+ assert_equal("B", pack_level[3])
84
+ end
85
+
86
+ def test_pack_level__invalid
87
+ assert_raise(ArgumentError) {
88
+ @encoder.instance_eval { pack_level(-1) }
89
+ }
90
+ end
91
+
92
+ private
93
+
94
+ def sio(string = nil)
95
+ return StringIO.new(string || "")
96
+ end
97
+ end
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
4
+
5
+ require "test/unit"
6
+
7
+ begin
8
+ require "rubygems"
9
+ require "redgreen"
10
+ require "win32console" if /win32/ =~ RUBY_PLATFORM
11
+ rescue LoadError
12
+ # nop
13
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nayutaya-googlemaps-polyline
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Yuya Kato
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-03-23 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Polyline Encoder/Decoder for Google Maps API
17
+ email: yuyakato@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/googlemaps_polyline/core.rb
26
+ - lib/googlemaps_polyline/decoder.rb
27
+ - lib/googlemaps_polyline/encoder.rb
28
+ - lib/googlemaps_polyline/version.rb
29
+ - lib/googlemaps_polyline.rb
30
+ - nayutaya-googlemaps-polyline.gemspec
31
+ - nayutaya-googlemaps-polyline.gemspec.erb
32
+ - Rakefile
33
+ - README.md
34
+ - test/core_test.rb
35
+ - test/decoder_test.rb
36
+ - test/encoder_test.rb
37
+ - test/test_helper.rb
38
+ has_rdoc: true
39
+ homepage: http://github.com/nayutaya/googlemaps-polyline/
40
+ licenses: []
41
+
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 1.8.6
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.3.5
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: Google Maps Polyline Utility
66
+ test_files:
67
+ - test/core_test.rb
68
+ - test/decoder_test.rb
69
+ - test/encoder_test.rb
70
+ - test/test_helper.rb