cartocss_helper 1.2.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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