mapknitter-exporter 1.0.9 → 1.0.10
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 +5 -5
- data/lib/cartagen.rb +32 -38
- data/lib/{mapknitterExporter.rb → exporter.rb} +152 -152
- data/lib/mapknitter_exporter.rb +2 -0
- metadata +7 -8
- data/lib/mapknitter-exporter.rb +0 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: b7375456e31a28ea56a97f708814a8873b6609fad954965a42e1d83ee90c1d95
|
|
4
|
+
data.tar.gz: 99d12f79f66187f338f2c38658d7b237f683a9cfc60a7169466cb205d2732b8b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: af46d5776b301f7eac1f99c128606ee628476638b6b337e0903978793fa79f5878bf576b890ce808019bc7fefbc139e1483c65b9d784d16e7e364337cd8f1381
|
|
7
|
+
data.tar.gz: c2f23ed6de2fa5012d5d25bfd4dfc4adfd77af63947524af7ccc4eb14f91e90584018fcd89ffd1674319a9282eccdfa1625cf37223f4a00c163854eb1a7ce4fc
|
data/lib/cartagen.rb
CHANGED
|
@@ -1,67 +1,61 @@
|
|
|
1
1
|
class Cartagen
|
|
2
|
-
|
|
3
2
|
def self.chop_word(string)
|
|
4
3
|
word = string.split(' ')[0]
|
|
5
|
-
string.slice!(word+' ')
|
|
4
|
+
string.slice!(word + ' ')
|
|
6
5
|
word
|
|
7
6
|
end
|
|
8
7
|
|
|
9
|
-
def self.spherical_mercator_lon_to_x(lon,scale=
|
|
10
|
-
(lon*scale)/180
|
|
8
|
+
def self.spherical_mercator_lon_to_x(lon, scale = 10_000)
|
|
9
|
+
(lon * scale) / 180
|
|
11
10
|
end
|
|
12
11
|
|
|
13
|
-
def self.spherical_mercator_x_to_lon(
|
|
14
|
-
(
|
|
12
|
+
def self.spherical_mercator_x_to_lon(x_axis, scale = 10_000)
|
|
13
|
+
(x_axis / scale) * 180
|
|
15
14
|
end
|
|
16
15
|
|
|
17
|
-
def self.spherical_mercator_lat_to_y(lat,scale=
|
|
18
|
-
#180/Math::PI * Math.log(Math.tan(Math::PI/4+lat*(Math::PI/180)/2)) * scale_factor
|
|
16
|
+
def self.spherical_mercator_lat_to_y(lat, scale = 10_000)
|
|
17
|
+
# 180/Math::PI * Math.log(Math.tan(Math::PI/4+lat*(Math::PI/180)/2)) * scale_factor
|
|
19
18
|
y = Math.log(Math.tan((90 + lat) * Math::PI / 360)) / (Math::PI / 180)
|
|
20
19
|
y * scale / 180
|
|
21
20
|
end
|
|
22
21
|
|
|
23
|
-
def self.spherical_mercator_y_to_lat(
|
|
24
|
-
#180/Math::PI * (2 * Math.atan(Math.exp(y/scale_factor*Math::PI/180)) - Math::PI/2)
|
|
25
|
-
lat = (
|
|
26
|
-
180/Math::PI * (2 * Math.atan(Math.exp(lat * Math::PI / 180)) - Math::PI / 2)
|
|
22
|
+
def self.spherical_mercator_y_to_lat(y_axis, scale = 10_000)
|
|
23
|
+
# 180/Math::PI * (2 * Math.atan(Math.exp(y/scale_factor*Math::PI/180)) - Math::PI/2)
|
|
24
|
+
lat = (y_axis / scale) * 180
|
|
25
|
+
180 / Math::PI * (2 * Math.atan(Math.exp(lat * Math::PI / 180)) - Math::PI / 2)
|
|
27
26
|
end
|
|
28
|
-
|
|
27
|
+
|
|
29
28
|
# collects coastline ways into collected_way relations;
|
|
30
29
|
# see http://wiki.openstreetmap.org/wiki/Relations/Proposed/Collected_Ways
|
|
31
30
|
def self.collect_ways(features)
|
|
32
|
-
# collected_ways variable unused review this function
|
|
33
|
-
collected_ways = []
|
|
34
31
|
nodes = {}
|
|
35
32
|
features['osm']['node'].each do |node|
|
|
36
33
|
nodes[node['id']] = node
|
|
37
34
|
end
|
|
38
35
|
features['osm']['way'].each do |way|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
next unless way['tag']
|
|
37
|
+
|
|
38
|
+
coastline = false
|
|
39
|
+
way['tag'].each do |tag|
|
|
40
|
+
if tag['k'] == 'natural' && tag['v'] == 'coastline'
|
|
41
|
+
coastline = true
|
|
42
|
+
break
|
|
46
43
|
end
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
end
|
|
61
|
-
end
|
|
44
|
+
end
|
|
45
|
+
next unless coastline
|
|
46
|
+
|
|
47
|
+
relation = {}
|
|
48
|
+
relation['way'] = []
|
|
49
|
+
relation['way'] << way
|
|
50
|
+
# are a way's nodes ordered? yes.
|
|
51
|
+
# check each way to see if it has a first or last node in common with 'way'
|
|
52
|
+
features['osm']['way'].each do |subway|
|
|
53
|
+
if subway['nd'].first['ref'] == nodes[way['nd'].first['ref']] || subway['nd'].first['ref'] == nodes[way['nd'].last['ref']] || subway['nd'].last['ref'] == nodes[way['nd'].first['ref']] || subway['nd'].last['ref'] == nodes[way['nd'].last['ref']]
|
|
54
|
+
# we have a match!
|
|
55
|
+
|
|
56
|
+
break
|
|
62
57
|
end
|
|
63
58
|
end
|
|
64
59
|
end
|
|
65
60
|
end
|
|
66
|
-
|
|
67
61
|
end
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
require_relative 'cartagen'
|
|
2
|
+
require_relative 'mapknitter_exporter'
|
|
3
3
|
require 'open3'
|
|
4
|
+
require 'net/http'
|
|
5
|
+
require "shellwords"
|
|
6
|
+
require "fileutils"
|
|
4
7
|
|
|
5
8
|
class MapKnitterExporter
|
|
6
|
-
|
|
7
9
|
def self.ulimit
|
|
8
10
|
# use ulimit to restrict to 7200 CPU seconds and 5gb virtual memory, and 5gB file storage:
|
|
9
|
-
#"ulimit -t 7200 && ulimit -v 5000000 && ulimit -f 5000000 && "
|
|
11
|
+
# "ulimit -t 7200 && ulimit -v 5000000 && ulimit -f 5000000 && "
|
|
10
12
|
"ulimit -t 14400 && ulimit -v 5000000 && ulimit -f 10000000 && nice -n 19 "
|
|
11
13
|
end
|
|
12
14
|
|
|
@@ -26,26 +28,63 @@ class MapKnitterExporter
|
|
|
26
28
|
########################
|
|
27
29
|
## Run on each image:
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
def self.image_magick_manipulation(height, width, mask_location, local_location, completed_local_location, maxdimension, maskpoints, masked_local_location, points)
|
|
32
|
+
image_magick = "convert "
|
|
33
|
+
image_magick += "-contrast-stretch 0 "
|
|
34
|
+
image_magick += local_location.shellescape + " "
|
|
35
|
+
image_magick += "-crop " + maxdimension.to_i.to_s + "x" + maxdimension.to_i.to_s + "+0+0! "
|
|
36
|
+
image_magick += "-flatten "
|
|
37
|
+
image_magick += "-distort Perspective '" + points + "' "
|
|
38
|
+
image_magick += "-flatten "
|
|
39
|
+
image_magick += if width > height
|
|
40
|
+
"-crop " + width + "x" + width + "+0+0\! "
|
|
41
|
+
else
|
|
42
|
+
"-crop " + height + "x" + height + "+0+0\! "
|
|
43
|
+
end
|
|
44
|
+
image_magick += "+repage "
|
|
45
|
+
image_magick += completed_local_location
|
|
46
|
+
puts image_magick
|
|
47
|
+
system(ulimit + image_magick)
|
|
48
|
+
|
|
49
|
+
# create a mask (later we can blur edges here)
|
|
50
|
+
image_magick2 = 'convert +antialias '
|
|
51
|
+
image_magick2 += if width > height
|
|
52
|
+
"-size " + width + "x" + width + " "
|
|
53
|
+
else
|
|
54
|
+
"-size " + height + "x" + height + " "
|
|
55
|
+
end
|
|
56
|
+
# attempt at blurred edges in masking, but I've given up, as gdal_merge doesn't seem to respect variable-opacity alpha channels
|
|
57
|
+
image_magick2 += ' xc:none -draw "fill black stroke red stroke-width 30 polyline '
|
|
58
|
+
image_magick2 += maskpoints + '" '
|
|
59
|
+
image_magick2 += ' -alpha set -channel A -transparent red -blur 0x8 -channel R -evaluate set 0 +channel ' + mask_location
|
|
60
|
+
# image_magick2 += ' xc:none -draw "fill black stroke none polyline '
|
|
61
|
+
# image_magick2 += maskpoints + '" '
|
|
62
|
+
# image_magick2 += ' '+mask_location
|
|
63
|
+
puts image_magick2
|
|
64
|
+
system(ulimit + image_magick2)
|
|
65
|
+
|
|
66
|
+
image_magick3 = 'composite ' + mask_location + ' ' + completed_local_location + ' -compose DstIn -alpha Set ' + masked_local_location
|
|
67
|
+
puts image_magick3
|
|
68
|
+
system(ulimit + image_magick3)
|
|
69
|
+
end
|
|
32
70
|
|
|
71
|
+
# pixels per meter = pxperm
|
|
72
|
+
def self.generate_perspectival_distort(pxperm, id, nodes_array, image_file_name, img_url, height, width, collection_id) # rubocop:disable Metrics/AbcSize
|
|
33
73
|
image_file_name ||= img_url.split('/').last
|
|
34
|
-
# everything in -working/ can be deleted;
|
|
74
|
+
# everything in -working/ can be deleted;
|
|
35
75
|
# this is just so we can use the files locally outside of s3
|
|
36
76
|
working_directory = get_working_directory(collection_id)
|
|
37
|
-
Dir.mkdir(working_directory) unless
|
|
38
|
-
require "shellwords"
|
|
77
|
+
Dir.mkdir(working_directory) unless File.exist?(working_directory) && File.directory?(working_directory)
|
|
39
78
|
local_location = "#{working_directory}w#{id}-#{image_file_name}"
|
|
40
79
|
directory = warps_directory(collection_id)
|
|
41
|
-
Dir.mkdir(directory) unless
|
|
42
|
-
completed_local_location = directory + 'w' + id.to_s+'.png'
|
|
80
|
+
Dir.mkdir(directory) unless File.exist?(directory) && File.directory?(directory)
|
|
81
|
+
completed_local_location = directory + 'w' + id.to_s + '.png'
|
|
43
82
|
|
|
44
83
|
# everything -masked.png can be deleted
|
|
45
84
|
masked_local_location = directory + 'w' + id.to_s + '-masked.png'
|
|
46
85
|
# everything -mask.png can be deleted
|
|
47
86
|
mask_location = directory + 'w' + id.to_s + '-mask.png'
|
|
48
|
-
#completed_local_location = directory+id.to_s+'.tif'
|
|
87
|
+
# completed_local_location = directory+id.to_s+'.tif'
|
|
49
88
|
# know everything -unwarped can be deleted
|
|
50
89
|
geotiff_location = directory + 'w' + id.to_s + '-geo-unwarped.tif'
|
|
51
90
|
# everything -geo WITH AN ID could be deleted, but there is a feature request to preserve these
|
|
@@ -62,24 +101,23 @@ class MapKnitterExporter
|
|
|
62
101
|
westmost = node['lon'].to_f if node['lon'].to_f < westmost
|
|
63
102
|
eastmost = node['lon'].to_f if node['lon'].to_f > eastmost
|
|
64
103
|
end
|
|
65
|
-
|
|
66
|
-
scale =
|
|
67
|
-
y1 = pxperm.to_f * Cartagen.spherical_mercator_lat_to_y(northmost,scale)
|
|
68
|
-
x1 = pxperm.to_f * Cartagen.spherical_mercator_lon_to_x(westmost,scale)
|
|
69
|
-
y2 = pxperm.to_f * Cartagen.spherical_mercator_lat_to_y(southmost,scale)
|
|
70
|
-
x2 = pxperm.to_f * Cartagen.spherical_mercator_lon_to_x(eastmost,scale)
|
|
104
|
+
|
|
105
|
+
scale = 20_037_508.34
|
|
106
|
+
y1 = pxperm.to_f * Cartagen.spherical_mercator_lat_to_y(northmost, scale)
|
|
107
|
+
x1 = pxperm.to_f * Cartagen.spherical_mercator_lon_to_x(westmost, scale)
|
|
108
|
+
y2 = pxperm.to_f * Cartagen.spherical_mercator_lat_to_y(southmost, scale)
|
|
109
|
+
x2 = pxperm.to_f * Cartagen.spherical_mercator_lon_to_x(eastmost, scale)
|
|
71
110
|
|
|
72
111
|
# should determine if it's stored in s3 or locally:
|
|
73
|
-
if
|
|
112
|
+
if img_url.slice(0, 4) == 'http'
|
|
74
113
|
host = img_url.split('//').last.split('/').first
|
|
75
|
-
Net::HTTP.start(host)
|
|
114
|
+
Net::HTTP.start(host) do |http|
|
|
76
115
|
resp = http.get(img_url)
|
|
77
|
-
open(local_location, "wb")
|
|
116
|
+
open(local_location, "wb") do |file| # rubocop:disable Security/Open
|
|
78
117
|
file.write(resp.body)
|
|
79
|
-
|
|
80
|
-
|
|
118
|
+
end
|
|
119
|
+
end
|
|
81
120
|
else
|
|
82
|
-
require "fileutils"
|
|
83
121
|
FileUtils.cp(img_url, local_location)
|
|
84
122
|
end
|
|
85
123
|
|
|
@@ -87,34 +125,34 @@ class MapKnitterExporter
|
|
|
87
125
|
maskpoints = ""
|
|
88
126
|
coordinates = ""
|
|
89
127
|
first = true
|
|
90
|
-
|
|
91
|
-
#EXIF orientation values:
|
|
92
|
-
#Value 0th Row 0th Column
|
|
93
|
-
#1 top left side
|
|
94
|
-
#2 top right side
|
|
95
|
-
#3 bottom right side
|
|
96
|
-
#4 bottom left side
|
|
97
|
-
#5 left side top
|
|
98
|
-
#6 right side top
|
|
99
|
-
#7 right side bottom
|
|
100
|
-
#8 left side bottom
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
128
|
+
|
|
129
|
+
# EXIF orientation values:
|
|
130
|
+
# Value 0th Row 0th Column
|
|
131
|
+
# 1 top left side
|
|
132
|
+
# 2 top right side
|
|
133
|
+
# 3 bottom right side
|
|
134
|
+
# 4 bottom left side
|
|
135
|
+
# 5 left side top
|
|
136
|
+
# 6 right side top
|
|
137
|
+
# 7 right side bottom
|
|
138
|
+
# 8 left side bottom
|
|
139
|
+
|
|
140
|
+
rotation = `identify -format %[exif:Orientation] #{local_location.shellescape}`.to_i
|
|
141
|
+
# stdin, stdout, stderr = Open3.popen3('identify -format %[exif:Orientation] #{local_location}')
|
|
142
|
+
# rotation = stdout.readlines.first.to_s.to_i
|
|
143
|
+
# puts stderr.readlines
|
|
106
144
|
|
|
107
145
|
if rotation == 6
|
|
108
146
|
puts 'rotated CCW'
|
|
109
|
-
source_corners = source_corners = [[0,height],[0,0],[width,0],[width,height]]
|
|
147
|
+
source_corners = source_corners = [[0, height], [0, 0], [width, 0], [width, height]]
|
|
110
148
|
elsif rotation == 8
|
|
111
149
|
puts 'rotated CW'
|
|
112
|
-
source_corners = [[width,0],[width,height],[0,height],[0,0]]
|
|
150
|
+
source_corners = [[width, 0], [width, height], [0, height], [0, 0]]
|
|
113
151
|
elsif rotation == 3
|
|
114
152
|
puts 'rotated 180 deg'
|
|
115
|
-
source_corners = [[width,height],[0,height],[0,0],[width,0]]
|
|
153
|
+
source_corners = [[width, height], [0, height], [0, 0], [width, 0]]
|
|
116
154
|
else
|
|
117
|
-
source_corners = [[0,0],[width,0],[width,height],[0,height]]
|
|
155
|
+
source_corners = [[0, 0], [width, 0], [width, height], [0, height]]
|
|
118
156
|
end
|
|
119
157
|
|
|
120
158
|
maxdimension = 0
|
|
@@ -125,15 +163,15 @@ class MapKnitterExporter
|
|
|
125
163
|
ny1 = corner[1]
|
|
126
164
|
nx2 = -x1 + (pxperm.to_f * Cartagen.spherical_mercator_lon_to_x(node['lon'].to_f, scale.to_f))
|
|
127
165
|
ny2 = y1 - (pxperm.to_f * Cartagen.spherical_mercator_lat_to_y(node['lat'].to_f, scale.to_f))
|
|
128
|
-
|
|
129
|
-
points
|
|
130
|
-
maskpoints
|
|
166
|
+
|
|
167
|
+
points += ' ' unless first
|
|
168
|
+
maskpoints += ' ' unless first
|
|
131
169
|
points = points + nx1.to_s + ',' + ny1.to_s + ' ' + nx2.to_i.to_s + ',' + ny2.to_i.to_s
|
|
132
170
|
maskpoints = maskpoints + nx2.to_i.to_s + ',' + ny2.to_i.to_s
|
|
133
171
|
first = false
|
|
134
172
|
# we need to find an origin; find northwestern-most point
|
|
135
|
-
coordinates = coordinates+' -gcp '+nx2.to_s+', '+ny2.to_s+', '+node['lon'].to_s + ', ' + node['lat'].to_s
|
|
136
|
-
|
|
173
|
+
coordinates = coordinates + ' -gcp ' + nx2.to_s + ', ' + ny2.to_s + ', ' + node['lon'].to_s + ', ' + node['lat'].to_s
|
|
174
|
+
|
|
137
175
|
# identify largest dimension to set canvas size for ImageMagick:
|
|
138
176
|
maxdimension = nx1.to_i if maxdimension < nx1.to_i
|
|
139
177
|
maxdimension = ny1.to_i if maxdimension < ny1.to_i
|
|
@@ -142,71 +180,35 @@ class MapKnitterExporter
|
|
|
142
180
|
end
|
|
143
181
|
|
|
144
182
|
# close mask polygon:
|
|
145
|
-
maskpoints
|
|
146
|
-
|
|
147
|
-
|
|
183
|
+
maskpoints += ' '
|
|
184
|
+
nx2 = -x1 + (pxperm.to_f * Cartagen.spherical_mercator_lon_to_x(nodes_array.first['lon'].to_f, scale.to_f))
|
|
185
|
+
ny2 = y1 - (pxperm.to_f * Cartagen.spherical_mercator_lat_to_y(nodes_array.first['lat'].to_f, scale.to_f))
|
|
148
186
|
maskpoints = maskpoints + nx2.to_i.to_s + ',' + ny2.to_i.to_s
|
|
149
187
|
|
|
150
|
-
height = (y1-y2).to_i.to_s
|
|
151
|
-
width = (-x1+x2).to_i.to_s
|
|
188
|
+
height = (y1 - y2).to_i.to_s
|
|
189
|
+
width = (-x1 + x2).to_i.to_s
|
|
152
190
|
|
|
153
191
|
# http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=11319
|
|
154
192
|
# http://www.imagemagick.org/discourse-server/viewtopic.php?f=3&t=8764
|
|
155
|
-
# read about equalization
|
|
193
|
+
# read about equalization
|
|
156
194
|
# -equalize
|
|
157
195
|
# -contrast-stretch 0
|
|
158
196
|
|
|
159
|
-
|
|
160
|
-
imageMagick += "-contrast-stretch 0 "
|
|
161
|
-
imageMagick += local_location.shellescape+" "
|
|
162
|
-
imageMagick += "-crop "+maxdimension.to_i.to_s+"x"+maxdimension.to_i.to_s+"+0+0! "
|
|
163
|
-
imageMagick += "-flatten "
|
|
164
|
-
imageMagick += "-distort Perspective '"+points+"' "
|
|
165
|
-
imageMagick += "-flatten "
|
|
166
|
-
if width > height
|
|
167
|
-
imageMagick += "-crop "+width+"x"+width+"+0+0\! "
|
|
168
|
-
else
|
|
169
|
-
imageMagick += "-crop "+height+"x"+height+"+0+0\! "
|
|
170
|
-
end
|
|
171
|
-
imageMagick += "+repage "
|
|
172
|
-
imageMagick += completed_local_location
|
|
173
|
-
puts imageMagick
|
|
174
|
-
system(self.ulimit+imageMagick)
|
|
197
|
+
image_magick_manipulation(height, width, mask_location, local_location, completed_local_location, maxdimension, maskpoints, masked_local_location, points)
|
|
175
198
|
|
|
176
|
-
|
|
177
|
-
imageMagick2 = 'convert +antialias '
|
|
178
|
-
if width > height
|
|
179
|
-
imageMagick2 += "-size "+width+"x"+width+" "
|
|
180
|
-
else
|
|
181
|
-
imageMagick2 += "-size "+height+"x"+height+" "
|
|
182
|
-
end
|
|
183
|
-
# attempt at blurred edges in masking, but I've given up, as gdal_merge doesn't seem to respect variable-opacity alpha channels
|
|
184
|
-
imageMagick2 += ' xc:none -draw "fill black stroke red stroke-width 30 polyline '
|
|
185
|
-
imageMagick2 += maskpoints + '" '
|
|
186
|
-
imageMagick2 += ' -alpha set -channel A -transparent red -blur 0x8 -channel R -evaluate set 0 +channel '+mask_location
|
|
187
|
-
#imageMagick2 += ' xc:none -draw "fill black stroke none polyline '
|
|
188
|
-
#imageMagick2 += maskpoints + '" '
|
|
189
|
-
#imageMagick2 += ' '+mask_location
|
|
190
|
-
puts imageMagick2
|
|
191
|
-
system(self.ulimit+imageMagick2)
|
|
192
|
-
|
|
193
|
-
imageMagick3 = 'composite '+mask_location+' '+completed_local_location+' -compose DstIn -alpha Set '+masked_local_location
|
|
194
|
-
puts imageMagick3
|
|
195
|
-
system(self.ulimit+imageMagick3)
|
|
196
|
-
|
|
197
|
-
gdal_translate = "gdal_translate -of GTiff -a_srs EPSG:4326 "+coordinates+' -co "TILED=NO" '+masked_local_location+' '+geotiff_location
|
|
199
|
+
gdal_translate = "gdal_translate -of GTiff -a_srs EPSG:4326 " + coordinates + ' -co "TILED=NO" ' + masked_local_location + ' ' + geotiff_location
|
|
198
200
|
puts gdal_translate
|
|
199
|
-
system(
|
|
200
|
-
|
|
201
|
-
#gdalwarp = 'gdalwarp -srcnodata "255" -dstnodata 0 -cblend 30 -of GTiff -t_srs EPSG:4326 '+geotiff_location+' '+warped_geotiff_location
|
|
202
|
-
gdalwarp = 'gdalwarp -of GTiff -t_srs EPSG:4326 '+geotiff_location+' '+warped_geotiff_location
|
|
201
|
+
system(ulimit + gdal_translate)
|
|
202
|
+
|
|
203
|
+
# gdalwarp = 'gdalwarp -srcnodata "255" -dstnodata 0 -cblend 30 -of GTiff -t_srs EPSG:4326 '+geotiff_location+' '+warped_geotiff_location
|
|
204
|
+
gdalwarp = 'gdalwarp -of GTiff -t_srs EPSG:4326 ' + geotiff_location + ' ' + warped_geotiff_location
|
|
203
205
|
puts gdalwarp
|
|
204
|
-
system(
|
|
206
|
+
system(ulimit + gdalwarp)
|
|
205
207
|
|
|
206
208
|
# deletions could happen here; do it in distinct method so we can run it independently
|
|
207
209
|
delete_temp_files(id)
|
|
208
210
|
|
|
209
|
-
[x1,y1]
|
|
211
|
+
[x1, y1]
|
|
210
212
|
end
|
|
211
213
|
|
|
212
214
|
########################
|
|
@@ -214,41 +216,41 @@ class MapKnitterExporter
|
|
|
214
216
|
|
|
215
217
|
# distort all warpables, returns upper left corner coords in x,y
|
|
216
218
|
def self.distort_warpables(scale, images, export, id)
|
|
217
|
-
|
|
218
219
|
puts '> generating geotiffs of each warpable in GDAL'
|
|
219
220
|
lowest_x = 0
|
|
220
221
|
lowest_y = 0
|
|
221
222
|
all_coords = []
|
|
222
223
|
current = 0
|
|
223
224
|
images.each_with_index do |image, index|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
225
|
+
current += 1
|
|
226
|
+
|
|
227
|
+
export.status = 'warping ' + current.to_s + ' of ' + images.length.to_s
|
|
228
|
+
puts 'warping ' + current.to_s + ' of ' + images.length.to_s
|
|
229
|
+
export.save
|
|
230
|
+
##
|
|
231
|
+
image['id'] = image['id'] || index
|
|
232
|
+
|
|
233
|
+
img_coords = generate_perspectival_distort(
|
|
234
|
+
scale,
|
|
235
|
+
image['id'],
|
|
236
|
+
image['nodes'],
|
|
237
|
+
image['image_file_name'],
|
|
238
|
+
image['src'],
|
|
239
|
+
image['height'].to_i,
|
|
240
|
+
image['width'].to_i,
|
|
241
|
+
id # collection id
|
|
242
|
+
)
|
|
243
|
+
puts '- ' + img_coords.to_s
|
|
244
|
+
all_coords << img_coords
|
|
245
|
+
|
|
246
|
+
lowest_x = img_coords.first if img_coords.first < lowest_x || lowest_x.zero?
|
|
247
|
+
lowest_y = img_coords.last if img_coords.last < lowest_y || lowest_y.zero?
|
|
246
248
|
end
|
|
247
249
|
[lowest_x, lowest_y, all_coords]
|
|
248
250
|
end
|
|
249
251
|
|
|
250
252
|
# generate a tiff from all warpable images in this set
|
|
251
|
-
def self.generate_composite_tiff(
|
|
253
|
+
def self.generate_composite_tiff(_coords, _origin, warpables, id, ordered)
|
|
252
254
|
directory = "public/warps/#{id}/"
|
|
253
255
|
composite_location = directory + id.to_s + '.tif'
|
|
254
256
|
minlat = nil
|
|
@@ -258,36 +260,35 @@ class MapKnitterExporter
|
|
|
258
260
|
warpables.each_with_index do |warpable, i|
|
|
259
261
|
warpable['nodes'].each do |n|
|
|
260
262
|
puts "warpable: ", n['id'], i, n['lat'], n['lon']
|
|
261
|
-
minlat = n['lat'].to_f if minlat
|
|
262
|
-
minlon = n['lon'].to_f if minlon
|
|
263
|
-
maxlat = n['lat'].to_f if maxlat
|
|
264
|
-
maxlon = n['lon'].to_f if maxlon
|
|
263
|
+
minlat = n['lat'].to_f if minlat.nil? || n['lat'].to_f < minlat
|
|
264
|
+
minlon = n['lon'].to_f if minlon.nil? || n['lon'].to_f < minlon
|
|
265
|
+
maxlat = n['lat'].to_f if maxlat.nil? || n['lat'].to_f > maxlat
|
|
266
|
+
maxlon = n['lon'].to_f if maxlon.nil? || n['lon'].to_f > maxlon
|
|
265
267
|
end
|
|
266
268
|
end
|
|
267
269
|
puts "minlat #{minlat}, minlon #{minlon}, maxlat #{maxlat}, maxlon #{maxlon}"
|
|
268
|
-
|
|
269
|
-
if ordered != true && warpables.first.keys.include?('poly_area')
|
|
270
|
+
if ordered != true && warpables.first.key?('poly_area')
|
|
270
271
|
# sort by area; this would be overridden by a provided order
|
|
271
|
-
warpables = warpables.sort{ |a,b| b['poly_area'] <=> a['poly_area'] }
|
|
272
|
+
warpables = warpables.sort { |a, b| b['poly_area'] <=> a['poly_area'] }
|
|
272
273
|
end
|
|
273
274
|
geotiffs = ""
|
|
274
275
|
warpables.each do |warpable|
|
|
275
276
|
wid = "w" + warpable['id'].to_s
|
|
276
|
-
geotiffs += ' '+directory+wid+'.tif'
|
|
277
|
+
geotiffs += ' ' + directory + wid + '.tif'
|
|
277
278
|
end
|
|
278
|
-
gdalwarp = "gdalwarp -
|
|
279
|
+
gdalwarp = "gdalwarp -te_srs EPSG:4326 -t_srs EPSG:4326 -te #{minlon} #{minlat} #{maxlon} #{maxlat} #{geotiffs} #{directory}#{id}.tif"
|
|
279
280
|
puts gdalwarp
|
|
280
|
-
system(
|
|
281
|
+
system(ulimit + gdalwarp)
|
|
281
282
|
composite_location
|
|
282
283
|
end
|
|
283
284
|
|
|
284
285
|
# generates a tileset at public/tms/<id>/
|
|
285
286
|
def self.generate_tiles(key, id)
|
|
286
287
|
key = "AIzaSyAOLUQngEmJv0_zcG1xkGq-CXIPpLQY8iQ" if key == "" # ugh, let's clean this up!
|
|
287
|
-
key
|
|
288
|
-
gdal2tiles = "gdal2tiles.py -k --s_srs EPSG:
|
|
288
|
+
key ||= "AIzaSyAOLUQngEmJv0_zcG1xkGq-CXIPpLQY8iQ"
|
|
289
|
+
gdal2tiles = "gdal2tiles.py -k --s_srs EPSG:900913 -t #{id} -g #{key} public/warps/#{id}/#{id}.tif public/tms/#{id}/"
|
|
289
290
|
puts gdal2tiles
|
|
290
|
-
if system(
|
|
291
|
+
if system(ulimit + gdal2tiles)
|
|
291
292
|
"public/tms/#{id}/"
|
|
292
293
|
else
|
|
293
294
|
false
|
|
@@ -298,7 +299,7 @@ class MapKnitterExporter
|
|
|
298
299
|
def self.zip_tiles(id)
|
|
299
300
|
rmzip = "cd public/tms/ && rm #{id}.zip && cd ../../"
|
|
300
301
|
system(rmzip)
|
|
301
|
-
zip = "cd public/tms/ && #{
|
|
302
|
+
zip = "cd public/tms/ && #{ulimit} zip -rq #{id}.zip #{id}/ && cd ../../"
|
|
302
303
|
if system(zip)
|
|
303
304
|
"public/tms/#{id}.zip"
|
|
304
305
|
else
|
|
@@ -308,8 +309,8 @@ class MapKnitterExporter
|
|
|
308
309
|
|
|
309
310
|
# generates a tileset at public/tms/<id>/
|
|
310
311
|
def self.generate_jpg(id)
|
|
311
|
-
|
|
312
|
-
if system(
|
|
312
|
+
image_magick = "convert -background white -flatten public/warps/#{id}/#{id}.tif public/warps/#{id}/#{id}.jpg"
|
|
313
|
+
if system(ulimit + image_magick)
|
|
313
314
|
"public/warps/#{id}/#{id}.jpg"
|
|
314
315
|
else
|
|
315
316
|
false
|
|
@@ -330,31 +331,31 @@ class MapKnitterExporter
|
|
|
330
331
|
|
|
331
332
|
# filter out those that have no corner coordinates
|
|
332
333
|
placed_warpables = warpables.keep_if do |w|
|
|
333
|
-
w['nodes'] && w['nodes'].
|
|
334
|
+
w['nodes'] && !w['nodes'].empty?
|
|
334
335
|
end
|
|
335
336
|
|
|
336
337
|
directory = "public/warps/#{id}/"
|
|
337
|
-
|
|
338
|
+
_stdin, stdout, stderr = Open3.popen3('rm -r ' + directory.to_s)
|
|
338
339
|
puts stdout.readlines
|
|
339
340
|
puts stderr.readlines
|
|
340
|
-
|
|
341
|
+
_stdin, stdout, stderr = Open3.popen3("rm -r public/tms/#{id}")
|
|
341
342
|
puts stdout.readlines
|
|
342
343
|
puts stderr.readlines
|
|
343
344
|
|
|
344
345
|
puts '> averaging scales; resolution: ' + resolution.to_s
|
|
345
|
-
pxperm = 100/
|
|
346
|
+
pxperm = 100 / resolution.to_f # pixels per meter
|
|
346
347
|
puts '> scale: ' + pxperm.to_s + 'pxperm'
|
|
347
348
|
|
|
348
349
|
puts '> distorting warpables'
|
|
349
|
-
|
|
350
|
-
origin =
|
|
350
|
+
|
|
351
|
+
origin = distort_warpables(pxperm, placed_warpables, export, id)
|
|
351
352
|
warpable_coords = origin.pop
|
|
352
353
|
|
|
353
354
|
export.status = 'compositing'
|
|
354
355
|
export.save
|
|
355
356
|
|
|
356
357
|
puts '> generating composite tiff'
|
|
357
|
-
composite_location =
|
|
358
|
+
composite_location = generate_composite_tiff(
|
|
358
359
|
warpable_coords,
|
|
359
360
|
origin,
|
|
360
361
|
placed_warpables,
|
|
@@ -364,7 +365,7 @@ class MapKnitterExporter
|
|
|
364
365
|
|
|
365
366
|
identify = "identify -quiet -format '%b,%w,%h' #{composite_location}"
|
|
366
367
|
puts identify
|
|
367
|
-
info =
|
|
368
|
+
info = `#{identify}`.split(',')
|
|
368
369
|
puts info
|
|
369
370
|
|
|
370
371
|
if info[0] != ''
|
|
@@ -381,14 +382,14 @@ class MapKnitterExporter
|
|
|
381
382
|
export.tms = false
|
|
382
383
|
export.status = 'tiling'
|
|
383
384
|
export.save
|
|
384
|
-
export.tms =
|
|
385
|
+
export.tms = generate_tiles(key, id)
|
|
385
386
|
export.save unless export.tms == false
|
|
386
387
|
|
|
387
388
|
puts '> zipping tiles'
|
|
388
389
|
export.zip = false
|
|
389
390
|
export.status = 'zipping tiles'
|
|
390
391
|
export.save
|
|
391
|
-
export.zip =
|
|
392
|
+
export.zip = zip_tiles(id)
|
|
392
393
|
export.save unless export.zip == false
|
|
393
394
|
# end fork
|
|
394
395
|
|
|
@@ -397,7 +398,7 @@ class MapKnitterExporter
|
|
|
397
398
|
export.jpg = false
|
|
398
399
|
export.status = 'creating jpg'
|
|
399
400
|
export.save
|
|
400
|
-
export.jpg =
|
|
401
|
+
export.jpg = generate_jpg(id)
|
|
401
402
|
unless export.jpg == false
|
|
402
403
|
export.status = 'complete'
|
|
403
404
|
export.save
|
|
@@ -406,5 +407,4 @@ class MapKnitterExporter
|
|
|
406
407
|
|
|
407
408
|
export
|
|
408
409
|
end
|
|
409
|
-
|
|
410
410
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mapknitter-exporter
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jeffrey Warren
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-11-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: The GDAL/ImageMagick-based exporter system from MapKnitter
|
|
14
14
|
email: jeff@unterbahn.com
|
|
@@ -17,11 +17,11 @@ extensions: []
|
|
|
17
17
|
extra_rdoc_files: []
|
|
18
18
|
files:
|
|
19
19
|
- lib/cartagen.rb
|
|
20
|
-
- lib/
|
|
21
|
-
- lib/
|
|
22
|
-
homepage: http://rubygems.org/gems/
|
|
20
|
+
- lib/exporter.rb
|
|
21
|
+
- lib/mapknitter_exporter.rb
|
|
22
|
+
homepage: http://rubygems.org/gems/mapknitter_exporter
|
|
23
23
|
licenses:
|
|
24
|
-
-
|
|
24
|
+
- GPL-3.0
|
|
25
25
|
metadata: {}
|
|
26
26
|
post_install_message:
|
|
27
27
|
rdoc_options: []
|
|
@@ -38,8 +38,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '0'
|
|
40
40
|
requirements: []
|
|
41
|
-
|
|
42
|
-
rubygems_version: 2.6.13
|
|
41
|
+
rubygems_version: 3.1.6
|
|
43
42
|
signing_key:
|
|
44
43
|
specification_version: 4
|
|
45
44
|
summary: The GDAL/ImageMagick-based exporter system from MapKnitter
|
data/lib/mapknitter-exporter.rb
DELETED