google-maps-stitch-bin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/tiler ADDED
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require 'optparse'
6
+ require 'tiler'
7
+
8
+ ###require File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "tiler"))
9
+
10
+ options = {}
11
+
12
+ optparse = OptionParser.new do |opts|
13
+
14
+ opts.banner = "Usage: tiler.rb [options] ..."
15
+
16
+ opts.on('--start_lat LAT', Float, 'Latitude of startpoint (top left)' ) do |start_lat|
17
+ options[:start_lat] = start_lat
18
+ end
19
+
20
+ opts.on('--start_lon LON', Float, 'Longitude of startpoint (top left)' ) do |start_lon|
21
+ options[:start_lon] = start_lon
22
+ end
23
+
24
+ opts.on('--end_lat LAT', Float, 'Latitude of endpoint (bottom right)' ) do |end_lat|
25
+ options[:end_lat] = end_lat
26
+ end
27
+
28
+ opts.on('--end_lon LON', Float, 'Longitude of endoint (bottom right)' ) do |end_lon|
29
+ options[:end_lon] = end_lon
30
+ end
31
+
32
+ opts.on('--zoom ZOOM_LEVEL', Integer, 'Zoom Level in Google maps') do |zoom|
33
+ if (1..18).include?(zoom)
34
+ options[:zoom] = zoom
35
+ else
36
+ raise OptionParser::InvalidArgument
37
+ end
38
+ end
39
+
40
+ opts.on('--source SOURCE', String, '"map" or "sattelite". Default is "sattelite"') do |source|
41
+ if ["map", "sattelite"].include?(source)
42
+ options[:source] = source
43
+ else
44
+ raise OptionParser::InvalidArgument
45
+ end
46
+ end
47
+
48
+ opts.on('--output FILEPATH', String, 'select output file') do |output|
49
+ options[:output] = output
50
+ end
51
+
52
+
53
+ opts.on( '-h', '--help', 'Display this help' ) do
54
+ puts opts
55
+ exit
56
+ end
57
+ end
58
+
59
+
60
+ begin
61
+ optparse.parse!
62
+ mandatory_opts = [:output, :start_lat, :start_lon, :end_lat, :end_lon, :zoom ]
63
+ missing_opts = mandatory_opts.select { |param| options[param].nil? }
64
+
65
+ if !missing_opts.empty?
66
+ puts
67
+ puts "Missing options: #{missing_opts.join(', ')}"
68
+ puts
69
+ puts optparse
70
+ exit
71
+ end
72
+
73
+ rescue OptionParser::InvalidArgument, OptionParser::InvalidOption, OptionParser::MissingArgument => e
74
+ puts
75
+ puts e.inspect
76
+ puts
77
+ puts optparse
78
+ exit
79
+ end
80
+
81
+ tiler = Tiler.new(options)
82
+ tiler.run
data/lib/tiler/tile.rb ADDED
@@ -0,0 +1,37 @@
1
+ require "tempfile"
2
+ class Tile
3
+
4
+ attr_reader :x, :y, :z
5
+
6
+ attr_accessor :file
7
+
8
+ def initialize(args)
9
+ @x = args[:x]
10
+ @y = args[:y]
11
+ @z = args[:z]
12
+ @source = args[:source] || "sattelite"
13
+ end
14
+
15
+ def remote_url
16
+ "https://khms0.google.com/kh/v=143&src=app&x=#{x}&y=#{y}&z=#{z.to_s}"
17
+ end
18
+
19
+ def download
20
+ open(remote_url) do |image|
21
+ file = Tempfile.new("x_#{x}_y_#{y}_z_#{z}")
22
+ file.write(image.read)
23
+ puts "downloaded #{remote_url} to #{file.path}"
24
+ @file = file
25
+ @local_file_name = file.path
26
+ end
27
+ end
28
+
29
+ def local_file_name
30
+ @local_file_name
31
+ end
32
+
33
+ def downloaded?
34
+ !@local_file_name.nil?
35
+ end
36
+
37
+ end
@@ -0,0 +1,81 @@
1
+ class TilesCollection
2
+
3
+ attr_accessor :zoom, :source, :output_file
4
+ attr_reader :start, :end
5
+
6
+ def initialize(args)
7
+ @zoom = args[:zoom]
8
+ @source = args[:source] || "sattelite"
9
+ @start_x = args[:start_x]
10
+ @start_y = args[:start_y]
11
+ @end_x = args[:end_x]
12
+ @end_y = args[:end_y]
13
+ @output = args[:output]
14
+ save_tiles
15
+ end
16
+
17
+ def tile(x,y)
18
+ @tiles[y][x]
19
+ end
20
+
21
+ def rows
22
+ @start_y.upto(@end_y)
23
+ end
24
+
25
+ def columns
26
+ @start_x.upto(@end_x)
27
+ end
28
+
29
+ def all
30
+ @tiles
31
+ end
32
+
33
+ def flatten
34
+ rows.map do |y|
35
+ columns.map do |x|
36
+ tile(x,y)
37
+ end
38
+ end.flatten
39
+ end
40
+
41
+ def save_tile(x,y,tile)
42
+ @tiles[y] = {} unless @tiles[y]
43
+ @tiles[y][x] = tile
44
+ end
45
+
46
+ def save_tiles
47
+ @tiles = {}
48
+ rows.map do |y|
49
+ columns.map do |x|
50
+ save_tile(x,y,Tile.new(x: x, y: y, z: @zoom))
51
+ end
52
+ end
53
+ end
54
+
55
+ def download
56
+ flatten.each{ |tile| tile.download }
57
+ end
58
+
59
+ def cleanup
60
+ flatten.each do |tile|
61
+ tile.file.close
62
+ tile.file.unlink
63
+ end
64
+ end
65
+
66
+ def stitch
67
+ output_data = Magick::ImageList.new
68
+ columns.each do |column|
69
+ col = Magick::ImageList.new
70
+ rows.each do |row|
71
+ begin
72
+ col.push(Magick::Image.read(tile(column,row).local_file_name).first)
73
+ rescue
74
+ debugger
75
+ end
76
+ end
77
+ output_data.push(col.append(true))
78
+ end
79
+ output_data.append(false).write(@output)
80
+ end
81
+ end
data/lib/tiler.rb ADDED
@@ -0,0 +1,102 @@
1
+ require 'simple_mercator_location'
2
+ require 'open-uri'
3
+ require 'tiler/tile'
4
+ require 'tiler/tiles'
5
+ require 'RMagick'
6
+ require 'debugger'
7
+
8
+
9
+ class Tiler
10
+
11
+ extend Forwardable
12
+
13
+ attr_accessor :zoom,
14
+ :source,
15
+ :output,
16
+ :start_x,
17
+ :start_y,
18
+ :end_x,
19
+ :end_y,
20
+ :start_lat,
21
+ :start_lon,
22
+ :end_lat,
23
+ :end_lon
24
+
25
+
26
+ def_delegator :tiles, :download
27
+ def_delegator :tiles, :stitch
28
+ def_delegator :tiles, :cleanup
29
+
30
+
31
+ def initialize(args = {})
32
+ set_rectangle(args)
33
+ args = defaults.merge(args)
34
+
35
+ self.zoom = args[:zoom]
36
+ self.source = args[:source]
37
+ self.output = args[:output]
38
+ end
39
+
40
+ def defaults
41
+ { zoom: 1, source: "sattelite", start_x: 0, start_y: 0, end_x: 0, end_y: 0}
42
+ end
43
+
44
+ def tiles
45
+ @tiles ||= TilesCollection.new(zoom: zoom, source: source, start_x: start_x, start_y: start_y, end_x: end_x, end_y: end_y, output: output)
46
+ end
47
+
48
+ def run
49
+ download
50
+ stitch
51
+ cleanup
52
+ end
53
+
54
+ private
55
+
56
+ def set_rectangle(args)
57
+ if given_lat_lon?(args)
58
+ set_lat_lon(args)
59
+ set_x_y_from_lat_lon(args)
60
+ elsif given_x_y?(args)
61
+ set_x_y(args)
62
+ end
63
+ end
64
+
65
+ def set_x_y_from_lat_lon(args)
66
+ start = SimpleMercatorLocation.new(lat: args[:start_lat], lon: args[:start_lon], zoom: args[:zoom])
67
+ finish = SimpleMercatorLocation.new(lat: args[:end_lat], lon: args[:end_lon], zoom: args[:zoom])
68
+ self.start_x = start.to_tile.first
69
+ self.start_y = start.to_tile.last
70
+ self.end_x = finish.to_tile.first
71
+ self.end_y = finish.to_tile.last
72
+ end
73
+
74
+ def set_x_y(args)
75
+ self.start_x = args[:start_x]
76
+ self.start_y = args[:start_y]
77
+ self.end_x = args[:end_x]
78
+ self.end_y = args[:end_y]
79
+ end
80
+
81
+ def set_lat_lon(args)
82
+ self.start_lat = args[:start_lat]
83
+ self.start_lon = args[:start_lon]
84
+ self.end_lat = args[:end_lat]
85
+ self.end_lon = args[:end_lon]
86
+ end
87
+
88
+ def given_x_y?(args)
89
+ args.has_key?(:start_x) && args[:start_x].is_a?(Integer) &&
90
+ args.has_key?(:start_y) && args[:start_y].is_a?(Integer) &&
91
+ args.has_key?(:end_x) && args[:end_x].is_a?(Integer) &&
92
+ args.has_key?(:end_y) && args[:end_y].is_a?(Integer)
93
+ end
94
+
95
+ def given_lat_lon?(args)
96
+ args.has_key?(:start_lat) && args[:start_lat].is_a?(Float) &&
97
+ args.has_key?(:start_lon) && args[:start_lon].is_a?(Float) &&
98
+ args.has_key?(:end_lat) && args[:end_lat].is_a?(Float) &&
99
+ args.has_key?(:end_lon) && args[:end_lon].is_a?(Float)
100
+ end
101
+
102
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tiler do
4
+
5
+
6
+ describe :initialize do
7
+ context "called without args" do
8
+ it "should not throw an error" do
9
+ expect{Tiler.new}.to_not raise_error
10
+ end
11
+ end
12
+
13
+ context "called with args" do
14
+ it "sets instance variables" do
15
+ t = Tiler.new(zoom: 4)
16
+ expect(t.zoom).to eql 4
17
+ end
18
+ end
19
+ end
20
+
21
+ describe :run do
22
+ let(:tiler) { Tiler.new }
23
+
24
+ before :each do
25
+ tiler.stub :download
26
+ tiler.stub :stitch
27
+ tiler.stub :cleanup
28
+ tiler.stub :create_collection
29
+ end
30
+
31
+ it "calls Tiler#download" do
32
+ expect(tiler).to receive(:download).exactly(1).times
33
+ tiler.run
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ require "rspec"
2
+ require "awesome_print"
3
+ require "debugger"
4
+
5
+ RSpec.configure do |config|
6
+ config.color_enabled = true
7
+ config.filter_run :focus => true
8
+ config.run_all_when_everything_filtered = true
9
+ config.treat_symbols_as_metadata_keys_with_true_values = true
10
+ end
11
+
12
+ def timed(name)
13
+ start = Time.now
14
+ puts "\n[STARTED: #{name}]"
15
+ yield if block_given?
16
+ finish = Time.now
17
+ puts "[FINISHED: #{name} in #{(finish - start) * 1000} milliseconds]"
18
+ end
19
+
20
+ require "tiler"
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: google-maps-stitch-bin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Roman Lehnert
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-12-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.5'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.5'
30
+ description: ''
31
+ email: roman.lehnert@googlemail.com
32
+ executables:
33
+ - tiler
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - lib/tiler/tile.rb
38
+ - lib/tiler/tiles.rb
39
+ - lib/tiler.rb
40
+ - spec/lib/tiler_spec.rb
41
+ - spec/spec_helper.rb
42
+ - bin/tiler
43
+ homepage: ''
44
+ licenses:
45
+ - MIT
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 1.8.25
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: Get images from google maps
68
+ test_files:
69
+ - spec/lib/tiler_spec.rb
70
+ - spec/spec_helper.rb