map_print 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 423a53002a18daf1de1ba8cd5aabdcc9c17fb112
4
- data.tar.gz: 49824e15480ccfffd1c89e48573c8e8fb7957ea7
3
+ metadata.gz: bcc0124c6e8b0ca5bae918c8306ff3057f8d400e
4
+ data.tar.gz: 0c47173c8d8a2079d54a6775ee738f3f9a50a233
5
5
  SHA512:
6
- metadata.gz: 8ee96b45449be505392177a1a893295e0c844728d48b762f28945c2cda30cb368ea48ce12d81dc30720adc740fa973125c70759fe3061592043b3e8c320ff069
7
- data.tar.gz: a3f083c06a7c3781c23362bde338748cadaf53cc9b0e057b212110ad56e2442f0452f88d10b293bb99a8cf972d2d36242b070f93dc1f59a68014b084b560c7f6
6
+ metadata.gz: 2a3fc9ee3d584924d37ac49a68319a9827f9c4b3a00718c5f77d81ee969b0ddacec7ba30626fca03fb04e527c68ee206c2cf3cc0fd5f0d4ff2a16f5c129f17da
7
+ data.tar.gz: 36f8e4882219e98149d3750d778e25292d277198a13b21c5e4b0f6c39d50486627105d2bba0bdfe1a6dc63967fb6dfee58892b3b854632f3f37df37dbbac1c26
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- map_print (1.0.1)
4
+ map_print (1.1.0)
5
5
  mini_magick (~> 4.3)
6
6
  parallel (~> 1.6)
7
7
  prawn (~> 2.0)
data/README.md CHANGED
@@ -27,7 +27,7 @@ Or install it yourself as:
27
27
 
28
28
  ### Executable
29
29
 
30
- `map_print print --south-west="-35.026862,-58.425003" --north-east="-29.980172,-52.959305" --zoom="10" --output="output.png"`
30
+ `map_print print --south-west="-35.026862,-58.425003" --north-east="-29.980172,-52.959305" --width=500 --height=800 --zoom="10" --output="output.png"`
31
31
 
32
32
  Indicating southwest and northeast to determine the bounding box. Set the zoom at which the tiles should be requested.
33
33
 
@@ -210,7 +210,14 @@ map_configuration = {
210
210
  padding: {top: 5, right: 5, bottom: 5, left: 5},
211
211
  bar_height: 10,
212
212
  background_color: 'black',
213
- background_opacity: 0.4
213
+ background_opacity: 0.4,
214
+ text_style: {
215
+ fill_color: '#ffffff',
216
+ color: '#000000',
217
+ font: 'Arial',
218
+ pointsize: '16',
219
+ gravity: 'NorthWest'
220
+ }
214
221
  }
215
222
  }
216
223
  ```
data/bin/map_print CHANGED
@@ -10,8 +10,10 @@ class MapPrintCommand < Thor
10
10
 
11
11
  method_option :south_west, type: :string, required: true
12
12
  method_option :north_east, type: :string, required: true
13
- method_option :output, type: :string, required: true
13
+ method_option :width, type: :numeric, required: true
14
+ method_option :height, type: :numeric, required: true
14
15
  method_option :zoom, type: :numeric, default: 10
16
+ method_option :output, type: :string, required: true
15
17
 
16
18
  method_option :provider, type: :string, default: 'osm',
17
19
  enum: ['osm', 'bing']
@@ -25,8 +27,11 @@ class MapPrintCommand < Thor
25
27
  south_west = MapPrint::LatLng.new(*south_west_coordinate)
26
28
  north_east = MapPrint::LatLng.new(*north_east_coordinate)
27
29
 
30
+ png_options = {height: options[:height], width: options[:width]}
31
+
28
32
  map_options = {
29
33
  format: 'png',
34
+ png_options: png_options,
30
35
  map: {
31
36
  sw: {
32
37
  lat: south_west.lat,
@@ -38,30 +38,33 @@ module MapPrint
38
38
  end
39
39
  end
40
40
 
41
- def feature(geometry, properties={})
41
+ def validate_feature(geometry, properties)
42
42
  raise NoGeometryPresent.new("No geometry present for this feature") if geometry.nil?
43
43
  case geometry['type']
44
+ when 'Point'
45
+ if properties.nil? || properties['image'].nil?
46
+ raise NoPointImage.new("Missing image in point geometry")
47
+ end
48
+ when 'MultiPoint', 'MultiLineString', 'MultiPolygon', 'GeometryCollection'
49
+ raise FeatureNotImplemented.new("Please consider contributing!")
50
+ else
51
+ Logger.warn "Feature type '#{geometry['type']}' not implemented!"
52
+ end
53
+ end
54
+
55
+ def feature(geometry, properties={})
56
+ validate_feature(geometry, properties)
57
+ case geometry['type']
44
58
  when 'Feature'
45
59
  feature(geometry['geometry'], geometry['properties'])
46
60
  when 'FeatureCollection'
47
61
  feature_collection(geometry['features'])
48
62
  when 'Point'
49
- raise NoPointImage.new("Missing image in point geometry") unless properties && properties['image']
50
63
  point(geometry, properties['image'])
51
64
  when 'LineString'
52
65
  line_string(geometry, properties)
53
66
  when 'Polygon'
54
67
  polygon(geometry, properties)
55
- when 'MultiPoint'
56
- raise FeatureNotImplemented.new("Please consider contributing!")
57
- when 'MultiLineString'
58
- raise FeatureNotImplemented.new("Please consider contributing!")
59
- when 'MultiPolygon'
60
- raise FeatureNotImplemented.new("Please consider contributing!")
61
- when 'GeometryCollection'
62
- raise FeatureNotImplemented.new("Please consider contributing!")
63
- else
64
- Logger.warn "Feature type '#{geometry['type']}' not implemented!"
65
68
  end
66
69
  rescue GeoJSONHandlerError => ex
67
70
  Logger.warn ex
@@ -77,7 +80,7 @@ module MapPrint
77
80
  x = get_x(point['coordinates'][0])
78
81
  y = get_y(point['coordinates'][1])
79
82
 
80
- if 0 <= x && x <= @width && 0 <= y && y <= @height
83
+ if point_inside_map?(x, y)
81
84
  point_image = MiniMagick::Image.open(image_path)
82
85
  x -= point_image.width / 2
83
86
  y -= point_image.height / 2
@@ -92,17 +95,7 @@ module MapPrint
92
95
  end
93
96
 
94
97
  def line_string(geometry, properties)
95
- properties ||= {}
96
- coords = geometry['coordinates']
97
- coords = coords.first if coords.first.first.is_a?(Array)
98
- points = coords.map do |coord|
99
- x = get_x(coord[0])
100
- y = get_y(coord[1])
101
- if 0 <= x && x <= @width && 0 <= y && y <= @height
102
- Logger.warn "Line coordinate outside map's boundaries!\ngeometry: #{geometry.inspect}\nproperties: #{properties.inspect}"
103
- end
104
- "#{x},#{y}"
105
- end
98
+ points = generate_drawable_points(geometry, properties)
106
99
 
107
100
  draw_command = (0..(points.length - 2)).map do |i|
108
101
  "line #{points[i]} #{points[i+1]}"
@@ -115,17 +108,7 @@ module MapPrint
115
108
  end
116
109
 
117
110
  def polygon(geometry, properties)
118
- properties ||= {}
119
- coords = geometry['coordinates']
120
- coords = coords.first if coords.first.first.is_a?(Array)
121
- points = coords.map do |coord|
122
- x = get_x(coord[0])
123
- y = get_y(coord[1])
124
- if 0 <= x && x <= @width && 0 <= y && y <= @height
125
- Logger.warn "Polygon coordinate outside map's boundaries!\ngeometry: #{geometry.inspect}\nproperties: #{properties.inspect}"
126
- end
127
- "#{x},#{y}"
128
- end
111
+ points = generate_drawable_points(geometry, properties)
129
112
 
130
113
  @image.combine_options do |c|
131
114
  c.density 300
@@ -133,20 +116,29 @@ module MapPrint
133
116
  end
134
117
  end
135
118
 
136
- def draw_options(properties, line=true)
119
+ def stroke_options(properties)
137
120
  options = ''
138
121
  if properties['stroke'] || properties['stroke'].nil?
139
122
  options += "stroke #{properties['color'] || '#0033ff'} "
140
123
  options += "stroke-width #{properties['weight'] || 5} "
141
124
  options += "stroke-opacity #{properties['opacity'] || 0.5} "
142
125
  end
126
+ options
127
+ end
143
128
 
144
- if properties['fill'] || (!line && properties['fill'].nil?)
129
+ def fill_options(properties, line)
130
+ options = ''
131
+ if properties['fill'] != false || !line
145
132
  options += "fill #{properties['fillColor'] || '#0033ff'} "
146
133
  options += "fill-opacity #{properties['fillOpacity'] || 0.2} "
147
134
  options += "fill-rule #{properties['fillRule'] || 'evenodd'} "
148
135
  end
136
+ options
137
+ end
149
138
 
139
+ def draw_options(properties, line=true)
140
+ options = stroke_options(properties)
141
+ options += fill_options(properties, line)
150
142
  options += "stroke-dasharray #{properties['dashArray']} " if properties['dashArray']
151
143
  options += "stroke-linecap #{properties['lineCap']} " if properties['lineCap']
152
144
  options += "stroke-linejoin #{properties['lineJoin']} " if properties['lineJoin']
@@ -160,5 +152,27 @@ module MapPrint
160
152
  def get_y(lat)
161
153
  @height * (@top_lat - lat) / @total_lat;
162
154
  end
155
+
156
+ def point_inside_map?(x, y)
157
+ 0 <= x && x <= @width && 0 <= y && y <= @height
158
+ end
159
+
160
+ def consider_outside_boundaries(x, y, geometry, properties)
161
+ if !point_inside_map?(x, y)
162
+ Logger.warn "Coordinate outside map's boundaries!\ngeometry: #{geometry.inspect}\nproperties: #{properties.inspect}"
163
+ end
164
+ end
165
+
166
+ def generate_drawable_points(geometry, properties)
167
+ properties ||= {}
168
+ coords = geometry['coordinates']
169
+ coords = coords.first if coords.first.first.is_a?(Array)
170
+ coords.map do |coord|
171
+ x = get_x(coord[0])
172
+ y = get_y(coord[1])
173
+ consider_outside_boundaries(x, y, geometry, properties)
174
+ "#{x},#{y}"
175
+ end
176
+ end
163
177
  end
164
178
  end
@@ -6,12 +6,21 @@ module MapPrint
6
6
  include PngHandlers::Texts
7
7
  include Validations::Size
8
8
 
9
+ OVERFLOW = {
10
+ expand: 'expand',
11
+ compact: 'compact',
12
+ hidden: 'hidden'
13
+ }
14
+ VERTICAL = 'vertical'
15
+ HORIZONTAL = 'horizontal'
16
+
9
17
  def initialize(legend)
10
18
  @legend = legend
11
19
  validate_data!
20
+ overflow_option_adjustments
12
21
  @x_step = @legend[:size][:width] / @legend[:columns]
13
22
  @y_step = @legend[:size][:height] / @legend[:rows]
14
- @elements_in_block = @legend[:orientation] == 'vertical' ? @legend[:rows] : @legend[:columns]
23
+ @elements_in_block = @legend[:orientation] == VERTICAL ? @legend[:rows] : @legend[:columns]
15
24
  @legend[:textbox_style] ||= {}
16
25
 
17
26
  if @legend[:textbox_size]
@@ -73,7 +82,7 @@ module MapPrint
73
82
  end
74
83
 
75
84
  def get_next_x_y(x, y, z)
76
- if @legend[:orientation] == 'vertical'
85
+ if @legend[:orientation] == VERTICAL
77
86
  y, x = next_step(y, x, @y_step, @x_step, z)
78
87
  else
79
88
  x, y = next_step(x, y, @x_step, @y_step, z)
@@ -92,5 +101,61 @@ module MapPrint
92
101
 
93
102
  return small_step_value, big_step_value
94
103
  end
104
+
105
+ def overflow_hidden?
106
+ @legend[:overflow].nil? || @legend[:overflow].downcase == OVERFLOW[:hidden]
107
+ end
108
+
109
+ def overflow_expand?
110
+ @legend[:overflow].downcase == OVERFLOW[:expand]
111
+ end
112
+
113
+ def overflow_compact?
114
+ @legend[:overflow].downcase == OVERFLOW[:compact]
115
+ end
116
+
117
+ def vertical_orientation?
118
+ @legend[:orientation] == VERTICAL
119
+ end
120
+
121
+ def horizontal_orientation?
122
+ @legend[:orientation] == HORIZONTAL
123
+ end
124
+
125
+ def available_legend_spots
126
+ @legend[:columns] * @legend[:rows]
127
+ end
128
+
129
+ def overflow_option_adjustments
130
+ return unless @legend[:elements].size > available_legend_spots
131
+ case
132
+ when overflow_hidden?
133
+ @legend[:elements] = @legend[:elements][0..(available_legend_spots-1)]
134
+ when overflow_expand?
135
+ expand_adjustments
136
+ when overflow_compact?
137
+ compact_adjustments
138
+ end
139
+ end
140
+
141
+ def expand_adjustments
142
+ if vertical_orientation?
143
+ column_width = @legend[:size][:width] / @legend[:columns]
144
+ compact_adjustments
145
+ @legend[:size][:width] = @legend[:columns] * column_width
146
+ elsif horizontal_orientation?
147
+ row_height = @legend[:size][:height] / @legend[:rows]
148
+ compact_adjustments
149
+ @legend[:size][:height] = @legend[:rows] * row_height
150
+ end
151
+ end
152
+
153
+ def compact_adjustments
154
+ if vertical_orientation?
155
+ @legend[:columns] = (@legend[:elements].size / @legend[:rows].to_f).ceil
156
+ elsif horizontal_orientation?
157
+ @legend[:rows] = (@legend[:elements].size / @legend[:columns].to_f).ceil
158
+ end
159
+ end
95
160
  end
96
161
  end
@@ -19,12 +19,12 @@ module MapPrint
19
19
 
20
20
  scalebar_image = @context.print_scalebar
21
21
  if scalebar_image
22
- @pdf.image scalebar_image.path, at: [@context.scalebar[:position][:x], @pdf.bounds.top - @context.scalebar[:position][:y]]
22
+ print_image(scalebar_image.path, @context.scalebar[:position])
23
23
  end
24
24
 
25
25
  legend_image = @context.print_legend
26
26
  if legend_image
27
- @pdf.image legend_image.path, at: [@context.legend[:position][:x], @pdf.bounds.top - @context.legend[:position][:y]]
27
+ print_image(legend_image.path, @context.legend[:position])
28
28
  end
29
29
 
30
30
  @pdf.render_file(@context.output_path)
@@ -42,5 +42,9 @@ module MapPrint
42
42
  position = @context.map[:position] || {}
43
43
  @pdf.image map_image.path, at: [position[:x] || 0, @pdf.bounds.top - (position[:y] || 0)], fit: size.values
44
44
  end
45
+
46
+ def print_image(image_path, position)
47
+ @pdf.image image_path, at: [position[:x], @pdf.bounds.top - position[:y]]
48
+ end
45
49
  end
46
50
  end
@@ -54,20 +54,17 @@ module MapPrint
54
54
  quarter = (size[:width] - @padding_left - @padding_right) / 4
55
55
 
56
56
  y_position = size[:height] - (@scalebar[:bar_height] || 10) - @padding_bottom
57
+ orig_y = size[:height] - @padding_bottom
57
58
  image.combine_options do |c|
58
59
  c.density 300
59
60
  c.stroke 'black'
60
- c.fill 'white'
61
- c.draw "rectangle #{@padding_left},#{size[:height] - @padding_bottom} #{@padding_left + quarter},#{y_position}"
62
- c.fill 'black'
63
- c.draw "rectangle #{@padding_left + quarter},#{size[:height] - @padding_bottom} #{@padding_left + 2*quarter},#{y_position}"
64
- c.fill 'white'
65
- c.draw "rectangle #{@padding_left + 2*quarter},#{size[:height] - @padding_bottom} #{@padding_left + 3*quarter},#{y_position}"
66
- c.fill 'black'
67
- c.draw "rectangle #{@padding_left + 3*quarter},#{size[:height] - @padding_bottom} #{@padding_left + 4*quarter},#{y_position}"
61
+ (0..3).each do |i|
62
+ c.fill (i % 2 == 0 ? 'white' : 'black')
63
+ c.draw "rectangle #{@padding_left + i*quarter},#{orig_y} #{@padding_left + (i+1)*quarter},#{y_position}"
64
+ end
68
65
  end
69
66
 
70
- text_options = { pointsize: 4, gravity: 'NorthWest' }
67
+ text_options = { pointsize: 4, gravity: 'NorthWest' }.merge(@scalebar[:text_style] || {})
71
68
  draw_text(image, "0", "#{@padding_left},#{@padding_top}", text_options)
72
69
  draw_text(image, (pixels_for_distance/4).round(-2).to_s, "#{-quarter + @padding_left - @padding_right},#{@padding_top}", text_options.merge(gravity: 'North'))
73
70
  draw_text(image, (pixels_for_distance/2).round(-2).to_s, "#{@padding_left - @padding_right},#{@padding_top}", text_options.merge(gravity: 'North'))
@@ -1,3 +1,3 @@
1
1
  module MapPrint
2
- VERSION = '1.0.1'
2
+ VERSION = '1.1.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: map_print
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Fast
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-25 00:00:00.000000000 Z
11
+ date: 2016-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler