Skip to content
Snippets Groups Projects
Commit 9bc4dba5 authored by Laurens Oostwegel's avatar Laurens Oostwegel Committed by Laurens Oostwegel
Browse files

Add processing rules

parent 05912aa5
No related branches found
No related tags found
1 merge request!4Resolve "Create the Geometry, Quadkey, RelationID and Floorspace rules"
Pipeline #65093 passed
Showing with 173 additions and 6 deletions
...@@ -25,7 +25,6 @@ linters: ...@@ -25,7 +25,6 @@ linters:
script: script:
- flake8 --max-line-length=$LINE_LENGTH $SOURCES - flake8 --max-line-length=$LINE_LENGTH $SOURCES
- black --check --line-length $LINE_LENGTH $SOURCES - black --check --line-length $LINE_LENGTH $SOURCES
- pylint -E $SOURCES
release_job: release_job:
stage: release stage: release
......
class GeometryRule:
def __call__(self, geometry, *args, **kwargs):
"""
Wrap the WKT formatted geometry of a building in the `ST_GeomFromText()` function
Args:
geometry (str):
WKT formatted geometry of the building
Returns:
A dictionary with the WKT formatted geometry of the building wrapped in the
`ST_GeomFromText()` function.
"""
return {"geometry": f"ST_GeomFromText('{geometry}', 4326)"}
<?xml version="1.0" encoding="UTF-8" ?>
<rule name="GeometryRule">
<input>
<param type="str">geometry</param>
</input>
<function filepath="geometry.py"/>
<output>
<param type="str">geometry</param>
</output>
</rule>
class QuadkeyRule:
def __call__(self, longitude, latitude, *args, **kwargs):
"""
Determine the Quadkey of the tile in which the building centroid is located given its
longitude and latitude.
Args:
longitude:
Longitude of the building centroid
latitude:
Latitude of the building centroid
Returns:
A dictionary with the zoom-level 18 Quadkey.
"""
import mercantile
if longitude is None or latitude is None:
quadkey = None
else:
quadkey = mercantile.quadkey(mercantile.tile(longitude, latitude, 18))
return {"quadkey": quadkey}
<?xml version="1.0" encoding="UTF-8" ?>
<rule name="QuadkeyRule">
<input>
<param type="float">longitude</param>
<param type="float">latitude</param>
</input>
<function filepath="quadkey.py"/>
<output>
<param type="str">quadkey</param>
</output>
</rule>
class RelationIDRule:
def __call__(self, relations, *args, **kwargs):
"""
Determine the building relation OSM ID.
Args:
relations:
List of the attributes of all relations that the building is member of.
Returns:
OSM ID of the first relation that the building is member of.
"""
for relation in relations:
osm_id = relation.get("osm_id", None)
if osm_id is not None:
return {"relation_id": osm_id}
return {"relation_id": None}
<?xml version="1.0" encoding="UTF-8" ?>
<rule name="RelationIDRule">
<input>
<param type="list">relations</param>
</input>
<function filepath="relation_id.py"/>
<output>
<param type="int">relation_id</param>
</output>
</rule>
<?xml version="1.0" encoding="UTF-8" ?>
<rule name="StoriesAndFloorspaceRule" category="building">
<input>
<param type="int">tags</param>
<param type="float">relations</param>
<param type="float">area</param>
</input>
<function filepath="stories_and_floorspace.py"/>
<output>
<param type="float">storeys</param>
<param type="float">floorspace</param>
</output>
</rule>
class StoriesAndFloorspaceRule:
def __call__(self, tags, relations, area, *args, **kwargs):
"""
Find the `building:levels` tag in the attributes of the building or one of the building
relations and save this as the number of stories. Calculate the floorspace of the
building, based on the footprint size of the building and the number of stories.
Args:
tags (dict):
Building tags, such as the building levels or building type.
relations (list):
List of the attributes of all relations that the building is member of.
area (float):
Footprint size of the building.
Returns:
A dictionary with the number of stories and the floorspace of the building.
"""
from math import ceil
story_options = [
self.get_story_tag(building["tags"]) for building in [tags] + relations
]
for story_string in story_options:
if story_string is None or story_string == "":
continue
try:
stories = ceil(float(story_string))
if stories < 1:
raise ValueError("Number of stories cannot be below 1")
floorspace = stories * area
return {"stories": stories, "floorspace": floorspace}
except ValueError:
continue
return {"stories": None, "floorspace": None}
@staticmethod
def get_story_tag(tags):
"""
Get the number of stories, if the attribute `building:levels` exist
Args:
tags:
Building tags, such as the building levels or building type.
Returns:
Number of stories, if the attribute `building:levels` exist, otherwise `None`.
"""
return tags.get("building:levels", None)
...@@ -6,7 +6,7 @@ class ObmBuildingsUpsert: ...@@ -6,7 +6,7 @@ class ObmBuildingsUpsert:
osm_id, osm_id,
floorspace=None, floorspace=None,
occupancy=None, occupancy=None,
storeys=None, stories=None,
relation_id=None, relation_id=None,
quadkey=None, quadkey=None,
*args, *args,
...@@ -27,7 +27,7 @@ class ObmBuildingsUpsert: ...@@ -27,7 +27,7 @@ class ObmBuildingsUpsert:
The calculated floorspace of the building. The calculated floorspace of the building.
occupancy (str): occupancy (str):
The occupancy type formatted to the GEM occupancy types. The occupancy type formatted to the GEM occupancy types.
storeys (int): stories (int):
Number of stories in the building. Number of stories in the building.
relation_id (int): relation_id (int):
ID of the OSM relation feature that this building is part of. ID of the OSM relation feature that this building is part of.
...@@ -44,7 +44,7 @@ class ObmBuildingsUpsert: ...@@ -44,7 +44,7 @@ class ObmBuildingsUpsert:
{geometry}, {geometry},
{self.format_value(floorspace)}, {self.format_value(floorspace)},
{self.format_value(occupancy)}, {self.format_value(occupancy)},
{self.format_value(storeys)}, {self.format_value(stories)},
{self.format_value(relation_id)}, {self.format_value(relation_id)},
{self.format_value(quadkey)}, {self.format_value(quadkey)},
NOW() NOW()
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<param type="int">osm_id</param> <param type="int">osm_id</param>
<param type="float">floorspace</param> <param type="float">floorspace</param>
<param type="str">occupancy</param> <param type="str">occupancy</param>
<param type="int">storeys</param> <param type="int">stories</param>
<param type="int">relation_id</param> <param type="int">relation_id</param>
<param type="str">quadkey</param> <param type="str">quadkey</param>
</input> </input>
......
...@@ -10,7 +10,23 @@ all land-use objects that intersect the building. ...@@ -10,7 +10,23 @@ all land-use objects that intersect the building.
### Process rules ### Process rules
*Not implemented* * **Geometry**
Wraps the WKT formatted geometry of a building in the `ST_GeomFromText()` function
* **Quadkey**
Determines the Quadkey tile of a building, based on the latitude and longitude of the centroid.
* **RelationID**
Determines the building relation OSM ID.
* **StoriesAndFloorspace**
Finds the `building:levels` tag in the attributes of the building or one of the building
relations and saves it as number of stories. Calculates the floorspace of the building, based on the
footprint size of the building and the number of stories.
### Upsert rules ### Upsert rules
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment