Fix OSM multipolygon buildings
This commit is contained in:
@@ -356,6 +356,90 @@ class ParseOsmTest(unittest.TestCase):
|
||||
os.unlink(handle.name)
|
||||
|
||||
|
||||
class ParseOsmMultipolygonTest(unittest.TestCase):
|
||||
def parse_text(self, text):
|
||||
handle = tempfile.NamedTemporaryFile("w", suffix=".osm", delete=False,
|
||||
encoding="utf-8")
|
||||
handle.write(text)
|
||||
handle.close()
|
||||
try:
|
||||
return parse_osm(handle.name)
|
||||
finally:
|
||||
os.unlink(handle.name)
|
||||
|
||||
def test_building_relation_uses_relation_tags_and_members(self):
|
||||
_, ways, _ = self.parse_text("""<?xml version='1.0' encoding='UTF-8'?>
|
||||
<osm version='0.6'>
|
||||
<bounds minlon='114.0' minlat='30.0' maxlon='114.01' maxlat='30.01'/>
|
||||
<node id='1' lon='114.001' lat='30.001'/>
|
||||
<node id='2' lon='114.004' lat='30.001'/>
|
||||
<node id='3' lon='114.004' lat='30.004'/>
|
||||
<node id='4' lon='114.001' lat='30.004'/>
|
||||
<node id='5' lon='114.002' lat='30.002'/>
|
||||
<node id='6' lon='114.003' lat='30.002'/>
|
||||
<node id='7' lon='114.003' lat='30.003'/>
|
||||
<node id='8' lon='114.002' lat='30.003'/>
|
||||
<way id='outer'><nd ref='1'/><nd ref='2'/><nd ref='3'/><nd ref='4'/><nd ref='1'/></way>
|
||||
<way id='inner'><nd ref='5'/><nd ref='6'/><nd ref='7'/><nd ref='8'/><nd ref='5'/></way>
|
||||
<relation id='65'>
|
||||
<member type='way' ref='outer' role='outer'/>
|
||||
<member type='way' ref='inner' role='inner'/>
|
||||
<tag k='type' v='multipolygon'/>
|
||||
<tag k='building' v='yes'/>
|
||||
<tag k='height' v='8'/>
|
||||
</relation>
|
||||
</osm>
|
||||
""")
|
||||
relation_buildings = [way for way in ways if way["id"] == "65"]
|
||||
self.assertEqual(len(relation_buildings), 1)
|
||||
building = relation_buildings[0]
|
||||
self.assertEqual(building["tags"]["building"], "yes")
|
||||
self.assertEqual(building["tags"]["height"], "8")
|
||||
self.assertEqual(building["source"], "relation")
|
||||
self.assertEqual(len(building["coords"]), 5)
|
||||
self.assertEqual(len(building["inner_coords"]), 1)
|
||||
self.assertEqual(len(building["inner_coords"][0]), 5)
|
||||
|
||||
def test_open_outer_members_are_stitched(self):
|
||||
_, ways, _ = self.parse_text("""<?xml version='1.0' encoding='UTF-8'?>
|
||||
<osm version='0.6'>
|
||||
<bounds minlon='114.0' minlat='30.0' maxlon='114.01' maxlat='30.01'/>
|
||||
<node id='1' lon='114.001' lat='30.001'/>
|
||||
<node id='2' lon='114.004' lat='30.001'/>
|
||||
<node id='3' lon='114.004' lat='30.004'/>
|
||||
<node id='4' lon='114.001' lat='30.004'/>
|
||||
<way id='a'><nd ref='1'/><nd ref='2'/><nd ref='3'/></way>
|
||||
<way id='b'><nd ref='3'/><nd ref='4'/><nd ref='1'/></way>
|
||||
<relation id='66'>
|
||||
<member type='way' ref='a' role='outer'/>
|
||||
<member type='way' ref='b' role='outer'/>
|
||||
<tag k='type' v='multipolygon'/>
|
||||
<tag k='building' v='yes'/>
|
||||
</relation>
|
||||
</osm>
|
||||
""")
|
||||
building = [way for way in ways if way["id"] == "66"][0]
|
||||
self.assertEqual(len(building["coords"]), 5)
|
||||
self.assertEqual(building["coords"][0], building["coords"][-1])
|
||||
|
||||
def test_incomplete_relation_member_is_skipped_not_fatal(self):
|
||||
_, ways, _ = self.parse_text("""<?xml version='1.0' encoding='UTF-8'?>
|
||||
<osm version='0.6'>
|
||||
<bounds minlon='114.0' minlat='30.0' maxlon='114.01' maxlat='30.01'/>
|
||||
<node id='1' lon='114.001' lat='30.001'/>
|
||||
<node id='2' lon='114.004' lat='30.001'/>
|
||||
<way id='broken'><nd ref='1'/><nd ref='2'/></way>
|
||||
<relation id='67'>
|
||||
<member type='way' ref='broken' role='outer'/>
|
||||
<member type='way' ref='missing' role='outer'/>
|
||||
<tag k='type' v='multipolygon'/>
|
||||
<tag k='building' v='yes'/>
|
||||
</relation>
|
||||
</osm>
|
||||
""")
|
||||
self.assertEqual([way["id"] for way in ways], ["broken"])
|
||||
|
||||
|
||||
class TagsTest(unittest.TestCase):
|
||||
def test_reads_key_value_children(self):
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
Reference in New Issue
Block a user