mapknitter-exporter 1.0.7 → 1.0.11
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} +154 -153
- 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: 9cd00b0b1199beb4075803558cf464f5ec1d0413469ef3b6bf4773695a1f430b
|
|
4
|
+
data.tar.gz: d37ee986536f693079f9d35790fb9d9291bc08ebd5247809c8ad13b1e22c4c1e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: be119aad6a45664530677cb1de1cfc8b0ce3b1adc9197460768a5c713f1e4982280124db86e6af6f1f57ec939e083139b7ad2825d600fa390465f864275a7716
|
|
7
|
+
data.tar.gz: 3fd7505b2dcd03988042bce15cd6afc9f7af52970d8a3d48743cfa1b9ddbbd29d17dc03ceafd8c6dcd778351e89b1004cf510109c0684de57480709f2b31a97e
|
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,25 +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
|
|
|
33
|
-
|
|
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
|
|
73
|
+
image_file_name ||= img_url.split('/').last
|
|
74
|
+
# everything in -working/ can be deleted;
|
|
34
75
|
# this is just so we can use the files locally outside of s3
|
|
35
76
|
working_directory = get_working_directory(collection_id)
|
|
36
|
-
Dir.mkdir(working_directory) unless
|
|
37
|
-
require "shellwords"
|
|
77
|
+
Dir.mkdir(working_directory) unless File.exist?(working_directory) && File.directory?(working_directory)
|
|
38
78
|
local_location = "#{working_directory}w#{id}-#{image_file_name}"
|
|
39
79
|
directory = warps_directory(collection_id)
|
|
40
|
-
Dir.mkdir(directory) unless
|
|
41
|
-
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'
|
|
42
82
|
|
|
43
83
|
# everything -masked.png can be deleted
|
|
44
84
|
masked_local_location = directory + 'w' + id.to_s + '-masked.png'
|
|
45
85
|
# everything -mask.png can be deleted
|
|
46
86
|
mask_location = directory + 'w' + id.to_s + '-mask.png'
|
|
47
|
-
#completed_local_location = directory+id.to_s+'.tif'
|
|
87
|
+
# completed_local_location = directory+id.to_s+'.tif'
|
|
48
88
|
# know everything -unwarped can be deleted
|
|
49
89
|
geotiff_location = directory + 'w' + id.to_s + '-geo-unwarped.tif'
|
|
50
90
|
# everything -geo WITH AN ID could be deleted, but there is a feature request to preserve these
|
|
@@ -61,24 +101,23 @@ class MapKnitterExporter
|
|
|
61
101
|
westmost = node['lon'].to_f if node['lon'].to_f < westmost
|
|
62
102
|
eastmost = node['lon'].to_f if node['lon'].to_f > eastmost
|
|
63
103
|
end
|
|
64
|
-
|
|
65
|
-
scale =
|
|
66
|
-
y1 = pxperm.to_f * Cartagen.spherical_mercator_lat_to_y(northmost,scale)
|
|
67
|
-
x1 = pxperm.to_f * Cartagen.spherical_mercator_lon_to_x(westmost,scale)
|
|
68
|
-
y2 = pxperm.to_f * Cartagen.spherical_mercator_lat_to_y(southmost,scale)
|
|
69
|
-
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)
|
|
70
110
|
|
|
71
111
|
# should determine if it's stored in s3 or locally:
|
|
72
|
-
if
|
|
73
|
-
|
|
74
|
-
|
|
112
|
+
if img_url.slice(0, 4) == 'http'
|
|
113
|
+
host = img_url.split('//').last.split('/').first
|
|
114
|
+
Net::HTTP.start(host) do |http|
|
|
75
115
|
resp = http.get(img_url)
|
|
76
|
-
open(local_location, "wb")
|
|
116
|
+
open(local_location, "wb") do |file| # rubocop:disable Security/Open
|
|
77
117
|
file.write(resp.body)
|
|
78
|
-
|
|
79
|
-
|
|
118
|
+
end
|
|
119
|
+
end
|
|
80
120
|
else
|
|
81
|
-
require "fileutils"
|
|
82
121
|
FileUtils.cp(img_url, local_location)
|
|
83
122
|
end
|
|
84
123
|
|
|
@@ -86,34 +125,34 @@ class MapKnitterExporter
|
|
|
86
125
|
maskpoints = ""
|
|
87
126
|
coordinates = ""
|
|
88
127
|
first = true
|
|
89
|
-
|
|
90
|
-
#EXIF orientation values:
|
|
91
|
-
#Value 0th Row 0th Column
|
|
92
|
-
#1 top left side
|
|
93
|
-
#2 top right side
|
|
94
|
-
#3 bottom right side
|
|
95
|
-
#4 bottom left side
|
|
96
|
-
#5 left side top
|
|
97
|
-
#6 right side top
|
|
98
|
-
#7 right side bottom
|
|
99
|
-
#8 left side bottom
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
|
105
144
|
|
|
106
145
|
if rotation == 6
|
|
107
146
|
puts 'rotated CCW'
|
|
108
|
-
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]]
|
|
109
148
|
elsif rotation == 8
|
|
110
149
|
puts 'rotated CW'
|
|
111
|
-
source_corners = [[width,0],[width,height],[0,height],[0,0]]
|
|
150
|
+
source_corners = [[width, 0], [width, height], [0, height], [0, 0]]
|
|
112
151
|
elsif rotation == 3
|
|
113
152
|
puts 'rotated 180 deg'
|
|
114
|
-
source_corners = [[width,height],[0,height],[0,0],[width,0]]
|
|
153
|
+
source_corners = [[width, height], [0, height], [0, 0], [width, 0]]
|
|
115
154
|
else
|
|
116
|
-
source_corners = [[0,0],[width,0],[width,height],[0,height]]
|
|
155
|
+
source_corners = [[0, 0], [width, 0], [width, height], [0, height]]
|
|
117
156
|
end
|
|
118
157
|
|
|
119
158
|
maxdimension = 0
|
|
@@ -124,15 +163,15 @@ class MapKnitterExporter
|
|
|
124
163
|
ny1 = corner[1]
|
|
125
164
|
nx2 = -x1 + (pxperm.to_f * Cartagen.spherical_mercator_lon_to_x(node['lon'].to_f, scale.to_f))
|
|
126
165
|
ny2 = y1 - (pxperm.to_f * Cartagen.spherical_mercator_lat_to_y(node['lat'].to_f, scale.to_f))
|
|
127
|
-
|
|
128
|
-
points
|
|
129
|
-
maskpoints
|
|
166
|
+
|
|
167
|
+
points += ' ' unless first
|
|
168
|
+
maskpoints += ' ' unless first
|
|
130
169
|
points = points + nx1.to_s + ',' + ny1.to_s + ' ' + nx2.to_i.to_s + ',' + ny2.to_i.to_s
|
|
131
170
|
maskpoints = maskpoints + nx2.to_i.to_s + ',' + ny2.to_i.to_s
|
|
132
171
|
first = false
|
|
133
172
|
# we need to find an origin; find northwestern-most point
|
|
134
|
-
coordinates = coordinates+' -gcp '+nx2.to_s+', '+ny2.to_s+', '+node['lon'].to_s + ', ' + node['lat'].to_s
|
|
135
|
-
|
|
173
|
+
coordinates = coordinates + ' -gcp ' + nx2.to_s + ', ' + ny2.to_s + ', ' + node['lon'].to_s + ', ' + node['lat'].to_s
|
|
174
|
+
|
|
136
175
|
# identify largest dimension to set canvas size for ImageMagick:
|
|
137
176
|
maxdimension = nx1.to_i if maxdimension < nx1.to_i
|
|
138
177
|
maxdimension = ny1.to_i if maxdimension < ny1.to_i
|
|
@@ -141,71 +180,35 @@ class MapKnitterExporter
|
|
|
141
180
|
end
|
|
142
181
|
|
|
143
182
|
# close mask polygon:
|
|
144
|
-
maskpoints
|
|
145
|
-
|
|
146
|
-
|
|
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))
|
|
147
186
|
maskpoints = maskpoints + nx2.to_i.to_s + ',' + ny2.to_i.to_s
|
|
148
187
|
|
|
149
|
-
height = (y1-y2).to_i.to_s
|
|
150
|
-
width = (-x1+x2).to_i.to_s
|
|
188
|
+
height = (y1 - y2).to_i.to_s
|
|
189
|
+
width = (-x1 + x2).to_i.to_s
|
|
151
190
|
|
|
152
191
|
# http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=11319
|
|
153
192
|
# http://www.imagemagick.org/discourse-server/viewtopic.php?f=3&t=8764
|
|
154
|
-
# read about equalization
|
|
193
|
+
# read about equalization
|
|
155
194
|
# -equalize
|
|
156
195
|
# -contrast-stretch 0
|
|
157
196
|
|
|
158
|
-
|
|
159
|
-
imageMagick += "-contrast-stretch 0 "
|
|
160
|
-
imageMagick += local_location.shellescape+" "
|
|
161
|
-
imageMagick += "-crop "+maxdimension.to_i.to_s+"x"+maxdimension.to_i.to_s+"+0+0! "
|
|
162
|
-
imageMagick += "-flatten "
|
|
163
|
-
imageMagick += "-distort Perspective '"+points+"' "
|
|
164
|
-
imageMagick += "-flatten "
|
|
165
|
-
if width > height
|
|
166
|
-
imageMagick += "-crop "+width+"x"+width+"+0+0\! "
|
|
167
|
-
else
|
|
168
|
-
imageMagick += "-crop "+height+"x"+height+"+0+0\! "
|
|
169
|
-
end
|
|
170
|
-
imageMagick += "+repage "
|
|
171
|
-
imageMagick += completed_local_location
|
|
172
|
-
puts imageMagick
|
|
173
|
-
system(self.ulimit+imageMagick)
|
|
197
|
+
image_magick_manipulation(height, width, mask_location, local_location, completed_local_location, maxdimension, maskpoints, masked_local_location, points)
|
|
174
198
|
|
|
175
|
-
|
|
176
|
-
imageMagick2 = 'convert +antialias '
|
|
177
|
-
if width > height
|
|
178
|
-
imageMagick2 += "-size "+width+"x"+width+" "
|
|
179
|
-
else
|
|
180
|
-
imageMagick2 += "-size "+height+"x"+height+" "
|
|
181
|
-
end
|
|
182
|
-
# attempt at blurred edges in masking, but I've given up, as gdal_merge doesn't seem to respect variable-opacity alpha channels
|
|
183
|
-
imageMagick2 += ' xc:none -draw "fill black stroke red stroke-width 30 polyline '
|
|
184
|
-
imageMagick2 += maskpoints + '" '
|
|
185
|
-
imageMagick2 += ' -alpha set -channel A -transparent red -blur 0x8 -channel R -evaluate set 0 +channel '+mask_location
|
|
186
|
-
#imageMagick2 += ' xc:none -draw "fill black stroke none polyline '
|
|
187
|
-
#imageMagick2 += maskpoints + '" '
|
|
188
|
-
#imageMagick2 += ' '+mask_location
|
|
189
|
-
puts imageMagick2
|
|
190
|
-
system(self.ulimit+imageMagick2)
|
|
191
|
-
|
|
192
|
-
imageMagick3 = 'composite '+mask_location+' '+completed_local_location+' -compose DstIn -alpha Set '+masked_local_location
|
|
193
|
-
puts imageMagick3
|
|
194
|
-
system(self.ulimit+imageMagick3)
|
|
195
|
-
|
|
196
|
-
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
|
|
197
200
|
puts gdal_translate
|
|
198
|
-
system(
|
|
199
|
-
|
|
200
|
-
#gdalwarp = 'gdalwarp -srcnodata "255" -dstnodata 0 -cblend 30 -of GTiff -t_srs EPSG:4326 '+geotiff_location+' '+warped_geotiff_location
|
|
201
|
-
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
|
|
202
205
|
puts gdalwarp
|
|
203
|
-
system(
|
|
206
|
+
system(ulimit + gdalwarp)
|
|
204
207
|
|
|
205
208
|
# deletions could happen here; do it in distinct method so we can run it independently
|
|
206
209
|
delete_temp_files(id)
|
|
207
210
|
|
|
208
|
-
[x1,y1]
|
|
211
|
+
[x1, y1]
|
|
209
212
|
end
|
|
210
213
|
|
|
211
214
|
########################
|
|
@@ -213,41 +216,41 @@ class MapKnitterExporter
|
|
|
213
216
|
|
|
214
217
|
# distort all warpables, returns upper left corner coords in x,y
|
|
215
218
|
def self.distort_warpables(scale, images, export, id)
|
|
216
|
-
|
|
217
219
|
puts '> generating geotiffs of each warpable in GDAL'
|
|
218
220
|
lowest_x = 0
|
|
219
221
|
lowest_y = 0
|
|
220
222
|
all_coords = []
|
|
221
223
|
current = 0
|
|
222
224
|
images.each_with_index do |image, index|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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?
|
|
245
248
|
end
|
|
246
249
|
[lowest_x, lowest_y, all_coords]
|
|
247
250
|
end
|
|
248
251
|
|
|
249
252
|
# generate a tiff from all warpable images in this set
|
|
250
|
-
def self.generate_composite_tiff(
|
|
253
|
+
def self.generate_composite_tiff(_coords, _origin, warpables, id, ordered)
|
|
251
254
|
directory = "public/warps/#{id}/"
|
|
252
255
|
composite_location = directory + id.to_s + '.tif'
|
|
253
256
|
minlat = nil
|
|
@@ -257,36 +260,35 @@ class MapKnitterExporter
|
|
|
257
260
|
warpables.each_with_index do |warpable, i|
|
|
258
261
|
warpable['nodes'].each do |n|
|
|
259
262
|
puts "warpable: ", n['id'], i, n['lat'], n['lon']
|
|
260
|
-
minlat = n['lat'].to_f if minlat
|
|
261
|
-
minlon = n['lon'].to_f if minlon
|
|
262
|
-
maxlat = n['lat'].to_f if maxlat
|
|
263
|
-
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
|
|
264
267
|
end
|
|
265
268
|
end
|
|
266
269
|
puts "minlat #{minlat}, minlon #{minlon}, maxlat #{maxlat}, maxlon #{maxlon}"
|
|
267
|
-
|
|
268
|
-
if ordered != true && warpables.first.keys.include?('poly_area')
|
|
270
|
+
if ordered != true && warpables.first.key?('poly_area')
|
|
269
271
|
# sort by area; this would be overridden by a provided order
|
|
270
|
-
warpables = warpables.sort{ |a,b| b['poly_area'] <=> a['poly_area'] }
|
|
272
|
+
warpables = warpables.sort { |a, b| b['poly_area'] <=> a['poly_area'] }
|
|
271
273
|
end
|
|
272
274
|
geotiffs = ""
|
|
273
275
|
warpables.each do |warpable|
|
|
274
276
|
wid = "w" + warpable['id'].to_s
|
|
275
|
-
geotiffs += ' '+directory+wid+'.tif'
|
|
277
|
+
geotiffs += ' ' + directory + wid + '.tif'
|
|
276
278
|
end
|
|
277
|
-
gdalwarp = "gdalwarp -
|
|
279
|
+
gdalwarp = "gdalwarp -te_srs EPSG:4326 -t_srs EPSG:4326 -te #{minlon} #{minlat} #{maxlon} #{maxlat} #{geotiffs} #{directory}#{id}.tif"
|
|
278
280
|
puts gdalwarp
|
|
279
|
-
system(
|
|
281
|
+
system(ulimit + gdalwarp)
|
|
280
282
|
composite_location
|
|
281
283
|
end
|
|
282
284
|
|
|
283
285
|
# generates a tileset at public/tms/<id>/
|
|
284
286
|
def self.generate_tiles(key, id)
|
|
285
287
|
key = "AIzaSyAOLUQngEmJv0_zcG1xkGq-CXIPpLQY8iQ" if key == "" # ugh, let's clean this up!
|
|
286
|
-
key
|
|
287
|
-
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}/"
|
|
288
290
|
puts gdal2tiles
|
|
289
|
-
if system(
|
|
291
|
+
if system(ulimit + gdal2tiles)
|
|
290
292
|
"public/tms/#{id}/"
|
|
291
293
|
else
|
|
292
294
|
false
|
|
@@ -297,7 +299,7 @@ class MapKnitterExporter
|
|
|
297
299
|
def self.zip_tiles(id)
|
|
298
300
|
rmzip = "cd public/tms/ && rm #{id}.zip && cd ../../"
|
|
299
301
|
system(rmzip)
|
|
300
|
-
zip = "cd public/tms/ && #{
|
|
302
|
+
zip = "cd public/tms/ && #{ulimit} zip -rq #{id}.zip #{id}/ && cd ../../"
|
|
301
303
|
if system(zip)
|
|
302
304
|
"public/tms/#{id}.zip"
|
|
303
305
|
else
|
|
@@ -307,8 +309,8 @@ class MapKnitterExporter
|
|
|
307
309
|
|
|
308
310
|
# generates a tileset at public/tms/<id>/
|
|
309
311
|
def self.generate_jpg(id)
|
|
310
|
-
|
|
311
|
-
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)
|
|
312
314
|
"public/warps/#{id}/#{id}.jpg"
|
|
313
315
|
else
|
|
314
316
|
false
|
|
@@ -329,31 +331,31 @@ class MapKnitterExporter
|
|
|
329
331
|
|
|
330
332
|
# filter out those that have no corner coordinates
|
|
331
333
|
placed_warpables = warpables.keep_if do |w|
|
|
332
|
-
w['nodes'] && w['nodes'].
|
|
334
|
+
w['nodes'] && !w['nodes'].empty?
|
|
333
335
|
end
|
|
334
336
|
|
|
335
337
|
directory = "public/warps/#{id}/"
|
|
336
|
-
|
|
338
|
+
_stdin, stdout, stderr = Open3.popen3('rm -r ' + directory.to_s)
|
|
337
339
|
puts stdout.readlines
|
|
338
340
|
puts stderr.readlines
|
|
339
|
-
|
|
341
|
+
_stdin, stdout, stderr = Open3.popen3("rm -r public/tms/#{id}")
|
|
340
342
|
puts stdout.readlines
|
|
341
343
|
puts stderr.readlines
|
|
342
344
|
|
|
343
345
|
puts '> averaging scales; resolution: ' + resolution.to_s
|
|
344
|
-
pxperm = 100/
|
|
346
|
+
pxperm = 100 / resolution.to_f # pixels per meter
|
|
345
347
|
puts '> scale: ' + pxperm.to_s + 'pxperm'
|
|
346
348
|
|
|
347
349
|
puts '> distorting warpables'
|
|
348
|
-
|
|
349
|
-
origin =
|
|
350
|
+
|
|
351
|
+
origin = distort_warpables(pxperm, placed_warpables, export, id)
|
|
350
352
|
warpable_coords = origin.pop
|
|
351
353
|
|
|
352
354
|
export.status = 'compositing'
|
|
353
355
|
export.save
|
|
354
356
|
|
|
355
357
|
puts '> generating composite tiff'
|
|
356
|
-
composite_location =
|
|
358
|
+
composite_location = generate_composite_tiff(
|
|
357
359
|
warpable_coords,
|
|
358
360
|
origin,
|
|
359
361
|
placed_warpables,
|
|
@@ -363,7 +365,7 @@ class MapKnitterExporter
|
|
|
363
365
|
|
|
364
366
|
identify = "identify -quiet -format '%b,%w,%h' #{composite_location}"
|
|
365
367
|
puts identify
|
|
366
|
-
info =
|
|
368
|
+
info = `#{identify}`.split(',')
|
|
367
369
|
puts info
|
|
368
370
|
|
|
369
371
|
if info[0] != ''
|
|
@@ -380,14 +382,14 @@ class MapKnitterExporter
|
|
|
380
382
|
export.tms = false
|
|
381
383
|
export.status = 'tiling'
|
|
382
384
|
export.save
|
|
383
|
-
export.tms =
|
|
385
|
+
export.tms = generate_tiles(key, id)
|
|
384
386
|
export.save unless export.tms == false
|
|
385
387
|
|
|
386
388
|
puts '> zipping tiles'
|
|
387
389
|
export.zip = false
|
|
388
390
|
export.status = 'zipping tiles'
|
|
389
391
|
export.save
|
|
390
|
-
export.zip =
|
|
392
|
+
export.zip = zip_tiles(id)
|
|
391
393
|
export.save unless export.zip == false
|
|
392
394
|
# end fork
|
|
393
395
|
|
|
@@ -396,7 +398,7 @@ class MapKnitterExporter
|
|
|
396
398
|
export.jpg = false
|
|
397
399
|
export.status = 'creating jpg'
|
|
398
400
|
export.save
|
|
399
|
-
export.jpg =
|
|
401
|
+
export.jpg = generate_jpg(id)
|
|
400
402
|
unless export.jpg == false
|
|
401
403
|
export.status = 'complete'
|
|
402
404
|
export.save
|
|
@@ -405,5 +407,4 @@ class MapKnitterExporter
|
|
|
405
407
|
|
|
406
408
|
export
|
|
407
409
|
end
|
|
408
|
-
|
|
409
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.11
|
|
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.14.4
|
|
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