map_print 0.1.0 → 0.2.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 +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
|