Skip to content
Snippets Groups Projects

Resolve "Change the processing of the `stories` rule to a `height` GEM Taxonomy tag"

Compare and Show latest version
4 files
+ 42
42
Compare changes
  • Side-by-side
  • Inline
Files
4
@@ -39,12 +39,10 @@ class HeightAndFloorspaceRule:
gem_taxonomy_height = []
# The number of stories ideally comes from the tags from OpenStreetMap. If we are able
# to use that, we can also calculate the floorspace. The height_and_floorspace tags in
# to use that, we can also calculate the floorspace. The height tags in
# OSM are also parsed, but no floorspace is estimated.
try:
stories, floorspace = HeightAndFloorspaceRule.get_stories_and_floorspace_from_osm(
tags, area
)
stories, floorspace = self.get_stories_and_floorspace_from_osm(tags, area)
# OSM can have unexpected data types in their tagging scheme, therefore we do not raise
# an exception in case of a ValueError, but instead ignore the values.
except ValueError:
@@ -53,7 +51,7 @@ class HeightAndFloorspaceRule:
gem_taxonomy_height.append(stories)
try:
height = HeightAndFloorspaceRule.get_height_from_osm(tags)
height = self.get_height_from_osm(tags)
# OSM can have unexpected data types in their tagging scheme, therefore we do not raise
# an exception in case of a ValueError, but instead ignore the values.
except ValueError:
@@ -61,24 +59,22 @@ class HeightAndFloorspaceRule:
if height:
gem_taxonomy_height.append(height)
# If any of the number of stories and height_and_floorspace are found in OSM, these are
# returned.
# If any of the number of stories and height are found in OSM, these are returned.
if len(gem_taxonomy_height) > 0:
return {
"height_and_floorspace": "+".join(gem_taxonomy_height),
"height": "+".join(gem_taxonomy_height),
"floorspace": floorspace,
}
# If no information can be retrieved from OSM, we use the height_and_floorspace
# estimation from GHSL and do not estimate any floorspace.
ghsl_height = HeightAndFloorspaceRule.get_height_from_ghsl(ghsl_characteristics_type)
# If no information can be retrieved from OSM, we use the height estimation from GHSL
# and do not estimate any floorspace.
ghsl_height = self.get_height_from_ghsl(ghsl_characteristics_type)
if ghsl_height:
return {"height_and_floorspace": ghsl_height, "floorspace": None}
return {"height": ghsl_height, "floorspace": None}
return {"height_and_floorspace": None, "floorspace": None}
return {"height": None, "floorspace": None}
@staticmethod
def get_stories_and_floorspace_from_osm(tags: dict, area: float):
def get_stories_and_floorspace_from_osm(self, tags: dict, area: float):
"""
Get the number of stories and the floorspace, based on the tags `building:levels`,
`roof:levels`, `building:levels:underground` and `building:min_level` and the footprint
@@ -91,18 +87,16 @@ class HeightAndFloorspaceRule:
Footprint size of the building.
Returns:
A string formatted according to the `height_and_floorspace` tag in the GEM Taxonomy.
A string formatted according to the `height` tag in the GEM Taxonomy.
"""
from math import ceil
# Parse the story tags from OpenStreetMap.
main_stories = HeightAndFloorspaceRule.tag_to_float(tags, "building:levels")
roof_stories = HeightAndFloorspaceRule.tag_to_float(tags, "roof:levels")
underground_stories = HeightAndFloorspaceRule.tag_to_float(
tags, "building:levels:underground"
)
min_stories = HeightAndFloorspaceRule.tag_to_float(tags, "building:min_level")
main_stories = self.tag_to_float(tags, "building:levels")
roof_stories = self.tag_to_float(tags, "roof:levels")
underground_stories = self.tag_to_float(tags, "building:levels:underground")
min_stories = self.tag_to_float(tags, "building:min_level")
# Parse the main stories and roof stories.
stories = None
@@ -155,29 +149,27 @@ class HeightAndFloorspaceRule:
return "+".join(story_tags), floorspace
@staticmethod
def get_height_from_osm(tags: dict):
def get_height_from_osm(self, tags: dict):
"""
Get the height_and_floorspace of a building, based on the `height_and_floorspace` and
`min_height` tags.
Get the heightb of a building, based on the `height` and `min_height` tags.
Args:
tags (dict):
Building tags, such as the building levels or building type.
Returns:
A string formatted according to the `height_and_floorspace` tag in the GEM Taxonomy.
A string formatted according to the `height` tag in the GEM Taxonomy.
"""
# Parse the height_and_floorspace tag from OpenStreetMap.
height = HeightAndFloorspaceRule.tag_to_float(tags, "height_and_floorspace")
# Parse the height tag from OpenStreetMap.
height = self.tag_to_float(tags, "height")
# Check if height_and_floorspace exists
# Check if height exists
if not height:
return None
# Check if there is a `min_height` tag
min_height = HeightAndFloorspaceRule.tag_to_float(tags, "min_height")
min_height = self.tag_to_float(tags, "min_height")
if min_height:
height -= min_height
@@ -186,10 +178,9 @@ class HeightAndFloorspaceRule:
return f"HHT:{height:.2f}"
@staticmethod
def get_height_from_ghsl(ghsl_characteristics_type: int):
def get_height_from_ghsl(self, ghsl_characteristics_type: int):
"""
Get the GEM Taxonomy height_and_floorspace tag, based on the type in the GHSL
Get the GEM Taxonomy height tag, based on the type in the GHSL
characteristics layer that has the most overlap with the building.
Args:
@@ -197,7 +188,7 @@ class HeightAndFloorspaceRule:
The GHSL characteristics type most overlapping the building.
Returns:
A string formatted according to the `height_and_floorspace` tag in the GEM Taxonomy.
A string formatted according to the `height` tag in the GEM Taxonomy.
"""
ghsl_type_map = {
@@ -214,8 +205,7 @@ class HeightAndFloorspaceRule:
}
return ghsl_type_map.get(ghsl_characteristics_type, None)
@staticmethod
def tag_to_float(tags: dict, tag_key: str):
def tag_to_float(self, tags: dict, tag_key: str):
"""
Try to parse a tag as a floating point value. If the value cannot be parsed, return
None.
Loading