import os
import ruamel.yaml
import logging
import jsonschema
logger = logging.getLogger('plaza_preprocessing.config')
DEFAULT_CONFIG = """
tag-filter:
plaza: # what counts as a plaza
includes:
# tag-keys: # tag keys only
# -
tag-key-values: # tags with specific values
- or:
- highway: pedestrian
- or:
- highway: footway
- area: yes
excludes: # no tags should match
# tag-keys:
# - <key>
tag-key-values:
- or:
- area: no
barrier: # what OSM "way" constitutes a barrier
includes:
tag-key-values:
- or:
- barrier: wall
- or:
- barrier: fence
- or:
- barrier: hedge
- or:
- barrier: retaining_wall
point_obstacle:
includes:
tag-keys:
- amenity
tag-key-values:
- or:
- barrier: block
excludes:
tag-keys:
- indoor
footway-tags: # tags that will be used for the newly generated ways
- highway: footway
graph-strategy: visibility # one of visibility, spiderweb
spiderweb-grid-size: 2 # grid size in meters, if spiderweb is used
obstacle-buffer: 2 # minimal distance from any obstacles in meters
shortest-path-algorithm: astar # one of astar, dijkstra
entry-point-lookup-buffer: 0.05 # tolerance in meters, will be used to detect slightly offset entry points
"""
SCHEMA = {
'title': 'plaza_preprocessing configuration Schema',
'type': 'object',
'properties': {
'tag-filter': {
'type': 'object',
'properties': {
'plaza': {
'type': 'object',
'$ref': '#/definitions/tag-filter'
},
'barrier': {
'type': 'object',
'$ref': '#/definitions/tag-filter'
},
'point_obstacle': {
'type': 'object',
'$ref': '#/definitions/tag-filter'
}
},
'additionalProperties': False,
'required': ['plaza', 'barrier', 'point_obstacle']
},
'footway-tags': {
'type': 'array',
'items': {
'type': 'object',
'additionalProperties': {'type': 'string'}
}
},
'graph-strategy': {
'type': 'string',
'enum': ['visibility', 'spiderweb']
},
'spiderweb-grid-size': {
'type': 'number'
},
'obstacle-buffer': {
'type': 'number'
},
'shortest-path-algorithm': {
'type': 'string',
'enum': ['astar', 'dijkstra']
},
'entry-point-lookup-buffer': {
'type': 'number',
}
},
'additionalProperties': False,
'required': ['tag-filter', 'footway-tags', 'graph-strategy', 'spiderweb-grid-size',
'obstacle-buffer', 'shortest-path-algorithm', 'entry-point-lookup-buffer'],
'definitions': {
'tag-filter': {
'properties': {
'includes': {
'type': 'object',
'$ref': '#/definitions/tag-listing'
},
'excludes': {
'type': 'object',
'$ref': '#/definitions/tag-listing'
}
},
'required': ['includes'],
'additionalProperties': False,
},
'tag-listing': {
'properties': {
'tag-keys': {
'type': 'array',
'items': {'type': 'string'}
},
'tag-key-values': {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'or': {
'type': 'array',
'items': {
'type': 'object',
'additionalProperties': {'type': 'string'}
}
}
}
}
}
}
}
}
}
[docs]def load_config(config_path: str) -> dict:
"""
Loads the configuration and creates the default configuration if it does not yet exist.
"""
# create default config if it does not yet exist
if not os.path.exists(config_path):
create_default_config(config_path)
with open(config_path, 'r') as f:
config = ruamel.yaml.load(f, ruamel.yaml.RoundTripLoader)
jsonschema.validate(config, SCHEMA)
return config
[docs]def create_default_config(config_path: str):
"""
Creates the default configuration file.
"""
logger.info(f"Creating default configuration at {config_path}")
with open(config_path, 'w') as f:
f.write(DEFAULT_CONFIG)
def _or_filter_matches(or_filter, tags):
return any( # or
all( # and
all(tags.get(tag_key) == tag_value for tag_key, tag_value in and_filter.items())
for and_filter in or_filter['or'])
for or_filter in or_filter
)