import logging
import unittest
import mock
from qgis.core import QgsFeature, QgsFeatureRequest, QgsVectorLayer
from catatom2osm.app import QgsSingleton
from catatom2osm.geo.geometry import Geometry
from catatom2osm.geo.layer.polygon import PolygonLayer
from catatom2osm.geo.point import Point
qgs = QgsSingleton()
m_log = mock.MagicMock()
m_log.app_level = logging.INFO
[docs]class TestPolygonLayer(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(), f"Loading {fn}")
fn = "test_layer.shp"
PolygonLayer.create_shp(fn, self.fixture.crs())
self.layer = PolygonLayer(fn, "building", "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
PolygonLayer.delete_shp("test_layer.shp")
[docs] @mock.patch("catatom2osm.geo.layer.polygon.log", m_log)
def test_get_area(self):
area = self.layer.get_area()
self.assertEqual(round(area, 1), 1140234.8)
[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):
multiparts = [
f for f in self.layer.getFeatures() if len(Geometry.get_multipolygon(f)) > 1
]
self.assertGreater(len(multiparts), 0, "There are multipart features")
features_before = self.layer.featureCount()
request = QgsFeatureRequest()
request.setFilterFid(multiparts[0].id())
nparts = len(Geometry.get_multipolygon(multiparts[0]))
self.layer.explode_multi_parts(request)
self.assertEqual(features_before + nparts - 1, self.layer.featureCount())
nparts = sum([len(Geometry.get_multipolygon(f)) for f in multiparts])
self.assertGreater(nparts, len(multiparts), "With more than one part")
self.assertTrue(nparts > 1, "Find a multipart feature")
self.layer.explode_multi_parts()
m = "After exploding there must be more features than before"
self.assertGreater(self.layer.featureCount(), features_before, m)
m = (
"Number of features before plus number of parts minus multiparts "
"equals actual number of features"
)
self.assertEqual(
features_before + nparts - len(multiparts), self.layer.featureCount(), m
)
m = "Parts must be single polygons"
self.assertTrue(
all(
[
len(Geometry.get_multipolygon(f)) == 1
for f in self.layer.getFeatures()
]
),
m,
)
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
def test_get_parents_per_vertex_and_geometries(self):
(
parents_per_vertex,
geometries,
) = self.layer.get_parents_per_vertex_and_geometries()
self.assertEqual(len(geometries), self.layer.featureCount())
self.assertTrue(
all(
[
Geometry.get_multipolygon(geometries[f.id()])
== Geometry.get_multipolygon(f)
for f in self.layer.getFeatures()
]
)
)
self.assertGreater(len(parents_per_vertex), 0)
self.assertTrue(
all(
[
Geometry.fromPointXY(Point(vertex)).intersects(geometries[fid])
for (vertex, fids) in list(parents_per_vertex.items())
for fid in fids
]
)
)
[docs] @mock.patch("catatom2osm.geo.layer.base.log", m_log)
@mock.patch("catatom2osm.geo.layer.base.progressbar", mock.MagicMock())
def test_difference(self):
layer1 = PolygonLayer("Polygon", "test1", "memory")
layer2 = PolygonLayer("Polygon", "test2", "memory")
g1 = Geometry.fromPolygonXY(
[
[
Point(10, 10),
Point(20, 10),
Point(20, 20),
Point(10, 20),
Point(10, 10),
]
]
)
g2 = Geometry.fromPolygonXY(
[
[
Point(30, 10),
Point(40, 10),
Point(40, 20),
Point(30, 20),
Point(30, 10),
]
]
)
h1 = Geometry.fromPolygonXY(
[
[
Point(14, 14),
Point(16, 14),
Point(16, 16),
Point(14, 16),
Point(14, 14),
]
]
)
h2 = Geometry.fromPolygonXY(
[
[
Point(20, 10),
Point(30, 10),
Point(30, 20),
Point(20, 20),
Point(20, 10),
]
]
)
h3 = Geometry.fromPolygonXY(
[
[
Point(38, 10),
Point(42, 10),
Point(42, 20),
Point(38, 20),
Point(38, 10),
]
]
)
h4 = Geometry.fromPolygonXY(
[
[
Point(30, 30),
Point(40, 30),
Point(40, 40),
Point(40, 30),
Point(30, 30),
]
]
)
r1 = g1.difference(h1)
r2 = g2.difference(h3)
layer1.writer.addFeatures([QgsFeature() for i in range(2)])
layer1.writer.changeGeometryValues({1: g1, 2: g2})
layer2.writer.addFeatures([QgsFeature() for i in range(4)])
layer2.writer.changeGeometryValues({1: h1, 2: h2, 3: h3, 4: h4})
layer1.difference(layer2)
self.assertEqual(layer1.featureCount(), 2)
request = QgsFeatureRequest().setFilterFid(1)
f1 = next(layer1.getFeatures(request))
request = QgsFeatureRequest().setFilterFid(2)
f2 = next(layer1.getFeatures(request))
self.assertEqual(f1.geometry().difference(r1).area(), 0)
self.assertEqual(f2.geometry().difference(r2).area(), 0)