def testGeopackageLargeFID(self): tmpfile = os.path.join(self.basetestpath, 'testGeopackageLargeFID.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint) lyr.CreateField(ogr.FieldDefn('str_field', ogr.OFTString)) ds = None vl = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr') f = QgsFeature() f.setAttributes([1234567890123, None]) self.assertTrue(vl.startEditing()) self.assertTrue(vl.dataProvider().addFeatures([f])) self.assertTrue(vl.commitChanges()) got = [feat for feat in vl.getFeatures()][0] self.assertEqual(got['fid'], 1234567890123) self.assertTrue(vl.startEditing()) self.assertTrue(vl.changeGeometry(1234567890123, QgsGeometry.fromWkt('Point (3 50)'))) self.assertTrue(vl.changeAttributeValue(1234567890123, 1, 'foo')) self.assertTrue(vl.commitChanges()) got = [feat for feat in vl.getFeatures()][0] self.assertEqual(got['str_field'], 'foo') got_geom = got.geometry() self.assertIsNotNone(got_geom) self.assertTrue(vl.startEditing()) self.assertTrue(vl.deleteFeature(1234567890123)) self.assertTrue(vl.commitChanges())
def layerExtent(self, layer, writer, progress): rect = layer.extent() 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 rect = [QgsPoint(minx, miny), QgsPoint(minx, maxy), QgsPoint(maxx, maxy), QgsPoint(maxx, miny), QgsPoint(minx, miny)] geometry = QgsGeometry().fromPolygon([rect]) feat = QgsFeature() feat.setGeometry(geometry) attrs = [ minx, miny, maxx, maxy, cntx, cnty, area, perim, height, width, ] feat.setAttributes(attrs) writer.addFeature(feat)
def testNoSliverPolygons(self): # create a layer with some polygons that will be used as a source for "avoid intersections" l = QgsVectorLayer('MultiPolygon', 'test_layer', 'memory') assert l.isValid() QgsProject.instance().addMapLayer(l) QgsProject.instance().writeEntry("Digitizing", "/AvoidIntersectionsList", [l.id()]) features = [] for i, wkt in enumerate(feat_wkt): f = QgsFeature(i + 1) f.setGeometry(QgsGeometry.fromWkt(wkt)) features.append(f) l.dataProvider().addFeatures(features) assert l.pendingFeatureCount() == 7 # create a geometry and remove its intersections with other geometries g = QgsGeometry.fromWkt(newg_wkt) assert g.avoidIntersections() == 0 # the resulting multi-polygon must have exactly three parts # (in QGIS 2.0 it has one more tiny part that appears at the border between two of the original polygons) mpg = g.asMultiPolygon() assert len(mpg) == 3
def layerOmmb(self, layer, writer, feedback): req = QgsFeatureRequest().setSubsetOfAttributes([]) features = vector.features(layer, req) total = 100.0 / len(features) newgeometry = QgsGeometry() first = True for current, inFeat in enumerate(features): if first: newgeometry = inFeat.geometry() first = False else: newgeometry = newgeometry.combine(inFeat.geometry()) feedback.setProgress(int(current * total)) geometry, area, angle, width, height = newgeometry.orientedMinimumBoundingBox() if geometry: outFeat = QgsFeature() outFeat.setGeometry(geometry) outFeat.setAttributes([area, width * 2 + height * 2, angle, width, height]) writer.addFeature(outFeat)
def processAlgorithm(self, progress): fieldname = self.getParameterValue(self.FIELD) output = self.getOutputFromName(self.OUTPUT) vlayer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) vprovider = vlayer.dataProvider() fieldindex = vlayer.fieldNameIndex(fieldname) fields = vprovider.fields() fields.append(QgsField('NUM_FIELD', QVariant.Int)) writer = output.getVectorWriter(fields, vprovider.geometryType(), vlayer.crs()) outFeat = QgsFeature() classes = {} features = vector.features(vlayer) total = 100.0 / len(features) for current, feature in enumerate(features): progress.setPercentage(int(current * total)) inGeom = feature.geometry() outFeat.setGeometry(inGeom) atMap = feature.attributes() clazz = atMap[fieldindex] if clazz not in classes: classes[clazz] = len(classes.keys()) atMap.append(classes[clazz]) outFeat.setAttributes(atMap) writer.addFeature(outFeat) del writer
def test_ValueMap_representValue(self): layer = QgsVectorLayer("none?field=number1:integer&field=number2:double&field=text1:string&field=number3:integer&field=number4:double&field=text2:string", "layer", "memory") assert layer.isValid() QgsMapLayerRegistry.instance().addMapLayer(layer) f = QgsFeature() f.setAttributes([2, 2.5, 'NULL', None, None, None]) assert layer.dataProvider().addFeatures([f]) reg = QgsEditorWidgetRegistry.instance() factory = reg.factory("ValueMap") self.assertIsNotNone(factory) # Tests with different value types occurring in the value map config = {'two': '2', 'twoandhalf': '2.5', 'NULL text': 'NULL', 'nothing': self.VALUEMAP_NULL_TEXT} self.assertEqual(factory.representValue(layer, 0, config, None, 2), 'two') self.assertEqual(factory.representValue(layer, 1, config, None, 2.5), 'twoandhalf') self.assertEqual(factory.representValue(layer, 2, config, None, 'NULL'), 'NULL text') # Tests with null values of different types, if value map contains null self.assertEqual(factory.representValue(layer, 3, config, None, None), 'nothing') self.assertEqual(factory.representValue(layer, 4, config, None, None), 'nothing') self.assertEqual(factory.representValue(layer, 5, config, None, None), 'nothing') # Tests with fallback display for different value types config = {} self.assertEqual(factory.representValue(layer, 0, config, None, 2), '(2)') self.assertEqual(factory.representValue(layer, 1, config, None, 2.5), '(2.50000)') self.assertEqual(factory.representValue(layer, 2, config, None, 'NULL'), '(NULL)') # Tests with fallback display for null in different types of fields self.assertEqual(factory.representValue(layer, 3, config, None, None), '(NULL)') self.assertEqual(factory.representValue(layer, 4, config, None, None), '(NULL)') self.assertEqual(factory.representValue(layer, 5, config, None, None), '(NULL)') QgsMapLayerRegistry.instance().removeAllMapLayers()
def test_SetGeometry(self): feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(123, 456))) myGeometry = feat.geometry() myExpectedGeometry = "!None" myMessage = "\nExpected: %s\nGot: %s" % (myExpectedGeometry, myGeometry) assert myGeometry is not None, myMessage
def loopThruPolygons(self, inLayer, numRand, design): sProvider = inLayer.dataProvider() sFeat = QgsFeature() sGeom = QgsGeometry() sPoints = [] if design == self.tr("field"): index = sProvider.fieldNameIndex(numRand) count = 10.00 add = 60.00 / sProvider.featureCount() sFit = sProvider.getFeatures() featureErrors = [] while sFit.nextFeature(sFeat): sGeom = sFeat.geometry() if design == self.tr("density"): sDistArea = QgsDistanceArea() value = int(round(numRand * sDistArea.measure(sGeom))) elif design == self.tr("field"): sAtMap = sFeat.attributes() try: value = int(sAtMap[index]) except (ValueError,TypeError): featureErrors.append(sFeat) continue else: value = numRand sExt = sGeom.boundingBox() sPoints.extend(self.simpleRandom(value, sGeom, sExt.xMinimum(), sExt.xMaximum(), sExt.yMinimum(), sExt.yMaximum())) count = count + add self.progressBar.setValue(count) return sPoints, featureErrors
def testFilter(self): """ test calculating aggregate with filter """ layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory") pr = layer.dataProvider() int_values = [4, 2, 3, 2, 5, None, 8] features = [] for v in int_values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([v]) features.append(f) assert pr.addFeatures(features) agg = QgsAggregateCalculator(layer) filter_string = "fldint > 2" agg.setFilter(filter_string) self.assertEqual(agg.filter(), filter_string) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint') self.assertTrue(ok) self.assertEqual(val, 20) # remove filter and retest agg.setFilter(None) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint') self.assertTrue(ok) self.assertEqual(val, 24)
def testAddMultipleFeatures(self): # test adding multiple features to an edit buffer layer = createEmptyLayer() self.assertTrue(layer.startEditing()) self.assertEqual(layer.editBuffer().addedFeatures(), {}) self.assertFalse(layer.editBuffer().isFeatureAdded(1)) self.assertFalse(layer.editBuffer().isFeatureAdded(3)) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPoint(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPoint(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeatures([f1, f2])) # test contents of buffer added = layer.editBuffer().addedFeatures() new_feature_ids = list(added.keys()) self.assertEqual(added[new_feature_ids[0]]['fldtxt'], 'test2') self.assertEqual(added[new_feature_ids[0]]['fldint'], 246) self.assertEqual(added[new_feature_ids[1]]['fldtxt'], 'test') self.assertEqual(added[new_feature_ids[1]]['fldint'], 123) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[0])) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[1]))
def testDeleteMultipleFeatures(self): # test deleting multiple features from an edit buffer # make a layer with two features layer = createEmptyLayer() self.assertTrue(layer.startEditing()) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPoint(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeature(f1)) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPoint(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeature(f2)) layer.commitChanges() layer.startEditing() self.assertEqual(layer.editBuffer().deletedFeatureIds(), []) self.assertFalse(layer.editBuffer().isFeatureDeleted(1)) self.assertFalse(layer.editBuffer().isFeatureDeleted(2)) # delete features layer.deleteFeatures([1, 2]) # test contents of buffer self.assertEqual(set(layer.editBuffer().deletedFeatureIds()), set([1, 2])) self.assertTrue(layer.editBuffer().isFeatureDeleted(1)) self.assertTrue(layer.editBuffer().isFeatureDeleted(2))
def test_expressionRequiresFormScope(self): res = list(QgsValueRelationFieldFormatter.expressionFormAttributes("current_value('ONE') AND current_value('TWO')")) res = sorted(res) self.assertEqual(res, ['ONE', 'TWO']) res = list(QgsValueRelationFieldFormatter.expressionFormVariables("@current_geometry")) self.assertEqual(res, ['current_geometry']) self.assertFalse(QgsValueRelationFieldFormatter.expressionRequiresFormScope("")) self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("current_value('TWO')")) self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("current_value ( 'TWO' )")) self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("@current_geometry")) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("", QgsFeature())) self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("@current_geometry", QgsFeature())) self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'TWO' )", QgsFeature())) layer = QgsVectorLayer("none?field=pkid:integer&field=decoded:string", "layer", "memory") self.assertTrue(layer.isValid()) QgsProject.instance().addMapLayer(layer) f = QgsFeature(layer.fields()) f.setAttributes([1, 'value']) point = QgsGeometry.fromPointXY(QgsPointXY(123, 456)) f.setGeometry(point) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("current_geometry", f)) self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'TWO' )", f)) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'pkid' )", f)) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("@current_geometry current_value ( 'pkid' )", f)) QgsProject.instance().removeMapLayer(layer.id())
def testIndex(self): idx = QgsSpatialIndex() fid = 0 for y in range(5, 15, 5): for x in range(5, 25, 5): ft = QgsFeature() ft.setFeatureId(fid) ft.setGeometry(QgsGeometry.fromPoint(QgsPoint(x, y))) idx.insertFeature(ft) fid += 1 # intersection test rect = QgsRectangle(7.0, 3.0, 17.0, 13.0) fids = idx.intersects(rect) myExpectedValue = 4 myValue = len(fids) myMessage = 'Expected: %s Got: %s' % (myExpectedValue, myValue) self.assertEqual(myValue, myExpectedValue, myMessage) fids.sort() myMessage = ('Expected: %s\nGot: %s\n' % ([1, 2, 5, 6], fids)) assert fids == [1, 2, 5, 6], myMessage # nearest neighbor test fids = idx.nearestNeighbor(QgsPoint(8.75, 6.25), 3) myExpectedValue = 0 myValue = len(fids) myMessage = 'Expected: %s Got: %s' % (myExpectedValue, myValue) fids.sort() myMessage = ('Expected: %s\nGot: %s\n' % ([0, 1, 5], fids)) assert fids == [0, 1, 5], myMessage
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.fields().toList(), QgsWkbTypes.Polygon, layer.crs() ) outFeat = QgsFeature() features = vector.features(layer) total = 100.0 / len(features) for current, f in enumerate(features): outGeomList = [] if f.geometry().isMultipart(): outGeomList = f.geometry().asMultiPolyline() else: outGeomList.append(f.geometry().asPolyline()) polyGeom = self.removeBadLines(outGeomList) if len(polyGeom) != 0: outFeat.setGeometry(QgsGeometry.fromPolygon(polyGeom)) attrs = f.attributes() outFeat.setAttributes(attrs) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, progress): fieldType = self.getParameterValue(self.FIELD_TYPE) fieldName = self.getParameterValue(self.FIELD_NAME) fieldLength = self.getParameterValue(self.FIELD_LENGTH) fieldPrecision = self.getParameterValue(self.FIELD_PRECISION) output = self.getOutputFromName(self.OUTPUT_LAYER) layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_LAYER)) fields = layer.fields() fields.append(QgsField(fieldName, self.TYPES[fieldType], '', fieldLength, fieldPrecision)) writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs()) outFeat = QgsFeature() features = vector.features(layer) total = 100.0 / len(features) for current, feat in enumerate(features): progress.setPercentage(int(current * total)) geom = feat.geometry() outFeat.setGeometry(geom) atMap = feat.attributes() atMap.append(None) outFeat.setAttributes(atMap) writer.addFeature(outFeat) del writer
def processAlgorithm(self, progress): layerA = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_A)) layerB = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_B)) fieldA = self.getParameterValue(self.FIELD_A) fieldB = self.getParameterValue(self.FIELD_B) idxA = layerA.fields().lookupField(fieldA) idxB = layerB.fields().lookupField(fieldB) fieldList = [layerA.fields()[idxA], layerB.fields()[idxB]] writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldList, QgsWkbTypes.Point, layerA.crs()) spatialIndex = vector.spatialindex(layerB) outFeat = QgsFeature() features = vector.features(layerA) total = 100.0 / len(features) hasIntersections = False for current, inFeatA in enumerate(features): inGeom = inFeatA.geometry() hasIntersections = False lines = spatialIndex.intersects(inGeom.boundingBox()) engine = None if len(lines) > 0: hasIntersections = True # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(inGeom.geometry()) engine.prepareGeometry() if hasIntersections: request = QgsFeatureRequest().setFilterFids(lines) for inFeatB in layerB.getFeatures(request): tmpGeom = inFeatB.geometry() points = [] attrsA = inFeatA.attributes() attrsB = inFeatB.attributes() if engine.intersects(tmpGeom.geometry()): tempGeom = inGeom.intersection(tmpGeom) if tempGeom.type() == QgsWkbTypes.PointGeometry: if tempGeom.isMultipart(): points = tempGeom.asMultiPoint() else: points.append(tempGeom.asPoint()) for j in points: outFeat.setGeometry(tempGeom.fromPoint(j)) outFeat.setAttributes([attrsA[idxA], attrsB[idxB]]) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) crsId = self.getParameterValue(self.TARGET_CRS) targetCrs = QgsCoordinateReferenceSystem() targetCrs.createFromUserInput(crsId) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.fields().toList(), layer.wkbType(), targetCrs) layerCrs = layer.crs() crsTransform = QgsCoordinateTransform(layerCrs, targetCrs) outFeat = QgsFeature() features = vector.features(layer) total = 100.0 / len(features) for current, f in enumerate(features): geom = f.geometry() geom.transform(crsTransform) outFeat.setGeometry(geom) outFeat.setAttributes(f.attributes()) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer self.crs = targetCrs
def renderGeometry(self, symbol, geom, buffer=20): f = QgsFeature() f.setGeometry(geom) image = QImage(200, 200, QImage.Format_RGB32) painter = QPainter() ms = QgsMapSettings() extent = geom.get().boundingBox() # buffer extent by 10% if extent.width() > 0: extent = extent.buffered((extent.height() + extent.width()) / buffer) else: extent = extent.buffered(buffer / 2) ms.setExtent(extent) ms.setOutputSize(image.size()) context = QgsRenderContext.fromMapSettings(ms) context.setPainter(painter) context.setScaleFactor(96 / 25.4) # 96 DPI context.expressionContext().setFeature(f) painter.begin(image) try: image.fill(QColor(0, 0, 0)) symbol.startRender(context) symbol.renderFeature(f, context) symbol.stopRender(context) finally: painter.end() return image
def test_representValue(self): QgsSettings().setValue("qgis/nullValue", "NULL") layer = QgsVectorLayer("none?field=number1:integer&field=number2:double&field=text1:string&field=number3:integer&field=number4:double&field=text2:string", "layer", "memory") self.assertTrue(layer.isValid()) QgsProject.instance().addMapLayer(layer) f = QgsFeature() f.setAttributes([2, 2.5, 'NULL', None, None, None]) layer.dataProvider().addFeatures([f]) fieldFormatter = QgsValueMapFieldFormatter() # Tests with different value types occurring in the value map config = {'map': {'two': '2', 'twoandhalf': '2.5', 'NULL text': 'NULL', 'nothing': self.VALUEMAP_NULL_TEXT}} self.assertEqual(fieldFormatter.representValue(layer, 0, config, None, 2), 'two') self.assertEqual(fieldFormatter.representValue(layer, 1, config, None, 2.5), 'twoandhalf') self.assertEqual(fieldFormatter.representValue(layer, 2, config, None, 'NULL'), 'NULL text') # Tests with null values of different types, if value map contains null self.assertEqual(fieldFormatter.representValue(layer, 3, config, None, None), 'nothing') self.assertEqual(fieldFormatter.representValue(layer, 4, config, None, None), 'nothing') self.assertEqual(fieldFormatter.representValue(layer, 5, config, None, None), 'nothing') # Tests with fallback display for different value types config = {} self.assertEqual(fieldFormatter.representValue(layer, 0, config, None, 2), '(2)') self.assertEqual(fieldFormatter.representValue(layer, 1, config, None, 2.5), '(2.50000)') self.assertEqual(fieldFormatter.representValue(layer, 2, config, None, 'NULL'), '(NULL)') # Tests with fallback display for null in different types of fields self.assertEqual(fieldFormatter.representValue(layer, 3, config, None, None), '(NULL)') self.assertEqual(fieldFormatter.representValue(layer, 4, config, None, None), '(NULL)') self.assertEqual(fieldFormatter.representValue(layer, 5, config, None, None), '(NULL)') QgsProject.instance().removeAllMapLayers()
def test_link_feature(self): """ Check if an existing feature can be linked """ wrapper = self.createWrapper(self.vl_a, '"name"=\'Douglas Adams\'') # NOQA f = QgsFeature(self.vl_b.fields()) f.setAttributes([self.vl_b.dataProvider().defaultValueClause(0), 'The Hitchhiker\'s Guide to the Galaxy']) self.vl_b.addFeature(f) def choose_linked_feature(): dlg = QApplication.activeModalWidget() dlg.setSelectedFeatures([f.id()]) dlg.accept() btn = self.widget.findChild(QToolButton, 'mLinkFeatureButton') timer = QTimer() timer.setSingleShot(True) timer.setInterval(0) # will run in the event loop as soon as it's processed when the dialog is opened timer.timeout.connect(choose_linked_feature) timer.start() btn.click() # magically the above code selects the feature here... link_feature = next(self.vl_link.getFeatures(QgsFeatureRequest().setFilterExpression('"fk_book"={}'.format(f[0])))) self.assertIsNotNone(link_feature[0]) self.assertEqual(self.table_view.model().rowCount(), 1)
def testTriangleTINPolyhedralSurface(self): """ Test support for Triangles (mapped to Polygons) """ testsets = ( ("Triangle((0 0, 0 1, 1 1, 0 0))", QgsWkbTypes.Triangle, "Triangle ((0 0, 0 1, 1 1, 0 0))"), ("Triangle Z((0 0 1, 0 1 2, 1 1 3, 0 0 1))", QgsWkbTypes.TriangleZ, "TriangleZ ((0 0 1, 0 1 2, 1 1 3, 0 0 1))"), ("Triangle M((0 0 4, 0 1 5, 1 1 6, 0 0 4))", QgsWkbTypes.TriangleM, "TriangleM ((0 0 4, 0 1 5, 1 1 6, 0 0 4))"), ("Triangle ZM((0 0 0 1, 0 1 2 3, 1 1 4 5, 0 0 0 1))", QgsWkbTypes.TriangleZM, "TriangleZM ((0 0 0 1, 0 1 2 3, 1 1 4 5, 0 0 0 1))"), ("TIN (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))", QgsWkbTypes.MultiPolygon, "MultiPolygon (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))"), ("TIN Z(((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))", QgsWkbTypes.MultiPolygonZ, "MultiPolygonZ (((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))"), ("TIN M(((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))", QgsWkbTypes.MultiPolygonM, "MultiPolygonM (((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))"), ("TIN ZM(((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))", QgsWkbTypes.MultiPolygonZM, "MultiPolygonZM (((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))"), ("PolyhedralSurface (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))", QgsWkbTypes.MultiPolygon, "MultiPolygon (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))"), ("PolyhedralSurface Z(((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))", QgsWkbTypes.MultiPolygonZ, "MultiPolygonZ (((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))"), ("PolyhedralSurface M(((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))", QgsWkbTypes.MultiPolygonM, "MultiPolygonM (((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))"), ("PolyhedralSurface ZM(((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))", QgsWkbTypes.MultiPolygonZM, "MultiPolygonZM (((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))") ) for row in testsets: datasource = os.path.join(self.basetestpath, 'test.csv') with open(datasource, 'wt') as f: f.write('id,WKT\n') f.write('1,"%s"' % row[0]) vl = QgsVectorLayer(datasource, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(vl.wkbType(), row[1]) f = QgsFeature() self.assertTrue(vl.getFeatures(QgsFeatureRequest(1)).nextFeature(f)) self.assertTrue(f.geometry()) self.assertEqual(f.geometry().constGet().asWkt(), row[2])
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_LAYER)) writer = self.getOutputFromName( self.OUTPUT_LAYER).getVectorWriter( layer.fields(), QgsWkbTypes.Point, layer.crs()) outFeat = QgsFeature() features = vector.features(layer) total = 100.0 / len(features) for current, feat in enumerate(features): inGeom = feat.geometry() attrs = feat.attributes() if inGeom.isEmpty(): outGeom = QgsGeometry(None) else: outGeom = QgsGeometry(inGeom.centroid()) if not outGeom: raise GeoAlgorithmExecutionException( self.tr('Error calculating centroid')) outFeat.setGeometry(outGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer
def testAddZ(self): """Check adding z values to non z input.""" input = QgsVectorLayer( 'Point?crs=epsg:4326&field=name:string(20)', 'test', 'memory') self.assertTrue(input.isValid(), 'Provider not initialized') ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 10))) myResult, myFeatures = input.dataProvider().addFeatures([ft]) self.assertTrue(myResult) self.assertTrue(myFeatures) dest_file_name = os.path.join(str(QDir.tempPath()), 'add_z.geojson') options = QgsVectorFileWriter.SaveVectorOptions() options.overrideGeometryType = QgsWkbTypes.PointZ options.driverName = 'GeoJSON' write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat( input, dest_file_name, options) self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message) # Open result and check created_layer = QgsVectorLayer(dest_file_name, 'test', 'ogr') self.assertTrue(created_layer.isValid()) f = next(created_layer.getFeatures(QgsFeatureRequest())) self.assertEqual(f.geometry().asWkt(), 'PointZ (10 10 0)')
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) idx = layer.fieldNameIndex(self.getParameterValue(self.COLUMN)) fields = layer.pendingFields() fields.remove(idx) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, layer.wkbType(), layer.crs()) features = vector.features(layer) count = len(features) total = 100.0 / float(count) feat = QgsFeature() for count, f in enumerate(features): feat.setGeometry(f.geometry()) attributes = f.attributes() del attributes[idx] feat.setAttributes(attributes) writer.addFeature(feat) progress.setPercentage(int(count * total)) del writer
def testWriteWithBinaryField(self): """ Test writing with a binary field :return: """ basetestpath = tempfile.mkdtemp() tmpfile = os.path.join(basetestpath, 'binaryfield.sqlite') ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid']) lyr.CreateField(ogr.FieldDefn('strfield', ogr.OFTString)) lyr.CreateField(ogr.FieldDefn('intfield', ogr.OFTInteger)) lyr.CreateField(ogr.FieldDefn('binfield', ogr.OFTBinary)) lyr.CreateField(ogr.FieldDefn('binfield2', ogr.OFTBinary)) f = None ds = None vl = QgsVectorLayer(tmpfile) self.assertTrue(vl.isValid()) # check that 1 of its fields is a bool fields = vl.fields() self.assertEqual(fields.at(fields.indexFromName('binfield')).type(), QVariant.ByteArray) dp = vl.dataProvider() f = QgsFeature(fields) bin_1 = b'xxx' bin_2 = b'yyy' bin_val1 = QByteArray(bin_1) bin_val2 = QByteArray(bin_2) f.setAttributes([1, 'str', 100, bin_val1, bin_val2]) self.assertTrue(dp.addFeature(f)) # write a gpkg package with a binary field filename = os.path.join(str(QDir.tempPath()), 'with_bin_field') rc, errmsg = QgsVectorFileWriter.writeAsVectorFormat(vl, filename, 'utf-8', vl.crs(), 'GPKG') self.assertEqual(rc, QgsVectorFileWriter.NoError) # open the resulting geopackage vl = QgsVectorLayer(filename + '.gpkg', '', 'ogr') self.assertTrue(vl.isValid()) fields = vl.fields() # test type of converted field idx = fields.indexFromName('binfield') self.assertEqual(fields.at(idx).type(), QVariant.ByteArray) idx2 = fields.indexFromName('binfield2') self.assertEqual(fields.at(idx2).type(), QVariant.ByteArray) # test values self.assertEqual(vl.getFeature(1).attributes()[idx], bin_val1) self.assertEqual(vl.getFeature(1).attributes()[idx2], bin_val2) del vl os.unlink(filename + '.gpkg')
def testClear(self): s = QgsAuxiliaryStorage() self.assertTrue(s.isValid()) # Create a new auxiliary layer with 'pk' as key vl = createLayer() pkf = vl.fields().field(vl.fields().indexOf('pk')) al = s.createAuxiliaryLayer(pkf, vl) self.assertTrue(al.isValid()) vl.setAuxiliaryLayer(al) # Add a field in auxiliary layer p = QgsPropertyDefinition('myprop', QgsPropertyDefinition.DataTypeNumeric, '', '', 'me') self.assertFalse(al.exists(p)) self.assertTrue(al.addAuxiliaryField(p)) self.assertTrue(al.exists(p)) # Count auxiliary features self.assertEqual(al.featureCount(), 0) # Set value for auxiliary fields req = QgsFeatureRequest().setFilterExpression("name = 'Honey'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) afName = QgsAuxiliaryLayer.nameFromProperty(p, True) index = vl.fields().indexOf(afName) vl.changeAttributeValue(f.id(), index, 333) # Count auxiliary features self.assertEqual(al.featureCount(), 1) # Clear and count al.clear() self.assertEqual(al.featureCount(), 0)
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) interval = self.getParameterValue(self.INTERVAL) isPolygon = layer.geometryType() == QgsWkbTypes.PolygonGeometry writer = self.getOutputFromName( self.OUTPUT).getVectorWriter(layer.fields().toList(), layer.wkbType(), layer.crs()) features = vector.features(layer) total = 100.0 / len(features) for current, f in enumerate(features): featGeometry = f.geometry() attrs = f.attributes() newGeometry = self.densifyGeometry(featGeometry, interval, isPolygon) feature = QgsFeature() feature.setGeometry(newGeometry) feature.setAttributes(attrs) writer.addFeature(feature) progress.setPercentage(int(current * total)) del writer
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 processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_VECTOR), context) rasterPath = str(self.getParameterValue(self.INPUT_RASTER)) rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly) geoTransform = rasterDS.GetGeoTransform() rasterDS = None fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) fields.append(QgsField('line_id', QVariant.Int, '', 10, 0)) fields.append(QgsField('point_id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(fields, QgsWkbTypes.Point, layer.crs(), context) outFeature = QgsFeature() outFeature.setFields(fields) self.fid = 0 self.lineId = 0 self.pointId = 0 features = QgsProcessingUtils.getFeatures(layer, context) total = 100.0 / layer.featureCount() if layer.featureCount() else 0 for current, f in enumerate(features): geom = f.geometry() if geom.isMultipart(): lines = geom.asMultiPolyline() for line in lines: for i in range(len(line) - 1): p1 = line[i] p2 = line[i + 1] (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform) (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform) self.buildLine(x1, y1, x2, y2, geoTransform, writer, outFeature) else: points = geom.asPolyline() for i in range(len(points) - 1): p1 = points[i] p2 = points[i + 1] (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform) (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform) self.buildLine(x1, y1, x2, y2, geoTransform, writer, outFeature) self.pointId = 0 self.lineId += 1 feedback.setProgress(int(current * total)) del writer
def add_new_feature(self, form, geometry): """ Add a new new feature to the given layer """ # TODO Extract into function. # NOTE This function is doing too much, acts as add and also edit. layer = form.QGISLayer if layer.geometryType() in [QGis.WKBMultiLineString, QGis.WKBMultiPoint, QGis.WKBMultiPolygon]: geometry.convertToMultiType() try: form, feature = self.editfeaturestack.pop() self.editfeaturegeometry(form, feature, newgeometry=geometry) return except IndexError: pass layer = form.QGISLayer fields = layer.pendingFields() feature = QgsFeature(fields) feature.setGeometry(geometry) for index in xrange(fields.count()): pkindexes = layer.dataProvider().pkAttributeIndexes() if index in pkindexes and layer.dataProvider().name() == 'spatialite': continue value = layer.dataProvider().defaultValue(index) feature[index] = value RoamEvents.open_feature_form(form, feature, editmode=False)
def testCreateLayer(self): layer = QgsVectorLayer( "Point?field=id:integer&field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1, "test", 1]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f2 = QgsFeature() f2.setAttributes([2, "test2", 3]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2))) f4 = QgsFeature() f4.setAttributes([4, NULL, 3]) f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3))) pr.addFeatures([f, f2, f3, f4]) uri = '{} table="qgis_test"."new_table" sql='.format(self.dbconn) error, message = QgsVectorLayerExporter.exportLayer( layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.Point) self.assertEqual([f.name() for f in new_layer.fields()], ['qgs_fid', 'id', 'fldtxt', 'fldint']) features = [f.attributes() for f in new_layer.getFeatures()] self.assertEqual(features, [[1, 1, 'test', 1], [2, 2, 'test2', 3], [3, 3, 'test2', NULL], [4, 4, NULL, 3]]) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['Point (1 2)', '', 'Point (3 2)', 'Point (4 3)'])
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) field_name = self.parameterAsString(parameters, self.FIELD, context) type = self.parameterAsEnum(parameters, self.TYPE, context) use_field = bool(field_name) field_index = -1 fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 20)) if use_field: # keep original field type, name and parameters field_index = source.fields().lookupField(field_name) if field_index >= 0: fields.append(source.fields()[field_index]) if type == 0: # envelope fields.append(QgsField('width', QVariant.Double, '', 20, 6)) fields.append(QgsField('height', QVariant.Double, '', 20, 6)) fields.append(QgsField('area', QVariant.Double, '', 20, 6)) fields.append(QgsField('perimeter', QVariant.Double, '', 20, 6)) elif type == 1: # oriented rect fields.append(QgsField('width', QVariant.Double, '', 20, 6)) fields.append(QgsField('height', QVariant.Double, '', 20, 6)) fields.append(QgsField('angle', QVariant.Double, '', 20, 6)) fields.append(QgsField('area', QVariant.Double, '', 20, 6)) fields.append(QgsField('perimeter', QVariant.Double, '', 20, 6)) elif type == 2: # circle fields.append(QgsField('radius', QVariant.Double, '', 20, 6)) fields.append(QgsField('area', QVariant.Double, '', 20, 6)) elif type == 3: # convex hull fields.append(QgsField('area', QVariant.Double, '', 20, 6)) fields.append(QgsField('perimeter', QVariant.Double, '', 20, 6)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Polygon, source.sourceCrs()) if field_index >= 0: geometry_dict = {} bounds_dict = {} total = 50.0 / source.featureCount() if source.featureCount() else 1 features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([field_index])) for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue if type == 0: # bounding boxes - calculate on the fly for efficiency if not f.attributes()[field_index] in bounds_dict: bounds_dict[f.attributes()[field_index]] = f.geometry().boundingBox() else: bounds_dict[f.attributes()[field_index]].combineExtentWith(f.geometry().boundingBox()) else: if not f.attributes()[field_index] in geometry_dict: geometry_dict[f.attributes()[field_index]] = [f.geometry()] else: geometry_dict[f.attributes()[field_index]].append(f.geometry()) feedback.setProgress(int(current * total)) if type == 0: # bounding boxes current = 0 total = 50.0 / len(bounds_dict) if bounds_dict else 1 for group, rect in bounds_dict.items(): if feedback.isCanceled(): break # envelope feature = QgsFeature() feature.setGeometry(QgsGeometry.fromRect(rect)) feature.setAttributes([current, group, rect.width(), rect.height(), rect.area(), rect.perimeter()]) sink.addFeature(feature, QgsFeatureSink.FastInsert) geometry_dict[group] = None feedback.setProgress(50 + int(current * total)) current += 1 else: current = 0 total = 50.0 / len(geometry_dict) if geometry_dict else 1 for group, geometries in geometry_dict.items(): if feedback.isCanceled(): break feature = self.createFeature(feedback, current, type, geometries, group) sink.addFeature(feature, QgsFeatureSink.FastInsert) geometry_dict[group] = None feedback.setProgress(50 + int(current * total)) current += 1 else: total = 80.0 / source.featureCount() if source.featureCount() else 1 features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([])) geometry_queue = [] bounds = QgsRectangle() for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue if type == 0: # bounding boxes, calculate on the fly for efficiency bounds.combineExtentWith(f.geometry().boundingBox()) else: geometry_queue.append(f.geometry()) feedback.setProgress(int(current * total)) if not feedback.isCanceled(): if type == 0: feature = QgsFeature() feature.setGeometry(QgsGeometry.fromRect(bounds)) feature.setAttributes([0, bounds.width(), bounds.height(), bounds.area(), bounds.perimeter()]) else: feature = self.createFeature(feedback, 0, type, geometry_queue) sink.addFeature(feature, QgsFeatureSink.FastInsert) return {self.OUTPUT: dest_id}
def createReferencedLayer(): layer = QgsVectorLayer( "Point?field=x:string&field=y:integer&field=z:integer", "referencedlayer", "memory") pr = layer.dataProvider() f1 = QgsFeature() f1.setFields(layer.fields()) f1.setAttributes(["foo", 123, 321]) f2 = QgsFeature() f2.setFields(layer.fields()) f2.setAttributes(["bar", 456, 654]) f3 = QgsFeature() f3.setFields(layer.fields()) f3.setAttributes(["foobar'bar", 789, 554]) assert pr.addFeatures([f1, f2, f3]) return layer
def createReferencingLayer(): layer = QgsVectorLayer("Point?field=fldtxt:string&field=foreignkey:integer", "referencinglayer", "memory") pr = layer.dataProvider() f1 = QgsFeature() f1.setFields(layer.fields()) f1.setAttributes(["test1", 123]) f2 = QgsFeature() f2.setFields(layer.fields()) f2.setAttributes(["test2", 123]) f3 = QgsFeature() f3.setFields(layer.fields()) f3.setAttributes(["foobar'bar", 124]) assert pr.addFeatures([f1, f2, f3]) return layer
def getSource(self): # create temporary table for edit tests self.execSQLCommand('DROP TABLE IF EXISTS qgis_test.edit_data') self.execSQLCommand( """CREATE TABLE qgis_test.edit_data (pk INTEGER PRIMARY KEY,cnt integer, name nvarchar(max), name2 nvarchar(max), num_char nvarchar(max), geom geometry)""" ) vl = QgsVectorLayer( self.dbconn + ' sslmode=disable key=\'pk\' srid=4326 type=POINT table="qgis_test"."edit_data" (geom) sql=', 'test', 'mssql') self.assertTrue(vl.isValid(), vl.dataProvider().error().message()) f1 = QgsFeature() f1.setAttributes([5, -200, NULL, 'NuLl', '5']) f1.setGeometry(QgsGeometry.fromWkt('Point (-71.123 78.23)')) f2 = QgsFeature() f2.setAttributes([3, 300, 'Pear', 'PEaR', '3']) f3 = QgsFeature() f3.setAttributes([1, 100, 'Orange', 'oranGe', '1']) f3.setGeometry(QgsGeometry.fromWkt('Point (-70.332 66.33)')) f4 = QgsFeature() f4.setAttributes([2, 200, 'Apple', 'Apple', '2']) f4.setGeometry(QgsGeometry.fromWkt('Point (-68.2 70.8)')) f5 = QgsFeature() f5.setAttributes([4, 400, 'Honey', 'Honey', '4']) f5.setGeometry(QgsGeometry.fromWkt('Point (-65.32 78.3)')) self.assertTrue(vl.dataProvider().addFeatures([f1, f2, f3, f4, f5])) return vl
def testInsertPolygonInMultiPolygon(self): layer = QgsVectorLayer("MultiPolygon?crs=epsg:4326&field=id:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1]) f.setGeometry( QgsGeometry.fromWkt( 'MultiPolygon(((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))' )) pr.addFeatures([f]) uri = '{} table="qgis_test"."new_table_multipolygon" sql='.format( self.dbconn) error, message = QgsVectorLayerExporter.exportLayer( layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.MultiPolygon) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, [ 'MultiPolygon (((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))' ]) # add single part f2 = QgsFeature() f2.setAttributes([2]) f2.setGeometry( QgsGeometry.fromWkt('Polygon((30 0, 31 0, 31 1, 30 1, 30 0))')) self.assertTrue(new_layer.dataProvider().addFeatures([f2])) # should become multipart geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, [ 'MultiPolygon (((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))', 'MultiPolygon (((30 0, 31 0, 31 1, 30 1, 30 0)))' ])
def testCreateLayerMultiPoint(self): layer = QgsVectorLayer( "MultiPoint?crs=epsg:3111&field=id:integer&field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1, "test", 1]) f.setGeometry(QgsGeometry.fromWkt('MultiPoint(1 2, 3 4)')) f2 = QgsFeature() f2.setAttributes([2, "test2", 3]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromWkt('MultiPoint(7 8)')) pr.addFeatures([f, f2, f3]) uri = '{} table="qgis_test"."new_table_multipoint" sql='.format( self.dbconn) error, message = QgsVectorLayerExporter.exportLayer( layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:3111')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.MultiPoint) self.assertEqual(new_layer.crs().authid(), 'EPSG:3111') self.assertEqual([f.name() for f in new_layer.fields()], ['qgs_fid', 'id', 'fldtxt', 'fldint']) features = [f.attributes() for f in new_layer.getFeatures()] self.assertEqual( features, [[1, 1, 'test', 1], [2, 2, 'test2', 3], [3, 3, 'test2', NULL]]) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual( geom, ['MultiPoint ((1 2),(3 4))', '', 'MultiPoint ((7 8))'])
def testAddFeatures(self): # test adding features to an edit buffer layer = createEmptyLayer() self.assertTrue(layer.startEditing()) self.assertEqual(layer.editBuffer().addedFeatures(), {}) self.assertFalse(layer.editBuffer().isFeatureAdded(1)) self.assertFalse(layer.editBuffer().isFeatureAdded(3)) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeature(f1)) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeature(f2)) # test contents of buffer added = layer.editBuffer().addedFeatures() new_feature_ids = list(added.keys()) self.assertEqual(added[new_feature_ids[0]]['fldtxt'], 'test2') self.assertEqual(added[new_feature_ids[0]]['fldint'], 246) self.assertEqual(added[new_feature_ids[1]]['fldtxt'], 'test') self.assertEqual(added[new_feature_ids[1]]['fldint'], 123) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[0])) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[1])) # check if error in case adding not adaptable geometry # eg. a Multiline in a Line layer = createEmptyLinestringLayer() self.assertTrue(layer.startEditing()) self.assertEqual(layer.editBuffer().addedFeatures(), {}) self.assertFalse(layer.editBuffer().isFeatureAdded(1)) self.assertFalse(layer.editBuffer().isFeatureAdded(3)) # add a features with a multi line geometry of not touched lines => # cannot be forced to be linestring multiline = [ [QgsPointXY(1, 1), QgsPointXY(2, 2)], [QgsPointXY(3, 3), QgsPointXY(4, 4)], ] f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromMultiPolylineXY(multiline)) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeatures([f1])) self.assertFalse(layer.commitChanges())
def testChangeAttributeValues(self): # test changing attributes values from an edit buffer # make a layer with two features layer = createEmptyLayer() self.assertTrue(layer.startEditing()) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeature(f1)) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeature(f2)) layer.commitChanges() layer.startEditing() self.assertEqual(layer.editBuffer().changedAttributeValues(), {}) self.assertFalse(layer.editBuffer().isFeatureAttributesChanged(1)) self.assertFalse(layer.editBuffer().isFeatureAttributesChanged(2)) # change attribute values layer.changeAttributeValue(1, 0, 'a') # test contents of buffer self.assertEqual( list(layer.editBuffer().changedAttributeValues().keys()), [1]) self.assertEqual(layer.editBuffer().changedAttributeValues()[1], {0: 'a'}) self.assertTrue(layer.editBuffer().isFeatureAttributesChanged(1)) self.assertFalse(layer.editBuffer().isFeatureAttributesChanged(2)) layer.changeAttributeValue(2, 1, 5) # test contents of buffer self.assertEqual( set(layer.editBuffer().changedAttributeValues().keys()), set([1, 2])) self.assertEqual(layer.editBuffer().changedAttributeValues()[1], {0: 'a'}) self.assertEqual(layer.editBuffer().changedAttributeValues()[2], {1: 5}) self.assertTrue(layer.editBuffer().isFeatureAttributesChanged(1)) self.assertTrue(layer.editBuffer().isFeatureAttributesChanged(2))
def processAlgorithm(self, parameters, context, feedback): # Get variables from dialog source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) field_name = self.parameterAsString(parameters, self.FIELD, context) kneighbors = self.parameterAsInt(parameters, self.KNEIGHBORS, context) use_field = bool(field_name) field_index = -1 fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 20)) current = 0 # Get properties of the field the grouping is based on if use_field: field_index = source.fields().lookupField(field_name) if field_index >= 0: fields.append(source.fields()[field_index]) # Add a field with the name of the grouping field # Initialize writer (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Polygon, source.sourceCrs()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) success = False fid = 0 # Get unique values of grouping field unique_values = source.uniqueValues(field_index) total = 100.0 / float(source.featureCount() * len(unique_values)) for unique in unique_values: points = [] filter = QgsExpression.createFieldEqualityExpression(field_name, unique) request = QgsFeatureRequest().setFilterExpression(filter) request.setSubsetOfAttributes([]) # Get features with the grouping attribute equal to the current grouping value features = source.getFeatures(request) for in_feature in features: if feedback.isCanceled(): break # Add points or vertices of more complex geometry points.extend(extract_points(in_feature.geometry())) current += 1 feedback.setProgress(int(current * total)) # A minimum of 3 points is necessary to proceed if len(points) >= 3: out_feature = QgsFeature() the_hull = concave_hull(points, kneighbors) if the_hull: vertex = [QgsPointXY(point[0], point[1]) for point in the_hull] poly = QgsGeometry().fromPolygonXY([vertex]) out_feature.setGeometry(poly) # Give the polygon the same attribute as the point grouping attribute out_feature.setAttributes([fid, unique]) sink.addFeature(out_feature, QgsFeatureSink.FastInsert) success = True # at least one polygon created fid += 1 if not success: raise QgsProcessingException('No hulls could be created. Most likely there were not at least three unique points in any of the groups.') else: # Field parameter provided but can't read from it raise QgsProcessingException('Unable to find grouping field') else: # Not grouped by field # Initialize writer (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Polygon, source.sourceCrs()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) points = [] request = QgsFeatureRequest() request.setSubsetOfAttributes([]) features = source.getFeatures(request) # Get all features total = 100.0 / source.featureCount() if source.featureCount() else 0 for in_feature in features: if feedback.isCanceled(): break # Add points or vertices of more complex geometry points.extend(extract_points(in_feature.geometry())) current += 1 feedback.setProgress(int(current * total)) # A minimum of 3 points is necessary to proceed if len(points) >= 3: out_feature = QgsFeature() the_hull = concave_hull(points, kneighbors) if the_hull: vertex = [QgsPointXY(point[0], point[1]) for point in the_hull] poly = QgsGeometry().fromPolygonXY([vertex]) out_feature.setGeometry(poly) out_feature.setAttributes([0]) sink.addFeature(out_feature, QgsFeatureSink.FastInsert) else: # the_hull returns None only when there are less than three points after cleaning raise QgsProcessingException('At least three unique points are required to create a concave hull.') else: raise QgsProcessingException('At least three points are required to create a concave hull.') return {self.OUTPUT: dest_id}
def testAddMultipleFeatures(self): # test adding multiple features to an edit buffer layer = createEmptyLayer() self.assertTrue(layer.startEditing()) self.assertEqual(layer.editBuffer().addedFeatures(), {}) self.assertFalse(layer.editBuffer().isFeatureAdded(1)) self.assertFalse(layer.editBuffer().isFeatureAdded(3)) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeatures([f1, f2])) # test contents of buffer added = layer.editBuffer().addedFeatures() new_feature_ids = list(added.keys()) self.assertEqual(added[new_feature_ids[0]]['fldtxt'], 'test2') self.assertEqual(added[new_feature_ids[0]]['fldint'], 246) self.assertEqual(added[new_feature_ids[1]]['fldtxt'], 'test') self.assertEqual(added[new_feature_ids[1]]['fldint'], 123) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[0])) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[1]))
def testChangeGeometry(self): # test changing geometries values from an edit buffer # make a layer with two features layer = createEmptyLayer() self.assertTrue(layer.startEditing()) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeature(f1)) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeature(f2)) layer.commitChanges() layer.startEditing() self.assertEqual(layer.editBuffer().changedGeometries(), {}) self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(1)) self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2)) # change attribute values layer.changeGeometry(1, QgsGeometry.fromPointXY(QgsPointXY(10, 20))) # test contents of buffer self.assertEqual(list(layer.editBuffer().changedGeometries().keys()), [1]) self.assertEqual( layer.editBuffer().changedGeometries()[1].constGet().x(), 10) self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1)) self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2)) layer.changeGeometry(2, QgsGeometry.fromPointXY(QgsPointXY(20, 40))) # test contents of buffer self.assertEqual(set(layer.editBuffer().changedGeometries().keys()), set([1, 2])) self.assertEqual( layer.editBuffer().changedGeometries()[1].constGet().x(), 10) self.assertEqual( layer.editBuffer().changedGeometries()[2].constGet().x(), 20) self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1)) self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(2))
def processAlgorithm(self, parameters, context, feedback): inLayer = self.parameterAsVectorLayer(parameters, self.INPUT, context) boundary = self.parameterAsEnum(parameters, self.MODE, context) == self.MODE_BOUNDARY smallestArea = self.parameterAsEnum(parameters, self.MODE, context) == self.MODE_SMALLEST_AREA if inLayer.selectedFeatureCount() == 0: feedback.reportError(self.tr('{0}: (No selection in input layer "{1}")').format(self.displayName(), parameters[self.INPUT])) featToEliminate = [] selFeatIds = inLayer.selectedFeatureIds() (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, inLayer.fields(), inLayer.wkbType(), inLayer.sourceCrs()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) for aFeat in inLayer.getFeatures(): if feedback.isCanceled(): break if aFeat.id() in selFeatIds: # Keep references to the features to eliminate featToEliminate.append(aFeat) else: # write the others to output sink.addFeature(aFeat, QgsFeatureSink.FastInsert) # Delete all features to eliminate in processLayer processLayer = QgsProcessingUtils.mapLayerFromString(dest_id, context) processLayer.startEditing() # ANALYZE if len(featToEliminate) > 0: # Prevent zero division start = 20.00 add = 80.00 / len(featToEliminate) else: start = 100 feedback.setProgress(start) madeProgress = True # We go through the list and see if we find any polygons we can # merge the selected with. If we have no success with some we # merge and then restart the whole story. while madeProgress: # Check if we made any progress madeProgress = False featNotEliminated = [] # Iterate over the polygons to eliminate for i in range(len(featToEliminate)): if feedback.isCanceled(): break feat = featToEliminate.pop() geom2Eliminate = feat.geometry() bbox = geom2Eliminate.boundingBox() fit = processLayer.getFeatures( QgsFeatureRequest().setFilterRect(bbox).setSubsetOfAttributes([])) mergeWithFid = None mergeWithGeom = None max = 0 min = -1 selFeat = QgsFeature() # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(geom2Eliminate.constGet()) engine.prepareGeometry() while fit.nextFeature(selFeat): if feedback.isCanceled(): break selGeom = selFeat.geometry() if engine.intersects(selGeom.constGet()): # We have a candidate iGeom = geom2Eliminate.intersection(selGeom) if not iGeom: continue if boundary: selValue = iGeom.length() else: # area. We need a common boundary in # order to merge if 0 < iGeom.length(): selValue = selGeom.area() else: selValue = -1 if -1 != selValue: useThis = True if smallestArea: if -1 == min: min = selValue else: if selValue < min: min = selValue else: useThis = False else: if selValue > max: max = selValue else: useThis = False if useThis: mergeWithFid = selFeat.id() mergeWithGeom = QgsGeometry(selGeom) # End while fit if mergeWithFid is not None: # A successful candidate newGeom = mergeWithGeom.combine(geom2Eliminate) if processLayer.changeGeometry(mergeWithFid, newGeom): madeProgress = True else: raise QgsProcessingException( self.tr('Could not replace geometry of feature with id {0}').format(mergeWithFid)) start = start + add feedback.setProgress(start) else: featNotEliminated.append(feat) # End for featToEliminate featToEliminate = featNotEliminated # End while if not processLayer.commitChanges(): raise QgsProcessingException(self.tr('Could not commit changes')) for feature in featNotEliminated: if feedback.isCanceled(): break sink.addFeature(feature, QgsFeatureSink.FastInsert) return {self.OUTPUT: dest_id}
def testDeleteMultipleFeatures(self): # test deleting multiple features from an edit buffer # make a layer with two features layer = createEmptyLayer() self.assertTrue(layer.startEditing()) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeature(f1)) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeature(f2)) layer.commitChanges() layer.startEditing() self.assertEqual(layer.editBuffer().deletedFeatureIds(), []) self.assertFalse(layer.editBuffer().isFeatureDeleted(1)) self.assertFalse(layer.editBuffer().isFeatureDeleted(2)) # delete features layer.deleteFeatures([1, 2]) # test contents of buffer self.assertEqual(set(layer.editBuffer().deletedFeatureIds()), set([1, 2])) self.assertTrue(layer.editBuffer().isFeatureDeleted(1)) self.assertTrue(layer.editBuffer().isFeatureDeleted(2))
def processAlgorithm(self, parameters, context, feedback): expr_context = self.createExpressionContext(parameters, context, self.source) self.group_by_expr.prepare(expr_context) # Group features in memory layers source = self.source count = self.source.featureCount() if count: progress_step = 50.0 / count current = 0 groups = {} keys = [] # We need deterministic order for the tests feature = QgsFeature() for feature in self.source.getFeatures(): expr_context.setFeature(feature) group_by_value = self.evaluateExpression(self.group_by_expr, expr_context) # Get an hashable key for the dict key = group_by_value if isinstance(key, list): key = tuple(key) group = groups.get(key, None) if group is None: sink, id = QgsProcessingUtils.createFeatureSink( 'memory:', context, source.fields(), source.wkbType(), source.sourceCrs()) layer = QgsProcessingUtils.mapLayerFromString(id, context) group = {'sink': sink, 'layer': layer, 'feature': feature} groups[key] = group keys.append(key) group['sink'].addFeature(feature, QgsFeatureSink.FastInsert) current += 1 feedback.setProgress(int(current * progress_step)) if feedback.isCanceled(): return (sink, dest_id) = self.parameterAsSink( parameters, self.OUTPUT, context, self.fields, QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) # Calculate aggregates on memory layers if len(keys): progress_step = 50.0 / len(keys) for current, key in enumerate(keys): group = groups[key] expr_context = self.createExpressionContext(parameters, context) expr_context.appendScope( QgsExpressionContextUtils.layerScope(group['layer'])) expr_context.setFeature(group['feature']) geometry = self.evaluateExpression(self.geometry_expr, expr_context) if geometry is not None and not geometry.isEmpty(): geometry = QgsGeometry.unaryUnion( geometry.asGeometryCollection()) if geometry.isEmpty(): raise QgsProcessingException( 'Impossible to combine geometries for {} = {}'.format( self.group_by, group_by_value)) attrs = [] for fields_expr in self.fields_expr: attrs.append(self.evaluateExpression(fields_expr, expr_context)) # Write output feature outFeat = QgsFeature() if geometry is not None: outFeat.setGeometry(geometry) outFeat.setAttributes(attrs) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) feedback.setProgress(50 + int(current * progress_step)) if feedback.isCanceled(): return return {self.OUTPUT: dest_id}
from shapely.geometry import Polygon, MultiPolygon from shapely.wkb import loads from shapely.wkt import dumps polyLayer = processing.getObject(Polygons) polyPrder = polyLayer.dataProvider() n = polyLayer.featureCount() l = 0 writer = processing.VectorWriter(Results, None, polyPrder.fields(), QGis.WKBMultiPolygon, polyPrder.crs()) resgeom = QgsGeometry() resfeat = QgsFeature() for feat in processing.features(polyLayer): progress.setPercentage(int(100 * l / n)) l += 1 g = loads(feat.geometry().asWkb()) if g.geom_type == 'MultiPolygon': resg = [Polygon(p.exterior, [r for r in p.interiors if Polygon(r).area > Max_area]) for p in g] else: resg = [Polygon(g.exterior, [r for r in g.interiors if Polygon(r).area > Max_area])]
def processAlgorithm(self, feedback): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_LAYER)) fields = layer.fields() fields.append(QgsField('node_pos', QVariant.Int)) fields.append(QgsField('node_index', QVariant.Int)) fields.append(QgsField('distance', QVariant.Double)) fields.append(QgsField('angle', QVariant.Double)) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter( fields, QgsWkbTypes.Point, layer.crs()) node_indices_string = self.getParameterValue(self.NODES) indices = [] for node in node_indices_string.split(','): try: indices.append(int(node)) except: raise GeoAlgorithmExecutionException( self.tr('\'{}\' is not a valid node index').format(node)) features = vector.features(layer) total = 100.0 / len(features) for current, f in enumerate(features): input_geometry = f.geometry() if not input_geometry: writer.addFeature(f) else: total_nodes = input_geometry.geometry().nCoordinates() for node in indices: if node < 0: node_index = total_nodes + node else: node_index = node if node_index < 0 or node_index >= total_nodes: continue distance = input_geometry.distanceToVertex(node_index) angle = math.degrees( input_geometry.angleAtVertex(node_index)) output_feature = QgsFeature() attrs = f.attributes() attrs.append(node) attrs.append(node_index) attrs.append(distance) attrs.append(angle) output_feature.setAttributes(attrs) point = input_geometry.vertexAt(node_index) output_feature.setGeometry(QgsGeometry.fromPoint(point)) writer.addFeature(output_feature) feedback.setProgress(int(current * total)) del writer
def doCheck(self, feedback): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_LAYER)) settings = QgsSettings() method = int(settings.value(settings_method_key, 1)) valid_output = self.getOutputFromName(self.VALID_OUTPUT) valid_fields = layer.fields() valid_writer = valid_output.getVectorWriter(valid_fields, layer.wkbType(), layer.crs()) valid_count = 0 invalid_output = self.getOutputFromName(self.INVALID_OUTPUT) invalid_fields = layer.fields().toList() + [ QgsField(name='_errors', type=QVariant.String, len=255) ] invalid_writer = invalid_output.getVectorWriter( invalid_fields, layer.wkbType(), layer.crs()) invalid_count = 0 error_output = self.getOutputFromName(self.ERROR_OUTPUT) error_fields = [ QgsField(name='message', type=QVariant.String, len=255) ] error_writer = error_output.getVectorWriter(error_fields, QgsWkbTypes.Point, layer.crs()) error_count = 0 features = vector.features(layer) total = 100.0 / len(features) for current, inFeat in enumerate(features): geom = inFeat.geometry() attrs = inFeat.attributes() valid = True if not geom.isNull() and not geom.isEmpty(): errors = list(geom.validateGeometry()) if errors: # QGIS method return a summary at the end if method == 1: errors.pop() valid = False reasons = [] for error in errors: errFeat = QgsFeature() error_geom = QgsGeometry.fromPoint(error.where()) errFeat.setGeometry(error_geom) errFeat.setAttributes([error.what()]) error_writer.addFeature(errFeat) error_count += 1 reasons.append(error.what()) reason = "\n".join(reasons) if len(reason) > 255: reason = reason[:252] + '...' attrs.append(reason) outFeat = QgsFeature() outFeat.setGeometry(geom) outFeat.setAttributes(attrs) if valid: valid_writer.addFeature(outFeat) valid_count += 1 else: invalid_writer.addFeature(outFeat) invalid_count += 1 feedback.setProgress(int(current * total)) del valid_writer del invalid_writer del error_writer if valid_count == 0: valid_output.open = False if invalid_count == 0: invalid_output.open = False if error_count == 0: error_output.open = False
def testFidSupport(self): # We do not use @unittest.expectedFailure since the test might actually succeed # on Linux 64bit with GDAL 1.11, where "long" is 64 bit... # GDAL 2.0 is guaranteed to properly support it on all platforms version_num = int(gdal.VersionInfo('VERSION_NUM')) if version_num < GDAL_COMPUTE_VERSION(2, 0, 0): return tmpfile = os.path.join(self.basetestpath, 'testFidSupport.sqlite') ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid']) lyr.CreateField(ogr.FieldDefn('strfield', ogr.OFTString)) lyr.CreateField(ogr.FieldDefn('intfield', ogr.OFTInteger)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(12) f.SetField(0, 'foo') f.SetField(1, 123) lyr.CreateFeature(f) f = None ds = None vl = QgsVectorLayer('{}'.format(tmpfile), 'test', 'ogr') self.assertEqual(len(vl.fields()), 3) got = [(f.attribute('fid'), f.attribute('strfield'), f.attribute('intfield')) for f in vl.getFeatures()] self.assertEqual(got, [(12, 'foo', 123)]) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("strfield = 'foo'"))] self.assertEqual(got, [(12, 'foo')]) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 12"))] self.assertEqual(got, [(12, 'foo')]) result = [f['strfield'] for f in vl.dataProvider().getFeatures(QgsFeatureRequest().setSubsetOfAttributes(['strfield'], vl.dataProvider().fields()))] self.assertEqual(result, ['foo']) result = [f['fid'] for f in vl.dataProvider().getFeatures(QgsFeatureRequest().setSubsetOfAttributes(['fid'], vl.dataProvider().fields()))] self.assertEqual(result, [12]) # Test that when the 'fid' field is not set, regular insertion is done f = QgsFeature() f.setFields(vl.fields()) f.setAttributes([None, 'automatic_id']) (res, out_f) = vl.dataProvider().addFeatures([f]) self.assertEqual(out_f[0].id(), 13) self.assertEqual(out_f[0].attribute('fid'), 13) self.assertEqual(out_f[0].attribute('strfield'), 'automatic_id') # Test that when the 'fid' field is set, it is really used to set the id f = QgsFeature() f.setFields(vl.fields()) f.setAttributes([9876543210, 'bar']) (res, out_f) = vl.dataProvider().addFeatures([f]) self.assertEqual(out_f[0].id(), 9876543210) self.assertEqual(out_f[0].attribute('fid'), 9876543210) self.assertEqual(out_f[0].attribute('strfield'), 'bar') got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'bar')]) self.assertTrue(vl.dataProvider().changeAttributeValues({9876543210: {1: 'baz'}})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baz')]) self.assertTrue(vl.dataProvider().changeAttributeValues({9876543210: {0: 9876543210, 1: 'baw'}})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baw')]) # Not allowed: changing the fid regular field self.assertTrue(vl.dataProvider().changeAttributeValues({9876543210: {0: 12, 1: 'baw'}})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baw')]) # Cannot delete fid self.assertFalse(vl.dataProvider().deleteAttributes([0])) # Delete first "genuine" attribute self.assertTrue(vl.dataProvider().deleteAttributes([1])) got = [(f.attribute('fid'), f.attribute('intfield')) for f in vl.dataProvider().getFeatures(QgsFeatureRequest().setFilterExpression("fid = 12"))] self.assertEqual(got, [(12, 123)])
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) if self.parameterAsBool(parameters, self.KEEP_FIELDS, context): fields = source.fields() else: fields = QgsFields() (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Polygon, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) allLinesList = [] features = source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes([])) feedback.pushInfo( QCoreApplication.translate('Polygonize', 'Processing lines…')) total = (40.0 / source.featureCount()) if source.featureCount() else 1 for current, inFeat in enumerate(features): if feedback.isCanceled(): break if inFeat.geometry(): allLinesList.append(inFeat.geometry()) feedback.setProgress(int(current * total)) feedback.setProgress(40) feedback.pushInfo( QCoreApplication.translate('Polygonize', 'Noding lines…')) allLines = QgsGeometry.unaryUnion(allLinesList) if feedback.isCanceled(): return {} feedback.setProgress(45) feedback.pushInfo( QCoreApplication.translate('Polygonize', 'Polygonizing…')) polygons = QgsGeometry.polygonize([allLines]) if polygons.isEmpty(): feedback.reportError(self.tr('No polygons were created!')) feedback.setProgress(50) if not polygons.isEmpty(): feedback.pushInfo( QCoreApplication.translate('Polygonize', 'Saving polygons…')) total = 50.0 / polygons.constGet().numGeometries() for i in range(polygons.constGet().numGeometries()): if feedback.isCanceled(): break outFeat = QgsFeature() geom = QgsGeometry(polygons.constGet().geometryN(i).clone()) outFeat.setGeometry(geom) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) feedback.setProgress(50 + int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) 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()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) # 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 testUpdateMode(self): """ Test that on-the-fly re-opening in update/read-only mode works """ tmpdir = tempfile.mkdtemp() self.dirs_to_cleanup.append(tmpdir) srcpath = os.path.join(TEST_DATA_DIR, 'provider') for file in glob.glob(os.path.join(srcpath, 'shapefile.*')): shutil.copy(os.path.join(srcpath, file), tmpdir) datasource = os.path.join(tmpdir, 'shapefile.shp') vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') caps = vl.dataProvider().capabilities() self.assertTrue(caps & QgsVectorDataProvider.AddFeatures) self.assertTrue(caps & QgsVectorDataProvider.DeleteFeatures) self.assertTrue(caps & QgsVectorDataProvider.ChangeAttributeValues) self.assertTrue(caps & QgsVectorDataProvider.AddAttributes) self.assertTrue(caps & QgsVectorDataProvider.DeleteAttributes) self.assertTrue(caps & QgsVectorDataProvider.CreateSpatialIndex) self.assertTrue(caps & QgsVectorDataProvider.SelectAtId) self.assertTrue(caps & QgsVectorDataProvider.ChangeGeometries) # self.assertTrue(caps & QgsVectorDataProvider.ChangeFeatures) # We should be really opened in read-only mode even if write capabilities are declared self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-only") # Unbalanced call to leaveUpdateMode() self.assertFalse(vl.dataProvider().leaveUpdateMode()) # Test that startEditing() / commitChanges() plays with enterUpdateMode() / leaveUpdateMode() self.assertTrue(vl.startEditing()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().isValid()) self.assertTrue(vl.commitChanges()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-only") self.assertTrue(vl.dataProvider().isValid()) # Manual enterUpdateMode() / leaveUpdateMode() with 2 depths self.assertTrue(vl.dataProvider().enterUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") caps = vl.dataProvider().capabilities() self.assertTrue(caps & QgsVectorDataProvider.AddFeatures) f = QgsFeature() f.setAttributes([200]) f.setGeometry(QgsGeometry.fromWkt('Point (2 49)')) (ret, feature_list) = vl.dataProvider().addFeatures([f]) self.assertTrue(ret) fid = feature_list[0].id() features = [ f_iter for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid)) ] values = [f_iter['pk'] for f_iter in features] self.assertEqual(values, [200]) got_geom = [f_iter.geometry() for f_iter in features][0].constGet() self.assertEqual((got_geom.x(), got_geom.y()), (2.0, 49.0)) self.assertTrue(vl.dataProvider().changeGeometryValues( {fid: QgsGeometry.fromWkt('Point (3 50)')})) self.assertTrue(vl.dataProvider().changeAttributeValues( {fid: { 0: 100 }})) features = [ f_iter for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid)) ] values = [f_iter['pk'] for f_iter in features] got_geom = [f_iter.geometry() for f_iter in features][0].constGet() self.assertEqual((got_geom.x(), got_geom.y()), (3.0, 50.0)) self.assertTrue(vl.dataProvider().deleteFeatures([fid])) # Check that it has really disappeared osgeo.gdal.PushErrorHandler('CPLQuietErrorHandler') features = [ f_iter for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid)) ] osgeo.gdal.PopErrorHandler() self.assertEqual(features, []) self.assertTrue(vl.dataProvider().addAttributes( [QgsField("new_field", QVariant.Int, "integer")])) self.assertTrue(vl.dataProvider().deleteAttributes( [len(vl.dataProvider().fields()) - 1])) self.assertTrue(vl.startEditing()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.commitChanges()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().enterUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().leaveUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().leaveUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-only") # Test that update mode will be implictly enabled if doing an action # that requires update mode (ret, _) = vl.dataProvider().addFeatures([QgsFeature()]) self.assertTrue(ret) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write")
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) fields = source.fields() fields.append(QgsField('node_pos', QVariant.Int)) fields.append(QgsField('node_index', QVariant.Int)) fields.append(QgsField('distance', QVariant.Double)) fields.append(QgsField('angle', QVariant.Double)) fields.append(QgsField('NUM_FIELD', QVariant.Int)) wkb_type = QgsWkbTypes.Point if QgsWkbTypes.hasM(source.wkbType()): wkb_type = QgsWkbTypes.addM(wkb_type) if QgsWkbTypes.hasZ(source.wkbType()): wkb_type = QgsWkbTypes.addZ(wkb_type) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, wkb_type, source.sourceCrs()) node_indices_string = self.parameterAsString(parameters, self.NODES, context) indices = [] for node in node_indices_string.split(','): try: indices.append(int(node)) except: raise QgsProcessingException( self.tr('\'{}\' is not a valid node index').format(node)) features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break input_geometry = f.geometry() if not input_geometry: sink.addFeature(f, QgsFeatureSink.FastInsert) else: total_nodes = input_geometry.geometry().nCoordinates() for node in indices: if node < 0: node_index = total_nodes + node else: node_index = node if node_index < 0 or node_index >= total_nodes: continue distance = input_geometry.distanceToVertex(node_index) angle = math.degrees(input_geometry.angleAtVertex(node_index)) output_feature = QgsFeature() attrs = f.attributes() attrs.append(node) attrs.append(node_index) attrs.append(distance) attrs.append(angle) output_feature.setAttributes(attrs) point = input_geometry.vertexAt(node_index) output_feature.setGeometry(QgsGeometry(point)) sink.addFeature(output_feature, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def run_checks(): self.assertEqual([f.name() for f in vl.fields()], ['fid', 'type', 'value']) # expression req = QgsFeatureRequest() req.setFilterExpression("value=16") it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter fid req = QgsFeatureRequest() req.setFilterFid(5) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter fids req = QgsFeatureRequest() req.setFilterFids([5]) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # check with subset of attributes req = QgsFeatureRequest() req.setFilterFids([5]) req.setSubsetOfAttributes([2]) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes()[2], 16) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter rect and expression req = QgsFeatureRequest() req.setFilterExpression("value=16 or value=14") req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5)) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter rect and fids req = QgsFeatureRequest() req.setFilterFids([3, 5]) req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5)) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # Ensure that orig_ogc_fid is still retrieved even if attribute subset is passed req = QgsFeatureRequest() req.setSubsetOfAttributes([]) it = vl.getFeatures(req) ids = [] geoms = {} while it.nextFeature(f): ids.append(f.id()) geoms[f.id()] = f.geometry().asWkt() self.assertCountEqual(ids, [3, 4, 5]) self.assertEqual(geoms, {3: 'Point (3 3)', 4: 'Point (4 4)', 5: 'Point (5 5)'})
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 processAlgorithm(self, parameters, context, feedback): line_source = self.parameterAsSource(parameters, self.LINES, context) if line_source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.LINES)) poly_source = self.parameterAsSource(parameters, self.POLYGONS, context) if poly_source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.POLYGONS)) length_field_name = self.parameterAsString(parameters, self.LEN_FIELD, context) count_field_name = self.parameterAsString(parameters, self.COUNT_FIELD, context) fields = poly_source.fields() if fields.lookupField(length_field_name) < 0: fields.append(QgsField(length_field_name, QVariant.Double)) length_field_index = fields.lookupField(length_field_name) if fields.lookupField(count_field_name) < 0: fields.append(QgsField(count_field_name, QVariant.Int)) count_field_index = fields.lookupField(count_field_name) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, poly_source.wkbType(), poly_source.sourceCrs()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) spatialIndex = QgsSpatialIndex(line_source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs(), context.transformContext())), feedback) distArea = QgsDistanceArea() distArea.setSourceCrs(poly_source.sourceCrs(), context.transformContext()) distArea.setEllipsoid(context.project().ellipsoid()) features = poly_source.getFeatures() total = 100.0 / poly_source.featureCount() if poly_source.featureCount() else 0 for current, poly_feature in enumerate(features): if feedback.isCanceled(): break output_feature = QgsFeature() count = 0 length = 0 if poly_feature.hasGeometry(): poly_geom = poly_feature.geometry() has_intersections = False lines = spatialIndex.intersects(poly_geom.boundingBox()) engine = None if len(lines) > 0: has_intersections = True # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(poly_geom.constGet()) engine.prepareGeometry() if has_intersections: request = QgsFeatureRequest().setFilterFids(lines).setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs(), context.transformContext()) for line_feature in line_source.getFeatures(request): if feedback.isCanceled(): break if engine.intersects(line_feature.geometry().constGet()): outGeom = poly_geom.intersection(line_feature.geometry()) length += distArea.measureLength(outGeom) count += 1 output_feature.setGeometry(poly_geom) attrs = poly_feature.attributes() if length_field_index == len(attrs): attrs.append(length) else: attrs[length_field_index] = length if count_field_index == len(attrs): attrs.append(count) else: attrs[count_field_index] = count output_feature.setAttributes(attrs) sink.addFeature(output_feature, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): sourceA = self.parameterAsSource(parameters, self.INPUT, context) sourceB = self.parameterAsSource(parameters, self.INTERSECT, context) fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS, context) fieldsB = self.parameterAsFields(parameters, self.INTERSECT_FIELDS, context) fieldListA = QgsFields() field_indices_a = [] if len(fieldsA) > 0: for f in fieldsA: idxA = sourceA.fields().lookupField(f) if idxA >= 0: field_indices_a.append(idxA) fieldListA.append(sourceA.fields()[idxA]) else: fieldListA = sourceA.fields() field_indices_a = [i for i in range(0, fieldListA.count())] fieldListB = QgsFields() field_indices_b = [] if len(fieldsB) > 0: for f in fieldsB: idxB = sourceB.fields().lookupField(f) if idxB >= 0: field_indices_b.append(idxB) fieldListB.append(sourceB.fields()[idxB]) else: fieldListB = sourceB.fields() field_indices_b = [i for i in range(0, fieldListB.count())] fieldListB = vector.testForUniqueness(fieldListA, fieldListB) for b in fieldListB: fieldListA.append(b) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fieldListA, QgsWkbTypes.Point, sourceA.sourceCrs()) spatialIndex = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback) outFeat = QgsFeature() features = sourceA.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(field_indices_a)) total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 0 for current, inFeatA in enumerate(features): if feedback.isCanceled(): break if not inFeatA.hasGeometry(): continue inGeom = inFeatA.geometry() has_intersections = False lines = spatialIndex.intersects(inGeom.boundingBox()) engine = None if len(lines) > 0: has_intersections = True # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(inGeom.geometry()) engine.prepareGeometry() if has_intersections: request = QgsFeatureRequest().setFilterFids(lines) request.setDestinationCrs(sourceA.sourceCrs()) request.setSubsetOfAttributes(field_indices_b) for inFeatB in sourceB.getFeatures(request): if feedback.isCanceled(): break tmpGeom = inFeatB.geometry() points = [] if engine.intersects(tmpGeom.geometry()): tempGeom = inGeom.intersection(tmpGeom) out_attributes = [inFeatA.attributes()[i] for i in field_indices_a] out_attributes.extend([inFeatB.attributes()[i] for i in field_indices_b]) if tempGeom.type() == QgsWkbTypes.PointGeometry: if tempGeom.isMultipart(): points = tempGeom.asMultiPoint() else: points.append(tempGeom.asPoint()) for j in points: outFeat.setGeometry(tempGeom.fromPoint(j)) outFeat.setAttributes(out_attributes) sink.addFeature(outFeat, 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): poly_source = self.parameterAsSource(parameters, self.POLYGONS, context) if poly_source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.POLYGONS)) point_source = self.parameterAsSource(parameters, self.POINTS, context) if point_source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.POINTS)) weight_field = self.parameterAsString(parameters, self.WEIGHT, context) weight_field_index = -1 if weight_field: weight_field_index = point_source.fields().lookupField( weight_field) class_field = self.parameterAsString(parameters, self.CLASSFIELD, context) class_field_index = -1 if class_field: class_field_index = point_source.fields().lookupField(class_field) field_name = self.parameterAsString(parameters, self.FIELD, context) fields = poly_source.fields() if fields.lookupField(field_name) < 0: fields.append(QgsField(field_name, QVariant.Int)) field_index = fields.lookupField(field_name) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, poly_source.wkbType(), poly_source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) spatialIndex = QgsSpatialIndex( point_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes( []).setDestinationCrs(poly_source.sourceCrs(), context.transformContext())), feedback) point_attribute_indices = [] if weight_field_index >= 0: point_attribute_indices.append(weight_field_index) if class_field_index >= 0: point_attribute_indices.append(class_field_index) features = poly_source.getFeatures() total = 100.0 / poly_source.featureCount() if poly_source.featureCount( ) else 0 for current, polygon_feature in enumerate(features): if feedback.isCanceled(): break count = 0 output_feature = QgsFeature() if polygon_feature.hasGeometry(): geom = polygon_feature.geometry() engine = QgsGeometry.createGeometryEngine(geom.constGet()) engine.prepareGeometry() count = 0 classes = set() points = spatialIndex.intersects(geom.boundingBox()) if len(points) > 0: request = QgsFeatureRequest().setFilterFids( points).setDestinationCrs(poly_source.sourceCrs(), context.transformContext()) request.setSubsetOfAttributes(point_attribute_indices) for point_feature in point_source.getFeatures(request): if feedback.isCanceled(): break if engine.contains( point_feature.geometry().constGet()): if weight_field_index >= 0: weight = point_feature.attributes( )[weight_field_index] try: count += float(weight) except: # Ignore fields with non-numeric values pass elif class_field_index >= 0: point_class = point_feature.attributes( )[class_field_index] if point_class not in classes: classes.add(point_class) else: count += 1 output_feature.setGeometry(geom) attrs = polygon_feature.attributes() if class_field_index >= 0: score = len(classes) else: score = count if field_index == len(attrs): attrs.append(score) else: attrs[field_index] = score output_feature.setAttributes(attrs) sink.addFeature(output_feature, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
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)