cartocss_helper 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/cartocss_helper/configuration.rb +103 -0
- data/lib/cartocss_helper/data_file_handling.rb +97 -0
- data/lib/cartocss_helper/downloader.rb +198 -0
- data/lib/cartocss_helper/git.rb +32 -0
- data/lib/cartocss_helper/heuristic.rb +117 -0
- data/lib/cartocss_helper/image_generator.rb +121 -0
- data/lib/cartocss_helper/style_specific/default_osm_style.rb +553 -0
- data/lib/cartocss_helper/style_specific/style_specific.rb +11 -0
- data/lib/cartocss_helper/tag_lister.rb +223 -0
- data/lib/cartocss_helper/validator.rb +172 -0
- data/lib/cartocss_helper/visualise_changes_diff_from_images.rb +158 -0
- data/lib/cartocss_helper/visualise_changes_image_generation.rb +148 -0
- data/lib/cartocss_helper.rb +70 -0
- data/license.txt +9 -0
- data/readme.md +25 -0
- metadata +111 -0
@@ -0,0 +1,148 @@
|
|
1
|
+
require_relative 'visualise_changes_diff_from_images'
|
2
|
+
require_relative 'git'
|
3
|
+
require_relative 'downloader'
|
4
|
+
|
5
|
+
module CartoCSSHelper
|
6
|
+
class VisualDiff
|
7
|
+
def self.visualise_changes_synthethic_test(tags, type, on_water, zlevel_range, old_branch, new_branch)
|
8
|
+
tags = VisualDiff.remove_magic_from_tags(tags)
|
9
|
+
on_water_string = ''
|
10
|
+
if on_water
|
11
|
+
on_water_string = ' on water'
|
12
|
+
end
|
13
|
+
header = "#{ VisualDiff.dict_to_pretty_tag_list(tags) } #{ type }#{ on_water_string }"
|
14
|
+
puts "visualise_changes_synthethic_test <#{header}> #{old_branch} -> #{new_branch}"
|
15
|
+
Git.checkout(old_branch)
|
16
|
+
old = VisualDiff.collect_images_for_synthethic_test(tags, type, on_water, zlevel_range)
|
17
|
+
Git.checkout(new_branch)
|
18
|
+
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
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.remove_magic_from_tags(tags)
|
23
|
+
magicless_tags = Hash.new
|
24
|
+
tags.each {|key, value|
|
25
|
+
if value == :any
|
26
|
+
value = 'any tag value'
|
27
|
+
end
|
28
|
+
magicless_tags[key]=value
|
29
|
+
}
|
30
|
+
return magicless_tags
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.collect_images_for_synthethic_test(tags, type, on_water, zlevel_range)
|
34
|
+
collection = []
|
35
|
+
zlevel_range.each { |zlevel|
|
36
|
+
scene = Scene.new(tags, zlevel, on_water, type)
|
37
|
+
collection.push(ImageForComparison.new(scene.get_image_filename, "z#{zlevel}"))
|
38
|
+
}
|
39
|
+
return collection
|
40
|
+
end
|
41
|
+
|
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
|
47
|
+
@latitude = latitude
|
48
|
+
@longitude = longitude
|
49
|
+
@data_filename = Downloader.download_osm_data_for_location(@latitude, @longitude, @download_bbox_size)
|
50
|
+
@loaded = false
|
51
|
+
end
|
52
|
+
|
53
|
+
def load
|
54
|
+
if !@loaded
|
55
|
+
puts "\tloading data into database"
|
56
|
+
DataFileLoader.load_data_into_database(@data_filename)
|
57
|
+
puts "\tgenerating images"
|
58
|
+
@loaded = true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_timestamp
|
63
|
+
f = File.new(@data_filename)
|
64
|
+
return f.mtime.to_i
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.visualise_changes_on_real_data(tags, type, wanted_latitude, wanted_longitude, zlevels, old_branch, new_branch)
|
69
|
+
#special support for following tag values: :any_value
|
70
|
+
header = "#{ VisualDiff.dict_to_pretty_tag_list(tags) } #{type} #{ wanted_latitude } #{ wanted_longitude } #{zlevels}"
|
71
|
+
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)
|
79
|
+
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
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.scale_inverse(zlevel, reference_value, reference_zlevel)
|
84
|
+
return VisualDiff.scale reference_zlevel, reference_value, zlevel
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.scale(zlevel, reference_value, reference_zlevel)
|
88
|
+
diff = zlevel - reference_zlevel
|
89
|
+
rescaler = 2.0**diff
|
90
|
+
return reference_value*rescaler
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.collect_images_for_real_data_test(tags, type, latitude, longitude, zlevels, source)
|
94
|
+
collection = []
|
95
|
+
zlevels.each { |zlevel|
|
96
|
+
image_size_for_16_zoom_level = 1000
|
97
|
+
image_size = (VisualDiff.scale zlevel, image_size_for_16_zoom_level, 16)
|
98
|
+
mutiplier = 1000
|
99
|
+
image_size = (image_size*mutiplier).to_int
|
100
|
+
render_bbox_size = 0.015
|
101
|
+
wanted_image_size = 400
|
102
|
+
ratio = 1.0*image_size/(wanted_image_size*mutiplier)
|
103
|
+
image_size /= ratio
|
104
|
+
render_bbox_size /= ratio
|
105
|
+
image_size /= mutiplier
|
106
|
+
image_size = image_size.to_i
|
107
|
+
if image_size!=wanted_image_size
|
108
|
+
puts VisualDiff.scale zlevel, image_size_for_16_zoom_level, 16
|
109
|
+
puts zlevel
|
110
|
+
puts image_size
|
111
|
+
puts wanted_image_size
|
112
|
+
puts ratio
|
113
|
+
raise "#{image_size} mismatches #{wanted_image_size}"
|
114
|
+
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"}"
|
116
|
+
if !File.exists?(filename)
|
117
|
+
source.load
|
118
|
+
Scene.run_tilemill_export_image(latitude, longitude, zlevel, render_bbox_size, image_size, filename)
|
119
|
+
end
|
120
|
+
collection.push(ImageForComparison.new(filename, "z#{zlevel}"))
|
121
|
+
}
|
122
|
+
return collection
|
123
|
+
end
|
124
|
+
|
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\/\\:\*\?\"<>\|]/, '_')
|
128
|
+
filename_sufix = "#{ old_branch } -> #{ new_branch }"
|
129
|
+
filename = CartoCSSHelper::Configuration.get_path_to_folder_for_output + "#{header} #{filename_sufix}.png"
|
130
|
+
diff = FullSetOfComparedImages.new(old, new, header, filename, image_size)
|
131
|
+
diff.save
|
132
|
+
end
|
133
|
+
def self.dict_to_pretty_tag_list(dict)
|
134
|
+
result = ''
|
135
|
+
dict.to_a.each { |tag|
|
136
|
+
if result != ''
|
137
|
+
result << '; '
|
138
|
+
end
|
139
|
+
value = "'#{tag[1]}'"
|
140
|
+
if tag[1] == :any_value
|
141
|
+
value = '{any value}'
|
142
|
+
end
|
143
|
+
result << "#{tag[0]}=#{value}"
|
144
|
+
}
|
145
|
+
return result
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
module CartoCSSHelper
|
5
|
+
end
|
6
|
+
require_relative 'cartocss_helper/tag_lister.rb'
|
7
|
+
require_relative 'cartocss_helper/visualise_changes_image_generation.rb'
|
8
|
+
require_relative 'cartocss_helper/downloader.rb'
|
9
|
+
require_relative 'cartocss_helper/data_file_handling.rb'
|
10
|
+
require_relative 'cartocss_helper/validator.rb'
|
11
|
+
require_relative 'cartocss_helper/git.rb'
|
12
|
+
include CartoCSSHelper::Validator
|
13
|
+
include CartoCSSHelper::Git
|
14
|
+
|
15
|
+
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)
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
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)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.add_common_secondary_tags(tags)
|
52
|
+
return tags.merge({'name' => 'ÉÉÉÉÉÉ ÉÉÉÉÉÉ ÉÉÉÉÉÉ', 'ref' => '1', 'ele' => '8000', 'operator' => 'operator ÉÉ ÉÉ ÉÉ', 'brand' => 'brand ÉÉ ÉÉ ÉÉ ÉÉ'})
|
53
|
+
end
|
54
|
+
|
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)}"
|
57
|
+
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)
|
60
|
+
}
|
61
|
+
test_tag_on_real_data(tags, zlevels, old_brach, new_branch)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.probe(tags, new_branch, old_brach='master',test_on_water=false, zlevels=Configuration.get_min_z..Configuration.get_max_z)
|
65
|
+
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
|
+
}
|
69
|
+
end
|
70
|
+
end
|
data/license.txt
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
This software and associated documentation files (the "Software") is
|
2
|
+
released under the CC0 Public Domain Dedication, version 1.0, as
|
3
|
+
published by Creative Commons. To the extent possible under law, the
|
4
|
+
author(s) have dedicated all copyright and related and neighboring
|
5
|
+
rights to the Software to the public domain worldwide. The Software is
|
6
|
+
distributed WITHOUT ANY WARRANTY.
|
7
|
+
If you did not receive a copy of the CC0 Public Domain Dedication
|
8
|
+
along with the Software, see
|
9
|
+
<http://creativecommons.org/publicdomain/zero/1.0/>
|
data/readme.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
##CartoCSS Helper
|
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.
|
4
|
+
|
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
|
+
|
7
|
+
Fortunately it is possible to automate it almost entirely. With this tool testing new rendering change requires only specification of tag combination that should be tested and type of element.
|
8
|
+
|
9
|
+
It is work in progress, major problems that should be solved include:
|
10
|
+
|
11
|
+
* Lack of documentation
|
12
|
+
* Executing git checkout commands on map style git repository during normal script operation (https://github.com/matkoniecz/CartoCSSHelper/issues/9)
|
13
|
+
* Current rendering method is obnoxiously slow. (https://github.com/matkoniecz/CartoCSSHelper/issues/1)
|
14
|
+
|
15
|
+
###Example
|
16
|
+
|
17
|
+
`require cartocss_helper`
|
18
|
+
`tags = {'landuse' => 'village_green', 'tourism' => 'attraction'}`
|
19
|
+
`CartoCSSHelper.test tags, 'master', 'v2.28.1'`
|
20
|
+
|
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
|
+
|
23
|
+
###Automated stuff
|
24
|
+
|
25
|
+
[![Code Climate](https://codeclimate.com/github/mkoniecz/CartoCSSHelper/badges/gpa.svg)](https://codeclimate.com/github/mkoniecz/CartoCSSHelper)
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cartocss_helper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mateusz Konieczny
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-04-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rest-client
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.7.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.7.3
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sys-filesystem
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.1.4
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.1.4
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rmagick
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.13.4
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.13.4
|
62
|
+
description: Tool to make development of CartoCSS styles more efficient. Automates
|
63
|
+
actions necessary to produce test images and validates style. Loading data using
|
64
|
+
osm2pgsql, rendering with TileMill, obtaining test data from overpass turbo.
|
65
|
+
email:
|
66
|
+
- matkoniecz@gmail.com
|
67
|
+
executables: []
|
68
|
+
extensions: []
|
69
|
+
extra_rdoc_files: []
|
70
|
+
files:
|
71
|
+
- lib/cartocss_helper.rb
|
72
|
+
- lib/cartocss_helper/visualise_changes_image_generation.rb
|
73
|
+
- lib/cartocss_helper/tag_lister.rb
|
74
|
+
- lib/cartocss_helper/image_generator.rb
|
75
|
+
- lib/cartocss_helper/validator.rb
|
76
|
+
- lib/cartocss_helper/downloader.rb
|
77
|
+
- lib/cartocss_helper/git.rb
|
78
|
+
- lib/cartocss_helper/heuristic.rb
|
79
|
+
- lib/cartocss_helper/visualise_changes_diff_from_images.rb
|
80
|
+
- lib/cartocss_helper/configuration.rb
|
81
|
+
- lib/cartocss_helper/style_specific/style_specific.rb
|
82
|
+
- lib/cartocss_helper/style_specific/default_osm_style.rb
|
83
|
+
- lib/cartocss_helper/data_file_handling.rb
|
84
|
+
- license.txt
|
85
|
+
- readme.md
|
86
|
+
homepage: https://github.com/matkoniecz/CartoCSSHelper
|
87
|
+
licenses:
|
88
|
+
- CC0
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 1.8.23
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.8.23
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: Tool to make development of CartoCSS styles more efficient.
|
111
|
+
test_files: []
|