示例#1
0
 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"])
示例#2
0
 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())
示例#3
0
 def setUp(self):
     fn = "test/fixtures/parcel.gpkg|layername=parcel"
     self.parcel = ParcelLayer("38012")
     fixture = QgsVectorLayer(fn, "parcel", "ogr")
     self.assertTrue(fixture.isValid(), "Loading fixture")
     self.parcel.append(fixture)
     self.assertEqual(self.parcel.featureCount(), 186)
     fn = "test/fixtures/cons.gpkg|layername=cons"
     fixture2 = QgsVectorLayer(fn, "cons", "ogr")
     self.building = ConsLayer("MultiPolygon", "cons", "memory")
     self.building.append(fixture2)
     self.assertTrue(self.building.isValid(), "Loading fixture")
示例#4
0
 def create_missing_parcels(self, *sources, split=None):
     """Create fake parcels for buildings not contained in any."""
     pa_refs = [f["localId"] for f in self.getFeatures()]
     to_add = {}
     for source in sources:
         if source is None:
             continue
         for feat in source.getFeatures():
             ref = ConsLayer.get_id(feat)
             if ref not in pa_refs:
                 mp = Geometry.get_outer_rings(feat)
                 geom = Geometry.fromMultiPolygonXY(mp)
                 if ref in to_add:
                     parcel = to_add[ref]
                     geom = parcel.geometry().combine(geom)
                     parcel.setGeometry(geom)
                     to_add[ref] = parcel
                 elif split is None or split.is_inside_area(geom):
                     parcel = QgsFeature(self.fields())
                     parcel["localId"] = ref
                     parcel.setGeometry(geom)
                     to_add[ref] = parcel
     if to_add:
         self.writer.addFeatures(to_add.values())
         log.debug(_("Added %d missing parcels"), len(to_add))
示例#5
0
 def get_groups_by_adjacent_buildings(self, buildings):
     """Get groups of parcel ids with buildings sharing walls in another parcel."""
     exp = "NOT(localId ~ 'part')"
     bu_groups, __ = buildings.get_contacts_and_geometries(exp)
     bu_refs = {f.id(): ConsLayer.get_id(f) for f in buildings.search(exp)}
     geometries = {}
     pa_ids = {}
     pa_refs = {}
     pa_zone = {}
     for f in self.getFeatures():
         geometries[f.id()] = QgsGeometry(f.geometry())
         pa_ids[f["localId"]] = f.id()
         pa_refs[f.id()] = f["localId"]
         pa_zone[f.id()] = self.get_zone(f)
     adjs = defaultdict(list)
     for group in bu_groups:
         pids = set()
         for bid in group:
             ref = bu_refs[bid]
             pids.add(pa_ids[ref])
         k = "-".join(set([pa_zone[fid] for fid in pids]))
         adjs[k].append(pids)
     mz_groups = {k for k in adjs.keys() if "-" in k}
     mz_groups |= {z for k in mz_groups for z in k.split("-")}
     pa_groups = merge_groups([adj for z in mz_groups for adj in adjs[z]])
     for z, adj in adjs.items():
         if z not in mz_groups:
             if len(adj) == 1:
                 pa_groups.append(adj[0])
             else:
                 for group in merge_groups(adj):
                     pa_groups.append(group)
     return pa_groups, pa_refs, geometries
示例#6
0
 def delete_void_parcels(self, *sources):
     """Remove parcels without buildings (or pools)/addresses."""
     refs = []
     for source in sources:
         if source is not None:
             for f in source.getFeatures():
                 refs.append(ConsLayer.get_id(f))
     to_clean = [
         f.id() for f in self.getFeatures() if f["localId"] not in refs
     ]
     if to_clean:
         self.writer.deleteFeatures(to_clean)
         log.debug(_("Removed %d void parcels"), len(to_clean))
示例#7
0
 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)
示例#8
0
 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"])
示例#9
0
 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"])
示例#10
0
 def tearDown(self):
     del self.layer
     ConsLayer.delete_shp("test_layer.shp")
示例#11
0
class TestConsLayer(unittest.TestCase):
    @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())

    def tearDown(self):
        del self.layer
        ConsLayer.delete_shp("test_layer.shp")

    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))

    @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))

    @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"])

    @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"])

    @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"])

    @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)

    @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")

    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"])

    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
            ]))

    @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)

    @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)

    @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)

    @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)

    @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])

    @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]])

    @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])

    @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()

    @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)

    @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"], "")

    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))

    @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"},
        )
示例#12
0
 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()
示例#13
0
 def test_is_pool(self):
     self.assertTrue(ConsLayer.is_pool({"localId": "foo_PI.1"}))
     self.assertFalse(ConsLayer.is_pool({"localId": "foo_part1"}))
示例#14
0
 def test_is_building(self):
     self.assertTrue(ConsLayer.is_building({"localId": "foobar"}))
     self.assertFalse(ConsLayer.is_building({"localId": "foo_bar"}))
示例#15
0
class TestParcelLayer(unittest.TestCase):
    @mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
    @mock.patch("catatom2osm.geo.layer.base.log", m_log)
    def setUp(self):
        fn = "test/fixtures/parcel.gpkg|layername=parcel"
        self.parcel = ParcelLayer("38012")
        fixture = QgsVectorLayer(fn, "parcel", "ogr")
        self.assertTrue(fixture.isValid(), "Loading fixture")
        self.parcel.append(fixture)
        self.assertEqual(self.parcel.featureCount(), 186)
        fn = "test/fixtures/cons.gpkg|layername=cons"
        fixture2 = QgsVectorLayer(fn, "cons", "ogr")
        self.building = ConsLayer("MultiPolygon", "cons", "memory")
        self.building.append(fixture2)
        self.assertTrue(self.building.isValid(), "Loading fixture")

    def test_init(self):
        layer = ParcelLayer("38012")
        self.assertEqual(layer.fields()[0].name(), "localId")
        self.assertEqual(layer.fields()[1].name(), "parts")
        self.assertEqual(layer.rename["localId"], "inspireId_localId")

    def test_not_empty(self):
        layer = ParcelLayer("38012")
        self.assertGreater(len(layer.fields().toList()), 0)

    def test_delete_void_parcels(self):
        self.parcel.delete_void_parcels(self.building)
        self.assertEqual(self.parcel.featureCount(), 110)

    def test_create_missing_parcels(self):
        self.parcel.create_missing_parcels(self.building)
        self.assertEqual(self.parcel.featureCount(), 188)
        p = next(self.parcel.search("localId = '8642317CS5284S'"))
        self.assertEqual(len(Geometry.get_multipolygon(p)[0]), 1)

    def test_get_groups_by_adjacent_buildings(self):
        self.parcel.create_missing_parcels(self.building)
        pa_groups, pa_refs, __ = self.parcel.get_groups_by_adjacent_buildings(
            self.building)
        self.assertEqual(len(pa_groups), 21)
        self.assertEqual(sum([len(gr) for gr in pa_groups]), 85)

    @mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
    @mock.patch("catatom2osm.geo.layer.base.log", m_log)
    @mock.patch("catatom2osm.geo.layer.polygon.log", m_log)
    def test_merge_by_adjacent_buildings(self):
        self.building.remove_outside_parts()
        self.building.explode_multi_parts()
        self.building.clean()
        self.parcel.delete_void_parcels(self.building)
        self.parcel.create_missing_parcels(self.building)
        self.parcel.count_parts(self.building)
        pca = sum([f["parts"] for f in self.parcel.getFeatures()])
        la = self.parcel.featureCount()
        tasks = self.parcel.merge_by_adjacent_buildings(self.building)
        pcd = sum([f["parts"] for f in self.parcel.getFeatures()])
        ld = self.parcel.featureCount()
        cl = len([k for k, v in tasks.items() if k != v])
        self.assertEqual(ld, la - cl)
        self.assertEqual(pca, pcd)
        pa_refs = [f["localId"] for f in self.parcel.getFeatures()]
        expected = [
            "001000300CS52D",
            "001000400CS52D",
            "8641608CS5284S",
            "8641612CS5284S",
            "8641613CS5284S",
            "8641616CS5284S",
            "8641620CS5284S",
            "8641621CS5284S",
            "8641632CS5284S",
            "8641636CS5284S",
            "8641638CS5284S",
            "8641649CS5284S",
            "8641653CS5284S",
            "8641658CS5284S",
            "8641660CS5284S",
            "8642302CS5284S",
            "8642310CS5284S",
            "8642312CS5284S",
            "8642313CS5284S",
            "8642314CS5284S",
            "8642317CS5284S",
            "8642321CS5284S",
            "8642325CS5484N",
            "8642701CS5284S",
            "8742701CS5284S",
            "8742707CS5284S",
            "8742711CS5284S",
            "8742721CS5284S",
            "8839301CS5283N",
            "8840501CS5284S",
            "8841602CS5284S",
            "8841603CS5284S",
            "8844121CS5284S",
            "8940301CS5284S",
            "8940302CS5284S",
            "8940305CS5284S",
            "8940306CS5284S",
            "8940307CS5284S",
            "8940309CS5284S",
            "8941505CS5284S",
            "9041703CS5294S",
            "9041704CS5294S",
            "9041705CS5294S",
            "9041716CS5294S",
            "9041719CS5294S",
            "9042401CS5294S",
            "9042402CS5294S",
            "9042404CS5294S",
        ]
        self.assertEqual(pa_refs, expected)
        f = next(self.parcel.search("localId = '8840501CS5284S'"))
        self.assertEqual(f["parts"], 11)
        merged = []
        for bu in self.building.getFeatures():
            if self.building.is_building(bu):
                ref = self.building.get_id(bu)
                if ref not in pa_refs:
                    merged.append(ref)
        self.assertEqual(len(merged), 71)
        self.assertTrue(all([tasks[ref] != ref for ref in merged]))

    @mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
    @mock.patch("catatom2osm.geo.layer.base.log", m_log)
    @mock.patch("catatom2osm.geo.layer.polygon.log", m_log)
    def test_count_parts(self):
        self.building.remove_outside_parts()
        self.building.explode_multi_parts()
        self.building.clean()
        self.parcel.delete_void_parcels(self.building)
        self.parcel.create_missing_parcels(self.building)
        parts_count = self.parcel.count_parts(self.building)
        self.assertEqual(sum(parts_count.values()), 324)
        self.assertEqual(len(parts_count), self.parcel.featureCount())
        f = next(self.parcel.search("localId = '8840501CS5284S'"))
        self.assertEqual(f["parts"], 7)
        self.assertEqual(parts_count["8840501CS5284S"], 7)
        f = next(self.parcel.search("localId = '8840502CS5284S'"))
        self.assertEqual(f["parts"], 4)
        self.assertEqual(parts_count["8840502CS5284S"], 4)

    @mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
    @mock.patch("catatom2osm.geo.layer.base.log", m_log)
    @mock.patch("catatom2osm.geo.layer.polygon.log", m_log)
    def test_get_groups_by_parts_count(self):
        self.building.remove_outside_parts()
        self.building.explode_multi_parts()
        self.building.clean()
        self.parcel.delete_void_parcels(self.building)
        self.parcel.create_missing_parcels(self.building)
        self.parcel.count_parts(self.building)
        self.parcel.merge_by_adjacent_buildings(self.building)
        features = {pa.id(): pa for pa in self.parcel.getFeatures()}
        (
            pa_groups,
            pa_refs,
            geometries,
            parts_count,
        ) = self.parcel.get_groups_by_parts_count(10, 100)
        self.assertEqual(len(parts_count), 48)
        self.assertEqual(len(pa_groups), 18)
        self.assertTrue(
            all([
                sum([parts_count[pa_refs[fid]] for fid in group]) <= 10
                for group in pa_groups
            ]))
        label_count = set([
            len(set([self.parcel.get_zone(features[fid]) for fid in group]))
            for group in pa_groups
        ])
        self.assertEqual(label_count, {1})

    @mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
    @mock.patch("catatom2osm.geo.layer.base.log", m_log)
    @mock.patch("catatom2osm.geo.layer.polygon.log", m_log)
    def test_merge_by_parts_count(self):
        self.building.remove_outside_parts()
        self.building.explode_multi_parts()
        self.building.clean()
        self.parcel.delete_void_parcels(self.building)
        self.parcel.create_missing_parcels(self.building)
        self.parcel.merge_by_adjacent_buildings(self.building)
        pca = sum([f["parts"] for f in self.parcel.getFeatures()])
        la = self.parcel.featureCount()
        tasks = self.parcel.merge_by_parts_count(20, 30)
        pcd = sum([f["parts"] for f in self.parcel.getFeatures()])
        ld = self.parcel.featureCount()
        cl = len([k for k, v in tasks.items() if k != v])
        self.assertEqual(ld, la - cl)
        self.assertEqual(pca, pcd)