cartocss_helper 0.0.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/cartocss_helper.rb +105 -40
- data/lib/cartocss_helper/configuration.rb +1 -1
- data/lib/cartocss_helper/data_file_handling.rb +42 -4
- data/lib/cartocss_helper/downloader.rb +111 -28
- data/lib/cartocss_helper/git.rb +11 -5
- data/lib/cartocss_helper/image_generator.rb +2 -30
- data/lib/cartocss_helper/style_specific/default_osm_style.rb +13 -1
- data/lib/cartocss_helper/tilemill_handler.rb +36 -0
- data/lib/cartocss_helper/util/filehelper.rb +6 -0
- data/lib/cartocss_helper/visualise_changes_diff_from_images.rb +1 -1
- data/lib/cartocss_helper/visualise_changes_image_generation.rb +128 -29
- data/lib/data/testing_locations.rb +242 -0
- data/readme.md +37 -6
- metadata +5 -2
data/lib/cartocss_helper.rb
CHANGED
@@ -9,62 +9,127 @@ require_relative 'cartocss_helper/downloader.rb'
|
|
9
9
|
require_relative 'cartocss_helper/data_file_handling.rb'
|
10
10
|
require_relative 'cartocss_helper/validator.rb'
|
11
11
|
require_relative 'cartocss_helper/git.rb'
|
12
|
+
require_relative 'data/testing_locations'
|
12
13
|
include CartoCSSHelper::Validator
|
13
14
|
include CartoCSSHelper::Git
|
14
15
|
|
15
16
|
module CartoCSSHelper
|
16
|
-
def self.test_tag_on_real_data(tags,
|
17
|
-
|
18
|
-
test_tag_on_real_data_for_this_type(tags,
|
17
|
+
def self.test_tag_on_real_data(tags, new_branch, old_branch, zlevels, types=['node', 'closed_way', 'way'])
|
18
|
+
types.each {|type|
|
19
|
+
test_tag_on_real_data_for_this_type(tags, new_branch, old_branch, zlevels, type)
|
19
20
|
}
|
20
21
|
end
|
21
22
|
|
22
|
-
def self.test_tag_on_real_data_for_this_type(tags,
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
london_longitude = -0.1
|
41
|
-
CartoCSSHelper::VisualDiff.visualise_changes_on_real_data(tags, type, london_latitude, london_longitude, zlevels, old_branch, new_branch)
|
42
|
-
#TODO: solve problems with respons to big to store in memory
|
43
|
-
#utrecht_latitude = 52.09
|
44
|
-
#utrecht_longitude = 5.11
|
45
|
-
#CartoCSSHelper::VisualDiff.visualise_changes_on_real_data(tags, type, utrecht_latitude, utrecht_longitude, zlevels, old_branch, new_branch)
|
46
|
-
rural_uk_latitude = 53.2
|
47
|
-
rural_uk_longitude = -1.8
|
48
|
-
CartoCSSHelper::VisualDiff.visualise_changes_on_real_data(tags, type, rural_uk_latitude, rural_uk_longitude, zlevels, old_branch, new_branch)
|
23
|
+
def self.test_tag_on_real_data_for_this_type(tags, new_branch, old_branch, zlevels, type)
|
24
|
+
min = 6
|
25
|
+
generated = 0
|
26
|
+
|
27
|
+
n = 0
|
28
|
+
max_n = get_maxn_for_nth_location
|
29
|
+
while generated < min
|
30
|
+
location = get_nth_location(n)
|
31
|
+
generated +=1 if CartoCSSHelper::VisualDiff.visualise_changes_on_real_data(tags, type, location[0], location[1], zlevels, new_branch, old_branch)
|
32
|
+
n+=1
|
33
|
+
if n > max_n
|
34
|
+
return
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_maxn_for_nth_location
|
40
|
+
return get_list_of_testing_locations.length-1
|
49
41
|
end
|
50
42
|
|
43
|
+
def get_nth_location(n)
|
44
|
+
return get_list_of_testing_locations[n]
|
45
|
+
end
|
46
|
+
|
47
|
+
|
51
48
|
def self.add_common_secondary_tags(tags)
|
52
|
-
|
49
|
+
added_tags = {'name' => 'ÉÉÉÉÉÉ ÉÉÉÉÉÉ', 'ref' => '1', 'ele' => '8000', 'operator' => 'ÉÉ ÉÉ ÉÉ operator', 'brand' => 'ÉÉ ÉÉ ÉÉ brand'}
|
50
|
+
return tags.merge(added_tags)
|
53
51
|
end
|
54
52
|
|
55
|
-
def self.
|
56
|
-
puts "processing #{VisualDiff.dict_to_pretty_tag_list(tags)}"
|
53
|
+
def self.test_tag_on_sythetic_data(tags, new_branch, old_branch='master', zlevels=Configuration.get_min_z..Configuration.get_max_z, types=['node', 'closed_way', 'way'], test_on_water=false)
|
57
54
|
syn_tags = add_common_secondary_tags(tags)
|
58
|
-
|
59
|
-
CartoCSSHelper::VisualDiff.visualise_changes_synthethic_test(syn_tags, type, test_on_water, zlevels,
|
55
|
+
types.each {|type|
|
56
|
+
CartoCSSHelper::VisualDiff.visualise_changes_synthethic_test(syn_tags, type, test_on_water, zlevels, new_branch, old_branch)
|
60
57
|
}
|
61
|
-
test_tag_on_real_data(tags, zlevels, old_brach, new_branch)
|
62
58
|
end
|
63
59
|
|
64
|
-
def self.
|
60
|
+
def self.test(tags, new_branch, old_branch='master', zlevels=Configuration.get_min_z..Configuration.get_max_z, types=['node', 'closed_way', 'way'], test_on_water=false)
|
61
|
+
puts "processing #{VisualDiff.dict_to_pretty_tag_list(tags)}"
|
62
|
+
test_tag_on_sythetic_data(tags, new_branch, old_branch, zlevels, types, test_on_water)
|
63
|
+
test_tag_on_real_data(tags, new_branch, old_branch, zlevels, types)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.probe(tags, new_branch, old_branch='master', zlevels=Configuration.get_min_z..Configuration.get_max_z, types=['node', 'closed_way', 'way'], test_on_water=false)
|
65
67
|
syn_tags = add_common_secondary_tags(tags)
|
66
|
-
|
67
|
-
CartoCSSHelper::VisualDiff.visualise_changes_synthethic_test(syn_tags, type, test_on_water, zlevels,
|
68
|
+
types.each {|type|
|
69
|
+
CartoCSSHelper::VisualDiff.visualise_changes_synthethic_test(syn_tags, type, test_on_water, zlevels, new_branch, old_branch)
|
68
70
|
}
|
69
71
|
end
|
70
|
-
|
72
|
+
|
73
|
+
def visualise_place_by_url(url, zlevels, new_branch, old_branch='master', header=nil, download_bbox_size=0.04, image_size = 350)
|
74
|
+
raise "#{url} is not a string" unless old_branch.class == String
|
75
|
+
raise "#{zlevels} is not a range" unless zlevels.class == Range
|
76
|
+
raise "#{new_branch} is not a string" unless new_branch.class == String
|
77
|
+
raise "#{old_branch} is not a string" unless old_branch.class == String
|
78
|
+
raise "#{header} is not a string" unless header.class == String
|
79
|
+
raise "#{download_bbox_size} is not a number" unless download_bbox_size.kind_of? Numeric
|
80
|
+
raise "#{image_size} is not a integer" unless image_size.kind_of? Integer
|
81
|
+
|
82
|
+
latitude = url.scan(/\/((-|)\d+(\.\d+))/)[0][0].to_f
|
83
|
+
longitude = url.scan(/\/((-|)\d+(\.\d+))/)[1][0].to_f
|
84
|
+
if header == nil
|
85
|
+
header = url
|
86
|
+
end
|
87
|
+
header += ' ' + old_branch + '->' + new_branch + ' ' + zlevels.to_s + ' '+ image_size.to_s + 'px'
|
88
|
+
CartoCSSHelper::VisualDiff.visualise_changes_for_location(latitude, longitude, zlevels, header, new_branch, old_branch, download_bbox_size, image_size)
|
89
|
+
end
|
90
|
+
|
91
|
+
def get_place_of_storage_of_resource_under_url(url)
|
92
|
+
return CartoCSSHelper::Configuration.get_path_to_folder_for_overpass_cache + '.manual.cache' + FileHelper::make_string_usable_as_filename(url)
|
93
|
+
end
|
94
|
+
|
95
|
+
def download_remote_file(url)
|
96
|
+
filename = get_place_of_storage_of_resource_under_url(url)
|
97
|
+
if !File.exists?(filename)
|
98
|
+
begin
|
99
|
+
url = url
|
100
|
+
timeout = 600
|
101
|
+
data = RestClient::Request.execute(:method => :get, :url => url, :timeout => timeout)
|
102
|
+
rescue => e
|
103
|
+
puts "visualise_place_by_remote_file failed to fetch #{url}"
|
104
|
+
raise e
|
105
|
+
end
|
106
|
+
file = File.new(filename, 'w')
|
107
|
+
file.write data
|
108
|
+
file.close
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def visualise_place_by_remote_file(url, latitude, longitude, zlevels, new_branch, old_branch='master', header=nil, bb=0.04, image_size = 350)
|
113
|
+
download_remote_file(url)
|
114
|
+
filename = get_place_of_storage_of_resource_under_url(url)
|
115
|
+
visualise_place_by_file(filename, latitude, longitude, zlevels, new_branch, old_branch, header, bb, image_size)
|
116
|
+
end
|
117
|
+
|
118
|
+
def visualise_place_by_file(filename, latitude, longitude, zlevels, new_branch, old_branch='master', header=nil, bb=0.04, image_size = 350)
|
119
|
+
raise "#{filename} does not exists" unless File.exists?(filename)
|
120
|
+
raise "#{latitude} is not a number" unless latitude.kind_of? Numeric
|
121
|
+
raise "#{longitude} is not a number" unless longitude.kind_of? Numeric
|
122
|
+
raise "#{zlevels} is not a range" unless zlevels.class == Range
|
123
|
+
raise "#{new_branch} is not a string" unless new_branch.class == String
|
124
|
+
raise "#{old_branch} is not a string" unless old_branch.class == String
|
125
|
+
raise "#{header} is not a string" unless header.class == String
|
126
|
+
raise "#{bb} is not a number" unless bb.kind_of? Numeric
|
127
|
+
raise "#{image_size} is not a integer" unless image_size.kind_of? Integer
|
128
|
+
|
129
|
+
if header == nil
|
130
|
+
header = filename
|
131
|
+
end
|
132
|
+
header += ' ' + old_branch + '->' + new_branch + '[' + latitude.to_s + ',' + longitude.to_s + ']' + ' ' + image_size.to_s + 'px'
|
133
|
+
CartoCSSHelper::VisualDiff.visualise_changes_for_location_from_file(filename, latitude, longitude, zlevels, header, new_branch, old_branch, bb, image_size)
|
134
|
+
end
|
135
|
+
end
|
@@ -86,7 +86,7 @@ module CartoCSSHelper::Configuration
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def get_path_to_folder_for_branch_specific_cache
|
89
|
-
location = File.join(get_path_to_folder_for_cache, CartoCSSHelper::Git.get_commit_hash, '')
|
89
|
+
location = File.join(get_path_to_folder_for_cache, 'generated_images', CartoCSSHelper::Git.get_commit_hash, '')
|
90
90
|
FileUtils::mkdir_p location
|
91
91
|
return location
|
92
92
|
end
|
@@ -3,7 +3,20 @@ require_relative 'configuration'
|
|
3
3
|
|
4
4
|
module CartoCSSHelper
|
5
5
|
class DataFileLoader
|
6
|
+
@@loaded_filename = nil
|
7
|
+
def self.get_filename_of_recently_loaded_file
|
8
|
+
if @@loaded_filename == Configuration.get_data_filename
|
9
|
+
return nil
|
10
|
+
end
|
11
|
+
return @@loaded_filename
|
12
|
+
end
|
6
13
|
def self.load_data_into_database(data_filename, debug=false)
|
14
|
+
if get_filename_of_recently_loaded_file == data_filename
|
15
|
+
puts "\tavoided reloading the same file! <#{data_filename}>"
|
16
|
+
return
|
17
|
+
end
|
18
|
+
puts "\tloading data into database <#{data_filename}>"
|
19
|
+
@@loaded_filename = nil
|
7
20
|
silence = '> /dev/null 2>&1'
|
8
21
|
if debug
|
9
22
|
silence = ''
|
@@ -13,7 +26,16 @@ module CartoCSSHelper
|
|
13
26
|
if debug
|
14
27
|
puts command
|
15
28
|
end
|
16
|
-
system
|
29
|
+
if !system(command)
|
30
|
+
puts 'loading data into database failed'
|
31
|
+
if !debug
|
32
|
+
puts 'retry with enabled debug'
|
33
|
+
load_data_into_database(data_filename, true)
|
34
|
+
else
|
35
|
+
raise 'osm2pgsql failed'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
@@loaded_filename = data_filename
|
17
39
|
end
|
18
40
|
end
|
19
41
|
|
@@ -26,9 +48,26 @@ module CartoCSSHelper
|
|
26
48
|
@size = size
|
27
49
|
end
|
28
50
|
|
29
|
-
def
|
51
|
+
def open_file
|
30
52
|
@data_file = open(Configuration.get_data_filename, 'w')
|
53
|
+
end
|
54
|
+
|
55
|
+
def close_file
|
56
|
+
@data_file.close
|
57
|
+
end
|
58
|
+
|
59
|
+
def prepare_file
|
60
|
+
open_file
|
31
61
|
generate_prefix
|
62
|
+
end
|
63
|
+
|
64
|
+
def finish_file
|
65
|
+
generate_sufix
|
66
|
+
close_file
|
67
|
+
end
|
68
|
+
|
69
|
+
def generate
|
70
|
+
prepare_file
|
32
71
|
if @type == 'node'
|
33
72
|
generate_node_topology(@lat, @lon, @tags)
|
34
73
|
elsif @type == 'way'
|
@@ -38,8 +77,7 @@ module CartoCSSHelper
|
|
38
77
|
else
|
39
78
|
raise 'this type of element does not exists'
|
40
79
|
end
|
41
|
-
|
42
|
-
@data_file.close
|
80
|
+
finish_file
|
43
81
|
end
|
44
82
|
|
45
83
|
def generate_node_topology(lat, lon, tags)
|
@@ -6,6 +6,12 @@ require 'sys/filesystem'
|
|
6
6
|
|
7
7
|
module CartoCSSHelper
|
8
8
|
class Downloader
|
9
|
+
def self.get_file_with_downloaded_osm_data_for_location(latitude, longitude, size)
|
10
|
+
query = get_query_to_download_data_around_location(latitude, longitude, size)
|
11
|
+
return get_overpass_query_results_file_location(query, "download data for #{latitude} #{longitude} (#{size})")
|
12
|
+
end
|
13
|
+
|
14
|
+
|
9
15
|
def self.download_osm_data_for_location(latitude, longitude, size, accept_cache=true)
|
10
16
|
filename = CartoCSSHelper::Configuration.get_path_to_folder_for_cache + "#{latitude} #{longitude} #{size}.osm"
|
11
17
|
if File.exists?(filename)
|
@@ -15,7 +21,7 @@ module CartoCSSHelper
|
|
15
21
|
File.delete(filename)
|
16
22
|
end
|
17
23
|
query = get_query_to_download_data_around_location(latitude, longitude, size)
|
18
|
-
text = get_overpass_query_results(query)
|
24
|
+
text = get_overpass_query_results(query, "download data for #{latitude} #{longitude} (#{size})")
|
19
25
|
file = File.new(filename, 'w')
|
20
26
|
file.write text
|
21
27
|
file.close
|
@@ -23,12 +29,12 @@ module CartoCSSHelper
|
|
23
29
|
end
|
24
30
|
|
25
31
|
def self.get_query_to_download_data_around_location(latitude, longitude, size)
|
26
|
-
min_latitude = latitude - size/2
|
27
|
-
max_latitude = latitude + size/2
|
28
|
-
min_longitude = longitude - size/2
|
29
|
-
max_longitude = longitude + size/2
|
32
|
+
min_latitude = latitude - size.to_f/2
|
33
|
+
max_latitude = latitude + size.to_f/2
|
34
|
+
min_longitude = longitude - size.to_f/2
|
35
|
+
max_longitude = longitude + size.to_f/2
|
30
36
|
bb = "#{min_latitude},#{min_longitude},#{max_latitude},#{max_longitude}"
|
31
|
-
query =
|
37
|
+
query = "[timeout:#{Downloader.get_allowed_timeout_in_seconds}];"
|
32
38
|
query += "\n"
|
33
39
|
query += "(node(#{bb});<;);"
|
34
40
|
query += "\n"
|
@@ -44,18 +50,18 @@ module CartoCSSHelper
|
|
44
50
|
end
|
45
51
|
|
46
52
|
def self.locate_element_with_given_tags_and_type(tags, type, latitude, longitude)
|
47
|
-
max_range_in_km_for_radius =
|
53
|
+
max_range_in_km_for_radius = 1600
|
48
54
|
|
49
55
|
#special support for following tag values: :any_value
|
50
56
|
range = 10*1000
|
51
57
|
loop do
|
52
|
-
list = Downloader.get_overpass_query_results(Downloader.get_query_to_get_location(tags, type, latitude, longitude, range))
|
58
|
+
list = Downloader.get_overpass_query_results(Downloader.get_query_to_get_location(tags, type, latitude, longitude, range), "find #{tags} within #{range/1000}km from #{latitude}, #{longitude}")
|
53
59
|
if list.length != 0
|
54
60
|
return self.list_returned_by_overpass_to_a_single_location(list)
|
55
61
|
end
|
56
|
-
range=range+[range,
|
62
|
+
range=range+[2*range, 200000].min
|
57
63
|
if range >= max_range_in_km_for_radius*1000
|
58
|
-
list = Downloader.get_overpass_query_results(Downloader.get_query_to_get_location(tags, type, latitude, longitude, :infinity))
|
64
|
+
list = Downloader.get_overpass_query_results(Downloader.get_query_to_get_location(tags, type, latitude, longitude, :infinity), "find #{tags} across the world")
|
59
65
|
if list.length != 0
|
60
66
|
return self.list_returned_by_overpass_to_a_single_location(list)
|
61
67
|
else
|
@@ -74,7 +80,7 @@ module CartoCSSHelper
|
|
74
80
|
|
75
81
|
def self.get_query_to_get_location(tags, type, latitude, longitude, range)
|
76
82
|
#special support for following tag values: :any_value
|
77
|
-
locator =
|
83
|
+
locator = "[timeout:#{Downloader.get_allowed_timeout_in_seconds}][out:csv(::lat,::lon;false)];"
|
78
84
|
locator += "\n"
|
79
85
|
if type == 'closed_way'
|
80
86
|
type = 'way'
|
@@ -119,22 +125,50 @@ module CartoCSSHelper
|
|
119
125
|
return element
|
120
126
|
end
|
121
127
|
|
122
|
-
def self.
|
128
|
+
def self.get_overpass_query_results_file_location(query, description, debug=false)
|
129
|
+
filename = get_query_cache_filename(query)
|
130
|
+
get_overpass_query_results(query, description, debug)
|
131
|
+
return filename
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.get_overpass_query_results(query, description, debug=false)
|
123
135
|
cached = get_overpass_query_results_from_cache(query)
|
136
|
+
if cached == ''
|
137
|
+
raise OverpassRefusedResponse
|
138
|
+
end
|
124
139
|
return cached unless cached == nil
|
125
140
|
|
126
141
|
check_for_free_space
|
127
142
|
|
128
|
-
puts 'Running Overpass query'
|
143
|
+
puts 'Running Overpass query (connection initiated on ' + Time.now.to_s + ') ' + description
|
129
144
|
if debug
|
130
145
|
puts query
|
131
146
|
puts
|
132
147
|
end
|
133
|
-
|
148
|
+
begin
|
149
|
+
cached = Downloader.run_overpass_query query, description
|
150
|
+
rescue OverpassRefusedResponse
|
151
|
+
write_to_cache(query, '')
|
152
|
+
raise OverpassRefusedResponse
|
153
|
+
end
|
154
|
+
write_to_cache(query, cached)
|
155
|
+
return cached
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.write_to_cache(query, response)
|
134
159
|
file = File.new(get_query_cache_filename(query), 'w')
|
135
|
-
file.write
|
160
|
+
file.write response
|
136
161
|
file.close
|
137
|
-
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.get_timestamp_of_file(timestamp_filename)
|
165
|
+
if !File.exists?(timestamp_filename)
|
166
|
+
return nil
|
167
|
+
end
|
168
|
+
f = File.new(timestamp_filename)
|
169
|
+
timestamp = f.mtime.to_i
|
170
|
+
f.close
|
171
|
+
return timestamp
|
138
172
|
end
|
139
173
|
|
140
174
|
def self.get_overpass_query_results_from_cache(query)
|
@@ -156,39 +190,88 @@ module CartoCSSHelper
|
|
156
190
|
end
|
157
191
|
|
158
192
|
def self.check_for_free_space
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
193
|
+
if not_enough_free_space
|
194
|
+
attempt_cleanup
|
195
|
+
if not_enough_free_space
|
196
|
+
raise 'less than 2GB of free space on disk with cache folder'
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.not_enough_free_space
|
202
|
+
minimum_gb = 2
|
203
|
+
return get_available_space_for_cache_in_gb < minimum_gb
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.get_available_space_for_cache_in_gb
|
207
|
+
stat = Sys::Filesystem.stat(CartoCSSHelper::Configuration.get_path_to_folder_for_cache)
|
208
|
+
return stat.block_size * stat.blocks_available / 1024 / 1024 / 1024
|
209
|
+
end
|
210
|
+
|
211
|
+
def self.attempt_cleanup
|
212
|
+
if not_enough_free_space
|
213
|
+
delete_large_overpass_caches
|
164
214
|
end
|
165
215
|
end
|
166
216
|
|
167
|
-
def self.
|
168
|
-
|
169
|
-
|
217
|
+
def self.delete_file(file)
|
218
|
+
open(CartoCSSHelper::Configuration.get_path_to_folder_for_cache+'log.txt', 'a') { |file|
|
219
|
+
file.puts("deleting #{file}, #{File.size(file)/1024/1024}MB")
|
220
|
+
}
|
221
|
+
File.delete(file)
|
222
|
+
end
|
223
|
+
|
224
|
+
def self.delete_large_overpass_caches
|
225
|
+
#todo - find library that deals with caches like this, bug here may be unfunny
|
226
|
+
Dir.glob(CartoCSSHelper::Configuration.get_path_to_folder_for_overpass_cache+'*') {|file|
|
227
|
+
if File.size(file) > (1024 * 1024 * 50)
|
228
|
+
delete_file(file)
|
229
|
+
end
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
class OverpassRefusedResponse < IOError; end
|
234
|
+
|
235
|
+
def self.run_overpass_query(query, description, retry_count=0, retry_max=5)
|
170
236
|
start = Time.now.to_s
|
171
237
|
begin
|
172
|
-
|
173
|
-
|
238
|
+
url = Downloader.format_query_into_url(query)
|
239
|
+
timeout = Downloader.get_allowed_timeout_in_seconds+10
|
240
|
+
return RestClient::Request.execute(:method => :get, :url => url, :timeout => timeout)
|
241
|
+
rescue RestClient::RequestTimeout
|
242
|
+
puts 'Overpass API refused to process this request. It will be not attemped again, most likely query is too complex.'
|
243
|
+
raise OverpassRefusedResponse
|
244
|
+
rescue RestClient::RequestFailed, RestClient::ServerBrokeConnection => e
|
174
245
|
puts query
|
175
246
|
puts e.response
|
176
247
|
puts e.http_code
|
177
248
|
puts start
|
178
|
-
puts Time.now.to_s
|
249
|
+
puts "Rerunning #{description} started at #{Time.now.to_s} (#{retry_count}/#{retry_max}) after #{e}"
|
179
250
|
if retry_count < retry_max
|
180
251
|
sleep 60*5
|
181
|
-
Downloader.run_overpass_query(query, retry_count+1, retry_max)
|
252
|
+
Downloader.run_overpass_query(query, description, retry_count+1, retry_max)
|
182
253
|
else
|
183
254
|
e.raise
|
184
255
|
end
|
185
256
|
rescue ArgumentError => e
|
186
257
|
puts 'ArgumentError from rest-client, most likely caused by https://github.com/rest-client/rest-client/issues/359'
|
187
258
|
puts 'try overpass query that will return smaller amount of data'
|
259
|
+
puts e
|
260
|
+
e.raise
|
261
|
+
rescue => e
|
262
|
+
puts 'query failed'
|
263
|
+
puts query
|
264
|
+
puts
|
265
|
+
puts url
|
266
|
+
puts e
|
188
267
|
e.raise
|
189
268
|
end
|
190
269
|
end
|
191
270
|
|
271
|
+
def self.get_allowed_timeout_in_seconds
|
272
|
+
return 10 * 60
|
273
|
+
end
|
274
|
+
|
192
275
|
def self.format_query_into_url(query)
|
193
276
|
query = query.gsub(/\n/, '')
|
194
277
|
query = query.gsub(/\t/, '')
|
data/lib/cartocss_helper/git.rb
CHANGED
@@ -9,18 +9,24 @@ module CartoCSSHelper
|
|
9
9
|
end
|
10
10
|
Dir.chdir(Configuration.get_path_to_tilemill_project_folder) {
|
11
11
|
require 'open3'
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
command = "git checkout #{branch} #{silence}"
|
13
|
+
Open3.popen3(command) {|_, stdout, stderr, wait_thr |
|
14
|
+
error = stderr.read.chomp
|
15
|
+
if error != '' or wait_thr.value.success? != true
|
16
|
+
raise 'failed checkout to ' + branch + ' due to ' + error
|
17
|
+
end
|
18
|
+
return
|
19
|
+
}
|
20
|
+
raise 'impossible happened'
|
15
21
|
}
|
16
22
|
end
|
17
23
|
|
18
24
|
def get_commit_hash
|
19
25
|
Dir.chdir(Configuration.get_path_to_tilemill_project_folder) {
|
20
|
-
Open3.popen3('git log -n 1 --pretty=format:"%H"') {|_, stdout, stderr,
|
26
|
+
Open3.popen3('git log -n 1 --pretty=format:"%H"') {|_, stdout, stderr, wait_thr|
|
21
27
|
commit = stdout.read.chomp
|
22
28
|
error = stderr.read.chomp
|
23
|
-
if error != ''
|
29
|
+
if error != '' or wait_thr.value.success? != true
|
24
30
|
raise error
|
25
31
|
end
|
26
32
|
return commit
|
@@ -2,6 +2,7 @@
|
|
2
2
|
require_relative 'configuration.rb'
|
3
3
|
require_relative 'heuristic.rb'
|
4
4
|
require_relative 'data_file_handling.rb'
|
5
|
+
require_relative 'tilemill_handler.rb'
|
5
6
|
require 'fileutils'
|
6
7
|
include CartoCSSHelper::Configuration
|
7
8
|
include CartoCSSHelper::Heuristic
|
@@ -86,36 +87,7 @@ module CartoCSSHelper
|
|
86
87
|
def generate_image(lat, lon, debug)
|
87
88
|
export_filename = self.get_filename
|
88
89
|
bbox_size = self.get_bbox_size
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.run_tilemill_export_image(lat, lon, zlevel, bbox_size, image_size, export_filename, debug=false)
|
93
|
-
if File.exists?(export_filename)
|
94
|
-
if debug
|
95
|
-
puts 'wanted file exists'
|
96
|
-
end
|
97
|
-
return
|
98
|
-
end
|
99
|
-
silence = '> /dev/null 2>&1'
|
100
|
-
if debug
|
101
|
-
silence = ''
|
102
|
-
end
|
103
|
-
#--bbox=[xmin,ymin,xmax,ymax]
|
104
|
-
bbox = "#{lon-bbox_size/2},#{lat-bbox_size/2},#{lon+bbox_size/2},#{lat+bbox_size/2}"
|
105
|
-
params = "--format=png --width=#{image_size} --height=#{image_size} --static_zoom=#{zlevel} --bbox=\"#{bbox}\""
|
106
|
-
project_name = CartoCSSHelper::Configuration.get_tilemill_project_name
|
107
|
-
command = "node /usr/share/tilemill/index.js export #{project_name} '#{export_filename}' #{params} #{silence}"
|
108
|
-
if debug
|
109
|
-
puts command
|
110
|
-
end
|
111
|
-
system command
|
112
|
-
unless File.exists?(export_filename)
|
113
|
-
if !debug
|
114
|
-
puts 'rerunning failed image generation with enabled debug'
|
115
|
-
return self.run_tilemill_export_image(lat, lon, zlevel, bbox_size, image_size, export_filename, true)
|
116
|
-
end
|
117
|
-
raise 'generation of file ' + export_filename + ' failed'
|
118
|
-
end
|
90
|
+
TilemillHandler.run_tilemill_export_image(lat, lon, @zlevel, bbox_size, 200, export_filename, debug)
|
119
91
|
end
|
120
92
|
end
|
121
93
|
end
|
@@ -44,6 +44,7 @@ module CartoCSSHelper
|
|
44
44
|
TagRenderingStatus.new('amenity', 'atm', :primary),
|
45
45
|
TagRenderingStatus.new('amenity', 'bank', :primary),
|
46
46
|
TagRenderingStatus.new('amenity', 'bar', :primary),
|
47
|
+
TagRenderingStatus.new('amenity', 'bench', :primary),
|
47
48
|
TagRenderingStatus.new('amenity', 'bicycle_parking', :primary),
|
48
49
|
TagRenderingStatus.new('amenity', 'bicycle_rental', :primary),
|
49
50
|
TagRenderingStatus.new('amenity', 'biergarten', :primary),
|
@@ -66,6 +67,7 @@ module CartoCSSHelper
|
|
66
67
|
TagRenderingStatus.new('amenity', 'grave_yard', :primary),
|
67
68
|
TagRenderingStatus.new('amenity', 'hospital', :primary),
|
68
69
|
TagRenderingStatus.new('amenity', 'hunting_stand', :primary),
|
70
|
+
TagRenderingStatus.new('amenity', 'ice_cream', :primary),
|
69
71
|
TagRenderingStatus.new('amenity', 'kindergarten', :primary),
|
70
72
|
TagRenderingStatus.new('amenity', 'library', :primary),
|
71
73
|
TagRenderingStatus.new('amenity', 'parking', :primary),
|
@@ -85,6 +87,7 @@ module CartoCSSHelper
|
|
85
87
|
TagRenderingStatus.new('amenity', 'toilets', :primary),
|
86
88
|
TagRenderingStatus.new('amenity', 'townhall', :primary),
|
87
89
|
TagRenderingStatus.new('amenity', 'university', :primary),
|
90
|
+
TagRenderingStatus.new('amenity', 'waste_basket', :primary),
|
88
91
|
TagRenderingStatus.new('area', 'no', :composite, {'barrier' => 'hedge'}),
|
89
92
|
TagRenderingStatus.new('area', 'yes', :composite, {'barrier' => 'hedge'}),
|
90
93
|
TagRenderingStatus.new('barrier', '*', :primary),
|
@@ -171,9 +174,9 @@ module CartoCSSHelper
|
|
171
174
|
TagRenderingStatus.new('highway', 'turning_loop', :primary), #note: special topology is required
|
172
175
|
TagRenderingStatus.new('highway', 'unclassified', :primary),
|
173
176
|
TagRenderingStatus.new('historic', 'archaeological_site', :primary),
|
174
|
-
TagRenderingStatus.new('historic', 'castle_walls', :primary),
|
175
177
|
TagRenderingStatus.new('historic', 'citywalls', :primary),
|
176
178
|
TagRenderingStatus.new('historic', 'memorial', :primary),
|
179
|
+
TagRenderingStatus.new('historic', 'monument', :primary),
|
177
180
|
TagRenderingStatus.new('horse', 'designated', :composite, {'highway'=>'path'}),
|
178
181
|
TagRenderingStatus.new('intermittent', 'yes', :composite, {'waterway'=>'river'}),
|
179
182
|
TagRenderingStatus.new('junction', 'yes', :composite, {'name'=>'a'}),
|
@@ -191,6 +194,7 @@ module CartoCSSHelper
|
|
191
194
|
TagRenderingStatus.new('landuse', 'forest', :primary),
|
192
195
|
TagRenderingStatus.new('landuse', 'garages', :primary),
|
193
196
|
TagRenderingStatus.new('landuse', 'grass', :primary),
|
197
|
+
TagRenderingStatus.new('landuse', 'greenhouse_horticulture', :primary),
|
194
198
|
TagRenderingStatus.new('landuse', 'industrial', :primary),
|
195
199
|
TagRenderingStatus.new('landuse', 'landfill', :primary),
|
196
200
|
TagRenderingStatus.new('landuse', 'meadow', :primary),
|
@@ -525,6 +529,13 @@ module CartoCSSHelper
|
|
525
529
|
TagRenderingStatus.new('waterway', 'stream', :primary),
|
526
530
|
TagRenderingStatus.new('waterway', 'wadi', :primary),
|
527
531
|
TagRenderingStatus.new('waterway', 'weir', :primary),
|
532
|
+
TagRenderingStatus.new('wetland', 'bog', :composite, {'natural' => 'wetland'}),
|
533
|
+
TagRenderingStatus.new('wetland', 'marsh', :composite, {'natural' => 'wetland'}),
|
534
|
+
TagRenderingStatus.new('wetland', 'mud', :composite, {'natural' => 'wetland'}),
|
535
|
+
TagRenderingStatus.new('wetland', 'string_bog', :composite, {'natural' => 'wetland'}),
|
536
|
+
TagRenderingStatus.new('wetland', 'swamp', :composite, {'natural' => 'wetland'}),
|
537
|
+
TagRenderingStatus.new('wetland', 'tidalflat', :composite, {'natural' => 'wetland'}),
|
538
|
+
TagRenderingStatus.new('wetland', 'wet_meadow', :composite, {'natural' => 'wetland'}),
|
528
539
|
]
|
529
540
|
end
|
530
541
|
|
@@ -547,6 +558,7 @@ module CartoCSSHelper
|
|
547
558
|
{'highway' => 'track'}, #tracktype=grade1...
|
548
559
|
{'amenity' => 'parking'}, #access=*...
|
549
560
|
#{'barrier' => 'hedge'}, #area=yes
|
561
|
+
{'natural' => 'wetland'}, #wetland=bog...
|
550
562
|
]
|
551
563
|
end
|
552
564
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module CartoCSSHelper
|
2
|
+
class TilemillHandler
|
3
|
+
def self.run_tilemill_export_image(lat, lon, zlevel, bbox_size, image_size, export_filename, debug=false)
|
4
|
+
if File.exists?(export_filename)
|
5
|
+
if debug
|
6
|
+
puts 'wanted file exists'
|
7
|
+
end
|
8
|
+
return
|
9
|
+
end
|
10
|
+
silence = '> /dev/null 2>&1'
|
11
|
+
if debug
|
12
|
+
silence = ''
|
13
|
+
end
|
14
|
+
#--bbox=[xmin,ymin,xmax,ymax]
|
15
|
+
xmin = lon-bbox_size/2
|
16
|
+
ymin = lat-bbox_size/2
|
17
|
+
xmax = lon+bbox_size/2
|
18
|
+
ymax = lat+bbox_size/2
|
19
|
+
bbox = "#{xmin},#{ymin},#{xmax},#{ymax}"
|
20
|
+
params = "--format=png --width=#{image_size} --height=#{image_size} --static_zoom=#{zlevel} --bbox=\"#{bbox}\""
|
21
|
+
project_name = CartoCSSHelper::Configuration.get_tilemill_project_name
|
22
|
+
command = "node /usr/share/tilemill/index.js export #{project_name} '#{export_filename}' #{params} #{silence}"
|
23
|
+
if debug
|
24
|
+
puts command
|
25
|
+
end
|
26
|
+
system command
|
27
|
+
unless File.exists?(export_filename)
|
28
|
+
if !debug
|
29
|
+
puts 'rerunning failed image generation with enabled debug'
|
30
|
+
return self.run_tilemill_export_image(lat, lon, zlevel, bbox_size, image_size, export_filename, true)
|
31
|
+
end
|
32
|
+
raise 'generation of file ' + export_filename + ' failed'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,10 +1,89 @@
|
|
1
1
|
require_relative 'visualise_changes_diff_from_images'
|
2
2
|
require_relative 'git'
|
3
3
|
require_relative 'downloader'
|
4
|
+
require_relative 'util/filehelper'
|
4
5
|
|
5
6
|
module CartoCSSHelper
|
6
7
|
class VisualDiff
|
7
|
-
|
8
|
+
@@job_pooling = false
|
9
|
+
@@jobs = []
|
10
|
+
|
11
|
+
def self.enable_job_pooling
|
12
|
+
#it results in avoiding loading the same database mutiple times
|
13
|
+
#useful if the same database will be used multiple times (for example the same place in multiple comparisons)
|
14
|
+
#use run_jobs function to run jobs
|
15
|
+
@@job_pooling = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.disable_job_pooling
|
19
|
+
@@job_pooling = false
|
20
|
+
end
|
21
|
+
|
22
|
+
class MapGenerationJob
|
23
|
+
attr_reader :filename, :active
|
24
|
+
def initialize(filename, latitude, longitude, zlevels, header, new_branch, old_branch, download_bbox_size, image_size)
|
25
|
+
@filename = filename
|
26
|
+
@latitude = latitude
|
27
|
+
@longitude = longitude
|
28
|
+
@zlevels = zlevels
|
29
|
+
@header = header
|
30
|
+
@old_branch = old_branch
|
31
|
+
@new_branch = new_branch
|
32
|
+
@download_bbox_size = download_bbox_size
|
33
|
+
@image_size = image_size
|
34
|
+
@active = true
|
35
|
+
end
|
36
|
+
def run_job
|
37
|
+
if !@active
|
38
|
+
return
|
39
|
+
end
|
40
|
+
print
|
41
|
+
source = CartoCSSHelper::VisualDiff::FileDataSource.new(@latitude, @longitude, @download_bbox_size, @filename)
|
42
|
+
CartoCSSHelper::VisualDiff.visualise_changes_for_given_source(@latitude, @longitude, @zlevels, @header, @new_branch, @old_branch, @image_size, source)
|
43
|
+
@active = false
|
44
|
+
end
|
45
|
+
def print
|
46
|
+
puts "#{@filename.gsub(Configuration.get_path_to_folder_for_cache, '#')} [#{@latitude};#{@longitude}], z: #{@zlevels}, text: #{@header}, '#{@old_branch}'->'#{@new_branch}', bbox:#{@download_bbox_size}, #{@image_size}px"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.add_job(filename, latitude, longitude, zlevels, header, new_branch, old_branch, download_bbox_size, image_size)
|
51
|
+
print 'pool <- '
|
52
|
+
new_job = MapGenerationJob.new(filename, latitude, longitude, zlevels, header, new_branch, old_branch, download_bbox_size, image_size)
|
53
|
+
new_job.print
|
54
|
+
|
55
|
+
raise "#{filename} does not exists" unless File.exists?(filename)
|
56
|
+
raise "#{latitude} is not a number" unless latitude.kind_of? Numeric
|
57
|
+
raise "#{longitude} is not a number" unless longitude.kind_of? Numeric
|
58
|
+
raise "#{zlevels} is not a range" unless zlevels.class == Range
|
59
|
+
raise "#{header} is not a string" unless header.class == String
|
60
|
+
raise "#{new_branch} is not a string" unless new_branch.class == String
|
61
|
+
raise "#{old_branch} is not a string" unless old_branch.class == String
|
62
|
+
raise "#{download_bbox_size} is not a number" unless download_bbox_size.kind_of? Numeric
|
63
|
+
raise "#{image_size} is not a integer" unless image_size.kind_of? Integer
|
64
|
+
|
65
|
+
@@jobs.push(new_job)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.run_jobs
|
69
|
+
for i in 0..@@jobs.length-1
|
70
|
+
if @@jobs[i].active
|
71
|
+
@@jobs[i].run_job
|
72
|
+
for x in 0..@@jobs.length-1
|
73
|
+
if @@jobs[i].filename == @@jobs[x].filename
|
74
|
+
@@jobs[x].run_job
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
@@jobs = []
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.shuffle_jobs
|
83
|
+
@@jobs.shuffle!
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.visualise_changes_synthethic_test(tags, type, on_water, zlevel_range, new_branch, old_branch)
|
8
87
|
tags = VisualDiff.remove_magic_from_tags(tags)
|
9
88
|
on_water_string = ''
|
10
89
|
if on_water
|
@@ -16,7 +95,7 @@ module CartoCSSHelper
|
|
16
95
|
old = VisualDiff.collect_images_for_synthethic_test(tags, type, on_water, zlevel_range)
|
17
96
|
Git.checkout(new_branch)
|
18
97
|
new = VisualDiff.collect_images_for_synthethic_test(tags, type, on_water, zlevel_range)
|
19
|
-
VisualDiff.pack_image_sets old, new, header,
|
98
|
+
VisualDiff.pack_image_sets old, new, header, new_branch, old_branch, 200
|
20
99
|
end
|
21
100
|
|
22
101
|
def self.remove_magic_from_tags(tags)
|
@@ -39,20 +118,18 @@ module CartoCSSHelper
|
|
39
118
|
return collection
|
40
119
|
end
|
41
120
|
|
42
|
-
class
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@download_bbox_size = wanted_download_bbox_size
|
121
|
+
class FileDataSource
|
122
|
+
attr_reader :download_bbox_size, :data_filename
|
123
|
+
def initialize(latitude, longitude, download_bbox_size, filename)
|
124
|
+
@download_bbox_size = download_bbox_size
|
47
125
|
@latitude = latitude
|
48
126
|
@longitude = longitude
|
49
|
-
@data_filename =
|
127
|
+
@data_filename = filename
|
50
128
|
@loaded = false
|
51
129
|
end
|
52
130
|
|
53
131
|
def load
|
54
132
|
if !@loaded
|
55
|
-
puts "\tloading data into database"
|
56
133
|
DataFileLoader.load_data_into_database(@data_filename)
|
57
134
|
puts "\tgenerating images"
|
58
135
|
@loaded = true
|
@@ -60,28 +137,48 @@ module CartoCSSHelper
|
|
60
137
|
end
|
61
138
|
|
62
139
|
def get_timestamp
|
63
|
-
|
64
|
-
return f.mtime.to_i
|
140
|
+
return Downloader.get_timestamp_of_file(@data_filename)
|
65
141
|
end
|
66
142
|
end
|
67
143
|
|
68
|
-
def self.visualise_changes_on_real_data(tags, type, wanted_latitude, wanted_longitude, zlevels,
|
144
|
+
def self.visualise_changes_on_real_data(tags, type, wanted_latitude, wanted_longitude, zlevels, new_branch, old_branch='master')
|
69
145
|
#special support for following tag values: :any_value
|
70
146
|
header = "#{ VisualDiff.dict_to_pretty_tag_list(tags) } #{type} #{ wanted_latitude } #{ wanted_longitude } #{zlevels}"
|
71
147
|
puts "visualise_changes_on_real_data <#{header}> #{old_branch} -> #{new_branch}"
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
new = VisualDiff.collect_images_for_real_data_test(tags, type, latitude, longitude, zlevels, source)
|
148
|
+
begin
|
149
|
+
latitude, longitude = Downloader.locate_element_with_given_tags_and_type tags, type, wanted_latitude, wanted_longitude
|
150
|
+
rescue Downloader::OverpassRefusedResponse
|
151
|
+
puts 'No nearby instances of tags and tag is not extremely rare - no generation of nearby location and wordwide search was impossible. No diff image will be generated for this location.'
|
152
|
+
return false
|
153
|
+
end
|
79
154
|
header = "#{ VisualDiff.dict_to_pretty_tag_list(tags) } #{type} #{ wanted_latitude } #{ wanted_longitude } #{zlevels}"
|
80
|
-
|
155
|
+
download_bbox_size = 0.4
|
156
|
+
visualise_changes_for_location(latitude, longitude, zlevels, header, new_branch, old_branch, download_bbox_size)
|
157
|
+
return true
|
81
158
|
end
|
82
159
|
|
83
|
-
def self.
|
84
|
-
|
160
|
+
def self.visualise_changes_for_location(latitude, longitude, zlevels, header, new_branch, old_branch, download_bbox_size, image_size=400)
|
161
|
+
filename = Downloader.get_file_with_downloaded_osm_data_for_location(latitude, longitude, download_bbox_size)
|
162
|
+
visualise_changes_for_location_from_file(filename, latitude, longitude, zlevels, header, new_branch, old_branch, download_bbox_size, image_size)
|
163
|
+
end
|
164
|
+
|
165
|
+
def self.visualise_changes_for_location_from_file(filename, latitude, longitude, zlevels, header, new_branch, old_branch, download_bbox_size, image_size=400)
|
166
|
+
prefix = ''
|
167
|
+
if @@job_pooling
|
168
|
+
prefix = 'pool <- '
|
169
|
+
end
|
170
|
+
add_job(filename, latitude, longitude, zlevels, header, new_branch, old_branch, download_bbox_size, image_size)
|
171
|
+
if !@@job_pooling
|
172
|
+
run_jobs
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.visualise_changes_for_given_source(latitude, longitude, zlevels, header, new_branch, old_branch, image_size, source)
|
177
|
+
Git.checkout old_branch
|
178
|
+
old = VisualDiff.collect_images_for_real_data_test(latitude, longitude, zlevels, source, image_size)
|
179
|
+
Git.checkout new_branch
|
180
|
+
new = VisualDiff.collect_images_for_real_data_test(latitude, longitude, zlevels, source, image_size)
|
181
|
+
VisualDiff.pack_image_sets old, new, header, new_branch, old_branch, image_size
|
85
182
|
end
|
86
183
|
|
87
184
|
def self.scale(zlevel, reference_value, reference_zlevel)
|
@@ -90,7 +187,7 @@ module CartoCSSHelper
|
|
90
187
|
return reference_value*rescaler
|
91
188
|
end
|
92
189
|
|
93
|
-
def self.collect_images_for_real_data_test(
|
190
|
+
def self.collect_images_for_real_data_test(latitude, longitude, zlevels, source, wanted_image_size=400)
|
94
191
|
collection = []
|
95
192
|
zlevels.each { |zlevel|
|
96
193
|
image_size_for_16_zoom_level = 1000
|
@@ -98,7 +195,6 @@ module CartoCSSHelper
|
|
98
195
|
mutiplier = 1000
|
99
196
|
image_size = (image_size*mutiplier).to_int
|
100
197
|
render_bbox_size = 0.015
|
101
|
-
wanted_image_size = 400
|
102
198
|
ratio = 1.0*image_size/(wanted_image_size*mutiplier)
|
103
199
|
image_size /= ratio
|
104
200
|
render_bbox_size /= ratio
|
@@ -112,7 +208,8 @@ module CartoCSSHelper
|
|
112
208
|
puts ratio
|
113
209
|
raise "#{image_size} mismatches #{wanted_image_size}"
|
114
210
|
end
|
115
|
-
|
211
|
+
cache_folder = CartoCSSHelper::Configuration.get_path_to_folder_for_branch_specific_cache
|
212
|
+
filename = "#{cache_folder+"#{latitude} #{longitude} #{zlevel}zlevel #{image_size}px #{source.get_timestamp} #{source.download_bbox_size}.png"}"
|
116
213
|
if !File.exists?(filename)
|
117
214
|
source.load
|
118
215
|
Scene.run_tilemill_export_image(latitude, longitude, zlevel, render_bbox_size, image_size, filename)
|
@@ -122,14 +219,16 @@ module CartoCSSHelper
|
|
122
219
|
return collection
|
123
220
|
end
|
124
221
|
|
125
|
-
def self.pack_image_sets(old, new, header,
|
126
|
-
old_branch = old_branch
|
127
|
-
new_branch = new_branch
|
222
|
+
def self.pack_image_sets(old, new, header, new_branch, old_branch, image_size)
|
223
|
+
old_branch = FileHelper::make_string_usable_as_filename(old_branch)
|
224
|
+
new_branch = FileHelper::make_string_usable_as_filename(new_branch)
|
225
|
+
header_for_filename = FileHelper::make_string_usable_as_filename(header)
|
128
226
|
filename_sufix = "#{ old_branch } -> #{ new_branch }"
|
129
|
-
filename = CartoCSSHelper::Configuration.get_path_to_folder_for_output + "#{
|
227
|
+
filename = CartoCSSHelper::Configuration.get_path_to_folder_for_output + "#{header_for_filename} #{filename_sufix} #{image_size}px.png"
|
130
228
|
diff = FullSetOfComparedImages.new(old, new, header, filename, image_size)
|
131
229
|
diff.save
|
132
230
|
end
|
231
|
+
|
133
232
|
def self.dict_to_pretty_tag_list(dict)
|
134
233
|
result = ''
|
135
234
|
dict.to_a.each { |tag|
|
@@ -0,0 +1,242 @@
|
|
1
|
+
def get_list_of_testing_locations
|
2
|
+
return [
|
3
|
+
[50.1, 19.9], #Krakow
|
4
|
+
[53.2, -1.8], #rural uk
|
5
|
+
[36.1, 140.7], #Japan
|
6
|
+
[54.8, 31.7], #Russia
|
7
|
+
[21.3, 39.5], #Mecca
|
8
|
+
[41.4, 44.5], #Georgia
|
9
|
+
[51.5, -0.1], #London
|
10
|
+
#TODO: solve problems with response too big to store in memory
|
11
|
+
#[52.09, 5.11], #Utrecht
|
12
|
+
|
13
|
+
#http://overpass-turbo.eu/s/ar4
|
14
|
+
#capital locations
|
15
|
+
[-41.2887639, 174.7772239],
|
16
|
+
[37.9841493, 23.7279843],
|
17
|
+
[46.0498650, 14.5068921],
|
18
|
+
[55.6867243, 12.5700724],
|
19
|
+
[28.6138967, 77.2159562],
|
20
|
+
[33.6945756, 73.0643744],
|
21
|
+
[48.2083537, 16.3725042],
|
22
|
+
#[48.8565056, 2.3521334], TODO: solve problems with rest-client crashing and blabbing about negative integers
|
23
|
+
[46.9482713, 7.4514512],
|
24
|
+
[45.4210328, -75.6900219],
|
25
|
+
[59.9132694, 10.7391112],
|
26
|
+
[33.3024248, 44.3787992],
|
27
|
+
[40.4167047, -3.7035825],
|
28
|
+
[-35.2819367, 149.1288940],
|
29
|
+
[34.5197058, 69.1624302],
|
30
|
+
[39.9059093, 116.3913489],
|
31
|
+
[-25.7250000, 28.1847222],
|
32
|
+
[39.9220794, 32.8537580],
|
33
|
+
[59.3251172, 18.0710935],
|
34
|
+
[35.6861720, 51.4223519],
|
35
|
+
[50.4501071, 30.5240501],
|
36
|
+
[53.9023386, 27.5619023],
|
37
|
+
[23.1379911, -82.3658562],
|
38
|
+
[56.9493977, 24.1051846],
|
39
|
+
[-4.3217055, 15.3125974],
|
40
|
+
[54.6843135, 25.2853984],
|
41
|
+
[55.1598408, 61.4025547],
|
42
|
+
[42.8766343, 74.6070116],
|
43
|
+
[41.3123363, 69.2787079],
|
44
|
+
[38.5762757, 68.7863940],
|
45
|
+
[47.9184676, 106.9177016],
|
46
|
+
[51.1282789, 71.4305478],
|
47
|
+
[13.5248339, 2.1098226],
|
48
|
+
[-8.8271656, 13.2436665],
|
49
|
+
[12.6500083, -8.0000014],
|
50
|
+
[36.8001077, 10.1847938],
|
51
|
+
[6.3280343, -10.7977882],
|
52
|
+
[4.3909085, 18.5505422],
|
53
|
+
[-15.4166967, 28.2813812],
|
54
|
+
[12.3681481, -1.5270853],
|
55
|
+
[12.1191543, 15.0502758],
|
56
|
+
[14.6930042, -17.4470260],
|
57
|
+
[8.4790017, -13.2680158],
|
58
|
+
[9.5171253, -13.6999235],
|
59
|
+
[0.3900022, 9.4540009],
|
60
|
+
[9.0107934, 38.7612525],
|
61
|
+
[5.5600141, -0.2057437],
|
62
|
+
[-25.9662133, 32.5674498],
|
63
|
+
[11.5936649, 43.1472403],
|
64
|
+
[-1.2832533, 36.8172449],
|
65
|
+
[-18.9100122, 47.5255809],
|
66
|
+
[15.5933247, 32.5356502],
|
67
|
+
[14.9160169, -23.5096132],
|
68
|
+
[62.0120000, -6.7680000],
|
69
|
+
[31.7774287, 35.2247239],
|
70
|
+
[59.4372155, 24.7453688],
|
71
|
+
[-29.3100536, 27.4782219],
|
72
|
+
[-24.6585857, 25.9084905],
|
73
|
+
[39.0196396, 125.7525841],
|
74
|
+
[36.5658725, 53.0585690],
|
75
|
+
[-33.9289049, 18.4172485],
|
76
|
+
[-22.5744184, 17.0791233],
|
77
|
+
[-15.7934036, -47.8823172],
|
78
|
+
[2.0427779, 45.3385636],
|
79
|
+
[26.2235041, 50.5822436],
|
80
|
+
[-33.4377968, -70.6504451],
|
81
|
+
[12.5268736, -70.0356845],
|
82
|
+
[12.1091242, -68.9316546],
|
83
|
+
[12.1471741, -68.2740783],
|
84
|
+
[6.9342870, 79.8532704],
|
85
|
+
[49.6112768, 6.1297990],
|
86
|
+
[18.4652988, -66.1166657],
|
87
|
+
[17.9712148, -76.7928128],
|
88
|
+
[-0.2201687, -78.5120913],
|
89
|
+
[42.5069391, 1.5212467],
|
90
|
+
[-12.0458271, -77.0304845],
|
91
|
+
[-1.9508511, 30.0615075],
|
92
|
+
[44.8178787, 20.4568089],
|
93
|
+
[-3.3638125, 29.3675028],
|
94
|
+
[27.7087963, 85.3202438],
|
95
|
+
[41.8933439, 12.4830718],
|
96
|
+
[21.0292095, 105.8524700],
|
97
|
+
[-34.6128690, -58.4459789],
|
98
|
+
[47.4983815, 19.0404707],
|
99
|
+
[-6.1791181, 35.7468174],
|
100
|
+
[43.4930746, 43.6193570],
|
101
|
+
[44.4361390, 26.1027436],
|
102
|
+
[4.8472017, 31.5951655],
|
103
|
+
[-17.7414972, 168.3150163],
|
104
|
+
[25.0783456, -77.3383331],
|
105
|
+
[17.9640988, 102.6133707],
|
106
|
+
[42.4415238, 19.2621081],
|
107
|
+
[47.0122737, 28.8605936],
|
108
|
+
[40.1776121, 44.5125849],
|
109
|
+
[38.8949549, -77.0366456],
|
110
|
+
[41.6509502, 41.6360085],
|
111
|
+
[41.9960424, 21.4316707],
|
112
|
+
[12.1461244, -86.2737170],
|
113
|
+
[17.2960919, -62.7223010],
|
114
|
+
[9.9325612, -84.0795739],
|
115
|
+
[13.6977587, -89.1930100],
|
116
|
+
[14.5906216, 120.9799696],
|
117
|
+
[23.5997857, 58.5451305],
|
118
|
+
[-9.4797487, 147.1503589],
|
119
|
+
[15.2984622, -61.3875049],
|
120
|
+
[52.5170365, 13.3888599],
|
121
|
+
[50.2796448, 57.2124606],
|
122
|
+
[-20.1637281, 57.5045331],
|
123
|
+
[-26.3257447, 31.1446630],
|
124
|
+
[39.5089040, 54.3631062],
|
125
|
+
[12.0535331, -61.7518050],
|
126
|
+
[13.1561653, -61.2248777],
|
127
|
+
[14.0095719, -60.9903195],
|
128
|
+
[13.1018264, -59.6188480],
|
129
|
+
[18.0794011, -15.9780393],
|
130
|
+
[13.4553495, -16.5756457],
|
131
|
+
[-25.2960638, -57.6311446],
|
132
|
+
[11.8613244, -15.5830554],
|
133
|
+
[15.3421010, 44.2005197],
|
134
|
+
[24.4747961, 54.3705762],
|
135
|
+
[-8.5536809, 125.5784093],
|
136
|
+
[15.3389974, 38.9326725],
|
137
|
+
[35.6823815, 139.7530053],
|
138
|
+
[18.0250713, -63.0483073],
|
139
|
+
[38.7130574, -9.1380056],
|
140
|
+
[-21.2074736, -159.7708145],
|
141
|
+
[52.3710088, 4.9001115],
|
142
|
+
[-7.7441461, 113.2158401],
|
143
|
+
[30.0488185, 31.2436663],
|
144
|
+
[48.4814020, 135.0769400],
|
145
|
+
[18.3411365, -64.9327890],
|
146
|
+
[43.9363996, 12.4466991],
|
147
|
+
[5.8216198, -55.1771974],
|
148
|
+
[17.2502830, -88.7694263],
|
149
|
+
[-17.8317726, 31.0456859],
|
150
|
+
[18.5473270, -72.3395928],
|
151
|
+
[33.8959203, 35.4784300],
|
152
|
+
[3.7528278, 8.7800610],
|
153
|
+
[6.8025766, -58.1628612],
|
154
|
+
[0.3389242, 6.7313031],
|
155
|
+
[-34.9059039, -56.1913569],
|
156
|
+
[21.4607723, -71.1399956],
|
157
|
+
[34.0223602, -6.8390357],
|
158
|
+
[14.0931919, -87.2012631],
|
159
|
+
[-19.0478620, -65.2596023],
|
160
|
+
[18.4801972, -69.9421110],
|
161
|
+
[24.6319692, 46.7150648],
|
162
|
+
[19.7540045, 96.1344976],
|
163
|
+
[6.8091068, -5.2732628],
|
164
|
+
[3.8689867, 11.5213344],
|
165
|
+
[-11.6931255, 43.2543044],
|
166
|
+
[7.0909924, 171.3816354],
|
167
|
+
[-13.8343691, -171.7692793],
|
168
|
+
[41.9034912, 12.4528349],
|
169
|
+
[17.1184569, -61.8448509],
|
170
|
+
[52.2319237, 21.0067265],
|
171
|
+
[-4.2694407, 15.2712256],
|
172
|
+
[-19.0534159, -169.9191992],
|
173
|
+
[14.6417889, -90.5132239],
|
174
|
+
[17.1393977, -62.6216154],
|
175
|
+
[48.1535383, 17.1096711],
|
176
|
+
[1.2904527, 103.8520380],
|
177
|
+
[29.3797091, 47.9735629],
|
178
|
+
[11.5682710, 104.9224426],
|
179
|
+
[-8.5211767, 179.1976747],
|
180
|
+
[4.5980478, -74.0760867],
|
181
|
+
[16.7053047, -62.2130447],
|
182
|
+
[1.3497964, 173.0277185],
|
183
|
+
[6.9207440, 158.1627143],
|
184
|
+
[7.4966382, 134.6349089],
|
185
|
+
[0.3177137, 32.5813539],
|
186
|
+
[19.2869856, -81.3717001],
|
187
|
+
[-9.4312971, 159.9552773],
|
188
|
+
[-2.2100307, 113.9267408],
|
189
|
+
[64.1750290, -51.7355386],
|
190
|
+
[-21.1343401, -175.2018085],
|
191
|
+
[33.5130695, 36.3095814],
|
192
|
+
[25.0375167, 121.5637000],
|
193
|
+
[8.9500000, 38.7666700],
|
194
|
+
[8.9707433, -79.5344539],
|
195
|
+
[60.1666277, 24.9435079],
|
196
|
+
[27.4730932, 89.6296788],
|
197
|
+
[35.8987546, 14.5134889],
|
198
|
+
[45.8131545, 15.9770298],
|
199
|
+
[50.0874401, 14.4212556],
|
200
|
+
[41.6934350, 44.8014979],
|
201
|
+
[13.7529438, 100.4941219],
|
202
|
+
[50.8465565, 4.3516970],
|
203
|
+
[31.9515694, 35.9239625],
|
204
|
+
[6.4990718, 2.6253361],
|
205
|
+
[25.2856329, 51.5264162],
|
206
|
+
[55.7516335, 37.6187042],
|
207
|
+
[4.8895453, 114.9417574],
|
208
|
+
[32.8966720, 13.1777923],
|
209
|
+
[42.6977211, 23.3225964],
|
210
|
+
[43.7311966, 7.4196400],
|
211
|
+
[37.9396678, 58.3874263],
|
212
|
+
[11.1852893, -60.7350240],
|
213
|
+
[41.3279457, 19.8185323],
|
214
|
+
[3.1570976, 101.7009528],
|
215
|
+
[35.1739302, 33.3647260],
|
216
|
+
[37.5666791, 126.9782914],
|
217
|
+
[47.1392862, 9.5227962],
|
218
|
+
[-14.2753717, -170.7048530],
|
219
|
+
[15.1759138, 145.7432916],
|
220
|
+
[18.2108070, -63.0535045],
|
221
|
+
[26.3544056, -9.5741765],
|
222
|
+
[43.8515421, 18.3886246],
|
223
|
+
[-2.9888297, 104.7568570],
|
224
|
+
[64.1459810, -21.9422367],
|
225
|
+
[40.3754289, 49.8328549],
|
226
|
+
[6.1258594, 1.2248504],
|
227
|
+
[54.1497740, -4.4779021],
|
228
|
+
[-18.1415884, 178.4421662],
|
229
|
+
[46.8516039, 29.6349435],
|
230
|
+
[38.3716205, 26.1342054],
|
231
|
+
[49.1855551, -2.1098279],
|
232
|
+
[10.6572142, -61.5180297],
|
233
|
+
[-1.6141280, 103.5796708],
|
234
|
+
[42.6636827, 21.1639418],
|
235
|
+
[-13.9734560, 33.7878122],
|
236
|
+
[43.7311424, 7.4197576],
|
237
|
+
[6.9031663, 79.9091644],
|
238
|
+
[-8.5202604, 179.1974823],
|
239
|
+
[4.1779879, 73.5107387],
|
240
|
+
[53.3497645, -6.2602732],
|
241
|
+
]
|
242
|
+
end
|
data/readme.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
##CartoCSS Helper
|
2
2
|
|
3
|
-
It is a tool making development of CartoCSS styles more efficient.
|
3
|
+
It is a tool making development of CartoCSS styles more efficient. Allows to write simple Ruby scripts that generate comparison images of how rendering changed between two versions of map style. It is also possible to generate validation reports detecting for example too low values of text-dy. Loading data using osm2pgsql, rendering with TileMill, obtaining test data from overpass turbo.
|
4
4
|
|
5
5
|
Proper testing of map rendering requires testing covering mutiple situations. Doing it manually means preparing test data and locating places with applicable real data, loading map data into database, then moving viewport of TileMill to check every data location across multiple zoom levels. It is painfully slow.
|
6
6
|
|
@@ -8,17 +8,48 @@ Fortunately it is possible to automate it almost entirely. With this tool testin
|
|
8
8
|
|
9
9
|
It is work in progress, major problems that should be solved include:
|
10
10
|
|
11
|
-
*
|
11
|
+
* Improving documentation
|
12
12
|
* Executing git checkout commands on map style git repository during normal script operation (https://github.com/matkoniecz/CartoCSSHelper/issues/9)
|
13
13
|
* Current rendering method is obnoxiously slow. (https://github.com/matkoniecz/CartoCSSHelper/issues/1)
|
14
14
|
|
15
|
+
###Installation
|
16
|
+
|
17
|
+
Assumes that osm2pgsql and TileMill are installed.
|
18
|
+
|
19
|
+
This tool is available as cartocss_helper Ruby gem.
|
20
|
+
|
21
|
+
Install ruby - see https://www.ruby-lang.org/en/documentation/installation/ for details.
|
22
|
+
|
23
|
+
Unfortunately, standard `gem install cartocss_helper` may not be enough as CartoCSS Helper depends on RMagick gem that requires special installation.
|
24
|
+
|
25
|
+
Install RMagick gem. `gem install rmagick` may not be enough - in my case, on Ubuntu 14.04 it was necessary to start from installing additional packages (`apt-get install ruby-dev imagemagick libmagickcore-dev libmagickwand-dev` solved the problem), followed by `gem install rmagick`.
|
26
|
+
|
27
|
+
Finally, run `gem install cartocss_helper`.
|
28
|
+
|
15
29
|
###Example
|
16
30
|
|
17
|
-
|
18
|
-
|
19
|
-
|
31
|
+
It is assumed that TileMill project with Default OSM Style (https://github.com/gravitystorm/openstreetmap-carto/) is located at `~/Documents/MapBox/project/osm-carto`.
|
32
|
+
|
33
|
+
require cartocss_helper
|
34
|
+
CartoCSSHelper::Configuration.set_style_specific_data(CartoCSSHelper::StyleDataForDefaultOSM.get_style_data)
|
35
|
+
CartoCSSHelper::Configuration.set_path_to_tilemill_project_folder(File.join(ENV['HOME'], 'Documents', 'MapBox', 'project', 'osm-carto', ''))
|
36
|
+
CartoCSSHelper::Configuration.set_path_to_folder_for_output(File.join(ENV['HOME'], 'Documents', 'CartoCSSHelper-output', ''))
|
37
|
+
CartoCSSHelper::Configuration.set_path_to_folder_for_cache(File.join(ENV['HOME'], 'Documents', 'CartoCSSHelper-tmp', ''))
|
38
|
+
|
39
|
+
tags = {'landuse' => 'village_green', 'tourism' => 'attraction'}
|
40
|
+
CartoCSSHelper.test tags, 'master', 'v2.28.1'
|
41
|
+
|
42
|
+
First part of this Ruby script is responsible for loading gem and configuration, including location of cache folder and folder where produced comparison images will be saved.
|
43
|
+
|
44
|
+
Second part runs quick test for specified tag combination rendering only this element as node, way and a closed way. It is followed by locating multiple places across globe where such tag combination is used.
|
45
|
+
|
46
|
+
For each test case images are produced both for current `master` branch and release `v2.28.1` across multiple zoom levels. Finally tool generates before/after comparisons for each case. Some of generated images were used in https://github.com/gravitystorm/openstreetmap-carto/issues/1371.
|
47
|
+
|
48
|
+
It is also possible to look for certain keys, with any value:
|
49
|
+
|
50
|
+
tags = {'landuse' => 'village_green', 'tourism' => 'attraction', 'name' => :any_value}
|
51
|
+
CartoCSSHelper.test tags, 'master', 'v2.28.1'
|
20
52
|
|
21
|
-
Runs quick test for specified tag combination rendering only this element, followed by locating multiple places across globe where such tags are used. For each test case images are produced both for current `master` branch and release `v2.28.1` across multiple zoom levels. Finally tool generates before/after comparisons for each case. Some of generated images were used in https://github.com/gravitystorm/openstreetmap-carto/issues/1371.
|
22
53
|
|
23
54
|
###Automated stuff
|
24
55
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cartocss_helper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-07-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rest-client
|
@@ -74,13 +74,16 @@ files:
|
|
74
74
|
- lib/cartocss_helper/image_generator.rb
|
75
75
|
- lib/cartocss_helper/validator.rb
|
76
76
|
- lib/cartocss_helper/downloader.rb
|
77
|
+
- lib/cartocss_helper/tilemill_handler.rb
|
77
78
|
- lib/cartocss_helper/git.rb
|
79
|
+
- lib/cartocss_helper/util/filehelper.rb
|
78
80
|
- lib/cartocss_helper/heuristic.rb
|
79
81
|
- lib/cartocss_helper/visualise_changes_diff_from_images.rb
|
80
82
|
- lib/cartocss_helper/configuration.rb
|
81
83
|
- lib/cartocss_helper/style_specific/style_specific.rb
|
82
84
|
- lib/cartocss_helper/style_specific/default_osm_style.rb
|
83
85
|
- lib/cartocss_helper/data_file_handling.rb
|
86
|
+
- lib/data/testing_locations.rb
|
84
87
|
- license.txt
|
85
88
|
- readme.md
|
86
89
|
homepage: https://github.com/matkoniecz/CartoCSSHelper
|