Skip to content

Commit e7c63b2

Browse files
authored
Add style-tools binary (#416)
Add style-tools binary Add styleutils.py Add spitezero to Dockerfile
1 parent e830bbf commit e7c63b2

File tree

3 files changed

+132
-0
lines changed

3 files changed

+132
-0
lines changed

Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ RUN set -eux ;\
124124
npm install -g \
125125
126126
127+
@beyondtracks/[email protected] \
127128
128129
\
129130
/bin/bash -c 'echo ""; echo ""; echo "##### Cleaning up"' >&2 ;\

bin/style-tools

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env python
2+
"""
3+
Usage:
4+
style-tools split <tileset> <style>
5+
style-tools merge <tileset> <style> <style_header>
6+
style-tools recompose <tileset> <style> <style_header>
7+
style-tools --help
8+
style-tools --version
9+
10+
Actions:
11+
split Break down style.json into separate jsons per yaml layer.
12+
merge Combine separate jsons into style.json.
13+
14+
Options:
15+
--help Show this screen.
16+
--version Show version.
17+
"""
18+
from pathlib import Path
19+
from docopt import docopt
20+
import openmaptiles
21+
from openmaptiles.styleutils import merge, split
22+
23+
24+
def main():
25+
args = docopt(__doc__, version=openmaptiles.__version__)
26+
tileset_fp = Path(args['<tileset>'])
27+
style = args['<style>']
28+
style_fp = Path(style)
29+
if args['split']:
30+
split(tileset_fp, style_fp)
31+
elif args['merge']:
32+
style_header = args['<style_header>']
33+
style_header_fp = Path(style_header)
34+
merge(tileset_fp, style_fp, style_header_fp)
35+
elif args['recompose']:
36+
style_header = args['<style_header>']
37+
style_header_fp = Path(style_header)
38+
merge(tileset_fp, style_fp, style_header_fp)
39+
split(tileset_fp, style_fp)
40+
41+
42+
if __name__ == '__main__':
43+
main()

openmaptiles/styleutils.py

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import json
2+
from pathlib import Path
3+
from openmaptiles.tileset import Tileset
4+
5+
6+
def fp_to_dict(fp: Path) -> dict:
7+
return json.loads(fp.read_text(encoding='utf-8'))
8+
9+
10+
def get_ts_lyr_style_json_fp(yaml_fp: str) -> Path:
11+
yaml_path = yaml_fp.filename
12+
json_name = Path(yaml_path.name).with_name('style.json')
13+
ts_lyr_dir = yaml_path.parent
14+
15+
return ts_lyr_dir.joinpath(json_name)
16+
17+
18+
def add_order(lyrs: list) -> list:
19+
for i, lyr in enumerate(lyrs):
20+
lyr['order'] = i
21+
return lyrs
22+
23+
24+
def get_order(layer: dict) -> int:
25+
order = layer.get('order')
26+
if order is None:
27+
raise ValueError(f'Missing order value in layer {layer.get("id")}')
28+
return int(order)
29+
30+
31+
def split(tileset_fp: Path, style_fp: Path):
32+
tileset = Tileset.parse(tileset_fp)
33+
tileset_lyrs = tileset.layers
34+
35+
# Add order to each style layer (e.g. backgroud - 0, labels - 196)
36+
style = fp_to_dict(style_fp)
37+
lyrs = style.get('layers')
38+
if not lyrs:
39+
raise ValueError(f'No layers in {style_fp}.')
40+
style_lyrs_w_order = add_order(lyrs)
41+
42+
# ts_lyr is a layer in tileset.yaml (e.g. landuse, landcover, water, waterway...)
43+
for ts_lyr in tileset_lyrs:
44+
snippet_fp = get_ts_lyr_style_json_fp(ts_lyr)
45+
snippet_lyrs = list()
46+
for style_lyr in style_lyrs_w_order:
47+
source_layer = style_lyr.get('source-layer')
48+
if source_layer == ts_lyr.filename.stem:
49+
snippet_lyrs.append(style_lyr)
50+
out_dict = {'layers': snippet_lyrs}
51+
52+
# write style layers with order to json for specific tileset layer
53+
snippet_fp.write_text(json.dumps(out_dict, indent=2))
54+
55+
56+
def merge(tileset_fp: Path, style_fp: Path, style_header_fp: Path):
57+
tileset = Tileset.parse(tileset_fp)
58+
tileset_lyrs = tileset.layers
59+
# Load style header file
60+
style = fp_to_dict(style_header_fp)
61+
62+
style_lyrs = list()
63+
# For each tileset layer read its style.json and append its layers to style_lyrs
64+
for ts_lyr in tileset_lyrs:
65+
ts_lyr_style_json_fp = get_ts_lyr_style_json_fp(ts_lyr)
66+
with open(ts_lyr_style_json_fp, 'r') as f:
67+
in_dict = json.load(f)
68+
ts_lyr_style_lyrs = in_dict.get('layers')
69+
for layer_style_layer in ts_lyr_style_lyrs:
70+
if layer_style_layer.get('order') is None:
71+
raise ValueError(f'Missing order value in layer {layer_style_layer.get("id")} '
72+
f'of snippet {ts_lyr_style_json_fp}.')
73+
else:
74+
style_lyrs.append(layer_style_layer)
75+
76+
# sort style_lyrs by order, let sort take care of duplicates
77+
style_lyrs.sort(key=get_order)
78+
# create a new list with original background layer
79+
new_style_lyrs = style.get('layers')[:1]
80+
# append sorted layers to new_style_lyrs
81+
for style_lyr in style_lyrs:
82+
# remove order kv
83+
style_lyr.pop('order')
84+
new_style_lyrs.append(style_lyr)
85+
style['layers'] = new_style_lyrs
86+
# save to temp file
87+
with open(style_fp, 'w') as fout:
88+
json.dump(style, fout, indent=2)

0 commit comments

Comments
 (0)