Skip to content

Commit

Permalink
Merge pull request #1812 from tilezen/zerebubuth/1730-water-labels-st…
Browse files Browse the repository at this point in the history
…rike-back

Update min zoom of water label points.
  • Loading branch information
zerebubuth committed Feb 1, 2019
2 parents 93c8117 + 3eecba7 commit ba68083
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 29 deletions.
49 changes: 49 additions & 0 deletions integration-test/1730-further-water-layer-name-dropping.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,52 @@ def test_no_label_boundary(self):
'name': type(None),
'name:fr': type(None),
})


class WaterLabelZoomAdjustmentTest(FixtureTest):

def test_label_lake_athabasca_z5(self):
import dsl

z, x, y = (5, 6, 9)

self.generate_fixtures(
dsl.way(1, dsl.box_area(z, x, y, 31390412728.710949), {
'featurecla': u'Lake',
'label': u'Lake Athabasca',
'min_label': 3.7,
'min_zoom': 2.0,
'name': u'Lake Athabasca',
'name_abb': u'L. Athabasca',
'name_de': u'Athabascasee',
'name_en': u'Lake Athabasca',
'name_es': u'Lago Athabasca',
'name_fr': u'lac Athabasca',
'name_hu': u'Atabaszk-tó',
'name_it': u'Athabasca',
'name_ja': u'アサバスカ湖',
'name_nl': u'Athabascameer',
'name_pl': u'Athabaska',
'name_pt': u'Lago Athabasca',
'name_ru': u'Атабаска',
'name_sv': u'Athabascasjön',
'name_tr': u'Athabasca Gölü',
'name_zh': u'阿薩巴斯卡湖',
'ne_id': u'1159106863',
'scalerank': 2,
'source': u'naturalearthdata.com',
'wdid_score': 4,
'wikidataid': u'Q272463',
}),
)

# we should get a label placement point, and its zoom should have been
# adjusted. we should also have all the names at this point.
self.assert_has_feature(
z, x, y, 'water', {
'kind': 'lake',
'label_placement': True,
'min_zoom': 5,
'name': str,
'name:de': str,
})
63 changes: 34 additions & 29 deletions queries.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -777,35 +777,6 @@ post_process:
where: >-
kind == 'lake'
# some water polygon features are too small to need a label - and if we label
# them then the label is often so prominent that it hides the polygon it's
# for! see the images here for examples of this:
# https://github.com/tilezen/vector-datasource/issues/1477#issuecomment-447162484
#
# therefore, we want to remove the name properties from those small water
# polygon features before we extract the label placements in a following step.
- fn: vectordatasource.transform.drop_names
params:
source_layer: water
start_zoom: 4
end_zoom: 16
geom_types: [Polygon, MultiPolygon]
where: >-
area < {
4: 40000000000,
5: 10000000000,
6: 5000000000,
7: 400000000,
8: 200000000,
9: 100000000,
10: 10000000,
11: 4000000,
12: 750000,
13: 100000,
14: 50000,
15: 10000,
}.get(zoom)
- fn: vectordatasource.transform.handle_label_placement
params:
layers:
Expand All @@ -817,6 +788,40 @@ post_process:
label_where: >-
'name' in properties
# some water polygon features are too small to need a label - and if we label
# them then the label is often so prominent that it hides the polygon it's
# for! see the images here for examples of this:
# https://github.com/tilezen/vector-datasource/issues/1477#issuecomment-447162484
#
# we want to reset min_zoom on these features and screen them out if they
# don't meet minimum sizes per zoom.
- fn: vectordatasource.transform.update_min_zoom
params:
source_layer: water
start_zoom: 4
end_zoom: 16
# the inclusion of "None" in the list might seem odd, but None compares
# numerically smaller than any integer, so acts as a default for this
# table.
min_zoom: >-
[min_zoom for min_zoom, area_threshold in [
(4, 40000000000),
(5, 10000000000),
(6, 5000000000),
(7, 400000000),
(8, 200000000),
(9, 100000000),
(10, 10000000),
(11, 4000000),
(12, 750000),
(13, 100000),
(14, 50000),
(15, 10000),
(16, None),
] if area >= area_threshold][0]
where: >-
kind == 'lake' and label_placement
- fn: vectordatasource.transform.handle_label_placement
params:
layers:
Expand Down
52 changes: 52 additions & 0 deletions vectordatasource/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -8627,3 +8627,55 @@ def remap_viewpoint_kinds(shape, props, fid, zoom):
props[key] = _REMAP_VIEWPOINT_KIND.get(props[key])

return (shape, props, fid)


def update_min_zoom(ctx):
"""
Update the min zoom for features matching the Python fragment "where"
clause. If none is provided, update all features.
The new min_zoom is calculated by evaluating a Python fragment passed
in through the "min_zoom" parameter. This is evaluated in the context
of the features' parameters, plus a zoom variable.
If the min zoom is lower than the current min zoom, the current one is
kept. If the min zoom is increased, then it's checked against the
current zoom and the feature dropped if it's not in range.
"""

params = _Params(ctx, 'update_min_zoom')
layer_name = params.required('source_layer')
start_zoom = params.optional('start_zoom', typ=int, default=0)
end_zoom = params.optional('end_zoom', typ=int)
min_zoom = params.required('min_zoom')
where = params.optional('where')

layer = _find_layer(ctx.feature_layers, layer_name)
zoom = ctx.nominal_zoom

if zoom < start_zoom or \
(end_zoom is not None and zoom >= end_zoom):
return None

min_zoom = compile(min_zoom, 'queries.yaml', 'eval')
if where:
where = compile(where, 'queries.yaml', 'eval')

new_features = []
for shape, props, fid in layer['features']:
local = defaultdict(lambda: None)
local.update(props)
local['zoom'] = zoom

if where and eval(where, {}, local):
new_min_zoom = eval(min_zoom, {}, local)
if new_min_zoom > props.get('min_zoom'):
props['min_zoom'] = new_min_zoom
if new_min_zoom >= zoom + 1 and zoom < 16:
# DON'T add feature - it's masked by min zoom.
continue

new_features.append((shape, props, fid))

layer['features'] = new_features
return layer

0 comments on commit ba68083

Please sign in to comment.