def testModel(self): """Test the mapping model""" model = QgsFieldMappingModel(self.source_fields, self.destination_fields) self.assertEqual(model.rowCount(QModelIndex()), 3) self.assertIsNone(model.data(model.index(9999, 0), Qt.DisplayRole)) # We now have this default mapping: # source exp | destination fld # ------------------------------------------- # source_field2 | destination_field1 # source_field1 | destination_field2 # NOT SET (NULL) | destination_field3 self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), '"source_field2"') self.assertEqual(model.data(model.index(0, 1), Qt.DisplayRole), 'destination_field1') self.assertEqual(model.data(model.index(0, 3), Qt.DisplayRole), 10) self.assertEqual(model.data(model.index(0, 4), Qt.DisplayRole), 8) self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), '"source_field1"') self.assertEqual(model.data(model.index(1, 1), Qt.DisplayRole), 'destination_field2') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), QVariant()) self.assertEqual(model.data(model.index(2, 1), Qt.DisplayRole), 'destination_field3') # Test expression scope ctx = model.contextGenerator().createExpressionContext() self.assertTrue('source_field1' in ctx.fields().names()) # Test add fields model.appendField(QgsField('destination_field4', QVariant.String)) self.assertEqual(model.rowCount(QModelIndex()), 4) self.assertEqual(model.data(model.index(3, 1), Qt.DisplayRole), 'destination_field4') # Test remove field model.removeField(model.index(3, 0)) self.assertEqual(model.rowCount(QModelIndex()), 3) self.assertEqual(model.data(model.index(2, 1), Qt.DisplayRole), 'destination_field3') # Test edit fields mapping = model.mapping() self.assertEqual(mapping[0].field.name(), 'destination_field1') self.assertEqual(mapping[1].field.name(), 'destination_field2') self.assertEqual(mapping[2].field.name(), 'destination_field3') self.assertEqual(mapping[0].originalName, 'destination_field1') self.assertEqual(mapping[1].originalName, 'destination_field2') self.assertEqual(mapping[2].originalName, 'destination_field3') # Test move up or down self.assertFalse(model.moveUp(model.index(0, 0))) self.assertFalse(model.moveUp(model.index(100, 0))) self.assertFalse(model.moveDown(model.index(2, 0))) self.assertFalse(model.moveDown(model.index(100, 0))) self.assertTrue(model.moveDown(model.index(0, 0))) mapping = model.mapping() self.assertEqual(mapping[1].field.name(), 'destination_field1') self.assertEqual(mapping[0].field.name(), 'destination_field2') self.assertEqual(mapping[2].field.name(), 'destination_field3') self.assertEqual(mapping[1].originalName, 'destination_field1') self.assertEqual(mapping[0].originalName, 'destination_field2') self.assertEqual(mapping[2].originalName, 'destination_field3') self.assertTrue(model.moveUp(model.index(1, 0))) mapping = model.mapping() self.assertEqual(mapping[0].field.name(), 'destination_field1') self.assertEqual(mapping[1].field.name(), 'destination_field2') self.assertEqual(mapping[2].field.name(), 'destination_field3') self.assertEqual(mapping[0].originalName, 'destination_field1') self.assertEqual(mapping[1].originalName, 'destination_field2') self.assertEqual(mapping[2].originalName, 'destination_field3') self.assertTrue(model.moveUp(model.index(2, 0))) mapping = model.mapping() self.assertEqual(mapping[0].field.name(), 'destination_field1') self.assertEqual(mapping[2].field.name(), 'destination_field2') self.assertEqual(mapping[1].field.name(), 'destination_field3') self.assertEqual(mapping[0].originalName, 'destination_field1') self.assertEqual(mapping[2].originalName, 'destination_field2') self.assertEqual(mapping[1].originalName, 'destination_field3')
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 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 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 processAlgorithm(self, feedback): layer = dataobjects.getLayerFromString( self.getParameterValue(self.INPUT_VECTOR)) startPoint = self.getParameterValue(self.START_POINT) endPoint = self.getParameterValue(self.END_POINT) strategy = self.getParameterValue(self.STRATEGY) directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) forwardValue = self.getParameterValue(self.VALUE_FORWARD) backwardValue = self.getParameterValue(self.VALUE_BACKWARD) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) speedFieldName = self.getParameterValue(self.SPEED_FIELD) defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) tolerance = self.getParameterValue(self.TOLERANCE) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter( fields.toList(), QgsWkbTypes.LineString, layer.crs()) tmp = startPoint.split(',') startPoint = QgsPoint(float(tmp[0]), float(tmp[1])) tmp = endPoint.split(',') endPoint = QgsPoint(float(tmp[0]), float(tmp[1])) directionField = -1 if directionFieldName is not None: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName is not None: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder( iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, [startPoint, endPoint]) feedback.pushInfo(self.tr('Calculating shortest path...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) idxEnd = graph.findVertex(snappedPoints[1]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: raise GeoAlgorithmExecutionException( self.tr('There is no route from start point to end point.')) route = [] cost = 0.0 current = idxEnd while current != idxStart: cost += graph.edge(tree[current]).cost(0) route.append( graph.vertex(graph.edge(tree[current]).inVertex()).point()) current = graph.edge(tree[current]).outVertex() route.append(snappedPoints[0]) route.reverse() self.setOutputValue(self.TRAVEL_COST, cost / multiplier) feedback.pushInfo(self.tr('Writing results...')) geom = QgsGeometry.fromPolyline(route) feat = QgsFeature() feat.setFields(fields) feat['start'] = startPoint.toString() feat['end'] = endPoint.toString() feat['cost'] = cost / multiplier feat.setGeometry(geom) writer.addFeature(feat) del writer
def processAlgorithm(self, context, feedback): layer = QgsProcessingUtils.mapLayerFromString( self.getParameterValue(self.INPUT_VECTOR), context) startPoint = self.getParameterValue(self.START_POINT) strategy = self.getParameterValue(self.STRATEGY) travelCost = self.getParameterValue(self.TRAVEL_COST) directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) forwardValue = self.getParameterValue(self.VALUE_FORWARD) backwardValue = self.getParameterValue(self.VALUE_BACKWARD) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) speedFieldName = self.getParameterValue(self.SPEED_FIELD) defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) tolerance = self.getParameterValue(self.TOLERANCE) tmp = startPoint.split(',') startPoint = QgsPoint(float(tmp[0]), float(tmp[1])) directionField = -1 if directionFieldName is not None: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName is not None: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder( iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, [startPoint]) feedback.pushInfo(self.tr('Calculating service area...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = [] for i, v in enumerate(cost): if v > travelCost and tree[i] != -1: vertexId = graph.edge(tree[i]).outVertex() if cost[vertexId] <= travelCost: vertices.append(i) upperBoundary = [] lowerBoundary = [] for i in vertices: upperBoundary.append( graph.vertex(graph.edge(tree[i]).inVertex()).point()) lowerBoundary.append( graph.vertex(graph.edge(tree[i]).outVertex()).point()) feedback.pushInfo(self.tr('Writing results...')) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) writer = self.getOutputFromName(self.OUTPUT_POINTS).getVectorWriter( fields, QgsWkbTypes.MultiPoint, layer.crs(), context) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = startPoint.toString() writer.addFeature(feat) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = startPoint.toString() writer.addFeature(feat) del writer upperBoundary.append(startPoint) lowerBoundary.append(startPoint) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) writer = self.getOutputFromName(self.OUTPUT_POLYGON).getVectorWriter( fields, QgsWkbTypes.Polygon, layer.crs(), context) geom = geomUpper.convexHull() feat.setGeometry(geom) feat['type'] = 'upper' feat['start'] = startPoint.toString() writer.addFeature(feat) geom = geomLower.convexHull() feat.setGeometry(geom) feat['type'] = 'lower' feat['start'] = startPoint.toString() writer.addFeature(feat) del writer
def testFilter(self): """Test filter creation""" renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('field') renderer.addCategory( QgsRendererCategory('a', createMarkerSymbol(), 'a')) renderer.addCategory( QgsRendererCategory('b', createMarkerSymbol(), 'b')) renderer.addCategory( QgsRendererCategory('c', createMarkerSymbol(), 'c')) # add default category renderer.addCategory( QgsRendererCategory('', createMarkerSymbol(), 'default')) fields = QgsFields() fields.append(QgsField('field', QVariant.String)) fields.append(QgsField('num', QVariant.Double)) self.assertEqual(renderer.filter(fields), '') # remove categories, leaving default assert renderer.updateCategoryRenderState(0, False) self.assertEqual(renderer.filter(fields), "(\"field\") NOT IN ('a') OR (\"field\") IS NULL") assert renderer.updateCategoryRenderState(1, False) self.assertEqual( renderer.filter(fields), "(\"field\") NOT IN ('a','b') OR (\"field\") IS NULL") assert renderer.updateCategoryRenderState(2, False) self.assertEqual( renderer.filter(fields), "(\"field\") NOT IN ('a','b','c') OR (\"field\") IS NULL") # remove default category assert renderer.updateCategoryRenderState(3, False) self.assertEqual(renderer.filter(fields), "FALSE") # add back other categories, leaving default disabled assert renderer.updateCategoryRenderState(0, True) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a')") assert renderer.updateCategoryRenderState(1, True) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b')") assert renderer.updateCategoryRenderState(2, True) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b','c')") renderer.deleteAllCategories() # just default category renderer.addCategory( QgsRendererCategory('', createMarkerSymbol(), 'default')) self.assertEqual(renderer.filter(fields), '') assert renderer.updateCategoryRenderState(0, False) self.assertEqual(renderer.filter(fields), 'FALSE') renderer.deleteAllCategories() # no default category renderer.addCategory( QgsRendererCategory('a', createMarkerSymbol(), 'a')) renderer.addCategory( QgsRendererCategory('b', createMarkerSymbol(), 'b')) renderer.addCategory( QgsRendererCategory('c', createMarkerSymbol(), 'c')) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b','c')") assert renderer.updateCategoryRenderState(0, False) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('b','c')") assert renderer.updateCategoryRenderState(2, False) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('b')") assert renderer.updateCategoryRenderState(1, False) self.assertEqual(renderer.filter(fields), "FALSE") renderer.deleteAllCategories() renderer.setClassAttribute('num') # numeric categories renderer.addCategory(QgsRendererCategory(1, createMarkerSymbol(), 'a')) renderer.addCategory(QgsRendererCategory(2, createMarkerSymbol(), 'b')) renderer.addCategory(QgsRendererCategory(3, createMarkerSymbol(), 'c')) self.assertEqual(renderer.filter(fields), '(\"num\") IN (1,2,3)') assert renderer.updateCategoryRenderState(0, False) self.assertEqual(renderer.filter(fields), "(\"num\") IN (2,3)") assert renderer.updateCategoryRenderState(2, False) self.assertEqual(renderer.filter(fields), "(\"num\") IN (2)") assert renderer.updateCategoryRenderState(1, False) self.assertEqual(renderer.filter(fields), "FALSE") # with value lists renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('field') renderer.addCategory( QgsRendererCategory(['a', 'b'], createMarkerSymbol(), 'ab')) renderer.addCategory( QgsRendererCategory('c', createMarkerSymbol(), 'c')) renderer.addCategory( QgsRendererCategory('', createMarkerSymbol(), 'default')) self.assertEqual(renderer.filter(fields), '') # remove categories, leaving default assert renderer.updateCategoryRenderState(0, False) self.assertEqual( renderer.filter(fields), "(\"field\") NOT IN ('a','b') OR (\"field\") IS NULL") assert renderer.updateCategoryRenderState(1, False) self.assertEqual( renderer.filter(fields), "(\"field\") NOT IN ('a','b','c') OR (\"field\") IS NULL") assert renderer.updateCategoryRenderState(2, False) self.assertEqual(renderer.filter(fields), "FALSE") assert renderer.updateCategoryRenderState(0, True) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b')") assert renderer.updateCategoryRenderState(1, True) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b','c')") assert renderer.updateCategoryRenderState(1, False) assert renderer.updateCategoryRenderState(2, True) self.assertEqual(renderer.filter(fields), "(\"field\") NOT IN ('c') OR (\"field\") IS NULL") renderer.deleteAllCategories() renderer.setClassAttribute('num') renderer.addCategory( QgsRendererCategory([1, 2], createMarkerSymbol(), 'a')) renderer.addCategory(QgsRendererCategory(3, createMarkerSymbol(), 'b')) self.assertEqual(renderer.filter(fields), '(\"num\") IN (1,2,3)') assert renderer.updateCategoryRenderState(0, False) self.assertEqual(renderer.filter(fields), "(\"num\") IN (3)") assert renderer.updateCategoryRenderState(1, False) self.assertEqual(renderer.filter(fields), "FALSE") assert renderer.updateCategoryRenderState(0, True) self.assertEqual(renderer.filter(fields), "(\"num\") IN (1,2)")
def testFieldsWithSpecialCharacters(self): ml = QgsVectorLayer("Point?srid=EPSG:4326&field=123:int", "mem_with_nontext_fieldnames", "memory") self.assertEqual(ml.isValid(), True) QgsProject.instance().addMapLayer(ml) ml.startEditing() self.assertTrue(ml.addAttribute(QgsField('abc:123', QVariant.String))) self.assertTrue(ml.addAttribute(QgsField( 'map', QVariant.String))) # matches QGIS expression function name f1 = QgsFeature(ml.fields()) f1.setGeometry(QgsGeometry.fromWkt('POINT(0 0)')) f1.setAttributes([1, 'a', 'b']) f2 = QgsFeature(ml.fields()) f2.setGeometry(QgsGeometry.fromWkt('POINT(1 1)')) f2.setAttributes([2, 'c', 'd']) ml.addFeatures([f1, f2]) ml.commitChanges() vl = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames", "vl", "virtual") self.assertEqual(vl.isValid(), True) self.assertEqual(vl.fields().at(0).name(), '123') self.assertEqual(vl.fields().at(1).name(), 'abc:123') self.assertEqual(vl.featureCount(), 2) features = [ f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( '"abc:123"=\'c\'')) ] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [2, 'c', 'd']) features = [ f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( '"map"=\'b\'')) ] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [1, 'a', 'b']) vl2 = QgsVectorLayer( "?query=select * from mem_with_nontext_fieldnames where \"abc:123\"='c'", "vl", "virtual") self.assertEqual(vl2.isValid(), True) self.assertEqual(vl2.fields().at(0).name(), '123') self.assertEqual(vl2.fields().at(1).name(), 'abc:123') self.assertEqual(vl2.featureCount(), 1) features = [f for f in vl2.getFeatures()] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [2, 'c', 'd']) vl3 = QgsVectorLayer( "?query=select * from mem_with_nontext_fieldnames where \"map\"='b'", "vl", "virtual") self.assertEqual(vl3.isValid(), True) self.assertEqual(vl3.fields().at(0).name(), '123') self.assertEqual(vl3.fields().at(1).name(), 'abc:123') self.assertEqual(vl3.featureCount(), 1) features = [f for f in vl3.getFeatures()] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [1, 'a', 'b']) QgsProject.instance().removeMapLayer(ml)
def processAlgorithm(self, parameters, context, feedback): idx = self.parameterAsEnum(parameters, self.TYPE, context) hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context) vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context) hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context) vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context) crs = self.parameterAsCrs(parameters, self.CRS, context) bbox = self.parameterAsExtent(parameters, self.EXTENT, context, crs) if hSpacing <= 0 or vSpacing <= 0: raise QgsProcessingException( self.tr('Invalid grid spacing: {0}/{1}').format( hSpacing, vSpacing)) if bbox.width() < hSpacing: raise QgsProcessingException( self.tr( 'Horizontal spacing is too large for the covered area')) if hSpacing <= hOverlay or vSpacing <= vOverlay: raise QgsProcessingException( self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay)) if bbox.height() < vSpacing: raise QgsProcessingException( self.tr('Vertical spacing is too large for the covered area')) fields = QgsFields() fields.append(QgsField('left', QVariant.Double, '', 24, 16)) fields.append(QgsField('top', QVariant.Double, '', 24, 16)) fields.append(QgsField('right', QVariant.Double, '', 24, 16)) fields.append(QgsField('bottom', QVariant.Double, '', 24, 16)) fields.append(QgsField('id', QVariant.Int, '', 10, 0)) if idx == 0: outputWkb = QgsWkbTypes.Point elif idx == 1: outputWkb = QgsWkbTypes.LineString else: outputWkb = QgsWkbTypes.Polygon (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, outputWkb, crs) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) if idx == 0: self._pointGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback) elif idx == 1: self._lineGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback) elif idx == 2: self._rectangleGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback) elif idx == 3: self._diamondGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback) elif idx == 4: self._hexagonGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) sampled_raster = self.parameterAsRasterLayer(parameters, self.RASTERCOPY, context) columnPrefix = self.parameterAsString(parameters, self.COLUMN_PREFIX, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) source_fields = source.fields() raster_fields = QgsFields() # append field to vector as columnPrefix_bandCount for b in range(sampled_raster.bandCount()): raster_fields.append( QgsField(columnPrefix + str('_{}'.format(b + 1)), QVariant.Double)) # combine all the vector fields out_fields = QgsProcessingUtils.combineFields(source_fields, raster_fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, out_fields, source.wkbType(), source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) total = 100.0 / source.featureCount() if source.featureCount() else 0 features = source.getFeatures() # create the coordinates transformation context ct = QgsCoordinateTransform(source.sourceCrs(), sampled_raster.crs(), context.transformContext()) for n, i in enumerate(source.getFeatures()): attrs = i.attributes() if i.geometry().isMultipart( ) and i.geometry().constGet().partCount() > 1: sink.addFeature(i, QgsFeatureSink.FastInsert) feedback.setProgress(int(n * total)) feedback.reportError( self.tr( 'Impossible to sample data of multipart feature {}.'). format(i.id())) continue # get the feature geometry as point point = QgsPointXY() if i.geometry().isMultipart(): point = i.geometry().asMultiPoint()[0] else: point = i.geometry().asPoint() # reproject to raster crs try: point = ct.transform(point) except QgsCsException: for b in range(sampled_raster.bandCount()): attrs.append(None) i.setAttributes(attrs) sink.addFeature(i, QgsFeatureSink.FastInsert) feedback.setProgress(int(n * total)) feedback.reportError( self.tr( 'Could not reproject feature {} to raster CRS').format( i.id())) continue for b in range(sampled_raster.bandCount()): value, ok = sampled_raster.dataProvider().sample(point, b + 1) if ok: attrs.append(value) else: attrs.append(NULL) i.setAttributes(attrs) sink.addFeature(i, QgsFeatureSink.FastInsert) feedback.setProgress(int(n * total)) return {self.OUTPUT: dest_id}
def epa2gis(inpname, epsg_crs): plugin_path = os.path.dirname(__file__) file_extension = os.path.dirname(inpname) inpname = os.path.basename(inpname) inp = file_extension + '/' + inpname if len(file_extension) == 0: inp = inpname newpath = file_extension + '/_shapefiles_' if not os.path.exists(newpath): os.makedirs(newpath) iface = qgis.utils.iface d.LoadFile(inp) d.BinUpdateClass() nlinkCount = d.getBinLinkCount() res = newpath + '\\' saveFile = res + inpname[:len(inpname) - 4] # Get all Sections mixing = d.getMixingSection() reactions = d.getReactionsSection() sources = d.getSourcesSection() rules = d.getRulesSection() quality = d.getQualitySection() curves = d.getCurvesSection() patterns = d.getPatternsSection() controls = d.getControlsSection() emitters = d.getEmittersSection() status = d.getStatusSection() demands = d.getDemandsSection() energy = d.getEnergySection() optReactions = d.getReactionsOptionsSection() times = d.getTimesSection() report = d.getReportSection() options = d.getOptionsSection() # Get all Section lengths allSections = [ len(energy), len(optReactions), len(demands), len(status), len(emitters), len(controls), len(patterns), len(curves[0]), len(quality), len(rules), len(sources), len(reactions), len(mixing), len(times), len(report), len(options), d.getBinNodeCount(), d.getBinLinkCount() ] ss = max(allSections) root = QgsProject.instance().layerTreeRoot() idx = root.insertGroup(0, inpname[:len(inpname) - 4]) xy = d.getBinNodeCoordinates() ndCoordsID = xy[0] x = xy[1] y = xy[2] vertx = xy[3] verty = xy[4] vertxyFinal = [] for i in range(len(vertx)): vertxy = [] for u in range(len(vertx[i])): vertxy.append([float(vertx[i][u]), float(verty[i][u])]) vertxyFinal.append(vertxy) otherDemads = d.getBinNodeBaseDemandsDemSection() ndID = d.getBinNodeNameID() ndBaseD = d.getBinNodeBaseDemands() ndPatID = d.getBinNodeDemandPatternID() otherDemadsIndex = [] otherDemadsPatterns = [] for i, p in enumerate(otherDemads[1]): otherDemadsIndex.append(ndID.index(p)) otherDemadsPatterns.append(otherDemads[2][i]) counter = collections.Counter(otherDemadsIndex) maxCategories = 1 if counter: maxCategories = max(counter.values()) if not ndBaseD: ndBaseD = otherDemads[0] # Get data of Junctions if d.getBinNodeJunctionCount() > 0: ndBaseTmp = np.empty(( len(ndBaseD), maxCategories, )) ndPatTmp = [] for t in range(0, maxCategories): for u in range(0, len(ndBaseD)): ndBaseTmp[u][t] = 0 ndPatTmp.append([''] * maxCategories) for uu in range(0, len(ndBaseD)): if d.getBinNodeBaseDemands(): ndBaseTmp[uu][0] = ndBaseD[uu] ndPatTmp[uu][0] = ndPatID[uu] dem_cat_tot = list(counter.values()) l = 0 for i, p in enumerate(dem_cat_tot): for t in range(p): demInd = otherDemadsIndex[l] if t == 0: ndBaseTmp[demInd][t] = ndBaseD[demInd] ndPatTmp[demInd][t] = ndPatID[demInd] if p > 1: ndBaseTmp[demInd][t] = otherDemads[0][l] ndPatTmp[demInd][t] = otherDemads[2][l] l = l + 1 #if i > 0: # if otherDemadsIndex[i - 1] == p: # ndBaseTmp[p][t] = otherDemads[0][i] # ndPatTmp[p][t] = otherDemads[2][i] # t = t - 1 # Write Junction Shapefile fields = ["ID", "Elevation"] # , "pattern", "demand"] fieldsCode = [0, 1] for u in range(0, maxCategories): fields.append('Demand' + str(u + 1)) fields.append('Pattern' + str(u + 1)) fieldsCode.append(1) fieldsCode.append(0) fields.append('Desc') fieldsCode.append(0) posJunction = QgsVectorLayer("point?crs=" + epsg_crs, "Junctions", "memory") prJunction = posJunction.dataProvider() ndBaseTmp = ndBaseTmp.tolist() createColumnsAttrb(prJunction, fields, fieldsCode) posJunction.startEditing() ndEle = d.getBinNodeJunctionElevations() ndDes = d.getBinNodeJunctionDescription() # Get data of Pipes # Write shapefile pipe if nlinkCount > 0: posPipe = QgsVectorLayer("LineString?crs=" + epsg_crs, "Pipes", "memory") prPipe = posPipe.dataProvider() fields = [ "ID", "NodeFrom", "NodeTo", "Status", "Length", "Diameter", "Roughness", "MinorLoss", "Desc" ] fieldsCode = [0, 0, 0, 0, 1, 1, 1, 1, 0] createColumnsAttrb(prPipe, fields, fieldsCode) posPipe.startEditing() pIndex = d.getBinLinkPumpIndex() vIndex = d.getBinLinkValveIndex() ndlConn = d.getBinNodesConnectingLinksID() stat = d.getBinLinkInitialStatus() ch = 0 linkID = d.getBinLinkNameID() linkLengths = d.getBinLinkLength() linkDiameters = d.getBinLinkDiameter() linkRough = d.getBinLinkRoughnessCoeff() linkMinorloss = d.getBinLinkMinorLossCoeff() linkDescription = d.getBinLinkPipeDescription() # Write Tank Shapefile and get tank data posTank = QgsVectorLayer("point?crs=" + epsg_crs, "Tanks", "memory") prTank = posTank.dataProvider() fields = [ "ID", "Elevation", "InitLevel", "MinLevel", "MaxLevel", "Diameter", "MinVolume", "VolumeCurve", "Desc" ] fieldsCode = [0, 1, 1, 1, 1, 1, 1, 0, 0] createColumnsAttrb(prTank, fields, fieldsCode) posTank.startEditing() if d.getBinNodeTankCount() > 0: ndTankelevation = d.getBinNodeTankElevations() initiallev = d.getBinNodeTankInitialLevel() minimumlev = d.getBinNodeTankMinimumWaterLevel() maximumlev = d.getBinNodeTankMaximumWaterLevel() diameter = d.getBinNodeTankDiameter() minimumvol = d.getBinNodeTankMinimumWaterVolume() volumecurv = d.getBinNodeTankVolumeCurveID() ndTankID = d.getBinNodeTankNameID() ndTankDescription = d.getBinNodeTankDescription() # Write Reservoir Shapefile posReservoirs = QgsVectorLayer("point?crs=" + epsg_crs, "Reservoirs", "memory") prReservoirs = posReservoirs.dataProvider() fields = ["ID", "Head", "Desc"] fieldsCode = [0, 1, 0] createColumnsAttrb(prReservoirs, fields, fieldsCode) head = d.getBinNodeReservoirElevations() ndReservoirDescription = d.getBinNodeReservoirDescription() posReservoirs.startEditing() if times: posTimes = QgsVectorLayer("point?crs=" + epsg_crs, "Times", "memory") prTimes = posTimes.dataProvider() if energy: posE = QgsVectorLayer("point?crs=" + epsg_crs, "Energy", "memory") prE = posE.dataProvider() if report: posRep = QgsVectorLayer("point?crs=" + epsg_crs, "Report", "memory") prRep = posRep.dataProvider() if options: posOpt = QgsVectorLayer("point?crs=" + epsg_crs, "Options", "memory") prOpt = posOpt.dataProvider() if optReactions: posO = QgsVectorLayer("point?crs=" + epsg_crs, "Reactions", "memory") prO = posO.dataProvider() ppE = [] ppO = [] ppTimes = [] ppRep = [] ppOpt = [] ppMix = [] ppReactions = [] ppSourc = [] ppRul = [] ppPat = [] ppQual = [] ppDem = [] ppStat = [] ppEmit = [] ppCont = [] ppCurv = [] for i in range(ss): if i < d.getBinNodeJunctionCount(): try: ndIndexNew = ndCoordsID.index(ndID[i]) featJ = QgsFeature() point = QgsPointXY(float(x[ndIndexNew]), float(y[ndIndexNew])) featJ.initAttributes(3 + len(ndBaseTmp[0]) * 2) featJ.setGeometry(QgsGeometry.fromPointXY(point)) featJ.setAttribute(0, ndID[i]) featJ.setAttribute(1, ndEle[i]) w = 2 for j in range(0, len(ndBaseTmp[0])): featJ.setAttribute(w, ndBaseTmp[i][j]) featJ.setAttribute(w + 1, ndPatTmp[i][j]) w = w + 2 featJ.setAttribute(w, ndDes[i]) prJunction.addFeatures([featJ]) except: pass if i < nlinkCount: if len(stat) == i: ch = 1 if ch == 1: stat.append('OPEN') try: x1 = x[ndCoordsID.index(d.getBinLinkFromNode()[i])] y1 = y[ndCoordsID.index(d.getBinLinkFromNode()[i])] x2 = x[ndCoordsID.index(d.getBinLinkToNode()[i])] y2 = y[ndCoordsID.index(d.getBinLinkToNode()[i])] if i in pIndex: pass elif i in vIndex: pass else: point1 = QgsPointXY(float(x1), float(y1)) point2 = QgsPointXY(float(x2), float(y2)) featPipe = QgsFeature() if vertx[i]: parts = [] parts.append(point1) for mm in range(len(vertxyFinal[i])): a = vertxyFinal[i][mm] parts.append(QgsPointXY(a[0], a[1])) parts.append(point2) featPipe.setGeometry( (QgsGeometry.fromPolylineXY(parts))) else: featPipe.setGeometry( QgsGeometry.fromPolylineXY([point1, point2])) featPipe.setAttributes([ linkID[i], ndlConn[0][i], ndlConn[1][i], stat[i], linkLengths[i], linkDiameters[i], linkRough[i], linkMinorloss[i], linkDescription[i] ]) prPipe.addFeatures([featPipe]) except: pass if i < d.getBinNodeTankCount(): p = d.getBinNodeTankIndex()[i] - 1 try: ndIndexNew = ndCoordsID.index(ndID[p]) except: continue featTank = QgsFeature() point = QgsPointXY(float(x[ndIndexNew]), float(y[ndIndexNew])) featTank.setGeometry(QgsGeometry.fromPointXY(point)) featTank.setAttributes([ ndTankID[i], ndTankelevation[i], initiallev[i], minimumlev[i], maximumlev[i], diameter[i], minimumvol[i], volumecurv[i], ndTankDescription[i] ]) prTank.addFeatures([featTank]) if i < d.getBinNodeReservoirCount(): p = d.getBinNodeReservoirIndex()[i] - 1 try: ndIndexNew = ndCoordsID.index(ndID[p]) except: continue feature = QgsFeature() point = QgsPointXY(float(x[ndIndexNew]), float(y[ndIndexNew])) feature.setGeometry(QgsGeometry.fromPointXY(point)) feature.setAttributes( [ndID[p], head[i], ndReservoirDescription[i]]) prReservoirs.addFeatures([feature]) if i < allSections[12]: if len(mixing[i]) == 3: ppMix.append([mixing[i][0], mixing[i][1], mixing[i][2]]) else: ppMix.append([mixing[i][0], mixing[i][1]]) if i < allSections[11]: ppReactions.append( [reactions[i][0], reactions[i][1], reactions[i][2]]) if i < allSections[10]: if len(sources[i]) == 4: ppSourc.append([ sources[i][0], sources[i][1], sources[i][2], sources[i][3] ]) elif len(sources[i]) == 3: ppSourc.append([sources[i][0], sources[i][1], sources[i][2]]) else: ppSourc.append([sources[i][0], sources[i][1]]) if i < allSections[9]: if len(rules[i]) > 2: ppRul.append([ rules[i][0][1][1], rules[i][1][0] + rules[i][2][0] + rules[i][3][0] ]) if i < allSections[8]: ppQual.append([quality[i][0], quality[i][1]]) if i < allSections[7]: ppCurv.append([ str(curves[0][i][0]), str(curves[0][i][1]), str(curves[0][i][2]), str(curves[1][i]) ]) if i < allSections[6]: ppPat.append([patterns[i][0], str(patterns[i][1])]) if i < allSections[5]: ppCont.append([controls[i]]) if i < allSections[4]: ppEmit.append([emitters[i][0], emitters[i][1]]) if i < allSections[3]: ppStat.append([status[i][0], status[i][1]]) if i < allSections[2]: if len(demands[i]) > 2: ppDem.append([demands[i][0], demands[i][1], demands[i][2]]) if i < allSections[0]: mm = energy[i][0] if mm.upper() == "GLOBAL": prE.addAttributes( [QgsField("Global" + energy[i][1], QVariant.String)]) if len(energy[i]) > 2: ppE.append(energy[i][2]) else: ppE.append('') if mm.upper() == "PUMP": prE.addAttributes([QgsField("Pump", QVariant.String)]) if len(energy[i]) > 2: ppE.append(energy[i][1] + ' ' + energy[i][2]) else: ppE.append(energy[i][1]) elif mm.upper() == "DEMAND": if energy[i][1].upper() == "CHARGE": prE.addAttributes([QgsField("DemCharge", QVariant.String)]) if len(energy[i]) > 2: ppE.append(energy[i][2]) if i < allSections[1]: mm = optReactions[i][0] if mm.upper() == "ORDER": prO.addAttributes( [QgsField("Order" + optReactions[i][1], QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][2]) else: ppO.append('') elif mm.upper() == "GLOBAL": prO.addAttributes( [QgsField("Global" + optReactions[i][1], QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][2]) else: ppO.append('') elif mm.upper() == "BULK": prO.addAttributes([QgsField("Bulk", QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][1] + ' ' + optReactions[i][2]) else: ppO.append(optReactions[i][1]) elif mm.upper() == "WALL": prO.addAttributes([QgsField("Wall", QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][1] + ' ' + optReactions[i][2]) else: ppO.append(optReactions[i][1]) elif mm.upper() == "TANK": prO.addAttributes([QgsField("Tank", QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][1] + ' ' + optReactions[i][2]) else: ppO.append(optReactions[i][1]) elif mm.upper() == "LIMITING": if optReactions[i][1].upper() == "POTENTIAL": prO.addAttributes([QgsField("LimPotent", QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][2]) elif mm.upper() == "ROUGHNESS": if optReactions[i][1].upper() == "CORRELATION": prO.addAttributes([QgsField("RoughCorr", QVariant.String)]) if len(optReactions[i]) > 2: ppO.append(optReactions[i][2]) if i < allSections[13]: mm = times[i][0] if mm.upper() == "DURATION": prTimes.addAttributes([QgsField("Duration", QVariant.String)]) ppTimes.append(times[i][1]) if mm.upper() == "HYDRAULIC": prTimes.addAttributes([QgsField("HydStep", QVariant.String)]) ppTimes.append(times[i][2]) elif mm.upper() == "QUALITY": prTimes.addAttributes([QgsField("QualStep", QVariant.String)]) ppTimes.append(times[i][2]) elif mm.upper() == "RULE": prTimes.addAttributes([QgsField("RuleStep", QVariant.String)]) ppTimes.append(times[i][2]) elif mm.upper() == "PATTERN": if times[i][1].upper() == "TIMESTEP": prTimes.addAttributes( [QgsField("PatStep", QVariant.String)]) ppTimes.append(times[i][2]) if times[i][1].upper() == "START": prTimes.addAttributes( [QgsField("PatStart", QVariant.String)]) ppTimes.append(times[i][2]) elif mm.upper() == "REPORT": if times[i][1].upper() == "TIMESTEP": prTimes.addAttributes( [QgsField("RepStep", QVariant.String)]) ppTimes.append(times[i][2]) if times[i][1].upper() == "START": prTimes.addAttributes( [QgsField("RepStart", QVariant.String)]) ppTimes.append(times[i][2]) elif mm.upper() == "START": if times[i][1].upper() == "CLOCKTIME": prTimes.addAttributes( [QgsField("StartClock", QVariant.String)]) if len(times[i]) > 3: ppTimes.append(times[i][2] + ' ' + times[i][3]) else: ppTimes.append(times[i][2]) elif mm.upper() == "STATISTIC": prTimes.addAttributes([QgsField("Statistic", QVariant.String)]) if times[i][1].upper() == 'NONE' or times[i][1].upper() == 'AVERAGE' or times[i][1].upper() \ == 'MINIMUM' or times[i][1].upper() == 'MAXIMUM' or times[i][1].upper() == 'RANGE': ppTimes.append(times[i][1]) if i < allSections[14]: mm = report[i][0] if mm.upper() == "PAGESIZE": prRep.addAttributes([QgsField("PageSize", QVariant.String)]) ppRep.append(report[i][1]) if mm.upper() == "FILE": prRep.addAttributes([QgsField("FileName", QVariant.String)]) ppRep.append(report[i][1]) elif mm.upper() == "STATUS": prRep.addAttributes([QgsField("Status", QVariant.String)]) ppRep.append(report[i][1]) elif mm.upper() == "SUMMARY": prRep.addAttributes([QgsField("Summary", QVariant.String)]) ppRep.append(report[i][1]) elif mm.upper() == "ENERGY": prRep.addAttributes([QgsField("Energy", QVariant.String)]) ppRep.append(report[i][1]) elif mm.upper() == "NODES": prRep.addAttributes([QgsField("Nodes", QVariant.String)]) if len(report[i]) > 2: ppRep.append(report[i][1] + ' ' + report[i][2]) else: ppRep.append(report[i][1]) elif mm.upper() == "LINKS": prRep.addAttributes([QgsField("Links", QVariant.String)]) if len(report[i]) > 2: ppRep.append(report[i][1] + ' ' + report[i][2]) else: ppRep.append(report[i][1]) else: prRep.addAttributes([QgsField(mm, QVariant.String)]) if len(report[i]) > 2: ppRep.append(report[i][1] + ' ' + report[i][2]) else: ppRep.append(report[i][1]) if i < allSections[15]: mm = options[i][0] if mm.upper() == "UNITS": prOpt.addAttributes([QgsField("Units", QVariant.String)]) ppOpt.append(options[i][1]) if mm.upper() == "HYDRAULICS": prOpt.addAttributes([QgsField("Hydraulics", QVariant.String)]) if len(options[i]) > 2: ppOpt.append(options[i][1] + ' ' + options[i][2]) else: ppOpt.append(options[i][1]) elif mm.upper() == "QUALITY": prOpt.addAttributes([QgsField("Quality", QVariant.String)]) if len(options[i]) > 2: ppOpt.append(options[i][1] + ' ' + options[i][2]) elif len(options[i]) > 3: ppOpt.append(options[i][1] + ' ' + options[i][2] + ' ' + options[i][3]) else: ppOpt.append(options[i][1]) elif mm.upper() == "VISCOSITY": prOpt.addAttributes([QgsField("Viscosity", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "DIFFUSIVITY": prOpt.addAttributes([QgsField("Diffusivity", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "SPECIFIC": if options[i][1].upper() == "GRAVITY": prOpt.addAttributes( [QgsField("SpecGrav", QVariant.String)]) ppOpt.append(options[i][2]) elif mm.upper() == "TRIALS": prOpt.addAttributes([QgsField("Trials", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "HEADLOSS": prOpt.addAttributes([QgsField("Headloss", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "ACCURACY": prOpt.addAttributes([QgsField("Accuracy", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "UNBALANCED": prOpt.addAttributes([QgsField("Unbalanced", QVariant.String)]) if len(options[i]) > 2: ppOpt.append(options[i][1] + ' ' + options[i][2]) else: ppOpt.append(options[i][1]) elif mm.upper() == "PATTERN": prOpt.addAttributes([QgsField("PatID", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "TOLERANCE": prOpt.addAttributes([QgsField("Tolerance", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "MAP": prOpt.addAttributes([QgsField("Map", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "DEMAND": if options[i][1].upper() == "MULTIPLIER": prOpt.addAttributes([QgsField("DemMult", QVariant.String)]) ppOpt.append(options[i][2]) elif mm.upper() == "EMITTER": if options[i][1].upper() == "EXPONENT": prOpt.addAttributes([QgsField("EmitExp", QVariant.String)]) ppOpt.append(options[i][2]) elif mm.upper() == "CHECKFREQ": prOpt.addAttributes([QgsField("CheckFreq", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "MAXCHECK": prOpt.addAttributes([QgsField("MaxCheck", QVariant.String)]) ppOpt.append(options[i][1]) elif mm.upper() == "DAMPLIMIT": prOpt.addAttributes([QgsField("DampLimit", QVariant.String)]) ppOpt.append(options[i][1]) try: writeDBF(posOpt, [ppOpt], prOpt, saveFile, inpname, "_OPTIONS", idx) writeDBF(posRep, [ppRep], prRep, saveFile, inpname, "_REPORT", idx) #if times: writeDBF(posTimes, [ppTimes], prTimes, saveFile, inpname, "_TIMES", idx) #if energy: writeDBF(posE, [ppE], prE, saveFile, inpname, "_ENERGY", idx) #if optReactions: writeDBF(posO, [ppO], prO, saveFile, inpname, "_REACTIONS", idx) posMix = QgsVectorLayer("point?crs=" + epsg_crs, "Mixing", "memory") prMix = posMix.dataProvider() fields = ["Tank_ID", "Model", "Fraction"] fieldsCode = [0, 0, 1] # 0 String, 1 Double createColumnsAttrb(prMix, fields, fieldsCode) writeDBF(posMix, ppMix, prMix, saveFile, inpname, "_MIXING", idx) posReact = QgsVectorLayer("point?crs=" + epsg_crs, "ReactionsI", "memory") prReact = posReact.dataProvider() fields = ["Type", "Pipe/Tank", "Coeff."] fieldsCode = [0, 0, 1] createColumnsAttrb(prReact, fields, fieldsCode) writeDBF(posReact, ppReactions, prReact, saveFile, inpname, "_REACTIONS_I", idx) posSourc = QgsVectorLayer("point?crs=" + epsg_crs, "Sources", "memory") prSourc = posSourc.dataProvider() fields = ["Node_ID", "Type", "Strength", "Pattern"] fieldsCode = [0, 0, 1, 0] createColumnsAttrb(prSourc, fields, fieldsCode) writeDBF(posSourc, ppSourc, prSourc, saveFile, inpname, "_SOURCES", idx) posRul = QgsVectorLayer("point?crs=" + epsg_crs, "Rules", "memory") prRul = posRul.dataProvider() fields = ["Rule_ID", "Rule"] fieldsCode = [0, 0] createColumnsAttrb(prRul, fields, fieldsCode) writeDBF(posRul, ppRul, prRul, saveFile, inpname, "_RULES", idx) posQual = QgsVectorLayer("point?crs=" + epsg_crs, "Sources", "memory") prQual = posQual.dataProvider() fields = ["Node_ID", "Init_Qual"] fieldsCode = [0, 1] createColumnsAttrb(prQual, fields, fieldsCode) writeDBF(posQual, ppQual, prQual, saveFile, inpname, "_QUALITY", idx) posStat = QgsVectorLayer("point?crs=" + epsg_crs, "Status", "memory") prStat = posStat.dataProvider() fields = ["Link_ID", "Status/Setting"] fieldsCode = [0, 0] createColumnsAttrb(prStat, fields, fieldsCode) writeDBF(posStat, ppStat, prStat, saveFile, inpname, "_STATUS", idx) posEmit = QgsVectorLayer("point?crs=" + epsg_crs, "Emitters", "memory") prEmit = posEmit.dataProvider() fields = ["Junc_ID", "Coeff."] fieldsCode = [0, 1] createColumnsAttrb(prEmit, fields, fieldsCode) writeDBF(posEmit, ppEmit, prEmit, saveFile, inpname, "_EMITTERS", idx) posCont = QgsVectorLayer("point?crs=" + epsg_crs, "Controls", "memory") prCont = posCont.dataProvider() fields = ["Controls"] fieldsCode = [0] createColumnsAttrb(prCont, fields, fieldsCode) writeDBF(posCont, ppCont, prCont, saveFile, inpname, "_CONTROLS", idx) posPat = QgsVectorLayer("point?crs=" + epsg_crs, "Patterns", "memory") prPat = posPat.dataProvider() fields = ["Pattern_ID", "Multipliers"] fieldsCode = [0, 0] createColumnsAttrb(prPat, fields, fieldsCode) writeDBF(posPat, ppPat, prPat, saveFile, inpname, "_PATTERNS", idx) posCurv = QgsVectorLayer("point?crs=" + epsg_crs, "Curves", "memory") prCurv = posCurv.dataProvider() fields = ["Curve_ID", "X-Value", "Y-Value", "Type"] fieldsCode = [0, 0, 0, 0] createColumnsAttrb(prCurv, fields, fieldsCode) writeDBF(posCurv, ppCurv, prCurv, saveFile, inpname, "_CURVES", idx) except: pass # Write Valve Shapefile posValve = QgsVectorLayer("LineString?crs=" + epsg_crs, "Valve", "memory") prValve = posValve.dataProvider() fields = [ "ID", "NodeFrom", "NodeTo", "Diameter", "Type", "Setting", "MinorLoss", "Desc" ] fieldsCode = [0, 0, 0, 1, 0, 1, 1, 0] createColumnsAttrb(prValve, fields, fieldsCode) posValve.startEditing() if d.getBinLinkValveCount() > 0: linkID = d.getBinLinkValveNameID() linkType = d.getBinLinkValveType() # valve type linkDiameter = d.getBinLinkValveDiameters() linkInitSett = d.getBinLinkValveSetting() # BinLinkValveSetting linkMinorloss = d.getBinLinkValveMinorLoss() linkDescription = d.getBinLinkValveDescription() for i, p in enumerate(d.getBinLinkValveIndex()): try: point1 = QgsPointXY( float(x[ndCoordsID.index(d.getBinLinkFromNode()[p])]), float(y[ndCoordsID.index(d.getBinLinkFromNode()[p])])) point2 = QgsPointXY( float(x[ndCoordsID.index(d.getBinLinkToNode()[p])]), float(y[ndCoordsID.index(d.getBinLinkToNode()[p])])) except: continue feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPolylineXY([point1, point2])) feature.setAttributes([ linkID[i], ndlConn[0][p], ndlConn[1][p], linkDiameter[i], linkType[i], linkInitSett[i], linkMinorloss[i], linkDescription[i] ]) prValve.addFeatures([feature]) QgsVectorFileWriter.writeAsVectorFormat( posValve, saveFile + "_valves" + '.shp', "System", QgsCoordinateReferenceSystem(posValve.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_valves" + '.shp', inpname[:len(inpname) - 4] + "_valves", "ogr") QgsProject.instance().addMapLayer(ll, False) nvalves = QgsLayerTreeLayer(ll) idx.insertChildNode(0, nvalves) nvalves.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'valvesline' + ".qml") ll.triggerRepaint() # Write Pump Shapefile posPump = QgsVectorLayer("LineString?crs=" + epsg_crs, "Pump", "memory") prPump = posPump.dataProvider() fields = ["ID", "NodeFrom", "NodeTo", "Power", "Pattern", "Curve", "Desc"] fieldsCode = [0, 0, 0, 0, 0, 0, 0] createColumnsAttrb(prPump, fields, fieldsCode) posPump.startEditing() if d.getBinLinkPumpCount() > 0: curveXY = d.getBinCurvesXY() curvesID = d.getBinCurvesNameID() a = curvesID b = [] for l in a: if l not in b: b.append(l) curvesIDunique = b CurvesTmpIndices = [] for p in range(0, len(curvesIDunique)): CurvesTmpIndices.append(curvesID.count(curvesIDunique[p])) curveIndices = [] Curve = d.getBinCurvesNameID() for i in range(len(Curve)): curveIndices.append(curvesIDunique.index(Curve[i])) if d.getBinCurveCount(): #CurvesTmpIndicesFinal = [CurvesTmpIndices[index] for index in curveIndices] CurvesTmp = [''] * len(curvesIDunique) i = 0 for u in range(d.getBinCurveCount()): if u < d.getBinLinkPumpCount(): fields.append('Head' + str(u + 1)) fields.append('Flow' + str(u + 1)) fieldsCode.append(1) fieldsCode.append(1) tmp1 = [] for p in range(CurvesTmpIndices[u]): tmp1.append([curveXY[i][0], curveXY[i][1]]) i = i + 1 CurvesTmp[u] = tmp1 createColumnsAttrb(prPump, fields, fieldsCode) chPowerPump = d.getBinLinkPumpPower() pumpID = d.getBinLinkPumpNameID() patternsIDs = d.getBinLinkPumpPatterns() ppatt = d.getBinLinkPumpPatternsPumpID() linkID = d.getBinLinkNameID() pumpdescription = d.getBinLinkPumpDescription() for i, p in enumerate(d.getBinLinkPumpIndex()): Curve = [] power = [] pattern = [] pumpNameIDPower = d.getBinLinkPumpNameIDPower() if len(pumpNameIDPower) > 0: for uu in range(0, len(pumpNameIDPower)): if pumpNameIDPower[uu] == pumpID[i]: power = chPowerPump[uu] if len(patternsIDs) > 0: for uu in range(0, len(ppatt)): if ppatt[uu] == pumpID[i]: pattern = patternsIDs[uu] try: point1 = QgsPointXY( float(x[ndCoordsID.index(d.getBinLinkFromNode()[p])]), float(y[ndCoordsID.index(d.getBinLinkFromNode()[p])])) point2 = QgsPointXY( float(x[ndCoordsID.index(d.getBinLinkToNode()[p])]), float(y[ndCoordsID.index(d.getBinLinkToNode()[p])])) except: continue feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPolylineXY([point1, point2])) if not Curve: Curve = 'NULL' if not power: power = 'NULL' if not pattern: pattern = 'NULL' if d.getBinCurveCount() > 0: try: Curve = d.getBinLinkPumpCurveNameID()[i] curveIndex = curvesIDunique.index(Curve) except: Curve = '' feature.initAttributes(7 + sum(CurvesTmpIndices) * 2 + 1) feature.setAttribute(0, linkID[p]) feature.setAttribute(1, ndlConn[0][p]) feature.setAttribute(2, ndlConn[1][p]) feature.setAttribute(3, power) feature.setAttribute(4, pattern) feature.setAttribute(5, Curve) feature.setAttribute(6, pumpdescription[i]) if 'curveIndex' in locals(): if d.getBinCurveCount() == 1: w = 7 for p in range(CurvesTmpIndices[curveIndex]): feature.setAttribute(w, CurvesTmp[curveIndex][p][0]) feature.setAttribute(w + 1, CurvesTmp[curveIndex][p][1]) w = w + 2 for j in range(d.getBinCurveCount() - 1): w = 7 for p in range(CurvesTmpIndices[curveIndex]): feature.setAttribute(w, CurvesTmp[curveIndex][p][0]) feature.setAttribute(w + 1, CurvesTmp[curveIndex][p][1]) w = w + 2 prPump.addFeatures([feature]) QgsVectorFileWriter.writeAsVectorFormat( posPump, saveFile + "_pumps" + '.shp', "System", QgsCoordinateReferenceSystem(posPump.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_pumps" + '.shp', inpname[:len(inpname) - 4] + "_pumps", "ogr") QgsProject.instance().addMapLayer(ll, False) npump = QgsLayerTreeLayer(ll) idx.insertChildNode(0, npump) npump.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'pumpsline' + ".qml") ll.triggerRepaint() QgsVectorFileWriter.writeAsVectorFormat( posPipe, saveFile + "_pipes" + '.shp', "System", QgsCoordinateReferenceSystem(posPipe.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_pipes" + '.shp', inpname[:len(inpname) - 4] + "_pipes", "ogr") QgsProject.instance().addMapLayer(ll, False) npipe = QgsLayerTreeLayer(ll) idx.insertChildNode(0, npipe) npipe.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'pipes' + ".qml") ll.triggerRepaint() iface.mapCanvas().setExtent(ll.extent()) QgsVectorFileWriter.writeAsVectorFormat( posJunction, saveFile + "_junctions" + '.shp', "System", QgsCoordinateReferenceSystem(posJunction.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_junctions" + '.shp', inpname[:len(inpname) - 4] + "_junctions", "ogr") QgsProject.instance().addMapLayer(ll, False) njunc = QgsLayerTreeLayer(ll) idx.insertChildNode(0, njunc) njunc.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'junctions' + ".qml") ll.triggerRepaint() QgsVectorFileWriter.writeAsVectorFormat( posTank, saveFile + "_tanks" + '.shp', "System", QgsCoordinateReferenceSystem(posTank.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_tanks" + '.shp', inpname[:len(inpname) - 4] + "_tanks", "ogr") QgsProject.instance().addMapLayer(ll, False) ntanks = QgsLayerTreeLayer(ll) idx.insertChildNode(0, ntanks) ntanks.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'tanks' + ".qml") ll.triggerRepaint() QgsVectorFileWriter.writeAsVectorFormat( posReservoirs, saveFile + "_reservoirs" + '.shp', "System", QgsCoordinateReferenceSystem(posReservoirs.crs().authid()), "ESRI Shapefile") ll = QgsVectorLayer(saveFile + "_reservoirs" + '.shp', inpname[:len(inpname) - 4] + "_reservoirs", "ogr") QgsProject.instance().addMapLayer(ll, False) nres = QgsLayerTreeLayer(ll) idx.insertChildNode(0, nres) nres.setCustomProperty("showFeatureCount", True) ll.loadNamedStyle(plugin_path + "/qmls/" + 'reservoirs' + ".qml") ll.triggerRepaint()
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) useField = self.getParameterValue(self.METHOD) == 1 fieldName = self.getParameterValue(self.FIELD) f = QgsField('value', QVariant.String, '', 255) if useField: index = layer.fieldNameIndex(fieldName) fType = layer.pendingFields()[index].type() if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]: f.setType(fType) f.setLength(20) elif fType == QVariant.Double: f.setType(QVariant.Double) f.setLength(20) f.setPrecision(6) else: f.setType(QVariant.String) f.setLength(255) fields = [QgsField('id', QVariant.Int, '', 20), f, QgsField('area', QVariant.Double, '', 20, 6), QgsField('perim', QVariant.Double, '', 20, 6) ] writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QGis.WKBPolygon, layer.dataProvider().crs()) outFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() fid = 0 val = None features = vector.features(layer) if useField: unique = layer.uniqueValues(index) current = 0 total = 100.0 / (len(features) * len(unique)) for i in unique: first = True hull = [] features = vector.features(layer) for f in features: idVar = f[fieldName] if unicode(idVar).strip() == unicode(i).strip(): if first: val = idVar first = False inGeom = QgsGeometry(f.geometry()) points = vector.extractPoints(inGeom) hull.extend(points) current += 1 progress.setPercentage(int(current * total)) if len(hull) >= 3: tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull)) try: outGeom = tmpGeom.convexHull() (area, perim) = vector.simpleMeasure(outGeom) outFeat.setGeometry(outGeom) outFeat.setAttributes([fid, val, area, perim]) writer.addFeature(outFeat) except: raise GeoAlgorithmExecutionException( self.tr('Exception while computing convex hull')) fid += 1 else: hull = [] total = 100.0 / layer.featureCount() features = vector.features(layer) for current, f in enumerate(features): inGeom = QgsGeometry(f.geometry()) points = vector.extractPoints(inGeom) hull.extend(points) progress.setPercentage(int(current * total)) tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull)) try: outGeom = tmpGeom.convexHull() (area, perim) = vector.simpleMeasure(outGeom) outFeat.setGeometry(outGeom) outFeat.setAttributes([0, 'all', area, perim]) writer.addFeature(outFeat) except: raise GeoAlgorithmExecutionException( self.tr('Exception while computing convex hull')) del writer
def outputFields(self, inputFields): self.field_idx = inputFields.lookupField(self.field_name) if self.field_idx >= 0: inputFields[self.field_idx] = QgsField(self.field_name, QVariant.Double, '', 24, 15) return inputFields
def processAlgorithm(self, parameters, context, feedback): spacing = self.parameterAsDouble(parameters, self.SPACING, context) inset = self.parameterAsDouble(parameters, self.INSET, context) randomize = self.parameterAsBool(parameters, self.RANDOMIZE, context) isSpacing = self.parameterAsBool(parameters, self.IS_SPACING, context) crs = self.parameterAsCrs(parameters, self.CRS, context) extent = self.parameterAsExtent(parameters, self.EXTENT, context, crs) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, crs) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) if randomize: seed() area = extent.width() * extent.height() if isSpacing: pSpacing = spacing else: pSpacing = sqrt(area / spacing) f = QgsFeature() f.initAttributes(1) f.setFields(fields) count = 0 id = 0 total = 100.0 / (area / pSpacing) y = extent.yMaximum() - inset extent_geom = QgsGeometry.fromRect(extent) extent_engine = QgsGeometry.createGeometryEngine( extent_geom.constGet()) extent_engine.prepareGeometry() while y >= extent.yMinimum(): x = extent.xMinimum() + inset while x <= extent.xMaximum(): if feedback.isCanceled(): break if randomize: geom = QgsGeometry( QgsPoint( uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)), uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0)))) else: geom = QgsGeometry(QgsPoint(x, y)) if extent_engine.intersects(geom.constGet()): f.setAttributes([id]) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) x += pSpacing id += 1 count += 1 feedback.setProgress(int(count * total)) y = y - pSpacing return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, [startPoint], feedback) feedback.pushInfo(self.tr('Calculating service area...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = [] for i, v in enumerate(cost): if v > travelCost and tree[i] != -1: vertexId = graph.edge(tree[i]).fromVertex() if cost[vertexId] <= travelCost: vertices.append(i) upperBoundary = [] lowerBoundary = [] for i in vertices: upperBoundary.append( graph.vertex(graph.edge(tree[i]).toVertex()).point()) lowerBoundary.append( graph.vertex(graph.edge(tree[i]).fromVertex()).point()) feedback.pushInfo(self.tr('Writing results...')) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.MultiPoint, network.sourceCrs()) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = startPoint.toString() sink.addFeature(feat, QgsFeatureSink.FastInsert) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = startPoint.toString() sink.addFeature(feat, QgsFeatureSink.FastInsert) upperBoundary.append(startPoint) lowerBoundary.append(startPoint) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoints = self.parameterAsSource(parameters, self.START_POINTS, context) endPoint = self.parameterAsPoint(parameters, self.END_POINT, context) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) feat = QgsFeature() feat.setFields(fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(context.project().crs(), True, tolerance) feedback.pushInfo(self.tr('Loading start points...')) request = QgsFeatureRequest() request.setFlags(request.flags() ^ QgsFeatureRequest.SubsetOfAttributes) request.setDestinationCrs(network.sourceCrs()) features = startPoints.getFeatures(request) total = 100.0 / startPoints.featureCount() if startPoints.featureCount( ) else 0 points = [endPoint] for current, f in enumerate(features): if feedback.isCanceled(): break points.append(f.geometry().asPoint()) feedback.setProgress(int(current * total)) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo(self.tr('Calculating shortest paths...')) graph = builder.graph() idxEnd = graph.findVertex(snappedPoints[0]) route = [] nPoints = len(snappedPoints) total = 100.0 / nPoints if nPoints else 1 for i in range(1, count + 1): if feedback.isCanceled(): break idxStart = graph.findVertex(snappedPoints[i]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: msg = self.tr( 'There is no route from start point ({}) to end point ({}).' .format(points[i].toString(), endPoint.toString())) feedback.setProgressText(msg) QgsMessageLog.logMessage(msg, self.tr('Processing'), QgsMessageLog.WARNING) continue cost = 0.0 current = idxEnd while current != idxStart: cost += graph.edge(tree[current]).cost(0) route.append( graph.vertex(graph.edge(tree[current]).inVertex()).point()) current = graph.edge(tree[current]).outVertex() route.append(snappedPoints[i]) route.reverse() geom = QgsGeometry.fromPolyline(route) feat.setGeometry(geom) feat['start'] = points[i].toString() feat['end'] = endPoint.toString() feat['cost'] = cost / multiplier sink.addFeature(feat, QgsFeatureSink.FastInsert) route[:] = [] feedback.setProgress(int(i * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): if parameters[self.INPUT] == parameters[self.HUBS]: raise QgsProcessingException( self.tr('Same layer given for both hubs and spokes')) point_source = self.parameterAsSource(parameters, self.INPUT, context) if point_source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) hub_source = self.parameterAsSource(parameters, self.HUBS, context) if hub_source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.HUBS)) fieldName = self.parameterAsString(parameters, self.FIELD, context) units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT, context)] fields = point_source.fields() fields.append(QgsField('HubName', QVariant.String)) fields.append(QgsField('HubDist', QVariant.Double)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, point_source.sourceCrs()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) index = QgsSpatialIndex(hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(point_source.sourceCrs(), context.transformContext()))) distance = QgsDistanceArea() distance.setSourceCrs(point_source.sourceCrs(), context.transformContext()) distance.setEllipsoid(context.ellipsoid()) # Scan source points, find nearest hub, and write to output file features = point_source.getFeatures() total = 100.0 / point_source.featureCount() if point_source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): sink.addFeature(f, QgsFeatureSink.FastInsert) continue src = f.geometry().boundingBox().center() neighbors = index.nearestNeighbor(src, 1) ft = next(hub_source.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], hub_source.fields()).setDestinationCrs(point_source.sourceCrs(), context.transformContext()))) closest = ft.geometry().boundingBox().center() hubDist = distance.measureLine(src, closest) if units != self.LAYER_UNITS: hub_dist_in_desired_units = distance.convertLengthMeasurement(hubDist, units) else: hub_dist_in_desired_units = hubDist attributes = f.attributes() attributes.append(ft[fieldName]) attributes.append(hub_dist_in_desired_units) feat = QgsFeature() feat.setAttributes(attributes) feat.setGeometry(QgsGeometry.fromPointXY(src)) sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) if network is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) startPoints = self.parameterAsSource(parameters, self.START_POINTS, context) if startPoints is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.START_POINTS)) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) include_bounds = True # default to true to maintain 3.0 API if self.INCLUDE_BOUNDS in parameters: include_bounds = self.parameterAsBool(parameters, self.INCLUDE_BOUNDS, context) fields = startPoints.fields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Loading start points…')) request = QgsFeatureRequest() request.setDestinationCrs(network.sourceCrs(), context.transformContext()) features = startPoints.getFeatures(request) total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0 points = [] source_attributes = {} i = 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue for p in f.geometry().vertices(): points.append(QgsPointXY(p)) source_attributes[i] = f.attributes() i += 1 feedback.setProgress(int(current * total)) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Building graph…')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Calculating service areas…')) graph = builder.graph() (point_sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.MultiPoint, network.sourceCrs()) (line_sink, line_dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LINES, context, fields, QgsWkbTypes.MultiLineString, network.sourceCrs()) total = 100.0 / len(snappedPoints) if snappedPoints else 1 for i, p in enumerate(snappedPoints): if feedback.isCanceled(): break idxStart = graph.findVertex(snappedPoints[i]) origPoint = points[i].toString() tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = set() area_points = [] lines = [] for vertex, start_vertex_cost in enumerate(cost): inbound_edge_index = tree[vertex] if inbound_edge_index == -1 and vertex != idxStart: # unreachable vertex continue if start_vertex_cost > travelCost: # vertex is too expensive, discard continue vertices.add(vertex) start_point = graph.vertex(vertex).point() # find all edges coming from this vertex for edge_id in graph.vertex(vertex).outgoingEdges(): edge = graph.edge(edge_id) end_vertex_cost = start_vertex_cost + edge.cost(0) end_point = graph.vertex(edge.toVertex()).point() if end_vertex_cost <= travelCost: # end vertex is cheap enough to include vertices.add(edge.toVertex()) lines.append([start_point, end_point]) else: # travelCost sits somewhere on this edge, interpolate position interpolated_end_point = QgsGeometryUtils.interpolatePointOnLineByValue(start_point.x(), start_point.y(), start_vertex_cost, end_point.x(), end_point.y(), end_vertex_cost, travelCost) area_points.append(interpolated_end_point) lines.append([start_point, interpolated_end_point]) for v in vertices: area_points.append(graph.vertex(v).point()) feat = QgsFeature() if point_sink is not None: geomPoints = QgsGeometry.fromMultiPointXY(area_points) feat.setGeometry(geomPoints) attrs = source_attributes[i] attrs.extend(['within', origPoint]) feat.setAttributes(attrs) point_sink.addFeature(feat, QgsFeatureSink.FastInsert) if include_bounds: upperBoundary = [] lowerBoundary = [] vertices = [] for vertex, c in enumerate(cost): if c > travelCost and tree[vertex] != -1: vertexId = graph.edge(tree[vertex]).fromVertex() if cost[vertexId] <= travelCost: vertices.append(vertex) for v in vertices: upperBoundary.append(graph.vertex(graph.edge(tree[v]).toVertex()).point()) lowerBoundary.append(graph.vertex(graph.edge(tree[v]).fromVertex()).point()) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) feat.setGeometry(geomUpper) attrs[-2] = 'upper' feat.setAttributes(attrs) point_sink.addFeature(feat, QgsFeatureSink.FastInsert) feat.setGeometry(geomLower) attrs[-2] = 'lower' feat.setAttributes(attrs) point_sink.addFeature(feat, QgsFeatureSink.FastInsert) if line_sink is not None: geom_lines = QgsGeometry.fromMultiPolylineXY(lines) feat.setGeometry(geom_lines) attrs = source_attributes[i] attrs.extend(['lines', origPoint]) feat.setAttributes(attrs) line_sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(i * total)) results = {} if point_sink is not None: results[self.OUTPUT] = dest_id if line_sink is not None: results[self.OUTPUT_LINES] = line_dest_id return results
def 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 processAlgorithm(self, parameters, context, feedback): 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_NAME, context) field_type = self.TYPES[self.parameterAsEnum(parameters, self.FIELD_TYPE, context)] width = self.parameterAsInt(parameters, self.FIELD_LENGTH, context) precision = self.parameterAsInt(parameters, self.FIELD_PRECISION, context) code = self.parameterAsString(parameters, self.FORMULA, context) globalExpression = self.parameterAsString(parameters, self.GLOBAL, context) fields = source.fields() field = QgsField(field_name, field_type, '', width, precision) fields.append(field) new_ns = {} (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, source.wkbType(), source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) # Run global code if globalExpression.strip() != '': try: bytecode = compile(globalExpression, '<string>', 'exec') exec(bytecode, new_ns) except: raise QgsProcessingException( self. tr("FieldPyculator code execute error.Global code block can't be executed!\n{0}\n{1}" ).format(str(sys.exc_info()[0].__name__), str(sys.exc_info()[1]))) # Replace all fields tags fields = source.fields() num = 0 for field in fields: field_name = str(field.name()) replval = '__attr[' + str(num) + ']' code = code.replace('<' + field_name + '>', replval) num += 1 # Replace all special vars code = code.replace('$id', '__id') code = code.replace('$geom', '__geom') need_id = code.find('__id') != -1 need_geom = code.find('__geom') != -1 need_attrs = code.find('__attr') != -1 # Compile try: bytecode = compile(code, '<string>', 'exec') except: raise QgsProcessingException( self. tr("FieldPyculator code execute error. Field code block can't be executed!\n{0}\n{1}" ).format(str(sys.exc_info()[0].__name__), str(sys.exc_info()[1]))) # Run features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, feat in enumerate(features): if feedback.isCanceled(): break feedback.setProgress(int(current * total)) attrs = feat.attributes() feat_id = feat.id() # Add needed vars if need_id: new_ns['__id'] = feat_id if need_geom: geom = feat.geometry() new_ns['__geom'] = geom if need_attrs: pyattrs = [a for a in attrs] new_ns['__attr'] = pyattrs # Clear old result if self.RESULT_VAR_NAME in new_ns: del new_ns[self.RESULT_VAR_NAME] # Exec exec(bytecode, new_ns) # Check result if self.RESULT_VAR_NAME not in new_ns: raise QgsProcessingException( self.tr( "FieldPyculator code execute error\n" "Field code block does not return '{0}' variable! " "Please declare this variable in your code!").format( self.RESULT_VAR_NAME)) # Write feature attrs.append(new_ns[self.RESULT_VAR_NAME]) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT_VECTOR, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT_VECTOR)) raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context) rasterPath = raster_layer.source() rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly) geoTransform = rasterDS.GetGeoTransform() rasterDS = None fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) fields.append(QgsField('line_id', QVariant.Int, '', 10, 0)) fields.append(QgsField('point_id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, raster_layer.crs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) outFeature = QgsFeature() outFeature.setFields(fields) self.fid = 0 self.lineId = 0 self.pointId = 0 features = source.getFeatures(QgsFeatureRequest().setDestinationCrs( raster_layer.crs(), context.transformContext())) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue geom = f.geometry() if geom.isMultipart(): lines = geom.asMultiPolyline() for line in lines: for i in range(len(line) - 1): p1 = line[i] p2 = line[i + 1] (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform) (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform) self.buildLine(x1, y1, x2, y2, geoTransform, sink, outFeature) else: points = geom.asPolyline() for i in range(len(points) - 1): p1 = points[i] p2 = points[i + 1] (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform) (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform) self.buildLine(x1, y1, x2, y2, geoTransform, sink, outFeature) self.pointId = 0 self.lineId += 1 feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) method = self.parameterAsEnum(parameters, self.METHOD, context) wkb_type = source.wkbType() fields = source.fields() new_fields = QgsFields() if QgsWkbTypes.geometryType(wkb_type) == QgsWkbTypes.PolygonGeometry: new_fields.append(QgsField('area', QVariant.Double)) new_fields.append(QgsField('perimeter', QVariant.Double)) elif QgsWkbTypes.geometryType(wkb_type) == QgsWkbTypes.LineGeometry: new_fields.append(QgsField('length', QVariant.Double)) else: new_fields.append(QgsField('xcoord', QVariant.Double)) new_fields.append(QgsField('ycoord', QVariant.Double)) if QgsWkbTypes.hasZ(source.wkbType()): self.export_z = True new_fields.append(QgsField('zcoord', QVariant.Double)) if QgsWkbTypes.hasM(source.wkbType()): self.export_m = True new_fields.append(QgsField('mvalue', QVariant.Double)) fields = QgsProcessingUtils.combineFields(fields, new_fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, wkb_type, source.sourceCrs()) coordTransform = None # Calculate with: # 0 - layer CRS # 1 - project CRS # 2 - ellipsoidal self.distance_area = QgsDistanceArea() if method == 2: self.distance_area.setSourceCrs(source.sourceCrs(), context.transformContext()) self.distance_area.setEllipsoid(context.project().ellipsoid()) elif method == 1: coordTransform = QgsCoordinateTransform(source.sourceCrs(), context.project().crs(), context.project()) features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break outFeat = f attrs = f.attributes() inGeom = f.geometry() if inGeom: if coordTransform is not None: inGeom.transform(coordTransform) if inGeom.type() == QgsWkbTypes.PointGeometry: attrs.extend(self.point_attributes(inGeom)) elif inGeom.type() == QgsWkbTypes.PolygonGeometry: attrs.extend(self.polygon_attributes(inGeom)) else: attrs.extend(self.line_attributes(inGeom)) outFeat.setAttributes(attrs) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def doCheck(self, context, feedback): layer = QgsProcessingUtils.mapLayerFromString( self.getParameterValue(self.INPUT_LAYER), context) 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(), context) valid_count = 0 invalid_output = self.getOutputFromName(self.INVALID_OUTPUT) invalid_fields = layer.fields() invalid_fields.append(QgsField('_errors', QVariant.String, 255)) invalid_writer = invalid_output.getVectorWriter( invalid_fields, layer.wkbType(), layer.crs(), context) invalid_count = 0 error_output = self.getOutputFromName(self.ERROR_OUTPUT) error_fields = QgsFields() error_fields.append(QgsField('message', QVariant.String, 255)) error_writer = error_output.getVectorWriter(error_fields, QgsWkbTypes.Point, layer.crs(), context) error_count = 0 features = QgsProcessingUtils.getFeatures(layer, context) total = 100.0 / QgsProcessingUtils.featureCount(layer, context) 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 processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context) minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context) bbox = source.sourceExtent() sourceIndex = QgsSpatialIndex(source, feedback) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, source.sourceCrs(), QgsFeatureSink.RegeneratePrimaryKey) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount if pointCount else 1 index = QgsSpatialIndex() points = dict() random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPointXY(p) ids = sourceIndex.intersects(geom.buffer(5, 5).boundingBox()) if len(ids) > 0 and \ vector.checkMinDistance(p, index, minDistance, points): request = QgsFeatureRequest().setFilterFids( ids).setSubsetOfAttributes([]) for f in source.getFeatures(request): if feedback.isCanceled(): break tmpGeom = f.geometry() if geom.within(tmpGeom): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.addFeature(f) points[nPoints] = p nPoints += 1 feedback.setProgress(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: feedback.pushInfo( self.tr( 'Could not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): 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): network = self.parameterAsSource(parameters, self.INPUT, context) if network is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) startPoints = self.parameterAsSource(parameters, self.START_POINTS, context) if startPoints is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.START_POINTS)) endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = startPoints.fields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) feat = QgsFeature() feat.setFields(fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo( QCoreApplication.translate('ShortestPathLayerToPoint', 'Loading start points…')) request = QgsFeatureRequest() request.setDestinationCrs(network.sourceCrs(), context.transformContext()) features = startPoints.getFeatures(request) total = 100.0 / startPoints.featureCount() if startPoints.featureCount( ) else 0 points = [endPoint] source_attributes = {} i = 1 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue for p in f.geometry().vertices(): points.append(QgsPointXY(p)) source_attributes[i] = f.attributes() i += 1 feedback.setProgress(int(current * total)) feedback.pushInfo( QCoreApplication.translate('ShortestPathLayerToPoint', 'Building graph…')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo( QCoreApplication.translate('ShortestPathLayerToPoint', 'Calculating shortest paths…')) graph = builder.graph() idxEnd = graph.findVertex(snappedPoints[0]) nPoints = len(snappedPoints) total = 100.0 / nPoints if nPoints else 1 for i in range(1, nPoints): if feedback.isCanceled(): break idxStart = graph.findVertex(snappedPoints[i]) tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: msg = self.tr( 'There is no route from start point ({}) to end point ({}).' .format(points[i].toString(), endPoint.toString())) feedback.reportError(msg) # add feature with no geometry feat.clearGeometry() attrs = source_attributes[i] attrs.append(points[i].toString()) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) continue route = [graph.vertex(idxEnd).point()] cost = costs[idxEnd] current = idxEnd while current != idxStart: current = graph.edge(tree[current]).fromVertex() route.append(graph.vertex(current).point()) route.reverse() geom = QgsGeometry.fromPolylineXY(route) feat.setGeometry(geom) attrs = source_attributes[i] attrs.extend( [points[i].toString(), endPoint.toString(), cost / multiplier]) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(i * total)) 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_VECTOR, context) raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context) rasterPath = exportRasterLayer(raster_layer) rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly) geoTransform = rasterDS.GetGeoTransform() fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) fields.append(QgsField('poly_id', QVariant.Int, '', 10, 0)) fields.append(QgsField('point_id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, raster_layer.crs()) outFeature = QgsFeature() outFeature.setFields(fields) fid = 0 polyId = 0 pointId = 0 features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs())) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue geom = f.geometry() bbox = geom.boundingBox() xMin = bbox.xMinimum() xMax = bbox.xMaximum() yMin = bbox.yMinimum() yMax = bbox.yMaximum() (startRow, startColumn) = raster.mapToPixel(xMin, yMax, geoTransform) (endRow, endColumn) = raster.mapToPixel(xMax, yMin, geoTransform) # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(geom.constGet()) engine.prepareGeometry() for row in range(startRow, endRow + 1): for col in range(startColumn, endColumn + 1): if feedback.isCanceled(): break (x, y) = raster.pixelToMap(row, col, geoTransform) point = QgsPoint(x, y) if engine.contains(point): outFeature.setGeometry(QgsGeometry(point)) outFeature['id'] = fid outFeature['poly_id'] = polyId outFeature['point_id'] = pointId fid += 1 pointId += 1 sink.addFeature(outFeature, QgsFeatureSink.FastInsert) pointId = 0 polyId += 1 feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) value_field_name = self.parameterAsString(parameters, self.VALUES_FIELD_NAME, context) category_field_names = self.parameterAsFields( parameters, self.CATEGORIES_FIELD_NAME, context) value_field_index = source.fields().lookupField(value_field_name) if value_field_index >= 0: value_field = source.fields().at(value_field_index) else: value_field = None category_field_indexes = [ source.fields().lookupField(n) for n in category_field_names ] # generate output fields fields = QgsFields() for c in category_field_indexes: fields.append(source.fields().at(c)) def addField(name): """ Adds a field to the output, keeping the same data type as the value_field """ field = QgsField(value_field) field.setName(name) fields.append(field) if value_field is None: field_type = 'none' fields.append(QgsField('count', QVariant.Int)) elif value_field.isNumeric(): field_type = 'numeric' fields.append(QgsField('count', QVariant.Int)) fields.append(QgsField('unique', QVariant.Int)) fields.append(QgsField('min', QVariant.Double)) fields.append(QgsField('max', QVariant.Double)) fields.append(QgsField('range', QVariant.Double)) fields.append(QgsField('sum', QVariant.Double)) fields.append(QgsField('mean', QVariant.Double)) fields.append(QgsField('median', QVariant.Double)) fields.append(QgsField('stddev', QVariant.Double)) fields.append(QgsField('minority', QVariant.Double)) fields.append(QgsField('majority', QVariant.Double)) fields.append(QgsField('q1', QVariant.Double)) fields.append(QgsField('q3', QVariant.Double)) fields.append(QgsField('iqr', QVariant.Double)) elif value_field.type() in (QVariant.Date, QVariant.Time, QVariant.DateTime): field_type = 'datetime' fields.append(QgsField('count', QVariant.Int)) fields.append(QgsField('unique', QVariant.Int)) fields.append(QgsField('empty', QVariant.Int)) fields.append(QgsField('filled', QVariant.Int)) # keep same data type for these fields addField('min') addField('max') else: field_type = 'string' fields.append(QgsField('count', QVariant.Int)) fields.append(QgsField('unique', QVariant.Int)) fields.append(QgsField('empty', QVariant.Int)) fields.append(QgsField('filled', QVariant.Int)) # keep same data type for these fields addField('min') addField('max') fields.append(QgsField('min_length', QVariant.Int)) fields.append(QgsField('max_length', QVariant.Int)) fields.append(QgsField('mean_length', QVariant.Double)) request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry) if value_field is not None: attrs = [value_field_index] else: attrs = [] attrs.extend(category_field_indexes) request.setSubsetOfAttributes(attrs) features = source.getFeatures( request, QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks) total = 50.0 / source.featureCount() if source.featureCount() else 0 if field_type == 'none': values = defaultdict(lambda: 0) else: values = defaultdict(list) for current, feat in enumerate(features): if feedback.isCanceled(): break feedback.setProgress(int(current * total)) attrs = feat.attributes() cat = tuple([attrs[c] for c in category_field_indexes]) if field_type == 'none': values[cat] += 1 continue if field_type == 'numeric': if attrs[value_field_index] == NULL: continue else: value = float(attrs[value_field_index]) elif field_type == 'string': if attrs[value_field_index] == NULL: value = '' else: value = str(attrs[value_field_index]) elif attrs[value_field_index] == NULL: value = NULL else: value = attrs[value_field_index] values[cat].append(value) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) if field_type == 'none': self.saveCounts(values, sink, feedback) elif field_type == 'numeric': self.calcNumericStats(values, sink, feedback) elif field_type == 'datetime': self.calcDateTimeStats(values, sink, feedback) else: self.calcStringStats(values, sink, feedback) return {self.OUTPUT: dest_id}
def testWidget(self): """Test widget operations""" widget = QgsFieldMappingWidget() for i in range(10): widget.appendField(QgsField(str(i))) self.assertTrue(widget.model().rowCount(QModelIndex()), 10) def _compare(widget, expected): actual = [] for field in widget.mapping(): actual.append(int(field.originalName)) self.assertEqual(actual, expected) _compare(widget, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) selection_model = widget.selectionModel() selection_model.clear() for i in range(0, 10, 2): selection_model.select(widget.model().index(i, 0), QItemSelectionModel.Select) self.assertTrue(widget.moveSelectedFieldsDown()) _compare(widget, [1, 0, 3, 2, 5, 4, 7, 6, 9, 8]) selection_model.clear() for i in range(1, 10, 2): selection_model.select(widget.model().index(i, 0), QItemSelectionModel.Select) self.assertTrue(widget.moveSelectedFieldsUp()) _compare(widget, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) selection_model.clear() for i in range(0, 10, 2): selection_model.select(widget.model().index(i, 0), QItemSelectionModel.Select) self.assertTrue(widget.removeSelectedFields()) _compare(widget, [1, 3, 5, 7, 9]) # Test set destination fields widget.setSourceFields(self.source_fields) widget.setDestinationFields(self.destination_fields) mapping = widget.mapping() self.assertEqual(mapping[0].field.name(), 'destination_field1') self.assertEqual(mapping[1].field.name(), 'destination_field2') self.assertEqual(mapping[2].field.name(), 'destination_field3') self.assertEqual(mapping[0].originalName, 'destination_field1') self.assertEqual(mapping[1].originalName, 'destination_field2') self.assertEqual(mapping[2].originalName, 'destination_field3') # Test constraints f = QgsField('constraint_field', QVariant.Int) constraints = QgsFieldConstraints() constraints.setConstraint(QgsFieldConstraints.ConstraintNotNull, QgsFieldConstraints.ConstraintOriginProvider) constraints.setConstraint(QgsFieldConstraints.ConstraintExpression, QgsFieldConstraints.ConstraintOriginProvider) constraints.setConstraint(QgsFieldConstraints.ConstraintUnique, QgsFieldConstraints.ConstraintOriginProvider) f.setConstraints(constraints) fields = QgsFields() fields.append(f) widget.setDestinationFields(fields) self.assertEqual( widget.model().data(widget.model().index(0, 5, QModelIndex()), Qt.DisplayRole), "Constraints active") self.assertEqual( widget.model().data(widget.model().index(0, 5, QModelIndex()), Qt.ToolTipRole), "Unique<br>Not null<br>Expression") self.assertEqual( widget.model().data(widget.model().index(0, 5, QModelIndex()), Qt.BackgroundColorRole), QColor(255, 224, 178))