def clean_features_iter(feat_iter): id = 0 for f in feat_iter: f_geom = f.geometry() # can be None # dropZValue if geometry is 3D if f_geom is None or f.geometry().constGet() is None: pass elif f.geometry().constGet().is3D(): f.geometry().constGet().dropZValue() f_geom = f.geometry() if f_geom is None or f_geom is NULL or not f_geom.isGeosValid(): # empty or invalid geometry pass elif f_geom.length() <= 0: ml_error = QgsFeature(error_feat) if f_geom.isMultipart(): ml_error.setGeometry( QgsGeometry.fromPointXY(f_geom.asMultiPolyline()[0][0])) else: ml_error.setGeometry( QgsGeometry.fromPointXY(f_geom.asPolyline()[0])) ml_error.setAttributes(['point']) points.append(ml_error) elif f_geom.type() == QgsWkbTypes.LineGeometry: if not f_geom.isMultipart(): f.setId(id) id += 1 yield f else: # multilinestring ml_segms = f_geom.asMultiPolyline() for ml in ml_segms: ml_geom = QgsGeometry(QgsGeometry.fromPolylineXY(ml)) ml_feat = QgsFeature(f) ml_feat.setId(id) id += 1 ml_feat.setGeometry(ml_geom) ml_error = QgsFeature(error_feat) ml_error.setGeometry( QgsGeometry.fromPointXY(ml_geom.asPolyline()[0])) ml_error.setAttributes(['multipart']) multiparts.append(ml_error) ml_error = QgsFeature(error_feat) ml_error.setGeometry( QgsGeometry.fromPointXY(ml_geom.asPolyline()[-1])) ml_error.setAttributes(['multipart']) multiparts.append(ml_error) yield ml_feat
def drawOnePath(self, rows, con, args, geomType, canvasItemList, mapCanvas): ''' draws line string on the mapCanvas. ''' resultPathRubberBand = canvasItemList['path'] for row in rows: cur2 = con.cursor() args['result_node_id'] = sql.Literal(row[1]) args['result_edge_id'] = sql.Literal(row[2]) args['result_cost'] = row[3] if row[2] != -1: query2 = sql.SQL(""" SELECT ST_AsText({geom_t} FROM {edge_schema}.{edge_table} WHERE {source} = {result_node_id} AND {id} = {result_edge_id} UNION SELECT ST_AsText(ST_Reverse({geom_t}) FROM {edge_schema}.{edge_table} WHERE {target} = {result_node_id} AND {id} = {result_edge_id}; """).format(**args) cur2.execute(query2) row2 = cur2.fetchone() geom = QgsGeometry().fromWkt(str(row2[0])) if geom.wkbType() == QgsWkbTypes.MultiLineString: for line in geom.asMultiPolyline(): for pt in line: resultPathRubberBand.addPoint(pt) elif geom.wkbType() == QgsWkbTypes.LineString: for pt in geom.asPolyline(): resultPathRubberBand.addPoint(pt)
def polygon_to_segments(self, geometry): # polygons to lines (mutlipart) boundary = QgsGeometry(geometry.constGet().boundary()) boundaries = boundary.asGeometryCollection() segments = [] for boundary in boundaries: if boundary.isMultipart(): lines = boundary.asMultiPolyline() for line in lines: for i in range(len(line) - 1): p1 = QgsPoint(line[i]) p2 = QgsPoint(line[i + 1]) segment = create_normalized_segment(p1, p2) segment_wkt = segment.asWkt() segments.append(segment) else: line = boundary.asPolyline() for i in range(len(line) - 1): p1 = QgsPoint(line[i]) p2 = QgsPoint(line[i + 1]) segment = create_normalized_segment(p1, p2) segments.append(segment) return segments
def arcsAadjacencyDictionary(layer): '''Build arc adjacency dictionary for the input stream network layer. This dictionary is a set of adjacency lists compiled for each node in th network. ''' arcsPerNode = dict() for f in layer.getFeatures(): geom = QgsGeometry(f.geometry()) polyline = geom.asPolyline() fromNode = polyline[0] toNode = polyline[-1] if fromNode not in arcsPerNode: arcsPerNode[fromNode] = [f] else: arcsPerNode[fromNode].append(f) if toNode not in arcsPerNode: arcsPerNode[toNode] = [f] else: arcsPerNode[toNode].append(f) return arcsPerNode
def drawOnePath(self, rows, con, args, geomType, canvasItemList, mapCanvas): ''' draws line string on the mapCanvas. ''' resultPathRubberBand = canvasItemList['path'] for row in rows: cur2 = con.cursor() args['result_node_id'] = row[1] args['result_edge_id'] = row[2] args['result_cost'] = row[3] if args['result_edge_id'] != -1: query2 = """ SELECT ST_AsText(%(transform_s)s%(geometry)s%(transform_e)s) FROM %(edge_table)s WHERE %(source)s = %(result_node_id)d AND %(id)s = %(result_edge_id)d UNION SELECT ST_AsText(%(transform_s)sST_Reverse(%(geometry)s)%(transform_e)s) FROM %(edge_table)s WHERE %(target)s = %(result_node_id)d AND %(id)s = %(result_edge_id)d; """ % args ##Utils.logMessage(query2) cur2.execute(query2) row2 = cur2.fetchone() ##Utils.logMessage(str(row2[0])) assert row2, "Invalid result geometry. (node_id:%(result_node_id)d, edge_id:%(result_edge_id)d)" % args geom = QgsGeometry().fromWkt(str(row2[0])) if geom.wkbType() == QgsWkbTypes.MultiLineString: for line in geom.asMultiPolyline(): for pt in line: resultPathRubberBand.addPoint(pt) elif geom.wkbType() == QgsWkbTypes.LineString: for pt in geom.asPolyline(): resultPathRubberBand.addPoint(pt)
def draw(self, rows, con, args, geomType, canvasItemList, mapCanvas): ''' draw the result ''' resultPathRubberBand = canvasItemList['path'] i = 0 count = len(rows) for row in rows: query2 = "" cur2 = con.cursor() args['result_node_id'] = row[1] args['result_edge_id'] = row[2] args['result_cost'] = row[3] if i == 0 and args['result_node_id'] == -1: args['result_next_node_id'] = rows[i + 1][1] query2 = """ SELECT ST_AsText(%(transform_s)sST_Line_Substring(%(geometry)s, %(source_pos)s, 1.0)%(transform_e)s) FROM %(edge_table)s WHERE %(target)s = %(result_next_node_id)s AND %(id)s = %(result_edge_id)s UNION SELECT ST_AsText(%(transform_s)sST_Line_Substring(ST_Reverse(%(geometry)s), 1.0 - %(source_pos)s, 1.0)%(transform_e)s) FROM %(edge_table)s WHERE %(source)s = %(result_next_node_id)s AND %(id)s = %(result_edge_id)s; """ % args elif i == (count - 1) and ((args['result_edge_id'] == -1) or (str(args['result_edge_id']) == args['target_id'])): if args['result_edge_id'] != -1: query2 = """ SELECT ST_AsText(%(transform_s)sST_Line_Substring(%(geometry)s, 0.0, %(target_pos)s)%(transform_e)s) FROM %(edge_table)s WHERE %(source)s = %(result_node_id)s AND %(id)s = %(result_edge_id)s UNION SELECT ST_AsText(%(transform_s)sST_Line_Substring(ST_Reverse(%(geometry)s), 0.0, 1.0 - %(target_pos)s)%(transform_e)s) FROM %(edge_table)s WHERE %(target)s = %(result_node_id)s AND %(id)s = %(result_edge_id)s; """ % args else: break else: query2 = """ SELECT ST_AsText(%(transform_s)s%(geometry)s%(transform_e)s) FROM %(edge_table)s WHERE %(source)s = %(result_node_id)d AND %(id)s = %(result_edge_id)d UNION SELECT ST_AsText(%(transform_s)sST_Reverse(%(geometry)s)%(transform_e)s) FROM %(edge_table)s WHERE %(target)s = %(result_node_id)d AND %(id)s = %(result_edge_id)d; """ % args ##Utils.logMessage(query2) cur2.execute(query2) row2 = cur2.fetchone() ##Utils.logMessage(str(row2[0])) assert row2, "Invalid result geometry. (node_id:%(result_node_id)d, edge_id:%(result_edge_id)d)" % args geom = QgsGeometry().fromWkt(str(row2[0])) if geom.wkbType() == QgsWkbTypes.MultiLineString: for line in geom.asMultiPolyline(): for pt in line: resultPathRubberBand.addPoint(pt) elif geom.wkbType() == QgsWkbTypes.LineString: for pt in geom.asPolyline(): resultPathRubberBand.addPoint(pt) i = i + 1
def draw(self, rows, con, args, geomType, canvasItemList, mapCanvas): ''' draw the result ''' resultPathsRubberBands = canvasItemList['paths'] rubberBand = None cur_route_id = -1 for row in rows: cur2 = con.cursor() if self.version < 2.1: args['result_route_id'] = row[1] args['result_node_id'] = row[2] args['result_edge_id'] = row[3] args['result_cost'] = row[4] else: args['result_route_id'] = row[2] args['result_node_id'] = row[4] args['result_edge_id'] = row[5] args['result_cost'] = row[6] if args['result_route_id'] != cur_route_id: cur_route_id = args['result_route_id'] if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None rubberBand = QgsRubberBand(mapCanvas, Utils.getRubberBandType(False)) rubberBand.setColor(QColor(255, 0, 0, 128)) rubberBand.setWidth(4) if args['result_edge_id'] != -1: #if args['result_edge_id'] != 0: # pgRouting <= 2.0.0rc1 query2 = """ SELECT ST_AsText(%(transform_s)s%(geometry)s%(transform_e)s) FROM %(edge_table)s WHERE %(source)s = %(result_node_id)d AND %(id)s = %(result_edge_id)d UNION SELECT ST_AsText(%(transform_s)sST_Reverse(%(geometry)s)%(transform_e)s) FROM %(edge_table)s WHERE %(target)s = %(result_node_id)d AND %(id)s = %(result_edge_id)d; """ % args ##Utils.logMessage(query2) cur2.execute(query2) row2 = cur2.fetchone() ##Utils.logMessage(str(row2[0])) assert row2, "Invalid result geometry. (route_id:%(result_route_id)d, node_id:%(result_node_id)d, edge_id:%(result_edge_id)d)" % args geom = QgsGeometry().fromWkt(str(row2[0])) if geom.wkbType() == QgsWkbTypes.MultiLineString: for line in geom.asMultiPolyline(): for pt in line: rubberBand.addPoint(pt) elif geom.wkbType() == QgsWkbTypes.LineString: for pt in geom.asPolyline(): rubberBand.addPoint(pt) if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None
def drawManyPaths(self, rows, columns, con, args, geomType, canvasItemList, mapCanvas): ''' draws multi line string on the mapCanvas. ''' resultPathsRubberBands = canvasItemList['paths'] rubberBand = None cur_path_id = None for row in rows: cur2 = con.cursor() result_path_id = str(row[columns[0]]) args['result_node_id'] = sql.Literal(row[columns[1]]) args['result_edge_id'] = sql.Literal(row[columns[2]]) if result_path_id != cur_path_id: cur_path_id = result_path_id if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None rubberBand = QgsRubberBand(mapCanvas, Utils.getRubberBandType(False)) rubberBand.setColor(QColor(255, 0, 0, 128)) rubberBand.setWidth(4) if row[columns[2]] != -1: query2 = sql.SQL(""" SELECT ST_AsText({transform_s}{geometry}{transform_e}) FROM {edge_schema}.{edge_table} WHERE {source} = {result_node_id} AND {id} = {result_edge_id} UNION SELECT ST_AsText({transform_s}ST_Reverse({geometry}){transform_e}) FROM {edge_schema}.{edge_table} WHERE {target} = {result_node_id} AND {id} = {result_edge_id} """).format(**args).as_string(con) cur2.execute(query2) row2 = cur2.fetchone() geom = QgsGeometry().fromWkt(str(row2[0])) if geom.wkbType() == QgsWkbTypes.MultiLineString: for line in geom.asMultiPolyline(): for pt in line: rubberBand.addPoint(pt) elif geom.wkbType() == QgsWkbTypes.LineString: for pt in geom.asPolyline(): rubberBand.addPoint(pt) if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None
class GeometryHighlight(QgsMapCanvasItem): _mapCanvas = None # QgsMapCanvas _geometry = None # QgsGeometry() _brush = QBrush() _pen = QPen() def __init__(self, mapCanvas, geometry, layer): super(GeometryHighlight, self).__init__(mapCanvas) self._mapCanvas = mapCanvas if not geometry or not isinstance(geometry, QgsGeometry) or geometry.isEmpty() or not geometry.isGeosValid(): return self._geometry = QgsGeometry(geometry) # Force deep copy self.setLineColor(Project.highlightLineColor()) self.setFillColor(Project.highlightFillColor()) if (layer and self._mapCanvas.mapSettings().hasCrsTransformEnabled()): ct = self._mapCanvas.mapSettings().layerTransform(layer) if ct: self._geometry.transform(ct) self.updateRect() self.update() def remove(self): self._mapCanvas.scene().removeItem(self) def setLineWidth(self, width): self._pen.setWidth(width) def setLineColor(self, color): lineColor = QColor(color) lineColor.setAlpha(255) self._pen.setColor(lineColor) def setFillColor(self, fillColor): self._brush.setColor(fillColor) self._brush.setStyle(Qt.SolidPattern) def updatePosition(self): pass # protected: def paint(self, painter, option=None, widget=None): # Override if not self._geometry: return painter.setPen(self._pen) painter.setBrush(self._brush) wkbType = self._geometry.wkbType() if wkbType == QGis.WKBPoint or wkbType == QGis.WKBPoint25D: self._paintPoint(painter, self._geometry.asPoint()) elif wkbType == QGis.WKBMultiPoint or wkbType == QGis.WKBMultiPoint25D: for point in self._geometry.asMultiPoint(): self._paintPoint(painter, point) elif wkbType == QGis.WKBLineString or wkbType == QGis.WKBLineString25D: self._paintLine(painter, self._geometry.asPolyline()) elif wkbType == QGis.WKBMultiLineString or wkbType == QGis.WKBMultiLineString25D: for line in self._geometry.asMultiPolyline(): self._paintLine(painter, line) elif wkbType == QGis.WKBPolygon or wkbType == QGis.WKBPolygon25D: self._paintPolygon(painter, self._geometry.asPolygon()) elif wkbType == QGis.WKBMultiPolygon or wkbType == QGis.WKBMultiPolygon25D: for polygon in self._geometry.asMultiPolygon(): self._paintPolygon(painter, polygon) def updateRect(self): if self._geometry: r = self._geometry.boundingBox() if r.isEmpty(): d = self._mapCanvas.extent().width() * 0.005 r.setXMinimum(r.xMinimum() - d) r.setYMinimum(r.yMinimum() - d) r.setXMaximum(r.xMaximum() + d) r.setYMaximum(r.yMaximum() + d) self.setRect(r) self.setVisible(True) else: self.setRect(QgsRectangle()) # private: def _paintPoint(self, painter, point): painter.drawEllipse(self.toCanvasCoordinates(point) - self.pos(), 2, 2) def _paintLine(self, painter, line): polyline = QPolygonF() for point in line: polyline.append(self.toCanvasCoordinates(point) - self.pos()) painter.drawPolyline(polyline) def _paintPolygon(self, painter, polygon): path = QPainterPath() for line in polygon: ring = QPolygonF() for point in line: cur = self.toCanvasCoordinates(point) - self.pos() ring.append(cur) ring.append(ring[0]) path.addPolygon(ring) painter.drawPath(path)
def canvasReleaseEvent(self, event): if not self.mouse_clicked: return if event.button() == Qt.LeftButton: self.mouse_clicked = False # Find first available ID for Junctions node_eid = NetworkUtils.find_next_id( self.params.junctions_vlay, Junction.prefix) # TODO: softcode elev = 0 if self.elev is None and self.params.dem_rlay is not None: self.iface.messageBar().pushMessage( Parameters.plug_in_name, 'Elevation value not available: element elevation set to 0.', QgsMessageBar.WARNING, 5) # TODO: softcode else: elev = self.elev j_demand = float(self.data_dock.txt_junction_demand.text()) deltaz = float(self.data_dock.txt_junction_deltaz.text()) pattern = self.data_dock.cbo_junction_pattern.itemData( self.data_dock.cbo_junction_pattern.currentIndex()) if pattern is not None: pattern_id = pattern.id else: pattern_id = None emitter_coeff_s = self.data_dock.txt_junction_emit_coeff.text() if emitter_coeff_s is None or emitter_coeff_s == '': emitter_coeff = float(0) else: emitter_coeff = float( self.data_dock.txt_junction_emit_coeff.text()) junction_desc = self.data_dock.txt_junction_desc.text() junction_tag = self.data_dock.cbo_junction_tag.currentText() # No links snapped: create a new stand-alone node if self.snapped_feat_id is None: NodeHandler.create_new_junction(self.params, self.mouse_pt, node_eid, elev, j_demand, deltaz, pattern_id, emitter_coeff, junction_desc, junction_tag) # A link has been snapped else: # Get the snapped pipe request = QgsFeatureRequest().setFilterFid( self.snapped_feat_id) feats = list(self.params.pipes_vlay.getFeatures(request)) if len(feats) > 0: snapped_pipe = QgsFeature(feats[0]) snapped_ft_pts = QgsGeometry.asPolyline( snapped_pipe.geometry()) # The new junction is on the start or end node of the pipe if NetworkUtils.points_overlap(QgsGeometry.fromPoint(self.snapped_vertex), QgsGeometry.fromPoint(snapped_ft_pts[0]), self.params.tolerance) or\ NetworkUtils.points_overlap(QgsGeometry.fromPoint(self.snapped_vertex), QgsGeometry.fromPoint(snapped_ft_pts[len(snapped_ft_pts) - 1]), self.params.tolerance): NodeHandler.create_new_junction( self.params, self.snapped_vertex, node_eid, self.elev, j_demand, deltaz, pattern_id, emitter_coeff, junction_desc, junction_tag) else: # Split the pipe (start_node_ft, end_node_ft) = NetworkUtils.find_start_end_nodes( self.params, snapped_pipe.geometry()) if start_node_ft is None or end_node_ft is None: self.iface.messageBar().pushMessage( Parameters.plug_in_name, 'The pipe is missing the start or end nodes. Cannot add a new junction along the pipe.', QgsMessageBar.WARNING, 5) # TODO: softcode return # Check that the snapped point on line is distant enough from start/end nodes if start_node_ft.geometry().distance(QgsGeometry.fromPoint(self.snapped_vertex)) > self.params.min_dist and\ end_node_ft.geometry().distance(QgsGeometry.fromPoint(self.snapped_vertex)) > self.params.min_dist: NodeHandler.create_new_junction( self.params, self.snapped_vertex, node_eid, self.elev, j_demand, deltaz, pattern_id, emitter_coeff, junction_desc, junction_tag) LinkHandler.split_pipe(self.params, snapped_pipe, self.snapped_vertex) else: self.iface.messageBar().pushMessage( Parameters.plug_in_name, 'The new junction is too close to either the pipe end or start nodes. Cannot add a new junction along the pipe.', QgsMessageBar.WARNING, 5) # TODO: softcode
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.VECTOR)) pointCount = float(self.getParameterValue(self.POINT_NUMBER)) minDistance = float(self.getParameterValue(self.MIN_DISTANCE)) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QGis.WKBPoint, layer.dataProvider().crs()) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 featureCount = layer.featureCount() total = 100.0 / pointCount index = QgsSpatialIndex() points = dict() da = QgsDistanceArea() request = QgsFeatureRequest() random.seed() while nIterations < maxIterations and nPoints < pointCount: # pick random feature fid = random.randint(0, featureCount - 1) f = layer.getFeatures(request.setFilterFid(fid)).next() fGeom = QgsGeometry(f.geometry()) if fGeom.isMultipart(): lines = fGeom.asMultiPolyline() # pick random line lineId = random.randint(0, len(lines) - 1) vertices = lines[lineId] else: vertices = fGeom.asPolyline() # pick random segment if len(vertices) == 2: vid = 0 else: vid = random.randint(0, len(vertices) - 2) startPoint = vertices[vid] endPoint = vertices[vid + 1] length = da.measureLine(startPoint, endPoint) dist = length * random.random() if dist > minDistance: d = dist / (length - dist) rx = (startPoint.x() + d * endPoint.x()) / (1 + d) ry = (startPoint.y() + d * endPoint.y()) / (1 + d) # generate random point pnt = QgsPoint(rx, ry) geom = QgsGeometry.fromPoint(pnt) if vector.checkMinDistance(pnt, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) writer.addFeature(f) index.insertFeature(f) points[nPoints] = pnt nPoints += 1 progress.setPercentage(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self.tr('Can not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) del writer
def draw(self, rows, con, args, geomType, canvasItemList, mapCanvas): ''' draw the result ''' resultPathsRubberBands = canvasItemList['paths'] rubberBand = None cur_path_id = -1 for row in rows: cur2 = con.cursor() args['result_path_id'] = row[0] args['result_source_id'] = row[1] args['result_target_id'] = row[2] args['result_cost'] = row[3] if args['result_path_id'] != cur_path_id: cur_path_id = args['result_path_id'] if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None rubberBand = QgsRubberBand(mapCanvas, Utils.getRubberBandType(False)) rubberBand.setColor(QColor(255, 0, 0, 128)) rubberBand.setWidth(4) if args['result_cost'] != -1: query2 = """ SELECT ST_AsText( ST_MakeLine( (SELECT the_geom FROM %(edge_table)s_vertices_pgr WHERE id = %(result_source_id)d), (SELECT the_geom FROM %(edge_table)s_vertices_pgr WHERE id = %(result_target_id)d) )) """ % args ##Utils.logMessage(query2) cur2.execute(query2) row2 = cur2.fetchone() ##Utils.logMessage(str(row2[0])) assert row2, "Invalid result geometry. (path_id:%(result_path_id)d, saource_id:%(result_source_id)d, target_id:%(result_target_id)d)" % args geom = QgsGeometry().fromWkt(str(row2[0])) if geom.wkbType() == QgsWkbTypes.MultiLineString: for line in geom.asMultiPolyline(): for pt in line: rubberBand.addPoint(pt) elif geom.wkbType() == QgsWkbTypes.LineString: for pt in geom.asPolyline(): rubberBand.addPoint(pt) if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None resultNodesTextAnnotations = canvasItemList['annotations'] Utils.setStartPoint(geomType, args) Utils.setEndPoint(geomType, args) for row in rows: cur2 = con.cursor() args['result_seq'] = row[0] args['result_source_id'] = row[1] args['result_target_id'] = row[2] args['result_cost'] = row[3] query2 = """ SELECT ST_AsText(%(transform_s)s%(startpoint)s%(transform_e)s) FROM %(edge_table)s WHERE %(source)s = %(result_target_id)d UNION SELECT ST_AsText(%(transform_s)s%(endpoint)s%(transform_e)s) FROM %(edge_table)s WHERE %(target)s = %(result_target_id)d """ % args cur2.execute(query2) row2 = cur2.fetchone() assert row2, "Invalid result geometry. (target_id:%(result_target_id)d)" % args geom = QgsGeometry().fromWkt(str(row2[0])) pt = geom.asPoint() textDocument = QTextDocument( "%(result_target_id)d:%(result_cost)f" % args) textAnnotation = QgsTextAnnotation() textAnnotation.setMapPosition(geom.asPoint()) textAnnotation.setFrameSize(QSizeF(textDocument.idealWidth(), 20)) textAnnotation.setFrameOffsetFromReferencePoint(QPointF(20, -40)) textAnnotation.setDocument(textDocument) QgsMapCanvasAnnotationItem(textAnnotation, mapCanvas) resultNodesTextAnnotations.append(textAnnotation)
def drawCostPaths(self, rows, con, args, geomType, canvasItemList, mapCanvas): resultPathsRubberBands = canvasItemList['paths'] rubberBand = None cur_path_id = -1 for row in rows: cur2 = con.cursor() args['result_path_id'] = row[0] args['result_source_id'] = sql.Literal(row[1]) args['result_target_id'] = sql.Literal(row[2]) args['result_cost'] = row[3] if args['result_path_id'] != cur_path_id: cur_path_id = args['result_path_id'] if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None rubberBand = QgsRubberBand(mapCanvas, Utils.getRubberBandType(False)) rubberBand.setColor(QColor(255, 0, 0, 128)) rubberBand.setWidth(4) if args['result_cost'] != -1: query2 = sql.SQL(""" SELECT ST_AsText( ST_MakeLine( (SELECT {geometry_vt} FROM {vertex_schema}.{vertex_table} WHERE id = {result_source_id}), (SELECT {geometry_vt} FROM {vertex_schema}.{vertex_table} WHERE id = {result_target_id}) )) """).format(**args) # Utils.logMessage(query2) cur2.execute(query2) row2 = cur2.fetchone() # Utils.logMessage(str(row2[0])) geom = QgsGeometry().fromWkt(str(row2[0])) if geom.wkbType() == QgsWkbTypes.MultiLineString: for line in geom.asMultiPolyline(): for pt in line: rubberBand.addPoint(pt) elif geom.wkbType() == QgsWkbTypes.LineString: for pt in geom.asPolyline(): rubberBand.addPoint(pt) # TODO label the edge instead of labeling the target points if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None resultNodesTextAnnotations = canvasItemList['annotations'] for row in rows: cur2 = con.cursor() args['result_seq'] = row[0] args['result_source_id'] = sql.Literal(row[1]) result_target_id = row[2] args['result_target_id'] = sql.Literal(result_target_id) result_cost = row[3] query2 = sql.SQL(""" SELECT ST_AsText( ST_startPoint({geometry}) ) FROM {edge_schema}.{edge_table} WHERE {source} = {result_target_id} UNION SELECT ST_AsText( ST_endPoint( {geometry} ) ) FROM {edge_schema}.{edge_table} WHERE {target} = {result_target_id} """).format(**args) cur2.execute(query2) row2 = cur2.fetchone() geom = QgsGeometry().fromWkt(str(row2[0])) pt = geom.asPoint() textDocument = QTextDocument("{0!s}:{1}".format(result_target_id, result_cost)) textAnnotation = QgsTextAnnotation() textAnnotation.setMapPosition(geom.asPoint()) textAnnotation.setFrameSize(QSizeF(textDocument.idealWidth(), 20)) textAnnotation.setFrameOffsetFromReferencePoint(QPointF(20, -40)) textAnnotation.setDocument(textDocument) QgsMapCanvasAnnotationItem(textAnnotation, mapCanvas) resultNodesTextAnnotations.append(textAnnotation)
def split_line_at_points( polyline_input, point_features, point_feature_id_field="id", start_node_id=None, end_node_id=None, ): """Split line at points Args: polyline (QgsPolyline): point_features (iteratable object of QgsFeature or list of dictonaries with id and geometry ('geom'): point_feature_id_field (str): fieldname if the id field of the point_features start_node_id (str or int): node id of point at begin of polyline end_node_id (str or int): node id of point at end of polyline Returns: (list of dict): Splitted polyline into parts as dictonary with: geom: Polyline geometry start_node_id: id of node at starting point of line end_node_id: id of node at end point of line distance at line: is distance of original line at the begin of this line part """ snap_points = [] source_crs = QgsCoordinateReferenceSystem(4326) dest_crs = QgsCoordinateReferenceSystem(3857) transform = QgsCoordinateTransform(source_crs, dest_crs, QgsProject.instance()) transform_back = QgsCoordinateTransform(dest_crs, source_crs, QgsProject.instance()) polyline = QgsGeometry(polyline_input) polyline.transform(transform) for point in point_features: if type(point) == QgsFeature: point = { point_feature_id_field: point[point_feature_id_field], "geom": point.geometry(), } if hasattr(point["geom"], "asPoint"): geom = point["geom"].asPoint() else: geom = point["geom"] geom = QgsGeometry.fromPointXY(geom) geom.transform(transform) geom = geom.asPoint() closest_seg = polyline.closestSegmentWithContext(geom) # get nearest point (related to the point) on the line point_on_line = closest_seg[1] point_geom_on_line = QgsPoint(point_on_line[0], point_on_line[1]) # get nr of vertex (at the end of the line where the closest point is # found end_vertex_nr = closest_seg[2] start_vertex_nr = end_vertex_nr - 1 p1 = polyline.asPolyline()[start_vertex_nr] # first vertex p2 = point_geom_on_line distance_on_subline = math.hypot(p2.x() - p1.x(), p2.y() - p1.y()) snap_points.append(( start_vertex_nr, distance_on_subline, point_geom_on_line, point[point_feature_id_field], )) # order on vertex nr and if same vertex nr on distance snap_points.sort(key=lambda x: x[1]) snap_points.sort(key=lambda x: x[0]) # create line parts line_parts = [] line_points = [] start_point_id = start_node_id total_line_distance = 0 for i, vertex in enumerate(polyline.asPolyline()): line_points.append(QgsPoint(vertex[0], vertex[1])) # get points after this vertex split_points_on_segment = [p for p in snap_points if p[0] == i] for point in split_points_on_segment: # only add another point if point is not equal to last vertex # todo: throw error when at begin or end vertex of original line? # todo: what to do of multiple points on same location? line_points.append(point[2]) geom = QgsGeometry.fromPolyline(line_points) # length, unit_type = d.convertMeasurement( # d.computeDistance(line_points), # Qgis.Meters, Qgis.Meters, False) # Qgis.Degrees length = geom.length() # add line parts line_parts.append({ "geom": geom.transform(transform_back), "start_point_id": start_point_id, "end_point_id": point[3], "distance_at_line": total_line_distance, "length": length, }) # create starting point of new line line_points = [point[2]] start_point_id = point[3] total_line_distance += length # last part of the line geom = QgsGeometry.fromPolyline(line_points) length = geom.length() # length, something = d.convertMeasurement( # d.computeDistance(line_points), # Qgis.Meters, Qgis.Meters, False) line_parts.append({ "geom": geom, "start_point_id": start_point_id, "end_point_id": end_node_id, "distance_at_line": total_line_distance, "length": length, }) return line_parts
def load_complex_gml(self, xml_uri, is_remote, attributes = {}, geometry_mapping = None, logger = None, swap_xy = False): """ :param xml_uri: the XML URI :param is_remote: True if it has to be fetched by http :param attributes: { 'attr1' : ( '//xpath/expression', QVariant.Int ) } :param geometry_mapping: XPath expression to a gml geometry node :param swap_xy: True if X/Y coordinates must be swapped :returns: the created layer """ if is_remote: xml = remote_open_from_qgis(xml_uri) else: # Open the file in binary mode, this means returning bytes # instead of a string whose encoding would have to be interpreted # it is up to the XML parser to determine which encoding it is xml = open(xml_uri, 'rb') src = ComplexFeatureSource(xml, attributes, geometry_mapping, logger) attr_list = [ (k, v[1]) for k, v in attributes.items() ] # first feature id, fid, g, xml, attrs = next(src.getFeatures()) qgsgeom = None if g is None: layer = self._create_layer('none', None, attr_list, src.title) else: wkb, srid = g qgsgeom = QgsGeometry() qgsgeom.fromWkb(wkb) if qgsgeom and qgsgeom.type() == QgsWkbTypes.PointGeometry: layer = self._create_layer('point', srid, attr_list, src.title + " (points)") elif qgsgeom and qgsgeom.type() == QgsWkbTypes.LineGeometry: layer = self._create_layer('linestring', srid, attr_list, src.title + " (lines)") elif qgsgeom and qgsgeom.type() == QgsWkbTypes.PolygonGeometry: layer = self._create_layer('polygon', srid, attr_list, src.title + " (polygons)") # add metadata self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping) # collect features features = [] for id, fid, g, xml, attrs in src.getFeatures(): qgsgeom = None wkb, srid = g qgsgeom = QgsGeometry() qgsgeom.fromWkb(wkb) if qgsgeom and qgsgeom.type() == QgsWkbTypes.PointGeometry: if swap_xy: p = qgsgeom.asPoint() qgsgeom = QgsGeometry.fromPoint(QgsPointXY(p[1], p[0])) elif qgsgeom and qgsgeom.type() == QgsWkbTypes.LineGeometry: if swap_xy: pl = qgsgeom.asPolyline() qgsgeom = QgsGeometry.fromPolyline([QgsPointXY(p[1],p[0]) for p in pl]) elif qgsgeom and qgsgeom.type() == QgsWkbTypes.PolygonGeometry: if swap_xy: pl = qgsgeom.asPolygon() qgsgeom = QgsGeometry.fromPolygon([[QgsPointXY(p[1],p[0]) for p in r] for r in pl]) f = QgsFeature(layer.dataProvider().fields(), id) if qgsgeom: f.setGeometry(qgsgeom) f.setAttribute("id", str(id)) f.setAttribute("fid", fid) f.setAttribute("_xml_", ET.tostring(xml).decode('utf8')) for k, v in attrs.items(): r = f.setAttribute(k, v) features.append(f) # write features if len(features) > 0: layer.dataProvider().addFeatures(features) return layer
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.VECTOR)) pointCount = float(self.getParameterValue(self.POINT_NUMBER)) minDistance = float(self.getParameterValue(self.MIN_DISTANCE)) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QGis.WKBPoint, layer.crs()) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 featureCount = layer.featureCount() total = 100.0 / pointCount if pointCount > 0 else 1 index = QgsSpatialIndex() points = dict() da = QgsDistanceArea() request = QgsFeatureRequest() random.seed() while nIterations < maxIterations and nPoints < pointCount: # pick random feature fid = random.randint(0, featureCount - 1) f = layer.getFeatures(request.setFilterFid(fid)).next() fGeom = QgsGeometry(f.geometry()) if fGeom.isMultipart(): lines = fGeom.asMultiPolyline() # pick random line lineId = random.randint(0, len(lines) - 1) vertices = lines[lineId] else: vertices = fGeom.asPolyline() # pick random segment if len(vertices) == 2: vid = 0 else: vid = random.randint(0, len(vertices) - 2) startPoint = vertices[vid] endPoint = vertices[vid + 1] length = da.measureLine(startPoint, endPoint) dist = length * random.random() if dist > minDistance: d = dist / (length - dist) rx = (startPoint.x() + d * endPoint.x()) / (1 + d) ry = (startPoint.y() + d * endPoint.y()) / (1 + d) # generate random point pnt = QgsPoint(rx, ry) geom = QgsGeometry.fromPoint(pnt) if vector.checkMinDistance(pnt, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) writer.addFeature(f) index.insertFeature(f) points[nPoints] = pnt nPoints += 1 progress.setPercentage(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Can not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) del writer
def draw(self, rows, con, args, geomType, canvasItemList, mapCanvas): ''' draw the result ''' resultPathsRubberBands = canvasItemList['paths'] rubberBand = None cur_path_id = -1 i = 0 count = len(rows) ids = args['ids'].split(',') args['last_id'] = ids[len(ids) - 1] pcts = args['pcts'].split(',') pct_idx = 0 for row in rows: cur2 = con.cursor() args['result_path_id'] = row[1] args['result_node_id'] = row[2] args['result_edge_id'] = row[3] args['result_cost'] = row[4] if args['result_path_id'] != cur_path_id: cur_path_id = args['result_path_id'] if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None rubberBand = QgsRubberBand(mapCanvas, Utils.getRubberBandType(False)) rubberBand.setColor(QColor(255, 0, 0, 128)) rubberBand.setWidth(4) query2 = "" if i < (count - 1): args['result_next_path_id'] = rows[i + 1][1] args['result_next_node_id'] = rows[i + 1][2] if args['result_next_path_id'] != args['result_path_id']: pct_idx += 1 elif i == (count - 1): pct_idx = len(pcts) - 1 args['current_pct'] = pcts[pct_idx] if i == 0 and args['result_node_id'] == -1: query2 = """ SELECT ST_AsText(%(transform_s)sST_Line_Substring(%(geometry)s, %(current_pct)s, 1.0)%(transform_e)s) FROM %(edge_table)s WHERE %(target)s = %(result_next_node_id)s AND %(id)s = %(result_edge_id)s UNION SELECT ST_AsText(%(transform_s)sST_Line_Substring(ST_Reverse(%(geometry)s), 1.0 - %(current_pct)s, 1.0)%(transform_e)s) FROM %(edge_table)s WHERE %(source)s = %(result_next_node_id)s AND %(id)s = %(result_edge_id)s; """ % args elif i < (count - 1) and ( args['result_path_id'] != args['result_next_path_id'] ) and (args['result_node_id'] == args['result_next_node_id']): # round trip case query2 = """ SELECT ST_AsText(ST_LineMerge(ST_Collect(ARRAY[ ( SELECT ST_AsText(%(transform_s)sST_Line_Substring(%(geometry)s, 0.0, %(current_pct)s)%(transform_e)s) FROM %(edge_table)s WHERE %(source)s = %(result_node_id)s AND %(id)s = %(result_edge_id)s UNION SELECT ST_AsText(%(transform_s)sST_Line_Substring(ST_Reverse(%(geometry)s), 0.0, 1.0 - %(current_pct)s)%(transform_e)s) FROM %(edge_table)s WHERE %(target)s = %(result_node_id)s AND %(id)s = %(result_edge_id)s ), ( SELECT ST_AsText(%(transform_s)sST_Reverse(ST_Line_Substring(%(geometry)s, 0.0, %(current_pct)s))%(transform_e)s) FROM %(edge_table)s WHERE %(source)s = %(result_node_id)s AND %(id)s = %(result_edge_id)s UNION SELECT ST_AsText(%(transform_s)sST_Reverse(ST_Line_Substring(ST_Reverse(%(geometry)s), 0.0, 1.0 - %(current_pct)s))%(transform_e)s) FROM %(edge_table)s WHERE %(target)s = %(result_node_id)s AND %(id)s = %(result_edge_id)s )]))); """ % args elif i == (count - 1) and ( (args['result_edge_id'] == -1) or (str(args['result_edge_id']) == args['last_id'])): if args['result_edge_id'] != -1: query2 = """ SELECT ST_AsText(%(transform_s)sST_Line_Substring(%(geometry)s, 0.0, %(current_pct)s)%(transform_e)s) FROM %(edge_table)s WHERE %(source)s = %(result_node_id)s AND %(id)s = %(result_edge_id)s UNION SELECT ST_AsText(%(transform_s)sST_Line_Substring(ST_Reverse(%(geometry)s), 0.0, 1.0 - %(current_pct)s)%(transform_e)s) FROM %(edge_table)s WHERE %(target)s = %(result_node_id)s AND %(id)s = %(result_edge_id)s; """ % args else: break else: query2 = """ SELECT ST_AsText(%(transform_s)s%(geometry)s%(transform_e)s) FROM %(edge_table)s WHERE %(source)s = %(result_node_id)d AND %(id)s = %(result_edge_id)d UNION SELECT ST_AsText(%(transform_s)sST_Reverse(%(geometry)s)%(transform_e)s) FROM %(edge_table)s WHERE %(target)s = %(result_node_id)d AND %(id)s = %(result_edge_id)d; """ % args ##Utils.logMessage(query2) cur2.execute(query2) row2 = cur2.fetchone() ##Utils.logMessage(str(row2[0])) assert row2, "Invalid result geometry. (node_id:%(result_node_id)d, edge_id:%(result_edge_id)d)" % args geom = QgsGeometry().fromWkt(str(row2[0])) if geom.wkbType() == QgsWkbTypes.MultiLineString: for line in geom.asMultiPolyline(): for pt in line: rubberBand.addPoint(pt) elif geom.wkbType() == QgsWkbTypes.LineString: for pt in geom.asPolyline(): rubberBand.addPoint(pt) i = i + 1 if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None
def __mergeFeaturesSimple(self, provider, origFeats): newFeats = [] QgsMessageLog.logMessage( '---- Merge Simple: {0} features'.format(len(origFeats)), 'VoGis') if len(origFeats) < 1: return [] prevToPnt = None #newGeom = QgsGeometry() newGeom = QgsGeometry().fromPolyline([]) attrMap = None #newGeom = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(2, 2)]) #QgsMessageLog.logMessage('newGeom WKB Type {0}'.format(newGeom.wkbType() == QGis.WKBLineString), 'VoGis') for feat in origFeats: #QgsMessageLog.logMessage('{0}:{1}'.format('ORIG FEAT AttributeMap', self.__printAttribs(feat.attributeMap())), 'VoGis') #self.__printAttribs(feat.attributeMap()) currentGeom = feat.geometry() currentPnts = currentGeom.asPolyline() if prevToPnt is None: #QgsMessageLog.logMessage('combining FIRST {0}'.format(currentGeom.asPolyline()), 'VoGis') newGeom = newGeom.combine(currentGeom) if QGis.QGIS_VERSION_INT < 10900: attrMap = feat.attributeMap() else: attrMap = feat.attributes() else: if currentPnts[0] == prevToPnt: #QgsMessageLog.logMessage('combining {0}'.format(currentGeom.asPolyline()), 'VoGis') newGeom = newGeom.combine(currentGeom) if QGis.QGIS_VERSION_INT < 10900: attrMap = feat.attributeMap() else: attrMap = feat.attributes() else: #QgsMessageLog.logMessage('creating {0}'.format(newGeom.asPolyline()), 'VoGis') featNew = self.createQgLineFeature(newGeom.asPolyline()) featNew = self.__transferAttributes( provider, attrMap, featNew) newFeats.append(featNew) #feat = QgsFeature() #newGeom = QgsGeometry() newGeom = QgsGeometry().fromPolyline(currentPnts) if QGis.QGIS_VERSION_INT < 10900: attrMap = feat.attributeMap() else: attrMap = feat.attributes() #newGeom = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(2, 2)]) prevToPnt = currentPnts[len(currentPnts) - 1] featNew = self.createQgLineFeature(newGeom.asPolyline()) self.__transferAttributes(provider, attrMap, featNew) #newFeats.append(self.createQgLineFeature(newGeom.asPolyline())) newFeats.append(featNew) tmpFeats = [] for feat in newFeats: if feat.geometry().isGeosEmpty() is True: QgsMessageLog.logMessage('dropping empty geometry', 'VoGis') continue else: tmpFeats.append(feat) newFeats = tmpFeats QgsMessageLog.logMessage( '---- {0} features after Merge Simple'.format(len(newFeats)), 'VoGis') #for idx, f in enumerate(newFeats): # QgsMessageLog.logMessage('--------feature {0}---------'.format(idx), 'VoGis') # geo = f.geometry() # pnts = geo.asPolyline() # for i, v in enumerate(pnts): # QgsMessageLog.logMessage(' pnt {0}: {1}/{2}'.format(i, v.x(), v.y()), 'VoGis') return newFeats
def __mergeFeaturesSimple(self, provider, origFeats): newFeats = [] QgsMessageLog.logMessage('---- Merge Simple: {0} features'.format(len(origFeats)), 'VoGis') if len(origFeats) < 1: return [] prevToPnt = None #newGeom = QgsGeometry() newGeom = QgsGeometry().fromPolyline([]) attrMap = None #newGeom = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(2, 2)]) #QgsMessageLog.logMessage('newGeom WKB Type {0}'.format(newGeom.wkbType() == QGis.WKBLineString), 'VoGis') for feat in origFeats: #QgsMessageLog.logMessage('{0}:{1}'.format('ORIG FEAT AttributeMap', self.__printAttribs(feat.attributeMap())), 'VoGis') #self.__printAttribs(feat.attributeMap()) currentGeom = feat.geometry() currentPnts = currentGeom.asPolyline() if prevToPnt is None: #QgsMessageLog.logMessage('combining FIRST {0}'.format(currentGeom.asPolyline()), 'VoGis') newGeom = newGeom.combine(currentGeom) if QGis.QGIS_VERSION_INT < 10900: attrMap = feat.attributeMap() else: attrMap = feat.attributes() else: if currentPnts[0] == prevToPnt: #QgsMessageLog.logMessage('combining {0}'.format(currentGeom.asPolyline()), 'VoGis') newGeom = newGeom.combine(currentGeom) if QGis.QGIS_VERSION_INT < 10900: attrMap = feat.attributeMap() else: attrMap = feat.attributes(); else: #QgsMessageLog.logMessage('creating {0}'.format(newGeom.asPolyline()), 'VoGis') featNew = self.createQgLineFeature(newGeom.asPolyline()) featNew = self.__transferAttributes(provider, attrMap, featNew) newFeats.append(featNew) #feat = QgsFeature() #newGeom = QgsGeometry() newGeom = QgsGeometry().fromPolyline(currentPnts) if QGis.QGIS_VERSION_INT < 10900: attrMap = feat.attributeMap() else: attrMap = feat.attributes() #newGeom = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(2, 2)]) prevToPnt = currentPnts[len(currentPnts) - 1] featNew = self.createQgLineFeature(newGeom.asPolyline()) self.__transferAttributes(provider, attrMap, featNew) #newFeats.append(self.createQgLineFeature(newGeom.asPolyline())) newFeats.append(featNew) tmpFeats = [] for feat in newFeats: if feat.geometry().isGeosEmpty() is True: QgsMessageLog.logMessage('dropping empty geometry', 'VoGis') continue else: tmpFeats.append(feat) newFeats = tmpFeats QgsMessageLog.logMessage('---- {0} features after Merge Simple'.format(len(newFeats)), 'VoGis') #for idx, f in enumerate(newFeats): # QgsMessageLog.logMessage('--------feature {0}---------'.format(idx), 'VoGis') # geo = f.geometry() # pnts = geo.asPolyline() # for i, v in enumerate(pnts): # QgsMessageLog.logMessage(' pnt {0}: {1}/{2}'.format(i, v.x(), v.y()), 'VoGis') return newFeats
def __mergeFeaturesSimple(self, provider, origFeats): newFeats = [] QgsMessageLog.logMessage("---- Merge Simple: {0} features".format(len(origFeats)), "VoGis", Qgis.Info) if len(origFeats) < 1: return [] prevToPnt = None #newGeom = QgsGeometry() newGeom = QgsGeometry().fromPolylineXY([]) attrMap = None #newGeom = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(2, 2)]) #QgsMessageLog.logMessage("newGeom WKB Type {0}".format(newGeom.wkbType() == QGis.WKBLineString), "VoGis", Qgis.Info) for feat in origFeats: #QgsMessageLog.logMessage("{0}:{1}".format("ORIG FEAT AttributeMap", self.__printAttribs(feat.attributeMap())), "VoGis", Qgis.Info) #self.__printAttribs(feat.attributeMap()) currentGeom = feat.geometry() currentPnts = currentGeom.asPolyline() if prevToPnt is None: #QgsMessageLog.logMessage("combining FIRST {0}".format(currentGeom.asPolyline()), "VoGis", Qgis.Info) newGeom = newGeom.combine(currentGeom) attrMap = feat.attributes() else: if currentPnts[0] == prevToPnt: #QgsMessageLog.logMessage("combining {0}".format(currentGeom.asPolyline()), "VoGis", Qgis.Info) newGeom = newGeom.combine(currentGeom) attrMap = feat.attributes(); else: #QgsMessageLog.logMessage("creating {0}".format(newGeom.asPolyline()), "VoGis", Qgis.Info) featNew = self.createQgLineFeature(newGeom.asPolyline()) featNew = self.__transferAttributes(provider, attrMap, featNew) newFeats.append(featNew) #feat = QgsFeature() #newGeom = QgsGeometry() newGeom = QgsGeometry().fromPolylineXY(currentPnts) attrMap = feat.attributes() #newGeom = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(2, 2)]) prevToPnt = currentPnts[len(currentPnts) - 1] featNew = self.createQgLineFeature(newGeom.asPolyline()) self.__transferAttributes(provider, attrMap, featNew) #newFeats.append(self.createQgLineFeature(newGeom.asPolyline())) newFeats.append(featNew) tmpFeats = [] for feat in newFeats: if feat.geometry().isEmpty() is True: QgsMessageLog.logMessage("dropping empty geometry", "VoGis", Qgis.Warning) continue else: tmpFeats.append(feat) newFeats = tmpFeats QgsMessageLog.logMessage("---- {0} features after Merge Simple".format(len(newFeats)), "VoGis", Qgis.Info) #for idx, f in enumerate(newFeats): # QgsMessageLog.logMessage("--------feature {0}---------".format(idx), "VoGis", Qgis.Info) # geo = f.geometry() # pnts = geo.asPolyline() # for i, v in enumerate(pnts): # QgsMessageLog.logMessage(" pnt {0}: {1}/{2}".format(i, v.x(), v.y()), "VoGis", Qgis.Info) return newFeats