diff --git a/docs/layers.md b/docs/layers.md index b9c0d455d..af6d24fed 100644 --- a/docs/layers.md +++ b/docs/layers.md @@ -141,8 +141,8 @@ Combination of OpenStreetMap administrative boundaries (zoom >= 8) and Natural E #### Boundaries properties (common): -* `name` -* `id` +* `name`: A suggested label, formed from the left and right region names, if available. If the name appears to be too long to be rendered on the geometry at a particular zoom it may be omitted. +* `id`: Identifier for the feature, only provided at zoom 13+. * `kind`: mapping of OpenStreetMap's `admin_level` int values to strings like `country` and `state`, plus `aboriginal_lands` boundary type, and also includes normalized Natural Earth values. * `kind_detail`: mapping of OpenStreetMap's `admin_level` values. `2` for countries, `4` for regions, and `6`, `8` (zoom 10+) * `source`: `openstreetmap.org` or `naturalearthdata.com` @@ -151,8 +151,8 @@ Combination of OpenStreetMap administrative boundaries (zoom >= 8) and Natural E #### Boundaries properties (common optional): -* `id:left`: For the relation on the left side of the boundary line. -* `id:right`: For the relation on the right side of the boundary line. +* `id:left`: For the relation on the left side of the boundary line. This is only provided at zoom 13+. +* `id:right`: For the relation on the right side of the boundary line. This is only provided at zoom 13+. * `name:left`: See name section above, other variants like `old_name` also supported. _See planned bug fix in [#1102](https://github.com/tilezen/vector-datasource/issues/1102)._ * `name:right`: See name section above, other variants like `old_name` also supported. _See planned bug fix in [#1102](https://github.com/tilezen/vector-datasource/issues/1102)._ * `maritime_boundary`: a special Tilezen calculated value loosely coupled with OpenStreetMap's maritime tag, but with spatial buffer processing for lines falling in the ocean. diff --git a/integration-test/1012-sort_key-boundary.py b/integration-test/1012-sort_key-boundary.py index 3280e6839..e77101525 100644 --- a/integration-test/1012-sort_key-boundary.py +++ b/integration-test/1012-sort_key-boundary.py @@ -40,5 +40,5 @@ def test_san_francisco_daly_city_locality_boundary(self): 'https://www.openstreetmap.org/relation/112271', ], clip=self.tile_bbox(10, 163, 396, padding=0.1)) self.assert_has_feature( - 10, 163, 396, "boundaries", + 11, 326, 792, "boundaries", {"kind": "locality", "sort_rank": 252}) diff --git a/integration-test/1482-maritime_boundary-buffered_land.py b/integration-test/1482-maritime_boundary-buffered_land.py index aa88d7f6f..2156c6b65 100644 --- a/integration-test/1482-maritime_boundary-buffered_land.py +++ b/integration-test/1482-maritime_boundary-buffered_land.py @@ -75,7 +75,6 @@ def test_generative_non_maritime(self): self.assert_has_feature( z, x, y, 'boundaries', { - 'id': 2, 'kind': 'country', 'maritime_boundary': type(None), }) @@ -95,7 +94,6 @@ def test_generative_maritime(self): self.assert_has_feature( z, x, y, 'boundaries', { - 'id': 2, 'kind': 'country', 'maritime_boundary': True, }) diff --git a/integration-test/1715-slimming-down-boundaries.py b/integration-test/1715-slimming-down-boundaries.py new file mode 100644 index 000000000..8840239f8 --- /dev/null +++ b/integration-test/1715-slimming-down-boundaries.py @@ -0,0 +1,72 @@ +# -*- encoding: utf-8 -*- +from . import FixtureTest + + +class BoundaryIdTest(FixtureTest): + + def _setup(self, z, x, y, left_id, right_id): + from tilequeue.tile import coord_to_bounds + from shapely.geometry import LineString + from ModestMaps.Core import Coordinate + import dsl + + minx, miny, maxx, maxy = coord_to_bounds( + Coordinate(zoom=z, column=x, row=y)) + + # move the coordinate points slightly out of the tile, so that we + # don't get borders along the sides of the tile. + w = maxx - minx + h = maxy - miny + minx -= 0.5 * w + miny -= 0.5 * h + maxx += 0.5 * w + maxy += 0.5 * h + + self.generate_fixtures( + dsl.way( + 1, + LineString([ + [minx, miny], + [minx, maxy], + [maxx, maxy], + [minx, miny], + ]), { + 'boundary': 'administrative', + 'admin_level': '2', + 'id': left_id, + 'name': 'Left', + } + ), + dsl.way( + 2, + LineString([ + [minx, miny], + [maxx, maxy], + [maxx, miny], + [minx, miny], + ]), { + 'boundary': 'administrative', + 'admin_level': '2', + 'id': right_id, + 'name': 'Right', + } + ), + ) + + def test_have_ids_at_z13(self): + z, x, y = (13, 100, 100) + self._setup(z, x, y, 1, 2) + self.assert_has_feature( + z, x, y, 'boundaries', { + 'id:left': 1, + 'id:right': 2, + }) + + def test_dropped_at_z12(self): + z, x, y = (12, 50, 50) + self._setup(z, x, y, 1, 2) + self.assert_has_feature( + z, x, y, 'boundaries', { + 'id:left': type(None), + 'id:right': type(None), + }) diff --git a/integration-test/841-normalize-boundaries-kind.py b/integration-test/841-normalize-boundaries-kind.py index 0405ff92e..ad316eee4 100644 --- a/integration-test/841-normalize-boundaries-kind.py +++ b/integration-test/841-normalize-boundaries-kind.py @@ -103,64 +103,64 @@ def test_admin1(self): # Admin-1 boundary self.assert_has_feature( 7, 75, 70, 'boundaries', - {'id': int, 'kind': 'region', 'kind_detail': '4'}) + {'kind': 'region', 'kind_detail': '4'}) def test_admin1_statistical(self): # Admin-1 statistical boundary self.assert_has_feature( 7, 101, 56, 'boundaries', - {'id': int, 'kind': 'region', 'kind_detail': '4'}) + {'kind': 'region', 'kind_detail': '4'}) def test_admin1_statistical_meta(self): # Admin-1 statistical meta bounds self.assert_has_feature( 7, 26, 52, 'boundaries', - {'id': int, 'kind': 'region', 'kind_detail': '4'}) + {'kind': 'region', 'kind_detail': '4'}) def test_admin1_region(self): # Admin-1 region boundary self.assert_has_feature( 7, 99, 57, 'boundaries', - {'id': int, 'kind': 'macroregion', 'kind_detail': '3'}) + {'kind': 'macroregion', 'kind_detail': '3'}) def test_disputed(self): # Disputed (please verify) self.assert_has_feature( 7, 39, 71, 'boundaries', - {'id': int, 'kind': 'disputed', 'kind_detail': '2'}) + {'kind': 'disputed', 'kind_detail': '2'}) def test_indefinite(self): # Indefinite (please verify) self.assert_has_feature( 7, 20, 44, 'boundaries', - {'id': int, 'kind': 'indefinite', 'kind_detail': '2'}) + {'kind': 'indefinite', 'kind_detail': '2'}) def test_indeterminant(self): # Indeterminant frontier self.assert_has_feature( 7, 91, 50, 'boundaries', - {'id': int, 'kind': 'indeterminate', 'kind_detail': '2'}) + {'kind': 'indeterminate', 'kind_detail': '2'}) def test_international(self): # International boundary (verify) self.assert_has_feature( 7, 67, 37, 'boundaries', - {'id': int, 'kind': 'country', 'kind_detail': '2'}) + {'kind': 'country', 'kind_detail': '2'}) def test_lease_limit(self): # Lease limit self.assert_has_feature( 7, 86, 45, 'boundaries', - {'id': int, 'kind': 'lease_limit', 'kind_detail': '2'}) + {'kind': 'lease_limit', 'kind_detail': '2'}) def test_line_of_control(self): # Line of control (please verify) self.assert_has_feature( 7, 90, 50, 'boundaries', - {'id': int, 'kind': 'line_of_control', 'kind_detail': '2'}) + {'kind': 'line_of_control', 'kind_detail': '2'}) def test_overlay(self): # Overlay limit self.assert_has_feature( 7, 109, 49, 'boundaries', - {'id': int, 'kind': 'overlay_limit', 'kind_detail': '2'}) + {'kind': 'overlay_limit', 'kind_detail': '2'}) diff --git a/integration-test/976-fractional-pois.py b/integration-test/976-fractional-pois.py index 4f1fb796e..8708cc2c9 100644 --- a/integration-test/976-fractional-pois.py +++ b/integration-test/976-fractional-pois.py @@ -92,7 +92,7 @@ def test_boundaries(self): # transit, and water self.assert_has_feature( 5, 9, 12, 'boundaries', - {'min_zoom': 2, 'id': int, + {'min_zoom': 2, 'source': 'naturalearthdata.com', 'kind': 'region'}) diff --git a/queries.yaml b/queries.yaml index d9d1501bf..0d46d32ee 100644 --- a/queries.yaml +++ b/queries.yaml @@ -602,6 +602,20 @@ post_process: base_layer: boundaries start_zoom: 8 + # drop id/id:left/id:right on boundaries up to zoom 12 inclusive. + # the left/right IDs tend to be unique as a pair, and so prevent merging. + # the id itself will be dropped by merging if it's possible to merge, and + # at mid and low zooms is of dubious usefulness. + - fn: vectordatasource.transform.drop_properties + params: + source_layer: boundaries + start_zoom: 0 + end_zoom: 13 + properties: + - id + - "id:left" + - "id:right" + # try to merge boundaries into as long segments as possible. - fn: vectordatasource.transform.merge_line_features params: @@ -628,6 +642,14 @@ post_process: end_zoom: 7 properties: [name] + # after dropping names, try again to merge boundaries into as few features as + # possible (to reduce tile size). + - fn: vectordatasource.transform.merge_line_features + params: + source_layer: boundaries + start_zoom: 8 + end_zoom: 15 + # before extracting the label placement points, remove small water areas which # are probably too small to label. - fn: vectordatasource.transform.drop_properties diff --git a/yaml/boundaries.yaml b/yaml/boundaries.yaml index d396cde5d..6abb95b5d 100644 --- a/yaml/boundaries.yaml +++ b/yaml/boundaries.yaml @@ -83,7 +83,7 @@ filters: kind_detail: '6' table: osm - filter: {admin_level: '8', boundary: administrative} - min_zoom: 10 + min_zoom: 11 output: <<: *output_properties kind: locality