コード例 #1
0
ファイル: polygon.py プロジェクト: OSM-es/CatAtom2Osm
    def get_adjacents_and_geometries(self, expression=""):
        """
        Auxiliary indexes for adjacency of geometries.

        Returns:
            (list) groups of adjacent polygons
            (dict) feature id: geometry
        """
        parents_per_vertex, geometries = self.get_parents_per_vertex_and_geometries(
            expression)
        adjs = []
        for (wkt, parents) in parents_per_vertex.items():
            point = Point(wkt)
            if len(parents) > 1:
                for fid in parents:
                    geom = geometries[fid]
                    (point, ndx, ndxa, ndxb, dist) = geom.closestVertex(point)
                    next = Point(geom.vertexAt(ndxb))
                    parents_next = parents_per_vertex[next.asWkt()]
                    common = set(x for x in parents if x in parents_next)
                    if len(common) > 1:
                        adjs.append(common)
        adjs = list(adjs)
        groups = merge_groups(adjs)
        return (groups, geometries)
コード例 #2
0
ファイル: test_zoning.py プロジェクト: OSM-es/CatAtom2Osm
 def test_is_inside_part(self):
     self.ulayer.append(self.fixture, level="M")
     feat = QgsFeature(self.ulayer.fields())
     zone = Geometry.fromPolygonXY([[
         Point(357270.987, 3123924.266),
         Point(357282.643, 3123936.187),
         Point(357283.703, 3123920.822),
         Point(357270.987, 3123924.266),
     ]])
     feat.setGeometry(zone)
     self.assertTrue(self.ulayer.is_inside(feat))
コード例 #3
0
ファイル: test_zoning.py プロジェクト: OSM-es/CatAtom2Osm
 def test_is_inside_false(self):
     self.ulayer.append(self.fixture, level="M")
     feat = QgsFeature(self.ulayer.fields())
     zone = Geometry.fromPolygonXY([[
         Point(357228.335, 3123901.881),
         Point(357231.779, 3123922.677),
         Point(357245.555, 3123897.377),
         Point(357228.335, 3123901.881),
     ]])
     feat.setGeometry(zone)
     self.assertFalse(self.ulayer.is_inside(feat))
コード例 #4
0
ファイル: cons.py プロジェクト: OSM-es/CatAtom2Osm
    def move_entrance(
        self,
        ad,
        ad_buildings,
        ad_parts,
        to_move,
        to_insert,
        parents_per_vx,
    ):
        """
        Auxiliary method to move entrance to the nearest building and part.

        Don't move and the entrance specification is changed if the new
        position is not enough close ('remote'), is a corner ('corner'),
        is in an inner ring ('inner') or is in a wall shared with another
        building ('shared').
        """
        point = ad.geometry().asPoint()
        distance = 9e9
        for bu in ad_buildings:
            bg = bu.geometry()
            d, c, v = bg.closestSegmentWithContext(point)[:3]
            if d < distance:
                (building, distance, closest, vertex) = (bu, d, c, v)
        bg = building.geometry()
        bid = building.id()
        va = Point(bg.vertexAt(vertex - 1))
        vb = Point(bg.vertexAt(vertex))
        if distance > config.addr_thr**2:
            ad["spec"] = "remote"
        elif vertex > len(Geometry.get_multipolygon(bg)[0][0]):
            ad["spec"] = "inner"
        elif (closest.sqrDist(va) < config.entrance_thr**2
              or closest.sqrDist(vb) < config.entrance_thr**2):
            ad["spec"] = "corner"
        elif PolygonLayer.is_shared_segment(parents_per_vx, va, vb, bid):
            ad["spec"] = "shared"
        else:
            dg = Geometry.fromPointXY(closest)
            to_move[ad.id()] = dg
            bg.insertVertex(closest.x(), closest.y(), vertex)
            to_insert[bid] = QgsGeometry(bg)
            building.setGeometry(bg)
            for part in ad_parts:
                pg = part.geometry()
                r = Geometry.get_multipolygon(pg)[0][0]
                for i in range(len(r) - 1):
                    vpa = Point(pg.vertexAt(i))
                    vpb = Point(pg.vertexAt(i + 1))
                    if va in (vpa, vpb) and vb in (vpa, vpb):
                        pg.insertVertex(closest.x(), closest.y(), i + 1)
                        to_insert[part.id()] = QgsGeometry(pg)
                        part.setGeometry(pg)
                        break
コード例 #5
0
ファイル: test_zoning.py プロジェクト: OSM-es/CatAtom2Osm
 def test_is_inside_full(self):
     self.ulayer.append(self.fixture, level="M")
     zone = Geometry.fromPolygonXY([[
         Point(357275.888, 3123959.765),
         Point(357276.418, 3123950.625),
         Point(357286.220, 3123957.911),
         Point(357275.888, 3123959.765),
     ]])
     feat = QgsFeature(self.ulayer.fields())
     feat.setGeometry(zone)
     self.assertTrue(self.ulayer.is_inside(feat))
コード例 #6
0
 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])
コード例 #7
0
 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])
コード例 #8
0
 def get_overpass_bbox(self, bbox):
     """Transform bbox to EPSG 4326 and returns str in overpass format."""
     if bbox.isEmpty():
         bbox = None
     else:
         p1 = Geometry.fromPointXY(Point(bbox.xMinimum(), bbox.yMinimum()))
         p2 = Geometry.fromPointXY(Point(bbox.xMaximum(), bbox.yMaximum()))
         target_crs = QgsCoordinateReferenceSystem.fromEpsgId(4326)
         crs_transform = self.get_crs_transform(self.crs(), target_crs)
         p1.transform(crs_transform)
         p2.transform(crs_transform)
         bbox = [
             p1.asPoint().y() - config.bbox_buffer,
             p1.asPoint().x() - config.bbox_buffer,
             p2.asPoint().y() + config.bbox_buffer,
             p2.asPoint().x() + config.bbox_buffer,
         ]
         bbox = "{:.8f},{:.8f},{:.8f},{:.8f}".format(*bbox)
     return bbox
コード例 #9
0
 def test_read_from_osm(self):
     layer = HighwayLayer()
     data = osm.Osm()
     data.Way(((10, 10), (15, 15)), {"name": "FooBar"})
     w2 = data.Way(((20, 20), (30, 30)))
     data.Relation([w2], {"name": "BarTaz"})
     layer.read_from_osm(data)
     self.assertEqual(layer.featureCount(), 2)
     names = [feat["name"] for feat in layer.getFeatures()]
     self.assertIn("BarTaz", names)
     self.assertIn("FooBar", names)
     for f in layer.getFeatures():
         if f["name"] == "FooBar":
             self.assertEqual(
                 f.geometry().asPolyline(), [Point(10, 10), Point(15, 15)]
             )
         if f["name"] == "BarTaz":
             self.assertEqual(
                 f.geometry().asPolyline(), [Point(20, 20), Point(30, 30)]
             )
コード例 #10
0
 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
         ]))
コード例 #11
0
ファイル: polygon.py プロジェクト: OSM-es/CatAtom2Osm
    def simplify(self):
        """
        Reduce the number of vertices in a polygon layer.

        * Delete vertex if the angle with its adjacents is near of the straight
          angle for less than 'straight_thr' degrees in all its parents.

        * Delete vertex if the distance to the segment formed by its parents is
          less than 'cath_thr' meters.
        """
        if log.app_level <= logging.DEBUG:
            debshp = DebugWriter("debug_simplify.shp", self)
        killed = 0
        to_change = {}
        # Clean non corners
        (parents_per_vertex,
         geometries) = self.get_parents_per_vertex_and_geometries()
        pbar = self.get_progressbar(_("Simplify"), len(parents_per_vertex))
        for wkt, parents in parents_per_vertex.items():
            point = Point(wkt)
            # Test if this vertex is a 'corner' in any of its parent polygons
            for fid in parents:
                geom = geometries[fid]
                (angle, is_acute, is_corner,
                 cath) = point.get_corner_context(geom)
                debmsg = "angle=%.1f, is_acute=%s, is_corner=%s, cath=%.4f" % (
                    angle,
                    is_acute,
                    is_corner,
                    cath,
                )
                if is_corner:
                    break
            msg = "Keep"
            if not is_corner:
                killed += 1  # delete the vertex from all its parents.
                for fid in frozenset(parents):
                    g = QgsGeometry(geometries[fid])
                    (__, ndx, __, __, __) = g.closestVertex(point)
                    (ndxa, ndxb) = g.adjacentVertices(ndx)
                    v = g.vertexAt(ndx)
                    va = g.vertexAt(ndxa)
                    vb = g.vertexAt(ndxb)
                    invalid_ring = v == va or v == vb or va == vb
                    g.deleteVertex(ndx)
                    msg = "Refused"
                    if Geometry.is_valid(g) and not invalid_ring:
                        parents.remove(fid)
                        geometries[fid] = g
                        to_change[fid] = g
                        msg = "Deleted"
            if log.app_level <= logging.DEBUG:
                debshp.add_point(point, msg + " " + debmsg)
            if len(to_change) > BUFFER_SIZE:
                self.writer.changeGeometryValues(to_change)
                to_change = {}
            pbar.update()
        pbar.close()
        if len(to_change) > 0:
            self.writer.changeGeometryValues(to_change)
        if killed > 0:
            log.debug(_("Simplified %d vertices in the '%s' layer"), killed,
                      self.name())
            report.values["vertex_simplify_" + self.name()] = killed
コード例 #12
0
ファイル: polygon.py プロジェクト: OSM-es/CatAtom2Osm
    def delete_invalid_geometries(self, query_small_area=lambda feat: True):
        """
        Delete invalid geometries.

        Test if any of it acute angle vertex could be deleted.
        Also removes zig-zag and spike vertex (see Point.get_spike_context).
        """
        if log.app_level <= logging.DEBUG:
            debshp = DebugWriter("debug_notvalid.shp", self, QgsFields(),
                                 WKBPolygon)
            debshp2 = DebugWriter("debug_spikes.shp", self)
        to_change = {}
        to_clean = []
        to_move = {}
        parts = 0
        rings = 0
        zz = 0
        spikes = 0
        geometries = {}
        msg = _("Delete invalid geometries")
        pbar = self.get_progressbar(msg, len(geometries))
        for feat in self.getFeatures():
            fid = feat.id()
            geom = feat.geometry()
            badgeom = False
            pn = 0
            for polygon in Geometry.get_multipolygon(geom):
                f = QgsFeature(QgsFields())
                g = Geometry.fromPolygonXY(polygon)
                if g.area() < config.min_area and query_small_area(feat):
                    parts += 1
                    geom.deletePart(pn)
                    to_change[fid] = geom
                    f.setGeometry(QgsGeometry(g))
                    if log.app_level <= logging.DEBUG:
                        debshp.addFeature(f)
                    continue
                pn += 1
                for i, ring in enumerate(polygon):
                    if badgeom:
                        break
                    skip = False
                    for n, v in enumerate(ring[0:-1]):
                        (
                            angle_v,
                            angle_a,
                            ndx,
                            ndxa,
                            is_acute,
                            is_zigzag,
                            is_spike,
                            vx,
                        ) = Point(v).get_spike_context(geom)
                        if skip or not is_acute:
                            skip = False
                            continue
                        g = Geometry.fromPolygonXY([ring])
                        f.setGeometry(QgsGeometry(g))
                        g.deleteVertex(n)
                        if not g.isGeosValid() or g.area() < config.min_area:
                            if i > 0:
                                rings += 1
                                geom.deleteRing(i)
                                to_change[fid] = geom
                                if log.app_level <= logging.DEBUG:
                                    debshp.addFeature(f)
                            else:
                                badgeom = True
                                to_clean.append(fid)
                                if log.app_level <= logging.DEBUG:
                                    debshp.addFeature(f)
                            break
                        if len(ring) > 4:  # (can delete vertexs)
                            va = Point(geom.vertexAt(ndxa))
                            if is_zigzag:
                                g = QgsGeometry(geom)
                                if ndxa > ndx:
                                    g.deleteVertex(ndxa)
                                    g.deleteVertex(ndx)
                                    skip = True
                                else:
                                    g.deleteVertex(ndx)
                                    g.deleteVertex(ndxa)
                                valid = g.isGeosValid()
                                if valid:
                                    geom = g
                                    zz += 1
                                    to_change[fid] = g
                                if log.app_level <= logging.DEBUG:
                                    debshp2.add_point(
                                        va,
                                        "zza %d %d %d %f" %
                                        (fid, ndx, ndxa, angle_a),
                                    )
                                    debshp2.add_point(
                                        v,
                                        "zz %d %d %d %s" %
                                        (fid, ndx, len(ring), valid),
                                    )
                            elif is_spike:
                                g = QgsGeometry(geom)
                                to_move[va] = vx
                                g.moveVertex(vx.x(), vx.y(), ndxa)
                                g.deleteVertex(ndx)
                                valid = g.isGeosValid()
                                if valid:
                                    spikes += 1
                                    skip = ndxa > ndx
                                    geom = g
                                    to_change[fid] = g
                                if log.app_level <= logging.DEBUG:
                                    debshp2.add_point(vx,
                                                      "vx %d %d" % (fid, ndx))
                                    debshp2.add_point(
                                        va, "va %d %d %d %f" %
                                        (fid, ndx, ndxa, angle_a))
                                    debshp2.add_point(
                                        v,
                                        "v %d %d %d %s" %
                                        (fid, ndx, len(ring), valid),
                                    )
                geometries[fid] = geom
            if geom.area() < config.min_area and query_small_area(feat):
                to_clean.append(fid)
                if fid in to_change:
                    del to_change[fid]
            pbar.update()
        pbar.close()
        if to_move:
            for fid, geom in geometries.items():
                if fid in to_clean:
                    continue
                n = 0
                v = Point(geom.vertexAt(n))
                while v.x() != 0 or v.y() != 0:
                    if v in to_move:
                        g = QgsGeometry(geom)
                        vx = to_move[v]
                        if log.app_level <= logging.DEBUG:
                            debshp2.add_point(v, "mv %d %d" % (fid, n))
                            debshp2.add_point(vx, "mvx %d %d" % (fid, n))
                        g.moveVertex(vx.x(), vx.y(), n)
                        if g.isGeosValid():
                            geom = g
                            to_change[fid] = g
                    n += 1
                    v = Point(geom.vertexAt(n))
        if to_change:
            self.writer.changeGeometryValues(to_change)
        if parts:
            msg = _("Deleted %d invalid part geometries in the '%s' layer")
            log.debug(msg, parts, self.name())
            report.values["geom_parts_" + self.name()] = parts
        if rings:
            msg = _("Deleted %d invalid ring geometries in the '%s' layer")
            log.debug(msg, rings, self.name())
            report.values["geom_rings_" + self.name()] = rings
        if to_clean:
            self.writer.deleteFeatures(to_clean)
            msg = _("Deleted %d invalid geometries in the '%s' layer")
            log.debug(msg, len(to_clean), self.name())
            report.values["geom_invalid_" + self.name()] = len(to_clean)
        if zz:
            msg = _("Deleted %d zig-zag vertices in the '%s' layer")
            log.debug(msg, zz, self.name())
            report.values["vertex_zz_" + self.name()] = zz
        if spikes:
            msg = _("Deleted %d spike vertices in the '%s' layer")
            log.debug(msg, spikes, self.name())
            report.values["vertex_spike_" + self.name()] = spikes
コード例 #13
0
ファイル: polygon.py プロジェクト: OSM-es/CatAtom2Osm
 def topology(self):
     """Add to nearest segments each vertex in a polygon layer."""
     threshold = self.dist_thr  # Distance threshold to create nodes
     dup_thr = self.dup_thr
     straight_thr = self.straight_thr
     tp = 0
     td = 0
     if log.app_level <= logging.DEBUG:
         debshp = DebugWriter("debug_topology.shp", self)
     geometries = {
         f.id(): QgsGeometry(f.geometry())
         for f in self.getFeatures()
     }
     index = self.get_index()
     to_change = {}
     nodes = set()
     pbar = self.get_progressbar(_("Topology"), len(geometries))
     for (gid, geom) in geometries.items():
         if geom.area() < config.min_area:
             continue
         for point in frozenset(Geometry.get_outer_vertices(geom)):
             if point not in nodes:
                 area_of_candidates = Point(point).boundingBox(threshold)
                 fids = index.intersects(area_of_candidates)
                 for fid in fids:
                     g = QgsGeometry(geometries[fid])
                     (p, ndx, ndxa, ndxb, dist_v) = g.closestVertex(point)
                     (dist_s, closest,
                      vertex) = g.closestSegmentWithContext(point)[:3]
                     va = Point(g.vertexAt(ndxa))
                     vb = Point(g.vertexAt(ndxb))
                     note = ""
                     if dist_v == 0:
                         dist_a = va.sqrDist(point)
                         dist_b = vb.sqrDist(point)
                         if dist_a < dup_thr**2:
                             g.deleteVertex(ndxa)
                             note = "dupe refused by isGeosValid"
                             if Geometry.is_valid(g):
                                 note = "Merge dup. %.10f %.5f,%.5f->%.5f,%.5f" % (
                                     dist_a,
                                     va.x(),
                                     va.y(),
                                     point.x(),
                                     point.y(),
                                 )
                                 nodes.add(p)
                                 nodes.add(va)
                                 td += 1
                         if dist_b < dup_thr**2:
                             g.deleteVertex(ndxb)
                             note = "dupe refused by isGeosValid"
                             if Geometry.is_valid(g):
                                 note = "Merge dup. %.10f %.5f,%.5f->%.5f,%.5f" % (
                                     dist_b,
                                     vb.x(),
                                     vb.y(),
                                     point.x(),
                                     point.y(),
                                 )
                                 nodes.add(p)
                                 nodes.add(vb)
                                 td += 1
                     elif dist_v < dup_thr**2:
                         g.moveVertex(point.x(), point.y(), ndx)
                         note = "dupe refused by isGeosValid"
                         if Geometry.is_valid(g):
                             note = "Merge dup. %.10f %.5f,%.5f->%.5f,%.5f" % (
                                 dist_v,
                                 p.x(),
                                 p.y(),
                                 point.x(),
                                 point.y(),
                             )
                             nodes.add(p)
                             td += 1
                     elif (dist_s < threshold**2 and closest != va
                           and closest != vb):
                         va = Point(g.vertexAt(vertex))
                         vb = Point(g.vertexAt(vertex - 1))
                         angle = abs(point.azimuth(va) - point.azimuth(vb))
                         note = "Topo refused by angle: %.2f" % angle
                         if abs(180 - angle) <= straight_thr:
                             note = "Topo refused by insertVertex"
                             if g.insertVertex(point.x(), point.y(),
                                               vertex):
                                 note = "Topo refused by isGeosValid"
                                 if Geometry.is_valid(g):
                                     note = "Add topo %.6f %.5f,%.5f" % (
                                         dist_s,
                                         point.x(),
                                         point.y(),
                                     )
                                     tp += 1
                     if note.startswith("Merge") or note.startswith("Add"):
                         to_change[fid] = g
                         geometries[fid] = g
                     if note and log.app_level <= logging.DEBUG:
                         debshp.add_point(point, note)
         if len(to_change) > BUFFER_SIZE:
             self.writer.changeGeometryValues(to_change)
             to_change = {}
         pbar.update()
     pbar.close()
     if len(to_change) > 0:
         self.writer.changeGeometryValues(to_change)
     if td:
         log.debug(_("Merged %d close vertices in the '%s' layer"), td,
                   self.name())
         report.values["vertex_close_" + self.name()] = td
     if tp:
         log.debug(_("Created %d topological points in the '%s' layer"), tp,
                   self.name())
         report.values["vertex_topo_" + self.name()] = tp
コード例 #14
0
ファイル: test_debug.py プロジェクト: OSM-es/CatAtom2Osm
 def test_add_point(self):
     layer = HighwayLayer()
     db = DebugWriter("test", layer, "memory")
     db.add_point(Point(0, 0), "foobar")
     db.add_point(Point(0, 0))
コード例 #15
0
 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]])
コード例 #16
0
 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)