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