def densify(geometry, maxsegmentlength): """Densifies geometry vertices, so no segment is longer than maxsegmentlength Only implemented for linestring at the time being""" g = togeometry(geometry) type = QGis.flatType((g.wkbType())) if not type == QGis.WKBLineString: raise NotImplementedError("Densify is only implemented for LineStrings at the moment") input_coords = tocoordinates(g) output_coords = [] maxsegmentlength = float(maxsegmentlength) for ix in xrange(len(input_coords) - 1): p0 = input_coords[ix] p1 = input_coords[ix + 1] output_coords.append(QgsPoint(p0)) # Avoid calculating these values at the cost of performace. in_segment = QgsGeometry.fromPolyline([p0, p1]) in_segment_length = in_segment.length() segcount = int(ceil(in_segment_length / maxsegmentlength)) if segcount > 1: new_seg_length = float(in_segment_length) / segcount for i in xrange(1,segcount): new_p = in_segment.interpolate(new_seg_length * i).asPoint() output_coords.append(new_p) # Add last coord output_coords.append(input_coords[-1]) return QgsGeometry.fromPolyline(output_coords)
def line_locate_point(geometry, point): coords = tocoordinates(geometry) assert QGis.flatType( (geometry.wkbType())) == QGis.WKBLineString, 'Expected a LineString' assert len(point) == 2, 'Expected a point' sqrddist, closestsegmentpoint, indexofclosestvertexafter = geometry.closestSegmentWithContext( point) sum_length = 0 # Length of segments before the segment, where the point is located for ix in range(1, indexofclosestvertexafter): p0 = coords[ix - 1] p1 = coords[ix] segment = QgsGeometry.fromPolyline([p0, p1]) sum_length += segment.length() # Part of segment where the points is located p0 = coords[indexofclosestvertexafter - 1] segment = QgsGeometry.fromPolyline([p0, closestsegmentpoint]) sum_length += segment.length() return sum_length
def densify(geometry, maxsegmentlength): """Densifies geometry vertices, so no segment is longer than maxsegmentlength Only implemented for linestring at the time being""" g = togeometry(geometry) type = QGis.flatType((g.wkbType())) if not type == QGis.WKBLineString: raise NotImplementedError( "Densify is only implemented for LineStrings at the moment") input_coords = tocoordinates(g) output_coords = [] maxsegmentlength = float(maxsegmentlength) for ix in xrange(len(input_coords) - 1): p0 = input_coords[ix] p1 = input_coords[ix + 1] output_coords.append(QgsPoint(p0)) # Avoid calculating these values at the cost of performace. in_segment = QgsGeometry.fromPolyline([p0, p1]) in_segment_length = in_segment.length() segcount = int(ceil(in_segment_length / maxsegmentlength)) if segcount > 1: new_seg_length = float(in_segment_length) / segcount for i in xrange(1, segcount): new_p = in_segment.interpolate(new_seg_length * i).asPoint() output_coords.append(new_p) # Add last coord output_coords.append(input_coords[-1]) return QgsGeometry.fromPolyline(output_coords)
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue( self.INPUT)) tolerance = self.getParameterValue(self.TOLERANCE) pointsBefore = 0 pointsAfter = 0 writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.pendingFields().toList(), QGis.flatType(layer.wkbType()), layer.crs()) features = vector.features(layer) total = 100.0 / len(features) if len(features) > 0 else 1 for current, f in enumerate(features): featGeometry = f.geometry() if featGeometry is not None: attrs = f.attributes() pointsBefore += self.geomVertexCount(featGeometry) newGeometry = featGeometry.simplify(tolerance) pointsAfter += self.geomVertexCount(newGeometry) feature = QgsFeature() feature.setGeometry(newGeometry) feature.setAttributes(attrs) writer.addFeature(feature) progress.setPercentage(int(current * total)) del writer ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Simplify: Input geometries have been simplified from %s to %s points' % (pointsBefore, pointsAfter)))
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) tolerance = self.getParameterValue(self.TOLERANCE) pointsBefore = 0 pointsAfter = 0 writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.pendingFields().toList(), QGis.flatType(layer.wkbType()), layer.crs()) features = vector.features(layer) total = 100.0 / len(features) if len(features) > 0 else 1 for current, f in enumerate(features): featGeometry = f.geometry() if featGeometry is not None: attrs = f.attributes() pointsBefore += self.geomVertexCount(featGeometry) newGeometry = featGeometry.simplify(tolerance) pointsAfter += self.geomVertexCount(newGeometry) feature = QgsFeature() feature.setGeometry(newGeometry) feature.setAttributes(attrs) writer.addFeature(feature) progress.setPercentage(int(current * total)) del writer ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Simplify: Input geometries have been simplified from %s to %s points' % (pointsBefore, pointsAfter)))
def report(self, rulename, typeinfo, message, geometry, level): if geometry: try: geometry = togeometry(geometry) except TypeError: geometry = None fields = [ ('rulename', unicode(rulename).encode('utf-8')), ('objecttype', unicode(typeinfo).encode('utf-8')), ('message', unicode(message).encode('utf-8')), ('level', unicode(level).encode('utf-8')) ] # QGis.flatType if we don't care about 25D and whatnot if geometry is None: print 'XXXXX text output xxxxx', message self.db.add_feature_to_layer( self.text_table, fields, None ) elif QGis.flatType(geometry.wkbType()) == QGis.WKBLineString: if geometry.length() < 0.001: # Lines with length 0 tends to crash spatialite. Report as point instead self.report(rulename, typeinfo, message, geometry.centroid(), level) else: self.db.add_feature_to_layer( self.linestring_table, fields, geometry ) elif QGis.flatType((geometry.wkbType())) == QGis.WKBPoint: self.db.add_feature_to_layer( self.point_table, fields, geometry ) elif QGis.flatType((geometry.wkbType())) == QGis.WKBPolygon: self.db.add_feature_to_layer( self.polygon_table, fields, geometry )
def tocoordinates(feature): g = togeometry(feature) type = QGis.flatType((g.wkbType())) if type == QGis.WKBPoint: return g.asPoint() if type == QGis.WKBLineString: return g.asPolyline() if type == QGis.WKBPolygon: return g.asPolygon() raise TypeError("Unknown geometry type: " + str(type))
def tocoordinates(feature): g = togeometry(feature) type = QGis.flatType((g.wkbType())) if type == QGis.WKBPoint: return g.asPoint() if type == QGis.WKBLineString: return g.asPolyline() if type == QGis.WKBPolygon: return g.asPolygon() raise TypeError("Unknown geometry type: " + str(type))
def toflatcoordinates(feature): """Returns a flat list of all coordinates in the geometry""" g = togeometry(feature) type = QGis.flatType((g.wkbType())) if type == QGis.WKBPoint: return [g.asPoint()] if type == QGis.WKBLineString: return g.asPolyline() if type == QGis.WKBPolygon: return [coord for ring in g.asPolygon() for coord in ring] raise TypeError("Unknown geometry type: " + str(type))
def toflatcoordinates(feature): """Returns a flat list of all coordinates in the geometry""" g = togeometry(feature) type = QGis.flatType((g.wkbType())) if type == QGis.WKBPoint: return [g.asPoint()] if type == QGis.WKBLineString: return g.asPolyline() if type == QGis.WKBPolygon: return [coord for ring in g.asPolygon() for coord in ring] raise TypeError("Unknown geometry type: " + str(type))
def get_layer_geometry(layer): """Get layer geometry for vector layers. From layer object extract which geometry type it has. Is it point, line or polygon. """ if layer.type() == QgsMapLayer.RasterLayer: return ['raster', 999] if ISQGIS3: wkb_type = QgsWkbTypes.flatType(layer.wkbType()) point_type = QgsWkbTypes.Point line_string_type = QgsWkbTypes.LineString polygon_type = QgsWkbTypes.Polygon multi_point_type = QgsWkbTypes.MultiPoint multi_line_string_type = QgsWkbTypes.MultiLineString multi_polygon_type = QgsWkbTypes.MultiPolygon else: wkb_type = QGis.flatType(layer.wkbType()) point_type = QGis.WKBPoint line_string_type = QGis.WKBLineString polygon_type = QGis.WKBPolygon multi_point_type = QGis.WKBMultiPoint multi_line_string_type = QGis.WKBMultiLineString multi_polygon_type = QGis.WKBMultiPolygon LOGGER.info('type {}', layer.wkbType()) geometry = [None, 100] if wkb_type == point_type: geometry = ['point', 1] if wkb_type == line_string_type: geometry = ['line', 2] if wkb_type == polygon_type: geometry = ['polygon', 3] if wkb_type == multi_point_type: geometry = ['point', 4] if wkb_type == multi_line_string_type: geometry = ['line', 5] if wkb_type == multi_polygon_type: geometry = ['polygon', 6] if wkb_type == 100: LOGGER.info('Layer is a data-only layer') return geometry
def line_locate_point(geometry, point): coords = tocoordinates(geometry) assert QGis.flatType((geometry.wkbType())) == QGis.WKBLineString, 'Expected a LineString' assert len(point) == 2, 'Expected a point' sqrddist, closestsegmentpoint, indexofclosestvertexafter = geometry.closestSegmentWithContext(point) sum_length = 0 # Length of segments before the segment, where the point is located for ix in range(1, indexofclosestvertexafter): p0 = coords[ix - 1] p1 = coords[ix] segment = QgsGeometry.fromPolyline([p0, p1]) sum_length += segment.length() # Part of segment where the points is located p0 = coords[indexofclosestvertexafter - 1] segment = QgsGeometry.fromPolyline([p0, closestsegmentpoint]) sum_length += segment.length() return sum_length