def save2PointShape(shapePath, geodata, attribName, attribData, label, spatialRef): """ :param label: :param shapePath: Pfad wo Shapefile agespeichert wird :param geodata: Koordinaten der Punkte :param attribName: Attributname (Feldname) von zusätzlichen Werten :param attribData: Werte für Attribute :param spatialRef: Räumliche Referenz """ # define fields for feature attributes. A QgsFields object is needed fields = QgsFields() fields.append(QgsField("StuetzenNr", QVariant.String)) fields.append(QgsField(attribName, QVariant.Int)) writer = QgsVectorFileWriter(shapePath, "UTF8", fields, QgsWkbTypes.PointZ, spatialRef, "ESRI Shapefile") if writer.hasError() != QgsVectorFileWriter.NoError: # TODO raise Exception("Vector Writer") for idx, (coords, attrib) in enumerate(zip(geodata, attribData)): feature = QgsFeature() feature.setFields(fields) # TODO: Nicht 3D weil Methode fromPoint() nicht existiert. Wird evtl. in der Zukunft implementiert feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(coords[0], coords[1]))) feature.setId(idx) feature.setAttribute("StuetzenNr", label[idx]) feature.setAttribute(attribName, attrib) writer.addFeature(feature) del feature # delete the writer to flush features to disk del writer
def processAlgorithm(self, parameters, context, feedback): spacing = self.parameterAsDouble(parameters, self.SPACING, context) inset = self.parameterAsDouble(parameters, self.INSET, context) randomize = self.parameterAsBool(parameters, self.RANDOMIZE, context) isSpacing = self.parameterAsBool(parameters, self.IS_SPACING, context) crs = self.parameterAsCrs(parameters, self.CRS, context) extent = self.parameterAsExtent(parameters, self.EXTENT, context, crs) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, crs) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) if randomize: seed() area = extent.width() * extent.height() if isSpacing: pSpacing = spacing else: pSpacing = sqrt(area / spacing) f = QgsFeature() f.initAttributes(1) f.setFields(fields) count = 0 total = 100.0 / (area / pSpacing) y = extent.yMaximum() - inset extent_geom = QgsGeometry.fromRect(extent) extent_engine = QgsGeometry.createGeometryEngine(extent_geom.constGet()) extent_engine.prepareGeometry() while y >= extent.yMinimum(): x = extent.xMinimum() + inset while x <= extent.xMaximum(): if feedback.isCanceled(): break if randomize: geom = QgsGeometry().fromPointXY(QgsPointXY( uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)), uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0)))) else: geom = QgsGeometry().fromPointXY(QgsPointXY(x, y)) if extent_engine.intersects(geom.constGet()): f.setAttribute('id', count) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) x += pSpacing count += 1 feedback.setProgress(int(count * total)) y = y - pSpacing return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_VECTOR), context) rasterPath = str(self.getParameterValue(self.INPUT_RASTER)) rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly) geoTransform = rasterDS.GetGeoTransform() rasterDS = None fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) fields.append(QgsField('line_id', QVariant.Int, '', 10, 0)) fields.append(QgsField('point_id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(fields, QgsWkbTypes.Point, layer.crs(), context) outFeature = QgsFeature() outFeature.setFields(fields) self.fid = 0 self.lineId = 0 self.pointId = 0 features = QgsProcessingUtils.getFeatures(layer, context) total = 100.0 / layer.featureCount() if layer.featureCount() else 0 for current, f in enumerate(features): geom = f.geometry() if geom.isMultipart(): lines = geom.asMultiPolyline() for line in lines: for i in range(len(line) - 1): p1 = line[i] p2 = line[i + 1] (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform) (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform) self.buildLine(x1, y1, x2, y2, geoTransform, writer, outFeature) else: points = geom.asPolyline() for i in range(len(points) - 1): p1 = points[i] p2 = points[i + 1] (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform) (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform) self.buildLine(x1, y1, x2, y2, geoTransform, writer, outFeature) self.pointId = 0 self.lineId += 1 feedback.setProgress(int(current * total)) del writer
def testFilter(self): """ test calculating aggregate with filter """ layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory") pr = layer.dataProvider() int_values = [4, 2, 3, 2, 5, None, 8] features = [] for v in int_values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([v]) features.append(f) assert pr.addFeatures(features) agg = QgsAggregateCalculator(layer) filter_string = "fldint > 2" agg.setFilter(filter_string) self.assertEqual(agg.filter(), filter_string) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint') self.assertTrue(ok) self.assertEqual(val, 20) # remove filter and retest agg.setFilter(None) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint') self.assertTrue(ok) self.assertEqual(val, 24)
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_VECTOR)) rasterPath = unicode(self.getParameterValue(self.INPUT_RASTER)) rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly) geoTransform = rasterDS.GetGeoTransform() rasterDS = None fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) fields.append(QgsField('line_id', QVariant.Int, '', 10, 0)) fields.append(QgsField('point_id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter( fields.toList(), QgsWkbTypes.Point, layer.crs()) outFeature = QgsFeature() outFeature.setFields(fields) self.fid = 0 self.lineId = 0 self.pointId = 0 features = vector.features(layer) total = 100.0 / len(features) for current, f in enumerate(features): geom = f.geometry() if geom.isMultipart(): lines = geom.asMultiPolyline() for line in lines: for i in xrange(len(line) - 1): p1 = line[i] p2 = line[i + 1] (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform) (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform) self.buildLine(x1, y1, x2, y2, geoTransform, writer, outFeature) else: points = geom.asPolyline() for i in xrange(len(points) - 1): p1 = points[i] p2 = points[i + 1] (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform) (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform) self.buildLine(x1, y1, x2, y2, geoTransform, writer, outFeature) self.pointId = 0 self.lineId += 1 progress.setPercentage(int(current * total)) del writer
def outattrPrep(self, dlg, lyr): feat = QgsFeature() species = '' production = '' most = QDateTime.currentDateTimeUtc() rn = dlg.tableWidget.rowCount() for i in range(rn): if i==0: species = dlg.tableWidget.item(i, 0).text() production = dlg.tableWidget.item(i, 1).text() else: species = species + ' | ' + dlg.tableWidget.item(i, 0).text() production = production + ' | ' + dlg.tableWidget.item(i, 1).text() flds = lyr.dataProvider().fields() feat.setFields(flds, True) feat.setAttribute(feat.fieldNameIndex('localid'), dlg.lineEdit_3.text()) feat.setAttribute(feat.fieldNameIndex('code'), dlg.lineEdit_5.text()) feat.setAttribute(feat.fieldNameIndex('largescale'), dlg.comboBox_4.currentText()) feat.setAttribute(feat.fieldNameIndex('disease'), dlg.comboBox_2.currentText()) feat.setAttribute(feat.fieldNameIndex('animalno'), dlg.lineEdit_6.text()) feat.setAttribute(feat.fieldNameIndex('species'), species) feat.setAttribute(feat.fieldNameIndex('production'), production) feat.setAttribute(feat.fieldNameIndex('year'), dlg.lineEdit_4.text()) feat.setAttribute(feat.fieldNameIndex('status'), dlg.comboBox_3.currentText()) feat.setAttribute(feat.fieldNameIndex('suspect'), self.dateCheck(dlg.dateEdit.date())) feat.setAttribute(feat.fieldNameIndex('confirmation'), self.dateCheck(dlg.dateEdit_2.date())) feat.setAttribute(feat.fieldNameIndex('expiration'), self.dateCheck(dlg.dateEdit_3.date())) feat.setAttribute(feat.fieldNameIndex('notes'), dlg.textEdit.toPlainText()) feat.setAttribute(feat.fieldNameIndex('hrid'), self.hashIDer(most)) feat.setAttribute(feat.fieldNameIndex('timestamp'), most.toString('dd/MM/yyyy hh:mm:ss')) return feat
def processAlgorithm(self, feedback): extent = str(self.getParameterValue(self.EXTENT)).split(',') spacing = float(self.getParameterValue(self.SPACING)) inset = float(self.getParameterValue(self.INSET)) randomize = self.getParameterValue(self.RANDOMIZE) isSpacing = self.getParameterValue(self.IS_SPACING) crsId = self.getParameterValue(self.CRS) crs = QgsCoordinateReferenceSystem() crs.createFromUserInput(crsId) extent = QgsRectangle(float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3])) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QgsWkbTypes.Point, crs) if randomize: seed() area = extent.width() * extent.height() if isSpacing: pSpacing = spacing else: pSpacing = sqrt(area / spacing) f = QgsFeature() f.initAttributes(1) f.setFields(fields) count = 0 total = 100.0 / (area / pSpacing) y = extent.yMaximum() - inset extent_geom = QgsGeometry.fromRect(extent) extent_engine = QgsGeometry.createGeometryEngine(extent_geom.geometry()) extent_engine.prepareGeometry() while y >= extent.yMinimum(): x = extent.xMinimum() + inset while x <= extent.xMaximum(): if randomize: geom = QgsGeometry().fromPoint(QgsPoint( uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)), uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0)))) else: geom = QgsGeometry().fromPoint(QgsPoint(x, y)) if extent_engine.intersects(geom.geometry()): f.setAttribute('id', count) f.setGeometry(geom) writer.addFeature(f) x += pSpacing count += 1 feedback.setProgress(int(count * total)) y = y - pSpacing del writer
def __createMemoryLayer(self, layer_name, gtype, geometries, attributes, fNames, fTypes): """ Create a memory layer from parameters :param layer_name: name for the layer :param gtype: geometry type of the layer :param geometries: objects geometries :param attributes: objects attributes :param fNames: fields names :param fTypes: fields types """ layerList = QgsMapLayerRegistry.instance().mapLayersByName(layer_name) if layerList: QgsMapLayerRegistry.instance().removeMapLayers([layerList[0].id()]) epsg = self.canvas().mapRenderer().destinationCrs().authid() fieldsParam = "" for i in range(len(fNames)): fieldsParam += "&field=" + fNames[i] + ":" + fTypes[i] layer = QgsVectorLayer(gtype + "?crs=" + epsg + fieldsParam + "&index=yes", layer_name, "memory") QgsMapLayerRegistry.instance().addMapLayer(layer) layer.startEditing() for i in range(len(geometries)): feature = QgsFeature() feature.setGeometry(QgsGeometry().fromWkt(geometries[i])) fields = layer.pendingFields() feature.setFields(fields) for j in range(len(fNames)): feature.setAttribute(fNames[j], attributes[i][j]) layer.addFeature(feature) layer.commitChanges()
def add_gbif_occ_to_layer(occurrences, layer): features = [] dp = layer.dataProvider() for o in occurrences: attrs = [] for k in o.keys(): field_index = dp.fieldNameIndex(k) # Add a layer attribute for each JSON fields(if not already encountered) if field_index == -1: dp.addAttributes([QgsField(k, QtCore.QVariant.String)]) attrs.append({'attr': k, 'val': _get_field_value(o, k)}) feat = QgsFeature() # We should tell the feature which will be its fields # !! We need a variable !! Don't merge the next two lines !! myFields = dp.fields() feat.setFields(myFields) for d in attrs: feat.setAttribute(d['attr'], d['val']) feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(o['decimalLongitude'], o['decimalLatitude']))) features.append(feat) add_features_to_layer(layer, features)
def canvasPressEvent(self, mouseEvent): self.rubber.reset() pos = mouseEvent.pos() features = self.getFeatures(pos) nFeat = len(features) if nFeat < 2: layerNames = " , ".join([feature.layer.name() for feature in features]) self.iface.messageBar().pushMessage("Intersect It", "You need 2 features to proceed a simple intersection." " %u given (%s)" % (nFeat, layerNames), QgsMessageBar.WARNING, 3) return intersectionP = self.intersection(features, pos) if intersectionP == QgsPoint(0,0): self.iface.messageBar().pushMessage("Intersect It", "Objects do not intersect.", QgsMessageBar.WARNING, 2) return layer = self.checkLayer() if layer is None: return f = QgsFeature() initFields = layer.dataProvider().fields() f.setFields(initFields) f.initAttributes(initFields.size()) f.setGeometry(QgsGeometry().fromPoint(intersectionP)) layer.editBuffer().addFeature(f) layer.triggerRepaint()
def postionupdated(self, position, info): if not self.logging or not self.layer or not self.layerprovider: return feature = QgsFeature() feature.setFields(self.fields) for field in self.fields: name = field.name() if name == 'time': value = self.gps.gpsinfo('utcDateTime').toString(Qt.ISODate) elif name == 'localtime': value = QDateTime.currentDateTime().toString(Qt.ISODate) elif name == 'user': value = getpass.getuser() else: try: value = self.gps.gpsinfo(name) except AttributeError: continue feature[name] = value geom = QgsGeometry.fromPoint(position) feature.setGeometry(geom) self.featurecache.append(feature) if len(self.featurecache) > 5: self.layerprovider.addFeatures(self.featurecache) self.featurecache = []
def testExportFeatureFieldFormatter(self): """ Test exporting a feature with formatting fields """ # source layer source = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "parent", "memory") pr = source.dataProvider() pf1 = QgsFeature() pf1.setFields(source.fields()) pf1.setAttributes(["test1", 1]) pf2 = QgsFeature() pf2.setFields(source.fields()) pf2.setAttributes(["test2", 2]) assert pr.addFeatures([pf1, pf2]) setup = QgsEditorWidgetSetup('ValueMap', {"map": {"one": 1, "two": 2, "three": 3}}) source.setEditorWidgetSetup(1, setup) exporter = QgsJsonExporter() exporter.setVectorLayer(source) expected = """{ "type":"Feature", "id":0, "geometry":null, "properties":{ "fldtxt":"test1", "fldint":"one" } }""" self.assertEqual(exporter.exportFeature(pf1), expected)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context) minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context) bbox = source.sourceExtent() sourceIndex = QgsSpatialIndex(source, feedback) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, source.sourceCrs()) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount if pointCount else 1 index = QgsSpatialIndex() points = dict() random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPointXY(p) ids = sourceIndex.intersects(geom.buffer(5, 5).boundingBox()) if len(ids) > 0 and \ vector.checkMinDistance(p, index, minDistance, points): request = QgsFeatureRequest().setFilterFids(ids).setSubsetOfAttributes([]) for f in source.getFeatures(request): if feedback.isCanceled(): break tmpGeom = f.geometry() if geom.within(tmpGeom): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.insertFeature(f) points[nPoints] = p nPoints += 1 feedback.setProgress(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: feedback.pushInfo(self.tr('Could not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) return {self.OUTPUT: dest_id}
def testExportFieldAlias(self): """ Test exporting a feature with fields' alias """ # source layer source = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "parent", "memory") pr = source.dataProvider() pf1 = QgsFeature() pf1.setFields(source.fields()) pf1.setAttributes(["test1", 1]) pf2 = QgsFeature() pf2.setFields(source.fields()) pf2.setAttributes(["test2", 2]) assert pr.addFeatures([pf1, pf2]) source.setFieldAlias(0, "alias_fldtxt") source.setFieldAlias(1, "alias_fldint") exporter = QgsJsonExporter() exporter.setAttributeDisplayName(True) exporter.setVectorLayer(source) expected = """{ "geometry": null, "id": 0, "properties": { "alias_fldint": 1, "alias_fldtxt": "test1" }, "type": "Feature" }""" self.assertEqual(exporter.exportFeature(pf1, indent=2), expected)
def save(self): # observation f = QgsFeature() fields = self.lineLayer.dataProvider().fields() f.setFields(fields) f["id"] = self.id f["type"] = self.obsType f["x"] = self.point.x() f["y"] = self.point.y() f["observation"] = self.observation f["precision"] = self.precision f.setGeometry(self.geometry()) ok, l = self.lineLayer.dataProvider().addFeatures([f]) self.lineLayer.updateExtents() self.lineLayer.setCacheImage(None) self.lineLayer.triggerRepaint() self.lineLayer.featureAdded.emit(l[0].id()) # emit signal so feature is added to snapping index # center f = QgsFeature() fields = self.pointLayer.dataProvider().fields() f.setFields(fields) f["id"] = self.id f.setGeometry(QgsGeometry().fromPoint(self.point)) ok, l = self.pointLayer.dataProvider().addFeatures([f]) self.pointLayer.updateExtents() self.pointLayer.setCacheImage(None) self.pointLayer.triggerRepaint() self.pointLayer.featureAdded.emit(l[0].id()) # emit signal so feature is added to snapping index
def populate_catalogue_layer(self, catalogue): """ Populate the catalogue vector layer with data got from `catalogue` :param catalogue: a :class:`hmtk.seismicity.catalogue.Catalogue` instance """ vl = self.catalogue_layer pr = vl.dataProvider() vl.startEditing() # Set field types (the schema of the vector layer) fields = [] mock_attributes = ["_magnitude"] for key in catalogue.data.keys() + mock_attributes: if key in mock_attributes: key_norm = key[1:] else: key_norm = key if isinstance(key_norm, numpy.ndarray): fields.append(QgsField(key, QVariant.Double)) else: fields.append(QgsField(key, QVariant.String)) pr.addAttributes(fields) qgs_fields = QgsFields() for f in fields: qgs_fields.append(f) # Create the features features = [] for i in range(catalogue.get_number_events()): fet = QgsFeature() fet.setFields(qgs_fields) x = catalogue.data['longitude'][i] y = catalogue.data['latitude'][i] fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(x, y))) for key in catalogue.data: event_data = catalogue.data[key] if len(event_data): if isinstance(catalogue.data[key], numpy.ndarray): fet[key] = float(event_data[i]) else: fet[key] = str(event_data[i]) fet['_magnitude'] = fet['magnitude'] ** 2 features.append(fet) pr.addFeatures(features) vl.commitChanges() self.event_feature_ids = dict([ (f['eventID'], f.id()) for f in vl.getFeatures()]) # Set the canvas extent to avoid projection problems and to # pan to the loaded events vl.updateExtents()
def new_context(self): feature = QgsFeature() fields = QgsFields() fields.append(QgsField("testfield", QVariant.Int)) feature.setFields(fields, True) feature["testfield"] = 20 context = QgsExpressionContextUtils.createFeatureBasedContext(feature, fields) return context
def test_MatchesTrueForFields(self): feature = QgsFeature() fields = QgsFields() fields.append(QgsField("testfield", QVariant.Int)) feature.setFields(fields, True) feature["testfield"] = 20 style = QgsConditionalStyle('"testfield" = @value') assert style.matches(20, feature)
def accept(self): def updatefeautrefields(feature): for key, value in values.iteritems(): try: feature[key] = value except KeyError: continue return feature if not self.featureform.allpassing: self.bar.pushMessage("Missing fields", "Some fields are still required.", QgsMessageBar.WARNING, duration=2) return if not self.featureform: return if not self.featureform.accept(): return layer = self.featureform.form.QGISLayer before = QgsFeature(self.feature) before.setFields(self.fields, initAttributes=False) values, savedvalues = self.featureform.getvalues() after = QgsFeature(self.feature) after.setFields(self.fields, initAttributes=False) after = updatefeautrefields(after) layer.startEditing() if after.id() > 0: if self.project.historyenabled(layer): # Mark the old one as history before['status'] = 'H' after['status'] = 'C' after['dateedited'] = QDateTime.currentDateTime() after['editedby'] = getpass.getuser() layer.addFeature(after) layer.updateFeature(before) else: layer.updateFeature(after) else: layer.addFeature(after) featureform.savevalues(layer, savedvalues) saved = layer.commitChanges() if not saved: self.failedsave.emit(layer.commitErrors()) map(error, layer.commitErrors()) else: self.featureform.featuresaved(after, values) self.featuresaved.emit() self.accepted.emit() self.featureform = None
def randomize(self, inLayer, outPath, minimum, design, value): outFeat = QgsFeature() outFeat.initAttributes(1) if design == self.tr("unstratified"): ext = inLayer.extent() if inLayer.type() == QgsMapLayer.RasterLayer: points = self.simpleRandom( int(value), ext, ext.xMinimum(), ext.xMaximum(), ext.yMinimum(), ext.yMaximum()) else: points = self.vectorRandom( int(value), inLayer, ext.xMinimum(), ext.xMaximum(), ext.yMinimum(), ext.yMaximum()) else: points, featErrors = self.loopThruPolygons(inLayer, value, design) if featErrors: if len(featErrors) >= 10: err_msg = "Too many features couldn't be calculated due to conversion error. " err_msg += "Please check out message log for more info." msgLogInstance = QgsMessageLog.instance() msgLogInstance.logMessage("WARNING - fTools: " + self.tr("Random Points")) msgLogInstance.logMessage("The following feature ids should be checked.") for feat in featErrors: msgLogInstance.logMessage("Feature id: %d" % feat.id()) msgLogInstance.logMessage("End of features to be checked.") else: features_ids = [] for feat in featErrors: features_ids.append(unicode(feat.id())) erroneous_ids = ', '.join(features_ids) err_msg = "The following features IDs couldn't be calculated due to conversion error: %s" % erroneous_ids self.iface.messageBar().pushMessage("Errors", err_msg) if len(points): crs = self.iface.mapCanvas().mapRenderer().destinationCrs() if not crs.isValid(): crs = None fields = QgsFields() fields.append(QgsField("ID", QVariant.Int)) outFeat.setFields(fields) check = QFile(self.shapefileName) if check.exists(): if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName): return writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fields, QGis.WKBPoint, crs) idVar = 0 count = 70.00 add = (100.00 - 70.00) / len(points) for i in points: outFeat.setGeometry(i) outFeat.setAttribute(0, idVar) writer.addFeature(outFeat) idVar = idVar + 1 count = count + add self.progressBar.setValue(count) del writer return True return False
def test_MatchesTrueForFields(self): feature = QgsFeature() fields = QgsFields() fields.append(QgsField("testfield", QVariant.Int)) feature.setFields(fields, True) feature["testfield"] = 20 style = QgsConditionalStyle('"testfield" = @value') context = QgsExpressionContextUtils.createFeatureBasedContext(feature, fields) assert style.matches(20, context)
def test_replaced_with_qgsexpression_feature_attribute_lookup(): feature = QgsFeature() fields = QgsFields() fields.append(QgsField('mycol')) feature.setFields(fields) feature['mycol'] = 'testvalue' default = '[% "mycol" %]' outdefault = roam.defaults.default_value(default, feature, None) assert outdefault == 'testvalue'
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.VECTOR)) pointCount = int(self.getParameterValue(self.POINT_NUMBER)) minDistance = float(self.getParameterValue(self.MIN_DISTANCE)) bbox = layer.extent() idxLayer = vector.spatialindex(layer) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QgsWkbTypes.Point, layer.crs()) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount index = QgsSpatialIndex() points = dict() request = QgsFeatureRequest() random.seed() while nIterations < maxIterations and nPoints < pointCount: rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() pnt = QgsPoint(rx, ry) geom = QgsGeometry.fromPoint(pnt) ids = idxLayer.intersects(geom.buffer(5, 5).boundingBox()) if len(ids) > 0 and \ vector.checkMinDistance(pnt, index, minDistance, points): for i in ids: f = next(layer.getFeatures(request.setFilterFid(i))) tmpGeom = f.geometry() if geom.within(tmpGeom): 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 processAlgorithm(self, feedback): pointCount = int(self.getParameterValue(self.POINT_NUMBER)) minDistance = float(self.getParameterValue(self.MIN_DISTANCE)) extent = str(self.getParameterValue(self.EXTENT)).split(',') crsId = self.getParameterValue(self.CRS) crs = QgsCoordinateReferenceSystem() crs.createFromUserInput(crsId) xMin = float(extent[0]) xMax = float(extent[1]) yMin = float(extent[2]) yMax = float(extent[3]) extent = QgsGeometry().fromRect( QgsRectangle(xMin, yMin, xMax, yMax)) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QgsWkbTypes.Point, crs) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount index = QgsSpatialIndex() points = dict() random.seed() while nIterations < maxIterations and nPoints < pointCount: rx = xMin + (xMax - xMin) * random.random() ry = yMin + (yMax - yMin) * random.random() pnt = QgsPoint(rx, ry) geom = QgsGeometry.fromPoint(pnt) if geom.within(extent) and \ 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 feedback.setProgress(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 processAlgorithm(self, progress): extent = self.getParameterValue(self.EXTENT).split(',') xSpace = self.getParameterValue(self.STEP_X) ySpace = self.getParameterValue(self.STEP_Y) bbox = QgsRectangle( float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3])) mapCRS = iface.mapCanvas().mapSettings().destinationCrs() fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) fields.append(QgsField('xmin', QVariant.Double, '', 24, 15)) fields.append(QgsField('xmax', QVariant.Double, '', 24, 15)) fields.append(QgsField('ymin', QVariant.Double, '', 24, 15)) fields.append(QgsField('ymax', QVariant.Double, '', 24, 15)) fieldCount = 5 writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QgsWkbTypes.Polygon, mapCRS) feat = QgsFeature() feat.initAttributes(fieldCount) feat.setFields(fields) geom = QgsGeometry() idVar = 0 # counters for progressbar - update every 5% count = 0 count_max = (bbox.yMaximum() - bbox.yMinimum()) / ySpace count_update = count_max * 0.05 y = bbox.yMaximum() while y >= bbox.yMinimum(): x = bbox.xMinimum() while x <= bbox.xMaximum(): pt1 = QgsPoint(x, y) pt2 = QgsPoint(x + xSpace, y) pt3 = QgsPoint(x + xSpace, y - ySpace) pt4 = QgsPoint(x, y - ySpace) pt5 = QgsPoint(x, y) polygon = [[pt1, pt2, pt3, pt4, pt5]] feat.setGeometry(geom.fromPolygon(polygon)) feat.setAttribute(0, idVar) feat.setAttribute(1, x) feat.setAttribute(2, x + xSpace) feat.setAttribute(3, y - ySpace) feat.setAttribute(4, y) writer.addFeature(feat) idVar += 1 x = x + xSpace y = y - ySpace count += 1 if int(math.fmod(count, count_update)) == 0: progress.setPercentage(int(count / count_max * 100)) del writer
def testString(self): """ Test calculation of aggregates on string fields""" layer = QgsVectorLayer("Point?field=fldstring:string", "layer", "memory") pr = layer.dataProvider() values = ['cc', 'aaaa', 'bbbbbbbb', 'aaaa', 'eeee', '', 'eeee', '', 'dddd'] features = [] for v in values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([v]) features.append(f) assert pr.addFeatures(features) tests = [[QgsAggregateCalculator.Count, 'fldstring', 9], [QgsAggregateCalculator.CountDistinct, 'fldstring', 6], [QgsAggregateCalculator.CountMissing, 'fldstring', 2], [QgsAggregateCalculator.Min, 'fldstring', 'aaaa'], [QgsAggregateCalculator.Max, 'fldstring', 'eeee'], [QgsAggregateCalculator.StringMinimumLength, 'fldstring', 0], [QgsAggregateCalculator.StringMaximumLength, 'fldstring', 8], [QgsAggregateCalculator.ArrayAggregate, 'fldstring', values], ] agg = QgsAggregateCalculator(layer) for t in tests: val, ok = agg.calculate(t[0], t[1]) self.assertTrue(ok) self.assertEqual(val, t[2]) # test string concatenation agg.setDelimiter(',') self.assertEqual(agg.delimiter(), ',') val, ok = agg.calculate(QgsAggregateCalculator.StringConcatenate, 'fldstring') self.assertTrue(ok) self.assertEqual(val, 'cc,aaaa,bbbbbbbb,aaaa,eeee,,eeee,,dddd') val, ok = agg.calculate(QgsAggregateCalculator.StringConcatenateUnique, 'fldstring') self.assertTrue(ok) self.assertEqual(val, 'cc,aaaa,bbbbbbbb,eeee,,dddd') # bad tests - the following stats should not be calculatable for string fields for t in [QgsAggregateCalculator.Sum, QgsAggregateCalculator.Mean, QgsAggregateCalculator.Median, QgsAggregateCalculator.StDev, QgsAggregateCalculator.StDevSample, QgsAggregateCalculator.Range, QgsAggregateCalculator.Minority, QgsAggregateCalculator.Majority, QgsAggregateCalculator.FirstQuartile, QgsAggregateCalculator.ThirdQuartile, QgsAggregateCalculator.InterQuartileRange ]: val, ok = agg.calculate(t, 'fldstring') self.assertFalse(ok)
def create_layer(self, parameters, name, is_memory, dest_crs, layer_style=None): save_as = parameters.file_path file_format = parameters.file_format # save paramaters serialized = base64.b64encode(parameters.serialize(with_style=False, with_geometry=False)) # save geometry layer = QgsVectorLayer("MultiPolygon?crs=%s" % dest_crs.authid(), name, "memory") pr = layer.dataProvider() layer.startEditing() layer.addAttribute(QgsField("params", QVariant.String)) fet1 = QgsFeature(0) fet1.setFields(layer.fields()) fet1.setAttribute("params", str(serialized)[2:-1]) fet1.setGeometry(parameters.geometry) pr.addFeatures([fet1]) layer.commitChanges() # copy layer style if layer_style is not None: self.set_layer_style(layer, layer_style) if is_memory: return layer if os.path.isfile(save_as): # delete first if already exists if save_as.endswith(".shp"): QgsVectorFileWriter.deleteShapeFile(save_as) else: os.unlink(save_as) # create the disk layer QgsMessageLog.logMessage("Mask saving '{}' as {}".format(save_as, file_format), 'Extensions') error = QgsVectorFileWriter.writeAsVectorFormat(layer, save_as, "System", dest_crs, file_format) if error == 0: nlayer = QgsVectorLayer(save_as, name, "ogr") if not nlayer.dataProvider().isValid(): return None if not nlayer.hasGeometryType(): return None # force CRS nlayer.setCrs(dest_crs) # copy layer style layer_style = self.get_layer_style(layer) self.set_layer_style(nlayer, layer_style) return nlayer else: raise RuntimeError(error) return None
def testAggregate(self): """ Test aggregate calculation """ layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory") pr = layer.dataProvider() int_values = [4, 2, 3, 2, 5, None, 8] features = [] for i in int_values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([i]) features.append(f) assert pr.addFeatures(features) tests = [[QgsAggregateCalculator.Count, 6], [QgsAggregateCalculator.Sum, 24], [QgsAggregateCalculator.Mean, 4], [QgsAggregateCalculator.StDev, 2.0816], [QgsAggregateCalculator.StDevSample, 2.2803], [QgsAggregateCalculator.Min, 2], [QgsAggregateCalculator.Max, 8], [QgsAggregateCalculator.Range, 6], [QgsAggregateCalculator.Median, 3.5], [QgsAggregateCalculator.CountDistinct, 5], [QgsAggregateCalculator.CountMissing, 1], [QgsAggregateCalculator.FirstQuartile, 2], [QgsAggregateCalculator.ThirdQuartile, 5.0], [QgsAggregateCalculator.InterQuartileRange, 3.0] ] for t in tests: val, ok = layer.aggregate(t[0], 'fldint') self.assertTrue(ok) if isinstance(t[1], int): self.assertEqual(val, t[1]) else: self.assertAlmostEqual(val, t[1], 3) # test with parameters layer = QgsVectorLayer("Point?field=fldstring:string", "layer", "memory") pr = layer.dataProvider() string_values = ['this', 'is', 'a', 'test'] features = [] for s in string_values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([s]) features.append(f) assert pr.addFeatures(features) params = QgsAggregateCalculator.AggregateParameters() params.delimiter = ' ' val, ok = layer.aggregate(QgsAggregateCalculator.StringConcatenate, 'fldstring', params) self.assertTrue(ok) self.assertEqual(val, 'this is a test')
def processAlgorithm(self, parameters, context, feedback): pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context) minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context) crs = self.parameterAsCrs(parameters, self.TARGET_CRS, context) bbox = self.parameterAsExtent(parameters, self.EXTENT, context, crs) extent = QgsGeometry().fromRect(bbox) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, crs) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount if pointCount else 1 index = QgsSpatialIndex() points = dict() random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPointXY(p) if geom.within(extent) and \ vector.checkMinDistance(p, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.addFeature(f) points[nPoints] = p nPoints += 1 feedback.setProgress(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: feedback.pushInfo(self.tr('Could not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) return {self.OUTPUT: dest_id}
def processAlgorithm(self, progress): pointCount = int(self.getParameterValue(self.POINT_NUMBER)) minDistance = float(self.getParameterValue(self.MIN_DISTANCE)) extent = unicode(self.getParameterValue(self.EXTENT)).split(',') xMin = float(extent[0]) xMax = float(extent[1]) yMin = float(extent[2]) yMax = float(extent[3]) extent = QgsGeometry().fromRect( QgsRectangle(xMin, yMin, xMax, yMax)) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) mapCRS = iface.mapCanvas().mapSettings().destinationCrs() writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QGis.WKBPoint, mapCRS) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount if pointCount > 0 else 1 index = QgsSpatialIndex() points = dict() random.seed() while nIterations < maxIterations and nPoints < pointCount: rx = xMin + (xMax - xMin) * random.random() ry = yMin + (yMax - yMin) * random.random() pnt = QgsPoint(rx, ry) geom = QgsGeometry.fromPoint(pnt) if geom.within(extent) and \ 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 processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString( self.getParameterValue(self.INPUT_LAYER), context) fieldName = self.getParameterValue(self.FIELD_NAME) fieldType = self.TYPES[self.getParameterValue(self.FIELD_TYPE)] width = self.getParameterValue(self.FIELD_LENGTH) precision = self.getParameterValue(self.FIELD_PRECISION) newField = self.getParameterValue(self.NEW_FIELD) formula = self.getParameterValue(self.FORMULA) output = self.getOutputFromName(self.OUTPUT_LAYER) fields = layer.fields() if newField: fields.append(QgsField(fieldName, fieldType, '', width, precision)) writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs(), context) exp = QgsExpression(formula) da = QgsDistanceArea() da.setSourceCrs(layer.crs()) da.setEllipsoid(QgsProject.instance().ellipsoid()) exp.setGeomCalculator(da) exp.setDistanceUnits(QgsProject.instance().distanceUnits()) exp.setAreaUnits(QgsProject.instance().areaUnits()) exp_context = QgsExpressionContext( QgsExpressionContextUtils.globalProjectLayerScopes(layer)) if not exp.prepare(exp_context): raise GeoAlgorithmExecutionException( self.tr('Evaluation error: {0}').format(exp.evalErrorString())) outFeature = QgsFeature() outFeature.initAttributes(len(fields)) outFeature.setFields(fields) error = '' calculationSuccess = True features = QgsProcessingUtils.getFeatures(layer, context) total = 100.0 / layer.featureCount() if layer.featureCount() else 0 rownum = 1 for current, f in enumerate(features): rownum = current + 1 exp_context.setFeature(f) exp_context.lastScope().setVariable("row_number", rownum) value = exp.evaluate(exp_context) if exp.hasEvalError(): calculationSuccess = False error = exp.evalErrorString() break else: outFeature.setGeometry(f.geometry()) for fld in f.fields(): outFeature[fld.name()] = f[fld.name()] outFeature[fieldName] = value writer.addFeature(outFeature, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) del writer if not calculationSuccess: raise GeoAlgorithmExecutionException( self.tr('An error occurred while evaluating the calculation ' 'string:\n{0}').format(error))
def processAlgorithm(self, context, feedback): layer = QgsProcessingUtils.mapLayerFromString( self.getParameterValue(self.INPUT_VECTOR), context) startPoint = self.getParameterValue(self.START_POINT) strategy = self.getParameterValue(self.STRATEGY) travelCost = self.getParameterValue(self.TRAVEL_COST) directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) forwardValue = self.getParameterValue(self.VALUE_FORWARD) backwardValue = self.getParameterValue(self.VALUE_BACKWARD) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) speedFieldName = self.getParameterValue(self.SPEED_FIELD) defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) tolerance = self.getParameterValue(self.TOLERANCE) tmp = startPoint.split(',') startPoint = QgsPoint(float(tmp[0]), float(tmp[1])) directionField = -1 if directionFieldName is not None: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName is not None: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder( iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, [startPoint]) feedback.pushInfo(self.tr('Calculating service area...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = [] for i, v in enumerate(cost): if v > travelCost and tree[i] != -1: vertexId = graph.edge(tree[i]).outVertex() if cost[vertexId] <= travelCost: vertices.append(i) upperBoundary = [] lowerBoundary = [] for i in vertices: upperBoundary.append( graph.vertex(graph.edge(tree[i]).inVertex()).point()) lowerBoundary.append( graph.vertex(graph.edge(tree[i]).outVertex()).point()) feedback.pushInfo(self.tr('Writing results...')) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) writer = self.getOutputFromName(self.OUTPUT_POINTS).getVectorWriter( fields, QgsWkbTypes.MultiPoint, layer.crs(), context) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = startPoint.toString() writer.addFeature(feat) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = startPoint.toString() writer.addFeature(feat) del writer upperBoundary.append(startPoint) lowerBoundary.append(startPoint) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) writer = self.getOutputFromName(self.OUTPUT_POLYGON).getVectorWriter( fields, QgsWkbTypes.Polygon, layer.crs(), context) geom = geomUpper.convexHull() feat.setGeometry(geom) feat['type'] = 'upper' feat['start'] = startPoint.toString() writer.addFeature(feat) geom = geomLower.convexHull() feat.setGeometry(geom) feat['type'] = 'lower' feat['start'] = startPoint.toString() writer.addFeature(feat) del writer
def testFidSupport(self): # We do not use @unittest.expectedFailure since the test might actually succeed # on Linux 64bit with GDAL 1.11, where "long" is 64 bit... # GDAL 2.0 is guaranteed to properly support it on all platforms version_num = int(gdal.VersionInfo('VERSION_NUM')) if version_num < GDAL_COMPUTE_VERSION(2, 0, 0): return tmpfile = os.path.join(self.basetestpath, 'testFidSupport.sqlite') ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid']) lyr.CreateField(ogr.FieldDefn('strfield', ogr.OFTString)) lyr.CreateField(ogr.FieldDefn('intfield', ogr.OFTInteger)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(12) f.SetField(0, 'foo') f.SetField(1, 123) lyr.CreateFeature(f) f = None ds = None vl = QgsVectorLayer('{}'.format(tmpfile), 'test', 'ogr') self.assertEqual(len(vl.fields()), 3) got = [(f.attribute('fid'), f.attribute('strfield'), f.attribute('intfield')) for f in vl.getFeatures()] self.assertEqual(got, [(12, 'foo', 123)]) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("strfield = 'foo'"))] self.assertEqual(got, [(12, 'foo')]) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 12"))] self.assertEqual(got, [(12, 'foo')]) result = [f['strfield'] for f in vl.dataProvider().getFeatures(QgsFeatureRequest().setSubsetOfAttributes(['strfield'], vl.dataProvider().fields()))] self.assertEqual(result, ['foo']) result = [f['fid'] for f in vl.dataProvider().getFeatures(QgsFeatureRequest().setSubsetOfAttributes(['fid'], vl.dataProvider().fields()))] self.assertEqual(result, [12]) # Test that when the 'fid' field is not set, regular insertion is done f = QgsFeature() f.setFields(vl.fields()) f.setAttributes([None, 'automatic_id']) (res, out_f) = vl.dataProvider().addFeatures([f]) self.assertEqual(out_f[0].id(), 13) self.assertEqual(out_f[0].attribute('fid'), 13) self.assertEqual(out_f[0].attribute('strfield'), 'automatic_id') # Test that when the 'fid' field is set, it is really used to set the id f = QgsFeature() f.setFields(vl.fields()) f.setAttributes([9876543210, 'bar']) (res, out_f) = vl.dataProvider().addFeatures([f]) self.assertEqual(out_f[0].id(), 9876543210) self.assertEqual(out_f[0].attribute('fid'), 9876543210) self.assertEqual(out_f[0].attribute('strfield'), 'bar') got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'bar')]) self.assertTrue(vl.dataProvider().changeAttributeValues({9876543210: {1: 'baz'}})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baz')]) self.assertTrue(vl.dataProvider().changeAttributeValues({9876543210: {0: 9876543210, 1: 'baw'}})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baw')]) # Not allowed: changing the fid regular field self.assertTrue(vl.dataProvider().changeAttributeValues({9876543210: {0: 12, 1: 'baw'}})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baw')]) # Cannot delete fid self.assertFalse(vl.dataProvider().deleteAttributes([0])) # Delete first "genuine" attribute self.assertTrue(vl.dataProvider().deleteAttributes([1])) got = [(f.attribute('fid'), f.attribute('intfield')) for f in vl.dataProvider().getFeatures(QgsFeatureRequest().setFilterExpression("fid = 12"))] self.assertEqual(got, [(12, 123)])
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs()) endPoints = self.parameterAsSource(parameters, self.END_POINTS, context) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = endPoints.fields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) feat = QgsFeature() feat.setFields(fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(self.tr('Loading end points...')) request = QgsFeatureRequest() request.setDestinationCrs(network.sourceCrs()) features = endPoints.getFeatures(request) total = 100.0 / endPoints.featureCount() if endPoints.featureCount() else 0 points = [startPoint] source_attributes = {} i = 1 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue for p in f.geometry().vertices(): points.append(QgsPointXY(p)) source_attributes[i] = f.attributes() i += 1 feedback.setProgress(int(current * total)) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo(self.tr('Calculating shortest paths...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) nPoints = len(snappedPoints) total = 100.0 / nPoints if nPoints else 1 for i in range(1, nPoints): if feedback.isCanceled(): break idxEnd = graph.findVertex(snappedPoints[i]) if tree[idxEnd] == -1: msg = self.tr('There is no route from start point ({}) to end point ({}).'.format(startPoint.toString(), points[i].toString())) feedback.reportError(msg) # add feature with no geometry feat.clearGeometry() attrs = source_attributes[i] attrs.extend([NULL, points[i].toString()]) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) continue route = [graph.vertex(idxEnd).point()] cost = costs[idxEnd] current = idxEnd while current != idxStart: current = graph.edge(tree[current]).fromVertex() route.append(graph.vertex(current).point()) route.reverse() geom = QgsGeometry.fromPolylineXY(route) attrs = source_attributes[i] attrs.extend([startPoint.toString(), points[i].toString(), cost / multiplier]) feat.setAttributes(attrs) feat.setGeometry(geom) sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(i * total)) return {self.OUTPUT: dest_id}
def simulation_step(self): # TODO: Remove print print("Step start", self._t_now) future_time: datetime.datetime = self._t_now + datetime.timedelta(seconds=self._time_step) # Create the ignition points list and sort it by ignition date ignition_points: List[SpreadSimulator.IgnitionPoint] ignition_points = [SpreadSimulator.IgnitionPoint(feature=feature, x=feature.geometry().asPoint().x(), y=feature.geometry().asPoint().y(), ignition_date=parser.parse(feature.attributes()[1])) for feature in self._ignition_layer.getFeatures()] print(self._ignition_layer, ignition_points[0].ignition_date) ignition_points.sort() # Delete ignition points that ignited prior to the starting date of the simulation while (len(ignition_points) > 0) and (ignition_points[0].ignition_date < self._t_now): print("delete", ignition_points[0].ignition_date) ignition_points.pop(0) ignition_points = [point for point in ignition_points if self._t_now <= point.ignition_date < future_time] if len(ignition_points) > 0: # Compute the perimeter of the ignition point if it has to burn ignition_perimeters: List[List[SpreadSimulator.Point]] = list() for ignition_point in ignition_points: print(ignition_point.ignition_date) ignition_point.fuel_model = self._get_fire_model(ignition_point.x, ignition_point.y) perimeter = self.__ignite_point(ignition_point) if perimeter is not None: ignition_perimeters.append(perimeter) # Move perimeters to a QGIS layer fields = self._perimeter_layer.fields() raw_perimeters_layer: QgsVectorLayer = SpreadSimulator.__create_memory_layer('Polygon', 'raw_perimeters') for perimeter in ignition_perimeters: qgis_points: List[QgsPointXY] = [QgsPointXY(point.x, point.y) for point in perimeter] qgis_feature: QgsFeature = QgsFeature() qgis_geometry: QgsGeometry = QgsGeometry.fromPolygonXY([qgis_points]) # NOQA qgis_feature.setGeometry(qgis_geometry) qgis_data_provider: QgsVectorLayer = raw_perimeters_layer.dataProvider() qgis_data_provider.addFeature(qgis_feature) # NOQA # Fix geometries params = {'INPUT': raw_perimeters_layer, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:fixgeometries', params, feedback=feedback, is_child_algorithm=False) fixed_layer = result['OUTPUT'] print(result) params = {'INPUT': fixed_layer, 'OUTPUT': 'memory:', 'FIELD': None} feedback = QgsProcessingFeedback() result = processing.run('native:dissolve', params, feedback=feedback, is_child_algorithm=False) dissolved_layer = result['OUTPUT'] print(result) params = {'INPUT': dissolved_layer, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:multiparttosingleparts', params, feedback=feedback, is_child_algorithm=False) single_part_layer = result['OUTPUT'] params = {'INPUT': single_part_layer, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:forcerhr', params, feedback=feedback, is_child_algorithm=False) del fixed_layer del dissolved_layer del single_part_layer with edit(self._perimeter_layer): features = list() for feature in result['OUTPUT'].getFeatures(): feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPolygonXY(feature.geometry().asPolygon())) feat.setFields(fields) feat['datetime'] = future_time.strftime("%Y-%m-%dT%H:%M:%S%Z") features.append(feat) (_, _) = self._perimeter_layer.dataProvider().addFeatures(features) del result['OUTPUT'] del raw_perimeters_layer # Calculate the propagation perimeters propagation_perimeters: List[List[Any]] = list() # Filter the perimeters needed to propagate and convert to simple points features_of_perimeters_to_propagate = [feature for feature in self._perimeter_layer.getFeatures() if parser.parse(feature.attributes()[1]) == self._t_now] for feature in features_of_perimeters_to_propagate: # Get the geometries, if a polygon is a list its points define the polygon, if it is a list of lists the # first defines the polygon and the other lists the islands. The islands can have polygons inside and so on. # So a recursive function is implemented propagation_perimeter: List[Any] = list() geometry = feature.geometry().asPolygon() points: List[SpreadSimulator.Point] = [SpreadSimulator.Point(x=point.x(), y=point.y()) for point in geometry[0]] for point in points: point.fuel_model = self._get_fire_model(point.x, point.y) propagation_perimeter.append(points) if len(geometry) > 1: # Has islands # TODO: Recursion pass propagation_perimeters.append(propagation_perimeter) if len(propagation_perimeters) > 0: # Propagate the perimeters as points propagated_perimeters: List[List[Any]] = list() for perimeter in propagation_perimeters: propagated_perimeter: List[Any] = list() new_perimeter = self._propagate_perimeter(perimeter[0][-2::-1]) propagated_perimeter.append(new_perimeter) if len(perimeter) > 1: # Has islands # TODO: Recursion pass propagated_perimeters.append(propagated_perimeter) # Move perimeters to a QGIS layer fields = self._perimeter_layer.fields() raw_perimeters_layer: QgsVectorLayer = SpreadSimulator.__create_memory_layer('Polygon', 'raw_perimeters') for perimeter in propagated_perimeters: qgis_perimeter: List[List[Any]] = list() qgis_points: List[QgsPointXY] = [QgsPointXY(point.x, point.y) for point in perimeter[0]] qgis_feature: QgsFeature = QgsFeature() qgis_perimeter.append(qgis_points) if len(perimeter) > 1: # TODO: Recursion pass qgis_geometry: QgsGeometry = QgsGeometry.fromPolygonXY(qgis_perimeter) # NOQA qgis_feature.setGeometry(qgis_geometry) qgis_data_provider: QgsVectorLayer = raw_perimeters_layer.dataProvider() qgis_data_provider.addFeature(qgis_feature) # NOQA # Fix geometries params = {'INPUT': raw_perimeters_layer, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:fixgeometries', params, feedback=feedback, is_child_algorithm=False) fixed_layer = result['OUTPUT'] print(result) params = {'INPUT': fixed_layer, 'OUTPUT': 'memory:', 'FIELD': None} feedback = QgsProcessingFeedback() result = processing.run('native:dissolve', params, feedback=feedback, is_child_algorithm=False) dissolved_layer = result['OUTPUT'] print(result) params = {'INPUT': dissolved_layer, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:multiparttosingleparts', params, feedback=feedback, is_child_algorithm=False) single_part_layer = result['OUTPUT'] params = {'INPUT': single_part_layer, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:forcerhr', params, feedback=feedback, is_child_algorithm=False) del fixed_layer del dissolved_layer del single_part_layer with edit(self._perimeter_layer): features = list() for feature in result['OUTPUT'].getFeatures(): feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPolygonXY(feature.geometry().asPolygon())) feat.setFields(fields) feat['datetime'] = future_time.strftime("%Y-%m-%dT%H:%M:%S%Z") features.append(feat) (_, _) = self._perimeter_layer.dataProvider().addFeatures(features) del result['OUTPUT'] del raw_perimeters_layer # Update time self._t_now = future_time # TODO: Remove print print(self._t_now.strftime("%Y-%m-%dT%H:%M:%S%Z"))
def testExportFeatureRelations(self): """ Test exporting a feature with relations """ #parent layer parent = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=foreignkey:integer", "parent", "memory") pr = parent.dataProvider() pf1 = QgsFeature() pf1.setFields(parent.fields()) pf1.setAttributes(["test1", 67, 123]) pf2 = QgsFeature() pf2.setFields(parent.fields()) pf2.setAttributes(["test2", 68, 124]) assert pr.addFeatures([pf1, pf2]) #child layer child = QgsVectorLayer( "Point?field=x:string&field=y:integer&field=z:integer", "referencedlayer", "memory") pr = child.dataProvider() f1 = QgsFeature() f1.setFields(child.fields()) f1.setAttributes(["foo", 123, 321]) f2 = QgsFeature() f2.setFields(child.fields()) f2.setAttributes(["bar", 123, 654]) f3 = QgsFeature() f3.setFields(child.fields()) f3.setAttributes(["foobar", 124, 554]) assert pr.addFeatures([f1, f2, f3]) QgsProject.instance().addMapLayers([child, parent]) rel = QgsRelation() rel.setId('rel1') rel.setName('relation one') rel.setReferencingLayer(child.id()) rel.setReferencedLayer(parent.id()) rel.addFieldPair('y', 'foreignkey') QgsProject.instance().relationManager().addRelation(rel) exporter = QgsJsonExporter() exporter.setVectorLayer(parent) self.assertEqual(exporter.vectorLayer(), parent) exporter.setIncludeRelated(True) self.assertEqual(exporter.includeRelated(), True) expected = """{ "type":"Feature", "id":0, "geometry":null, "properties":{ "fldtxt":"test1", "fldint":67, "foreignkey":123, "relation one":[{"x":"foo", "y":123, "z":321}, {"x":"bar", "y":123, "z":654}] } }""" self.assertEqual(exporter.exportFeature(pf1), expected) expected = """{ "type":"Feature", "id":0, "geometry":null, "properties":{ "fldtxt":"test2", "fldint":68, "foreignkey":124, "relation one":[{"x":"foobar", "y":124, "z":554}] } }""" self.assertEqual(exporter.exportFeature(pf2), expected) # with field formatter setup = QgsEditorWidgetSetup('ValueMap', {"map": {"apples": 123, "bananas": 124}}) child.setEditorWidgetSetup(1, setup) expected = """{ "type":"Feature", "id":0, "geometry":null, "properties":{ "fldtxt":"test1", "fldint":67, "foreignkey":123, "relation one":[{"x":"foo", "y":"apples", "z":321}, {"x":"bar", "y":"apples", "z":654}] } }""" self.assertEqual(exporter.exportFeature(pf1), expected) # test excluding related attributes exporter.setIncludeRelated(False) self.assertEqual(exporter.includeRelated(), False) expected = """{ "type":"Feature", "id":0, "geometry":null, "properties":{ "fldtxt":"test2", "fldint":68, "foreignkey":124 } }""" self.assertEqual(exporter.exportFeature(pf2), expected) # test without vector layer set exporter.setIncludeRelated(True) exporter.setVectorLayer(None) expected = """{ "type":"Feature", "id":0, "geometry":null, "properties":{ "fldtxt":"test2", "fldint":68, "foreignkey":124 } }""" self.assertEqual(exporter.exportFeature(pf2), expected)
def processAlgorithm(self, feedback): 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, QgsWkbTypes.Point, layer.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 = next( layer.getFeatures( request.setFilterFid(fid).setSubsetOfAttributes([]))) fGeom = 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 feedback.setProgress(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 processAlgorithm(self, feedback): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.VECTOR)) groupField = self.getParameterValue(self.GROUP_FIELD) orderField = self.getParameterValue(self.ORDER_FIELD) dateFormat = str(self.getParameterValue(self.DATE_FORMAT)) #gap = int(self.getParameterValue(self.GAP_PERIOD)) dirName = self.getOutputValue(self.OUTPUT_TEXT) fields = QgsFields() fields.append(QgsField('group', QVariant.String, '', 254, 0)) fields.append(QgsField('begin', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) writer = self.getOutputFromName(self.OUTPUT_LINES).getVectorWriter( fields, QgsWkbTypes.LineString, layer.crs()) points = dict() features = vector.features(layer) total = 100.0 / len(features) for current, f in enumerate(features): point = f.geometry().asPoint() group = f[groupField] order = f[orderField] if dateFormat != '': order = datetime.strptime(str(order), dateFormat) if group in points: points[group].append((order, point)) else: points[group] = [(order, point)] feedback.setProgress(int(current * total)) feedback.setProgress(0) da = QgsDistanceArea() current = 0 total = 100.0 / len(points) for group, vertices in list(points.items()): vertices.sort() f = QgsFeature() f.initAttributes(len(fields)) f.setFields(fields) f['group'] = group f['begin'] = vertices[0][0] f['end'] = vertices[-1][0] fileName = os.path.join(dirName, '%s.txt' % group) with open(fileName, 'w') as fl: fl.write('angle=Azimuth\n') fl.write('heading=Coordinate_System\n') fl.write('dist_units=Default\n') line = [] i = 0 for node in vertices: line.append(node[1]) if i == 0: fl.write('startAt=%f;%f;90\n' % (node[1].x(), node[1].y())) fl.write('survey=Polygonal\n') fl.write('[data]\n') else: angle = line[i - 1].azimuth(line[i]) distance = da.measureLine(line[i - 1], line[i]) fl.write('%f;%f;90\n' % (angle, distance)) i += 1 f.setGeometry(QgsGeometry.fromPolyline(line)) writer.addFeature(f) current += 1 feedback.setProgress(int(current * total)) del writer
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT_VECTOR, context) raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context) rasterPath = raster_layer.source() rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly) geoTransform = rasterDS.GetGeoTransform() rasterDS = None fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) fields.append(QgsField('line_id', QVariant.Int, '', 10, 0)) fields.append(QgsField('point_id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, raster_layer.crs()) outFeature = QgsFeature() outFeature.setFields(fields) self.fid = 0 self.lineId = 0 self.pointId = 0 features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs(), context.transformContext())) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break geom = f.geometry() if geom.isMultipart(): lines = geom.asMultiPolyline() for line in lines: for i in range(len(line) - 1): p1 = line[i] p2 = line[i + 1] (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform) (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform) self.buildLine(x1, y1, x2, y2, geoTransform, sink, outFeature) else: points = geom.asPolyline() for i in range(len(points) - 1): p1 = points[i] p2 = points[i + 1] (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform) (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform) self.buildLine(x1, y1, x2, y2, geoTransform, sink, outFeature) self.pointId = 0 self.lineId += 1 feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context) expression = QgsExpression( self.parameterAsString(parameters, self.EXPRESSION, context)) if expression.hasParserError(): raise QgsProcessingException(expression.parserErrorString()) expressionContext = self.createExpressionContext( parameters, context, source) expression.prepare(expressionContext) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs(), context.transformContext()) da.setEllipsoid(context.project().ellipsoid()) total = 100.0 / source.featureCount() if source.featureCount() else 0 current_progress = 0 for current, f in enumerate(source.getFeatures()): if feedback.isCanceled(): break if not f.hasGeometry(): continue current_progress = total * current feedback.setProgress(current_progress) expressionContext.setFeature(f) value = expression.evaluate(expressionContext) if expression.hasEvalError(): feedback.pushInfo( self.tr('Evaluation error for feature ID {}: {}').format( f.id(), expression.evalErrorString())) continue fGeom = f.geometry() engine = QgsGeometry.createGeometryEngine(fGeom.constGet()) engine.prepareGeometry() bbox = fGeom.boundingBox() if strategy == 0: pointCount = int(value) else: pointCount = int(round(value * da.measureArea(fGeom))) if pointCount == 0: feedback.pushInfo( "Skip feature {} as number of points for it is 0.".format( f.id())) continue index = QgsSpatialIndex() points = dict() nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 feature_total = total / pointCount if pointCount else 1 random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPointXY(p) if engine.contains(geom.constGet()) and \ vector.checkMinDistance(p, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.insertFeature(f) points[nPoints] = p nPoints += 1 feedback.setProgress(current_progress + int(nPoints * feature_total)) nIterations += 1 if nPoints < pointCount: feedback.pushInfo( self.tr('Could not generate requested number of random ' 'points. Maximum number of attempts exceeded.')) feedback.setProgress(100) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT_VECTOR, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT_VECTOR)) raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context) rasterPath = raster_layer.source() rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly) geoTransform = rasterDS.GetGeoTransform() fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) fields.append(QgsField('poly_id', QVariant.Int, '', 10, 0)) fields.append(QgsField('point_id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, raster_layer.crs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) outFeature = QgsFeature() outFeature.setFields(fields) fid = 0 polyId = 0 pointId = 0 features = source.getFeatures(QgsFeatureRequest().setDestinationCrs( raster_layer.crs(), context.transformContext())) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue geom = f.geometry() bbox = geom.boundingBox() xMin = bbox.xMinimum() xMax = bbox.xMaximum() yMin = bbox.yMinimum() yMax = bbox.yMaximum() (startRow, startColumn) = raster.mapToPixel(xMin, yMax, geoTransform) (endRow, endColumn) = raster.mapToPixel(xMax, yMin, geoTransform) # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(geom.constGet()) engine.prepareGeometry() for row in range(startRow, endRow + 1): for col in range(startColumn, endColumn + 1): if feedback.isCanceled(): break (x, y) = raster.pixelToMap(row, col, geoTransform) point = QgsPoint(x, y) if engine.contains(point): outFeature.setGeometry(QgsGeometry(point)) outFeature['id'] = fid outFeature['poly_id'] = polyId outFeature['point_id'] = pointId fid += 1 pointId += 1 sink.addFeature(outFeature, QgsFeatureSink.FastInsert) pointId = 0 polyId += 1 feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): spacing = self.parameterAsDouble(parameters, self.SPACING, context) inset = self.parameterAsDouble(parameters, self.INSET, context) randomize = self.parameterAsBool(parameters, self.RANDOMIZE, context) isSpacing = self.parameterAsBool(parameters, self.IS_SPACING, context) crs = self.parameterAsCrs(parameters, self.CRS, context) extent = self.parameterAsExtent(parameters, self.EXTENT, context, crs) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, crs) if randomize: seed() area = extent.width() * extent.height() if isSpacing: pSpacing = spacing else: pSpacing = sqrt(area / spacing) f = QgsFeature() f.initAttributes(1) f.setFields(fields) count = 0 total = 100.0 / (area / pSpacing) y = extent.yMaximum() - inset extent_geom = QgsGeometry.fromRect(extent) extent_engine = QgsGeometry.createGeometryEngine( extent_geom.constGet()) extent_engine.prepareGeometry() while y >= extent.yMinimum(): x = extent.xMinimum() + inset while x <= extent.xMaximum(): if feedback.isCanceled(): break if randomize: geom = QgsGeometry().fromPointXY( QgsPointXY( uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)), uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0)))) else: geom = QgsGeometry().fromPointXY(QgsPointXY(x, y)) if extent_engine.intersects(geom.constGet()): f.setAttribute('id', count) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) x += pSpacing count += 1 feedback.setProgress(int(count * total)) y = y - pSpacing return {self.OUTPUT: dest_id}
def compute(self, bound, xOffset, yOffset, polygon): crs = None layer = ftools_utils.getMapLayerByName( unicode(self.inShape.currentText())) if self.angle.value() != 0.0: bound = self.initRotation(bound) if layer is None: crs = self.iface.mapCanvas().mapRenderer().destinationCrs() else: crs = layer.crs() if not crs.isValid(): crs = None fields = QgsFields() fields.append(QgsField("ID", QVariant.Int)) fieldCount = 1 if polygon: fields.append(QgsField("X_MIN", QVariant.Double)) fields.append(QgsField("X_MAX", QVariant.Double)) fields.append(QgsField("Y_MIN", QVariant.Double)) fields.append(QgsField("Y_MAX", QVariant.Double)) fieldCount = 5 check = QFile(self.shapefileName) if check.exists(): if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName): return writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fields, QGis.WKBPolygon, crs) else: fields.append(QgsField("COORD", QVariant.Double)) fieldCount = 2 check = QFile(self.shapefileName) if check.exists(): if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName): return writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fields, QGis.WKBLineString, crs) outFeat = QgsFeature() outFeat.initAttributes(fieldCount) outFeat.setFields(fields) outGeom = QgsGeometry() idVar = 0 self.progressBar.setValue(0) if not polygon: # counters for progressbar - update every 5% count = 0 count_max = (bound.yMaximum() - bound.yMinimum()) / yOffset count_update = count_max * 0.10 y = bound.yMaximum() while y >= bound.yMinimum(): pt1 = QgsPoint(bound.xMinimum(), y) pt2 = QgsPoint(bound.xMaximum(), y) if self.angle.value() != 0.0: self.rotatePoint(pt1) self.rotatePoint(pt2) line = [pt1, pt2] outFeat.setGeometry(outGeom.fromPolyline(line)) outFeat.setAttribute(0, idVar) outFeat.setAttribute(1, y) writer.addFeature(outFeat) y = y - yOffset idVar = idVar + 1 count += 1 if int(math.fmod(count, count_update)) == 0: prog = int(count / count_max * 50) self.progressBar.setValue(prog) self.progressBar.setValue(50) # counters for progressbar - update every 5% count = 0 count_max = (bound.xMaximum() - bound.xMinimum()) / xOffset count_update = count_max * 0.10 x = bound.xMinimum() while x <= bound.xMaximum(): pt1 = QgsPoint(x, bound.yMaximum()) pt2 = QgsPoint(x, bound.yMinimum()) if self.angle.value() != 0.0: self.rotatePoint(pt1) self.rotatePoint(pt2) line = [pt1, pt2] outFeat.setGeometry(outGeom.fromPolyline(line)) outFeat.setAttribute(0, idVar) outFeat.setAttribute(1, x) writer.addFeature(outFeat) x = x + xOffset idVar = idVar + 1 count += 1 if int(math.fmod(count, count_update)) == 0: prog = 50 + int(count / count_max * 50) self.progressBar.setValue(prog) else: # counters for progressbar - update every 5% count = 0 count_max = (bound.yMaximum() - bound.yMinimum()) / yOffset count_update = count_max * 0.05 y = bound.yMaximum() while y >= bound.yMinimum(): x = bound.xMinimum() while x <= bound.xMaximum(): pt1 = QgsPoint(x, y) pt2 = QgsPoint(x + xOffset, y) pt3 = QgsPoint(x + xOffset, y - yOffset) pt4 = QgsPoint(x, y - yOffset) pt5 = QgsPoint(x, y) if self.angle.value() != 0.0: self.rotatePoint(pt1) self.rotatePoint(pt2) self.rotatePoint(pt3) self.rotatePoint(pt4) self.rotatePoint(pt5) polygon = [[pt1, pt2, pt3, pt4, pt5]] outFeat.setGeometry(outGeom.fromPolygon(polygon)) outFeat.setAttribute(0, idVar) outFeat.setAttribute(1, x) outFeat.setAttribute(2, x + xOffset) outFeat.setAttribute(3, y - yOffset) outFeat.setAttribute(4, y) writer.addFeature(outFeat) idVar = idVar + 1 x = x + xOffset y = y - yOffset count += 1 if int(math.fmod(count, count_update)) == 0: prog = int(count / count_max * 100) self.progressBar.setValue(100) del writer
def processAlgorithm(self, feedback): layer = dataobjects.getLayerFromString( self.getParameterValue(self.INPUT_VECTOR)) startPoint = self.getParameterValue(self.START_POINT) endPoint = self.getParameterValue(self.END_POINT) strategy = self.getParameterValue(self.STRATEGY) directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) forwardValue = self.getParameterValue(self.VALUE_FORWARD) backwardValue = self.getParameterValue(self.VALUE_BACKWARD) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) speedFieldName = self.getParameterValue(self.SPEED_FIELD) defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) tolerance = self.getParameterValue(self.TOLERANCE) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter( fields.toList(), QgsWkbTypes.LineString, layer.crs()) tmp = startPoint.split(',') startPoint = QgsPoint(float(tmp[0]), float(tmp[1])) tmp = endPoint.split(',') endPoint = QgsPoint(float(tmp[0]), float(tmp[1])) directionField = -1 if directionFieldName is not None: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName is not None: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder( iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, [startPoint, endPoint]) feedback.pushInfo(self.tr('Calculating shortest path...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) idxEnd = graph.findVertex(snappedPoints[1]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: raise GeoAlgorithmExecutionException( self.tr('There is no route from start point to end point.')) route = [] cost = 0.0 current = idxEnd while current != idxStart: cost += graph.edge(tree[current]).cost(0) route.append( graph.vertex(graph.edge(tree[current]).inVertex()).point()) current = graph.edge(tree[current]).outVertex() route.append(snappedPoints[0]) route.reverse() self.setOutputValue(self.TRAVEL_COST, cost / multiplier) feedback.pushInfo(self.tr('Writing results...')) geom = QgsGeometry.fromPolyline(route) feat = QgsFeature() feat.setFields(fields) feat['start'] = startPoint.toString() feat['end'] = endPoint.toString() feat['cost'] = cost / multiplier feat.setGeometry(geom) writer.addFeature(feat) del writer
def testDuplicateFeature(self): """ test duplicating a feature """ project = QgsProject().instance() # LAYERS # - add first layer (parent) layer1 = QgsVectorLayer("Point?field=fldtxt:string&field=pkid:integer", "parentlayer", "memory") # > check first layer (parent) self.assertTrue(layer1.isValid()) # - set the value for the copy layer1.setDefaultValueDefinition(1, QgsDefaultValue("rand(1000,2000)")) # > check first layer (parent) self.assertTrue(layer1.isValid()) # - add second layer (child) layer2 = QgsVectorLayer("Point?field=fldtxt:string&field=id:integer&field=foreign_key:integer", "childlayer", "memory") # > check second layer (child) self.assertTrue(layer2.isValid()) # - add layers project.addMapLayers([layer1, layer2]) # FEATURES # - add 2 features on layer1 (parent) l1f1orig = QgsFeature() l1f1orig.setFields(layer1.fields()) l1f1orig.setAttributes(["F_l1f1", 100]) l1f2orig = QgsFeature() l1f2orig.setFields(layer1.fields()) l1f2orig.setAttributes(["F_l1f2", 101]) # > check by adding features self.assertTrue(layer1.dataProvider().addFeatures([l1f1orig, l1f2orig])) # add 4 features on layer2 (child) l2f1orig = QgsFeature() l2f1orig.setFields(layer2.fields()) l2f1orig.setAttributes(["F_l2f1", 201, 100]) l2f2orig = QgsFeature() l2f2orig.setFields(layer2.fields()) l2f2orig.setAttributes(["F_l2f2", 202, 100]) l2f3orig = QgsFeature() l2f3orig.setFields(layer2.fields()) l2f3orig.setAttributes(["F_l2f3", 203, 100]) l2f4orig = QgsFeature() l2f4orig.setFields(layer2.fields()) l2f4orig.setAttributes(["F_l2f4", 204, 101]) # > check by adding features self.assertTrue(layer2.dataProvider().addFeatures([l2f1orig, l2f2orig, l2f3orig, l2f4orig])) # RELATION # - create the relationmanager relMgr = project.relationManager() # - create the relation rel = QgsRelation() rel.setId('rel1') rel.setName('childrel') rel.setReferencingLayer(layer2.id()) rel.setReferencedLayer(layer1.id()) rel.addFieldPair('foreign_key', 'pkid') rel.setStrength(QgsRelation.Composition) # > check relation self.assertTrue(rel.isValid()) # - add relation relMgr.addRelation(rel) # > check if referencedLayer is layer1 self.assertEqual(rel.referencedLayer(), layer1) # > check if referencingLayer is layer2 self.assertEqual(rel.referencingLayer(), layer2) # > check if the layers are correct in relation when loading from relationManager relations = project.relationManager().relations() relation = relations[list(relations.keys())[0]] # > check if referencedLayer is layer1 self.assertEqual(relation.referencedLayer(), layer1) # > check if referencingLayer is layer2 self.assertEqual(relation.referencingLayer(), layer2) # > check the relatedfeatures ''' # testoutput 1 print( "\nAll Features and relations") featit=layer1.getFeatures() f=QgsFeature() while featit.nextFeature(f): print( f.attributes()) childFeature = QgsFeature() relfeatit=rel.getRelatedFeatures(f) while relfeatit.nextFeature(childFeature): print( childFeature.attributes() ) print( "\n--------------------------") print( "\nFeatures on layer1") for f in layer1.getFeatures(): print( f.attributes() ) print( "\nFeatures on layer2") for f in layer2.getFeatures(): print( f.attributes() ) ''' # DUPLICATION # - duplicate feature l1f1orig with children layer1.startEditing() results = QgsVectorLayerUtils.duplicateFeature(layer1, l1f1orig, project, 0) # > check if name is name of duplicated (pk is different) result_feature = results[0] self.assertEqual(result_feature.attribute('fldtxt'), l1f1orig.attribute('fldtxt')) # > check duplicated child layer result_layer = results[1].layers()[0] self.assertEqual(result_layer, layer2) # > check duplicated child features self.assertTrue(results[1].duplicatedFeatures(result_layer)) ''' # testoutput 2 print( "\nFeatures on layer1 (after duplication)") for f in layer1.getFeatures(): print( f.attributes() ) print( "\nFeatures on layer2 (after duplication)") for f in layer2.getFeatures(): print( f.attributes() ) print( "\nAll Features and relations") featit=layer1.getFeatures() f=QgsFeature() while featit.nextFeature(f): print( f.attributes()) childFeature = QgsFeature() relfeatit=rel.getRelatedFeatures(f) while relfeatit.nextFeature(childFeature): print( childFeature.attributes() ) ''' # > compare text of parent feature self.assertEqual(result_feature.attribute('fldtxt'), l1f1orig.attribute('fldtxt')) # - create copyValueList childFeature = QgsFeature() relfeatit = rel.getRelatedFeatures(result_feature) copyValueList = [] while relfeatit.nextFeature(childFeature): copyValueList.append(childFeature.attribute('fldtxt')) # - create origValueList childFeature = QgsFeature() relfeatit = rel.getRelatedFeatures(l1f1orig) origValueList = [] while relfeatit.nextFeature(childFeature): origValueList.append(childFeature.attribute('fldtxt')) # - check if the ids are still the same self.assertEqual(copyValueList, origValueList)
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) if network is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) startPoints = self.parameterAsSource(parameters, self.START_POINTS, context) if startPoints is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.START_POINTS)) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) include_bounds = True # default to true to maintain 3.0 API if self.INCLUDE_BOUNDS in parameters: include_bounds = self.parameterAsBool(parameters, self.INCLUDE_BOUNDS, context) fields = startPoints.fields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Loading start points…')) request = QgsFeatureRequest() request.setDestinationCrs(network.sourceCrs(), context.transformContext()) features = startPoints.getFeatures(request) total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0 points = [] source_attributes = {} i = 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue for p in f.geometry().vertices(): points.append(QgsPointXY(p)) source_attributes[i] = f.attributes() i += 1 feedback.setProgress(int(current * total)) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Building graph…')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Calculating service areas…')) graph = builder.graph() (point_sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.MultiPoint, network.sourceCrs()) (line_sink, line_dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LINES, context, fields, QgsWkbTypes.MultiLineString, network.sourceCrs()) total = 100.0 / len(snappedPoints) if snappedPoints else 1 for i, p in enumerate(snappedPoints): if feedback.isCanceled(): break idxStart = graph.findVertex(snappedPoints[i]) origPoint = points[i].toString() tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = set() area_points = [] lines = [] for vertex, start_vertex_cost in enumerate(cost): inbound_edge_index = tree[vertex] if inbound_edge_index == -1 and vertex != idxStart: # unreachable vertex continue if start_vertex_cost > travelCost: # vertex is too expensive, discard continue vertices.add(vertex) start_point = graph.vertex(vertex).point() # find all edges coming from this vertex for edge_id in graph.vertex(vertex).outgoingEdges(): edge = graph.edge(edge_id) end_vertex_cost = start_vertex_cost + edge.cost(0) end_point = graph.vertex(edge.toVertex()).point() if end_vertex_cost <= travelCost: # end vertex is cheap enough to include vertices.add(edge.toVertex()) lines.append([start_point, end_point]) else: # travelCost sits somewhere on this edge, interpolate position interpolated_end_point = QgsGeometryUtils.interpolatePointOnLineByValue(start_point.x(), start_point.y(), start_vertex_cost, end_point.x(), end_point.y(), end_vertex_cost, travelCost) area_points.append(interpolated_end_point) lines.append([start_point, interpolated_end_point]) for v in vertices: area_points.append(graph.vertex(v).point()) feat = QgsFeature() if point_sink is not None: geomPoints = QgsGeometry.fromMultiPointXY(area_points) feat.setGeometry(geomPoints) attrs = source_attributes[i] attrs.extend(['within', origPoint]) feat.setAttributes(attrs) point_sink.addFeature(feat, QgsFeatureSink.FastInsert) if include_bounds: upperBoundary = [] lowerBoundary = [] vertices = [] for vertex, c in enumerate(cost): if c > travelCost and tree[vertex] != -1: vertexId = graph.edge(tree[vertex]).fromVertex() if cost[vertexId] <= travelCost: vertices.append(vertex) for v in vertices: upperBoundary.append(graph.vertex(graph.edge(tree[v]).toVertex()).point()) lowerBoundary.append(graph.vertex(graph.edge(tree[v]).fromVertex()).point()) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) feat.setGeometry(geomUpper) attrs[-2] = 'upper' feat.setAttributes(attrs) point_sink.addFeature(feat, QgsFeatureSink.FastInsert) feat.setGeometry(geomLower) attrs[-2] = 'lower' feat.setAttributes(attrs) point_sink.addFeature(feat, QgsFeatureSink.FastInsert) if line_sink is not None: geom_lines = QgsGeometry.fromMultiPolylineXY(lines) feat.setGeometry(geom_lines) attrs = source_attributes[i] attrs.extend(['lines', origPoint]) feat.setAttributes(attrs) line_sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(i * total)) results = {} if point_sink is not None: results[self.OUTPUT] = dest_id if line_sink is not None: results[self.OUTPUT_LINES] = line_dest_id return results
def compute(self, line1, line2, field1, field2, outPath, progressBar): layer1 = ftools_utils.getVectorLayerByName(line1) provider1 = layer1.dataProvider() fieldList = ftools_utils.getFieldList(layer1) index1 = provider1.fieldNameIndex(field1) field1 = fieldList[index1] field1.setName(unicode(field1.name()) + "_1") layer2 = ftools_utils.getVectorLayerByName(line2) provider2 = layer2.dataProvider() fieldList = ftools_utils.getFieldList(layer2) index2 = provider2.fieldNameIndex(field2) field2 = fieldList[index2] field2.setName(unicode(field2.name()) + "_2") fieldList = QgsFields() fieldList.append(field1) fieldList.append(field2) sRs = provider1.crs() check = QFile(self.shapefileName) if check.exists(): if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName): return writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fieldList, QGis.WKBPoint, sRs) inFeat = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() outFields = QgsFields() outFields.append(field1) outFields.append(field2) outFeat.setFields(outFields) start = 15.00 add = 85.00 / layer1.featureCount() index = ftools_utils.createIndex(provider2) singlelayer_tempList = [] fit1 = provider1.getFeatures(QgsFeatureRequest().setSubsetOfAttributes( [index1])) while fit1.nextFeature(inFeat): inGeom = inFeat.geometry() v1 = inFeat.attributes()[index1] lineList = index.intersects(inGeom.boundingBox()) for i in lineList: provider2.getFeatures(QgsFeatureRequest().setFilterFid( int(i)).setSubsetOfAttributes([index2 ])).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) v2 = inFeatB.attributes()[index2] if inGeom.intersects(tmpGeom): tempGeom = inGeom.intersection(tmpGeom) if tempGeom.type() == QGis.Point: tempList = [] if tempGeom.isMultipart(): tempList = tempGeom.asMultiPoint() else: tempList.append(tempGeom.asPoint()) for j in tempList: # if same layer, avoid insert duplicated points if line1 == line2: if j not in singlelayer_tempList: singlelayer_tempList.append(j) outFeat.setGeometry(tempGeom.fromPoint(j)) outFeat.setAttribute(0, v1) outFeat.setAttribute(1, v2) writer.addFeature(outFeat) else: outFeat.setGeometry(tempGeom.fromPoint(j)) outFeat.setAttribute(0, v1) outFeat.setAttribute(1, v2) writer.addFeature(outFeat) start = start + add progressBar.setValue(start) del writer
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromPoint', 'Building graph…')) snappedPoints = director.makeGraph(builder, [startPoint], feedback) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromPoint', 'Calculating service area…')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = [] for i, v in enumerate(cost): if v > travelCost and tree[i] != -1: vertexId = graph.edge(tree[i]).fromVertex() if cost[vertexId] <= travelCost: vertices.append(i) upperBoundary = [] lowerBoundary = [] for i in vertices: upperBoundary.append(graph.vertex(graph.edge(tree[i]).toVertex()).point()) lowerBoundary.append(graph.vertex(graph.edge(tree[i]).fromVertex()).point()) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromPoint', 'Writing results…')) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.MultiPoint, network.sourceCrs()) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = startPoint.toString() sink.addFeature(feat, QgsFeatureSink.FastInsert) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = startPoint.toString() sink.addFeature(feat, QgsFeatureSink.FastInsert) upperBoundary.append(startPoint) lowerBoundary.append(startPoint) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs()) endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) directionField = -1 if directionField: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Building graph…')) snappedPoints = director.makeGraph(builder, [startPoint, endPoint], feedback) feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Calculating shortest path…')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) idxEnd = graph.findVertex(snappedPoints[1]) tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: raise QgsProcessingException( self.tr('There is no route from start point to end point.')) route = [graph.vertex(idxEnd).point()] cost = costs[idxEnd] current = idxEnd while current != idxStart: current = graph.edge(tree[current]).fromVertex() route.append(graph.vertex(current).point()) route.reverse() feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Writing results…')) geom = QgsGeometry.fromPolylineXY(route) feat = QgsFeature() feat.setFields(fields) feat['start'] = startPoint.toString() feat['end'] = endPoint.toString() feat['cost'] = cost / multiplier feat.setGeometry(geom) sink.addFeature(feat, QgsFeatureSink.FastInsert) results = {} results[self.TRAVEL_COST] = cost / multiplier results[self.OUTPUT] = dest_id return results
def processAlgorithm(self, feedback): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_VECTOR)) rasterPath = str(self.getParameterValue(self.INPUT_RASTER)) rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly) geoTransform = rasterDS.GetGeoTransform() rasterDS = None fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) fields.append(QgsField('poly_id', QVariant.Int, '', 10, 0)) fields.append(QgsField('point_id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter( fields.toList(), QgsWkbTypes.Point, layer.crs()) outFeature = QgsFeature() outFeature.setFields(fields) fid = 0 polyId = 0 pointId = 0 features = vector.features(layer) total = 100.0 / len(features) for current, f in enumerate(features): geom = f.geometry() bbox = geom.boundingBox() xMin = bbox.xMinimum() xMax = bbox.xMaximum() yMin = bbox.yMinimum() yMax = bbox.yMaximum() (startRow, startColumn) = raster.mapToPixel(xMin, yMax, geoTransform) (endRow, endColumn) = raster.mapToPixel(xMax, yMin, geoTransform) # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() for row in range(startRow, endRow + 1): for col in range(startColumn, endColumn + 1): (x, y) = raster.pixelToMap(row, col, geoTransform) point = QgsPointV2() point.setX(x) point.setY(y) if engine.contains(point): outFeature.setGeometry(QgsGeometry(point)) outFeature['id'] = fid outFeature['poly_id'] = polyId outFeature['point_id'] = pointId fid += 1 pointId += 1 writer.addFeature(outFeature) pointId = 0 polyId += 1 feedback.setProgress(int(current * total)) del writer
def writeShapefile(self, filename, shape_type): if filename[-4:] != '.shp': filename += '.shp' proj = QgsProject.instance() crs = proj.crs() #Create new shapefile object, loop trough triangle edges and add each # edge as a line. if shape_type == 'points': shape = QgsWkbTypes.Point fields = QgsFields() fields.append(QgsField("Id", QVariant.Int, 'integer', 9, 0)) fields.append(QgsField("Depth", QVariant.Double, 'double', 9, 3)) fields.append(QgsField("Connect", QVariant.Int, 'integer', 2, 0)) elif shape_type == 'edges': shape = QgsWkbTypes.LineString fields = QgsFields() fields.append(QgsField("Id", QVariant.Int, 'integer', 9, 0)) fields.append(QgsField("Flag", QVariant.Int, 'integer', 2, 0)) fields.append(QgsField("Name", QVariant.String, 'string', 10, 0)) elif shape_type == 'faces': shape = QgsWkbTypes.Polygon fields = QgsFields() fields.append(QgsField("Id", QVariant.Int, 'integer', 9, 0)) fields.append(QgsField("Node1", QVariant.Int, 'integer', 11, 0)) fields.append(QgsField("Node2", QVariant.Int, 'integer', 11, 0)) fields.append(QgsField("Node3", QVariant.Int, 'integer', 11, 0)) fields.append(QgsField("Node4", QVariant.Int, 'integer', 11, 0)) fields.append(QgsField("type", QVariant.Int, 'integer', 1, 0)) fields.append(QgsField("area", QVariant.Int, 'integer', 9, 0)) fields.append(QgsField("volume", QVariant.Int, 'integer', 9, 0)) fields.append(QgsField("depth", QVariant.Double, 'double', 9, 2)) fields.append(QgsField("resolution", QVariant.Int, 'integer', 9, 0)) fields.append(QgsField("ETA", QVariant.Double, 'double', 3, 2)) fields.append(QgsField("NSR", QVariant.Double, 'double', 3, 2)) fields.append(QgsField("Angle", QVariant.Double, 'double', 3, 2)) fileWriter = QgsVectorFileWriter(filename, "system", fields, shape, crs, "ESRI Shapefile") if fileWriter.hasError() != QgsVectorFileWriter.NoError: raise Exception('Error when creating shapefile ' + filename + ' : ' + str(fileWriter.hasError())) if shape_type == 'points': for node in range(0, len(self.x)): point = QgsPointXY() point.setX(self.x[node]) point.setY(self.y[node]) newFeature = QgsFeature() newFeature.setGeometry(QgsGeometry.fromPointXY(point)) newFeature.setFields(fields) newFeature.setAttributes([ int(node + 1), float('%9.3f' % self.z[node]), int(self.conn[node]) ]) fileWriter.addFeature(newFeature) if shape_type == 'edges': for key in self.physical: edgID = np.nonzero( np.logical_or(self.physicalID == self.physical[key][0], np.asarray(self.physicalID) == 0))[0] points = [] edgeN = 0 for i, edg in enumerate(edgID): if self.physicalID[edg] > 0: points.append( QgsPointXY(self.x[self.edges[edg]], self.y[self.edges[edg]])) elif len(points) > 0: newFeature = QgsFeature() newFeature.setGeometry( QgsGeometry.fromPolylineXY(points)) newFeature.setFields(fields) newFeature.setAttributes( [int(edgeN + 1), int(self.physical[key][0]), key]) fileWriter.addFeature(newFeature) points = [] edgeN += 1 if shape_type == 'faces': for ie in range(0, len(self.faces)): if self.faces[ie, -1] < 0: nface = 3 else: nface = 4 points = [] for fc in range(0, nface): i = self.faces[ie, fc] points.append(QgsPointXY(self.x[i], self.y[i])) i = self.faces[ie, 0] points.append(QgsPointXY(self.x[i], self.y[i])) newFeature = QgsFeature() newFeature.setGeometry(QgsGeometry.fromPolygonXY([points])) newFeature.setFields(fields) newFeature.setAttributes([int(ie+1),\ int(self.faces[ie,0]+1),int(self.faces[ie,1]+1),int(self.faces[ie,2]+1),int(self.faces[ie,3]+1),\ int(nface),\ float('%9.f' % self.areas[ie]),float('%9.f' % self.volumes[ie]),float('%9.2f' % self.zctr[ie]),float('%9.f' % self.res[ie]),\ float('%3.2f' % self.eta[ie]),float('%3.2f' % self.nsr[ie]),float('%3.2f' % self.min_angle[ie])]) fileWriter.addFeature(newFeature) del fileWriter
def processAlgorithm(self, feedback): layer = dataobjects.getLayerFromString( self.getParameterValue(self.INPUT_VECTOR)) startPoints = dataobjects.getLayerFromString( self.getParameterValue(self.START_POINTS)) strategy = self.getParameterValue(self.STRATEGY) travelCost = self.getParameterValue(self.TRAVEL_COST) directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) forwardValue = self.getParameterValue(self.VALUE_FORWARD) backwardValue = self.getParameterValue(self.VALUE_BACKWARD) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) speedFieldName = self.getParameterValue(self.SPEED_FIELD) defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) tolerance = self.getParameterValue(self.TOLERANCE) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) writerPoints = self.getOutputFromName( self.OUTPUT_POINTS).getVectorWriter(fields, QgsWkbTypes.MultiPoint, layer.crs()) writerPolygons = self.getOutputFromName( self.OUTPUT_POLYGON).getVectorWriter(fields, QgsWkbTypes.Polygon, layer.crs()) directionField = -1 if directionFieldName is not None: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName is not None: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder( iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance) feedback.pushInfo(self.tr('Loading start points...')) request = QgsFeatureRequest() request.setFlags(request.flags() ^ QgsFeatureRequest.SubsetOfAttributes) features = vector.features(startPoints, request) points = [] for f in features: points.append(f.geometry().asPoint()) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, points) feedback.pushInfo(self.tr('Calculating service areas...')) graph = builder.graph() vertices = [] upperBoundary = [] lowerBoundary = [] total = 100.0 / len(snappedPoints) for i, p in enumerate(snappedPoints): idxStart = graph.findVertex(snappedPoints[i]) origPoint = points[i].toString() tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) for j, v in enumerate(cost): if v > travelCost and tree[j] != -1: vertexId = graph.edge(tree[j]).outVertex() if cost[vertexId] <= travelCost: vertices.append(j) for j in vertices: upperBoundary.append( graph.vertex(graph.edge(tree[j]).inVertex()).point()) lowerBoundary.append( graph.vertex(graph.edge(tree[j]).outVertex()).point()) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = origPoint writerPoints.addFeature(feat) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = origPoint writerPoints.addFeature(feat) upperBoundary.append(origPoint) lowerBoundary.append(origPoint) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) geom = geomUpper.convexHull() feat.setGeometry(geom) feat['type'] = 'upper' feat['start'] = origPoint writerPolygons.addFeature(feat) geom = geomLower.convexHull() feat.setGeometry(geom) feat['type'] = 'lower' feat['start'] = origPoint writerPolygons.addFeature(feat) vertices[:] = [] upperBoundary[:] = [] lowerBoundary[:] = [] feedback.setProgress(int(i * total)) del writerPoints del writerPolygons
def processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString( self.getParameterValue(self.INPUT_VECTOR), context) startPoint = self.getParameterValue(self.START_POINT) endPoints = QgsProcessingUtils.mapLayerFromString( self.getParameterValue(self.END_POINTS), context) strategy = self.getParameterValue(self.STRATEGY) directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) forwardValue = self.getParameterValue(self.VALUE_FORWARD) backwardValue = self.getParameterValue(self.VALUE_BACKWARD) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) speedFieldName = self.getParameterValue(self.SPEED_FIELD) defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) tolerance = self.getParameterValue(self.TOLERANCE) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) feat = QgsFeature() feat.setFields(fields) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter( fields, QgsWkbTypes.LineString, layer.crs(), context) tmp = startPoint.split(',') startPoint = QgsPointXY(float(tmp[0]), float(tmp[1])) directionField = -1 if directionFieldName is not None: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName is not None: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder( iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance) feedback.pushInfo(self.tr('Loading end points...')) request = QgsFeatureRequest() request.setFlags(request.flags() ^ QgsFeatureRequest.SubsetOfAttributes) features = QgsProcessingUtils.getFeatures(endPoints, context, request) count = QgsProcessingUtils.featureCount(endPoints, context) points = [startPoint] for f in features: points.append(f.geometry().asPoint()) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, points) feedback.pushInfo(self.tr('Calculating shortest paths...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) route = [] total = 100.0 / count if count else 1 for i in range(1, count + 1): idxEnd = graph.findVertex(snappedPoints[i]) if tree[idxEnd] == -1: msg = self.tr( 'There is no route from start point ({}) to end point ({}).' .format(startPoint.toString(), points[i].toString())) feedback.setProgressText(msg) QgsMessageLog.logMessage(msg, self.tr('Processing'), QgsMessageLog.WARNING) continue cost = 0.0 current = idxEnd while current != idxStart: cost += graph.edge(tree[current]).cost(0) route.append( graph.vertex(graph.edge(tree[current]).inVertex()).point()) current = graph.edge(tree[current]).outVertex() route.append(snappedPoints[0]) route.reverse() geom = QgsGeometry.fromPolyline(route) feat.setGeometry(geom) feat['start'] = startPoint.toString() feat['end'] = points[i].toString() feat['cost'] = cost / multiplier writer.addFeature(feat, QgsFeatureSink.FastInsert) route[:] = [] feedback.setProgress(int(i * total)) del writer
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context) minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context) bbox = source.sourceExtent() sourceIndex = QgsSpatialIndex(source, feedback) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, source.sourceCrs()) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount if pointCount else 1 index = QgsSpatialIndex() points = dict() random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPoint(p) ids = sourceIndex.intersects(geom.buffer(5, 5).boundingBox()) if len(ids) > 0 and \ vector.checkMinDistance(p, index, minDistance, points): request = QgsFeatureRequest().setFilterFids( ids).setSubsetOfAttributes([]) for f in source.getFeatures(request): if feedback.isCanceled(): break tmpGeom = f.geometry() if geom.within(tmpGeom): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.insertFeature(f) points[nPoints] = p nPoints += 1 feedback.setProgress(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: feedback.pushInfo( self.tr( 'Could not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) return {self.OUTPUT: dest_id}
def testNumeric(self): """ Test calculation of aggregates on numeric fields""" layer = QgsVectorLayer("Point?field=fldint:integer&field=flddbl:double", "layer", "memory") pr = layer.dataProvider() # must be same length: int_values = [4, 2, 3, 2, 5, None, 8] dbl_values = [5.5, 3.5, 7.5, 5, 9, None, 7] self.assertEqual(len(int_values), len(dbl_values)) features = [] for i in range(len(int_values)): f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([int_values[i], dbl_values[i]]) features.append(f) assert pr.addFeatures(features) tests = [[QgsAggregateCalculator.Count, 'fldint', 6], [QgsAggregateCalculator.Count, 'flddbl', 6], [QgsAggregateCalculator.Sum, 'fldint', 24], [QgsAggregateCalculator.Sum, 'flddbl', 37.5], [QgsAggregateCalculator.Mean, 'fldint', 4], [QgsAggregateCalculator.Mean, 'flddbl', 6.25], [QgsAggregateCalculator.StDev, 'fldint', 2.0816], [QgsAggregateCalculator.StDev, 'flddbl', 1.7969], [QgsAggregateCalculator.StDevSample, 'fldint', 2.2803], [QgsAggregateCalculator.StDevSample, 'flddbl', 1.9685], [QgsAggregateCalculator.Min, 'fldint', 2], [QgsAggregateCalculator.Min, 'flddbl', 3.5], [QgsAggregateCalculator.Max, 'fldint', 8], [QgsAggregateCalculator.Max, 'flddbl', 9], [QgsAggregateCalculator.Range, 'fldint', 6], [QgsAggregateCalculator.Range, 'flddbl', 5.5], [QgsAggregateCalculator.Median, 'fldint', 3.5], [QgsAggregateCalculator.Median, 'flddbl', 6.25], [QgsAggregateCalculator.CountDistinct, 'fldint', 5], [QgsAggregateCalculator.CountDistinct, 'flddbl', 6], [QgsAggregateCalculator.CountMissing, 'fldint', 1], [QgsAggregateCalculator.CountMissing, 'flddbl', 1], [QgsAggregateCalculator.FirstQuartile, 'fldint', 2], [QgsAggregateCalculator.FirstQuartile, 'flddbl', 5.0], [QgsAggregateCalculator.ThirdQuartile, 'fldint', 5.0], [QgsAggregateCalculator.ThirdQuartile, 'flddbl', 7.5], [QgsAggregateCalculator.InterQuartileRange, 'fldint', 3.0], [QgsAggregateCalculator.InterQuartileRange, 'flddbl', 2.5], [QgsAggregateCalculator.ArrayAggregate, 'fldint', int_values], [QgsAggregateCalculator.ArrayAggregate, 'flddbl', dbl_values], ] agg = QgsAggregateCalculator(layer) for t in tests: val, ok = agg.calculate(t[0], t[1]) self.assertTrue(ok) if isinstance(t[2], (int, list)): self.assertEqual(val, t[2]) else: self.assertAlmostEqual(val, t[2], 3) # bad tests - the following stats should not be calculatable for numeric fields for t in [QgsAggregateCalculator.StringMinimumLength, QgsAggregateCalculator.StringMaximumLength]: val, ok = agg.calculate(t, 'fldint') self.assertFalse(ok) val, ok = agg.calculate(t, 'flddbl') self.assertFalse(ok)
def processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString( self.getParameterValue(self.INPUT), context) method = self.getParameterValue(self.METHOD) geometryType = layer.geometryType() fields = layer.fields() export_z = False export_m = False if geometryType == QgsWkbTypes.PolygonGeometry: areaName = vector.createUniqueFieldName('area', fields) fields.append(QgsField(areaName, QVariant.Double)) perimeterName = vector.createUniqueFieldName('perimeter', fields) fields.append(QgsField(perimeterName, QVariant.Double)) elif geometryType == QgsWkbTypes.LineGeometry: lengthName = vector.createUniqueFieldName('length', fields) fields.append(QgsField(lengthName, QVariant.Double)) else: xName = vector.createUniqueFieldName('xcoord', fields) fields.append(QgsField(xName, QVariant.Double)) yName = vector.createUniqueFieldName('ycoord', fields) fields.append(QgsField(yName, QVariant.Double)) if QgsWkbTypes.hasZ(layer.wkbType()): export_z = True zName = vector.createUniqueFieldName('zcoord', fields) fields.append(QgsField(zName, QVariant.Double)) if QgsWkbTypes.hasM(layer.wkbType()): export_m = True zName = vector.createUniqueFieldName('mvalue', fields) fields.append(QgsField(zName, QVariant.Double)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, layer.wkbType(), layer.crs(), context) ellips = None crs = None coordTransform = None # Calculate with: # 0 - layer CRS # 1 - project CRS # 2 - ellipsoidal if method == 2: ellips = QgsProject.instance().ellipsoid() crs = layer.crs().srsid() elif method == 1: mapCRS = iface.mapCanvas().mapSettings().destinationCrs() layCRS = layer.crs() coordTransform = QgsCoordinateTransform(layCRS, mapCRS) outFeat = QgsFeature() outFeat.initAttributes(len(fields)) outFeat.setFields(fields) features = QgsProcessingUtils.getFeatures(layer, context) total = 100.0 / QgsProcessingUtils.featureCount(layer, context) for current, f in enumerate(features): inGeom = f.geometry() if method == 1: inGeom.transform(coordTransform) (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs) outFeat.setGeometry(inGeom) attrs = f.attributes() attrs.append(attr1) if attr2 is not None: attrs.append(attr2) # add point z/m if export_z: attrs.append(inGeom.geometry().z()) if export_m: attrs.append(inGeom.geometry().m()) outFeat.setAttributes(attrs) writer.addFeature(outFeat) feedback.setProgress(int(current * total)) del writer
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoints = self.parameterAsSource(parameters, self.START_POINTS, context) endPoint = self.parameterAsPoint(parameters, self.END_POINT, context) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) feat = QgsFeature() feat.setFields(fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(context.project().crs(), True, tolerance) feedback.pushInfo(self.tr('Loading start points...')) request = QgsFeatureRequest() request.setFlags(request.flags() ^ QgsFeatureRequest.SubsetOfAttributes) request.setDestinationCrs(network.sourceCrs()) features = startPoints.getFeatures(request) total = 100.0 / startPoints.featureCount() if startPoints.featureCount( ) else 0 points = [endPoint] for current, f in enumerate(features): if feedback.isCanceled(): break points.append(f.geometry().asPoint()) feedback.setProgress(int(current * total)) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo(self.tr('Calculating shortest paths...')) graph = builder.graph() idxEnd = graph.findVertex(snappedPoints[0]) route = [] nPoints = len(snappedPoints) total = 100.0 / nPoints if nPoints else 1 for i in range(1, count + 1): if feedback.isCanceled(): break idxStart = graph.findVertex(snappedPoints[i]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: msg = self.tr( 'There is no route from start point ({}) to end point ({}).' .format(points[i].toString(), endPoint.toString())) feedback.setProgressText(msg) QgsMessageLog.logMessage(msg, self.tr('Processing'), QgsMessageLog.WARNING) continue cost = 0.0 current = idxEnd while current != idxStart: cost += graph.edge(tree[current]).cost(0) route.append( graph.vertex(graph.edge(tree[current]).inVertex()).point()) current = graph.edge(tree[current]).outVertex() route.append(snappedPoints[i]) route.reverse() geom = QgsGeometry.fromPolyline(route) feat.setGeometry(geom) feat['start'] = points[i].toString() feat['end'] = endPoint.toString() feat['cost'] = cost / multiplier sink.addFeature(feat, QgsFeatureSink.FastInsert) route[:] = [] feedback.setProgress(int(i * total)) return {self.OUTPUT: dest_id}
def create_preview_group( group_name: str, images: List[dict], footprints_filename = None, catalog_layer_name = None, tile_service: str = 'xyz', search_query: str = None, sort_order: Tuple[str, str] = None) -> None: if tile_service.lower() not in ['wmts', 'xyz']: log.debug(f'Incorrect tile service passed for preview group: ' f'{tile_service} (must be wmts or xyz)') return item_ids = [f"{img['properties'][ITEM_TYPE]}:{img[ID]}" for img in images] uri = tile_service_data_src_uri( item_ids, service=tile_service) if uri: log.debug(f'Tile datasource URI:\n{uri}') rlayer = QgsRasterLayer(uri, 'Image previews', 'wms') rlayer.setCustomProperty(PLANET_PREVIEW_ITEM_IDS, json.dumps(item_ids)) if tile_service == 'xyz' and catalog_layer_name is not None: url = uri.split("url=")[-1] s = QSettings() s.setValue(f'qgis/connections-xyz/{catalog_layer_name}/username', "") s.setValue(f'qgis/connections-xyz/{catalog_layer_name}/password', "") s.setValue(f'qgis/connections-xyz/{catalog_layer_name}/authcfg', "") s.setValue(f'qgis/connections-xyz/{catalog_layer_name}/url', url.replace(PlanetClient.getInstance().api_key(), "")) else: log.debug('No tile URI for preview group') return vlayer = None if images: vlayer = create_preview_vector_layer(images[0]) vlayer.startEditing() dp = vlayer.dataProvider() fields: List[QgsField] = vlayer.fields() for img in images: feat = QgsFeature() feat.setFields(fields) qgs_geom = qgsgeometry_from_geojson(img['geometry']) feat.setGeometry(qgs_geom) f_names = [f.name() for f in fields] if 'item_id' in f_names: feat['item_id'] = img[ID] if search_query and 'search_query' in f_names: feat['search_query'] = json.dumps(search_query) if (sort_order and 'sort_order' in f_names and len(sort_order) > 1): feat['sort_order'] = ' '.join(sort_order) props: dict = img['properties'] for k, v in props.items(): if k in f_names: feat[k] = v dp.addFeature(feat) vlayer.commitChanges() if footprints_filename: QgsVectorFileWriter.writeAsVectorFormat(vlayer, footprints_filename, "UTF-8") gpkglayer = QgsVectorLayer(footprints_filename, 'Footprints') gpkglayer.setRenderer(vlayer.renderer().clone()) vlayer = gpkglayer QgsProject.instance().addMapLayer(vlayer, False) # noinspection PyArgumentList QgsProject.instance().addMapLayer(rlayer, False) # noinspection PyArgumentList root: QgsLayerTree = QgsProject.instance().layerTreeRoot() group = root.insertGroup(0, f'{group_name} {tile_service.upper()} preview') if vlayer: group.addLayer(vlayer) group.addLayer(rlayer) if vlayer: iface.setActiveLayer(vlayer)
def testExpression(self): """ test aggregate calculation using an expression """ # numeric layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory") pr = layer.dataProvider() int_values = [4, 2, 3, 2, 5, None, 8] features = [] for v in int_values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([v]) features.append(f) assert pr.addFeatures(features) # int agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, 48) # double val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 1.5') self.assertTrue(ok) self.assertEqual(val, 36) # datetime val, ok = agg.calculate( QgsAggregateCalculator.Max, "to_date('2012-05-04') + to_interval( fldint || ' day' )") self.assertTrue(ok) self.assertEqual(val, QDateTime(QDate(2012, 5, 12), QTime(0, 0, 0))) # date val, ok = agg.calculate( QgsAggregateCalculator.Min, "to_date(to_date('2012-05-04') + to_interval( fldint || ' day' ))") self.assertTrue(ok) self.assertEqual(val, QDateTime(QDate(2012, 5, 6), QTime(0, 0, 0))) # string val, ok = agg.calculate(QgsAggregateCalculator.Max, "fldint || ' oranges'") self.assertTrue(ok) self.assertEqual(val, '8 oranges') # geometry val, ok = agg.calculate(QgsAggregateCalculator.GeometryCollect, "make_point( coalesce(fldint,0), 2 )") self.assertTrue(ok) self.assertTrue(val.asWkt(), 'MultiPoint((4 2, 2 2, 3 2, 2 2,5 2, 0 2,8 2))') # try a bad expression val, ok = agg.calculate(QgsAggregateCalculator.Max, "not_a_field || ' oranges'") self.assertFalse(ok) val, ok = agg.calculate(QgsAggregateCalculator.Max, "5+") self.assertFalse(ok) # test expression context # check default context first # should have layer variables: val, ok = agg.calculate(QgsAggregateCalculator.Min, "@layer_name") self.assertTrue(ok) self.assertEqual(val, 'layer') # but not custom variables: val, ok = agg.calculate(QgsAggregateCalculator.Min, "@my_var") self.assertTrue(ok) self.assertEqual(val, NULL) # test with manual expression context scope = QgsExpressionContextScope() scope.setVariable('my_var', 5) context = QgsExpressionContext() context.appendScope(scope) val, ok = agg.calculate(QgsAggregateCalculator.Min, "@my_var", context) self.assertTrue(ok) self.assertEqual(val, 5)
def testDateTime(self): """ Test calculation of aggregates on date/datetime fields""" layer = QgsVectorLayer( "Point?field=flddate:date&field=flddatetime:datetime", "layer", "memory") pr = layer.dataProvider() # must be same length: datetime_values = [ QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2011, 1, 5), QTime(15, 3, 1)), QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1)), QDateTime(), QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)), QDateTime(), QDateTime(QDate(2011, 1, 5), QTime(11, 10, 54)) ] date_values = [ QDate(2015, 3, 4), QDate(2015, 3, 4), QDate(2019, 12, 28), QDate(), QDate(1998, 1, 2), QDate(), QDate(2011, 1, 5), QDate(2011, 1, 5), QDate(2011, 1, 5) ] self.assertEqual(len(datetime_values), len(date_values)) features = [] for i in range(len(datetime_values)): f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([date_values[i], datetime_values[i]]) features.append(f) assert pr.addFeatures(features) tests = [ [QgsAggregateCalculator.Count, 'flddatetime', 9], [QgsAggregateCalculator.Count, 'flddate', 9], [QgsAggregateCalculator.CountDistinct, 'flddatetime', 6], [QgsAggregateCalculator.CountDistinct, 'flddate', 5], [QgsAggregateCalculator.CountMissing, 'flddatetime', 2], [QgsAggregateCalculator.CountMissing, 'flddate', 2], [ QgsAggregateCalculator.Min, 'flddatetime', QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)) ], [ QgsAggregateCalculator.Min, 'flddate', QDateTime(QDate(1998, 1, 2), QTime(0, 0, 0)) ], [ QgsAggregateCalculator.Max, 'flddatetime', QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1)) ], [ QgsAggregateCalculator.Max, 'flddate', QDateTime(QDate(2019, 12, 28), QTime(0, 0, 0)) ], [ QgsAggregateCalculator.Range, 'flddatetime', QgsInterval(693871147) ], [QgsAggregateCalculator.Range, 'flddate', QgsInterval(693792000)], [ QgsAggregateCalculator.ArrayAggregate, 'flddatetime', [None if v.isNull() else v for v in datetime_values] ], [ QgsAggregateCalculator.ArrayAggregate, 'flddate', [None if v.isNull() else v for v in date_values] ], ] agg = QgsAggregateCalculator(layer) for t in tests: val, ok = agg.calculate(t[0], t[1]) self.assertTrue(ok) self.assertEqual(val, t[2]) # bad tests - the following stats should not be calculatable for string fields for t in [ QgsAggregateCalculator.Sum, QgsAggregateCalculator.Mean, QgsAggregateCalculator.Median, QgsAggregateCalculator.StDev, QgsAggregateCalculator.StDevSample, QgsAggregateCalculator.Minority, QgsAggregateCalculator.Majority, QgsAggregateCalculator.FirstQuartile, QgsAggregateCalculator.ThirdQuartile, QgsAggregateCalculator.InterQuartileRange, QgsAggregateCalculator.StringMinimumLength, QgsAggregateCalculator.StringMaximumLength, ]: val, ok = agg.calculate(t, 'flddatetime') self.assertFalse(ok)