Exemple #1
0
    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