gpx2png 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,9 +2,8 @@ source "http://rubygems.org"
2
2
 
3
3
  gem 'mini_exiftool'
4
4
  gem 'rmagick'
5
- # removed
6
- #gem 'chunky_png'
7
5
  gem 'gpx_utils'
6
+ gem 'colorize'
8
7
 
9
8
  group :development do
10
9
  gem "rspec"
@@ -3,6 +3,7 @@ GEM
3
3
  specs:
4
4
  addressable (2.3.5)
5
5
  builder (3.2.2)
6
+ colorize (0.6.0)
6
7
  diff-lcs (1.2.5)
7
8
  docile (1.1.1)
8
9
  faraday (0.8.8)
@@ -69,6 +70,7 @@ PLATFORMS
69
70
 
70
71
  DEPENDENCIES
71
72
  bundler
73
+ colorize
72
74
  gpx_utils
73
75
  jeweler
74
76
  mini_exiftool
data/README.md CHANGED
@@ -1,75 +1,11 @@
1
- gpx2exif
1
+ gpx2png
2
2
  =======
3
3
 
4
- Geotagging
5
- ----------
6
-
7
- Geotag your photos using stored GPX files. At this moment it supports only Garmin eTrex devices.
8
-
9
-
10
- Disclaimer
11
- ----------
12
-
13
- This gem add one executable which overwrite JPG files. BACKUP IS NEEDED!
14
-
15
-
16
- How to use it
17
- -------------
18
-
19
- 1. gem install gpx2exif
20
-
21
- 2. Go to path where you have JPG/JPEG photos (case insensitive) and GPX files.
22
-
23
- 3. From 0.0.1 there is 'simulation command'. Type 'geotag_simulate' and enter.
24
-
25
- 4. WARNING! it will overwrite all your photos so MAKE A BACKUP!
26
-
27
- 5. Type 'geotag_all_images' and press enter key.
28
-
29
- 6. See a nice piece of output and now you have geotagged photos :)
30
-
31
-
32
- If something is not working send me e-mail and I'll fix it.
33
-
34
-
35
- Create waypoint files
36
- ---------------------
37
-
38
- You can prepare your own list of waypoints and then store into eTrex using GPX file. At this moment there is
39
- only possible to convert data from YAML file to GPX. It is also possible to integrate with other (web)apps.
40
-
41
- How to use it
42
- -------------
43
-
44
- 1. Check samples/sample_yaml_pois.yml as a template.
45
-
46
- 2. Modify it, add yours POIs.
47
-
48
- 3. Run command
49
-
50
- generate_garmin_waypoints -y input_file.yml > output.gpx
51
-
52
- 4. You can check inter-POI distances using
53
-
54
- generate_garmin_waypoints -y input_file.yml -C
55
-
56
- Distance conflict does not mean something is wrong. POIs can be close to each other so it
57
- is a good idea to have your brain turned on ;)
58
-
59
- 5. You can change inter-POI distances using 'latlon something' distance for distance checking
60
- explained line before.
61
-
62
- generate_garmin_waypoints -y samples/sample_yaml_pois.yml -C -t 1
63
-
64
- 6. You can specify output file if you don't like using >> 'file.gpx'.
65
-
66
- generate_garmin_waypoints -y samples/sample_yaml_pois.yml -o file.gpx
67
-
68
-
69
4
  Render track with OpenStreetMap
70
5
  ---------------------
71
6
 
72
- You can "convert" your tracks to images using this command.
7
+ You can "convert" your tracks to map images using this command.
8
+
73
9
 
74
10
  How to use it
75
11
  -------------
@@ -92,13 +28,17 @@ How to use it
92
28
 
93
29
  gpx2png -g spec/fixtures/sample.gpx -z 11 -o map.png
94
30
 
95
- 4. Adding -u forces using [UMP tiles](http://ump.waw.pl/) .
31
+ 4. You can change map provider:
32
+
33
+ * OpenStreetMap - defualt
34
+ * UMP - add -u to use [UMP tiles](http://ump.waw.pl/)
35
+ * Cycle - add -u to use [UMP tiles](http://ump.waw.pl/)
96
36
 
97
37
 
98
- Contributing to gpx2xif
38
+ Contributing to gpx2png
99
39
  -------------------------------
100
40
 
101
- [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=bobik314&url=https://github.com/akwiatkowski/gpx2xif&title=gpx2xif&language=en_GB&tags=github&category=software)
41
+ [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=bobik314&url=https://github.com/akwiatkowski/gpx2png&title=gpx2png&language=en_GB&tags=github&category=software)
102
42
 
103
43
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
104
44
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
@@ -112,6 +52,6 @@ Contributing to gpx2xif
112
52
  Copyright
113
53
  ---------
114
54
 
115
- Copyright (c) 2012 Aleksander Kwiatkowski. See LICENSE.txt for
55
+ Copyright (c) 2012-2014 Aleksander Kwiatkowski. See LICENSE.txt for
116
56
  further details.
117
57
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
@@ -6,7 +6,7 @@ require 'gpx2png/osm'
6
6
  require 'gpx2png/ump'
7
7
  require 'optparse'
8
8
 
9
- options = { }
9
+ options = {}
10
10
  OptionParser.new do |opts|
11
11
  opts.banner = "Usage: gpx2png [options]"
12
12
 
@@ -22,8 +22,8 @@ OptionParser.new do |opts|
22
22
  opts.on("-o", "--output FILE", "Output image file") do |v|
23
23
  options[:output_file] = v
24
24
  end
25
- opts.on("-u", "--ump", "Use UMP tiles rather than OSM") do
26
- options[:ump] = true
25
+ opts.on("-k", "--klass CLASS", "Use different map provider (osm, ump, cycle, transport, outdoors, landscape)") do |v|
26
+ options[:klass] = v
27
27
  end
28
28
  end.parse!
29
29
 
@@ -40,15 +40,26 @@ if options[:zoom].nil? and options[:size].nil?
40
40
  @fail = true
41
41
  end
42
42
 
43
+ klass = case options[:klass].to_s
44
+ when "ump" then
45
+ Gpx2png::Ump
46
+ when "cycle" then
47
+ Gpx2png::OpenCycle
48
+ when "transport" then
49
+ Gpx2png::Transport
50
+ when "outdoors" then
51
+ Gpx2png::Outdoors
52
+ when "landscape" then
53
+ Gpx2png::Landscape
54
+ else
55
+ Gpx2png::Osm
56
+ end
57
+
43
58
  unless @fail
44
59
  g = GpxUtils::TrackImporter.new
45
60
  g.add_file(options[:gpx])
46
61
 
47
- if options[:ump]
48
- e = Gpx2png::Ump.new
49
- else
50
- e = Gpx2png::Osm.new
51
- end
62
+ e = klass.new
52
63
  e.coords = g.coords
53
64
 
54
65
  if options[:size]
@@ -58,7 +69,7 @@ unless @fail
58
69
  else
59
70
  # constant zoom
60
71
  e.zoom = options[:zoom].to_i
61
- e.renderer_options = {crop_enabled: true}
72
+ e.renderer_options = { crop_enabled: true }
62
73
  end
63
74
 
64
75
  e.save(options[:output_file])
@@ -3,3 +3,7 @@ $:.unshift(File.dirname(__FILE__))
3
3
  require 'gpx_utils'
4
4
  require 'gpx2png/osm'
5
5
  require 'gpx2png/ump'
6
+ require 'gpx2png/opencycle'
7
+ require 'gpx2png/transport'
8
+ require 'gpx2png/landscape'
9
+ require 'gpx2png/outdoors'
@@ -1,29 +1,125 @@
1
- require 'rubygems'
2
-
3
- $:.unshift(File.dirname(__FILE__))
1
+ require 'colorize'
2
+ require 'logger'
3
+ require 'gpx2png/layer'
4
+ require 'gpx2png/calculations/base_class_methods'
5
+ require 'gpx2png/calculations/base_instance_methods'
4
6
 
5
7
  module Gpx2png
6
8
  class Base
9
+ extend Calculations::BaseClassMethods
10
+ include Calculations::BaseInstanceMethods
7
11
 
8
12
  def initialize
9
- @coords = Array.new
13
+ @layers = Array.new
14
+ _layer = Layer.new
15
+ _layer.parent = self
16
+ @layers << _layer
17
+ @single_layer = true
18
+
10
19
  @zoom = 9
11
- @verbose = true
20
+
21
+ self.class.logger.debug("Init, default zoom #{@zoom.to_s.green}")
22
+ end
23
+
24
+ def add_layer(_layer_options)
25
+ if @single_layer
26
+ self.class.logger.debug("Created #{"first".to_s.red} layer")
27
+ # turn off single layer version
28
+ @single_layer = false
29
+ # set layer options for first layer and return it
30
+ _layer = @layers.first
31
+ _layer.options = _layer_options
32
+ return _layer
33
+ else
34
+ # create new layer with options, add to list and return
35
+ _layer = Layer.new
36
+ _layer.parent = self
37
+ _layer.options = _layer_options
38
+ @layers << _layer
39
+ self.class.logger.debug("Created layer, count: #{@layers.size.to_s.red}")
40
+ return _layer
41
+ end
12
42
  end
13
43
 
14
44
  def add(lat, lon)
15
- @coords << { lat: lat, lon: lon }
45
+ if @single_layer
46
+ # add coord to first layer
47
+ _layer = @layers.first
48
+ _layer.add(lat, lon)
49
+ else
50
+ # I'm afraid Dave I can't do that
51
+ self.class.logger.fatal("After you've added first layer you can use coords only from layers")
52
+ raise StandardError
53
+ end
54
+ end
55
+
56
+ def coords=(_coords)
57
+ if @single_layer
58
+ # add coord to first layer
59
+ _layer = @layers.first
60
+ _layer.coords = _coords
61
+ else
62
+ # I'm afraid Dave I can't do that
63
+ self.class.fatal("After you've added first layer you can use coords only from layers")
64
+ raise StandardError
65
+ end
66
+ end
67
+
68
+ def color(_color)
69
+ if @single_layer
70
+ # add coord to first layer
71
+ _layer = @layers.first
72
+ _layer.color = _color
73
+ else
74
+ # I'm afraid Dave I can't do that
75
+ self.class.fatal("After you've added first layer you have to use layers")
76
+ raise StandardError
77
+ end
78
+ end
79
+
80
+ # Create image with fixed size
81
+ def fixed_size(_width, _height)
82
+ @fixed_width = _width
83
+ @fixed_height = _height
84
+ self.class.logger.debug("Map image fixed dimension set #{@fixed_width.to_s.red} x #{@fixed_height.to_s.red}")
85
+ true
16
86
  end
17
87
 
18
- attr_accessor :zoom, :color, :coords
88
+ def zoom=(_zoom)
89
+ self.class.logger.debug("Map zoom set #{_zoom.to_s.red}")
90
+ @zoom = _zoom
91
+ end
92
+
93
+ def zoom
94
+ @zoom
95
+ end
96
+
97
+ attr_accessor :layers
98
+
99
+ # Simulate download of tiles
100
+ attr_accessor :simulate_download
101
+
102
+ def self.simulate_download=(b)
103
+ logger.debug("Simulate tiles download for class #{self.to_s.blue}") if b
104
+ @@simulate_download = b
105
+ end
106
+
107
+ def simulate_download?
108
+ return true if true == self.simulate_download or (defined? @@simulate_download and true == @@simulate_download)
109
+ end
110
+
111
+ def destroy
112
+ @r.destroy
113
+ self.class.logger.debug "Image destroyed"
114
+ end
19
115
 
20
- # Some math stuff
21
- def self.rad2deg(rad)
22
- return rad * 180.0 / Math::PI
116
+ def self.logger=(_logger)
117
+ @@logger = _logger
23
118
  end
24
119
 
25
- def self.deg2rad(deg)
26
- return deg * Math::PI / 180.0
120
+ def self.logger
121
+ @@logger = Logger.new(STDOUT) unless defined? @@logger
122
+ return @@logger
27
123
  end
28
124
 
29
125
  end
@@ -0,0 +1,15 @@
1
+ module Gpx2png
2
+ module Calculations
3
+ module BaseClassMethods
4
+ # Some math stuff
5
+ def rad2deg(rad)
6
+ return rad * 180.0 / Math::PI
7
+ end
8
+
9
+ def deg2rad(deg)
10
+ return deg * Math::PI / 180.0
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,32 @@
1
+ module Gpx2png
2
+ module Calculations
3
+ module BaseInstanceMethods
4
+
5
+ def calculate_minmax_latlon
6
+ @layers.each do |l|
7
+ enlarge_border_coords(l)
8
+ end
9
+ # when no coords specified
10
+ @lat_min ||= -0.01
11
+ @lat_max ||= 0.01
12
+ @lon_min ||= -0.01
13
+ @lon_max ||= 0.01
14
+ end
15
+
16
+ def enlarge_border_coords(layer)
17
+ _lat_min = layer.coords.collect { |c| c[:lat] }.min
18
+ _lat_max = layer.coords.collect { |c| c[:lat] }.max
19
+ _lon_min = layer.coords.collect { |c| c[:lon] }.min
20
+ _lon_max = layer.coords.collect { |c| c[:lon] }.max
21
+
22
+ @lat_min = _lat_min if @lat_min.nil? or _lat_min < @lat_min
23
+ @lat_max = _lat_max if @lat_max.nil? or _lat_max > @lat_max
24
+ @lon_min = _lon_min if @lon_min.nil? or _lon_min < @lon_min
25
+ @lon_max = _lon_max if @lon_max.nil? or _lon_max > @lon_max
26
+
27
+ self.class.logger.debug("Border coords #{@lat_min.to_s.green},#{@lon_min.to_s.green} - #{@lat_max.to_s.green},#{@lon_max.to_s.green}")
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,99 @@
1
+ module Gpx2png
2
+ module Calculations
3
+ module OsmClassMethods
4
+
5
+ TILE_WIDTH = 256
6
+ TILE_HEIGHT = 256
7
+
8
+ # http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#X_and_Y
9
+ # Convert latlon deg to OSM tile coords
10
+ def convert(zoom, coord)
11
+ lat_deg, lon_deg = coord
12
+ lat_rad = deg2rad(lat_deg)
13
+ x = (((lon_deg + 180) / 360) * (2 ** zoom)).floor
14
+ y = ((1 - Math.log(Math.tan(lat_rad) + 1 / Math.cos(lat_rad)) / Math::PI) /2 * (2 ** zoom)).floor
15
+
16
+ logger.debug "Converted #{lat_deg.to_s.green},#{lat_deg.to_s.green} to [#{x.to_s.red},#{y.to_s.red}]"
17
+
18
+ return [x, y]
19
+ end
20
+
21
+ # Convert OSM tile coords to latlon deg in top-left corner
22
+ def reverse_convert(zoom, coord)
23
+ x, y = coord
24
+ n = 2 ** zoom
25
+ lon_deg = x.to_f / n.to_f * 360.0 - 180.0
26
+ lat_deg = rad2deg(Math.atan(Math.sinh(Math::PI * (1.to_f - 2.to_f * y.to_f / n.to_f))))
27
+
28
+ logger.debug "Reverse converted [#{x.to_s.red},#{y.to_s.red}] to #{lat_deg.to_s.green},#{lat_deg.to_s.green}"
29
+
30
+ return [lat_deg, lon_deg]
31
+ end
32
+
33
+ # Lazy calc proper zoom for drawing
34
+ def calc_zoom(lat_min, lat_max, lon_min, lon_max, width, height)
35
+ # because I'm lazy! :] and math is not my best side
36
+
37
+ last_zoom = 2
38
+ (5..18).each do |zoom|
39
+ # calculate drawing tile size and pixel size
40
+ tile_min = point_on_absolute_image(zoom, [lat_min, lon_min])
41
+ tile_max = point_on_absolute_image(zoom, [lat_max, lon_max])
42
+ current_pixel_x_distance = tile_max[0] - tile_min[0]
43
+ current_pixel_y_distance = tile_min[1] - tile_max[1]
44
+ if current_pixel_x_distance > width or current_pixel_y_distance > height
45
+ logger.debug "Calculated best zoom #{last_zoom.to_s.red}"
46
+ return last_zoom
47
+ end
48
+ last_zoom = zoom
49
+ end
50
+ return 18
51
+ end
52
+
53
+ # Convert latlon deg coords to image point (x,y) and OSM tile coord
54
+ # return where you should put point on tile
55
+ def point_on_image(zoom, geo_coord)
56
+ osm_tile_coord = convert(zoom, geo_coord)
57
+ top_left_corner = reverse_convert(zoom, osm_tile_coord)
58
+ bottom_right_corner = reverse_convert(zoom, [
59
+ osm_tile_coord[0] + 1, osm_tile_coord[1] + 1
60
+ ])
61
+
62
+ # some line math: y = ax + b
63
+
64
+ x_geo = geo_coord[1]
65
+ # offset
66
+ x_offset = x_geo - top_left_corner[1]
67
+ # scale
68
+ x_distance = (bottom_right_corner[1] - top_left_corner[1])
69
+ x = (TILE_WIDTH.to_f * (x_offset / x_distance)).round
70
+
71
+ y_geo = geo_coord[0]
72
+ # offset
73
+ y_offset = y_geo - top_left_corner[0]
74
+ # scale
75
+ y_distance = (bottom_right_corner[0] - top_left_corner[0])
76
+ y = (TILE_HEIGHT.to_f * (y_offset / y_distance)).round
77
+
78
+ logger.debug("Point on image: zoom #{zoom.to_s.green}, coord #{geo_coord[0].to_s.green},#{geo_coord[1].to_s.green} => [#{x.to_s.red}, #{y.to_s.red}]")
79
+
80
+ return { osm_title_coord: osm_tile_coord, pixel_offset: [x, y] }
81
+ end
82
+
83
+ # Useful for calculating distance on output image
84
+ # It is not position on output image because we don't know tile coords
85
+ # For upper-left tile
86
+ def point_on_absolute_image(zoom, geo_coord)
87
+ _p = point_on_image(zoom, geo_coord)
88
+ _x = _p[:osm_title_coord][0] * TILE_WIDTH + _p[:pixel_offset][0]
89
+ _y = _p[:osm_title_coord][1] * TILE_WIDTH + _p[:pixel_offset][1]
90
+
91
+ logger.debug("Point on abs. image: zoom #{zoom.to_s.green}, coord #{geo_coord[0].to_s.green},#{geo_coord[1].to_s.green} => [#{_x.to_s.red}, #{_y.to_s.red}]")
92
+
93
+ return [_x, _y]
94
+ end
95
+
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,197 @@
1
+ require 'gpx2png/calculations/osm_class_methods'
2
+
3
+ module Gpx2png
4
+ module Calculations
5
+ module OsmInstanceMethods
6
+
7
+ TILE_WIDTH = OsmClassMethods::TILE_WIDTH
8
+ TILE_HEIGHT = OsmClassMethods::TILE_WIDTH
9
+
10
+ attr_reader :lat_min, :lat_max, :lon_min, :lon_max
11
+ attr_reader :tile_x_distance, :tile_y_distance
12
+ # points for cropping
13
+ attr_reader :bitmap_point_x_max, :bitmap_point_x_min, :bitmap_point_y_max, :bitmap_point_y_min
14
+
15
+ def initial_calculations
16
+ calculate_minmax_latlon
17
+
18
+ # auto zoom must be here
19
+ # drawing must fit into fixed resolution
20
+ # map must be bigger than fixed resolution
21
+ if @fixed_width and @fixed_height
22
+ @new_zoom = self.class.calc_zoom(
23
+ @lat_min, @lat_max,
24
+ @lon_min, @lon_max,
25
+ @fixed_width, @fixed_height
26
+ )
27
+ self.class.logger.debug "Calculated new zoom #{@new_zoom.to_s.red} (was #{@zoom.to_s.red})"
28
+ @zoom = @new_zoom
29
+ end
30
+
31
+ @border_tiles = [
32
+ self.class.convert(@zoom, [@lat_min, @lon_min]),
33
+ self.class.convert(@zoom, [@lat_max, @lon_max])
34
+ ]
35
+
36
+ @tile_x_range = (@border_tiles[0][0])..(@border_tiles[1][0])
37
+ @tile_y_range = (@border_tiles[1][1])..(@border_tiles[0][1])
38
+
39
+ # enlarging ranges to fill up map area
40
+ # both sizes are enlarged
41
+ if @fixed_width and @fixed_height
42
+ x_axis_expand_count = ((@fixed_width - (1 + @tile_x_range.max - @tile_x_range.min) * TILE_WIDTH).to_f / (TILE_WIDTH.to_f * 2.0)).ceil
43
+ y_axis_expand_count = ((@fixed_height - (1 + @tile_y_range.max - @tile_y_range.min) * TILE_HEIGHT).to_f / (TILE_HEIGHT.to_f * 2.0)).ceil
44
+ self.class.logger.debug "Expanding #{"X".to_s.blue} tiles from both sides #{x_axis_expand_count.to_s.green}"
45
+ self.class.logger.debug "Expanding #{"Y".to_s.blue} tiles from both sides #{y_axis_expand_count.to_s.green}"
46
+ @tile_x_range = ((@tile_x_range.min - x_axis_expand_count)..(@tile_x_range.max + x_axis_expand_count))
47
+ @tile_y_range = ((@tile_y_range.min - y_axis_expand_count)..(@tile_y_range.max + y_axis_expand_count))
48
+ end
49
+
50
+ # new/full image size
51
+ @full_image_x = (1 + @tile_x_range.max - @tile_x_range.min) * TILE_WIDTH
52
+ @full_image_y = (1 + @tile_y_range.max - @tile_y_range.min) * TILE_HEIGHT
53
+ @r.x = @full_image_x
54
+ @r.y = @full_image_y
55
+
56
+ if @fixed_width and @fixed_height
57
+ calculate_for_crop_with_auto_zoom
58
+ else
59
+ calculate_for_crop
60
+ end
61
+ end
62
+
63
+ # Calculate zoom level
64
+ def auto_zoom_for(x = 0, y = 0)
65
+ # TODO
66
+ end
67
+
68
+ # Calculate some numbers for cropping operation
69
+ def calculate_for_crop
70
+ point_min = self.class.point_on_image(@zoom, [@lat_min, @lon_min])
71
+ point_max = self.class.point_on_image(@zoom, [@lat_max, @lon_max])
72
+ @bitmap_point_x_min = (point_min[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_min[:pixel_offset][0]
73
+ @bitmap_point_x_max = (point_max[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_max[:pixel_offset][0]
74
+ @bitmap_point_y_max = (point_min[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_min[:pixel_offset][1]
75
+ @bitmap_point_y_min = (point_max[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_max[:pixel_offset][1]
76
+
77
+ @r.set_crop(@bitmap_point_x_min, @bitmap_point_x_max, @bitmap_point_y_min, @bitmap_point_y_max)
78
+ end
79
+
80
+ # Calculate some numbers for cropping operation with autozoom
81
+ def calculate_for_crop_with_auto_zoom
82
+ point_min = self.class.point_on_image(@zoom, [@lat_min, @lon_min])
83
+ point_max = self.class.point_on_image(@zoom, [@lat_max, @lon_max])
84
+ @bitmap_point_x_min = (point_min[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_min[:pixel_offset][0]
85
+ @bitmap_point_x_max = (point_max[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_max[:pixel_offset][0]
86
+ @bitmap_point_y_max = (point_min[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_min[:pixel_offset][1]
87
+ @bitmap_point_y_min = (point_max[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_max[:pixel_offset][1]
88
+
89
+ bitmap_x_center = (@bitmap_point_x_min + @bitmap_point_x_max) / 2
90
+ bitmap_y_center = (@bitmap_point_y_min + @bitmap_point_y_max) / 2
91
+
92
+ @r.set_crop_fixed(bitmap_x_center, bitmap_y_center, @fixed_width, @fixed_height)
93
+ end
94
+
95
+ def expand_map
96
+ # TODO expand min and max ranges
97
+ end
98
+
99
+ # Do everything
100
+ def download_and_join_tiles
101
+ self.class.logger.info "Output image dimension #{@full_image_x.to_s.red} x #{@full_image_y.to_s.red}"
102
+ @r.new_image
103
+
104
+ # {:x, :y, :blob}
105
+ @images = Array.new
106
+
107
+
108
+ @tile_x_range.each do |x|
109
+ @tile_y_range.each do |y|
110
+ url = self.class.url(@zoom, [x, y])
111
+
112
+ # blob time
113
+ unless simulate_download?
114
+ uri = URI.parse(url)
115
+ response = Net::HTTP.get_response(uri)
116
+ blob = response.body
117
+ else
118
+ blob = @r.blank_tile(TILE_WIDTH, TILE_HEIGHT, x+y)
119
+ end
120
+
121
+ @r.add_tile(
122
+ blob,
123
+ (x - @tile_x_range.min) * TILE_WIDTH,
124
+ (y - @tile_y_range.min) * TILE_HEIGHT
125
+ )
126
+
127
+ @images << {
128
+ url: url,
129
+ x: x,
130
+ y: y
131
+ }
132
+
133
+ self.class.logger.info "processed #{(x - @tile_x_range.min).to_s.red} x #{(y - @tile_y_range.min).to_s.red} (max #{(@tile_x_range.max - @tile_x_range.min).to_s.yellow} x #{(@tile_y_range.max - @tile_y_range.min).to_s.yellow})"
134
+ end
135
+ end
136
+
137
+ # sweet, image is joined
138
+
139
+ # min/max points used for cropping
140
+ @bitmap_point_x_max = (@full_image_x / 2).round
141
+ @bitmap_point_x_min = (@full_image_x / 2).round
142
+ @bitmap_point_y_max = (@full_image_y / 2).round
143
+ @bitmap_point_y_min = (@full_image_y / 2).round
144
+
145
+ # add all coords to the map
146
+ _coords_count = 0
147
+ @layers.each do |layer|
148
+ _coords = layer.coords
149
+ _coords_count += _coords.size
150
+ (1..._coords.size).each do |i|
151
+
152
+ lat_from = _coords[i-1][:lat]
153
+ lon_from = _coords[i-1][:lon]
154
+
155
+ lat_to = _coords[i][:lat]
156
+ lon_to = _coords[i][:lon]
157
+
158
+ point_from = self.class.point_on_image(@zoom, [lat_from, lon_from])
159
+ point_to = self.class.point_on_image(@zoom, [lat_to, lon_to])
160
+ # { osm_title_coord: osm_tile_coord, pixel_offset: [x, y] }
161
+
162
+ # first point
163
+ bitmap_xa = (point_from[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_from[:pixel_offset][0]
164
+ bitmap_ya = (point_from[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_from[:pixel_offset][1]
165
+ bitmap_xb = (point_to[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_to[:pixel_offset][0]
166
+ bitmap_yb = (point_to[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_to[:pixel_offset][1]
167
+
168
+ @r.line(
169
+ bitmap_xa, bitmap_ya,
170
+ bitmap_xb, bitmap_yb
171
+ )
172
+ end
173
+ end
174
+ self.class.logger.info "Layers - #{@layers.size.to_s.red} with #{_coords_count.to_s.yellow} coords have been added to image"
175
+
176
+ # add points
177
+ @markers.each do |point|
178
+ lat = point[:lat]
179
+ lon = point[:lon]
180
+
181
+ p = self.class.point_on_image(@zoom, [lat, lon])
182
+ bitmap_x = (p[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + p[:pixel_offset][0]
183
+ bitmap_y = (p[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + p[:pixel_offset][1]
184
+
185
+ point[:x] = bitmap_x
186
+ point[:y] = bitmap_y
187
+
188
+ @r.markers << point
189
+ end
190
+ self.class.logger.info "Markers - #{@markers.size.to_s.red} have been added to image"
191
+
192
+ end
193
+
194
+
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'gpx2png/osm'
3
+
4
+ module Gpx2png
5
+ class Landscape < Osm
6
+
7
+ # Convert OSM/UMP tile coords to url
8
+ def self.url(zoom, coord, server = '3.')
9
+ x, y = coord
10
+ url = "http://tile.thunderforest.com/landscape/#{zoom}/#{x}/#{y}.png"
11
+ return url
12
+ end
13
+
14
+ def self.licence_string
15
+ "All maps copyright Thunderforest.com and OpenStreetMap contributors"
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,36 @@
1
+ module Gpx2png
2
+ class Layer
3
+ def initialize
4
+ @coords = Array.new
5
+ @options = Hash.new
6
+ end
7
+
8
+ attr_accessor :options, :coords, :parent
9
+
10
+ def coords=(_coords)
11
+ logger.debug("Set #{_coords.size.to_s.red} for layer #{self.index.to_s.green}")
12
+ @coords = _coords
13
+ end
14
+
15
+ def coords
16
+ @coords
17
+ end
18
+
19
+ # Number of this layer
20
+ def index
21
+ if @parent
22
+ return parent.layers.index(self)
23
+ end
24
+ return nil
25
+ end
26
+
27
+ def logger
28
+ @parent.class.logger
29
+ end
30
+
31
+ def add(lat, lon)
32
+ logger.debug("Added coord #{lat.to_s.red},#{lon.to_s.red} for layer #{self.index.to_s.green}, count #{(@coords.size + 1).to_s.blue}")
33
+ @coords << { lat: lat, lon: lon }
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'gpx2png/osm'
3
+
4
+ module Gpx2png
5
+ class OpenCycle < Osm
6
+
7
+ # Convert OSM/UMP tile coords to url
8
+ def self.url(zoom, coord, server = '3.')
9
+ x, y = coord
10
+ url = "http://tile.thunderforest.com/cycle/#{zoom}/#{x}/#{y}.png"
11
+ return url
12
+ end
13
+
14
+ def self.licence_string
15
+ "All maps copyright Thunderforest.com and OpenStreetMap contributors"
16
+ end
17
+
18
+ end
19
+ end
@@ -1,8 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'gpx2png/osm_base'
3
3
 
4
- $:.unshift(File.dirname(__FILE__))
5
-
6
4
  module Gpx2png
7
5
  class Osm < OsmBase
8
6
 
@@ -1,36 +1,16 @@
1
- require 'rubygems'
2
1
  require 'gpx2png/base'
3
2
  require 'net/http'
4
3
  require "uri"
5
-
6
- $:.unshift(File.dirname(__FILE__))
4
+ require 'gpx2png/calculations/osm_class_methods'
5
+ require 'gpx2png/calculations/osm_instance_methods'
7
6
 
8
7
  module Gpx2png
9
8
  class OsmBase < Base
10
- TILE_WIDTH = 256
11
- TILE_HEIGHT = 256
12
-
13
- # if true it will not download tiles
14
- attr_accessor :simulate_download
9
+ extend Calculations::OsmClassMethods
10
+ include Calculations::OsmInstanceMethods
15
11
 
16
- def self.simulate_download=(b)
17
- @@simulate_download = b
18
- end
19
-
20
- def simulate_download?
21
- return true if true == self.simulate_download or (defined? @@simulate_download and true == @@simulate_download)
22
- end
23
-
24
- # http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#X_and_Y
25
- # Convert latlon deg to OSM tile coords
26
- def self.convert(zoom, coord)
27
- lat_deg, lon_deg = coord
28
- lat_rad = deg2rad(lat_deg)
29
- x = (((lon_deg + 180) / 360) * (2 ** zoom)).floor
30
- y = ((1 - Math.log(Math.tan(lat_rad) + 1 / Math.cos(lat_rad)) / Math::PI) /2 * (2 ** zoom)).floor
31
-
32
- return [x, y]
33
- end
12
+ TILE_WIDTH = Calculations::OsmClassMethods::TILE_WIDTH
13
+ TILE_HEIGHT = Calculations::OsmClassMethods::TILE_HEIGHT
34
14
 
35
15
  # Convert latlon deg to OSM tile url
36
16
  # TODO add algorithm to choose from diff. servers
@@ -46,265 +26,11 @@ module Gpx2png
46
26
  return url
47
27
  end
48
28
 
49
- # Convert OSM tile coords to latlon deg in top-left corner
50
- def self.reverse_convert(zoom, coord)
51
- x, y = coord
52
- n = 2 ** zoom
53
- lon_deg = x.to_f / n.to_f * 360.0 - 180.0
54
- lat_deg = rad2deg(Math.atan(Math.sinh(Math::PI * (1.to_f - 2.to_f * y.to_f / n.to_f))))
55
- return [lat_deg, lon_deg]
56
- end
57
-
58
- # Lazy calc proper zoom for drawing
59
- def self.calc_zoom(lat_min, lat_max, lon_min, lon_max, width, height)
60
- # because I'm lazy! :] and math is not my best side
61
-
62
- last_zoom = 2
63
- (5..18).each do |zoom|
64
- # calculate drawing tile size and pixel size
65
- tile_min = point_on_absolute_image(zoom, [lat_min, lon_min])
66
- tile_max = point_on_absolute_image(zoom, [lat_max, lon_max])
67
- current_pixel_x_distance = tile_max[0] - tile_min[0]
68
- current_pixel_y_distance = tile_min[1] - tile_max[1]
69
- if current_pixel_x_distance > width or current_pixel_y_distance > height
70
- return last_zoom
71
- end
72
- last_zoom = zoom
73
- end
74
- return 18
75
- end
76
-
77
- # Convert latlon deg coords to image point (x,y) and OSM tile coord
78
- # return where you should put point on tile
79
- def self.point_on_image(zoom, geo_coord)
80
- osm_tile_coord = convert(zoom, geo_coord)
81
- top_left_corner = reverse_convert(zoom, osm_tile_coord)
82
- bottom_right_corner = reverse_convert(zoom, [
83
- osm_tile_coord[0] + 1, osm_tile_coord[1] + 1
84
- ])
85
-
86
- # some line math: y = ax + b
87
-
88
- x_geo = geo_coord[1]
89
- # offset
90
- x_offset = x_geo - top_left_corner[1]
91
- # scale
92
- x_distance = (bottom_right_corner[1] - top_left_corner[1])
93
- x = (TILE_WIDTH.to_f * (x_offset / x_distance)).round
94
-
95
- y_geo = geo_coord[0]
96
- # offset
97
- y_offset = y_geo - top_left_corner[0]
98
- # scale
99
- y_distance = (bottom_right_corner[0] - top_left_corner[0])
100
- y = (TILE_HEIGHT.to_f * (y_offset / y_distance)).round
101
-
102
- return { osm_title_coord: osm_tile_coord, pixel_offset: [x, y] }
103
- end
104
-
105
- # Useful for calculating distance on output image
106
- # It is not position on output image because we don't know tile coords
107
- # For upper-left tile
108
- def self.point_on_absolute_image(zoom, geo_coord)
109
- _p = point_on_image(zoom, geo_coord)
110
- _x = _p[:osm_title_coord][0] * TILE_WIDTH + _p[:pixel_offset][0]
111
- _y = _p[:osm_title_coord][1] * TILE_WIDTH + _p[:pixel_offset][1]
112
- return [_x, _y]
113
- end
114
-
115
- # Create image with fixed size
116
- def fixed_size(_width, _height)
117
- @fixed_width = _width
118
- @fixed_height = _height
119
- end
120
-
121
- def initial_calculations
122
- @lat_min = @coords.collect { |c| c[:lat] }.min
123
- @lat_max = @coords.collect { |c| c[:lat] }.max
124
- @lon_min = @coords.collect { |c| c[:lon] }.min
125
- @lon_max = @coords.collect { |c| c[:lon] }.max
126
-
127
- # auto zoom must be here
128
- # drawing must fit into fixed resolution
129
- # map must be bigger than fixed resolution
130
- if @fixed_width and @fixed_height
131
- @new_zoom = self.class.calc_zoom(
132
- @lat_min, @lat_max,
133
- @lon_min, @lon_max,
134
- @fixed_width, @fixed_height
135
- )
136
- puts "Calculated new zoom #{@new_zoom} (was #{@zoom})" if @verbose
137
- @zoom = @new_zoom
138
- end
139
-
140
- @border_tiles = [
141
- self.class.convert(@zoom, [@lat_min, @lon_min]),
142
- self.class.convert(@zoom, [@lat_max, @lon_max])
143
- ]
144
-
145
- @tile_x_range = (@border_tiles[0][0])..(@border_tiles[1][0])
146
- @tile_y_range = (@border_tiles[1][1])..(@border_tiles[0][1])
147
-
148
- # enlarging ranges to fill up map area
149
- # both sizes are enlarged
150
- # = ( ( (preferred size - real size) / tile width ) / 2 ).ceil
151
- if @fixed_width and @fixed_height
152
- x_axis_expand_count = ((@fixed_width - (1 + @tile_x_range.max - @tile_x_range.min) * TILE_WIDTH).to_f / (TILE_WIDTH.to_f * 2.0)).ceil
153
- y_axis_expand_count = ((@fixed_height - (1 + @tile_y_range.max - @tile_y_range.min) * TILE_HEIGHT).to_f / (TILE_HEIGHT.to_f * 2.0)).ceil
154
- puts "Expanding X tiles from both sides #{x_axis_expand_count}" if @verbose
155
- puts "Expanding Y tiles from both sides #{y_axis_expand_count}" if @verbose
156
- @tile_x_range = ((@tile_x_range.min - x_axis_expand_count)..(@tile_x_range.max + x_axis_expand_count))
157
- @tile_y_range = ((@tile_y_range.min - y_axis_expand_count)..(@tile_y_range.max + y_axis_expand_count))
158
- end
159
-
160
- # new/full image size
161
- @full_image_x = (1 + @tile_x_range.max - @tile_x_range.min) * TILE_WIDTH
162
- @full_image_y = (1 + @tile_y_range.max - @tile_y_range.min) * TILE_HEIGHT
163
- @r.x = @full_image_x
164
- @r.y = @full_image_y
165
-
166
- if @fixed_width and @fixed_height
167
- calculate_for_crop_with_auto_zoom
168
- else
169
- calculate_for_crop
170
- end
171
- end
172
-
173
- # Calculate zoom level
174
- def auto_zoom_for(x = 0, y = 0)
175
- # TODO
176
- end
177
-
178
- attr_reader :lat_min, :lat_max, :lon_min, :lon_max
179
- attr_reader :tile_x_distance, :tile_y_distance
180
- # points for cropping
181
- attr_reader :bitmap_point_x_max, :bitmap_point_x_min, :bitmap_point_y_max, :bitmap_point_y_min
182
-
183
- # Do everything
184
- def download_and_join_tiles
185
- puts "Output image dimension #{@full_image_x}x#{@full_image_y}" if @verbose
186
- @r.new_image
187
-
188
- # {:x, :y, :blob}
189
- @images = Array.new
190
-
191
-
192
- @tile_x_range.each do |x|
193
- @tile_y_range.each do |y|
194
- url = self.class.url(@zoom, [x, y])
195
-
196
- # blob time
197
- unless simulate_download?
198
- uri = URI.parse(url)
199
- response = Net::HTTP.get_response(uri)
200
- blob = response.body
201
- else
202
- blob = @r.blank_tile(TILE_WIDTH, TILE_HEIGHT, x+y)
203
- end
204
-
205
- @r.add_tile(
206
- blob,
207
- (x - @tile_x_range.min) * TILE_WIDTH,
208
- (y - @tile_y_range.min) * TILE_HEIGHT
209
- )
210
-
211
- @images << {
212
- url: url,
213
- x: x,
214
- y: y
215
- }
216
-
217
- puts "processed #{x - @tile_x_range.min}x#{y - @tile_y_range.min} (max #{@tile_x_range.max - @tile_x_range.min}x#{@tile_y_range.max - @tile_y_range.min})" if @verbose
218
- end
219
- end
220
-
221
- # sweet, image is joined
222
-
223
- # min/max points used for cropping
224
- @bitmap_point_x_max = (@full_image_x / 2).round
225
- @bitmap_point_x_min = (@full_image_x / 2).round
226
- @bitmap_point_y_max = (@full_image_y / 2).round
227
- @bitmap_point_y_min = (@full_image_y / 2).round
228
-
229
- # add some coords to the map
230
- (1...@coords.size).each do |i|
231
- lat_from = @coords[i-1][:lat]
232
- lon_from = @coords[i-1][:lon]
233
-
234
- lat_to = @coords[i][:lat]
235
- lon_to = @coords[i][:lon]
236
-
237
- point_from = self.class.point_on_image(@zoom, [lat_from, lon_from])
238
- point_to = self.class.point_on_image(@zoom, [lat_to, lon_to])
239
- # { osm_title_coord: osm_tile_coord, pixel_offset: [x, y] }
240
-
241
- # first point
242
- bitmap_xa = (point_from[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_from[:pixel_offset][0]
243
- bitmap_ya = (point_from[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_from[:pixel_offset][1]
244
- bitmap_xb = (point_to[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_to[:pixel_offset][0]
245
- bitmap_yb = (point_to[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_to[:pixel_offset][1]
246
-
247
- @r.line(
248
- bitmap_xa, bitmap_ya,
249
- bitmap_xb, bitmap_yb
250
- )
251
- end
252
-
253
- # add points
254
- @markers.each do |point|
255
- lat = point[:lat]
256
- lon = point[:lon]
257
-
258
- p = self.class.point_on_image(@zoom, [lat, lon])
259
- bitmap_x = (p[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + p[:pixel_offset][0]
260
- bitmap_y = (p[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + p[:pixel_offset][1]
261
-
262
- point[:x] = bitmap_x
263
- point[:y] = bitmap_y
264
-
265
- @r.markers << point
266
- end
267
- end
268
-
269
- # Calculate some numbers for cropping operation
270
- def calculate_for_crop
271
- point_min = self.class.point_on_image(@zoom, [@lat_min, @lon_min])
272
- point_max = self.class.point_on_image(@zoom, [@lat_max, @lon_max])
273
- @bitmap_point_x_min = (point_min[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_min[:pixel_offset][0]
274
- @bitmap_point_x_max = (point_max[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_max[:pixel_offset][0]
275
- @bitmap_point_y_max = (point_min[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_min[:pixel_offset][1]
276
- @bitmap_point_y_min = (point_max[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_max[:pixel_offset][1]
277
-
278
- @r.set_crop(@bitmap_point_x_min, @bitmap_point_x_max, @bitmap_point_y_min, @bitmap_point_y_max)
279
- end
280
-
281
- # Calculate some numbers for cropping operation with autozoom
282
- def calculate_for_crop_with_auto_zoom
283
- point_min = self.class.point_on_image(@zoom, [@lat_min, @lon_min])
284
- point_max = self.class.point_on_image(@zoom, [@lat_max, @lon_max])
285
- @bitmap_point_x_min = (point_min[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_min[:pixel_offset][0]
286
- @bitmap_point_x_max = (point_max[:osm_title_coord][0] - @tile_x_range.min) * TILE_WIDTH + point_max[:pixel_offset][0]
287
- @bitmap_point_y_max = (point_min[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_min[:pixel_offset][1]
288
- @bitmap_point_y_min = (point_max[:osm_title_coord][1] - @tile_y_range.min) * TILE_HEIGHT + point_max[:pixel_offset][1]
289
-
290
- bitmap_x_center = (@bitmap_point_x_min + @bitmap_point_x_max) / 2
291
- bitmap_y_center = (@bitmap_point_y_min + @bitmap_point_y_max) / 2
292
-
293
- @r.set_crop_fixed(bitmap_x_center, bitmap_y_center, @fixed_width, @fixed_height)
294
- end
295
-
296
- def expand_map
297
- # TODO expand min and max ranges
298
- end
299
-
300
29
  def self.licence_string
301
30
  "Map data OpenStreetMap (CC-by-SA 2.0)"
302
31
  end
303
32
 
304
- def destroy
305
- @r.destroy
306
- puts "Image destroyed" if @verbose
307
- end
33
+
308
34
 
309
35
  end
310
36
  end
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'gpx2png/osm'
3
+
4
+ module Gpx2png
5
+ class Outdoors < Osm
6
+
7
+ # Convert OSM/UMP tile coords to url
8
+ def self.url(zoom, coord, server = '3.')
9
+ x, y = coord
10
+ url = "http://tile.thunderforest.com/outdoors/#{zoom}/#{x}/#{y}.png"
11
+ return url
12
+ end
13
+
14
+ def self.licence_string
15
+ "All maps copyright Thunderforest.com and OpenStreetMap contributors"
16
+ end
17
+
18
+ end
19
+ end
@@ -1,7 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'chunky_png'
3
3
 
4
- $:.unshift(File.dirname(__FILE__))
4
+ # WARNING: deprecated
5
5
 
6
6
  # This renderer has some/a lot of features missing
7
7
  module Gpx2png
@@ -2,8 +2,6 @@ require 'rubygems'
2
2
  require 'RMagick'
3
3
  require 'gpx2png/assets/sample_marker'
4
4
 
5
- $:.unshift(File.dirname(__FILE__))
6
-
7
5
  module Gpx2png
8
6
  class RmagickRenderer
9
7
  def initialize(_options = {})
@@ -77,8 +75,6 @@ module Gpx2png
77
75
 
78
76
  # Setup crop image using CSS padding style data
79
77
  def set_crop(x_min, x_max, y_min, y_max)
80
- # puts @x, @y, @crop_margin, x_min, x_max, y_min, y_max
81
-
82
78
  @crop_t = y_min - @crop_margin
83
79
  @crop_r = (@x - x_max) - @crop_margin
84
80
  @crop_b = (@y - y_max) - @crop_margin
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'gpx2png/osm'
3
+
4
+ module Gpx2png
5
+ class Transport < Osm
6
+
7
+ # Convert OSM/UMP tile coords to url
8
+ def self.url(zoom, coord, server = '3.')
9
+ x, y = coord
10
+ url = "http://tile.thunderforest.com/transport/#{zoom}/#{x}/#{y}.png"
11
+ return url
12
+ end
13
+
14
+ def self.licence_string
15
+ "All maps copyright Thunderforest.com and OpenStreetMap contributors"
16
+ end
17
+
18
+ end
19
+ end
@@ -1,8 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'gpx2png/osm'
3
3
 
4
- $:.unshift(File.dirname(__FILE__))
5
-
6
4
  module Gpx2png
7
5
  class Ump < Osm
8
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gpx2png
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-12-22 00:00:00.000000000 Z
12
+ date: 2013-12-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mini_exiftool
@@ -59,6 +59,22 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: colorize
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
62
78
  - !ruby/object:Gem::Dependency
63
79
  name: rspec
64
80
  requirement: !ruby/object:Gem::Requirement
@@ -142,10 +158,19 @@ files:
142
158
  - lib/gpx2png.rb
143
159
  - lib/gpx2png/assets/sample_marker.rb
144
160
  - lib/gpx2png/base.rb
161
+ - lib/gpx2png/calculations/base_class_methods.rb
162
+ - lib/gpx2png/calculations/base_instance_methods.rb
163
+ - lib/gpx2png/calculations/osm_class_methods.rb
164
+ - lib/gpx2png/calculations/osm_instance_methods.rb
165
+ - lib/gpx2png/landscape.rb
166
+ - lib/gpx2png/layer.rb
167
+ - lib/gpx2png/opencycle.rb
145
168
  - lib/gpx2png/osm.rb
146
169
  - lib/gpx2png/osm_base.rb
170
+ - lib/gpx2png/outdoors.rb
147
171
  - lib/gpx2png/renderers/chunky_png_renderer.rb
148
172
  - lib/gpx2png/renderers/rmagick_renderer.rb
173
+ - lib/gpx2png/transport.rb
149
174
  - lib/gpx2png/ump.rb
150
175
  homepage: http://github.com/akwiatkowski/gpx2png
151
176
  licenses:
@@ -162,7 +187,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
162
187
  version: '0'
163
188
  segments:
164
189
  - 0
165
- hash: 2224186545062807777
190
+ hash: 828698515099526590
166
191
  required_rubygems_version: !ruby/object:Gem::Requirement
167
192
  none: false
168
193
  requirements: