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.
@@ -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, zlevels, old_branch, new_branch)
17
- ['node', 'closed_way', 'way'].each {|type|
18
- test_tag_on_real_data_for_this_type(tags, zlevels, old_branch, new_branch, type)
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, zlevels, old_branch, new_branch, type)
23
- #special support for following tag values: :any_value
24
- krakow_latitude = 50.1
25
- krakow_longitude = 19.9
26
- CartoCSSHelper::VisualDiff.visualise_changes_on_real_data(tags, type, krakow_latitude, krakow_longitude, zlevels, old_branch, new_branch)
27
- japan_latitude = 36.1
28
- japan_longitude = 140.7
29
- CartoCSSHelper::VisualDiff.visualise_changes_on_real_data(tags, type, japan_latitude, japan_longitude, zlevels, old_branch, new_branch)
30
- russia_latitude = 54.8
31
- russia_longitude = 31.7
32
- CartoCSSHelper::VisualDiff.visualise_changes_on_real_data(tags, type, russia_latitude, russia_longitude, zlevels, old_branch, new_branch)
33
- mecca_latitude = 21.3
34
- mecca_longitude = 39.5
35
- CartoCSSHelper::VisualDiff.visualise_changes_on_real_data(tags, type, mecca_latitude, mecca_longitude, zlevels, old_branch, new_branch)
36
- georgia_latitude = 41.4
37
- georgia_longitude = 44.5
38
- CartoCSSHelper::VisualDiff.visualise_changes_on_real_data(tags, type, georgia_latitude, georgia_longitude, zlevels, old_branch, new_branch)
39
- london_latitude = 51.5
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
- return tags.merge({'name' => 'ÉÉÉÉÉÉ ÉÉÉÉÉÉ ÉÉÉÉÉÉ', 'ref' => '1', 'ele' => '8000', 'operator' => 'operator ÉÉ ÉÉ ÉÉ', 'brand' => 'brand ÉÉ ÉÉ ÉÉ ÉÉ'})
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.test(tags, new_branch, old_brach='master', test_on_water=false, zlevels=Configuration.get_min_z..Configuration.get_max_z)
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
- ['node', 'closed_way', 'way'].each {|type|
59
- CartoCSSHelper::VisualDiff.visualise_changes_synthethic_test(syn_tags, type, test_on_water, zlevels, old_brach, new_branch)
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.probe(tags, new_branch, old_brach='master',test_on_water=false, zlevels=Configuration.get_min_z..Configuration.get_max_z)
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
- ['node', 'closed_way', 'way'].each {|type|
67
- CartoCSSHelper::VisualDiff.visualise_changes_synthethic_test(syn_tags, type, test_on_water, zlevels, old_brach, new_branch)
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
- end
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 command
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 generate
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
- generate_sufix
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 = '[timeout:3600];'
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 = 100 #"Radius temporarly limited to 100 km to mitigate a bug.". Previously Overpass crashed for values larger than 3660
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, 100000].min
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 = '[timeout:3600][out:csv(::lat,::lon;false)];'
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.get_overpass_query_results(query, debug=false)
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
- cached = Downloader.run_overpass_query query
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 cached
160
+ file.write response
136
161
  file.close
137
- return cached
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
- stat = Sys::Filesystem.stat(CartoCSSHelper::Configuration.get_path_to_folder_for_overpass_cache)
160
- gb_available = stat.block_size * stat.blocks_available / 1024 / 1024 / 1024
161
- if gb_available < 2
162
- #TODO cleanup cache rather than crash
163
- raise 'less than 2GB of free space on disk with cache folder'
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.run_overpass_query(query, retry_count=0, retry_max=5)
168
- #default timeout is set to 180: http://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#timeout
169
- #[timeout:3600]; should be used in all queries executed here
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
- return RestClient::Request.execute(:method => :get, :url => Downloader.format_query_into_url(query), :timeout => 3600)
173
- rescue RestClient::RequestFailed => e
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/, '')
@@ -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
- if !system("git checkout #{branch} #{silence}")
13
- raise 'failed checkout'
14
- end
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
- Scene.run_tilemill_export_image(lat, lon, @zlevel, bbox_size, 200, export_filename, debug)
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
@@ -0,0 +1,6 @@
1
+ # encoding: UTF-8
2
+ module FileHelper
3
+ def self.make_string_usable_as_filename(string)
4
+ return string.gsub(/[\x00\/\\:\*\?\"<>\|]/, '_')
5
+ end
6
+ end
@@ -34,7 +34,7 @@ module CartoCSSHelper
34
34
  @compared = compress(before, after)
35
35
 
36
36
  @image_size = image_size
37
- @margin = 20
37
+ @margin = 10
38
38
  @standard_pointsize = 10
39
39
  @header_space = @standard_pointsize*1.5
40
40
  @diff_note_space = @standard_pointsize
@@ -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
- def self.visualise_changes_synthethic_test(tags, type, on_water, zlevel_range, old_branch, new_branch)
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, old_branch, new_branch, 200
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 RealDataSource
43
- def initialize(latitude, longitude, wanted_download_bbox_size)
44
- wanted_download_bbox_size = [wanted_download_bbox_size, 0.001].max
45
- wanted_download_bbox_size = [wanted_download_bbox_size, 0.400].min #0.5 is too big for Utrecht
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 = Downloader.download_osm_data_for_location(@latitude, @longitude, @download_bbox_size)
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
- f = File.new(@data_filename)
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, old_branch, new_branch)
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
- latitude, longitude = Downloader.locate_element_with_given_tags_and_type tags, type, wanted_latitude, wanted_longitude
73
- download_bbox_size = VisualDiff.scale_inverse zlevels.min, 0.03, 14
74
- source = RealDataSource.new(latitude, longitude, download_bbox_size)
75
- Git.checkout old_branch
76
- old = VisualDiff.collect_images_for_real_data_test(tags, type, latitude, longitude, zlevels, source)
77
- Git.checkout new_branch
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
- VisualDiff.pack_image_sets old, new, header, old_branch, new_branch, 400
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.scale_inverse(zlevel, reference_value, reference_zlevel)
84
- return VisualDiff.scale reference_zlevel, reference_value, zlevel
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(tags, type, latitude, longitude, zlevels, source)
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
- filename = "#{CartoCSSHelper::Configuration.get_path_to_folder_for_branch_specific_cache+"#{tags.to_a.to_s} #{type} #{latitude} #{longitude} #{zlevel}zlevel #{image_size}px #{source.get_timestamp}.png"}"
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, old_branch, new_branch, image_size)
126
- old_branch = old_branch.gsub(/[\x00\/\\:\*\?\"<>\|]/, '_')
127
- new_branch = new_branch.gsub(/[\x00\/\\:\*\?\"<>\|]/, '_')
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 + "#{header} #{filename_sufix}.png"
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. Automates actions necessary to produce test images and validates style. Loading data using osm2pgsql, rendering with TileMill, obtaining test data from overpass turbo.
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
- * Lack of documentation
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
- `require cartocss_helper`
18
- `tags = {'landuse' => 'village_green', 'tourism' => 'attraction'}`
19
- `CartoCSSHelper.test tags, 'master', 'v2.28.1'`
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: 0.0.0
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-04-11 00:00:00.000000000 Z
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