def get_feature_value(self, model=None): self.layer.startEditing() feature = None request = QgsFeatureRequest() if model is None: model = self.host.model() request.setFilterFid(model.id) feature_itr = self.layer.getFeatures(request) for feat in feature_itr: feature = feat break exp = QgsExpression(self.column.expression) if exp.hasParserError(): raise Exception(exp.parserErrorString()) exp.prepare(self.layer.pendingFields()) if feature is not None: value = exp.evaluate(feature) return value else: return None
def get_wkt(self, spatial_column, feature_id): """ Gets feature geometry in Well-Known Text format and returns it. :param spatial_column: The spatial column name. :type spatial_column: String :param feature_id: Feature id :type feature_id: Integer :return: Well-Known Text format of a geometry :rtype: WKT """ geom_wkt = None fid = feature_id request = QgsFeatureRequest() request.setFilterFid(fid) features = self.layer.getFeatures(request) geom_col_obj = self.entity.columns[spatial_column] geom_type = geom_col_obj.geometry_type() # get the wkt of the geometry for feature in features: geometry = feature.geometry() if geometry.isGeosValid(): if geom_type in ['MULTIPOLYGON', 'MULTILINESTRING']: geometry.convertToMultiType() geom_wkt = geometry.exportToWkt() return geom_wkt
def processAlgorithm(self, progress): network = dataobjects.getObjectFromUri( self.getParameterValue(self.NETWORK_LAYER)) # Ensure that upstream and downstream arc detected idxUpArcId= findField(network, 'UpArcId') if idxUpArcId == -1: raise GeoAlgorithmExecutionException( self.tr('Seems upstream and downstream arcs is not set. ' 'Please run corresponding tool and try again.')) # First add new fields to the network layer networkProvider = network.dataProvider() (idxStrahler, fieldList) = findOrCreateField(network, network.pendingFields(), 'StrahOrder', QVariant.Int, 10, 0) writer = self.getOutputFromName(self.STRAHLER_ORDER).getVectorWriter( fieldList.toList(), networkProvider.geometryType(), networkProvider.crs()) # Generate helper dictionaries myNetwork, arcsPerNodeId = makeHelperDictionaries(network) # Write output file for f in network.getFeatures(): writer.addFeature(f) del writer vl = QgsVectorLayer(self.getOutputValue(self.STRAHLER_ORDER), 'tmp', 'ogr') provider = vl.dataProvider() # calculate Strahler orders # Algorithm at pages 65-66 "Automated AGQ4Vector Watershed.pdf" req = QgsFeatureRequest() progress.setInfo(self.tr('Calculating Strahler orders...')) # Iterate over upsteram node ids starting from the last ones # which represents source arcs for nodeId in sorted(myNetwork.keys(), reverse=True): f = vl.getFeatures(req.setFilterFid(myNetwork[nodeId])).next() fid = f.id() upstreamArcs = f['UpArcId'] if upstreamArcs == NULL: provider.changeAttributeValues({fid:{idxStrahler: 1}}) else: orders = [] for i in upstreamArcs.split(','): f = vl.getFeatures(req.setFilterFid(int(i))).next() if f['StrahOrder']: orders.append(f['StrahOrder']) orders.sort(reverse=True) if len(orders) == 1: order = orders[0] elif len(orders) >= 2: diff = orders[0] - orders[1] if diff == 0: order = orders[0] + 1 else: order = max([orders[0], orders[1]]) provider.changeAttributeValues({fid:{idxStrahler: order}})
def testCopyMoveFeature(self): """ Test copy and move features""" rqst = QgsFeatureRequest() rqst.setFilterFid(4) self.vl.startEditing() (ok, rqst, msg) = self.vltools.copyMoveFeatures(self.vl, rqst, -0.1, 0.2) self.assertTrue(ok) for f in self.vl.getFeatures(rqst): geom = f.geometry() self.assertAlmostEqual(geom.asPoint().x(), -65.42) self.assertAlmostEqual(geom.asPoint().y(), 78.5)
def layerData(self, layer, request={}, offset=0): # Retrieve the data for a layer first = True data = {} fields = [] fieldTypes = [] fr = QgsFeatureRequest() if request: if 'exact' in request and request['exact']: fr.setFlags(QgsFeatureRequest.ExactIntersect) if 'nogeom' in request and request['nogeom']: fr.setFlags(QgsFeatureRequest.NoGeometry) if 'fid' in request: fr.setFilterFid(request['fid']) elif 'extents' in request: fr.setFilterRect(QgsRectangle(*request['extents'])) if 'attributes' in request: fr.setSubsetOfAttributes(request['attributes']) # IMPORTANT - we do not use `for f in layer.getFeatures(fr):` as we need # to verify that existing attributes and geometry are correctly cleared # from the feature when calling nextFeature() it = layer.getFeatures(fr) f = QgsFeature() while it.nextFeature(f): if first: first = False for field in f.fields(): fields.append(str(field.name())) fieldTypes.append(str(field.typeName())) if sys.version_info.major == 2: fielddata = dict((name, str(f[name])) for name in fields) else: fielddata = dict((name, str(f[name])) for name in fields) g = f.geometry() if not g.isEmpty(): fielddata[geomkey] = str(g.exportToWkt()) else: fielddata[geomkey] = "None" fielddata[fidkey] = f.id() id = fielddata[fields[0]] description = fielddata[fields[1]] fielddata['id'] = id fielddata['description'] = description data[f.id() + offset] = fielddata if 'id' not in fields: fields.insert(0, 'id') if 'description' not in fields: fields.insert(1, 'description') fields.append(fidkey) fields.append(geomkey) return fields, fieldTypes, data
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.VECTOR)) pointCount = int(self.getParameterValue(self.POINT_NUMBER)) minDistance = float(self.getParameterValue(self.MIN_DISTANCE)) bbox = layer.extent() idxLayer = vector.spatialindex(layer) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QgsWkbTypes.Point, layer.crs()) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount index = QgsSpatialIndex() points = dict() request = QgsFeatureRequest() random.seed() while nIterations < maxIterations and nPoints < pointCount: rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() pnt = QgsPoint(rx, ry) geom = QgsGeometry.fromPoint(pnt) ids = idxLayer.intersects(geom.buffer(5, 5).boundingBox()) if len(ids) > 0 and \ vector.checkMinDistance(pnt, index, minDistance, points): for i in ids: f = next(layer.getFeatures(request.setFilterFid(i))) tmpGeom = f.geometry() if geom.within(tmpGeom): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) writer.addFeature(f) index.insertFeature(f) points[nPoints] = pnt nPoints += 1 progress.setPercentage(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Can not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) del writer
def layerData(layer, request={}, offset=0): first = True data = {} fields = [] fieldTypes = [] fr = QgsFeatureRequest() if request: if 'exact' in request and request['exact']: fr.setFlags(QgsFeatureRequest.ExactIntersect) if 'nogeom' in request and request['nogeom']: fr.setFlags(QgsFeatureRequest.NoGeometry) if 'fid' in request: fr.setFilterFid(request['fid']) elif 'extents' in request: fr.setFilterRect(QgsRectangle(*request['extents'])) if 'attributes' in request: fr.setSubsetOfAttributes(request['attributes']) for f in layer.getFeatures(fr): if first: first = False for field in f.fields(): fields.append(str(field.name())) fieldTypes.append(str(field.typeName())) fielddata = dict((name, unicode(f[name])) for name in fields) g = f.geometry() if g: fielddata[geomkey] = str(g.exportToWkt()) else: fielddata[geomkey] = "None" fielddata[fidkey] = f.id() id = fielddata[fields[0]] description = fielddata[fields[1]] fielddata['id'] = id fielddata['description'] = description data[f.id() + offset] = fielddata if 'id' not in fields: fields.insert(0, 'id') if 'description' not in fields: fields.insert(1, 'description') fields.append(fidkey) fields.append(geomkey) return fields, fieldTypes, data
def testStatistics(self): """Test zonal stats""" sep = os.sep TEST_DATA_DIR = unitTestDataPath() + sep + "zonalstatistics" + sep myTempPath = QDir.tempPath() + sep testDir = QDir(TEST_DATA_DIR) for f in testDir.entryList(QDir.Files): QFile.remove(myTempPath + f) QFile.copy(TEST_DATA_DIR + f, myTempPath + f) myVector = QgsVectorLayer(myTempPath + "polys.shp", "poly", "ogr") myRasterPath = myTempPath + "edge_problem.asc" zs = QgsZonalStatistics(myVector, myRasterPath, "", 1) zs.calculateStatistics(None) feat = QgsFeature() # validate statistics for each feature request = QgsFeatureRequest().setFilterFid(0) feat = myVector.getFeatures(request).next() myMessage = ('Expected: %f\nGot: %f\n' % (12.0, feat[1])) assert feat[1] == 12.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (8.0, feat[2])) assert feat[2] == 8.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.666666666666667, feat[3])) assert abs(feat[3] - 0.666666666666667) < 0.00001, myMessage request.setFilterFid(1) feat = myVector.getFeatures(request).next() myMessage = ('Expected: %f\nGot: %f\n' % (9.0, feat[1])) assert feat[1] == 9.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.555555555555556, feat[3])) assert abs(feat[3] - 0.555555555555556) < 0.00001, myMessage request.setFilterFid(2) feat = myVector.getFeatures(request).next() myMessage = ('Expected: %f\nGot: %f\n' % (6.0, feat[1])) assert feat[1] == 6.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.833333333333333, feat[3])) assert abs(feat[3] - 0.833333333333333) < 0.00001, myMessage
def on_zoomButton_clicked(self): """ Slot used to zoom the mapcanvas to the features associated to a complex """ #case no item is selected we should warn the user if len(self.treeWidget.selectedItems()) == 0: QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("Please, select an item to zoom.")) return item = self.treeWidget.selectedItems()[0] #checking if the item is a complex (it should have depth = 2) if self.depth(item) == 2: bbox = QgsRectangle() for i in range(item.childCount()): aggregated_item = item.child(i) aggregated_class = aggregated_item.text(0) #getting the layer the needs to be updated aggregated_layer = None layers = self.iface.mapCanvas().layers() for layer in layers: if layer.name() == aggregated_class: aggregated_layer = layer break if not aggregated_layer: QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("The associated classes must be loaded in the table of contents.")) return for j in range(aggregated_item.childCount()): id = aggregated_item.child(j).text(0) freq = QgsFeatureRequest() freq.setFilterFid(int(id)) feature = layer.getFeatures( freq ).next() if j==0 and i == 0: bbox=feature.geometry().boundingBox() bbox.combineExtentWith(feature.geometry().boundingBox()) self.iface.mapCanvas().setExtent(bbox) self.iface.mapCanvas().refresh() else: QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("Select a complex.")) return
def processAlgorithm(self, progress): fileName = self.getParameterValue(self.INPUT) layer = dataobjects.getObjectFromUri(fileName) fieldName = self.getParameterValue(self.FIELD) value = self.getParameterValue(self.VALUE) selected = layer.selectedFeaturesIds() if len(selected) == 0: GeoAlgorithmExecutionException( self.tr('There is no selection in the input layer. ' 'Select one feature and try again.')) ft = layer.selectedFeatures()[0] geom = QgsGeometry(ft.geometry()) attrSum = ft[fieldName] idx = QgsSpatialIndex(layer.getFeatures()) req = QgsFeatureRequest() completed = False while not completed: intersected = idx.intersects(geom.boundingBox()) if len(intersected) < 0: progress.setInfo(self.tr('No adjacent features found.')) break for i in intersected: ft = layer.getFeatures(req.setFilterFid(i)).next() tmpGeom = QgsGeometry(ft.geometry()) if tmpGeom.touches(geom): geom = tmpGeom.combine(geom) selected.append(i) attrSum += ft[fieldName] if attrSum >= value: completed = True break layer.setSelectedFeatures(selected) self.setOutputValue(self.OUTPUT, fileName)
def processAlgorithm(self, progress): radius = self.getParameterValue(self.DISTANCE) horizontal = self.getParameterValue(self.HORIZONTAL) output = self.getOutputFromName(self.OUTPUT_LAYER) layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_LAYER)) writer = output.getVectorWriter(layer.fields(), layer.wkbType(), layer.crs()) features = vector.features(layer) total = 100.0 / len(features) if len(features) > 0 else 1 duplicates = dict() for current, f in enumerate(features): wkt = f.geometry().exportToWkt() if wkt not in duplicates: duplicates[wkt] = [f.id()] else: duplicates[wkt].extend([f.id()]) progress.setPercentage(int(current * total)) current = 0 total = 100.0 / len(duplicates) if len(duplicates) > 0 else 1 progress.setPercentage(0) fullPerimeter = 2 * math.pi request = QgsFeatureRequest() for (geom, fids) in duplicates.iteritems(): count = len(fids) if count == 1: f = layer.getFeatures(request.setFilterFid(fids[0])).next() writer.addFeature(f) else: angleStep = fullPerimeter / count if count == 2 and horizontal: currentAngle = math.pi / 2 else: currentAngle = 0 old_point = QgsGeometry.fromWkt(geom).asPoint() for fid in fids: sinusCurrentAngle = math.sin(currentAngle) cosinusCurrentAngle = math.cos(currentAngle) dx = radius * sinusCurrentAngle dy = radius * cosinusCurrentAngle f = layer.getFeatures(request.setFilterFid(fid)).next() new_point = QgsPoint(old_point.x() + dx, old_point.y() + dy) out_feature = QgsFeature() out_feature.setGeometry(QgsGeometry.fromPoint(new_point)) out_feature.setAttributes(f.attributes()) writer.addFeature(out_feature) currentAngle += angleStep current += 1 progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, progress): network = dataobjects.getObjectFromUri( self.getParameterValue(self.NETWORK_LAYER)) # Ensure that outlet arc is selected if network.selectedFeatureCount() != 1: raise GeoAlgorithmExecutionException( self.tr('Seems oulet arc is not selected. Select outlet' 'arc in the stream network layer and try again.')) # First add new fields to the network layer networkProvider = network.dataProvider() networkProvider.addAttributes( [QgsField('StrahOrder', QVariant.Int, '', 10), # Strahler order QgsField('DownNodeId', QVariant.Int, '', 10), # downstream node id QgsField('UpNodeId', QVariant.Int, '', 10), # upstream node id QgsField('DownArcId', QVariant.Int, '', 10), # downstream arc id QgsField('UpArcId', QVariant.String, '', 250), # comma separated list of upstream arc ids QgsField('Length', QVariant.Double, '', 20, 6), # length of the arc QgsField('LengthDown', QVariant.Double, '', 20, 6), # length downstream QgsField('LengthUp', QVariant.Double, '', 20, 6)]) # length upstream network.updateFields() # Determine indexes of the fields idxStrahler = network.fieldNameIndex('StrahOrder') idxDownNodeId = network.fieldNameIndex('DownNodeId') idxUpNodeId = network.fieldNameIndex('UpNodeId') idxDownArcId = network.fieldNameIndex('DownArcId') idxUpArcId = network.fieldNameIndex('UpArcId') idxLength = network.fieldNameIndex('Length') idxLenDown = network.fieldNameIndex('LengthDown') idxLenUp = network.fieldNameIndex('LengthUp') # Generate arc adjacency dictionary # Algorithm at pages 79-80 "Automated AGQ4Vector Watershed.pdf" progress.setInfo(self.tr('Generating arc adjacency dictionary...')) self.arcsPerNode = arcsAadjacencyDictionary(network) # Node indexing # Algorithm at pages 80-81 "Automated AGQ4Vector Watershed.pdf" progress.setInfo(self.tr('Indexing nodes...')) self.dwUpNodesId = dict() # Outlet arc and its upstream node outletArc = network.selectedFeatures()[0] upNode = outletArc.geometry().asPolyline()[-1] # Dictionary for storing node indexes per arc. # For outlet arc we assign -1 for downstream and 0 for upstream nodes self.dwUpNodesId[outletArc.id()] = [-1, 0] # Current node id self.nodeId = 0 # Start recursive node indexing procedure self.nodeIndexing(outletArc, upNode) # Write node indices to the network layer attributes progress.setInfo(self.tr('Assigning indices...')) for i in self.dwUpNodesId.keys(): nodeIds = self.dwUpNodesId[i] attrs = {idxDownNodeId:nodeIds[0], idxUpNodeId:nodeIds[1]} networkProvider.changeAttributeValues({i: attrs}) # Mapping between upstream node id from attribute table and QGIS # feature id. Will be used to sort features from the network table myNetwork = dict() # Find upstream and downstream arc ids for each arc in the stream # network layer. First we generate helper arcPerNodeId dictionary # with node ids as keys and lists of arc ids connected to this node # as values # Algorithm at pages 55-56 "Automated AGQ4Vector Watershed.pdf" arcsPerNodeId = dict() for f in network.getFeatures(): if f['UpNodeId'] not in arcsPerNodeId: arcsPerNodeId[f['UpNodeId']] = [f.id()] else: arcsPerNodeId[f['UpNodeId']].append(f.id()) if f['DownNodeId'] not in arcsPerNodeId: arcsPerNodeId[f['DownNodeId']] = [f.id()] else: arcsPerNodeId[f['DownNodeId']].append(f.id()) # Also populate mapping between upstream node id and feature id myNetwork[f['UpNodeId']] = f.id() # Populating upstream and downstream arc ids # Iterate over all arcs in the stream network layer for f in network.getFeatures(): fid = f.id() # Determine upstream node id upNodeId = f['UpNodeId'] attrs = {idxDownArcId:fid} changes = dict() ids = [] # Iterate over all arcs connected to the upstream node with # given id, skipping current arc for i in arcsPerNodeId[upNodeId]: if i != fid: # Modify DownArcId changes[i] = attrs # Collect ids of the arcs located upstream ids.append(str(i)) networkProvider.changeAttributeValues(changes) networkProvider.changeAttributeValues({fid:{idxUpArcId:','.join(ids)}}) # Also calculate length of the current arc networkProvider.changeAttributeValues({fid:{idxLength:f.geometry().length()}}) # Calculate length upstream for arcs # Algorithm at pages 61-62 "Automated AGQ4Vector Watershed.pdf" progress.setInfo(self.tr('Calculating length upstream...')) req = QgsFeatureRequest() # Iterate over upsteram node ids starting from the last ones # which represents source arcs for nodeId in sorted(myNetwork.keys(), reverse=True): f = network.getFeatures(req.setFilterFid(myNetwork[nodeId])).next() arcLen = f['Length'] upstreamArcs = f['UpArcId'] if not upstreamArcs: networkProvider.changeAttributeValues({f.id():{idxLenUp: arcLen}}) else: length = [] for i in upstreamArcs.split(','): f = network.getFeatures(req.setFilterFid(int(i))).next() if f['LengthUp']: length.append(f['LengthUp']) upLen = max(length) if len(length) > 0 else 0.0 networkProvider.changeAttributeValues({myNetwork[nodeId]:{idxLenUp:arcLen + upLen}}) # Calculate length downstream for arcs # Algorithm at pages 62-63 "Automated AGQ4Vector Watershed.pdf" progress.setInfo(self.tr('Calculating length downstream...')) first = True # Iterate over upsteram node ids starting from the first one # which represents downstream node of the outlet arc for nodeId in sorted(myNetwork.keys()): f = network.getFeatures(req.setFilterFid(myNetwork[nodeId])).next() # for outlet arc downstream length set to zero if first: networkProvider.changeAttributeValues({myNetwork[nodeId]:{idxLenDown:0.0}}) first = False continue arcLen = f['Length'] downArcId = f['DownArcId'] f = network.getFeatures(req.setFilterFid(downArcId)).next() lenDown = f['LengthDown'] if f['LengthDown'] else 0.0 networkProvider.changeAttributeValues({myNetwork[nodeId]:{idxLenDown: arcLen + lenDown}}) # calculate Strahler orders # Algorithm at pages 65-66 "Automated AGQ4Vector Watershed.pdf" progress.setInfo(self.tr('Calculating Strahler orders...')) # Iterate over upsteram node ids starting from the last ones # which represents source arcs for nodeId in sorted(myNetwork.keys(), reverse=True): f = network.getFeatures(req.setFilterFid(myNetwork[nodeId])).next() fid = f.id() upstreamArcs = f['UpArcId'] if upstreamArcs == NULL: networkProvider.changeAttributeValues({fid:{idxStrahler: 1}}) else: orders = [] for i in upstreamArcs.split(','): f = network.getFeatures(req.setFilterFid(int(i))).next() if f['StrahOrder']: orders.append(f['StrahOrder']) orders.sort(reverse=True) if len(orders) == 1: order = orders[0] elif len(orders) >= 2: diff = orders[0] - orders[1] if diff == 0: order = orders[0] + 1 else: order = max([orders[0], orders[1]]) networkProvider.changeAttributeValues({fid:{idxStrahler: order}}) # Calculate order frequency progress.setInfo(self.tr('Calculating order frequency...')) maxOrder = int(network.maximumValue(idxStrahler)) ordersFrequency = dict() bifRatios = dict() # Initialize dictionaries for i in xrange(1, maxOrder + 1): ordersFrequency[i] = dict(N=0.0, Ndu=0.0, Na=0.0) bifRatios[i] = dict(Rbu=0.0, Rbdu=0.0, Ru=0.0) for i in xrange(1, maxOrder + 1): req.setFilterExpression('"StrahOrder" = %s' % i) for f in network.getFeatures(req): order = int(f['StrahOrder']) upstreamArcs = f['UpArcId'].split(',') if f['UpArcId'] else [] if len(upstreamArcs) == 0: ordersFrequency[i]['N'] += 1.0 elif len(upstreamArcs) > 1: ordersFrequency[order]['N'] += 1.0 for j in upstreamArcs: f = network.getFeatures(QgsFeatureRequest().setFilterFid(int(j))).next() upOrder = int(f['StrahOrder']) diff = upOrder - order if diff == 1: ordersFrequency[upOrder]['Ndu'] += 1.0 if diff > 1: ordersFrequency[upOrder]['Na'] += 1.0 writerOrders = self.getOutputFromName( self.ORDER_FREQUENCY).getTableWriter(['order', 'N', 'NDU', 'NA']) writerBifrat = self.getOutputFromName( self.BIFURCATION_PARAMS).getTableWriter(['order', 'RBD', 'RB', 'RU']) # Calculate bifurcation parameters progress.setInfo(self.tr('Calculating bifurcation parameters...')) for k, v in ordersFrequency.iteritems(): if k != maxOrder: bifRatios[k]['Rbu'] = ordersFrequency[k]['N'] / ordersFrequency[k + 1]['N'] bifRatios[k]['Rbdu'] = ordersFrequency[k]['Ndu'] / ordersFrequency[k + 1]['N'] else: bifRatios[k]['Rbu'] = 0.0 bifRatios[k]['Rbdu'] = 0.0 bifRatios[k]['Ru'] = bifRatios[k]['Rbu'] - bifRatios[k]['Rbdu'] writerOrders.addRecord([k, v['N'], v['Ndu'], v['Na']]) writerBifrat.addRecord([k, bifRatios[k]['Rbdu'], bifRatios[k]['Rbu'], bifRatios[k]['Ru']]) del writerOrders del writerBifrat
def map_sg_codes_to_provinces( db_manager, site_layer, parcels_layer, sg_code_field, all_features=False): """Obtains sg codes from target layer. :param db_manager: A database manager :type db_manager: DatabaseManager :param site_layer: The target layer. :type site_layer: QgsVectorLayer :param parcels_layer: Vector layer that has sg code in one of its fields. :type parcels_layer: QgsVectorLayer :param sg_code_field: Name of the field that contains sg code :type sg_code_field: str :param all_features: If True select all features, else only the selected ones. :type all_features: bool :returns: Dict where key is sg code and value is province name :rtype: dict """ intersecting_parcels = [] sg_code_provinces = {} sg_code_index = parcels_layer.fieldNameIndex(sg_code_field) if sg_code_index == -1: message = 'Field "%s" not found' % sg_code_field raise Exception(message) parcels_provider = parcels_layer.dataProvider() site_crs = site_layer.crs() parcel_crs = parcels_layer.crs() province_crs = QgsCoordinateReferenceSystem(4326) site_parcel_transformer = QgsCoordinateTransform(site_crs, parcel_crs) province_transformer = QgsCoordinateTransform(parcel_crs, province_crs) if not all_features: selected_features = site_layer.selectedFeatures() else: selected_features = site_layer.getFeatures() for selected_feature in selected_features: for feature in parcels_provider.getFeatures(): geometry = selected_feature.geometry() feature_geometry = feature.geometry() geometry.transform(site_parcel_transformer) intersect = geometry.intersects(feature_geometry) if intersect: intersecting_parcels.append(feature.id()) feature = QgsFeature() for intersect in intersecting_parcels: index = int(intersect) request = QgsFeatureRequest() request.setFilterFid(index) parcels_provider.getFeatures(request).nextFeature(feature) sg_code = feature.attributes()[sg_code_index] geometry = feature.geometry() centroid = geometry.centroid().asPoint() centroid = province_transformer.transform(centroid) # noinspection PyTypeChecker province_name = province_for_point(db_manager, centroid) sg_code_provinces[sg_code] = province_name return sg_code_provinces
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) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 featureCount = source.featureCount() total = 100.0 / pointCount if pointCount else 1 index = QgsSpatialIndex() points = dict() da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs(), context.transformContext()) da.setEllipsoid(context.project().ellipsoid()) request = QgsFeatureRequest() random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break # pick random feature fid = random.randint(0, featureCount - 1) f = next( source.getFeatures( request.setFilterFid(fid).setSubsetOfAttributes([]))) fGeom = f.geometry() if fGeom.isMultipart(): lines = fGeom.asMultiPolyline() # pick random line lineId = random.randint(0, len(lines) - 1) vertices = lines[lineId] else: vertices = fGeom.asPolyline() # pick random segment if len(vertices) == 2: vid = 0 else: vid = random.randint(0, len(vertices) - 2) startPoint = vertices[vid] endPoint = vertices[vid + 1] length = da.measureLine(startPoint, endPoint) dist = length * random.random() if dist > minDistance: d = dist / (length - dist) rx = (startPoint.x() + d * endPoint.x()) / (1 + d) ry = (startPoint.y() + d * endPoint.y()) / (1 + d) # generate random point p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPointXY(p) if vector.checkMinDistance(p, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.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 on_btnRun_clicked(self): #Check for combo and list box selections if self.ui.cmbBaseLayer.count() < 1 or self.ui.cmbProcessLayer.count( ) < 1: QMessageBox.critical(self, 'Vector Geoprocessor', 'Invalid layer selection.') return if len(self.ui.listFields.selectedItems()) < 1: QMessageBox.critical(self, 'Vector Geoprocessor', 'Invalid field selection.') return #Initializations self.ui.ProgressBar.setValue(0) self.setCursor(Qt.WaitCursor) data = [] #Add new attributes to base layer bprovider = self.blayer.dataProvider() pprovider = self.player.dataProvider() pfields = pprovider.fields() for item in self.ui.listFields.selectedItems(): fname = item.text() for fld in pfields.toList(): if fname == fld.name(): newfield = QgsField() newfield.setName(fld.name()) newfield.setType(fld.type()) newfield.setTypeName(fld.typeName()) newfield.setLength(fld.length()) newfield.setPrecision(fld.precision()) newfield.setComment(fld.comment()) bprovider.addAttributes([newfield]) #Create a spatial index for faster processing spindex = QgsSpatialIndex() for pfeat in pprovider.getFeatures(): spindex.insertFeature(pfeat) #Find the intersection of process layer features with base layer #To increase speed, intersect with a bounding box rectangle first #Then further process within the geometric shape #Add requested processed information to base layer featreq = QgsFeatureRequest() bfields = bprovider.fields() ddic = {} len1 = len(self.ui.listFields.selectedItems()) len2 = len(bfields) b1 = 0 b2 = bprovider.featureCount() attr = {} for bfeat in bprovider.getFeatures(): b1 += 1 attr.clear() bgeom = bfeat.geometry() intersect = spindex.intersects(bgeom.boundingBox()) data[:] = [] for fid in intersect: pfeat = next(self.player.getFeatures( featreq.setFilterFid(fid))) if pfeat.geometry().intersects(bgeom) == False: data.append(fid) for fid in data: intersect.pop(intersect.index(fid)) count = 0 for item in self.ui.listFields.selectedItems(): pfindx = pprovider.fieldNameIndex(item.text()) if pfindx < 0: self.setCursor(Qt.ArrowCursor) QMessageBox.critical(self, 'Vector Geoprocessor', 'Processing error.') return data[:] = [] for fid in intersect: pfeat = next( self.player.getFeatures(featreq.setFilterFid(fid))) if self.oindex in [0, 1, 2, 3, 4]: data.append(float(pfeat.attribute(item.text()))) elif self.oindex in [5, 6]: data.append(str(pfeat.attribute(item.text()))) if len(data) == 0: value = None elif self.oindex == 0: #Find mean value of points within polygons value = sum(data) / float(len(data)) elif self.oindex == 1: #Find median value of points within polygons data = sorted(data) lendata = len(data) if lendata % 2: value = data[(lendata + 1) / 2 - 1] else: d1 = data[lendata / 2 - 1] d2 = data[lendata / 2] value = (d1 + d2) / 2.0 elif self.oindex == 2: #Find maximum value of points within polygons value = max(data) elif self.oindex == 3: #Find minimum value of points within polygons value = min(data) elif self.oindex == 4: #Find mean value (area-weighted) of polygons within polygons value = 0.0 totalarea = 0.0 for fid in intersect: pfeat = next( self.player.getFeatures(featreq.setFilterFid(fid))) pgeom = pfeat.geometry() isect = bgeom.intersection(pgeom) parea = isect.area() value += (float(pfeat.attribute(item.text()) * parea)) totalarea += parea value = value / totalarea elif self.oindex == 5: #Find largest area polygon within polygons data = list(set(data)) #Get unique items in data ddic.clear() for i in data: ddic.update({i: 0.0}) for fid in intersect: pfeat = next( self.player.getFeatures(featreq.setFilterFid(fid))) pgeom = pfeat.geometry() isect = bgeom.intersection(pgeom) parea = isect.area() key = str(pfeat.attribute(item.text())) parea = parea + ddic[key] ddic.update({key: parea}) parea = -1 for key in list(ddic.keys()): if ddic[key] > parea: parea = ddic[key] value = key elif self.oindex == 6: #Add polygon attribute to points if len(data) != 1: QMessageBox.warning( self, 'Vector Geoprocessor', 'Point intersects more than one polygon.') value = data[0] attr.update({(len2 - len1 + count): value}) count += 1 result = bprovider.changeAttributeValues({bfeat.id(): attr}) if not result: QMessageBox.critical(self, 'Vector Geoprocessor', 'Could not change attribute value.') return self.ui.ProgressBar.setValue(float(b1) / float(b2) * 100.0) QApplication.processEvents() self.setCursor(Qt.ArrowCursor)
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.VECTOR)) pointCount = float(self.getParameterValue(self.POINT_NUMBER)) minDistance = float(self.getParameterValue(self.MIN_DISTANCE)) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QgsWkbTypes.Point, layer.crs()) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 featureCount = layer.featureCount() total = 100.0 / pointCount index = QgsSpatialIndex() points = dict() da = QgsDistanceArea() request = QgsFeatureRequest() random.seed() while nIterations < maxIterations and nPoints < pointCount: # pick random feature fid = random.randint(0, featureCount - 1) f = next(layer.getFeatures(request.setFilterFid(fid).setSubsetOfAttributes([]))) fGeom = f.geometry() if fGeom.isMultipart(): lines = fGeom.asMultiPolyline() # pick random line lineId = random.randint(0, len(lines) - 1) vertices = lines[lineId] else: vertices = fGeom.asPolyline() # pick random segment if len(vertices) == 2: vid = 0 else: vid = random.randint(0, len(vertices) - 2) startPoint = vertices[vid] endPoint = vertices[vid + 1] length = da.measureLine(startPoint, endPoint) dist = length * random.random() if dist > minDistance: d = dist / (length - dist) rx = (startPoint.x() + d * endPoint.x()) / (1 + d) ry = (startPoint.y() + d * endPoint.y()) / (1 + d) # generate random point pnt = QgsPoint(rx, ry) geom = QgsGeometry.fromPoint(pnt) if vector.checkMinDistance(pnt, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) writer.addFeature(f) index.insertFeature(f) points[nPoints] = pnt nPoints += 1 progress.setPercentage(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Can not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) del writer
def on_btnRun_clicked(self): #Check for combo and list box selections if self.ui.cmbBaseLayer.count() < 1 or self.ui.cmbProcessLayer.count() < 1: QMessageBox.critical(self, 'Vector Geoprocessor', 'Invalid layer selection.') return if len(self.ui.listFields.selectedItems()) < 1: QMessageBox.critical(self, 'Vector Geoprocessor', 'Invalid field selection.') return #Initializations self.ui.ProgressBar.setValue(0) self.setCursor(Qt.WaitCursor) data = [] #Add new attributes to base layer bprovider = self.blayer.dataProvider() pprovider = self.player.dataProvider() pfields = pprovider.fields() for item in self.ui.listFields.selectedItems(): fname = item.text() for fld in pfields.toList(): if fname == fld.name(): newfield = QgsField() newfield.setName(fld.name()) newfield.setType(fld.type()) newfield.setTypeName(fld.typeName()) newfield.setLength(fld.length()) newfield.setPrecision(fld.precision()) newfield.setComment(fld.comment()) bprovider.addAttributes([newfield]) #Create a spatial index for faster processing spindex = QgsSpatialIndex() for pfeat in pprovider.getFeatures(): spindex.insertFeature(pfeat) #Find the intersection of process layer features with base layer #To increase speed, intersect with a bounding box rectangle first #Then further process within the geometric shape #Add requested processed information to base layer featreq = QgsFeatureRequest() bfields = bprovider.fields() ddic = {} len1 = len(self.ui.listFields.selectedItems()) len2 = len(bfields) b1 = 0 b2 = bprovider.featureCount() attr={} for bfeat in bprovider.getFeatures(): b1+=1 attr.clear() bgeom = bfeat.geometry() intersect = spindex.intersects(bgeom.boundingBox()) data[:] = [] for fid in intersect: pfeat = self.player.getFeatures(featreq.setFilterFid(fid)).next() if pfeat.geometry().intersects(bgeom) == False: data.append(fid) for fid in data: intersect.pop(intersect.index(fid)) count = 0 for item in self.ui.listFields.selectedItems(): pfindx = pprovider.fieldNameIndex(item.text()) if pfindx < 0: self.setCursor(Qt.ArrowCursor) QMessageBox.critical(self, 'Vector Geoprocessor', 'Processing error.') return data[:] = [] for fid in intersect: pfeat = self.player.getFeatures(featreq.setFilterFid(fid)).next() if self.oindex in [0,1,2,3,4]: data.append(float(pfeat.attribute(item.text()))) elif self.oindex in [5,6]: data.append(str(pfeat.attribute(item.text()))) if len(data) == 0: value = None elif self.oindex == 0: #Find mean value of points within polygons value = sum(data)/float(len(data)) elif self.oindex == 1: #Find median value of points within polygons data = sorted(data) lendata = len(data) if lendata % 2: value = data[(lendata+1)/2-1] else: d1 = data[lendata/2-1] d2 = data[lendata/2] value = (d1 + d2)/2.0 elif self.oindex == 2: #Find maximum value of points within polygons value = max(data) elif self.oindex == 3: #Find minimum value of points within polygons value = min(data) elif self.oindex == 4: #Find mean value (area-weighted) of polygons within polygons value = 0.0 totalarea = 0.0 for fid in intersect: pfeat = self.player.getFeatures(featreq.setFilterFid(fid)).next() pgeom = pfeat.geometry() isect = bgeom.intersection(pgeom) parea = isect.area() value+=(float(pfeat.attribute(item.text())*parea)) totalarea+=parea value = value / totalarea elif self.oindex == 5: #Find largest area polygon within polygons data = list(set(data)) #Get unique items in data ddic.clear() for i in data: ddic.update({i : 0.0}) for fid in intersect: pfeat = self.player.getFeatures(featreq.setFilterFid(fid)).next() pgeom = pfeat.geometry() isect = bgeom.intersection(pgeom) parea = isect.area() key = str(pfeat.attribute(item.text())) parea = parea + ddic[key] ddic.update({key : parea}) parea = -1 for key in ddic.keys(): if ddic[key] > parea: parea = ddic[key] value = key elif self.oindex == 6: #Add polygon attribute to points if len(data) != 1: QMessageBox.warning(self, 'Vector Geoprocessor', 'Point intersects more than one polygon.') value = data[0] attr.update({(len2-len1+count):value}) count+=1 result = bprovider.changeAttributeValues({bfeat.id():attr}) if not result: QMessageBox.critical(self, 'Vector Geoprocessor', 'Could not change attribute value.') return self.ui.ProgressBar.setValue(float(b1)/float(b2) * 100.0) QApplication.processEvents() self.setCursor(Qt.ArrowCursor)
def testStatistics(self): """Test zonal stats""" TEST_DATA_DIR = unitTestDataPath() + "/zonalstatistics/" myTempPath = QDir.tempPath() + "/" testDir = QDir(TEST_DATA_DIR) for f in testDir.entryList(QDir.Files): QFile.remove(myTempPath + f) QFile.copy(TEST_DATA_DIR + f, myTempPath + f) myVector = QgsVectorLayer(myTempPath + "polys.shp", "poly", "ogr") myRaster = QgsRasterLayer(myTempPath + "edge_problem.asc", "raster", "gdal") zs = QgsZonalStatistics(myVector, myRaster, "", 1, QgsZonalStatistics.All) zs.calculateStatistics(None) feat = QgsFeature() # validate statistics for each feature request = QgsFeatureRequest().setFilterFid(0) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (12.0, feat[1])) assert feat[1] == 12.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (8.0, feat[2])) assert feat[2] == 8.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.666666666666667, feat[3])) assert abs(feat[3] - 0.666666666666667) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.47140452079103201, feat[5])) assert abs(feat[5] - 0.47140452079103201) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage request.setFilterFid(1) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (9.0, feat[1])) assert feat[1] == 9.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.555555555555556, feat[3])) assert abs(feat[3] - 0.555555555555556) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.49690399499995302, feat[5])) assert abs(feat[5] - 0.49690399499995302) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage request.setFilterFid(2) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (6.0, feat[1])) assert feat[1] == 6.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.833333333333333, feat[3])) assert abs(feat[3] - 0.833333333333333) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.372677996249965, feat[5])) assert abs(feat[5] - 0.372677996249965) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage
def addDiffLayers(repo, commit, commit2, layernames): styles = [diffStylePoints, diffStyleLines, diffStylePolygons] geomTypes = ["Point","LineString","Polygon"] beforeFilename = tempFilename("gpkg") repo.exportdiff(commit.commitid, commit2.commitid, beforeFilename) afterFilename = tempFilename("gpkg") repo.exportdiff(commit2.commitid, commit.commitid, afterFilename) for layername in layernames: styles = [diffStylePoints, diffStyleLines, diffStylePolygons] geomTypes = ["Point","LineString","Polygon"] beforeLayer = loadLayerNoCrsDialog("%s|layername=%s" % (beforeFilename, layername), layername, "ogr") afterLayer = loadLayerNoCrsDialog("%s|layername=%s" % (afterFilename, layername), layername, "ogr") beforeCon = sqlite3.connect(beforeFilename) beforeCursor = beforeCon.cursor() afterCon = sqlite3.connect(afterFilename) afterCursor = afterCon.cursor() attributes = [v[1] for v in beforeCursor.execute("PRAGMA table_info('%s');" % layername)] attrnames = [f.name() for f in beforeLayer.pendingFields()] layerFeatures = [] beforeCursor.execute("SELECT * FROM %s_changes WHERE audit_op=2;" % layername) modified = beforeCursor.fetchall() for m in modified: geogigfid = m[0] beforeGpkgfid = gpkgfidFromGeogigfid(beforeCursor, layername, geogigfid) beforeCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername, beforeGpkgfid)) featureRow = beforeCursor.fetchone() attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames} attrs["changetype"] = MODIFIED_BEFORE request = QgsFeatureRequest() request.setFilterFid(beforeGpkgfid) feature = next(beforeLayer.getFeatures(request)) layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())}) afterGpkgfid = gpkgfidFromGeogigfid(afterCursor, layername, geogigfid) afterCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername,afterGpkgfid)) featureRow = afterCursor.fetchone() attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames} attrs["changetype"] = MODIFIED_AFTER request = QgsFeatureRequest() request.setFilterFid(afterGpkgfid) feature = next(afterLayer.getFeatures(request)) layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())}) afterCursor.execute("SELECT * FROM %s_changes WHERE audit_op=1;" % layername) added = afterCursor.fetchall() for a in added: geogigfid = a[0] afterGpkgfid = gpkgfidFromGeogigfid(afterCursor, layername, geogigfid) afterCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername, afterGpkgfid)) featureRow = afterCursor.fetchone() attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames} attrs["changetype"] = ADDED request = QgsFeatureRequest() request.setFilterFid(afterGpkgfid) feature = next(afterLayer.getFeatures(request)) layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())}) beforeCursor.execute("SELECT * FROM %s_changes WHERE audit_op=1;" % layername) removed = beforeCursor.fetchall() for r in removed: geogigfid = r[0] beforeGpkgfid = gpkgfidFromGeogigfid(beforeCursor, layername, geogigfid) beforeCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername, beforeGpkgfid)) featureRow = beforeCursor.fetchone() attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames} attrs["changetype"] = REMOVED request = QgsFeatureRequest() request.setFilterFid(beforeGpkgfid) feature = next(beforeLayer.getFeatures(request)) layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())}) if layerFeatures: attrnames.append("changetype") uriFields = "&".join(["field=%s" % f for f in attrnames]) uri = "%s?crs=%s&%s" % (geomTypes[beforeLayer.geometryType()], beforeLayer.crs().authid(), uriFields) layer = QgsVectorLayer(uri, "%s(diff)" % layername, "memory") featuresList = [] for feature in layerFeatures: qgsfeature = QgsFeature() qgsfeature.setGeometry(feature["geom"]) qgsfeature.setAttributes([feature["attrs"][attr] for attr in attrnames]) featuresList.append(qgsfeature) layer.dataProvider().addFeatures(featuresList) layer.updateExtents() QgsMapLayerRegistry.instance().addMapLayers([layer]) layer.loadNamedStyle(styles[layer.geometryType()])
def mapLayer_getFeatures(iface, request): """ Return information about features of the given vector layer. Retrieve information about (and, optionally, geometry of) features of the given vector layer by querying the underlying datasource programmatically. To retrieve features that were manually selected by the user within QGIS, see /qgis/mapLayer/selectedFeatures HTTP query arguments: id (optional): ID of layer from which selected features should be retrieved. If not specified, defaults to the currently active layer. geometry (optional, default false): if true, returns all feature information including their geometry in GeoJSON format. Accepts several string representations of booleans (e.g. 1, 0, true, false, yes, no, ...). orderBy (optional): expression that the results should be ordered by. If you want to order by a field, you'll have to give its name in quotes, e.g. ?orderBy="length" ascending (optional, default true): whether the results should be listen in ascending or descending order. Accepts several string representations of booleans (e.g. 1, 0, true, false, yes, no, ...). nullsfirst (optional): how null values should be treated in the ordering. Accepts several string representations of booleans (e.g. 1, 0, true, false, yes, no, ...). The different ways to filter features follow the different constructor signatures defined by the QgsFeatureRequest class, in particular: If the request is a HTTP POST request, the request body is treated as a QGIS filter expression, and the result of applying that filter is returned. If the request is a HTTP GET request, the following query arguments are considered in order, and the first one provided is applied: fid (integer): Construct a request with a QGIS feature ID filter rect (string): Construct a request with a rectangle filter. The rectangle should be specified as four numbers in the format "xmin,ymin,xmax,ymax". A GET request in which none of the arguments are specified returns ALL features of the given vector layer, which can produce very large results. Returns: If the 'geometry' argument was passed: a GeoJSON FeatureCollection with complete attribute and geometry data for all features of the layer. If the 'geometry' argument was not passed: a list of all features of the vector layer in JSON format, where each feature is an object specifying the feature's 'id' and all its 'attributes'. """ layer = qgis_layer_by_id_or_current(iface, request) # construct and run QgsFeatureRequest depending on arguments featurerequest = QgsFeatureRequest() featurerequest.addOrderBy(request.args.get('orderBy', ''), strtobool(request.args.get('ascending', 'y')), strtobool(request.args.get('nullsfirst', 'n'))) if request.command == 'POST': # POST request: complex QgsExpression passed as string featurerequest.setFilterExpression(QgsExpression(request.headers.get_payload())) else: if request.args.get('fid'): # query by feature id featurerequest.setFilterFid(int(request.args['fid'])) elif request.args.get('rect'): # query by rectangle r = [float(x) for x in request.args['rect'].split(',')] if len(r) != 4: raise ValueError('"rect" argument to getFeatures requires exactly four floats in the format "xmin,ymin,xmax,ymax"') featurerequest.setFilterRect(QgsRectangle(r[0], r[1], r[2], r[3])) result = layer.getFeatures(featurerequest) if strtobool(request.args.get('geometry', 'n')): return NetworkAPIResult(toGeoJSON(layer, result), 'application/geo+json; charset=utf-8') else: # note that the lazy QgsFeatureIterator returned here is currently # turned into a full in-memory list during conversion to JSON return NetworkAPIResult(result)
def evaluate(self): #Write parameters to GIS bfeat = QgsFeature() featreq = QgsFeatureRequest() i = 0 attr = {} for featid in self.bfeatids: i += 1 attr.clear() bfeat = next( self.sim.blayer.getFeatures(featreq.setFilterFid(featid))) for key in sorted(self.ofile.OptAttributes.keys()): bfindx = self.sim.bprovider.fieldNameIndex( self.ofile.OptAttributes[key][0]) ftype = str(self.sim.bprovider.fields()[bfindx].typeName()) if ftype in ['Integer', 'Integer64']: value = int(self.current.x[key]) elif ftype in ['Real', 'Double']: value = float(self.current.x[key]) if int(self.ofile.OptAttributes[key][4]) in [0, i]: attr.update({bfindx: value}) result = self.sim.bprovider.changeAttributeValues( {bfeat.id(): attr}) if not result: self.setCursor(Qt.ArrowCursor) QMessageBox.critical(self, 'Simulation Optimizer', 'Could not change attribute value1.') return #Can't get attribute table repainting to work for all conditions. self.sim.blayer.selectByIds(self.bfeatids) QApplication.processEvents() #Run simulations for featid in self.bfeatids: self.sim.ui.cbxOnlySelected.setChecked(1) self.sim.blayer.selectByIds([featid]) self.sim.on_btnRun_clicked() self.ui.textSimulation.append(self.sim.p.stdout) self.ui.textSimulation.append(self.sim.p.stderr) #Calculate error sqrerr = [] for featid in self.bfeatids: bfeat = next( self.sim.blayer.getFeatures(featreq.setFilterFid(featid))) for key in sorted(self.ofile.ObjAttributes.keys()): measured = float( bfeat.attribute(self.ofile.ObjAttributes[key][0])) simulated = float( bfeat.attribute(self.ofile.ObjAttributes[key][1])) factor = float(self.ofile.ObjAttributes[key][2]) error = (simulated - measured) * factor #error = (simulated - measured) / measured #error = (simulated - measured) sqrerr.append(error * error) sumsq = sum(sqrerr) / len(sqrerr) rmse = math.sqrt(sumsq) #Output string = '%4d ' % self.iterat string += '%11.5f ' % self.T string += '%5d ' % self.feval string += '%5.3f ' % self.p string += '%4d ' % self.accepted string += '%4d ' % self.declined if self.best.cost: string += ('%10.4f ' % self.best.cost) else: string += ('%10.4f ' % rmse) string += ('%10.4f ' % rmse) for i in self.best.x: string += '%10.4f ' % i for i in self.current.x: string += '%10.4f ' % i self.ui.textOptimization.append(string) f = open(self.logfile, 'a') f.write(string + '\n') f.close() return rmse
def processAlgorithm(self, progress): radius = self.getParameterValue(self.DISTANCE) horizontal = self.getParameterValue(self.HORIZONTAL) output = self.getOutputFromName(self.OUTPUT_LAYER) layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_LAYER)) writer = output.getVectorWriter(layer.fields(), layer.wkbType(), layer.crs()) features = vector.features(layer) total = 100.0 / len(features) if len(features) > 0 else 1 duplicates = dict() for current, f in enumerate(features): wkt = f.geometry().exportToWkt() if wkt not in duplicates: duplicates[wkt] = [f.id()] else: duplicates[wkt].extend([f.id()]) progress.setPercentage(int(current * total)) current = 0 total = 100.0 / len(duplicates) if len(duplicates) > 0 else 1 progress.setPercentage(0) fullPerimeter = 2 * math.pi request = QgsFeatureRequest() for (geom, fids) in duplicates.iteritems(): count = len(fids) if count == 1: f = layer.getFeatures(request.setFilterFid(fids[0])).next() writer.addFeature(f) else: angleStep = fullPerimeter / count if count == 2 and horizontal: currentAngle = math.pi / 2 else: currentAngle = 0 old_point = QgsGeometry.fromWkt(geom).asPoint() for fid in fids: sinusCurrentAngle = math.sin(currentAngle) cosinusCurrentAngle = math.cos(currentAngle) dx = radius * sinusCurrentAngle dy = radius * cosinusCurrentAngle f = layer.getFeatures(request.setFilterFid(fid)).next() new_point = QgsPoint(old_point.x() + dx, old_point.y() + dy) out_feature = QgsFeature() out_feature.setGeometry(QgsGeometry.fromPoint(new_point)) out_feature.setAttributes(f.attributes()) writer.addFeature(out_feature) currentAngle += angleStep current += 1 progress.setPercentage(int(current * total)) del writer
def run_checks(): self.assertEqual([f.name() for f in vl.fields()], ['fid', 'type', 'value']) # expression req = QgsFeatureRequest() req.setFilterExpression("value=16") it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter fid req = QgsFeatureRequest() req.setFilterFid(5) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter fids req = QgsFeatureRequest() req.setFilterFids([5]) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # check with subset of attributes req = QgsFeatureRequest() req.setFilterFids([5]) req.setSubsetOfAttributes([2]) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes()[2], 16) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter rect and expression req = QgsFeatureRequest() req.setFilterExpression("value=16 or value=14") req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5)) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter rect and fids req = QgsFeatureRequest() req.setFilterFids([3, 5]) req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5)) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # Ensure that orig_ogc_fid is still retrieved even if attribute subset is passed req = QgsFeatureRequest() req.setSubsetOfAttributes([]) it = vl.getFeatures(req) ids = [] geoms = {} while it.nextFeature(f): ids.append(f.id()) geoms[f.id()] = f.geometry().asWkt() self.assertCountEqual(ids, [3, 4, 5]) self.assertEqual(geoms, {3: 'Point (3 3)', 4: 'Point (4 4)', 5: 'Point (5 5)'})
def processAlgorithm(self, progress): network = dataobjects.getObjectFromUri( self.getParameterValue(self.NETWORK_LAYER)) # Ensure that nodes already indexed idxDownNodeId = findField(network, 'DownNodeId') idxUpNodeId = findField(network, 'UpNodeId') if idxDownNodeId == -1 or idxUpNodeId == -1: raise GeoAlgorithmExecutionException( self.tr('Seems nodes are not indexed. Please run node ' 'indexing tool first and try again.')) # First add new fields to the network layer networkProvider = network.dataProvider() (idxDownArcId, fieldList) = findOrCreateField(network, network.pendingFields(), 'DownArcId', QVariant.Int, 10, 0) (idxUpArcId, fieldList) = findOrCreateField(network, fieldList, 'UpArcId', QVariant.String, 250, 0) (idxLength, fieldList) = findOrCreateField(network, fieldList, 'Length', QVariant.Double, 20, 6) (idxLenDown, fieldList) = findOrCreateField(network, fieldList, 'LengthDown', QVariant.Double, 20, 6) (idxLenUp, fieldList) = findOrCreateField(network, fieldList, 'LengthUp', QVariant.Double, 20, 6) writer = self.getOutputFromName(self.UPDOWN_LAYER).getVectorWriter( fieldList.toList(), networkProvider.geometryType(), networkProvider.crs()) # Generate helper dictionaries myNetwork, arcsPerNodeId = makeHelperDictionaries(network) # Write output file for f in network.getFeatures(): writer.addFeature(f) del writer vl = QgsVectorLayer(self.getOutputValue(self.UPDOWN_LAYER), 'tmp', 'ogr') provider = vl.dataProvider() for f in vl.getFeatures(): fid = f.id() # Determine upstream node id upNodeId = f['UpNodeId'] attrs = {idxDownArcId:fid} changes = dict() ids = [] # Iterate over all arcs connected to the upstream node with # given id, skipping current arc for i in arcsPerNodeId[upNodeId]: if i != fid: # Modify DownArcId changes[i] = attrs # Collect ids of the arcs located upstream ids.append(str(i)) provider.changeAttributeValues(changes) provider.changeAttributeValues({fid:{idxUpArcId:','.join(ids)}}) # Also calculate length of the current arc provider.changeAttributeValues({fid:{idxLength:f.geometry().length()}}) # Calculate length upstream for arcs # Algorithm at pages 61-62 "Automated AGQ4Vector Watershed.pdf" progress.setInfo(self.tr('Calculating length upstream...')) req = QgsFeatureRequest() # Iterate over upsteram node ids starting from the last ones # which represents source arcs for nodeId in sorted(myNetwork.keys(), reverse=True): f = vl.getFeatures(req.setFilterFid(myNetwork[nodeId])).next() arcLen = f['Length'] if f['Length'] else 0.0 upstreamArcs = f['UpArcId'] if not upstreamArcs: provider.changeAttributeValues({f.id():{idxLenUp: arcLen}}) else: length = [] for i in upstreamArcs.split(','): f = vl.getFeatures(req.setFilterFid(int(i))).next() if f['LengthUp']: length.append(f['LengthUp']) upLen = max(length) if len(length) > 0 else 0.0 provider.changeAttributeValues({myNetwork[nodeId]:{idxLenUp:arcLen + upLen}}) # Calculate length downstream for arcs # Algorithm at pages 62-63 "Automated AGQ4Vector Watershed.pdf" progress.setInfo(self.tr('Calculating length downstream...')) first = True # Iterate over upsteram node ids starting from the first one # which represents downstream node of the outlet arc for nodeId in sorted(myNetwork.keys()): f = vl.getFeatures(req.setFilterFid(myNetwork[nodeId])).next() # for outlet arc downstream length set to zero if first: provider.changeAttributeValues({myNetwork[nodeId]:{idxLenDown:0.0}}) first = False continue arcLen = f['Length'] if f['Length'] else 0.0 downArcId = f['DownArcId'] f = vl.getFeatures(req.setFilterFid(downArcId)).next() lenDown = f['LengthDown'] if f['LengthDown'] else 0.0 provider.changeAttributeValues({myNetwork[nodeId]:{idxLenDown: arcLen + lenDown}})
def on_btnRun_clicked(self): #Initializations b1 = 0 self.ui.ProgressBar.setValue(0) self.setCursor(Qt.WaitCursor) featreq = QgsFeatureRequest() if self.ui.cbxOnlySelected.isChecked(): self.selectedIDs = self.sim.blayer.selectedFeatureIds() else: self.selectedIDs = [] for bfeat in self.sim.bprovider.getFeatures(): self.selectedIDs.append(bfeat.id()) self.selectedIDs.sort() b2 = len(self.selectedIDs) #Set up optimization and run x0 = [] lower = [] upper = [] if self.ui.cbxDoGroup.isChecked(): for key in sorted(self.ofile.OptAttributes.keys()): x0.append(float(self.ofile.OptAttributes[key][1])) lower.append(float(self.ofile.OptAttributes[key][2])) upper.append(float(self.ofile.OptAttributes[key][3])) string = 'Optimizing grouped features\n' string += 'Iter Temperature Eval Prob Acc Dec BestEval CurEval Parameters....' f = open(self.logfile, 'a') f.write(string + '\n') f.close() self.ui.textOptimization.append(string) opt = Optimize(x0, lower, upper, T0=self.ofile.T0, Tf=self.ofile.Tf, dwell=self.ofile.dwell, feps=self.ofile.feps, maxeval=self.ofile.maxeval, maxiter=self.ofile.maxiter, maxaccept=self.ofile.maxaccept, m=self.ofile.m, n=self.ofile.n, quench=self.ofile.quench, boltzmann=self.ofile.boltzmann) opt.init(self.sim, self.selectedIDs, self.ui, self.ofile, self.logfile, self.iface) solution = opt.run() self.UpdateGIS(solution, self.selectedIDs) self.WriteResult(solution) self.ui.ProgressBar.setValue(float(b2) / float(b2) * 100.0) else: #Run optimization for individual features for featid in self.selectedIDs: b1 += 1 x0[:] = [] lower[:] = [] upper[:] = [] bfeat = next( self.sim.blayer.getFeatures(featreq.setFilterFid(featid))) for key in sorted(self.ofile.OptAttributes.keys()): x0.append(float(self.ofile.OptAttributes[key][1])) lower.append(float(self.ofile.OptAttributes[key][2])) upper.append(float(self.ofile.OptAttributes[key][3])) string = 'Optimizing feature ID#: %d\n' % featid string += 'Iter Temperature Eval Prob Acc Dec BestEval CurEval Parameters....' f = open(self.logfile, 'a') f.write(string + '\n') f.close() self.ui.textOptimization.append(string) opt = Optimize(x0, lower, upper, T0=self.ofile.T0, Tf=self.ofile.Tf, dwell=self.ofile.dwell, feps=self.ofile.feps, maxeval=self.ofile.maxeval, maxiter=self.ofile.maxiter, maxaccept=self.ofile.maxaccept, m=self.ofile.m, n=self.ofile.n, quench=self.ofile.quench, boltzmann=self.ofile.boltzmann) opt.init(self.sim, [bfeat.id()], self.ui, self.ofile, self.logfile, self.iface) solution = opt.run() self.UpdateGIS(solution, [bfeat.id()]) self.WriteResult(solution) self.ui.ProgressBar.setValue(float(b1) / float(b2) * 100.0) if self.ui.cbxOnlySelected.isChecked(): self.sim.blayer.selectByIds(self.selectedIDs) else: self.sim.blayer.removeSelection() self.setCursor(Qt.ArrowCursor)
def run_checks(): self.assertEqual([f.name() for f in vl.fields()], ['fid', 'type', 'value']) # expression req = QgsFeatureRequest() req.setFilterExpression("value=16") it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter fid req = QgsFeatureRequest() req.setFilterFid(5) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter fids req = QgsFeatureRequest() req.setFilterFids([5]) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # check with subset of attributes req = QgsFeatureRequest() req.setFilterFids([5]) req.setSubsetOfAttributes([2]) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes()[2], 16) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter rect and expression req = QgsFeatureRequest() req.setFilterExpression("value=16 or value=14") req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5)) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter rect and fids req = QgsFeatureRequest() req.setFilterFids([3, 5]) req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5)) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # Ensure that orig_ogc_fid is still retrieved even if attribute subset is passed req = QgsFeatureRequest() req.setSubsetOfAttributes([]) it = vl.getFeatures(req) ids = [] geoms = {} while it.nextFeature(f): ids.append(f.id()) geoms[f.id()] = f.geometry().asWkt() self.assertCountEqual(ids, [3, 4, 5]) self.assertEqual(geoms, { 3: 'Point (3 3)', 4: 'Point (4 4)', 5: 'Point (5 5)' })
def 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) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, source.sourceCrs()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 featureCount = source.featureCount() total = 100.0 / pointCount if pointCount else 1 index = QgsSpatialIndex() points = dict() da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs(), context.transformContext()) da.setEllipsoid(context.project().ellipsoid()) request = QgsFeatureRequest() random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break # pick random feature fid = random.randint(0, featureCount - 1) f = next(source.getFeatures(request.setFilterFid(fid).setSubsetOfAttributes([]))) fGeom = f.geometry() if fGeom.isMultipart(): lines = fGeom.asMultiPolyline() # pick random line lineId = random.randint(0, len(lines) - 1) vertices = lines[lineId] else: vertices = fGeom.asPolyline() # pick random segment if len(vertices) == 2: vid = 0 else: vid = random.randint(0, len(vertices) - 2) startPoint = vertices[vid] endPoint = vertices[vid + 1] length = da.measureLine(startPoint, endPoint) dist = length * random.random() if dist > minDistance: d = dist / (length - dist) rx = (startPoint.x() + d * endPoint.x()) / (1 + d) ry = (startPoint.y() + d * endPoint.y()) / (1 + d) # generate random point p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPointXY(p) if vector.checkMinDistance(p, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.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 testStatistics(self): """Test zonal stats""" TEST_DATA_DIR = unitTestDataPath() + "/zonalstatistics/" myTempPath = QDir.tempPath() + "/" testDir = QDir(TEST_DATA_DIR) for f in testDir.entryList(QDir.Files): QFile.remove(myTempPath + f) QFile.copy(TEST_DATA_DIR + f, myTempPath + f) myVector = QgsVectorLayer(myTempPath + "polys.shp", "poly", "ogr") myRaster = QgsRasterLayer(myTempPath + "edge_problem.asc", "raster", "gdal") zs = QgsZonalStatistics(myVector, myRaster, "", 1, QgsZonalStatistics.All) zs.calculateStatistics(None) feat = QgsFeature() # validate statistics for each feature request = QgsFeatureRequest().setFilterFid(0) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (12.0, feat[1])) assert feat[1] == 12.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (8.0, feat[2])) assert feat[2] == 8.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.666666666666667, feat[3])) assert abs(feat[3] - 0.666666666666667) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.47140452079103201, feat[5])) assert abs(feat[5] - 0.47140452079103201) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage request.setFilterFid(1) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (9.0, feat[1])) assert feat[1] == 9.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.555555555555556, feat[3])) assert abs(feat[3] - 0.555555555555556) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.49690399499995302, feat[5])) assert abs(feat[5] - 0.49690399499995302) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage request.setFilterFid(2) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (6.0, feat[1])) assert feat[1] == 6.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.833333333333333, feat[3])) assert abs(feat[3] - 0.833333333333333) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.372677996249965, feat[5])) assert abs(feat[5] - 0.372677996249965) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage
def processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString( self.getParameterValue(self.VECTOR), context) pointCount = float(self.getParameterValue(self.POINT_NUMBER)) minDistance = float(self.getParameterValue(self.MIN_DISTANCE)) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QgsWkbTypes.Point, layer.crs(), context) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 featureCount = layer.featureCount() total = 100.0 / pointCount index = QgsSpatialIndex() points = dict() da = QgsDistanceArea() request = QgsFeatureRequest() random.seed() while nIterations < maxIterations and nPoints < pointCount: # pick random feature fid = random.randint(0, featureCount - 1) f = next( layer.getFeatures( request.setFilterFid(fid).setSubsetOfAttributes([]))) fGeom = f.geometry() if fGeom.isMultipart(): lines = fGeom.asMultiPolyline() # pick random line lineId = random.randint(0, len(lines) - 1) vertices = lines[lineId] else: vertices = fGeom.asPolyline() # pick random segment if len(vertices) == 2: vid = 0 else: vid = random.randint(0, len(vertices) - 2) startPoint = vertices[vid] endPoint = vertices[vid + 1] length = da.measureLine(startPoint, endPoint) dist = length * random.random() if dist > minDistance: d = dist / (length - dist) rx = (startPoint.x() + d * endPoint.x()) / (1 + d) ry = (startPoint.y() + d * endPoint.y()) / (1 + d) # generate random point pnt = QgsPointXY(rx, ry) geom = QgsGeometry.fromPoint(pnt) if vector.checkMinDistance(pnt, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) writer.addFeature(f) index.insertFeature(f) points[nPoints] = pnt nPoints += 1 feedback.setProgress(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: QgsMessageLog.logMessage( self.tr('Can not generate requested number of random points. ' 'Maximum number of attempts exceeded.'), self.tr('Processing'), QgsMessageLog.INFO) del writer
def processAlgorithm(self, parameters, context, feedback): t_troncon = self.parameterAsSource(parameters, self.SEGMENTS_TABLE, context) g_troncon = self.parameterAsSource(parameters, self.GEOM_SEGMENTS, context) t_obs = self.parameterAsSource(parameters, self.OBSERVATION_TABLE, context) g_obs = self.parameterAsVectorLayer(parameters, self.GEOM_OBSERVATION, context) # Get troncon ids and file ids exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope(t_troncon.createExpressionContextScope()) exp_str = '"id_geom_troncon" IS NOT NULL' exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression %s has eval error: %s').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) request.setSubsetOfAttributes( ['id', 'aab', 'aad', 'aaf', 'abq', 'id_file', 'id_geom_troncon'], t_troncon.fields()) has_geo_troncon = False troncons = {} file_ids = [] for tro in t_troncon.getFeatures(request): troncons[tro['id']] = tro file_ids.append(tro['id_file']) has_geo_troncon = True # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.OBSERVATIONS_CREATED: None} if not has_geo_troncon: raise QgsProcessingException(tr('* ERROR: No troncon geometries')) # Get observation ids exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope(t_obs.createExpressionContextScope()) exp_str = ('"id_troncon" IN ({}) AND ' '"id_file" IN ({})').format( ','.join([str(i) for i in troncons.keys()]), ','.join([str(i) for i in file_ids])) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) obs_ids = [] request = QgsFeatureRequest(exp, exp_context) for obs in t_obs.getFeatures(request): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.OBSERVATIONS_CREATED: None} troncon = troncons[obs['id_troncon']] # verifying ITV file if troncon['id_file'] != obs['id_file']: continue obs_ids.append(obs['id']) if not obs_ids: raise QgsProcessingException( tr('* ERROR: No observations to geolocalize found')) # Check observations already geolocalised on troncon exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope(QgsExpressionContextUtils.layerScope(g_obs)) exp_str = '"id" IN ({})'.format(','.join([str(i) for i in obs_ids])) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) geo_observations = [] for obs in g_obs.getFeatures(request): geo_observations.append(obs['id']) # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.OBSERVATIONS_CREATED: None} # build observation geometry based on table exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope(t_obs.createExpressionContextScope()) exp_str = ('"id_troncon" IN ({}) AND ' '"id_file" IN ({})').format( ','.join([str(i) for i in troncons.keys()]), ','.join([str(i) for i in file_ids])) if geo_observations: exp_str += ' AND id NOT IN ({})'.format(','.join( [str(i) for i in geo_observations])) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) features = [] fields = provider_fields(g_obs.fields()) for obs in t_obs.getFeatures(request): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.OBSERVATIONS_CREATED: None} troncon = troncons[obs['id_troncon']] # verifying ITV file if troncon['id_file'] != obs['id_file']: continue geo_req = QgsFeatureRequest() geo_req.setFilterFid(troncon['id_geom_troncon']) for g_tro in g_troncon.getFeatures(geo_req): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.OBSERVATIONS_CREATED: None} geom = g_tro.geometry() pt = None if troncon['aab'] == troncon['aad']: pt = geom.interpolate(geom.length() * obs['i'] / troncon['abq']) else: pt = geom.interpolate(geom.length() * (1 - obs['i'] / troncon['abq'])) fet = QgsFeature(fields) fet.setGeometry(pt) fet.setAttribute('id', obs['id']) features.append(fet) # Ajout des objets observations if features: g_obs.startEditing() (res, outFeats) = g_obs.dataProvider().addFeatures(features) if not res or not outFeats: raise QgsProcessingException( tr('* ERREUR: lors de l\'enregistrement ' 'des regards {}').format(', '.join( g_obs.dataProvider().errors()))) if not g_obs.commitChanges(): raise QgsProcessingException( tr('* ERROR: Commit {}.').format(g_obs.commitErrors())) # Returns empty dict if no outputs return {self.OBSERVATIONS_CREATED: len(features)}