map_print 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +37 -2
- data/README.md +112 -1
- data/bin/map_print +51 -3
- data/lib/base.rb +3 -0
- data/lib/map_print/core.rb +118 -27
- data/lib/map_print/geo_json_handler.rb +135 -0
- data/lib/map_print/image_handler.rb +9 -0
- data/lib/map_print/layer_handler.rb +44 -0
- data/lib/map_print/legend_handler.rb +9 -0
- data/lib/map_print/osm/tile.rb +53 -19
- data/lib/map_print/osm/tile_factory.rb +7 -0
- data/lib/map_print/providers/base.rb +55 -0
- data/lib/map_print/providers/bing.rb +13 -0
- data/lib/map_print/providers/open_street_map.rb +14 -0
- data/lib/map_print/scalebar_handler.rb +9 -0
- data/lib/map_print/text_handler.rb +9 -0
- data/lib/map_print/tiles/bing_tile.rb +42 -0
- data/lib/map_print/tiles/osm_tile.rb +21 -0
- data/lib/map_print/tiles/tile.rb +110 -0
- data/lib/map_print/tiles/tile_factory.rb +90 -0
- data/lib/map_print/version.rb +1 -1
- data/lib/map_print.rb +4 -13
- data/map_print.gemspec +5 -2
- data/marker.png +0 -0
- metadata +64 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 139b682f39bdac95f76c9c486a146dc16376e0f6
|
4
|
+
data.tar.gz: 6df45284cb99894a860474e60b8443cbe4adf458
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ecda32b632e257d4e79bd22900480796e2bb0f3167de4c5b53661902a923b8508314be59e69b6dd1b23e0a24638cd22f8eca0ae31954c59ada553d7b190ad57
|
7
|
+
data.tar.gz: 298ed01e24f773854d869243140641f33a5982fc640a504a3c3aa958cb9f79bb08d289a3ac77af272bf8ab57f130c45b6e6c10756c893f4903ea025b83965640
|
data/Gemfile.lock
CHANGED
@@ -4,20 +4,55 @@ PATH
|
|
4
4
|
map_print (0.1.0)
|
5
5
|
geo-distance (~> 0.1)
|
6
6
|
mini_magick (~> 4.3)
|
7
|
+
parallel (~> 1.6.1)
|
7
8
|
prawn (~> 2.0)
|
9
|
+
prawn-fast-png (~> 0.2.3)
|
10
|
+
thor
|
8
11
|
|
9
12
|
GEM
|
10
13
|
remote: https://rubygems.org/
|
11
14
|
specs:
|
12
|
-
|
15
|
+
activesupport (4.2.5)
|
16
|
+
i18n (~> 0.7)
|
17
|
+
json (~> 1.7, >= 1.7.7)
|
18
|
+
minitest (~> 5.1)
|
19
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
20
|
+
tzinfo (~> 1.1)
|
21
|
+
geo-distance (0.2.0)
|
22
|
+
geo_point (~> 0.2.5)
|
23
|
+
geo_units (~> 0.2.4.1)
|
24
|
+
geo_calc (0.7.6)
|
25
|
+
activesupport (>= 3.0.1)
|
26
|
+
geo_units (~> 0.2.1)
|
27
|
+
i18n
|
28
|
+
require_all (~> 1.2.0)
|
29
|
+
sugar-high (~> 0.4.6.3)
|
30
|
+
geo_point (0.2.5)
|
31
|
+
geo_calc (~> 0.7.5)
|
32
|
+
geo_units (~> 0.2.1)
|
33
|
+
geo_units (0.2.4.1)
|
34
|
+
sugar-high (~> 0.4.6.2)
|
35
|
+
i18n (0.7.0)
|
36
|
+
json (1.8.3)
|
13
37
|
mini_magick (4.3.6)
|
14
38
|
minitest (5.8.2)
|
39
|
+
parallel (1.6.1)
|
15
40
|
pdf-core (0.6.0)
|
16
41
|
prawn (2.0.2)
|
17
42
|
pdf-core (~> 0.6.0)
|
18
43
|
ttfunk (~> 1.4.0)
|
44
|
+
prawn-fast-png (0.2.3)
|
45
|
+
prawn
|
46
|
+
rmagick
|
19
47
|
rake (10.4.2)
|
48
|
+
require_all (1.2.1)
|
49
|
+
rmagick (2.15.4)
|
50
|
+
sugar-high (0.4.6.4)
|
51
|
+
thor (0.19.1)
|
52
|
+
thread_safe (0.3.5)
|
20
53
|
ttfunk (1.4.0)
|
54
|
+
tzinfo (1.2.2)
|
55
|
+
thread_safe (~> 0.1)
|
21
56
|
|
22
57
|
PLATFORMS
|
23
58
|
ruby
|
@@ -25,7 +60,7 @@ PLATFORMS
|
|
25
60
|
DEPENDENCIES
|
26
61
|
bundler (~> 1.10)
|
27
62
|
map_print!
|
28
|
-
minitest
|
63
|
+
minitest (~> 5.8)
|
29
64
|
rake (~> 10.0)
|
30
65
|
|
31
66
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -20,7 +20,118 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
|
23
|
+
### Executable
|
24
|
+
|
25
|
+
`map_print print --south-west="-35.026862,-58.425003" --north-east="-29.980172,-52.959305" --zoom="10" --output="output.png"`
|
26
|
+
|
27
|
+
Indicating southwest and northeast to determine the bounding box. Set the zoom at which the tiles should be requested.
|
28
|
+
|
29
|
+
In addition set the `output` path to which the resulting image will be written.
|
30
|
+
|
31
|
+
This is intended to be more of a testing method as it doesn't support all the options available and always returns a png. In the future we might provide more functionality depending on feature request.
|
32
|
+
|
33
|
+
### In ruby code
|
34
|
+
|
35
|
+
The mos common usage you'll be expecting is to create a new instance with the map configuration and then call `print` with the output path. MapPrint will take the map configuration, generate the map and write the output to the output path. In the example below `./map.png`.
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
MapPrint::Core.new(map_configuration).print('./map.png')```
|
39
|
+
|
40
|
+
`map_configuration` is a hash with the following options:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
BASIC_MAP = {
|
44
|
+
format: 'pdf', # pdf or png
|
45
|
+
pdf_options: {
|
46
|
+
page_size: 'A4', # A0-10, B0-10, C0-10
|
47
|
+
page_layout: :portrait # :portrait, :landscape
|
48
|
+
},
|
49
|
+
map: {
|
50
|
+
sw: { # required
|
51
|
+
lat: -35.026862,
|
52
|
+
lng: -58.425003
|
53
|
+
},
|
54
|
+
ne: { # required
|
55
|
+
lat: -29.980172,
|
56
|
+
lng: -52.959305
|
57
|
+
},
|
58
|
+
zoom: 9, # whatever is supported by the source, typically between 1-15
|
59
|
+
position: { # x,y position on the PDF (as prawn determines it)
|
60
|
+
x: 50,
|
61
|
+
y: 50
|
62
|
+
},
|
63
|
+
size: { # Resize the map image, typically used to print the map on pdf
|
64
|
+
width: 500,
|
65
|
+
height: 800
|
66
|
+
},
|
67
|
+
layers: [{ # Whatever layers you want to include. Currently only OSM and Bing are supported
|
68
|
+
type: 'osm', # (osm, bing) to understand variable substitution and stitching toghether the final image
|
69
|
+
urls: ['http://a.tile.thunderforest.com/transport/${z}/${x}/${y}.png'], # currently only one is being used, in the future it will load balance
|
70
|
+
level: 1, # used to order the layer appearance
|
71
|
+
opacity: 1.0 # in case you want the layer to have some transparency
|
72
|
+
}], # see geojson specification for feature/object support. See http://leafletjs.com/reference.html#path-options for formatting options, the following attributes under properties are supported: `stroke, color, weight, opacity, fill, fillColor, fillOpacity, fillRule, dashArray, lineCap, lineJoin`
|
73
|
+
geojson: '{
|
74
|
+
"type": "FeatureCollection",
|
75
|
+
"features": [{
|
76
|
+
"type":"Feature",
|
77
|
+
"geometry":{"type":"Point", "coordinates":[-32.026862,-55.425003]},
|
78
|
+
"properties":{"image": "./marker.png"}
|
79
|
+
}, {
|
80
|
+
"type": "Feature",
|
81
|
+
"geometry": {"type": "LineString", "coordinates": [ [-32.026862,-55.425003], [-31.026862,-55.425003], [-31.026862,-54.425003], [-32.026862,-54.425003] ] },
|
82
|
+
"properties": {"color": "#000000"}
|
83
|
+
}, {
|
84
|
+
"type": "Feature",
|
85
|
+
"geometry": {"type": "Polygon", "coordinates": [ [-32.126862,-55.825003], [-31.426862,-55.225003], [-31.326862,-54.825003], [-32.146862,-54.835003] ] },
|
86
|
+
"properties": {
|
87
|
+
"stroke": true,
|
88
|
+
"color": "#000000",
|
89
|
+
"weight": 2,
|
90
|
+
"opacity": 1,
|
91
|
+
"fill": true,
|
92
|
+
"fillColor": "#ffffff",
|
93
|
+
"fillOpacity": 1,
|
94
|
+
"fillRule": "evenodd",
|
95
|
+
"dashArray": "5,2,3",
|
96
|
+
"lineCap": "round",
|
97
|
+
"lineJoin": "round"
|
98
|
+
}
|
99
|
+
}]
|
100
|
+
}'
|
101
|
+
},
|
102
|
+
images: [ # not supported yet
|
103
|
+
{
|
104
|
+
path: './file.png',
|
105
|
+
position: {x: 50, y: 50 },
|
106
|
+
size: {width: 50, height: 50},
|
107
|
+
options: {}
|
108
|
+
}
|
109
|
+
],
|
110
|
+
texts: [ # not supported yet
|
111
|
+
{
|
112
|
+
text: "some text",
|
113
|
+
position: {x: 50, y: 50 },
|
114
|
+
size: {width: 50, height: 50},
|
115
|
+
options: {}
|
116
|
+
}
|
117
|
+
],
|
118
|
+
legend: { # not supported yet
|
119
|
+
position: {x: 50, y: 50},
|
120
|
+
size: {width: 50, height: 50},
|
121
|
+
columns: 5,
|
122
|
+
rows: 5,
|
123
|
+
elements: [{
|
124
|
+
image: './file.png',
|
125
|
+
text: 'text'
|
126
|
+
}]
|
127
|
+
},
|
128
|
+
scalebar: { # not supported yet
|
129
|
+
unit: 'meters', # meters, km, miles, feet
|
130
|
+
position: {x: 50, y: 50},
|
131
|
+
size: {width: 50, height: 50}
|
132
|
+
}
|
133
|
+
}
|
134
|
+
```
|
24
135
|
|
25
136
|
## Development
|
26
137
|
|
data/bin/map_print
CHANGED
@@ -1,6 +1,54 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'thor'
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'map_print'
|
5
6
|
|
6
|
-
|
7
|
+
class MapPrintCommand < Thor
|
8
|
+
|
9
|
+
desc "print", "Print a map using the given parameters"
|
10
|
+
|
11
|
+
method_option :south_west, type: :string, required: true
|
12
|
+
method_option :north_east, type: :string, required: true
|
13
|
+
method_option :output, type: :string, required: true
|
14
|
+
method_option :zoom, type: :numeric, default: 10
|
15
|
+
|
16
|
+
method_option :provider, type: :string, default: 'osm',
|
17
|
+
enum: ['osm', 'bing']
|
18
|
+
|
19
|
+
def print
|
20
|
+
south_west_coordinate = options[:south_west].split(',')
|
21
|
+
.map {|coordinate| Float(coordinate)}
|
22
|
+
north_east_coordinate = options[:north_east].split(',')
|
23
|
+
.map {|coordinate| Float(coordinate)}
|
24
|
+
|
25
|
+
south_west = MapPrint::LatLng.new(*south_west_coordinate)
|
26
|
+
north_east = MapPrint::LatLng.new(*north_east_coordinate)
|
27
|
+
|
28
|
+
map_options = {
|
29
|
+
format: 'png',
|
30
|
+
map: {
|
31
|
+
sw: {
|
32
|
+
lat: south_west.lat,
|
33
|
+
lng: south_west.lng
|
34
|
+
},
|
35
|
+
ne: {
|
36
|
+
lat: north_east.lat,
|
37
|
+
lng: north_east.lng
|
38
|
+
},
|
39
|
+
zoom: options[:zoom],
|
40
|
+
layers: [{
|
41
|
+
type: 'osm', # to understand variable substitution and stitching toghether the final image
|
42
|
+
urls: ['http://a.tile.thunderforest.com/transport/${z}/${x}/${y}.png'],
|
43
|
+
level: 1,
|
44
|
+
opacity: 1.0 # in case you want the layer to have some transparency
|
45
|
+
}]
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
MapPrint::Core.new(map_options).print(options[:output])
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
MapPrintCommand.start
|
data/lib/base.rb
ADDED
data/lib/map_print/core.rb
CHANGED
@@ -1,41 +1,132 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require_relative 'lat_lng'
|
2
|
+
require_relative 'tiles/tile'
|
3
|
+
require_relative 'tiles/tile_factory'
|
4
|
+
require_relative 'providers/base'
|
5
|
+
require_relative 'providers/bing'
|
6
|
+
require_relative 'providers/open_street_map'
|
7
|
+
require_relative 'layer_handler'
|
8
|
+
require_relative 'scalebar_handler'
|
9
|
+
require_relative 'image_handler'
|
10
|
+
require_relative 'text_handler'
|
11
|
+
require_relative 'legend_handler'
|
12
|
+
require_relative 'geo_json_handler'
|
4
13
|
|
5
14
|
module MapPrint
|
6
15
|
class Core
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
osm
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
attr_accessor :map, :images, :texts, :legend, :scalebar
|
17
|
+
|
18
|
+
PROVIDERS = {
|
19
|
+
'bing' => MapPrint::Providers::Bing,
|
20
|
+
'osm' => MapPrint::Providers::OpenStreetMap
|
21
|
+
}
|
22
|
+
|
23
|
+
def initialize(args)
|
24
|
+
@format = args[:format]
|
25
|
+
@pdf_options = args[:pdf_options]
|
26
|
+
@map = args[:map]
|
27
|
+
@images = args[:images]
|
28
|
+
@texts = args[:texts]
|
29
|
+
@legend = args[:legend]
|
30
|
+
@scalebar = args[:scalebar]
|
31
|
+
end
|
32
|
+
|
33
|
+
def print(output_path)
|
34
|
+
@output_path = output_path
|
35
|
+
|
36
|
+
if @format == 'pdf'
|
37
|
+
print_pdf
|
38
|
+
elsif @format == 'png'
|
39
|
+
print_png
|
40
|
+
else
|
41
|
+
raise "Unsupported format: #{@format}"
|
20
42
|
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
def print_pdf
|
47
|
+
pdf = init_pdf
|
48
|
+
map_image = print_layers
|
49
|
+
map_image = print_geojson(MiniMagick::Image.new(map_image.path))
|
50
|
+
|
51
|
+
FileUtils.cp map_image.path, './map.png' if defined?(DEBUG)
|
52
|
+
|
53
|
+
pdf.image map_image.path, at: [@map[:position][:x], pdf.bounds.top - @map[:position][:y]]
|
54
|
+
|
55
|
+
print_images_on_pdf(pdf)
|
56
|
+
print_texts_on_pdf(pdf)
|
57
|
+
print_legend_on_pdf(pdf)
|
58
|
+
|
59
|
+
pdf.render_file(@output_path)
|
60
|
+
@output_path
|
61
|
+
end
|
62
|
+
|
63
|
+
def print_png
|
64
|
+
map_image = print_layers
|
65
|
+
map_image = print_geojson(MiniMagick::Image.new(map_image.path))
|
66
|
+
|
67
|
+
print_images_on_png(map_image)
|
68
|
+
print_texts_on_png(map_image)
|
69
|
+
print_legend_on_png(map_image)
|
70
|
+
|
71
|
+
FileUtils.cp map_image.path, @output_path
|
72
|
+
end
|
73
|
+
|
74
|
+
def init_file
|
75
|
+
@file = File.open @output_path, 'wb'
|
76
|
+
end
|
21
77
|
|
22
|
-
|
78
|
+
def init_pdf
|
79
|
+
Prawn::Document.new @pdf_options || {}
|
80
|
+
end
|
23
81
|
|
24
|
-
|
82
|
+
def print_layers
|
83
|
+
file = LayerHandler.new(@map[:layers], @map[:sw], @map[:ne], @map[:zoom]).process
|
84
|
+
size = @map[:size]
|
25
85
|
|
26
|
-
|
27
|
-
width = image.width - osm.px_offset[:left] - osm.px_offset[:right]
|
28
|
-
height = image.height - osm.px_offset[:top] - osm.px_offset[:bottom]
|
29
|
-
puts "width – old: #{image.width} - new #{width}"
|
30
|
-
puts "height – old: #{image.height} - new #{height}"
|
86
|
+
FileUtils.cp file.path, 'layers.png' if defined?DEBUG
|
31
87
|
|
32
|
-
|
88
|
+
if size
|
89
|
+
image = MiniMagick::Image.new(file.path)
|
90
|
+
size[:width] ||= image.width
|
91
|
+
size[:height] ||= image.height
|
92
|
+
puts "Fitting map image (#{image.width}x#{image.height}) in #{size[:width]}x#{size[:height]}"
|
93
|
+
image.colorspace("RGB").resize("#{size[:width]}x#{size[:height]}\>").colorspace("sRGB").unsharp "0x0.75+0.75+0.008"
|
94
|
+
end
|
33
95
|
|
34
|
-
|
35
|
-
|
96
|
+
file
|
97
|
+
end
|
98
|
+
|
99
|
+
def print_geojson(map_image)
|
100
|
+
if @map[:geojson]
|
101
|
+
geojson_image = GeoJSONHandler.new(@map[:geojson], @map[:sw], @map[:ne], map_image.width, map_image.height).process
|
102
|
+
result = MiniMagick::Image.open(map_image.path).composite(geojson_image) do |c|
|
103
|
+
c.compose "atop"
|
104
|
+
end
|
105
|
+
result.write map_image.path
|
36
106
|
end
|
37
107
|
|
38
|
-
|
108
|
+
map_image
|
109
|
+
end
|
110
|
+
|
111
|
+
def print_images_on_pdf(pdf)
|
112
|
+
end
|
113
|
+
|
114
|
+
def print_texts_on_pdf(pdf)
|
115
|
+
end
|
116
|
+
|
117
|
+
def print_scalebar
|
118
|
+
end
|
119
|
+
|
120
|
+
def print_legend_on_pdf(pdf)
|
121
|
+
end
|
122
|
+
|
123
|
+
def print_images_on_png(png)
|
124
|
+
end
|
125
|
+
|
126
|
+
def print_texts_on_png(png)
|
127
|
+
end
|
128
|
+
|
129
|
+
def print_legend_on_png(png)
|
39
130
|
end
|
40
131
|
end
|
41
132
|
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module MapPrint
|
4
|
+
class GeoJSONHandler
|
5
|
+
def initialize(geojson, sw, ne, width, height)
|
6
|
+
@top_lat = ne[:lat]
|
7
|
+
@total_lat = ne[:lat] - sw[:lat]
|
8
|
+
@left_lng = sw[:lng]
|
9
|
+
@total_lng = ne[:lng] - sw[:lng]
|
10
|
+
@height = height
|
11
|
+
@width = width
|
12
|
+
@geojson = JSON[geojson]
|
13
|
+
end
|
14
|
+
|
15
|
+
def process
|
16
|
+
tempfile = Tempfile.new ['geojson', '.png']
|
17
|
+
`convert -size #{@width}x#{@height} xc:transparent #{tempfile.path}`
|
18
|
+
@image = MiniMagick::Image.new tempfile.path
|
19
|
+
|
20
|
+
draw_geojson
|
21
|
+
|
22
|
+
@image.write(tempfile.path)
|
23
|
+
MiniMagick::Image.open(tempfile.path)
|
24
|
+
ensure
|
25
|
+
tempfile.close
|
26
|
+
end
|
27
|
+
|
28
|
+
def draw_geojson
|
29
|
+
if @geojson['type'] == 'Feature'
|
30
|
+
feature(@geojson['geometry'], @geojson['properties'])
|
31
|
+
elsif @geojson['type'] == 'FeatureCollection'
|
32
|
+
feature_collection(@geojson['features'])
|
33
|
+
else
|
34
|
+
puts "Warning, expected type Feature with #{@geojson['type']} inside geometry and drawing properties, like: {'type': 'Feature', 'geometry':#{@geojson.to_json}, 'properties':{'image': 'path/or/url/to/image'}}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def feature(geometry, properties={})
|
39
|
+
case geometry['type']
|
40
|
+
when 'Feature'
|
41
|
+
feature(geometry['geometry'], geometry['properties'])
|
42
|
+
when 'FeatureCollection'
|
43
|
+
feature_collection(geometry['features'])
|
44
|
+
when 'Point'
|
45
|
+
point(geometry, properties['image'])
|
46
|
+
when 'LineString'
|
47
|
+
line_string(geometry, properties)
|
48
|
+
when 'Polygon'
|
49
|
+
polygon(geometry, properties)
|
50
|
+
when 'MultiPoint'
|
51
|
+
multi_point(geometry, properties)
|
52
|
+
when 'MultiLineString'
|
53
|
+
multi_line_string(geometry, properties)
|
54
|
+
when 'MultiPolygon'
|
55
|
+
multi_polygon(geometry, properties)
|
56
|
+
when 'GeometryCollection'
|
57
|
+
geometry_collection(geometry, properties)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def feature_collection(features)
|
62
|
+
features.each do |object|
|
63
|
+
feature(object)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def point(point, image_path)
|
68
|
+
x = get_x(point['coordinates'][1])
|
69
|
+
y = get_y(point['coordinates'][0])
|
70
|
+
|
71
|
+
point_image = MiniMagick::Image.open(image_path)
|
72
|
+
x -= point_image.width / 2
|
73
|
+
y -= point_image.height / 2
|
74
|
+
|
75
|
+
@image.composite(point_image) do |c|
|
76
|
+
c.geometry("+#{x}+#{y}")
|
77
|
+
end.write @image.path
|
78
|
+
end
|
79
|
+
|
80
|
+
def line_string(geometry, properties)
|
81
|
+
properties ||= {}
|
82
|
+
points = geometry['coordinates'].map do |coord|
|
83
|
+
"#{get_x(coord[1])},#{get_y(coord[0])}"
|
84
|
+
end
|
85
|
+
|
86
|
+
draw_command = (0..(points.length - 2)).map do |i|
|
87
|
+
"line #{points[i]} #{points[i+1]}"
|
88
|
+
end.join(' ')
|
89
|
+
|
90
|
+
@image.combine_options do |c|
|
91
|
+
c.draw "#{draw_options(properties)} #{draw_command}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def polygon(geometry, properties)
|
96
|
+
properties ||= {}
|
97
|
+
points = geometry['coordinates'].map do |coord|
|
98
|
+
"#{get_x(coord[1])},#{get_y(coord[0])}"
|
99
|
+
end
|
100
|
+
|
101
|
+
@image.combine_options do |c|
|
102
|
+
c.draw "#{draw_options(properties, false)} polygon #{points.join(' ')}"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
def draw_options(properties, line=true)
|
108
|
+
options = ''
|
109
|
+
if properties['stroke'] || properties['stroke'].nil?
|
110
|
+
options += "stroke #{properties['color'] || '#0033ff'} "
|
111
|
+
options += "stroke-width #{properties['weight'] || 5} "
|
112
|
+
options += "stroke-opacity #{properties['opacity'] || 0.5} "
|
113
|
+
end
|
114
|
+
|
115
|
+
if properties['fill'] || (!line && properties['fill'].nil?)
|
116
|
+
options += "fill #{properties['fillColor'] || '#0033ff'} "
|
117
|
+
options += "fill-opacity #{properties['fillOpacity'] || 0.2} "
|
118
|
+
options += "fill-rule #{properties['fillRule'] || 'evenodd'} "
|
119
|
+
end
|
120
|
+
|
121
|
+
options += "stroke-dasharray #{properties['dashArray']} " if properties['dashArray']
|
122
|
+
options += "stroke-linecap #{properties['lineCap']} " if properties['lineCap']
|
123
|
+
options += "stroke-linejoin #{properties['lineJoin']} " if properties['lineJoin']
|
124
|
+
options
|
125
|
+
end
|
126
|
+
|
127
|
+
def get_x(lng)
|
128
|
+
@width * (lng - @left_lng) / @total_lng;
|
129
|
+
end
|
130
|
+
|
131
|
+
def get_y(lat)
|
132
|
+
@height * (1 - (@top_lat - lat) / @total_lat);
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module MapPrint
|
2
|
+
class LayerHandler
|
3
|
+
PROVIDERS = {
|
4
|
+
'bing' => MapPrint::Providers::Bing,
|
5
|
+
'osm' => MapPrint::Providers::OpenStreetMap
|
6
|
+
}
|
7
|
+
|
8
|
+
def initialize(layers, south_west, north_east, zoom)
|
9
|
+
@layers = layers.sort_by { |layer| layer[:level] }
|
10
|
+
@south_west = MapPrint::LatLng.new(south_west[:lat], south_west[:lng])
|
11
|
+
@north_east = MapPrint::LatLng.new(north_east[:lat], north_east[:lng])
|
12
|
+
@zoom = zoom
|
13
|
+
end
|
14
|
+
|
15
|
+
def process
|
16
|
+
@layers.each do |layer|
|
17
|
+
provider_class = PROVIDERS[layer[:type]]
|
18
|
+
provider = provider_class.new(@south_west, @north_east, @zoom, layer[:urls].first)
|
19
|
+
layer[:image] = provider.download
|
20
|
+
end
|
21
|
+
|
22
|
+
@layers.first[:image].close
|
23
|
+
image = MiniMagick::Image.open(@layers.first[:image].path)
|
24
|
+
tmp_file = Tempfile.new(['layers', '.png'])
|
25
|
+
|
26
|
+
@layers[1..-1].each do |layer|
|
27
|
+
next_image = layer[:image]
|
28
|
+
next_image.close
|
29
|
+
tmp_image = MiniMagick::Image.open(next_image.path)
|
30
|
+
result = image.composite(tmp_image) do |c|
|
31
|
+
c.compose "atop"
|
32
|
+
if layer[:opacity] && layer[:opacity] < 1
|
33
|
+
c.blend layer[:opacity] * 100
|
34
|
+
end
|
35
|
+
end
|
36
|
+
result.write tmp_file.path
|
37
|
+
image = MiniMagick::Image.open(tmp_file.path)
|
38
|
+
end
|
39
|
+
image.write tmp_file.path
|
40
|
+
tmp_file.close
|
41
|
+
tmp_file
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/map_print/osm/tile.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'open-uri'
|
2
|
+
require 'fileutils'
|
2
3
|
|
3
4
|
module MapPrint
|
4
5
|
module OSM
|
5
6
|
class Tile
|
6
|
-
|
7
|
+
|
8
|
+
BIT_TO_QUADKEY = { [false, false] => "0", [false, true] => "1", [true, false] => "2", [true, true] => "3"}
|
7
9
|
|
8
10
|
METERS_PER_PIXELS = {
|
9
11
|
0 => 26862156543.031,
|
@@ -28,17 +30,18 @@ module MapPrint
|
|
28
30
|
}
|
29
31
|
|
30
32
|
class << self
|
33
|
+
|
31
34
|
def meters_per_pixel(zoom)
|
32
35
|
METERS_PER_PIXELS[zoom]
|
33
36
|
end
|
37
|
+
|
34
38
|
end
|
35
39
|
|
36
|
-
def initialize(x, y, z, base_url
|
40
|
+
def initialize(x, y, z, base_url)
|
37
41
|
@base_url = base_url
|
38
42
|
@x = x
|
39
43
|
@y = y
|
40
44
|
@z = z
|
41
|
-
@path = "#{@x}-#{@y}-#{@z}.png"
|
42
45
|
end
|
43
46
|
|
44
47
|
def coords
|
@@ -46,26 +49,14 @@ module MapPrint
|
|
46
49
|
end
|
47
50
|
|
48
51
|
def download
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
@image = open(get_url).read
|
53
|
-
File.open @path, 'wb' do |f|
|
54
|
-
f.write @image
|
52
|
+
unless File.exists?(file_path)
|
53
|
+
content = open(get_url).read
|
54
|
+
write_file(content)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
def delete
|
59
|
-
File.delete @path if File.exist?(@path)
|
60
|
-
end
|
61
|
-
|
62
58
|
def get_pixel_difference(lat_lng)
|
63
59
|
tile_lat_lng = tile_number_to_lat_lng
|
64
|
-
puts '================'
|
65
|
-
puts lat_lng.lat
|
66
|
-
puts lat_lng.lng
|
67
|
-
puts tile_lat_lng
|
68
|
-
puts '================'
|
69
60
|
|
70
61
|
x_pixels = GeoDistance.distance(lat_lng.lat, lat_lng.lng, lat_lng.lat, tile_lat_lng[:lng]).meters.number / METERS_PER_PIXELS[@z]
|
71
62
|
y_pixels = GeoDistance.distance(lat_lng.lat, lat_lng.lng, tile_lat_lng[:lat], lat_lng.lng).meters.number / METERS_PER_PIXELS[@z]
|
@@ -82,9 +73,52 @@ module MapPrint
|
|
82
73
|
{ lat: lat_deg, lng: lon_deg }
|
83
74
|
end
|
84
75
|
|
76
|
+
def file_path
|
77
|
+
File.join(folder_name, "#{@y}.png")
|
78
|
+
end
|
79
|
+
|
80
|
+
def tile2quad
|
81
|
+
quadkey_chars = []
|
82
|
+
|
83
|
+
tx = @x.to_i
|
84
|
+
ty = @y.to_i
|
85
|
+
|
86
|
+
@z.times do
|
87
|
+
quadkey_chars.push BIT_TO_QUADKEY[[ty.odd?, tx.odd?]] # bit order y,x
|
88
|
+
tx >>= 1 ; ty >>= 1
|
89
|
+
end
|
90
|
+
|
91
|
+
quadkey_chars.join.reverse
|
92
|
+
end
|
93
|
+
|
85
94
|
private
|
95
|
+
|
96
|
+
def write_file(content)
|
97
|
+
FileUtils.mkdir_p(folder_name)
|
98
|
+
|
99
|
+
File.open file_path, 'wb' do |f|
|
100
|
+
f.write content
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def provider_name
|
105
|
+
if @base_url =~ /openstreetmap/
|
106
|
+
'osm'
|
107
|
+
elsif @base_url =~ /virtualearth/
|
108
|
+
'bing'
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def folder_name
|
113
|
+
"cache/#{provider_name}/#{@z}/#{@x}"
|
114
|
+
end
|
115
|
+
|
86
116
|
def get_url
|
87
|
-
|
117
|
+
if provider_name == 'osm'
|
118
|
+
@base_url.gsub('${x}', @x.to_s).gsub('${y}', @y.to_s).gsub('${z}', @z.to_s)
|
119
|
+
elsif provider_name == 'bing'
|
120
|
+
@base_url.gsub('${quadkey}', tile2quad)
|
121
|
+
end
|
88
122
|
end
|
89
123
|
end
|
90
124
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module MapPrint
|
2
2
|
module OSM
|
3
3
|
class TileFactory
|
4
|
+
|
4
5
|
def initialize(base_url, sw_lat_lng, ne_lat_lng, zoom)
|
5
6
|
@base_url = base_url
|
6
7
|
@sw_lat_lng = sw_lat_lng
|
@@ -19,6 +20,12 @@ module MapPrint
|
|
19
20
|
@px_offset = offset
|
20
21
|
end
|
21
22
|
|
23
|
+
def download
|
24
|
+
Parallel.each(tiles, in_processes: 20) do |tile|
|
25
|
+
tile.download
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
22
29
|
def tiles
|
23
30
|
return @tiles if @tiles
|
24
31
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module MapPrint
|
4
|
+
module Providers
|
5
|
+
|
6
|
+
class Base
|
7
|
+
|
8
|
+
attr_accessor :provider
|
9
|
+
|
10
|
+
attr_accessor :south_west, :north_east, :zoom
|
11
|
+
|
12
|
+
def initialize(south_west, north_east, zoom, base_url=nil)
|
13
|
+
@south_west, @north_east, @zoom = south_west, north_east, zoom
|
14
|
+
@provider = build_provider(base_url)
|
15
|
+
end
|
16
|
+
|
17
|
+
def build_provider(base_url = nil)
|
18
|
+
raise 'SubClasses must override this method'
|
19
|
+
end
|
20
|
+
|
21
|
+
def download
|
22
|
+
provider.download
|
23
|
+
|
24
|
+
to_image
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def to_image
|
30
|
+
file = Tempfile.new(['map', '.png'])
|
31
|
+
|
32
|
+
MiniMagick::Tool::Montage.new do |montage|
|
33
|
+
montage.mode('concatenate')
|
34
|
+
montage.tile("#{provider.x_size}x#{provider.y_size}")
|
35
|
+
montage.merge! provider.tiles.collect(&:file_path)
|
36
|
+
montage << file.path
|
37
|
+
end
|
38
|
+
|
39
|
+
result_file = Tempfile.new(['result', '.png'])
|
40
|
+
|
41
|
+
image = MiniMagick::Image.new(file.path)
|
42
|
+
width = image.width - provider.px_offset[:left] - provider.px_offset[:right]
|
43
|
+
height = image.height - provider.px_offset[:top] - provider.px_offset[:bottom]
|
44
|
+
|
45
|
+
image.crop("#{width}x#{height}+#{provider.px_offset[:left]}+#{provider.px_offset[:top]}").repage("#{width}x#{height}")
|
46
|
+
image.write result_file.path
|
47
|
+
|
48
|
+
file.close
|
49
|
+
result_file
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module MapPrint
|
2
|
+
module Providers
|
3
|
+
|
4
|
+
class Bing < Base
|
5
|
+
BASE_URL = 'http://ecn.t0.tiles.virtualearth.net/tiles/r${quadkey}.jpeg?g=1515&shading=hill'
|
6
|
+
|
7
|
+
def build_provider(base_url=nil)
|
8
|
+
TileFactory.new(base_url || BASE_URL, 'bing', @south_west, @north_east, @zoom)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module MapPrint
|
2
|
+
module Providers
|
3
|
+
|
4
|
+
class OpenStreetMap < Base
|
5
|
+
BASE_URL = 'http://a.tile.openstreetmap.org/${z}/${x}/${y}.png'
|
6
|
+
|
7
|
+
def build_provider(base_url=nil)
|
8
|
+
TileFactory.new(base_url || BASE_URL, 'osm', @south_west, @north_east, @zoom)
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module MapPrint
|
2
|
+
|
3
|
+
class BingTile < Tile
|
4
|
+
|
5
|
+
BIT_TO_QUADKEY = {
|
6
|
+
[false, false] => '0',
|
7
|
+
[false, true] => '1',
|
8
|
+
[true, false] => '2',
|
9
|
+
[true, true] => '3'
|
10
|
+
}
|
11
|
+
|
12
|
+
def provider_name
|
13
|
+
'bing'
|
14
|
+
end
|
15
|
+
|
16
|
+
def cache_name
|
17
|
+
'bing-' + @base_url.scan(/\/\/(.*?)\/\$/).first.first.gsub('/', '-')
|
18
|
+
rescue
|
19
|
+
'bing'
|
20
|
+
end
|
21
|
+
|
22
|
+
def tile2quad
|
23
|
+
quadkey_chars = []
|
24
|
+
|
25
|
+
tx = @x.to_i
|
26
|
+
ty = @y.to_i
|
27
|
+
|
28
|
+
@z.times do
|
29
|
+
quadkey_chars.push BIT_TO_QUADKEY[[ty.odd?, tx.odd?]] # bit order y,x
|
30
|
+
tx >>= 1 ; ty >>= 1
|
31
|
+
end
|
32
|
+
|
33
|
+
quadkey_chars.join.reverse
|
34
|
+
end
|
35
|
+
|
36
|
+
def tile_url
|
37
|
+
@base_url.gsub('${quadkey}', tile2quad)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MapPrint
|
2
|
+
|
3
|
+
class OSMTile < Tile
|
4
|
+
|
5
|
+
def provider_name
|
6
|
+
'osm'
|
7
|
+
end
|
8
|
+
|
9
|
+
def cache_name
|
10
|
+
'osm-' + @base_url.scan(/\/\/(.*?)\/\$/).first.first.gsub('/', '-')
|
11
|
+
rescue
|
12
|
+
'osm'
|
13
|
+
end
|
14
|
+
|
15
|
+
def tile_url
|
16
|
+
@base_url.gsub('${x}', @x.to_s).gsub('${y}', @y.to_s).gsub('${z}', @z.to_s)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module MapPrint
|
5
|
+
class Tile
|
6
|
+
|
7
|
+
METERS_PER_PIXELS = {
|
8
|
+
0 => 26862156543.031,
|
9
|
+
1 => 8078271.521,
|
10
|
+
2 => 7739135.761,
|
11
|
+
3 => 6919567.881,
|
12
|
+
4 => 889783.941,
|
13
|
+
5 => 214891.9771,
|
14
|
+
6 => 222445.9801721,
|
15
|
+
7 => 161731222.991,
|
16
|
+
8 => 11611.5001,
|
17
|
+
9 => 52305.751,
|
18
|
+
10 => 152.871,
|
19
|
+
11 => 76.4371,
|
20
|
+
12 => 38.2191,
|
21
|
+
13 => 519.1091,
|
22
|
+
14 => 9.55461,
|
23
|
+
15 => 4.77731,
|
24
|
+
16 => 2.38871,
|
25
|
+
17 => 1.19431,
|
26
|
+
18 => 0.5972
|
27
|
+
}
|
28
|
+
|
29
|
+
class << self
|
30
|
+
|
31
|
+
def meters_per_pixel(zoom)
|
32
|
+
METERS_PER_PIXELS[zoom]
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(x, y, z, base_url)
|
38
|
+
@base_url = base_url
|
39
|
+
@x = x
|
40
|
+
@y = y
|
41
|
+
@z = z
|
42
|
+
end
|
43
|
+
|
44
|
+
def coords
|
45
|
+
{x: @x, y: @y, z: @z}
|
46
|
+
end
|
47
|
+
|
48
|
+
def download
|
49
|
+
unless File.exists?(file_path)
|
50
|
+
content = open(tile_url).read
|
51
|
+
write_file(content)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_pixel_difference(lat_lng)
|
56
|
+
tile_lat_lng = tile_number_to_lat_lng
|
57
|
+
puts '================'
|
58
|
+
puts lat_lng.lat
|
59
|
+
puts lat_lng.lng
|
60
|
+
puts tile_lat_lng
|
61
|
+
puts '================'
|
62
|
+
|
63
|
+
x_pixels = GeoDistance.distance(lat_lng.lat, lat_lng.lng, lat_lng.lat, tile_lat_lng[:lng]).meters.number / METERS_PER_PIXELS[@z]
|
64
|
+
y_pixels = GeoDistance.distance(lat_lng.lat, lat_lng.lng, tile_lat_lng[:lat], lat_lng.lng).meters.number / METERS_PER_PIXELS[@z]
|
65
|
+
|
66
|
+
{ x: x_pixels, y: y_pixels }
|
67
|
+
end
|
68
|
+
|
69
|
+
def tile_number_to_lat_lng
|
70
|
+
n = 2.0 ** @z
|
71
|
+
lon_deg = @x / n * 360.0 - 180.0
|
72
|
+
lat_rad = Math::atan(Math::sinh(Math::PI * (1 - 2 * @y / n)))
|
73
|
+
lat_deg = 180.0 * (lat_rad / Math::PI)
|
74
|
+
|
75
|
+
{ lat: lat_deg, lng: lon_deg }
|
76
|
+
end
|
77
|
+
|
78
|
+
def file_path
|
79
|
+
File.join(folder_name, "#{@y}.png")
|
80
|
+
end
|
81
|
+
|
82
|
+
def provider_name
|
83
|
+
raise 'SubClasses should overwrite this method'
|
84
|
+
end
|
85
|
+
|
86
|
+
def cache_name
|
87
|
+
raise 'SubClasses should overwrite this method'
|
88
|
+
end
|
89
|
+
|
90
|
+
def tile_url
|
91
|
+
raise 'SubClasses should overwrite this method'
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def write_file(content)
|
97
|
+
FileUtils.mkdir_p(folder_name)
|
98
|
+
|
99
|
+
File.open file_path, 'wb' do |f|
|
100
|
+
f.write content
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def folder_name
|
105
|
+
"cache/#{cache_name}/#{@z}/#{@x}"
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require_relative 'osm_tile'
|
2
|
+
require_relative 'bing_tile'
|
3
|
+
|
4
|
+
module MapPrint
|
5
|
+
|
6
|
+
class TileFactory
|
7
|
+
|
8
|
+
def initialize(base_url, type, sw_lat_lng, ne_lat_lng, zoom)
|
9
|
+
@base_url = base_url
|
10
|
+
@type = type
|
11
|
+
@sw_lat_lng = sw_lat_lng
|
12
|
+
@ne_lat_lng = ne_lat_lng
|
13
|
+
@zoom = zoom
|
14
|
+
end
|
15
|
+
|
16
|
+
def px_offset
|
17
|
+
return @px_offset if @px_offset
|
18
|
+
offset = {}
|
19
|
+
|
20
|
+
offset[:top] = (ne_offset[:y] * 256).to_i
|
21
|
+
offset[:right] = 256 - (ne_offset[:x] * 256).to_i
|
22
|
+
offset[:bottom] = 256 - (sw_offset[:y] * 256).to_i
|
23
|
+
offset[:left] = (sw_offset[:x] * 256).to_i
|
24
|
+
@px_offset = offset
|
25
|
+
end
|
26
|
+
|
27
|
+
def download
|
28
|
+
Parallel.each(tiles, in_processes: 20) do |tile|
|
29
|
+
tile.download
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def tiles
|
34
|
+
return @tiles if @tiles
|
35
|
+
|
36
|
+
@tiles = []
|
37
|
+
y_array.each do |y|
|
38
|
+
x_array.each do |x|
|
39
|
+
@tiles << tile_class.new(x, y, @zoom, @base_url)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
@tiles
|
44
|
+
end
|
45
|
+
|
46
|
+
def x_size
|
47
|
+
x_array.size
|
48
|
+
end
|
49
|
+
|
50
|
+
def y_size
|
51
|
+
y_array.size
|
52
|
+
end
|
53
|
+
|
54
|
+
def ne_offset
|
55
|
+
@ne_lat_lng.get_slippy_map_tile_number(@zoom)[:offset]
|
56
|
+
end
|
57
|
+
|
58
|
+
def sw_offset
|
59
|
+
@sw_lat_lng.get_slippy_map_tile_number(@zoom)[:offset]
|
60
|
+
end
|
61
|
+
|
62
|
+
def x_array
|
63
|
+
return @x_array if @x_array
|
64
|
+
|
65
|
+
x1 = @sw_lat_lng.get_slippy_map_tile_number(@zoom)[:x]
|
66
|
+
x2 = @ne_lat_lng.get_slippy_map_tile_number(@zoom)[:x]
|
67
|
+
@x_array ||= x1 < x2 ? x1..x2 : (x2..x1).to_a
|
68
|
+
end
|
69
|
+
|
70
|
+
def y_array
|
71
|
+
return @y_array if @y_array
|
72
|
+
|
73
|
+
y1 = @sw_lat_lng.get_slippy_map_tile_number(@zoom)[:y]
|
74
|
+
y2 = @ne_lat_lng.get_slippy_map_tile_number(@zoom)[:y]
|
75
|
+
@y_array ||= y1 < y2 ? y1..y2 : (y2..y1).to_a
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def tile_class
|
81
|
+
if @type == 'osm'
|
82
|
+
OSMTile
|
83
|
+
elsif @type =~ 'bing'
|
84
|
+
BingTile
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
data/lib/map_print/version.rb
CHANGED
data/lib/map_print.rb
CHANGED
@@ -1,17 +1,8 @@
|
|
1
|
-
require 'map_print/version'
|
2
1
|
require 'prawn'
|
3
2
|
require 'mini_magick'
|
4
3
|
require 'geo-distance'
|
4
|
+
require 'parallel'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
require 'map_print/core'
|
11
|
-
|
12
|
-
|
13
|
-
module MapPrint
|
14
|
-
def self.print(path)
|
15
|
-
MapPrint::Core.print(path)
|
16
|
-
end
|
17
|
-
end
|
6
|
+
require_relative 'base'
|
7
|
+
require_relative 'map_print/version'
|
8
|
+
require_relative 'map_print/core'
|
data/map_print.gemspec
CHANGED
@@ -23,14 +23,17 @@ Gem::Specification.new do |spec|
|
|
23
23
|
end
|
24
24
|
|
25
25
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
-
spec.bindir = '
|
27
|
-
spec.executables = spec.files.grep(%r{^
|
26
|
+
spec.bindir = 'bin'
|
27
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ['lib']
|
29
29
|
|
30
30
|
spec.add_development_dependency 'bundler', '~> 1.10'
|
31
31
|
spec.add_development_dependency 'rake', '~> 10.0'
|
32
32
|
spec.add_development_dependency 'minitest', '~> 5.8'
|
33
33
|
spec.add_dependency 'prawn', '~> 2.0'
|
34
|
+
spec.add_dependency 'prawn-fast-png', '~> 0.2.3'
|
34
35
|
spec.add_dependency 'mini_magick', '~> 4.3'
|
35
36
|
spec.add_dependency 'geo-distance', '~> 0.1'
|
37
|
+
spec.add_dependency 'parallel', '~> 1.6'
|
38
|
+
spec.add_dependency 'thor', '~> 0.19'
|
36
39
|
end
|
data/marker.png
ADDED
Binary file
|
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: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andreas Fast
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '2.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: prawn-fast-png
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.2.3
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.2.3
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: mini_magick
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,11 +108,42 @@ dependencies:
|
|
94
108
|
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0.1'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: parallel
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.6'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.6'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: thor
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.19'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.19'
|
97
139
|
description: MapPrint allows to export many map sources and GeoJSON objects to a pdf
|
98
140
|
file, along with legend and text elements to create rich maps.
|
99
141
|
email:
|
100
142
|
- andis.machine@gmail.com
|
101
|
-
executables:
|
143
|
+
executables:
|
144
|
+
- console
|
145
|
+
- map_print
|
146
|
+
- setup
|
102
147
|
extensions: []
|
103
148
|
extra_rdoc_files: []
|
104
149
|
files:
|
@@ -113,13 +158,28 @@ files:
|
|
113
158
|
- bin/console
|
114
159
|
- bin/map_print
|
115
160
|
- bin/setup
|
161
|
+
- lib/base.rb
|
116
162
|
- lib/map_print.rb
|
117
163
|
- lib/map_print/core.rb
|
164
|
+
- lib/map_print/geo_json_handler.rb
|
165
|
+
- lib/map_print/image_handler.rb
|
118
166
|
- lib/map_print/lat_lng.rb
|
167
|
+
- lib/map_print/layer_handler.rb
|
168
|
+
- lib/map_print/legend_handler.rb
|
119
169
|
- lib/map_print/osm/tile.rb
|
120
170
|
- lib/map_print/osm/tile_factory.rb
|
171
|
+
- lib/map_print/providers/base.rb
|
172
|
+
- lib/map_print/providers/bing.rb
|
173
|
+
- lib/map_print/providers/open_street_map.rb
|
174
|
+
- lib/map_print/scalebar_handler.rb
|
175
|
+
- lib/map_print/text_handler.rb
|
176
|
+
- lib/map_print/tiles/bing_tile.rb
|
177
|
+
- lib/map_print/tiles/osm_tile.rb
|
178
|
+
- lib/map_print/tiles/tile.rb
|
179
|
+
- lib/map_print/tiles/tile_factory.rb
|
121
180
|
- lib/map_print/version.rb
|
122
181
|
- map_print.gemspec
|
182
|
+
- marker.png
|
123
183
|
homepage: http://github.com/afast/map_print
|
124
184
|
licenses:
|
125
185
|
- MIT
|