import logging
import unittest
from collections import Counter
import mock
from qgis.core import QgsExpression, QgsFeature, QgsFeatureRequest, QgsVectorLayer
from catatom2osm import osm
from catatom2osm.app import QgsSingleton
from catatom2osm.geo.geometry import Geometry
from catatom2osm.geo.layer.address import AddressLayer
from catatom2osm.geo.layer.cons import ConsLayer
from catatom2osm.geo.point import Point
from catatom2osm.geo.tools import is_inside
qgs = QgsSingleton()
m_log = mock.MagicMock()
m_log.app_level = logging.INFO
[docs]class TestConsLayerSimple(unittest.TestCase):
[docs] def test_is_building(self):
self.assertTrue(ConsLayer.is_building({"localId": "foobar"}))
self.assertFalse(ConsLayer.is_building({"localId": "foo_bar"}))
[docs] def test_is_part(self):
self.assertTrue(ConsLayer.is_part({"localId": "foo_part1"}))
self.assertFalse(ConsLayer.is_part({"localId": "foo_PI.1"}))
[docs] def test_is_pool(self):
self.assertTrue(ConsLayer.is_pool({"localId": "foo_PI.1"}))
self.assertFalse(ConsLayer.is_pool({"localId": "foo_part1"}))
[docs] def test_get_id(self):
buil = {"localId": "XXXXXX14XXXXXX"}
part = {"localId": "XXXXXX14XXXXXX_part9"}
pool = {"localId": "XXXXXX14XXXXXX_PI.99"}
addr = {"localId": "99.999.9.9.XXXXXX14XXXXXX"}
self.assertTrue(ConsLayer.get_id(part), buil["localId"])
self.assertTrue(ConsLayer.get_id(pool), buil["localId"])
self.assertTrue(ConsLayer.get_id(addr), buil["localId"])
[docs]class TestConsLayer(unittest.TestCase):
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def setUp(self):
fn = "test/fixtures/cons.shp"
self.fixture = QgsVectorLayer(fn, "building", "ogr")
self.assertTrue(self.fixture.isValid(), "Loading fixture")
fn = "test_layer.shp"
ConsLayer.create_shp(fn, self.fixture.crs())
self.layer = ConsLayer(fn, "zoning", "ogr")
self.assertTrue(self.layer.isValid(), "Init QGIS")
self.layer.append(self.fixture, rename="")
self.assertEqual(self.layer.featureCount(), self.fixture.featureCount())
[docs] def tearDown(self):
del self.layer
ConsLayer.delete_shp("test_layer.shp")
[docs] def test_merge_adjacent_features(self):
parts = [p for p in self.layer.search("localId like '8840501CS5284S_part%%'")]
geom = Geometry.merge_adjacent_features(parts)
area = sum([p.geometry().area() for p in parts])
self.assertEqual(100 * round(geom.area(), 2), 100 * round(area, 2))
self.assertGreater(len(Geometry.get_multipolygon(geom)), 0)
self.assertLess(len(Geometry.get_multipolygon(geom)), len(parts))
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_explode_multi_parts(self):
mp0 = [
f for f in self.layer.getFeatures() if len(Geometry.get_multipolygon(f)) > 1
]
self.assertGreater(len(mp0), 0)
address = AddressLayer()
fn = "test/fixtures/address.gml"
address_gml = QgsVectorLayer(fn, "address", "ogr")
address.append(address_gml)
refs = {ad["localId"].split(".")[-1] for ad in address.getFeatures()}
mp1 = [
f
for f in self.layer.getFeatures()
if f["localId"] in refs and len(Geometry.get_multipolygon(f)) > 1
]
self.assertGreater(len(mp1), 0)
self.layer.explode_multi_parts(address)
mp2 = [
f for f in self.layer.getFeatures() if len(Geometry.get_multipolygon(f)) > 1
]
self.assertEqual(len(mp1), len(mp2))
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_append_building(self):
layer = ConsLayer()
self.assertTrue(layer.isValid(), "Init QGIS")
fn = "test/fixtures/building.gml"
fixture = QgsVectorLayer(fn, "building", "ogr")
self.assertTrue(fixture.isValid())
layer.append(fixture)
feature = next(fixture.getFeatures())
new_fet = next(layer.getFeatures())
self.assertEqual(feature["conditionOfConstruction"], new_fet["condition"])
self.assertEqual(feature["localId"], new_fet["localId"])
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_append_buildingpart(self):
layer = ConsLayer()
self.assertTrue(layer.isValid(), "Init QGIS")
fn = "test/fixtures/buildingpart.gml"
fixture = QgsVectorLayer(fn, "building", "ogr")
self.assertTrue(fixture.isValid())
layer.append(fixture)
feature = next(fixture.getFeatures())
new_fet = next(layer.getFeatures())
self.assertEqual(feature["numberOfFloorsAboveGround"], new_fet["lev_above"])
self.assertEqual(feature["localId"], new_fet["localId"])
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_append_othercons(self):
layer = ConsLayer()
self.assertTrue(layer.isValid(), "Init QGIS")
fn = "test/fixtures/othercons.gml"
fixture = QgsVectorLayer(fn, "building", "ogr")
self.assertTrue(fixture.isValid())
layer.append(fixture)
feature = next(fixture.getFeatures())
new_fet = next(layer.getFeatures())
self.assertEqual(feature["constructionNature"], new_fet["nature"])
self.assertEqual(feature["localId"], new_fet["localId"])
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_append_cons(self):
exp = QgsExpression("nature = 'openAirPool'")
request = QgsFeatureRequest(exp)
feat = next(self.layer.getFeatures(request))
self.assertNotEqual(feat, None)
layer = ConsLayer()
layer.rename = {}
layer.append(self.layer)
feat = next(layer.getFeatures(request))
self.assertNotEqual(feat, None)
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_remove_parts_below_ground(self):
to_clean = [f.id() for f in self.layer.search("lev_above=0 and lev_below>0")]
self.assertGreater(len(to_clean), 0, "There are parts below ground")
self.layer.remove_outside_parts()
to_clean = [f.id() for f in self.layer.search("lev_above=0 and lev_below>0")]
self.assertEqual(len(to_clean), 0, "There are not parts below ground")
[docs] def test_index_of_parts(self):
parts = self.layer.index_of_parts()
p = {f.id(): f for f in self.layer.getFeatures() if self.layer.is_part(f)}
self.assertEqual(sum(len(g) for g in list(parts.values())), len(p))
for (localid, group) in list(parts.items()):
for pa in group:
self.assertTrue(localid, pa["localid"].split("_")[0])
self.assertIn("_", pa["localid"])
[docs] def test_index_of_building_and_parts(self):
(buildings, parts) = self.layer.index_of_building_and_parts()
b = [f for f in self.layer.getFeatures() if self.layer.is_building(f)]
p = [f for f in self.layer.getFeatures() if self.layer.is_part(f)]
self.assertEqual(sum(len(g) for g in list(buildings.values())), len(b))
self.assertEqual(sum(len(g) for g in list(parts.values())), len(p))
self.assertTrue(
all(
[
localid == bu["localid"]
for (localid, group) in list(buildings.items())
for bu in group
]
)
)
self.assertTrue(
all(
[
localid == pa["localid"][0:14]
for (localid, group) in list(parts.items())
for pa in group
]
)
)
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_remove_outside_parts(self):
refs = [
"8742721CS5284S_part10",
"8742721CS5284S_part5",
"8742708CS5284S_part1",
"8742707CS5284S_part2",
"8742707CS5284S_part6",
]
self.layer.remove_outside_parts()
for feat in self.layer.getFeatures():
self.assertNotIn(feat["localId"], refs)
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_get_parts(self):
self.layer.explode_multi_parts()
parts = [p for p in self.layer.search("localId like '8840501CS5284S_part%%'")]
for outline in self.layer.search("localId = '8840501CS5284S'"):
parts_inside = [p for p in parts if is_inside(p, outline)]
parts_for_level, max_level, min_level = self.layer.get_parts(outline, parts)
max_levelc = max([p["lev_above"] for p in parts_inside])
min_levelc = max([p["lev_below"] for p in parts_inside])
self.assertEqual(
len(parts_inside), sum([len(p) for p in list(parts_for_level.values())])
)
for part in parts_inside:
self.assertIn(
part, parts_for_level[(part["lev_above"], part["lev_below"])]
)
self.assertEqual(max_level, max_levelc)
self.assertEqual(min_level, min_levelc)
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_merge_adjacent_parts(self, ref=None):
if ref is None:
self.layer.explode_multi_parts()
ref = "8842323CS5284S"
parts = [p for p in self.layer.search("localId like '%s_part%%'" % ref)]
for outline in self.layer.search("localId = '%s'" % ref):
cn, cng, ch, chg = self.layer.merge_adjacent_parts(outline, parts)
parts_for_level, max_level, min_level = self.layer.get_parts(outline, parts)
if len(parts_for_level) > 1:
areap = 0
for level, group in list(parts_for_level.items()):
geom = Geometry.merge_adjacent_features(group)
poly = Geometry.get_multipolygon(geom)
if len(poly) < len(group):
areap += geom.area()
aream = sum([g.area() for g in list(chg.values())])
self.assertEqual(100 * round(areap, 2), 100 * round(aream, 2))
self.assertEqual(len(cn), 0)
else:
self.assertEqual(
set(cn),
set([p.id() for p in parts_for_level[max_level, min_level]]),
)
self.assertEqual(
max([level[0] for level in list(parts_for_level.keys())]), max_level
)
self.assertEqual(
max([level[1] for level in list(parts_for_level.keys())]), min_level
)
self.assertEqual(ch[outline.id()][6], max_level)
self.assertEqual(ch[outline.id()][7], min_level)
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_merge_building_parts(self):
self.layer.remove_outside_parts()
self.layer.merge_building_parts()
for ref in self.layer.getFeatures():
if self.layer.is_building(ref):
self.test_merge_adjacent_parts(ref)
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.polygon.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_add_topological_points(self):
refs = [
("8842708CS5284S", Point(358821.08, 3124205.68), 0),
("8842708CS5284S_part1", Point(358821.08, 3124205.68), 0),
("8942328CS5284S", Point(358857.04, 3124248.6705), 1),
("8942328CS5284S_part3", Point(358857.04, 3124248.6705), 0),
]
for ref in refs:
building = next(self.layer.search("localId = '%s'" % ref[0]))
poly = Geometry.get_multipolygon(building)
self.assertNotIn(ref[1], poly[ref[2]][0])
self.layer.topology()
for ref in refs:
building = next(self.layer.search("localId = '%s'" % ref[0]))
poly = Geometry.get_multipolygon(building)
self.assertIn(ref[1], poly[ref[2]][0])
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.polygon.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_delete_invalid_geometries(self):
f1 = QgsFeature(self.layer.fields())
g1 = Geometry.fromPolygonXY(
[
[
Point(358794.000, 3124330.000),
Point(358794.200, 3124329.800),
Point(358794.400, 3124330.000),
Point(358794.200, 3124500.000),
Point(358794.000, 3124330.000),
]
]
)
f1.setGeometry(g1)
f2 = QgsFeature(self.layer.fields())
g2 = Geometry.fromPolygonXY(
[
[
Point(358794.000, 3124330.000),
Point(358795.000, 3124331.000),
Point(358794.500, 3124500.000),
Point(358794.000, 3124330.000),
]
]
)
f2.setGeometry(g2)
f3 = QgsFeature(self.layer.fields())
g3 = Geometry.fromPolygonXY(
[
[
Point(358890.000, 3124329.000),
Point(358900.000, 3124329.000),
Point(358900.000, 3124501.000),
Point(358890.000, 3124501.000),
Point(358890.000, 3124330.000),
],
[
Point(358894.000, 3124330.000),
Point(358895.000, 3124331.000),
Point(358894.500, 3124500.000),
Point(358894.000, 3124330.000),
],
]
)
f3.setGeometry(g3)
f4 = QgsFeature(self.layer.fields())
g4 = Geometry.fromPolygonXY(
[
[
Point(357400.00, 3124305.00), # spike
Point(357405.00, 3124305.04),
Point(357404.99, 3124307.60),
Point(357405.00, 3124307.40), # zig-zag
Point(357405.00, 3124313.00), # spike
Point(357405.04, 3124310.00),
Point(357407.50, 3124311.00),
Point(357409.96, 3124310.00),
Point(357410.00, 3124313.00), # spike
Point(357410.02, 3124306.00),
Point(357410.00, 3124305.00),
Point(357400.00, 3124305.00),
]
]
)
f4.setGeometry(g4)
f5 = QgsFeature(self.layer.fields())
g5 = Geometry.fromPolygonXY(
[
[
Point(357400.00, 3124305.00),
Point(357405.00, 3124305.04),
Point(357405.00, 3124310.00),
Point(357400.00, 3124310.00),
Point(357400.00, 3124305.00),
]
]
)
f5.setGeometry(g5)
fc = self.layer.featureCount()
self.layer.writer.addFeatures([f1, f2, f3, f4, f5])
self.layer.delete_invalid_geometries()
self.assertEqual(fc, self.layer.featureCount() - 3)
request = QgsFeatureRequest().setFilterFid(self.layer.featureCount() - 3)
f = next(self.layer.getFeatures(request))
mp = Geometry.get_multipolygon(f)
self.assertEqual(len(mp[0]), 1)
request = QgsFeatureRequest().setFilterFid(self.layer.featureCount() - 2)
f = next(self.layer.getFeatures(request))
mp = Geometry.get_multipolygon(f)
r = [
(357410.00, 3124305.00),
(357405.00, 3124305.00),
(357405.00, 3124309.98),
(357407.50, 3124311.00),
(357410.01, 3124310.02),
(357410.02, 3124306.00),
(357410.00, 3124305.00),
]
self.assertEqual(r, [(round(p.x(), 2), round(p.y(), 2)) for p in mp[0][0]])
request = QgsFeatureRequest().setFilterFid(self.layer.featureCount() - 1)
f = next(self.layer.getFeatures(request))
mp = Geometry.get_multipolygon(f)
r = [
(357400.00, 3124305.00),
(357400.00, 3124310.00),
(357405.00, 3124310.00),
(357405.00, 3124305.00),
(357400.00, 3124305.00),
]
self.assertEqual(r, [(round(p.x(), 2), round(p.y(), 2)) for p in mp[0][0]])
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.polygon.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_simplify1(self):
refs = [
("8643326CS5284S", Point(358684.62, 3124377.54), True),
("8643326CS5284S", Point(358686.29, 3124376.11), True),
("8643324CS5284S", Point(358677.29, 3124366.64), False),
]
self.layer.explode_multi_parts()
self.layer.simplify()
for ref in refs:
building = next(self.layer.search("localId = '%s'" % ref[0]))
self.assertEqual(
ref[1] in Geometry.get_multipolygon(building)[0][0], ref[2]
)
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.polygon.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_simplify2(self):
layer = ConsLayer()
fn = "test/fixtures/38023.buildingpart.gml"
fixture1 = QgsVectorLayer(fn, "building", "ogr")
self.assertTrue(fixture1.isValid(), "Loading fixture")
layer.append(fixture1, rename="")
self.assertEqual(layer.featureCount(), fixture1.featureCount())
fn = "test/fixtures/38023.buildingpart.gml"
fixture2 = QgsVectorLayer(fn, "buildingpart", "ogr")
self.assertTrue(fixture2.isValid(), "Loading fixture")
layer.append(fixture2, rename="")
self.assertEqual(
layer.featureCount(),
fixture1.featureCount() + fixture2.featureCount(),
)
layer.remove_outside_parts()
layer.explode_multi_parts()
layer.topology()
layer.simplify()
for feat in layer.getFeatures():
geom = feat.geometry()
self.assertTrue(geom.isGeosValid(), feat["localId"])
layer.merge_building_parts()
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_move_address(self):
refs = {
"38.012.10.10.8643403CS5284S": "Entrance",
"38.012.10.11.8842304CS5284S": "Entrance",
# '38.012.10.13.8842305CS5284S': 'Entrance',
"38.012.10.14.8643404CS5284S": "corner",
"38.012.10.14.8643406CS5284S": "Parcel",
"38.012.10.2.8642321CS5284S": "Entrance",
"38.012.15.73.8544911CS5284S": "remote",
}
self.layer.explode_multi_parts()
address = AddressLayer()
fn = "test/fixtures/address.gml"
address_gml = QgsVectorLayer(fn, "address", "ogr")
address.append(address_gml)
self.assertEqual(address.featureCount(), 14)
self.layer.move_address(address)
self.assertEqual(address.featureCount(), 7)
for ad in address.getFeatures():
if ad["localId"] in list(refs.keys()):
self.assertEqual(ad["spec"], refs[ad["localId"]])
if ad["spec"] == "Entrance":
refcat = ad["localId"].split(".")[-1]
building = next(self.layer.search("localId = '%s'" % refcat))
self.assertTrue(ad.geometry().touches(building.geometry()))
self.layer.move_address(address)
self.assertEqual(address.featureCount(), 6)
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_validate(self):
self.layer.merge_building_parts()
max_level = {}
min_level = {}
self.layer.validate(max_level, min_level)
refs = ["7239208CS5273N", "38012A00400007"]
for (l, v) in list({1: 126, 2: 114, 3: 67, 4: 16, 5: 1}.items()):
self.assertEqual(Counter(list(max_level.values()))[l], v)
for (l, v) in list({1: 68, 2: 2}.items()):
self.assertEqual(Counter(list(min_level.values()))[l], v)
for ref in refs:
exp = QgsExpression("localId = '%s'" % ref)
request = QgsFeatureRequest(exp)
feat = next(self.layer.getFeatures(request))
self.assertNotEqual(feat["fixme"], "")
[docs] def test_to_osm(self):
data = self.layer.to_osm(upload="always")
self.assertEqual(data.upload, "always")
ways = 0
rels = 0
for feat in self.layer.getFeatures():
p = Geometry.get_multipolygon(feat)
ways += sum([len(s) for s in p])
rels += 1 if len(p) + len(p[0]) > 2 else 0
self.assertEqual(ways, len(data.ways))
self.assertEqual(rels, len(data.relations))
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.cons.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_conflate(self):
self.layer.reproject()
d = osm.Osm()
d.Way(
(
(-16.44211325828, 28.23715394977),
(-16.44208978895, 28.23714124855),
(-16.44209884141, 28.23712884271),
(-16.44212197546, 28.23714361157),
(-16.44211325828, 28.23715394977),
),
dict(building="yes", ref="1"),
)
d.Way(
(
(-16.44016295806, 28.23657619128),
(-16.43985450402, 28.23641077902),
(-16.43991753593, 28.23632689127),
(-16.44020855561, 28.23648403305),
(-16.44016295806, 28.23657619128),
),
dict(building="yes", ref="2"),
)
d.Way(
(
(-16.44051231511, 28.23655551417),
(-16.44042112, 28.23650529975),
(-16.4405699826, 28.23631153095),
(-16.44065782495, 28.23635288407),
(-16.44051231511, 28.23655551417),
),
dict(building="yes", ref="3"),
)
self.assertEqual(len(d.ways), 3)
self.layer.conflate(d, delete=False)
self.assertEqual(len(d.ways), 3)
for el in d.ways:
self.assertEqual("conflict" in el.tags, el.tags["ref"] == "3")
d.Way(
(
(-16.44038491018, 28.23645095),
(-16.44029706784, 28.23640132629),
(-16.44042514332, 28.23624713819),
(-16.44049689241, 28.23629558045),
(-16.44038491018, 28.23645095),
),
dict(building="yes", ref="4"),
)
d.Way(
(
(-16.44019514591, 28.23634461522),
(-16.44002616674, 28.23625009376),
(-16.44011199743, 28.23611540052),
(-16.44027829438, 28.23619810692),
),
dict(building="yes", ref="5"),
)
d.Way(
(
(-16.43993497163, 28.23591926797),
(-16.43972575933, 28.23580584175),
(-16.4398062256, 28.23610122228),
(-16.43959701329, 28.23598543321),
(-16.43993497163, 28.23591926797),
),
dict(building="yes", ref="6"),
)
d.Way(
(
(-16.4386775, 28.2360472),
(-16.4386158, 28.2363235),
(-16.4384536, 28.2362954),
(-16.4385153, 28.2360191),
(-16.4386775, 28.2360472),
),
dict(building="yes", ref="7"),
)
d.Way(
(
(-16.4386049, 28.2357006),
(-16.4385316, 28.2356401),
(-16.4385093, 28.2356419),
(-16.4384993, 28.2357054),
(-16.4386049, 28.2357006),
),
dict(building="yes", ref="8"),
)
w0 = d.Way(
(
(-16.4409784, 28.2365733),
(-16.4409231, 28.236542),
(-16.4409179, 28.2365154),
(-16.4409268, 28.236504),
(-16.4408588, 28.236465),
)
)
w1 = d.Way(((-16.4406755, 28.236688), (-16.4408332, 28.2367735)))
w2 = d.Way(
(
(-16.4408332, 28.2367735),
(-16.4408943, 28.2366893),
(-16.4409395, 28.2367147),
(-16.4409818, 28.2366563),
(-16.4409366, 28.2366308),
(-16.4409784, 28.2365733),
)
)
w3 = d.Way(
(
(-16.4408588, 28.236465),
(-16.4408086, 28.2365319),
(-16.4407037, 28.2364709),
(-16.4406669, 28.2365102),
(-16.4406513, 28.2365338),
(-16.440639, 28.2365663),
(-16.4407394, 28.2366223),
(-16.4407188, 28.2366474),
(-16.440707, 28.2366405),
(-16.4406755, 28.236688),
)
)
w4 = d.Way(
(
(-16.440072, 28.236560),
(-16.439966, 28.236505),
(-16.439888, 28.236605),
(-16.4399860, 28.236666),
(-16.440072, 28.236560),
)
)
w5 = d.Way(
(
(-16.439965, 28.236703),
(-16.439861, 28.236642),
(-16.439805, 28.236733),
(-16.439903, 28.236790),
(-16.439965, 28.236703),
)
)
r1 = d.Relation(tags=dict(building="yes", ref="9"))
r1.append(w0, "outer")
r1.append(w1, "outer")
r1.append(w2, "outer")
r1.append(w3, "outer")
r2 = d.Relation(tags=dict(building="yes", ref="10"))
r2.append(w4, "outer")
r2.append(w5, "outer")
self.assertEqual(len(d.ways), 14)
self.assertEqual(len(d.relations), 2)
self.layer.conflate(d)
self.assertEqual(len(d.ways), 12)
self.assertEqual(len(d.relations), 2)
self.assertEqual(
{e.tags["ref"] for e in d.ways if "ref" in e.tags},
{"3", "4", "5", "6", "7", "8"},
)