diff --git a/docs/layers.md b/docs/layers.md index c9c4ed364..0dc6a743f 100644 --- a/docs/layers.md +++ b/docs/layers.md @@ -1450,6 +1450,7 @@ To improve performance, some road segments are merged at low and mid-zooms. To f * `all_networks` and `all_shield_texts`: All the networks of which this road is a part, and all of the shield texts. See `network` and `shield_text` below. **Note** that these properties will not be present on MVT format tiles, as we cannot currently encode lists as values. * `network`: eg: `US:I` for the United States Interstate network, useful for shields and road selections. This only contains _road_ network types. Please see `bicycle_network` and `walking_network` for bicycle and walking networks, respectively. Note that networks may include "modifier" information, for example `US:I:Business` for a business route or `US:I:Truck` for a truck route. The whitelist of "modifier" values is; `Alternate`, `Business`, `Bypass`, `Connector`, `Historic`, `Scenic`, `Spur`, `Toll` and `Truck`. * `shield_text`: Contains text to display on a shield. For example, I 90 would have a `network` of `US:I` and a `shield_text` of `90`. The `ref`, `I 90`, is less useful for shield display without further processing. For some roads, this can include non-numeric characters, for example the M1 motorway in the UK will have a `shield_text` of `M1`, rather than just `1`. Whitepsace, punctuation, and prefixes are generally stripped. +* `shield_text_length`: The length of the `shield_text` field as a string. E.g. if `shield_text` is `'12345'`, `shield_text_length` would be `'5'`. Missing if `shield_text` is !(0 < length < 7) or field doesn't exist #### Road properties (common optional): @@ -1475,12 +1476,15 @@ To improve performance, some road segments are merged at low and mid-zooms. To f * `all_walking_networks` and `all_walking_shield_texts`: All of the walking networks of which this road is a part, and each corresponding shield text. See `walking_network` and `walking_shield_text` below. **Note** that these properties will not be present on MVT format tiles, as we cannot currently encode lists as values. * `walking_network`: e.g: `nwn` for a "National Walking Network". Other common values include `iwn` for international, `rwn` for regional and `lwn` for local walking networks. * `walking_shield_text`: Contains text intended to be displayed on a shield related to the walking network. This is the value from the `ref` tag and is _not_ guaranteed to be numeric, or even concise. +* `walking_shield_text_length`: The length of the `walking_shield_text` field as a string. E.g. if `walking_shield_text` is `'12345'`, `walking_shield_text_length` would be `'5'`. Missing if `walking_shield_text` is !(0 < length < 7) or field doesn't exist * `all_bicycle_networks` and `all_bicycle_shield_texts`: All of the bicycle networks of which this road is a part, and each corresponding shield text. See `bicycle_network` and `bicycle_shield_text` below. **Note** that these properties will not be present on MVT format tiles, as we cannot currently encode lists as values. * `bicycle_network`: Present if the feature is part of a cycling network. If so, the value will be one of `icn` for International Cycling Network, `ncn` for National Cycling Network, `rcn` for Regional Cycling Network, `lcn` for Local Cycling Network. * `bicycle_shield_text`: Contains text intended to be displayed on a shield related to the bicycle network. This is the value from the `ref` tag and is _not_ guaranteed to be numeric, or even concise. +* `bicycle_shield_text_length`: The length of the `bicycle_shield_text` field as a string. E.g. if `bicycle_shield_text` is `'12345'`, `bicycle_shield_text_length` would be `'5'`. Missing if `bicycle_shield_text` is !(0 < length < 7) or field doesn't exist * `all_bus_networks` and `all_bus_shield_texts`: All of the bus and trolley-bus routes of which this road is a part, and each corresponding shield text. See `bus_network` and `bus_shield_text` below. **Note** that these properties will not be present on MVT format tiles, as we cannot currently encode lists as values. * `bus_network`: Note that this is often not present for bus routes / networks. This may be replaced with `operator` in the future, see [issue 1194](https://github.com/tilezen/vector-datasource/issues/1194). * `bus_shield_text`: Contains text intended to be displayed on a shield related to the bus or trolley-bus network. This is the value from the `ref` tag and is _not_ guaranteed to be numeric, or even concise. +* `bus_shield_text_length`: The length of the `bus_shield_text` field as a string. E.g. if `bus_shield_text` is `'12345'`, `bus_shield_text_length` would be `'5'`. Missing if `bus_shield_text` is !(0 < length < 7) or field doesn't exist * `surface`: Common values include `asphalt`, `unpaved`, `paved`, `ground`, `gravel`, `dirt`, `concrete`, `grass`, `paving_stones`, `compacted`, `sand`, and `cobblestone`. `cobblestone:flattened`, `concrete:plates` and `concrete:lanes` values are transformed to `cobblestone_flattened`, `concrete_plates` and `concrete_lanes` respectively. These values are simplified at lower zooms, see the section "Roads surface values simplification" for more details. #### Road properties (optional): @@ -1498,6 +1502,7 @@ To improve performance, some road segments are merged at low and mid-zooms. To f * `hgv_restriction`: optional property indicating limitations to heavy goods vehicle truck access. See below for list of values. Available on both point and line geometries. See also `hgv_restriction_shield_text`. * `hgv_time_restrictions` - optional property specifying when heavy goods vehicle truck access is restricted. See the `hgv_time_restrictions` values list below. * `hgv_restriction_shield_text`: optional and paired with `hgv_restriction` points with values like `5.1m`. Because the units are different per restriction an abbreviation should be provided. Values in meters can be specified with one decimal precision but value of 5.0m should be given as 5m. +* `hgv_restriction_shield_text_length`: optional. Returns length of `hgv_restriction_shield_text` as a string. Missing if `hgv_restriction_shield_text` is !(0 < length < 7) or field doesn't exist * `motor_vehicle`: OpenStreetMap features * `operator`: OpenStreetMap features * `piste_difficulty`: ski pistes from OpenStreetMap diff --git a/integration-test/1979-shield-text-length.py b/integration-test/1979-shield-text-length.py new file mode 100644 index 000000000..efd6e6a77 --- /dev/null +++ b/integration-test/1979-shield-text-length.py @@ -0,0 +1,148 @@ +# -*- encoding: utf-8 -*- +import dsl +from . import FixtureTest + +z, x, y = (16, 10470, 25340) + +way35 = { + 'cycleway:right': 'lane', + 'hgv': 'designated', + 'hgv:state_network': 'yes', + 'highway': 'primary', + 'lanes': '2', + 'lcn_ref': '50', + 'maxspeed': '35 mph', + 'name': 'Sloat Boulevard', + 'name:etymology:wikidata': 'Q634931', + 'oneway': 'yes', + 'ref': 'CA 35', + 'sidewalk': 'right', + 'source': 'openstreetmap.org', + 'source:hgv:state_network': 'Caltrans http://www.dot.ca.gov/hq/traffops/trucks/truckmap/', + 'tiger:cfcc': 'A45', + 'tiger:county': 'San Francisco, CA', + 'tiger:name_base': 'Sloat', + 'tiger:name_type': 'Blvd', +} + +rel35 = { + 'network': 'US:CA', + 'ref': '35', + 'route': 'road', + 'source': 'openstreetmap.org', + 'type': 'route', +} + +rel50Cycle = { + 'cycle_network': 'US:CA:SF', + 'network': 'lcn', + 'ref': '50', + 'source': 'openstreetmap.org', + 'route': 'bicycle', + 'type': 'route', +} + +rel23Bus = { + 'network': 'Muni', + 'ref': '23', + 'route': 'bus', + 'source': 'openstreetmap.org', + 'type': 'route', +} + + +class ShieldTextLengthTest(FixtureTest): + + def test_create_shield_text_length(self): + self.generate_fixtures( + # https://www.openstreetmap.org/way/417097119 + dsl.way(417097119, dsl.tile_diagonal(z, x, y), way35), + dsl.relation(1976278, rel35, ways=[417097119]), + dsl.relation(32312, rel50Cycle, ways=[417097119]), + dsl.relation(3002741, rel23Bus, ways=[417097119]) + ) + + self.assert_has_feature( + z, x, y, 'roads', { + 'id': 417097119, + 'shield_text': '35', + 'shield_text_length': '2', + 'bicycle_shield_text': '50', + 'bicycle_shield_text_length': '2', + 'bus_shield_text': '23', + 'bus_shield_text_length': '2' + }) + + # make sure text length is encoded as a string + self.assert_no_matching_feature(z, x, y, 'roads', {'id': 417097119, 'shield_text_length': 2}) + + # empty strings and route refs over 6 chars in length don't report length + def test_lengths_over_6_or_empty_are_not_reported(self): + + rel123456 = rel35.copy() + rel123456['ref'] = '123456' + + relCycleTooLong = rel50Cycle.copy() + relCycleTooLong['ref'] = '1234567' + + relBusEmpty = rel23Bus.copy() + relBusEmpty['ref'] = '' + + self.generate_fixtures( + # https://www.openstreetmap.org/way/417097119 + dsl.way(417097119, dsl.tile_diagonal(z, x, y), way35), + dsl.relation(1976278, rel123456, ways=[417097119]), + dsl.relation(32312, relCycleTooLong, ways=[417097119]), + dsl.relation(3002741, relBusEmpty, ways=[417097119]) + ) + + self.assert_has_feature( + z, x, y, 'roads', { + 'id': 417097119, + 'shield_text': '123456', + 'shield_text_length': '6', + 'bicycle_shield_text': '1234567', + 'bus_shield_text': '', + }) + + self.assert_no_matching_feature(z, x, y, 'roads', { + 'id': 417097119, 'bicycle_shield_text_length': '7', 'bus_shield_text_length': '0'}) + + def test_walking_shield_works(self): + + # modify the data to include a trail to make sure we're adding walking shield text length too + self.generate_fixtures( + # https://www.openstreetmap.org/way/417097119 + dsl.way(417097119, dsl.tile_diagonal(z, x, y), way35), + dsl.relation(1976278, { + "name": "Pacific Crest Trail", + "network": "nwn", + "ref": "PCT", + "route": "hiking", + "type": "route", + "wikidata": "Q2003736", + "wikipedia": "en:Pacific Crest Trail", + }, ways=[417097119]), + ) + + self.assert_has_feature( + z, x, y, 'roads', { + 'id': 417097119, + 'walking_shield_text': 'PCT', + 'walking_shield_text_length': '3', + }) + + def test_hgv_shield_text_length(self): + self.generate_fixtures( + dsl.way(1, dsl.tile_diagonal(z, x, y), + {'highway': 'unclassified', + 'source': 'openstreetmap.org', + 'maxweight': 1.5})) + + self.assert_has_feature( + z, x, y, 'roads', { + 'kind': 'minor_road', + 'kind_detail': 'unclassified', + 'hgv_restriction': 'weight', + 'hgv_restriction_shield_text': '1.5t', + 'hgv_restriction_shield_text_length': '4'}) diff --git a/vectordatasource/transform.py b/vectordatasource/transform.py index 7ddac657b..5c392602f 100644 --- a/vectordatasource/transform.py +++ b/vectordatasource/transform.py @@ -8220,7 +8220,9 @@ def network_key(t): # expose first network as network/shield_text network, ref = tuples[0] properties[prefix + 'network'] = network - properties[prefix + 'shield_text'] = ref + properties[prefix + 'shield_text'] = str(ref) + if 0 < len(ref) <= 7: + properties[prefix + 'shield_text_length'] = str(len(ref)) # replace properties with sorted versions of themselves properties[all_networks] = [n[0] for n in tuples] @@ -8993,6 +8995,8 @@ def _false(val): props['hgv_restriction'] = hgv_restriction if hgv_restriction_shield_text: props['hgv_restriction_shield_text'] = hgv_restriction_shield_text + if 0 < len(hgv_restriction_shield_text) < 7: + props['hgv_restriction_shield_text_length'] = str(len(hgv_restriction_shield_text)) return shape, props, fid