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): source = self.parameterAsSource(parameters, self.INPUT, context) extent = self.parameterAsExtent(parameters, self.TARGET_AREA, context) target_crs = self.parameterAsCrs(parameters, self.TARGET_AREA_CRS, context) target_geom = QgsGeometry.fromRect(extent) fields = QgsFields() fields.append(QgsField('auth_id', QVariant.String, '', 20)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem()) # make intersection tests nice and fast engine = QgsGeometry.createGeometryEngine(target_geom.constGet()) engine.prepareGeometry() layer_bounds = QgsGeometry.fromRect(source.sourceExtent()) crses_to_check = QgsCoordinateReferenceSystem.validSrsIds() total = 100.0 / len(crses_to_check) found_results = 0 transform_context = QgsCoordinateTransformContext() for current, srs_id in enumerate(crses_to_check): if feedback.isCanceled(): break candidate_crs = QgsCoordinateReferenceSystem.fromSrsId(srs_id) if not candidate_crs.isValid(): continue transform_candidate = QgsCoordinateTransform(candidate_crs, target_crs, transform_context) transformed_bounds = QgsGeometry(layer_bounds) try: if not transformed_bounds.transform(transform_candidate) == 0: continue except: continue try: if engine.intersects(transformed_bounds.constGet()): feedback.pushInfo(self.tr('Found candidate CRS: {}').format(candidate_crs.authid())) f = QgsFeature(fields) f.setAttributes([candidate_crs.authid()]) sink.addFeature(f, QgsFeatureSink.FastInsert) found_results += 1 except: continue feedback.setProgress(int(current * total)) if found_results == 0: feedback.reportError(self.tr('No matching projections found')) return {self.OUTPUT: dest_id}
def testProxyFeatureSink(self): fields = QgsFields() fields.append(QgsField('fldtxt', QVariant.String)) fields.append(QgsField('fldint', QVariant.Int)) store = QgsFeatureStore(fields, QgsCoordinateReferenceSystem()) proxy = QgsProxyFeatureSink(store) self.assertEqual(proxy.destinationSink(), store) self.assertEqual(len(store), 0) f = QgsFeature() f.setAttributes(["test", 123]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200))) proxy.addFeature(f) self.assertEqual(len(store), 1) self.assertEqual(store.features()[0]['fldtxt'], 'test') f2 = QgsFeature() f2.setAttributes(["test2", 457]) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(200, 200))) f3 = QgsFeature() f3.setAttributes(["test3", 888]) f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(300, 200))) proxy.addFeatures([f2, f3]) self.assertEqual(len(store), 3) self.assertEqual(store.features()[1]['fldtxt'], 'test2') self.assertEqual(store.features()[2]['fldtxt'], 'test3')
def test1(self): d = QgsVirtualLayerDefinition() self.assertEqual(d.toString(), "") d.setFilePath("/file") self.assertEqual(d.toString(), "file:///file") self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).filePath(), "/file") self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).filePath(), "/file") d.setFilePath(os.path.join("C:/", "file")) self.assertEqual(d.toString(), "file:///C:/file") # self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).filePath(), os.path.join('C:/', 'file')) d.setQuery("SELECT * FROM mytable") self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).query(), "SELECT * FROM mytable") self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).query(), "SELECT * FROM mytable") q = "SELECT * FROM tableéé /*:int*/" d.setQuery(q) self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).query(), q) self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).query(), q) s1 = "file://foo&bar=okié" d.addSource("name", s1, "provider", "utf8") self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).sourceLayers()[0].source(), s1) self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).sourceLayers()[0].source(), s1) n1 = "éé ok" d.addSource(n1, s1, "provider") self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).sourceLayers()[1].name(), n1) self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).sourceLayers()[1].name(), n1) d.addSource("ref1", "id0001") self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).sourceLayers()[2].reference(), "id0001") self.assertEqual( QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).sourceLayers()[2].reference(), "id0001" ) s = "dbname='C:\\tt' table=\"test\" (geometry) sql=" d.addSource("nn", s, "spatialite") self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).sourceLayers()[3].source(), s) self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).sourceLayers()[3].source(), s) d.setGeometryField("geom") self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).geometryField(), "geom") self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).geometryField(), "geom") d.setGeometryWkbType(QgsWkbTypes.Point) self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).geometryWkbType(), QgsWkbTypes.Point) self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).geometryWkbType(), QgsWkbTypes.Point) f = QgsFields() f.append(QgsField("a", QVariant.Int)) f.append(QgsField("f", QVariant.Double)) f.append(QgsField("s", QVariant.String)) d.setFields(f) f2 = QgsVirtualLayerDefinition.fromUrl(d.toUrl()).fields() self.assertEqual(f[0].name(), f2[0].name()) self.assertEqual(f[0].type(), f2[0].type()) self.assertEqual(f[1].name(), f2[1].name()) self.assertEqual(f[1].type(), f2[1].type()) self.assertEqual(f[2].name(), f2[2].name()) self.assertEqual(f[2].type(), f2[2].type())
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 to_shp(path, any_features_list, layer_fields, crs, name, encoding, geom_type): if path is None: if geom_type == 0: network = QgsVectorLayer('Point?crs=' + crs.toWkt(), name, "memory") else: network = QgsVectorLayer('LineString?crs=' + crs.toWkt(), name, "memory") else: fields = QgsFields() for field in layer_fields: fields.append(field) file_writer = QgsVectorFileWriter(path, encoding, fields, geom_type, crs, "ESRI Shapefile") if file_writer.hasError() != QgsVectorFileWriter.NoError: print "Error when creating shapefile: ", file_writer.errorMessage() del file_writer network = QgsVectorLayer(path, name, "ogr") pr = network.dataProvider() if path is None: pr.addAttributes(layer_fields) new_features = [] for i in any_features_list: new_feat = QgsFeature() new_feat.setFeatureId(i[0]) new_feat.setAttributes([attr[0] for attr in i[1]]) new_feat.setGeometry(QgsGeometry(QgsGeometry.fromWkt(str(i[2])))) #QgsGeometry() new_features.append(new_feat) network.startEditing() pr.addFeatures(new_features) network.commitChanges() return network
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 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 create_points_at(startpoint, endpoint, distance, geom, fid, force, divide): """Creating Points at coordinates along the line """ length = geom.length() def distance_fn(): if divide > 0: return length / divide else: import random return distance * random.uniform(0.5,2.5) feats = [] if endpoint > 0: length = endpoint # set the first point at startpoint point = geom.interpolate(startpoint) field_id = QgsField(name="id", type=QVariant.Int) field = QgsField(name="dist", type=QVariant.Double) fields = QgsFields() fields.append(field_id) fields.append(field) feature = QgsFeature(fields) feature['dist'] = startpoint feature['id'] = fid feature.setGeometry(point) feats.append(feature) current_distance = 0 while startpoint + current_distance <= length: step = distance_fn() # Get a point along the line at the current distance point = geom.interpolate(startpoint + current_distance) # Create a new QgsFeature and assign it the new geometry feature = QgsFeature(fields) feature['dist'] = (startpoint + step) feature['id'] = fid feature.setGeometry(point) feats.append(feature) # Increase the distance current_distance = current_distance + step # set the last point at endpoint if wanted if force is True: end = geom.length() point = geom.interpolate(end) feature = QgsFeature(fields) feature['dist'] = end feature['id'] = fid feature.setGeometry(point) feats.append(feature) return feats
def testExportLayerToExistingDatabase(self): fields = QgsFields() fields.append(QgsField('f1', QVariant.Int)) tmpfile = os.path.join(self.basetestpath, 'testCreateNewGeopackage.gpkg') options = {} options['update'] = True options['driverName'] = 'GPKG' options['layerName'] = 'table1' exporter = QgsVectorLayerExporter(tmpfile, "ogr", fields, QgsWkbTypes.Polygon, QgsCoordinateReferenceSystem(3111), False, options) self.assertFalse(exporter.errorCode(), 'unexpected export error {}: {}'.format(exporter.errorCode(), exporter.errorMessage())) options['layerName'] = 'table2' exporter = QgsVectorLayerExporter(tmpfile, "ogr", fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem(3113), False, options) self.assertFalse(exporter.errorCode(), 'unexpected export error {} : {}'.format(exporter.errorCode(), exporter.errorMessage())) del exporter # make sure layers exist lyr = QgsVectorLayer('{}|layername=table1'.format(tmpfile), "lyr1", "ogr") self.assertTrue(lyr.isValid()) self.assertEqual(lyr.crs().authid(), 'EPSG:3111') self.assertEqual(lyr.wkbType(), QgsWkbTypes.Polygon) lyr2 = QgsVectorLayer('{}|layername=table2'.format(tmpfile), "lyr2", "ogr") self.assertTrue(lyr2.isValid()) self.assertEqual(lyr2.crs().authid(), 'EPSG:3113') self.assertEqual(lyr2.wkbType(), QgsWkbTypes.Point)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) field_name = self.parameterAsString(parameters, self.FIELD_NAME, context) values = source.uniqueValues(source.fields().lookupField(field_name)) fields = QgsFields() field = source.fields()[source.fields().lookupField(field_name)] field.setName('VALUES') fields.append(field) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem()) results = {} if sink: for value in values: if feedback.isCanceled(): break f = QgsFeature() f.setAttributes([value]) sink.addFeature(f, QgsFeatureSink.FastInsert) results[self.OUTPUT] = dest_id output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context) if output_file: self.createHTML(output_file, values) results[self.OUTPUT_HTML_FILE] = output_file results[self.TOTAL_VALUES] = len(values) results[self.UNIQUE_VALUES] = ';'.join([str(v) for v in values]) return results
def testLegendKeysWhileCounting(self): # test determining legend keys for features, while counting features fields = QgsFields() fields.append(QgsField('x')) # setup renderer renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('x') symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 0, 0)) renderer.addCategory(QgsRendererCategory('a', symbol_a, 'a')) symbol_b = createMarkerSymbol() symbol_b.setColor(QColor(0, 255, 0)) renderer.addCategory(QgsRendererCategory('b', symbol_b, 'b')) symbol_c = createMarkerSymbol() symbol_c.setColor(QColor(0, 0, 255)) renderer.addCategory(QgsRendererCategory('c', symbol_c, 'c', False)) symbol_d = createMarkerSymbol() symbol_d.setColor(QColor(255, 0, 255)) renderer.addCategory(QgsRendererCategory(['d', 'e'], symbol_d, 'de')) # add default category default_symbol = createMarkerSymbol() default_symbol.setColor(QColor(255, 255, 255)) renderer.addCategory(QgsRendererCategory('', default_symbol, 'default')) context = QgsRenderContext() context.setRendererScale(0) # simulate counting renderer.startRender(context, fields) f = QgsFeature(fields) f.setAttributes(['a']) keys = renderer.legendKeysForFeature(f, context) self.assertEqual(keys, {'0'}) f.setAttributes(['b']) keys = renderer.legendKeysForFeature(f, context) self.assertEqual(keys, {'1'}) # hidden category, should still return keys f.setAttributes(['c']) keys = renderer.legendKeysForFeature(f, context) self.assertEqual(keys, {'2'}) # list f.setAttributes(['d']) keys = renderer.legendKeysForFeature(f, context) self.assertEqual(keys, {'3'}) f.setAttributes(['e']) keys = renderer.legendKeysForFeature(f, context) self.assertEqual(keys, {'3'}) # no matching category f.setAttributes(['xxx']) keys = renderer.legendKeysForFeature(f, context) self.assertFalse(keys) renderer.stopRender(context)
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 processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) field_names = self.parameterAsFields(parameters, self.FIELDS, context) fields = QgsFields() field_indices = [] for field_name in field_names: field_index = source.fields().lookupField(field_name) if field_index < 0: feedback.reportError(self.tr('Invalid field name {}').format(field_name)) continue field = source.fields()[field_index] fields.append(field) field_indices.append(field_index) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem()) results = {} values = set() if len(field_indices) == 1: # one field, can use provider optimised method values = tuple([v] for v in source.uniqueValues(field_indices[0])) else: # have to scan whole table # TODO - add this support to QgsVectorDataProvider so we can run it on # the backend request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes(field_indices) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(source.getFeatures(request, QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)): if feedback.isCanceled(): break value = tuple(f.attribute(i) for i in field_indices) values.add(value) feedback.setProgress(int(current * total)) if sink: for value in values: if feedback.isCanceled(): break f = QgsFeature() f.setAttributes([attr for attr in value]) sink.addFeature(f, QgsFeatureSink.FastInsert) results[self.OUTPUT] = dest_id output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context) if output_file: self.createHTML(output_file, values) results[self.OUTPUT_HTML_FILE] = output_file results[self.TOTAL_VALUES] = len(values) results[self.UNIQUE_VALUES] = ';'.join([','.join([str(attr) for attr in v]) for v in values]) return results
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 testOriginalSymbolForFeature(self): # test renderer with features fields = QgsFields() fields.append(QgsField('x')) # setup renderer renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('x') symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 0, 0)) renderer.addCategory(QgsRendererCategory('a', symbol_a, 'a')) symbol_b = createMarkerSymbol() symbol_b.setColor(QColor(0, 255, 0)) renderer.addCategory(QgsRendererCategory('b', symbol_b, 'b')) symbol_c = createMarkerSymbol() symbol_c.setColor(QColor(0, 0, 255)) renderer.addCategory(QgsRendererCategory('c', symbol_c, 'c', False)) symbol_d = createMarkerSymbol() symbol_d.setColor(QColor(255, 0, 255)) renderer.addCategory(QgsRendererCategory(['d', 'e'], symbol_d, 'de')) # add default category default_symbol = createMarkerSymbol() default_symbol.setColor(QColor(255, 255, 255)) renderer.addCategory(QgsRendererCategory('', default_symbol, 'default')) context = QgsRenderContext() renderer.startRender(context, fields) f = QgsFeature(fields) f.setAttributes(['a']) symbol = renderer.originalSymbolForFeature(f, context) self.assertEqual(symbol.color(), QColor(255, 0, 0)) f.setAttributes(['b']) symbol = renderer.originalSymbolForFeature(f, context) self.assertEqual(symbol.color(), QColor(0, 255, 0)) # list f.setAttributes(['d']) symbol = renderer.originalSymbolForFeature(f, context) self.assertEqual(symbol.color(), QColor(255, 0, 255)) f.setAttributes(['e']) symbol = renderer.originalSymbolForFeature(f, context) self.assertEqual(symbol.color(), QColor(255, 0, 255)) # hidden category f.setAttributes(['c']) symbol = renderer.originalSymbolForFeature(f, context) self.assertIsNone(symbol) # no matching category f.setAttributes(['xxx']) symbol = renderer.originalSymbolForFeature(f, context) self.assertEqual(symbol.color(), QColor(255, 255, 255)) # default symbol renderer.stopRender(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') context = QgsExpressionContextUtils.createFeatureBasedContext(feature, fields) assert style.matches(20, context)
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 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): 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 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 _make_layer(self, layer_wkb_name): fields = QgsFields() wkb_type = getattr(QgsWkbTypes, layer_wkb_name) fields.append(QgsField('int_f', QVariant.Int)) layer = QgsMemoryProviderUtils.createMemoryLayer( '%s_layer' % layer_wkb_name, fields, wkb_type, QgsCoordinateReferenceSystem(4326)) self.assertTrue(layer.isValid()) self.assertEqual(layer.wkbType(), wkb_type) return layer
def create_memory_layer( layer_name, geometry, coordinate_reference_system=None, fields=None): """Create a vector memory layer. :param layer_name: The name of the layer. :type layer_name: str :param geometry: The geometry of the layer. :rtype geometry: QgsWkbTypes (note: from C++ QgsWkbTypes::GeometryType enum) :param coordinate_reference_system: The CRS of the memory layer. :type coordinate_reference_system: QgsCoordinateReferenceSystem :param fields: Fields of the vector layer. Default to None. :type fields: QgsFields :return: The memory layer. :rtype: QgsVectorLayer """ if geometry == QgsWkbTypes.PointGeometry: wkb_type = QgsWkbTypes.MultiPoint elif geometry == QgsWkbTypes.LineGeometry: wkb_type = QgsWkbTypes.MultiLineString elif geometry == QgsWkbTypes.PolygonGeometry: wkb_type = QgsWkbTypes.MultiPolygon elif geometry == QgsWkbTypes.NullGeometry: wkb_type = QgsWkbTypes.NoGeometry else: raise MemoryLayerCreationError( 'Layer geometry must be one of: Point, Line, ' 'Polygon or Null, I got %s' % geometry) if coordinate_reference_system is None: coordinate_reference_system = QgsCoordinateReferenceSystem() if fields is None: fields = QgsFields() elif not isinstance(fields, QgsFields): # fields is a list new_fields = QgsFields() for f in fields: new_fields.append(f) fields = new_fields memory_layer = QgsMemoryProviderUtils. \ createMemoryLayer(name=layer_name, fields=fields, geometryType=wkb_type, crs=coordinate_reference_system) memory_layer.dataProvider().createSpatialIndex() memory_layer.keywords = { 'inasafe_fields': {} } return memory_layer
def processAlgorithm(self, feedback): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_LAYER)) byFeature = self.getParameterValue(self.BY_FEATURE) if byFeature and layer.geometryType() == QgsWkbTypes.PointGeometry and layer.featureCount() <= 2: raise GeoAlgorithmExecutionException(self.tr("Can't calculate an OMBB for each point, it's a point. The number of points must be greater than 2")) if byFeature: fields = layer.fields() else: fields = QgsFields() fields.append(QgsField('area', QVariant.Double)) fields.append(QgsField('perimeter', QVariant.Double)) fields.append(QgsField('angle', QVariant.Double)) fields.append(QgsField('width', QVariant.Double)) fields.append(QgsField('height', QVariant.Double)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Polygon, layer.crs()) if byFeature: self.featureOmbb(layer, writer, feedback) else: self.layerOmmb(layer, writer, feedback) del writer
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): 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): 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) extent = QgsRectangle(float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3])) 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) 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.00 / (area / pSpacing) y = extent.yMaximum() - inset 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 geom.intersects(extent): f.setAttribute("id", count) f.setGeometry(geom) writer.addFeature(f) x += pSpacing count += 1 progress.setPercentage(int(count * total)) y = y - pSpacing del writer
def check_geometry(self, vlayer): lstErrors = [] if self.mySelection: layer = vlayer.selectedFeatures() nFeat = len(layer) else: layer = [] ft = QgsFeature() fit = vlayer.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([])) while fit.nextFeature(ft): layer.append(QgsFeature(ft)) nFeat = len(layer) nElement = 0 if nFeat > 0: self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) for feat in layer: if not self.running: return list() geom = QgsGeometry(feat.geometry()) # ger reference to geometry self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) nElement += 1 # Check Add error if not geom.isGeosEmpty(): lstErrors.append((feat.id(), list(geom.validateGeometry()))) self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nFeat) if self.writeShape: fields = QgsFields() fields.append(QgsField("FEAT_ID", QVariant.Int)) fields.append(QgsField("ERROR", QVariant.String)) writer = QgsVectorFileWriter(self.myName, self.myEncoding, fields, QGis.WKBPoint, vlayer.crs()) for rec in lstErrors: if len(rec[1]) < 1: continue for err in rec[1]: fidItem = unicode(rec[0]) message = err.what() if err.hasWhere(): locErr = err.where() xP = locErr.x() yP = locErr.y() myPoint = QgsPoint(xP, yP) geometry = QgsGeometry().fromPoint(myPoint) ft = QgsFeature() ft.setGeometry(geometry) ft.setAttributes([fidItem, message]) writer.addFeature(ft) del writer return "writeShape" else: return lstErrors
def regularMatrix(self, parameters, context, source, inField, target_source, targetField, nPoints, feedback): distArea = QgsDistanceArea() distArea.setSourceCrs(source.sourceCrs(), context.transformContext()) distArea.setEllipsoid(context.project().ellipsoid()) inIdx = source.fields().lookupField(inField) targetIdx = target_source.fields().lookupField(targetField) index = QgsSpatialIndex(target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(source.sourceCrs(), context.transformContext())), feedback) first = True sink = None dest_id = None features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([inIdx])) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, inFeat in enumerate(features): if feedback.isCanceled(): break inGeom = inFeat.geometry() if first: featList = index.nearestNeighbor(inGeom.asPoint(), nPoints) first = False fields = QgsFields() input_id_field = source.fields()[inIdx] input_id_field.setName('ID') fields.append(input_id_field) for f in target_source.getFeatures(QgsFeatureRequest().setFilterFids(featList).setSubsetOfAttributes([targetIdx]).setDestinationCrs(source.sourceCrs(), context.transformContext())): fields.append(QgsField(str(f[targetField]), QVariant.Double)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, source.wkbType(), source.sourceCrs()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) data = [inFeat[inField]] for target in target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setFilterFids(featList).setDestinationCrs(source.sourceCrs(), context.transformContext())): if feedback.isCanceled(): break outGeom = target.geometry() dist = distArea.measureLine(inGeom.asPoint(), outGeom.asPoint()) data.append(dist) out_feature = QgsFeature() out_feature.setGeometry(inGeom) out_feature.setAttributes(data) sink.addFeature(out_feature, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.VECTOR)) pointCount = float(self.getParameterValue(self.POINT_NUMBER)) minDistance = float(self.getParameterValue(self.MIN_DISTANCE)) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QGis.WKBPoint, layer.dataProvider().crs()) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 featureCount = layer.featureCount() total = 100.0 / pointCount index = QgsSpatialIndex() points = dict() da = QgsDistanceArea() request = QgsFeatureRequest() random.seed() while nIterations < maxIterations and nPoints < pointCount: # pick random feature fid = random.randint(0, featureCount - 1) f = layer.getFeatures(request.setFilterFid(fid)).next() fGeom = QgsGeometry(f.geometry()) if fGeom.isMultipart(): lines = fGeom.asMultiPolyline() # pick random line lineId = random.randint(0, len(lines) - 1) vertices = lines[lineId] else: vertices = fGeom.asPolyline() # pick random segment if len(vertices) == 2: vid = 0 else: vid = random.randint(0, len(vertices) - 2) startPoint = vertices[vid] endPoint = vertices[vid + 1] length = da.measureLine(startPoint, endPoint) dist = length * random.random() if dist > minDistance: d = dist / (length - dist) rx = (startPoint.x() + d * endPoint.x()) / (1 + d) ry = (startPoint.y() + d * endPoint.y()) / (1 + d) # generate random point pnt = QgsPoint(rx, ry) geom = QgsGeometry.fromPoint(pnt) if vector.checkMinDistance(pnt, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) writer.addFeature(f) index.insertFeature(f) points[nPoints] = pnt nPoints += 1 progress.setPercentage(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self.tr('Can not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) del writer
def test_make_features_compatible_attributes(self): """Test corner cases for attributes""" # Test feature with attributes fields = QgsFields() fields.append(QgsField('int_f', QVariant.Int)) fields.append(QgsField('str_f', QVariant.String)) f1 = QgsFeature(fields) f1['int_f'] = 1 f1['str_f'] = 'str' f1.setGeometry(QgsGeometry.fromWkt('Point(9 45)')) f2 = f1 QgsVectorLayerUtils.matchAttributesToFields(f2, fields) self.assertEqual(f1.attributes(), f2.attributes()) self.assertTrue(f1.geometry().asWkt(), f2.geometry().asWkt()) # Test pad with 0 with fields f1.setAttributes([]) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 2) self.assertEqual(f1.attributes()[0], QVariant()) self.assertEqual(f1.attributes()[1], QVariant()) # Test pad with 0 without fields f1 = QgsFeature() QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 2) self.assertEqual(f1.attributes()[0], QVariant()) self.assertEqual(f1.attributes()[1], QVariant()) # Test drop extra attrs f1 = QgsFeature(fields) f1.setAttributes([1, 'foo', 'extra']) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 2) self.assertEqual(f1.attributes()[0], 1) self.assertEqual(f1.attributes()[1], 'foo') # Rearranged fields fields2 = QgsFields() fields2.append(QgsField('str_f', QVariant.String)) fields2.append(QgsField('int_f', QVariant.Int)) f1 = QgsFeature(fields2) f1.setAttributes([1, 'foo', 'extra']) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 2) self.assertEqual(f1.attributes()[0], 'foo') self.assertEqual(f1.attributes()[1], 1) # mixed fields2.append(QgsField('extra', QVariant.String)) fields.append(QgsField('extra2', QVariant.Int)) f1.setFields(fields2) f1.setAttributes([1, 'foo', 'blah']) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 3) self.assertEqual(f1.attributes()[0], 'foo') self.assertEqual(f1.attributes()[1], 1) self.assertEqual(f1.attributes()[2], QVariant()) fields.append(QgsField('extra', QVariant.Int)) f1.setAttributes([1, 'foo', 'blah']) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 4) self.assertEqual(f1.attributes()[0], 1) self.assertEqual(f1.attributes()[1], 'foo') self.assertEqual(f1.attributes()[2], 'blah') self.assertEqual(f1.attributes()[3], QVariant()) # case insensitive fields2.append(QgsField('extra3', QVariant.String)) fields.append(QgsField('EXTRA3', QVariant.Int)) f1.setFields(fields2) f1.setAttributes([1, 'foo', 'blah', 'blergh']) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 5) self.assertEqual(f1.attributes()[0], 'foo') self.assertEqual(f1.attributes()[1], 1) self.assertEqual(f1.attributes()[2], QVariant()) self.assertEqual(f1.attributes()[3], 'blah') self.assertEqual(f1.attributes()[4], 'blergh')
class FieldsMapper(QgisFeatureBasedAlgorithm): INPUT_LAYER = 'INPUT_LAYER' FIELDS_MAPPING = 'FIELDS_MAPPING' OUTPUT_LAYER = 'OUTPUT_LAYER' def group(self): return self.tr('Vector table') def groupId(self): return 'vectortable' def tags(self): return self.tr('attributes,table').split(',') def initParameters(self, config=None): fields_mapping = FieldsMapper.ParameterFieldsMapping( self.FIELDS_MAPPING, description=self.tr('Fields mapping')) fields_mapping.setMetadata({ 'widget_wrapper': 'processing.algs.qgis.ui.FieldsMappingPanel.FieldsMappingWidgetWrapper' }) self.addParameter(fields_mapping) def name(self): return 'refactorfields' def displayName(self): return self.tr('Refactor fields') def outputName(self): return self.tr('Refactored') def inputLayerTypes(self): return [QgsProcessing.TypeVector] def parameterAsFieldsMapping(self, parameters, name, context): return parameters[name] def supportInPlaceEdit(self, layer): return False def prepareAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, 'INPUT', context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, 'INPUT')) mapping = self.parameterAsFieldsMapping(parameters, self.FIELDS_MAPPING, context) self.fields = QgsFields() self.expressions = [] da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs(), context.transformContext()) da.setEllipsoid(context.project().ellipsoid()) # create an expression context using thread safe processing context self.expr_context = self.createExpressionContext( parameters, context, source) for field_def in mapping: self.fields.append( QgsField(name=field_def['name'], type=field_def['type'], typeName="", len=field_def.get('length', 0), prec=field_def.get('precision', 0))) if field_def['expression']: expression = QgsExpression(field_def['expression']) expression.setGeomCalculator(da) expression.setDistanceUnits(context.project().distanceUnits()) expression.setAreaUnits(context.project().areaUnits()) if expression.hasParserError(): feedback.reportError( self.tr(u'Parser error in expression "{}": {}').format( expression.expression(), expression.parserErrorString())) return False self.expressions.append(expression) else: self.expressions.append(None) return True def outputFields(self, inputFields): return self.fields def processAlgorithm(self, parameters, context, feeback): for expression in self.expressions: if expression is not None: expression.prepare(self.expr_context) self._row_number = 0 return super().processAlgorithm(parameters, context, feeback) def processFeature(self, feature, context, feedback): attributes = [] for expression in self.expressions: if expression is not None: self.expr_context.setFeature(feature) self.expr_context.lastScope().setVariable( "row_number", self._row_number) value = expression.evaluate(self.expr_context) if expression.hasEvalError(): raise QgsProcessingException( self.tr( u'Evaluation error in expression "{}": {}').format( expression.expression(), expression.evalErrorString())) attributes.append(value) else: attributes.append(NULL) feature.setAttributes(attributes) self._row_number += 1 return [feature] class ParameterFieldsMappingType(QgsProcessingParameterType): def __init__(self): super().__init__() def create(self, name): return FieldsMapper.ParameterFieldsMapping(name) def metadata(self): return { 'widget_wrapper': 'processing.algs.qgis.ui.FieldsMappingPanel.FieldsMappingWidgetWrapper' } def name(self): return QCoreApplication.translate('Processing', 'Fields Mapper') def id(self): return 'fields_mapping' def pythonImportString(self): return 'from processing.algs.qgis.FieldsMapper import FieldsMapper' def className(self): return 'FieldsMapper.ParameterFieldsMapping' def description(self): return QCoreApplication.translate( 'Processing', 'A mapping of field names to field type definitions and expressions. Used for the refactor fields algorithm.' ) class ParameterFieldsMapping(QgsProcessingParameterDefinition): def __init__(self, name, description='', parentLayerParameterName='INPUT'): super().__init__(name, description) self._parentLayerParameter = parentLayerParameterName def clone(self): copy = FieldsMapper.ParameterFieldsMapping( self.name(), self.description(), self._parentLayerParameter) return copy def type(self): return self.typeName() @staticmethod def typeName(): return 'fields_mapping' def checkValueIsAcceptable(self, value, context=None): if not isinstance(value, list): return False for field_def in value: if not isinstance(field_def, dict): return False if 'name' not in field_def.keys(): return False if 'type' not in field_def.keys(): return False if 'expression' not in field_def.keys(): return False return True def valueAsPythonString(self, value, context): return str(value) def asScriptCode(self): raise NotImplementedError() @classmethod def fromScriptCode(cls, name, description, isOptional, definition): raise NotImplementedError() def parentLayerParameter(self): return self._parentLayerParameter
def __init__(self, destination, encoding, fields, geometryType, crs, options=None): self.destination = destination self.isNotFileBased = False self.layer = None self.writer = None if encoding is None: settings = QSettings() encoding = settings.value('/Processing/encoding', 'System', str) if self.destination.startswith(self.MEMORY_LAYER_PREFIX): self.isNotFileBased = True uri = QgsWkbTypes.displayString(geometryType) + "?uuid=" + str(uuid.uuid4()) if crs.isValid(): uri += '&crs=' + crs.authid() fieldsdesc = [] for f in fields: qgsfield = _toQgsField(f) fieldsdesc.append('field=%s:%s' % (qgsfield.name(), TYPE_MAP_MEMORY_LAYER.get(qgsfield.type(), "string"))) if fieldsdesc: uri += '&' + '&'.join(fieldsdesc) self.layer = QgsVectorLayer(uri, self.destination, 'memory') self.writer = self.layer.dataProvider() elif self.destination.startswith(self.POSTGIS_LAYER_PREFIX): self.isNotFileBased = True uri = QgsDataSourceUri(self.destination[len(self.POSTGIS_LAYER_PREFIX):]) connInfo = uri.connectionInfo() (success, user, passwd) = QgsCredentials.instance().get(connInfo, None, None) if success: QgsCredentials.instance().put(connInfo, user, passwd) else: raise GeoAlgorithmExecutionException("Couldn't connect to database") try: db = postgis.GeoDB(host=uri.host(), port=int(uri.port()), dbname=uri.database(), user=user, passwd=passwd) except postgis.DbError as e: raise GeoAlgorithmExecutionException( "Couldn't connect to database:\n%s" % e.message) def _runSQL(sql): try: db._exec_sql_and_commit(str(sql)) except postgis.DbError as e: raise GeoAlgorithmExecutionException( 'Error creating output PostGIS table:\n%s' % e.message) fields = [_toQgsField(f) for f in fields] fieldsdesc = ",".join('%s %s' % (f.name(), TYPE_MAP_POSTGIS_LAYER.get(f.type(), "VARCHAR")) for f in fields) _runSQL("CREATE TABLE %s.%s (%s)" % (uri.schema(), uri.table().lower(), fieldsdesc)) if geometryType != QgsWkbTypes.NullGeometry: _runSQL("SELECT AddGeometryColumn('{schema}', '{table}', 'the_geom', {srid}, '{typmod}', 2)".format( table=uri.table().lower(), schema=uri.schema(), srid=crs.authid().split(":")[-1], typmod=QgsWkbTypes.displayString(geometryType).upper())) self.layer = QgsVectorLayer(uri.uri(), uri.table(), "postgres") self.writer = self.layer.dataProvider() elif self.destination.startswith(self.SPATIALITE_LAYER_PREFIX): self.isNotFileBased = True uri = QgsDataSourceUri(self.destination[len(self.SPATIALITE_LAYER_PREFIX):]) try: db = spatialite.GeoDB(uri=uri) except spatialite.DbError as e: raise GeoAlgorithmExecutionException( "Couldn't connect to database:\n%s" % e.message) def _runSQL(sql): try: db._exec_sql_and_commit(str(sql)) except spatialite.DbError as e: raise GeoAlgorithmExecutionException( 'Error creating output Spatialite table:\n%s' % str(e)) fields = [_toQgsField(f) for f in fields] fieldsdesc = ",".join('%s %s' % (f.name(), TYPE_MAP_SPATIALITE_LAYER.get(f.type(), "VARCHAR")) for f in fields) _runSQL("DROP TABLE IF EXISTS %s" % uri.table().lower()) _runSQL("CREATE TABLE %s (%s)" % (uri.table().lower(), fieldsdesc)) if geometryType != QgsWkbTypes.NullGeometry: _runSQL("SELECT AddGeometryColumn('{table}', 'the_geom', {srid}, '{typmod}', 2)".format( table=uri.table().lower(), srid=crs.authid().split(":")[-1], typmod=QgsWkbTypes.displayString(geometryType).upper())) self.layer = QgsVectorLayer(uri.uri(), uri.table(), "spatialite") self.writer = self.layer.dataProvider() else: formats = QgsVectorFileWriter.supportedFiltersAndFormats() OGRCodes = {} for (key, value) in list(formats.items()): extension = str(key) extension = extension[extension.find('*.') + 2:] extension = extension[:extension.find(' ')] OGRCodes[extension] = value OGRCodes['dbf'] = "DBF file" extension = self.destination[self.destination.rfind('.') + 1:] if extension not in OGRCodes: extension = 'shp' self.destination = self.destination + '.shp' if geometryType == QgsWkbTypes.NoGeometry: if extension == 'shp': extension = 'dbf' self.destination = self.destination[:self.destination.rfind('.')] + '.dbf' if extension not in self.nogeometry_extensions: raise GeoAlgorithmExecutionException( "Unsupported format for tables with no geometry") qgsfields = QgsFields() for field in fields: qgsfields.append(_toQgsField(field)) # use default dataset/layer options dataset_options = QgsVectorFileWriter.defaultDatasetOptions(OGRCodes[extension]) layer_options = QgsVectorFileWriter.defaultLayerOptions(OGRCodes[extension]) self.writer = QgsVectorFileWriter(self.destination, encoding, qgsfields, geometryType, crs, OGRCodes[extension], dataset_options, layer_options)
from qgis.core import (QgsVectorLayer, QgsFeatureIterator, QgsFeature, QgsGeometry, QgsFields, QgsField, QgsVectorFileWriter, QgsWkbTypes) app = QgsApplication([], False) path_input_layer = Path( __file__).parent.parent / "Projekt1" / "data" / "nc.gpkg" path_output_layer = Path(__file__).parent / "outputs" / "convex_hull_nc.gpkg" layer_input: QgsVectorLayer = QgsVectorLayer(str(path_input_layer)) features: QgsFeatureIterator = layer_input.getFeatures() fields: QgsFields = QgsFields() fields.append(QgsField("name", QVariant.String)) writer: QgsVectorFileWriter = QgsVectorFileWriter(str(path_output_layer), "UTF-8", fields, QgsWkbTypes.Polygon, layer_input.sourceCrs()) feature: QgsFeature for feature in features: attrs = feature.attributes() print(attrs) geom: QgsGeometry = feature.geometry()
def processAlgorithm(self, parameters, context, feedback): spacing = self.parameterAsDouble(parameters, self.SPACING, context) inset = self.parameterAsDouble(parameters, self.INSET, context) randomize = self.parameterAsBoolean(parameters, self.RANDOMIZE, context) isSpacing = self.parameterAsBoolean(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 id = 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(QgsPoint( uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)), uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0)))) else: geom = QgsGeometry(QgsPoint(x, y)) if extent_engine.intersects(geom.constGet()): f.setAttributes([id]) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) x += pSpacing id += 1 count += 1 feedback.setProgress(int(count * total)) y = y - pSpacing return {self.OUTPUT: dest_id}
def testModel(self): conn = QgsProviderRegistry.instance().providerMetadata( 'postgres').createConnection(self.uri, {}) self.assertTrue(conn) model = QgsDatabaseTableModel(conn) self.assertGreaterEqual(model.rowCount(), 3) old_count = model.rowCount() self.assertEqual(model.columnCount(), 1) tables = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('qgis_test.someData', tables) self.assertIn('qgis_test.some_poly_data', tables) self.assertIn('information_schema.attributes', tables) self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleTableName), 'someData') self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleSchema), 'qgis_test') self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleComment), 'QGIS Test Table') self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleCrs), QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleCustomInfo), {}) self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleTableFlags), 4) self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleWkbType), QgsWkbTypes.Point) self.assertEqual( model.data( model.index(tables.index('qgis_test.some_poly_data'), 0, QModelIndex()), QgsDatabaseTableModel.RoleWkbType), QgsWkbTypes.Polygon) self.assertIsNone( model.data(model.index(model.rowCount(), 0, QModelIndex()), Qt.DisplayRole)) model.refresh() self.assertEqual(model.rowCount(), old_count) fields = QgsFields() fields.append(QgsField('test', QVariant.String)) conn.createVectorTable('qgis_test', 'myNewTable', fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem('EPSG:3857'), False, {}) self.assertEqual(model.rowCount(), old_count) model.refresh() self.assertEqual(model.rowCount(), old_count + 1) tables = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('qgis_test.someData', tables) self.assertIn('qgis_test.some_poly_data', tables) self.assertIn('information_schema.attributes', tables) self.assertIn('qgis_test.myNewTable', tables) conn.createVectorTable('qgis_test', 'myNewTable2', fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem('EPSG:3857'), False, {}) conn.createVectorTable('qgis_test', 'myNewTable3', fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem('EPSG:3857'), False, {}) model.refresh() self.assertEqual(model.rowCount(), old_count + 3) tables = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('qgis_test.someData', tables) self.assertIn('qgis_test.some_poly_data', tables) self.assertIn('information_schema.attributes', tables) self.assertIn('qgis_test.myNewTable', tables) self.assertIn('qgis_test.myNewTable2', tables) self.assertIn('qgis_test.myNewTable3', tables) conn.createVectorTable('qgis_test', 'myNewTable4', fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem('EPSG:3857'), False, {}) conn.dropVectorTable('qgis_test', 'myNewTable2') conn.dropVectorTable('qgis_test', 'myNewTable') model.refresh() self.assertEqual(model.rowCount(), old_count + 2) tables = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('qgis_test.someData', tables) self.assertIn('qgis_test.some_poly_data', tables) self.assertIn('information_schema.attributes', tables) self.assertNotIn('qgis_test.myNewTable', tables) self.assertNotIn('qgis_test.myNewTable2', tables) self.assertIn('qgis_test.myNewTable3', tables) self.assertIn('qgis_test.myNewTable4', tables) conn.dropVectorTable('qgis_test', 'myNewTable3') conn.dropVectorTable('qgis_test', 'myNewTable4') model.refresh() self.assertEqual(model.rowCount(), old_count) tables = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('qgis_test.someData', tables) self.assertIn('qgis_test.some_poly_data', tables) self.assertIn('information_schema.attributes', tables) self.assertNotIn('qgis_test.myNewTable', tables) self.assertNotIn('qgis_test.myNewTable2', tables) self.assertNotIn('qgis_test.myNewTable3', tables) self.assertNotIn('qgis_test.myNewTable4', tables)
def processAlgorithm(self, parameters, context, feedback): layer = self.parameterAsLayer(parameters, self.INPUT, context) fields = QgsFields() fields.append(QgsField('MINX', QVariant.Double)) fields.append(QgsField('MINY', QVariant.Double)) fields.append(QgsField('MAXX', QVariant.Double)) fields.append(QgsField('MAXY', QVariant.Double)) fields.append(QgsField('CNTX', QVariant.Double)) fields.append(QgsField('CNTY', QVariant.Double)) fields.append(QgsField('AREA', QVariant.Double)) fields.append(QgsField('PERIM', QVariant.Double)) fields.append(QgsField('HEIGHT', QVariant.Double)) fields.append(QgsField('WIDTH', QVariant.Double)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Polygon, layer.crs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) try: # may not be possible layer.updateExtents() except: pass rect = layer.extent() geometry = QgsGeometry.fromRect(rect) minx = rect.xMinimum() miny = rect.yMinimum() maxx = rect.xMaximum() maxy = rect.yMaximum() height = rect.height() width = rect.width() cntx = minx + width / 2.0 cnty = miny + height / 2.0 area = width * height perim = 2 * width + 2 * height feat = QgsFeature() feat.setGeometry(geometry) attrs = [ minx, miny, maxx, maxy, cntx, cnty, area, perim, height, width, ] feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) return {self.OUTPUT: dest_id}
def parse(self): """ Start parsing the osm file """ # Configuration for OGR gdal.SetConfigOption('OSM_CONFIG_FILE', self._osm_conf) gdal.SetConfigOption('OSM_USE_CUSTOM_INDEXING', 'NO') if not isfile(self.__osmFile): raise GeoAlgorithmException(tr('File does not exist')) uri = self.__osmFile + "|layername=" layers = {} # If loadOnly, no parsing required: # It's used only when we ask to open an osm file if self.__loadOnly: file_name = basename(self.__osmFile) for layer in self.__layers: layers[layer] = QgsVectorLayer(uri + layer, file_name + " " + layer, "ogr") if not layers[layer].isValid(): msg = tr("Error on the layer : {}").format(layer) raise GeoAlgorithmException(msg) return layers # Foreach layers for layer in self.__layers: self.signalText.emit(tr('Parsing layer : {}').format(layer)) layers[layer] = {} # Reading it with a QgsVectorLayer layers[layer]['vectorLayer'] = QgsVectorLayer( uri + layer, "test_" + layer, "ogr") if not layers[layer]['vectorLayer'].isValid(): msg = "Error on the layer : {}".format(layer) raise GeoAlgorithmException(msg) layers[layer]['vectorLayer'].setProviderEncoding('UTF-8') # Set some default tags layers[layer]['tags'] = ['full_id', 'osm_id', 'osm_type'] # Save the geometry type of the layer layers[layer]['geomType'] = layers[layer]['vectorLayer'].wkbType() # Set a featureCount layers[layer]['featureCount'] = 0 # Get the other_tags fields = layers[layer]['vectorLayer'].fields() field_names = [field.name() for field in fields] other_tags_index = field_names.index('other_tags') features = layers[layer]['vectorLayer'].getFeatures() for i, feature in enumerate(features): layers[layer]['featureCount'] += 1 # Improve the parsing if comma in whitelist, # we skip the parsing of tags, but featureCount is needed if self.__whiteListColumn[layer] == ',': continue # Get the "others_tags" field attributes = str(feature.attributes()[other_tags_index]) if attributes: h_store = QgsHstoreUtils.parse(attributes) for key in h_store.keys(): if key not in layers[layer]['tags']: # If the key in OSM is not already in the table if self.__whiteListColumn[layer]: if key in self.__whiteListColumn[layer]: layers[layer]['tags'].append(key) else: layers[layer]['tags'].append(key) percent = int(100 / len(self.__layers) * (i + 1)) self.signalPercentage.emit(percent) # Delete empty layers if this option is set to True if self.__deleteEmptyLayers: delete_layers = [] for keys, values in layers.items(): if values['featureCount'] < 1: delete_layers.append(keys) for layer in delete_layers: del layers[layer] # Creating GeoJSON files for each layers for layer in self.__layers: msg = tr('Creating memory layer : ' + layer) self.signalText.emit(msg) self.signalPercentage.emit(0) # Adding the attribute table fields = QgsFields() for key in layers[layer]['tags']: fields.append(QgsField(key, QVariant.String)) layers[layer]['vector_layer'] = ( QgsMemoryProviderUtils.createMemoryLayer( layer, fields, layers[layer]['geomType'], layers[layer]['vectorLayer'].crs())) layers[layer]['vector_layer'].startEditing() # Foreach feature in the layer features = layers[layer]['vectorLayer'].getFeatures() for i, feature in enumerate(features): fet = QgsFeature() fet.setGeometry(feature.geometry()) new_attributes = [] attributes = feature.attributes() if layer in ['points', 'lines', 'multilinestrings']: if layer == 'points': osm_type = "node" elif layer == 'lines': osm_type = "way" elif layer == 'multilinestrings': osm_type = 'relation' new_attributes.append(self.DIC_OSM_TYPE[osm_type] + str(attributes[0])) new_attributes.append(attributes[0]) new_attributes.append(osm_type) if attributes[1]: h_store = QgsHstoreUtils.parse(str(attributes[1])) for tag in layers[layer]['tags'][3:]: if str(tag) in h_store: new_attributes.append(h_store[tag]) else: new_attributes.append("") fet.setAttributes(new_attributes) layers[layer]['vector_layer'].addFeature(fet) elif layer == 'multipolygons': if attributes[0]: osm_type = "relation" new_attributes.append(self.DIC_OSM_TYPE[osm_type] + str(attributes[0])) new_attributes.append(str(attributes[0])) else: osm_type = "way" new_attributes.append(self.DIC_OSM_TYPE[osm_type] + str(attributes[1])) new_attributes.append(attributes[1]) new_attributes.append(osm_type) h_store = QgsHstoreUtils.parse(str(attributes[2])) for tag in layers[layer]['tags'][3:]: if str(tag) in h_store: new_attributes.append(h_store[tag]) else: new_attributes.append("") fet.setAttributes(new_attributes) layers[layer]['vector_layer'].addFeature(fet) percentage = int(100 / layers[layer]['featureCount'] * (i + 1)) self.signalPercentage.emit(percentage) layers[layer]['vector_layer'].commitChanges() return layers
def processAlgorithm(self, parameters, context, feedback): idx = self.parameterAsEnum(parameters, self.TYPE, context) hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context) vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context) hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context) vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context) crs = self.parameterAsCrs(parameters, self.CRS, context) bbox = self.parameterAsExtent(parameters, self.EXTENT, context, crs) if hSpacing <= 0 or vSpacing <= 0: raise QgsProcessingException( self.tr('Invalid grid spacing: {0}/{1}').format( hSpacing, vSpacing)) if bbox.width() < hSpacing: raise QgsProcessingException( self.tr( 'Horizontal spacing is too large for the covered area')) if hSpacing <= hOverlay or vSpacing <= vOverlay: raise QgsProcessingException( self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay)) if bbox.height() < vSpacing: raise QgsProcessingException( self.tr('Vertical spacing is too large for the covered area')) fields = QgsFields() fields.append(QgsField('left', QVariant.Double, '', 24, 16)) fields.append(QgsField('top', QVariant.Double, '', 24, 16)) fields.append(QgsField('right', QVariant.Double, '', 24, 16)) fields.append(QgsField('bottom', QVariant.Double, '', 24, 16)) fields.append(QgsField('id', QVariant.Int, '', 10, 0)) if idx == 0: outputWkb = QgsWkbTypes.Point elif idx == 1: outputWkb = QgsWkbTypes.LineString else: outputWkb = QgsWkbTypes.Polygon (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, outputWkb, crs) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) if idx == 0: self._pointGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback) elif idx == 1: self._lineGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback) elif idx == 2: self._rectangleGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback) elif idx == 3: self._diamondGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback) elif idx == 4: self._hexagonGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback) return {self.OUTPUT: dest_id}
def testWidget(self): """Test widget operations""" widget = QgsFieldMappingWidget() for i in range(10): widget.appendField(QgsField(str(i))) self.assertTrue(widget.model().rowCount(QModelIndex()), 10) def _compare(widget, expected): actual = [] for field in widget.mapping(): actual.append(int(field.originalName)) self.assertEqual(actual, expected) _compare(widget, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) selection_model = widget.selectionModel() selection_model.clear() for i in range(0, 10, 2): selection_model.select(widget.model().index(i, 0), QItemSelectionModel.Select) self.assertTrue(widget.moveSelectedFieldsDown()) _compare(widget, [1, 0, 3, 2, 5, 4, 7, 6, 9, 8]) selection_model.clear() for i in range(1, 10, 2): selection_model.select(widget.model().index(i, 0), QItemSelectionModel.Select) self.assertTrue(widget.moveSelectedFieldsUp()) _compare(widget, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) selection_model.clear() for i in range(0, 10, 2): selection_model.select(widget.model().index(i, 0), QItemSelectionModel.Select) self.assertTrue(widget.removeSelectedFields()) _compare(widget, [1, 3, 5, 7, 9]) # Test set destination fields widget.setSourceFields(self.source_fields) widget.setDestinationFields(self.destination_fields) mapping = widget.mapping() self.assertEqual(mapping[0].field.name(), 'destination_field1') self.assertEqual(mapping[1].field.name(), 'destination_field2') self.assertEqual(mapping[2].field.name(), 'destination_field3') self.assertEqual(mapping[0].originalName, 'destination_field1') self.assertEqual(mapping[1].originalName, 'destination_field2') self.assertEqual(mapping[2].originalName, 'destination_field3') # Test constraints f = QgsField('constraint_field', QVariant.Int) constraints = QgsFieldConstraints() constraints.setConstraint(QgsFieldConstraints.ConstraintNotNull, QgsFieldConstraints.ConstraintOriginProvider) constraints.setConstraint(QgsFieldConstraints.ConstraintExpression, QgsFieldConstraints.ConstraintOriginProvider) constraints.setConstraint(QgsFieldConstraints.ConstraintUnique, QgsFieldConstraints.ConstraintOriginProvider) f.setConstraints(constraints) fields = QgsFields() fields.append(f) widget.setDestinationFields(fields) self.assertEqual( widget.model().data(widget.model().index(0, 5, QModelIndex()), Qt.DisplayRole), "Constraints active") self.assertEqual( widget.model().data(widget.model().index(0, 5, QModelIndex()), Qt.ToolTipRole), "Unique<br>Not null<br>Expression") self.assertEqual( widget.model().data(widget.model().index(0, 5, QModelIndex()), Qt.BackgroundColorRole), QColor(255, 224, 178))
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) group_field_name = self.parameterAsString(parameters, self.GROUP_FIELD, context) order_field_name = self.parameterAsString(parameters, self.ORDER_FIELD, context) date_format = self.parameterAsString(parameters, self.DATE_FORMAT, context) text_dir = self.parameterAsString(parameters, self.OUTPUT_TEXT_DIR, context) group_field_index = source.fields().lookupField(group_field_name) order_field_index = source.fields().lookupField(order_field_name) if group_field_index >= 0: group_field_def = source.fields().at(group_field_index) else: group_field_def = None order_field_def = source.fields().at(order_field_index) fields = QgsFields() if group_field_def is not None: fields.append(group_field_def) begin_field = QgsField(order_field_def) begin_field.setName('begin') fields.append(begin_field) end_field = QgsField(order_field_def) end_field.setName('end') fields.append(end_field) output_wkb = QgsWkbTypes.LineString if QgsWkbTypes.hasM(source.wkbType()): output_wkb = QgsWkbTypes.addM(output_wkb) if QgsWkbTypes.hasZ(source.wkbType()): output_wkb = QgsWkbTypes.addZ(output_wkb) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, output_wkb, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) points = dict() features = source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes( [group_field_index, order_field_index]), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks) 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 point = f.geometry().constGet().clone() if group_field_index >= 0: group = f[group_field_index] else: group = 1 order = f[order_field_index] if date_format != '': order = datetime.strptime(str(order), date_format) if group in points: points[group].append((order, point)) else: points[group] = [(order, point)] feedback.setProgress(int(current * total)) feedback.setProgress(0) da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs(), context.transformContext()) da.setEllipsoid(context.project().ellipsoid()) current = 0 total = 100.0 / len(points) if points else 1 for group, vertices in points.items(): if feedback.isCanceled(): break vertices.sort(key=lambda x: (x[0] is None, x[0])) f = QgsFeature() attributes = [] if group_field_index >= 0: attributes.append(group) attributes.extend([vertices[0][0], vertices[-1][0]]) f.setAttributes(attributes) line = [node[1] for node in vertices] if text_dir: fileName = os.path.join(text_dir, '%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') for i in range(len(line)): if i == 0: fl.write('startAt=%f;%f;90\n' % (line[i].x(), line[i].y())) fl.write('survey=Polygonal\n') fl.write('[data]\n') else: angle = line[i - 1].azimuth(line[i]) distance = da.measureLine(QgsPointXY(line[i - 1]), QgsPointXY(line[i])) fl.write('%f;%f;90\n' % (angle, distance)) f.setGeometry(QgsGeometry(QgsLineString(line))) sink.addFeature(f, QgsFeatureSink.FastInsert) current += 1 feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def testCreateMemoryLayer(self): """ Test QgsMemoryProviderUtils.createMemoryLayer() """ # no fields layer = QgsMemoryProviderUtils.createMemoryLayer( 'my name', QgsFields()) self.assertTrue(layer.isValid()) self.assertEqual(layer.name(), 'my name') self.assertTrue(layer.fields().isEmpty()) # similar layers should have unique sources layer2 = QgsMemoryProviderUtils.createMemoryLayer( 'my name', QgsFields()) self.assertNotEqual(layer.source(), layer2.source()) # geometry type layer = QgsMemoryProviderUtils.createMemoryLayer( 'my name', QgsFields(), QgsWkbTypes.Point) self.assertTrue(layer.isValid()) self.assertEqual(layer.wkbType(), QgsWkbTypes.Point) layer = QgsMemoryProviderUtils.createMemoryLayer( 'my name', QgsFields(), QgsWkbTypes.PolygonZM) self.assertTrue(layer.isValid()) self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM) # crs layer = QgsMemoryProviderUtils.createMemoryLayer( 'my name', QgsFields(), QgsWkbTypes.PolygonZM, QgsCoordinateReferenceSystem.fromEpsgId(3111)) self.assertTrue(layer.isValid()) self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM) self.assertTrue(layer.crs().isValid()) self.assertEqual(layer.crs().authid(), 'EPSG:3111') # fields fields = QgsFields() fields.append(QgsField("string", QVariant.String)) fields.append(QgsField("long", QVariant.LongLong)) fields.append(QgsField("double", QVariant.Double)) fields.append(QgsField("integer", QVariant.Int)) fields.append(QgsField("date", QVariant.Date)) fields.append(QgsField("datetime", QVariant.DateTime)) fields.append(QgsField("time", QVariant.Time)) fields.append(QgsField("#complex_name", QVariant.String)) fields.append(QgsField("complex/name", QVariant.String)) fields.append(QgsField("binaryfield", QVariant.ByteArray)) fields.append(QgsField("boolfield", QVariant.Bool)) layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields) self.assertTrue(layer.isValid()) self.assertFalse(layer.fields().isEmpty()) self.assertEqual(len(layer.fields()), len(fields)) for i in range(len(fields)): self.assertEqual(layer.fields()[i].name(), fields[i].name()) self.assertEqual(layer.fields()[i].type(), fields[i].type()) self.assertEqual(layer.fields()[i].length(), fields[i].length()) self.assertEqual(layer.fields()[i].precision(), fields[i].precision(), fields[i].name()) # unsupported field type fields = QgsFields() fields.append(QgsField("rect", QVariant.RectF)) layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields) self.assertTrue(layer.isValid()) self.assertFalse(layer.fields().isEmpty()) self.assertEqual(layer.fields()[0].name(), 'rect') self.assertEqual(layer.fields()[0].type(), QVariant.String) # should be mapped to string # field precision fields = QgsFields() fields.append(QgsField("string", QVariant.String, len=10)) fields.append(QgsField("long", QVariant.LongLong, len=6)) fields.append(QgsField("double", QVariant.Double, len=10, prec=7)) fields.append(QgsField("double2", QVariant.Double, len=-1, prec=-1)) layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields) self.assertTrue(layer.isValid()) self.assertFalse(layer.fields().isEmpty()) self.assertEqual(len(layer.fields()), len(fields)) for i in range(len(fields)): self.assertEqual(layer.fields()[i].name(), fields[i].name()) self.assertEqual(layer.fields()[i].type(), fields[i].type()) self.assertEqual(layer.fields()[i].length(), fields[i].length()) self.assertEqual(layer.fields()[i].precision(), fields[i].precision())
def linearMatrix(self, parameters, context, source, inField, target_source, targetField, same_source_and_target, matType, nPoints, feedback): if same_source_and_target: # need to fetch an extra point from the index, since the closest match will always be the same # as the input feature nPoints += 1 inIdx = source.fields().lookupField(inField) outIdx = target_source.fields().lookupField(targetField) fields = QgsFields() input_id_field = source.fields()[inIdx] input_id_field.setName('InputID') fields.append(input_id_field) if matType == 0: target_id_field = target_source.fields()[outIdx] target_id_field.setName('TargetID') fields.append(target_id_field) fields.append(QgsField('Distance', QVariant.Double)) else: fields.append(QgsField('MEAN', QVariant.Double)) fields.append(QgsField('STDDEV', QVariant.Double)) fields.append(QgsField('MIN', QVariant.Double)) fields.append(QgsField('MAX', QVariant.Double)) out_wkb = QgsWkbTypes.multiType( source.wkbType()) if matType == 0 else source.wkbType() (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, out_wkb, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) index = QgsSpatialIndex( target_source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes( []).setDestinationCrs(source.sourceCrs(), context.transformContext())), feedback) distArea = QgsDistanceArea() distArea.setSourceCrs(source.sourceCrs(), context.transformContext()) distArea.setEllipsoid(context.project().ellipsoid()) features = source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes([inIdx])) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, inFeat in enumerate(features): if feedback.isCanceled(): break inGeom = inFeat.geometry() inID = str(inFeat.attributes()[inIdx]) featList = index.nearestNeighbor(inGeom.asPoint(), nPoints) distList = [] vari = 0.0 request = QgsFeatureRequest().setFilterFids( featList).setSubsetOfAttributes([outIdx]).setDestinationCrs( source.sourceCrs(), context.transformContext()) for outFeat in target_source.getFeatures(request): if feedback.isCanceled(): break if same_source_and_target and inFeat.id() == outFeat.id(): continue outID = outFeat.attributes()[outIdx] outGeom = outFeat.geometry() dist = distArea.measureLine(inGeom.asPoint(), outGeom.asPoint()) if matType == 0: out_feature = QgsFeature() out_geom = QgsGeometry.unaryUnion( [inFeat.geometry(), outFeat.geometry()]) out_feature.setGeometry(out_geom) out_feature.setAttributes([inID, outID, dist]) sink.addFeature(out_feature, QgsFeatureSink.FastInsert) else: distList.append(float(dist)) if matType != 0: mean = sum(distList) / len(distList) for i in distList: vari += (i - mean) * (i - mean) vari = math.sqrt(vari / len(distList)) out_feature = QgsFeature() out_feature.setGeometry(inFeat.geometry()) out_feature.setAttributes( [inID, mean, vari, min(distList), max(distList)]) sink.addFeature(out_feature, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) join_source = self.parameterAsSource(parameters, self.JOIN, context) join_fields = self.parameterAsFields(parameters, self.JOIN_FIELDS, context) method = self.parameterAsEnum(parameters, self.METHOD, context) discard_nomatch = self.parameterAsBool(parameters, self.DISCARD_NONMATCHING, context) source_fields = source.fields() fields_to_join = QgsFields() join_field_indexes = [] if not join_fields: fields_to_join = join_source.fields() join_field_indexes = [i for i in range(len(fields_to_join))] else: for f in join_fields: idx = join_source.fields().lookupField(f) join_field_indexes.append(idx) if idx >= 0: fields_to_join.append(join_source.fields().at(idx)) out_fields = QgsProcessingUtils.combineFields(source_fields, fields_to_join) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, out_fields, source.wkbType(), source.sourceCrs()) # do the join # build a list of 'reversed' predicates, because in this function # we actually test the reverse of what the user wants (allowing us # to prepare geometries and optimise the algorithm) predicates = [ self.reversed_predicates[self.predicates[i][0]] for i in self.parameterAsEnums(parameters, self.PREDICATE, context) ] remaining = set() if not discard_nomatch: remaining = set(source.allFeatureIds()) added_set = set() request = QgsFeatureRequest().setSubsetOfAttributes( join_field_indexes).setDestinationCrs(source.sourceCrs(), context.transformContext()) features = join_source.getFeatures(request) total = 100.0 / join_source.featureCount() if join_source.featureCount( ) else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue bbox = f.geometry().boundingBox() engine = None request = QgsFeatureRequest().setFilterRect(bbox) for test_feat in source.getFeatures(request): if feedback.isCanceled(): break if method == 1 and test_feat.id() in added_set: # already added this feature, and user has opted to only output first match continue join_attributes = [] for a in join_field_indexes: join_attributes.append(f.attributes()[a]) if engine is None: engine = QgsGeometry.createGeometryEngine( f.geometry().constGet()) engine.prepareGeometry() for predicate in predicates: if getattr(engine, predicate)(test_feat.geometry().constGet()): added_set.add(test_feat.id()) # join attributes and add attributes = test_feat.attributes() attributes.extend(join_attributes) output_feature = test_feat output_feature.setAttributes(attributes) sink.addFeature(output_feature, QgsFeatureSink.FastInsert) break feedback.setProgress(int(current * total)) if not discard_nomatch: remaining = remaining.difference(added_set) for f in source.getFeatures(QgsFeatureRequest().setFilterFids( list(remaining))): if feedback.isCanceled(): break sink.addFeature(f, QgsFeatureSink.FastInsert) return {self.OUTPUT: dest_id}
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 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() 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()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) 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 if not f.hasGeometry(): continue 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 testJSONExporter(self): """ test converting features to GeoJSON """ fields = QgsFields() fields.append(QgsField("name", QVariant.String)) fields.append(QgsField("cost", QVariant.Double)) fields.append(QgsField("population", QVariant.Int)) feature = QgsFeature(fields, 5) feature.setGeometry(QgsGeometry(QgsPointV2(5, 6))) feature.setAttributes(['Valsier Peninsula', 6.8, 198]) exporter = QgsJSONExporter() expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) # test with linestring for bbox inclusion l = QgsLineStringV2() l.setPoints([QgsPointV2(5, 6), QgsPointV2(15, 16)]) feature.setGeometry(QgsGeometry(QgsLineStringV2(l))) expected = """{ "type":"Feature", "id":5, "bbox":[5, 6, 15, 16], "geometry": {"type": "LineString", "coordinates": [ [5, 6], [15, 16]]}, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) # test that precision is respected feature.setGeometry(QgsGeometry(QgsPointV2(5.444444444, 6.333333333))) exporter.setPrecision(3) self.assertEqual(exporter.precision(), 3) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5.444, 6.333]}, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) feature.setGeometry(QgsGeometry(QgsPointV2(5, 6))) exporter.setPrecision(17) # test that attribute subset is respected exporter.setAttributes([0, 2]) self.assertEqual(exporter.attributes(), [0, 2]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula", "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setAttributes([1]) self.assertEqual(exporter.attributes(), [1]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "cost":6.8 } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setAttributes([]) # text excluding attributes exporter.setExcludedAttributes([1]) self.assertEqual(exporter.excludedAttributes(), [1]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula", "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setExcludedAttributes([1, 2]) self.assertEqual(exporter.excludedAttributes(), [1, 2]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula" } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setExcludedAttributes([0, 1, 2]) self.assertEqual(exporter.excludedAttributes(), [0, 1, 2]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":null }""" self.assertEqual(exporter.exportFeature(feature), expected) # test that excluded attributes take precedence over included exporter.setAttributes([1, 2]) exporter.setExcludedAttributes([0, 1]) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setAttributes([]) exporter.setExcludedAttributes([]) # test excluding geometry exporter.setIncludeGeometry(False) self.assertEqual(exporter.includeGeometry(), False) feature.setGeometry(QgsGeometry(QgsLineStringV2(l))) expected = """{ "type":"Feature", "id":5, "geometry":null, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setIncludeGeometry(True) feature.setGeometry(QgsGeometry(QgsPointV2(5, 6))) # test excluding attributes exporter.setIncludeAttributes(False) self.assertEqual(exporter.includeAttributes(), False) expected = """{ "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":null }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setIncludeGeometry(False) expected = """{ "type":"Feature", "id":5, "geometry":null, "properties":null }""" self.assertEqual(exporter.exportFeature(feature), expected) exporter.setIncludeAttributes(True) # test overriding ID expected = """{ "type":"Feature", "id":29, "geometry":null, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }""" self.assertEqual(exporter.exportFeature(feature, id=29), expected) # test injecting extra attributes expected = """{ "type":"Feature", "id":5, "geometry":null, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198, "extra":"val1", "extra2":2 } }""" self.assertEqual(exporter.exportFeature(feature, extraProperties={"extra": "val1", "extra2": 2}), expected) exporter.setIncludeAttributes(False) expected = """{ "type":"Feature", "id":5, "geometry":null, "properties":{ "extra":"val1", "extra2":{"nested_map":5, "nested_map2":"val"}, "extra3":[1,2,3] } }""" self.assertEqual(exporter.exportFeature(feature, extraProperties={"extra": "val1", "extra2": {"nested_map": 5, "nested_map2": "val"}, "extra3": [1, 2, 3]}), expected) exporter.setIncludeGeometry(True)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) sampled_raster = self.parameterAsRasterLayer(parameters, self.RASTERCOPY, context) columnPrefix = self.parameterAsString(parameters, self.COLUMN_PREFIX, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) source_fields = source.fields() raster_fields = QgsFields() # append field to vector as columnPrefix_bandCount for b in range(sampled_raster.bandCount()): raster_fields.append( QgsField(columnPrefix + str('_{}'.format(b + 1)), QVariant.Double)) # combine all the vector fields out_fields = QgsProcessingUtils.combineFields(source_fields, raster_fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, out_fields, source.wkbType(), source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) total = 100.0 / source.featureCount() if source.featureCount() else 0 features = source.getFeatures() # create the coordinates transformation context ct = QgsCoordinateTransform(source.sourceCrs(), sampled_raster.crs(), context.transformContext()) for n, i in enumerate(source.getFeatures()): attrs = i.attributes() if i.geometry().isMultipart( ) and i.geometry().constGet().partCount() > 1: sink.addFeature(i, QgsFeatureSink.FastInsert) feedback.setProgress(int(n * total)) feedback.reportError( self.tr( 'Impossible to sample data of multipart feature {}.'). format(i.id())) continue # get the feature geometry as point point = QgsPointXY() if i.geometry().isMultipart(): point = i.geometry().asMultiPoint()[0] else: point = i.geometry().asPoint() # reproject to raster crs try: point = ct.transform(point) except QgsCsException: for b in range(sampled_raster.bandCount()): attrs.append(None) i.setAttributes(attrs) sink.addFeature(i, QgsFeatureSink.FastInsert) feedback.setProgress(int(n * total)) feedback.reportError( self.tr( 'Could not reproject feature {} to raster CRS').format( i.id())) continue for b in range(sampled_raster.bandCount()): value, ok = sampled_raster.dataProvider().sample(point, b + 1) if ok: attrs.append(value) else: attrs.append(NULL) i.setAttributes(attrs) sink.addFeature(i, QgsFeatureSink.FastInsert) feedback.setProgress(int(n * total)) return {self.OUTPUT: dest_id}
class PyProvider(QgsVectorDataProvider): next_feature_id = 1 @classmethod def providerKey(cls): """Returns the memory provider key""" return 'pythonprovider' @classmethod def description(cls): """Returns the memory provider description""" return 'Python Test Provider' @classmethod def createProvider(cls, uri, providerOptions): return PyProvider(uri, providerOptions) # Implementation of functions from QgsVectorDataProvider def __init__(self, uri='', providerOptions=QgsDataProvider.ProviderOptions()): super().__init__(uri) # Use the memory layer to parse the uri mlayer = QgsVectorLayer(uri, 'ml', 'memory') self.setNativeTypes(mlayer.dataProvider().nativeTypes()) self._uri = uri self._fields = mlayer.fields() self._wkbType = mlayer.wkbType() self._features = {} self._extent = QgsRectangle() self._extent.setMinimal() self._subset_string = '' self._crs = mlayer.crs() self._spatialindex = None self._provider_options = providerOptions if 'index=yes'in self._uri: self.createSpatialIndex() def featureSource(self): return PyFeatureSource(self) def dataSourceUri(self, expandAuthConfig=True): return self._uri def storageType(self): return "Python test memory storage" def getFeatures(self, request=QgsFeatureRequest()): return QgsFeatureIterator(PyFeatureIterator(PyFeatureSource(self), request)) def uniqueValues(self, fieldIndex, limit=1): results = set() if fieldIndex >= 0 and fieldIndex < self.fields().count(): req = QgsFeatureRequest() req.setFlags(QgsFeatureRequest.NoGeometry) req.setSubsetOfAttributes([fieldIndex]) for f in self.getFeatures(req): results.add(f.attributes()[fieldIndex]) return results def wkbType(self): return self._wkbType def featureCount(self): if not self.subsetString(): return len(self._features) else: req = QgsFeatureRequest() req.setFlags(QgsFeatureRequest.NoGeometry) req.setSubsetOfAttributes([]) return len([f for f in self.getFeatures(req)]) def fields(self): return self._fields def addFeatures(self, flist, flags=None): added = False f_added = [] for f in flist: if f.hasGeometry() and (f.geometry().wkbType() != self.wkbType()): return added, f_added for f in flist: _f = QgsFeature(self.fields()) _f.setGeometry(f.geometry()) attrs = [None for i in range(_f.fields().count())] for i in range(min(len(attrs), len(f.attributes()))): attrs[i] = f.attributes()[i] _f.setAttributes(attrs) _f.setId(self.next_feature_id) self._features[self.next_feature_id] = _f self.next_feature_id += 1 added = True f_added.append(_f) if self._spatialindex is not None: self._spatialindex.insertFeature(_f) if len(f_added): self.clearMinMaxCache() self.updateExtents() return added, f_added def deleteFeatures(self, ids): if not ids: return True removed = False for id in ids: if id in self._features: if self._spatialindex is not None: self._spatialindex.deleteFeature(self._features[id]) del self._features[id] removed = True if removed: self.clearMinMaxCache() self.updateExtents() return removed def addAttributes(self, attrs): try: for new_f in attrs: if new_f.type() not in (QVariant.Int, QVariant.Double, QVariant.String, QVariant.Date, QVariant.Time, QVariant.DateTime, QVariant.LongLong, QVariant.StringList, QVariant.List): continue self._fields.append(new_f) for f in self._features.values(): old_attrs = f.attributes() old_attrs.append(None) f.setAttributes(old_attrs) self.clearMinMaxCache() return True except Exception: return False def renameAttributes(self, renamedAttributes): result = True # We need to replace all fields because python bindings return a copy from [] and at() new_fields = [self._fields.at(i) for i in range(self._fields.count())] for fieldIndex, new_name in renamedAttributes.items(): if fieldIndex < 0 or fieldIndex >= self._fields.count(): result = False continue if self._fields.indexFromName(new_name) >= 0: #field name already in use result = False continue new_fields[fieldIndex].setName(new_name) if result: self._fields = QgsFields() for i in range(len(new_fields)): self._fields.append(new_fields[i]) return result def deleteAttributes(self, attributes): attrIdx = sorted(attributes, reverse=True) # delete attributes one-by-one with decreasing index for idx in attrIdx: self._fields.remove(idx) for f in self._features.values(): attr = f.attributes() del(attr[idx]) f.setAttributes(attr) self.clearMinMaxCache() return True def changeAttributeValues(self, attr_map): for feature_id, attrs in attr_map.items(): try: f = self._features[feature_id] except KeyError: continue for k, v in attrs.items(): f.setAttribute(k, v) self.clearMinMaxCache() return True def changeGeometryValues(self, geometry_map): for feature_id, geometry in geometry_map.items(): try: f = self._features[feature_id] f.setGeometry(geometry) except KeyError: continue self.updateExtents() return True def allFeatureIds(self): return list(self._features.keys()) def subsetString(self): return self._subset_string def setSubsetString(self, subsetString): if subsetString == self._subset_string: return True self._subset_string = subsetString self.updateExtents() self.clearMinMaxCache() self.dataChanged.emit() return True def supportsSubsetString(self): return True def createSpatialIndex(self): if self._spatialindex is None: self._spatialindex = QgsSpatialIndex() for f in self._features.values(): self._spatialindex.insertFeature(f) return True def capabilities(self): return QgsVectorDataProvider.AddFeatures | QgsVectorDataProvider.DeleteFeatures | QgsVectorDataProvider.CreateSpatialIndex | QgsVectorDataProvider.ChangeGeometries | QgsVectorDataProvider.ChangeAttributeValues | QgsVectorDataProvider.AddAttributes | QgsVectorDataProvider.DeleteAttributes | QgsVectorDataProvider.RenameAttributes | QgsVectorDataProvider.SelectAtId | QgsVectorDataProvider. CircularGeometries #/* Implementation of functions from QgsDataProvider */ def name(self): return self.providerKey() def extent(self): if self._extent.isEmpty() and self._features: self._extent.setMinimal() if not self._subset_string: # fast way - iterate through all features for feat in self._features.values(): if feat.hasGeometry(): self._extent.combineExtentWith(feat.geometry().boundingBox()) else: for f in self.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([])): if f.hasGeometry(): self._extent.combineExtentWith(f.geometry().boundingBox()) elif not self._features: self._extent.setMinimal() return QgsRectangle(self._extent) def updateExtents(self): self._extent.setMinimal() def isValid(self): return True def crs(self): return self._crs
def testExportFeatures(self): """ Test exporting feature collections """ fields = QgsFields() fields.append(QgsField("name", QVariant.String)) fields.append(QgsField("cost", QVariant.Double)) fields.append(QgsField("population", QVariant.Int)) feature = QgsFeature(fields, 5) feature.setGeometry(QgsGeometry(QgsPointV2(5, 6))) feature.setAttributes(['Valsier Peninsula', 6.8, 198]) exporter = QgsJSONExporter() # single feature expected = """{ "type": "FeatureCollection", "features":[ { "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } } ]}""" self.assertEqual(exporter.exportFeatures([feature]), expected) # multiple features feature2 = QgsFeature(fields, 6) feature2.setGeometry(QgsGeometry(QgsPointV2(7, 8))) feature2.setAttributes(['Henry Gale Island', 9.7, 38]) expected = """{ "type": "FeatureCollection", "features":[ { "type":"Feature", "id":5, "geometry": {"type": "Point", "coordinates": [5, 6]}, "properties":{ "name":"Valsier Peninsula", "cost":6.8, "population":198 } }, { "type":"Feature", "id":6, "geometry": {"type": "Point", "coordinates": [7, 8]}, "properties":{ "name":"Henry Gale Island", "cost":9.7, "population":38 } } ]}""" self.assertEqual(exporter.exportFeatures([feature, feature2]), expected)
def regularMatrix(self, parameters, context, source, inField, target_source, targetField, nPoints, feedback): distArea = QgsDistanceArea() distArea.setSourceCrs(source.sourceCrs(), context.transformContext()) distArea.setEllipsoid(context.project().ellipsoid()) inIdx = source.fields().lookupField(inField) targetIdx = target_source.fields().lookupField(targetField) index = QgsSpatialIndex( target_source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes( []).setDestinationCrs(source.sourceCrs(), context.transformContext())), feedback) first = True sink = None dest_id = None features = source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes([inIdx])) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, inFeat in enumerate(features): if feedback.isCanceled(): break inGeom = inFeat.geometry() if first: featList = index.nearestNeighbor(inGeom.asPoint(), nPoints) first = False fields = QgsFields() input_id_field = source.fields()[inIdx] input_id_field.setName('ID') fields.append(input_id_field) for f in target_source.getFeatures( QgsFeatureRequest().setFilterFids( featList).setSubsetOfAttributes([ targetIdx ]).setDestinationCrs(source.sourceCrs(), context.transformContext())): fields.append( QgsField(str(f[targetField]), QVariant.Double)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, source.wkbType(), source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) data = [inFeat[inField]] for target in target_source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes( []).setFilterFids(featList).setDestinationCrs( source.sourceCrs(), context.transformContext())): if feedback.isCanceled(): break outGeom = target.geometry() dist = distArea.measureLine(inGeom.asPoint(), outGeom.asPoint()) data.append(dist) out_feature = QgsFeature() out_feature.setGeometry(inGeom) out_feature.setAttributes(data) sink.addFeature(out_feature, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def test_MatchesReturnsTrueForComplexMatch(self): style = QgsConditionalStyle("@value > 10 and @value = 20") context = QgsExpressionContextUtils.createFeatureBasedContext( QgsFeature(), QgsFields()) assert style.matches(20, context)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) outputFormat = self.parameterAsInt(parameters, self.PrmOutputFormat, context) field1Name = self.parameterAsString(parameters, self.PrmYFieldName, context).strip() field2Name = self.parameterAsString(parameters, self.PrmXFieldName, context).strip() coordOrder = self.parameterAsInt(parameters, self.PrmCoordinateOrder, context) delimType = self.parameterAsInt(parameters, self.PrmCoordinateDelimiter, context) otherDelim = self.parameterAsString(parameters, self.PrmOtherDelimiter, context).strip() crsType = self.parameterAsInt(parameters, self.PrmOutputCRSType, context) crsOther = self.parameterAsCrs(parameters, self.PrmCustomCRS, context) wgs84Format = self.parameterAsInt(parameters, self.PrmWgs84NumberFormat, context) decimalPrecision = self.parameterAsInt(parameters, self.PrmCoordinatePrecision, context) dmsPrecision = self.parameterAsInt(parameters, self.PrmDMSSecondPrecision, context) plusCodesLength = self.parameterAsInt(parameters, self.PrmPlusCodesLength, context) if delimType == 0: delimiter = ',' elif delimType == 1: delimiter = ' ' elif delimType == 2: delimiter = '\t' else: delimiter = otherDelim layerCRS = source.sourceCrs() # For the first condition, the user has either EPSG:4326 selected or # or have chosen GeoJSON or WKT which will be 4326 as well if crsType == 0 or outputFormat >= 2: # Forced WGS 84 outCRS = epsg4326 elif crsType == 1: # Layer CRS outCRS = layerCRS elif crsType == 2: # Project CRS outCRS = QgsProject.instance().crs() else: outCRS = crsOther fieldsout = QgsFields(source.fields()) if fieldsout.append(QgsField(field1Name, QVariant.String)) == False: msg = "Field names must be unique. There is already a field named '{}'".format( field1Name) feedback.reportError(msg) raise QgsProcessingException(msg) if outputFormat == 0: # Two fields for coordinates if fieldsout.append(QgsField(field2Name, QVariant.String)) == False: msg = "Field names must be unique. There is already a field named '{}'".format( field2Name) feedback.reportError(msg) raise QgsProcessingException(msg) (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fieldsout, source.wkbType(), layerCRS) if layerCRS != outCRS: transform = QgsCoordinateTransform(layerCRS, outCRS, QgsProject.instance()) latlon = LatLon() latlon.setPrecision(dmsPrecision) total = 100.0 / source.featureCount() if source.featureCount() else 0 iterator = source.getFeatures() for cnt, feature in enumerate(iterator): if feedback.isCanceled(): break pt = feature.geometry().asPoint() if layerCRS != outCRS: pt = transform.transform(pt) try: if outputFormat == 0: # Two fields for coordinates if outCRS == epsg4326: if wgs84Format == 0: # Decimal Degrees msg = '{:.{prec}f}'.format(pt.y(), prec=decimalPrecision) msg2 = '{:.{prec}f}'.format(pt.x(), prec=decimalPrecision) elif wgs84Format == 1: # DMS latlon.setCoord(pt.y(), pt.x()) msg = latlon.convertDD2DMS(pt.y(), True, True) msg2 = latlon.convertDD2DMS(pt.x(), False, True) else: #DDMMSS latlon.setCoord(pt.y(), pt.x()) msg = latlon.convertDD2DMS(pt.y(), True, False) msg2 = latlon.convertDD2DMS(pt.x(), False, False) else: msg = '{:.{prec}f}'.format(pt.y(), prec=decimalPrecision) msg2 = '{:.{prec}f}'.format(pt.x(), prec=decimalPrecision) elif outputFormat == 1: # One field for coordinate if outCRS == epsg4326: if wgs84Format == 0: # Decimal Degrees if coordOrder == 0: msg = '{:.{prec}f}{}{:.{prec}f}'.format( pt.y(), delimiter, pt.x(), prec=decimalPrecision) else: msg = '{:.{prec}f}{}{:.{prec}f}'.format( pt.x(), delimiter, pt.y(), prec=decimalPrecision) elif wgs84Format == 1: # DMS latlon.setCoord(pt.y(), pt.x()) if coordOrder == 0: msg = latlon.getDMS(delimiter) else: msg = latlon.getDMSLonLatOrder(delimiter) else: #DDMMSS latlon.setCoord(pt.y(), pt.x()) if coordOrder == 0: msg = latlon.getDDMMSS(delimiter) else: msg = latlon.getDDMMSSLonLatOrder(delimiter) else: if coordOrder == 0: msg = '{:.{prec}f}{}{:.{prec}f}'.format( pt.y(), delimiter, pt.x(), prec=decimalPrecision) else: msg = '{:.{prec}f}{}{:.{prec}f}'.format( pt.x(), delimiter, pt.y(), prec=decimalPrecision) elif outputFormat == 2: # GeoJSON msg = '{{"type": "Point","coordinates": [{:.{prec}f},{:.{prec}f}]}}'.format( pt.x(), pt.y(), prec=decimalPrecision) elif outputFormat == 3: # WKT msg = 'POINT({:.{prec}f} {:.{prec}f})'.format( pt.x(), pt.y(), prec=decimalPrecision) elif outputFormat == 4: # MGRS msg = mgrs.toMgrs(pt.y(), pt.x(), 5) else: # Plus codes msg = olc.encode(pt.y(), pt.x(), plusCodesLength) except: msg = '' f = QgsFeature() f.setGeometry(feature.geometry()) if outputFormat == 0: # Two fields for coordinates f.setAttributes(feature.attributes() + [msg, msg2]) else: f.setAttributes(feature.attributes() + [msg]) sink.addFeature(f) if cnt % 100 == 0: feedback.setProgress(int(cnt * total)) return {self.PrmOutputLayer: dest_id}
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 test1(self): d = QgsVirtualLayerDefinition() self.assertEqual(d.toString(), "") d.setFilePath("/file") self.assertEqual(d.toString(), "file:///file") self.assertEqual( QgsVirtualLayerDefinition.fromUrl(d.toUrl()).filePath(), "/file") self.assertEqual( QgsVirtualLayerDefinition.fromUrl(strToUrl( d.toString())).filePath(), "/file") d.setFilePath(os.path.join('C:/', 'file')) self.assertEqual(d.toString(), "file:///C:/file") # self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).filePath(), os.path.join('C:/', 'file')) d.setQuery("SELECT * FROM mytable") self.assertEqual( QgsVirtualLayerDefinition.fromUrl(d.toUrl()).query(), "SELECT * FROM mytable") self.assertEqual( QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).query(), "SELECT * FROM mytable") q = "SELECT * FROM tableéé /*:int*/" d.setQuery(q) self.assertEqual( QgsVirtualLayerDefinition.fromUrl(d.toUrl()).query(), q) self.assertEqual( QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).query(), q) s1 = "file://foo&bar=okié" d.addSource("name", s1, "provider", "utf8") self.assertEqual( QgsVirtualLayerDefinition.fromUrl( d.toUrl()).sourceLayers()[0].source(), s1) self.assertEqual( QgsVirtualLayerDefinition.fromUrl(strToUrl( d.toString())).sourceLayers()[0].source(), s1) n1 = "éé ok" d.addSource(n1, s1, "provider") self.assertEqual( QgsVirtualLayerDefinition.fromUrl( d.toUrl()).sourceLayers()[1].name(), n1) self.assertEqual( QgsVirtualLayerDefinition.fromUrl(strToUrl( d.toString())).sourceLayers()[1].name(), n1) d.addSource("ref1", "id0001") self.assertEqual( QgsVirtualLayerDefinition.fromUrl( d.toUrl()).sourceLayers()[2].reference(), "id0001") self.assertEqual( QgsVirtualLayerDefinition.fromUrl(strToUrl( d.toString())).sourceLayers()[2].reference(), "id0001") s = "dbname='C:\\tt' table=\"test\" (geometry) sql=" d.addSource("nn", s, "spatialite") self.assertEqual( QgsVirtualLayerDefinition.fromUrl( d.toUrl()).sourceLayers()[3].source(), s) self.assertEqual( QgsVirtualLayerDefinition.fromUrl(strToUrl( d.toString())).sourceLayers()[3].source(), s) d.setGeometryField("geom") self.assertEqual( QgsVirtualLayerDefinition.fromUrl(d.toUrl()).geometryField(), "geom") self.assertEqual( QgsVirtualLayerDefinition.fromUrl(strToUrl( d.toString())).geometryField(), "geom") d.setGeometryWkbType(QgsWkbTypes.Point) self.assertEqual( QgsVirtualLayerDefinition.fromUrl(d.toUrl()).geometryWkbType(), QgsWkbTypes.Point) self.assertEqual( QgsVirtualLayerDefinition.fromUrl(strToUrl( d.toString())).geometryWkbType(), QgsWkbTypes.Point) f = QgsFields() f.append(QgsField("a", QVariant.Int)) f.append(QgsField("f", QVariant.Double)) f.append(QgsField("s", QVariant.String)) d.setFields(f) f2 = QgsVirtualLayerDefinition.fromUrl(d.toUrl()).fields() self.assertEqual(f[0].name(), f2[0].name()) self.assertEqual(f[0].type(), f2[0].type()) self.assertEqual(f[1].name(), f2[1].name()) self.assertEqual(f[1].type(), f2[1].type()) self.assertEqual(f[2].name(), f2[2].name()) self.assertEqual(f[2].type(), f2[2].type())
def processAlgorithm(self, parameters, context, feedback): target = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.TARGET), context) join = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.JOIN), context) predicates = self.getParameterValue(self.PREDICATE) precision = self.getParameterValue(self.PRECISION) summary = self.getParameterValue(self.SUMMARY) == 1 keep = self.getParameterValue(self.KEEP) == 1 sumList = self.getParameterValue(self.STATS).lower().split(',') targetFields = target.fields() joinFields = join.fields() fieldList = QgsFields() if not summary: joinFields = vector.testForUniqueness(targetFields, joinFields) seq = list(range(len(targetFields) + len(joinFields))) targetFields.extend(joinFields) targetFields = dict(list(zip(seq, targetFields))) else: numFields = {} for j in range(len(joinFields)): if joinFields[j].type() in [QVariant.Int, QVariant.Double, QVariant.LongLong, QVariant.UInt, QVariant.ULongLong]: numFields[j] = [] for i in sumList: field = QgsField(i + str(joinFields[j].name()), QVariant.Double, '', 24, 16) fieldList.append(field) field = QgsField('count', QVariant.Double, '', 24, 16) fieldList.append(field) joinFields = vector.testForUniqueness(targetFields, fieldList) targetFields.extend(fieldList) seq = list(range(len(targetFields))) targetFields = dict(list(zip(seq, targetFields))) fields = QgsFields() for f in list(targetFields.values()): fields.append(f) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, target.wkbType(), target.crs(), context) outFeat = QgsFeature() inFeatB = QgsFeature() inGeom = QgsGeometry() index = QgsProcessingUtils.createSpatialIndex(join, context) mapP2 = dict() features = QgsProcessingUtils.getFeatures(join, context) for f in features: mapP2[f.id()] = QgsFeature(f) features = QgsProcessingUtils.getFeatures(target, context) total = 100.0 / QgsProcessingUtils.featureCount(target, context) for c, f in enumerate(features): atMap1 = f.attributes() outFeat.setGeometry(f.geometry()) inGeom = vector.snapToPrecision(f.geometry(), precision) none = True joinList = [] if inGeom.type() == QgsWkbTypes.PointGeometry: bbox = inGeom.buffer(10, 2).boundingBox() else: bbox = inGeom.boundingBox() bbox.grow(0.51 * precision) joinList = index.intersects(bbox) if len(joinList) > 0: count = 0 for i in joinList: inFeatB = mapP2[i] inGeomB = vector.snapToPrecision(inFeatB.geometry(), precision) res = False for predicate in predicates: res = getattr(inGeom, predicate)(inGeomB) if res: break if res: count = count + 1 none = False atMap2 = inFeatB.attributes() if not summary: atMap = atMap1 atMap2 = atMap2 atMap.extend(atMap2) atMap = dict(list(zip(seq, atMap))) break else: for j in list(numFields.keys()): numFields[j].append(atMap2[j]) if summary and not none: atMap = atMap1 for j in list(numFields.keys()): for k in sumList: if k == 'sum': atMap.append(sum(self._filterNull(numFields[j]))) elif k == 'mean': try: nn_count = sum(1 for _ in self._filterNull(numFields[j])) atMap.append(sum(self._filterNull(numFields[j])) / nn_count) except ZeroDivisionError: atMap.append(NULL) elif k == 'min': try: atMap.append(min(self._filterNull(numFields[j]))) except ValueError: atMap.append(NULL) elif k == 'median': atMap.append(self._median(numFields[j])) else: try: atMap.append(max(self._filterNull(numFields[j]))) except ValueError: atMap.append(NULL) numFields[j] = [] atMap.append(count) atMap = dict(list(zip(seq, atMap))) if none: outFeat.setAttributes(atMap1) else: outFeat.setAttributes(list(atMap.values())) if keep: writer.addFeature(outFeat) else: if not none: writer.addFeature(outFeat) feedback.setProgress(int(c * total)) del writer
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) 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()) 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) 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.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, 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) 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 featureCount = source.featureCount() total = 100.0 / pointCount if pointCount else 1 index = QgsSpatialIndex() points = dict() da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs()) da.setEllipsoid(context.project().ellipsoid()) request = QgsFeatureRequest() random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break # pick random feature fid = random.randint(0, featureCount - 1) f = next( source.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 p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPoint(p) if 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(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, 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