Skip to content

Commit cea49b1

Browse files
committed
Normalize incline values during OSM to OSW conversion
1 parent f92d546 commit cea49b1

File tree

4 files changed

+73
-6
lines changed

4 files changed

+73
-6
lines changed

src/osm_osw_reformatter/serializer/osw/osw_normalizer.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def normalize(self):
6767
raise ValueError("This is an invalid way")
6868

6969
def _normalize_way(self, keep_keys={}, defaults = {}):
70-
generic_keep_keys = {"highway": str, "width": float, "surface": surface, "name": str, "description": str, "foot": foot}
70+
generic_keep_keys = {"highway": str, "width": float, "surface": surface, "name": str, "description": str, "foot": foot, "incline": incline}
7171
generic_defaults = {}
7272

7373
new_tags = _normalize(self.tags, {**generic_keep_keys, **keep_keys}, {**generic_defaults, **defaults})
@@ -81,7 +81,7 @@ def _normalize_pedestrian(self, keep_keys = {}, defaults = {}):
8181
return new_tags
8282

8383
def _normalize_stairs(self, keep_keys = {}, defaults = {}):
84-
generic_keep_keys = {"step_count": int, "incline": ["climb", climb]}
84+
generic_keep_keys = {"step_count": int, "incline": incline}
8585
generic_defaults = {"foot": "yes"}
8686

8787
new_tags = self._normalize_way({**generic_keep_keys, **keep_keys}, {**generic_defaults, **defaults})
@@ -584,13 +584,19 @@ def crossing_markings(tag_value, tags):
584584
return None
585585

586586
def climb(tag_value, tags):
587-
if tag_value.lower() not in (
587+
if tag_value.lower() not in (
588588
"up",
589589
"down"
590590
):
591591
return None
592592
else:
593593
return tag_value.lower()
594+
595+
def incline(tag_value, tags):
596+
try:
597+
return float(str(tag_value).rstrip('%'))
598+
except (ValueError, TypeError):
599+
return None
594600

595601
def foot(tag_value, tags):
596602
if tag_value.lower() not in (
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<osm version="0.6" generator="test" upload="false">
3+
<node id="1" lat="0.0" lon="0.0" />
4+
<node id="2" lat="0.0" lon="0.1" />
5+
<way id="1">
6+
<nd ref="1"/>
7+
<nd ref="2"/>
8+
<tag k="highway" v="footway"/>
9+
<tag k="incline" v="0.1"/>
10+
<tag k="_id" v="1"/>
11+
</way>
12+
</osm>

tests/unit_tests/test_osm2osw/test_osm2osw.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
OUTPUT_DIR = os.path.join(os.path.dirname(os.path.dirname(ROOT_DIR)), 'output')
1111
TEST_FILE = os.path.join(ROOT_DIR, 'test_files/wa.microsoft.osm.pbf')
1212
TEST_WIDTH_FILE = os.path.join(ROOT_DIR, 'test_files/width-test.xml')
13+
TEST_INCLINE_FILE = os.path.join(ROOT_DIR, 'test_files/incline-test.xml')
1314

1415

1516
def is_valid_float(value):
@@ -218,6 +219,33 @@ async def run_test():
218219

219220
asyncio.run(run_test())
220221

222+
def test_retains_incline_tag(self):
223+
osm_file_path = TEST_INCLINE_FILE
224+
225+
async def run_test():
226+
osm2osw = OSM2OSW(osm_file=osm_file_path, workdir=OUTPUT_DIR, prefix='test')
227+
result = await osm2osw.convert()
228+
self.assertTrue(result.status)
229+
230+
found_incline = False
231+
for file_path in result.generated_files:
232+
if file_path.endswith('edges.geojson'):
233+
with open(file_path) as f:
234+
geojson = json.load(f)
235+
for feature in geojson.get('features', []):
236+
props = feature.get('properties', {})
237+
if 'incline' in props:
238+
self.assertIsInstance(props['incline'], (int, float))
239+
found_incline = True
240+
break
241+
242+
for file_path in result.generated_files:
243+
os.remove(file_path)
244+
245+
self.assertTrue(found_incline, 'Incline tag not found in output edges')
246+
247+
asyncio.run(run_test())
248+
221249

222250
if __name__ == '__main__':
223251
unittest.main()

tests/unit_tests/test_serializer/test_osw_normalizer.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import unittest
2-
from src.osm_osw_reformatter.serializer.osw.osw_normalizer import OSWWayNormalizer, OSWNodeNormalizer, \
3-
OSWPointNormalizer, tactile_paving, surface, crossing_markings, climb, _normalize
2+
from src.osm_osw_reformatter.serializer.osw.osw_normalizer import (
3+
OSWWayNormalizer,
4+
OSWNodeNormalizer,
5+
OSWPointNormalizer,
6+
tactile_paving,
7+
surface,
8+
crossing_markings,
9+
climb,
10+
incline,
11+
_normalize,
12+
)
413

514

615
class TestOSWWayNormalizer(unittest.TestCase):
@@ -53,6 +62,13 @@ def test_normalize_crossing(self):
5362
expected = {'highway': 'footway', 'footway': 'crossing', 'foot': 'yes'}
5463
self.assertEqual(result, expected)
5564

65+
def test_normalize_incline(self):
66+
tags = {'highway': 'footway', 'incline': '10%'}
67+
normalizer = OSWWayNormalizer(tags)
68+
result = normalizer.normalize()
69+
expected = {'highway': 'footway', 'incline': 10.0, 'foot': 'yes'}
70+
self.assertEqual(result, expected)
71+
5672
def test_normalize_invalid_way(self):
5773
tags = {'highway': 'invalid_type'}
5874
normalizer = OSWWayNormalizer(tags)
@@ -121,11 +137,16 @@ def test_crossing_markings(self):
121137
self.assertEqual(crossing_markings('dots', {'crossing:markings': 'dots'}), 'dots')
122138
self.assertIsNone(crossing_markings('invalid_value', {'crossing:markings': 'invalid_value'}))
123139

124-
def test_incline(self):
140+
def test_climb(self):
125141
self.assertEqual(climb('up', {}), 'up')
126142
self.assertEqual(climb('down', {}), 'down')
127143
self.assertIsNone(climb('invalid_value', {}))
128144

145+
def test_incline(self):
146+
self.assertEqual(incline('10%', {}), 10.0)
147+
self.assertEqual(incline('0.5', {}), 0.5)
148+
self.assertIsNone(incline('steep', {}))
149+
129150

130151
class TestNormalizeWidthField(unittest.TestCase):
131152
def test_removes_width_when_value_is_nan_string(self):

0 commit comments

Comments
 (0)