cartocss_helper 1.2.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,301 +0,0 @@
1
- # encoding: UTF-8
2
- require 'rest-client'
3
- require 'digest/sha1'
4
- require 'sys/filesystem'
5
-
6
-
7
- module CartoCSSHelper
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
- def self.download_osm_data_for_location(latitude, longitude, size, accept_cache=true)
15
- filename = CartoCSSHelper::Configuration.get_path_to_folder_for_cache + "#{latitude} #{longitude} #{size}.osm"
16
- if File.exists?(filename)
17
- if accept_cache
18
- return filename
19
- end
20
- delete_file(filename, 'query refusing to accept cache was used')
21
- end
22
- query = get_query_to_download_data_around_location(latitude, longitude, size)
23
- text = get_overpass_query_results(query, "download data for #{latitude} #{longitude} (#{size})")
24
- file = File.new(filename, 'w')
25
- file.write text
26
- file.close
27
- return filename
28
- end
29
-
30
- def self.get_query_to_download_data_around_location(latitude, longitude, size)
31
- min_latitude = latitude - size.to_f/2
32
- max_latitude = latitude + size.to_f/2
33
- min_longitude = longitude - size.to_f/2
34
- max_longitude = longitude + size.to_f/2
35
- bb = "#{min_latitude},#{min_longitude},#{max_latitude},#{max_longitude}"
36
- query = "[timeout:#{Downloader.get_allowed_timeout_in_seconds}];"
37
- query += "\n"
38
- query += "(node(#{bb});<;);"
39
- query += "\n"
40
- query += 'out;'
41
- query += "\n"
42
- query += '/*'
43
- query += "\nbbox size: #{size}"
44
- query += "\nhttp://www.openstreetmap.org/#map=17/#{latitude}/#{longitude}"
45
- query += "\n"
46
- query += '*/'
47
- query += "\n"
48
- return query
49
- end
50
-
51
- def self.locate_element_with_given_tags_and_type(tags, type, latitude, longitude)
52
- max_range_in_km_for_radius = 1600
53
-
54
- #special support for following tag values: :any_value
55
- range = 10*1000
56
- loop do
57
- 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}")
58
- if list.length != 0
59
- return self.list_returned_by_overpass_to_a_single_location(list)
60
- end
61
- range=range+[2*range, 200000].min
62
- if range >= max_range_in_km_for_radius*1000
63
- list = Downloader.get_overpass_query_results(Downloader.get_query_to_get_location(tags, type, latitude, longitude, :infinity), "find #{tags} across the world")
64
- if list.length != 0
65
- return self.list_returned_by_overpass_to_a_single_location(list)
66
- else
67
- raise 'failed to find such location'
68
- end
69
- end
70
- end
71
- end
72
-
73
- def self.list_returned_by_overpass_to_a_single_location(list)
74
- list = list.match(/((|-)[\d\.]+)\s+((|-)[\d\.]+)/).to_a
75
- lat = Float(list[1])
76
- lon = Float(list[3])
77
- return lat, lon
78
- end
79
-
80
- def self.get_query_to_get_location(tags, type, latitude, longitude, range)
81
- #special support for following tag values: :any_value
82
- locator = "[timeout:#{Downloader.get_allowed_timeout_in_seconds}][out:csv(::lat,::lon;false)];"
83
- locator += "\n"
84
- if type == 'closed_way'
85
- type = 'way'
86
- end
87
- locator += Downloader.get_query_element_to_get_location(tags, latitude, longitude, type, range)
88
- locator +='out center;'
89
- locator += "\n"
90
- locator += '/*'
91
- range_string = ''
92
- if range == :infinity
93
- range_string = 'infinity'
94
- else
95
- range_string = "#{range/1000}km"
96
- end
97
- locator += "\nrange: #{range_string}"
98
- locator += "\nhttp://www.openstreetmap.org/#map=17/#{latitude}/#{longitude}"
99
- locator += "\n"
100
- locator += '*/'
101
- locator += "\n"
102
- return locator
103
- end
104
-
105
- def self.get_query_element_to_get_location(tags, latitude, longitude, type, range)
106
- #special support for following tag values: :any_value
107
- #TODO - escape value with quotation signs in them
108
- element="(#{type}"
109
- element += "\n"
110
- tags.each {|tag|
111
- if tag[1] == :any_value
112
- element+="\t['#{tag[0]}']"
113
- else
114
- element+="\t['#{tag[0]}'='#{tag[1]}']"
115
- end
116
- element += "\n"
117
- }
118
- if range != :infinity
119
- element+="\t(around:#{range},#{latitude},#{longitude});"
120
- element += "\n"
121
- end
122
- element+=');'
123
- element += "\n"
124
- return element
125
- end
126
-
127
- def self.get_overpass_query_results_file_location(query, description, debug=false)
128
- filename = get_query_cache_filename(query)
129
- get_overpass_query_results(query, description, debug)
130
- return filename
131
- end
132
-
133
- def self.get_overpass_query_results(query, description, debug=false)
134
- cached = get_overpass_query_results_from_cache(query)
135
- if cached == ''
136
- if File.exists?(get_query_cache_refused_response_filename(query))
137
- raise OverpassRefusedResponse
138
- end
139
- end
140
- return cached unless cached == nil
141
-
142
- check_for_free_space
143
-
144
- puts 'Running Overpass query (connection initiated on ' + Time.now.to_s + ') ' + description
145
- if debug
146
- puts query
147
- puts
148
- end
149
- begin
150
- cached = Downloader.run_overpass_query query, description
151
- rescue OverpassRefusedResponse
152
- mark_query_as_refused(query)
153
- write_to_cache(query, '')
154
- raise OverpassRefusedResponse
155
- end
156
- write_to_cache(query, cached)
157
- return cached
158
- end
159
-
160
- def self.get_query_cache_refused_response_filename(query)
161
- return get_query_cache_filename(query)+'_response_refused'
162
- end
163
-
164
- def self.mark_query_as_refused(query)
165
- file = File.new(get_query_cache_refused_response_filename(query), 'w')
166
- file.write ''
167
- file.close
168
- end
169
-
170
- def self.write_to_cache(query, response)
171
- file = File.new(get_query_cache_filename(query), 'w')
172
- file.write response
173
- file.close
174
- end
175
-
176
- def self.get_timestamp_of_file(timestamp_filename)
177
- if !File.exists?(timestamp_filename)
178
- return nil
179
- end
180
- f = File.new(timestamp_filename)
181
- timestamp = f.mtime.to_i
182
- f.close
183
- return timestamp
184
- end
185
-
186
- def self.get_overpass_query_results_from_cache(query)
187
- query_cache_filename = get_query_cache_filename(query)
188
- if File.exists?(query_cache_filename)
189
- file = File.new(query_cache_filename)
190
- cached = file.read
191
- file.close
192
- return cached
193
- end
194
- return nil
195
- end
196
-
197
- def self.get_query_cache_filename(query)
198
- # noinspection RubyResolve
199
- hash = Digest::SHA1.hexdigest query
200
- query_cache_filename = CartoCSSHelper::Configuration.get_path_to_folder_for_overpass_cache + hash + '_query.cache'
201
- return query_cache_filename
202
- end
203
-
204
- def self.check_for_free_space
205
- if not_enough_free_space
206
- attempt_cleanup
207
- if not_enough_free_space
208
- raise 'less than 2GB of free space on disk with cache folder'
209
- end
210
- end
211
- end
212
-
213
- def self.not_enough_free_space
214
- minimum_gb = 1
215
- return get_available_space_for_cache_in_gb < minimum_gb
216
- end
217
-
218
- def self.get_available_space_for_cache_in_gb
219
- stat = Sys::Filesystem.stat(CartoCSSHelper::Configuration.get_path_to_folder_for_cache)
220
- return stat.block_size * stat.blocks_available / 1024 / 1024 / 1024
221
- end
222
-
223
- def self.attempt_cleanup
224
- if not_enough_free_space
225
- delete_large_overpass_caches 500
226
- end
227
- if not_enough_free_space
228
- delete_large_overpass_caches 100
229
- end
230
- if not_enough_free_space
231
- delete_large_overpass_caches 50
232
- end
233
- end
234
-
235
- def self.delete_file(filename, reason)
236
- open(CartoCSSHelper::Configuration.get_path_to_folder_for_output+'log.txt', 'a') { |file|
237
- message = "deleting #{filename}, #{File.size(filename)/1024/1024}MB - #{reason}"
238
- puts message
239
- file.puts(message)
240
- File.delete(filename)
241
- }
242
- end
243
-
244
- def self.delete_large_overpass_caches(threshold_in_MB)
245
- #todo - find library that deals with caches like this, bug here may be unfunny
246
- Dir.glob(CartoCSSHelper::Configuration.get_path_to_folder_for_overpass_cache+'*') {|file|
247
- if File.size(file) > (1024 * 1024 * threshold_in_MB)
248
- delete_file(file, "removing everpass cache entries larger than #{threshold_in_MB} MB to make free space on the disk")
249
- end
250
- }
251
- end
252
-
253
- class OverpassRefusedResponse < IOError; end
254
-
255
- def self.run_overpass_query(query, description, retry_count=0, retry_max=5)
256
- start = Time.now.to_s
257
- begin
258
- url = Downloader.format_query_into_url(query)
259
- timeout = Downloader.get_allowed_timeout_in_seconds+10
260
- return RestClient::Request.execute(:method => :get, :url => url, :timeout => timeout)
261
- rescue RestClient::RequestTimeout
262
- puts 'Overpass API refused to process this request. It will be not attemped again, most likely query is too complex.'
263
- raise OverpassRefusedResponse
264
- rescue RestClient::RequestFailed, RestClient::ServerBrokeConnection => e
265
- puts query
266
- puts e.response
267
- puts e.http_code
268
- puts start
269
- puts "Rerunning #{description} started at #{Time.now.to_s} (#{retry_count}/#{retry_max}) after #{e}"
270
- if retry_count < retry_max
271
- sleep 60*5
272
- Downloader.run_overpass_query(query, description, retry_count+1, retry_max)
273
- else
274
- e.raise
275
- end
276
- rescue ArgumentError => e
277
- puts 'ArgumentError from rest-client, most likely caused by https://github.com/rest-client/rest-client/issues/359'
278
- puts 'try overpass query that will return smaller amount of data'
279
- puts e
280
- e.raise
281
- rescue => e
282
- puts 'query failed'
283
- puts query
284
- puts
285
- puts url
286
- puts e
287
- e.raise
288
- end
289
- end
290
-
291
- def self.get_allowed_timeout_in_seconds
292
- return 10 * 60
293
- end
294
-
295
- def self.format_query_into_url(query)
296
- query = query.gsub(/\n/, '')
297
- query = query.gsub(/\t/, '')
298
- return 'http://overpass-api.de/api/interpreter?data=' + URI.escape(query)
299
- end
300
- end
301
- end
@@ -1,38 +0,0 @@
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
- latitude_bb_size = bbox_size[0]
15
- longitude_bb_size = bbox_size[0]
16
- #--bbox=[xmin,ymin,xmax,ymax]
17
- xmin = lon-longitude_bb_size/2
18
- ymin = lat-latitude_bb_size/2
19
- xmax = lon+longitude_bb_size/2
20
- ymax = lat+latitude_bb_size/2
21
- bbox = "#{xmin},#{ymin},#{xmax},#{ymax}"
22
- params = "--format=png --width=#{image_size} --height=#{image_size} --static_zoom=#{zlevel} --bbox=\"#{bbox}\""
23
- project_name = CartoCSSHelper::Configuration.get_tilemill_project_name
24
- command = "node /usr/share/tilemill/index.js export #{project_name} '#{export_filename}' #{params} #{silence}"
25
- if debug
26
- puts command
27
- end
28
- system command
29
- unless File.exists?(export_filename)
30
- if !debug
31
- puts 'rerunning failed image generation with enabled debug'
32
- return self.run_tilemill_export_image(lat, lon, zlevel, bbox_size, image_size, export_filename, true)
33
- end
34
- raise 'generation of file ' + export_filename + ' failed'
35
- end
36
- end
37
- end
38
- end