map_print 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +9 -2
- data/bin/map_print +6 -1
- data/lib/map_print/geo_json_handler.rb +51 -37
- data/lib/map_print/legend_handler.rb +67 -2
- data/lib/map_print/pdf_handler.rb +6 -2
- data/lib/map_print/scalebar_handler.rb +6 -9
- data/lib/map_print/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bcc0124c6e8b0ca5bae918c8306ff3057f8d400e
|
4
|
+
data.tar.gz: 0c47173c8d8a2079d54a6775ee738f3f9a50a233
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a3fc9ee3d584924d37ac49a68319a9827f9c4b3a00718c5f77d81ee969b0ddacec7ba30626fca03fb04e527c68ee206c2cf3cc0fd5f0d4ff2a16f5c129f17da
|
7
|
+
data.tar.gz: 36f8e4882219e98149d3750d778e25292d277198a13b21c5e4b0f6c39d50486627105d2bba0bdfe1a6dc63967fb6dfee58892b3b854632f3f37df37dbbac1c26
|
data/Gemfile.lock
CHANGED
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 :
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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] ==
|
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] ==
|
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
|
-
|
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
|
-
|
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
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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'))
|
data/lib/map_print/version.rb
CHANGED
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
|
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-
|
11
|
+
date: 2016-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|