def prepare_constraint_lines(self, parameters, context, feedback): sections = self.parameterAsSource(parameters, self.SECTIONS, context) # Merge constraint lines files outputs = processing.run( "native:mergevectorlayers", { "LAYERS": parameters[self.CONSTRAINT_LINES], "CRS": sections.sourceCrs(), "OUTPUT": QgsProcessingUtils.generateTempFilename( "constraint_lines.shp"), }, context=context, feedback=feedback, is_child_algorithm=True, ) constraint_lines = outputs["OUTPUT"] feedback.setCurrentStep(2) if feedback.isCanceled(): return {} # Add lines with first and last points of sections request = QgsFeatureRequest() request.addOrderBy('"sec_id"', True, True) request.addOrderBy('"p_id"', True, True) previous_sec_id = None previous_point = None left_line = QgsLineString() right_line = QgsLineString() total = total = (100.0 / sections.featureCount() if sections.featureCount() else 0) for current, f in enumerate(sections.getFeatures(request)): if previous_sec_id is None or previous_sec_id != f.attribute( "sec_id"): if previous_sec_id is not None: right_line.addVertex(previous_point) left_line.addVertex(f.geometry().constGet()) previous_sec_id = f.attribute("sec_id") previous_point = f.geometry().constGet() feedback.setProgress(int(current * total)) right_line.addVertex(previous_point) constraint_lines_layer = QgsVectorLayer(constraint_lines, "constraint_lines", "ogr") dp = constraint_lines_layer.dataProvider() left = QgsFeature() left.setGeometry(QgsGeometry(left_line)) right = QgsFeature() right.setGeometry(QgsGeometry(right_line)) dp.addFeatures([left, right]) return constraint_lines
def setLayer(self, layer): self.beginResetModel() self.clear() if layer is None: return sec_name_index = layer.fields().indexFromName("sec_name") request = QgsFeatureRequest() request.addOrderBy("sec_id") request.setSubsetOfAttributes([sec_name_index]) previous_f_id = None previous_item = None for f in layer.getFeatures(request): item = SectionItem( f.attribute(sec_name_index), f.id(), previous_f_id, ) if previous_item is not None: previous_item.set_next_f_id(f.id()) self.appendRow(item) previous_f_id = f.id() previous_item = item self.endResetModel()
def __build_data(self): req = QgsFeatureRequest() if self.__filter_expression is not None: req.setFilterExpression(self.__filter_expression) # Get unit of the first feature if needed if self.__uom is not None and self.__uom.startswith("@"): req2 = QgsFeatureRequest(req) req2.setLimit(1) for f in self.__layer.getFeatures(req): self.__uom = f[self.__uom[1:]] break req.setSubsetOfAttributes([self.__x_fieldname, self.__y_fieldname], self.__layer.fields()) # Do not forget to add an index on this field to speed up ordering req.addOrderBy(self.__x_fieldname) xy_values = [ (f[self.__x_fieldname], f[self.__y_fieldname] if f[self.__y_fieldname] is not None else self.__nodata_value) for f in self.__layer.getFeatures(req) ] self.__x_values = [coord[0] for coord in xy_values] self.__y_values = [coord[1] for coord in xy_values] self.__x_min, self.__x_max = (min(self.__x_values), max( self.__x_values)) if self.__x_values else (None, None) self.__y_min, self.__y_max = (min(self.__y_values), max( self.__y_values)) if self.__y_values else (None, None) self.data_modified.emit()
def insert_scenario(layer: QgsVectorLayer, name: str) -> int: """ Insert the new scenario and get its ID. """ feature = QgsFeature(layer.fields()) feature.setAttribute('nom', name) with edit(layer): layer.addFeature(feature) request = QgsFeatureRequest() request.setLimit(1) request.addOrderBy('id', False) feature = QgsFeature() layer.getFeatures(request).nextFeature(feature) return feature['id']
def __build_data(self): req = QgsFeatureRequest() if self.__filter_expression is not None: req.setFilterExpression(self.__filter_expression) # Get unit of the first feature if needed if self.__uom is not None and self.__uom.startswith("@"): request_unit = QgsFeatureRequest(req) request_unit.setLimit(1) for f in self.__layer.getFeatures(request_unit): self.__uom = f[self.__uom[1:]] break req.setSubsetOfAttributes([self.__x_fieldname, self.__y_fieldname], self.__layer.fields()) # Do not forget to add an index on this field to speed up ordering req.addOrderBy(self.__x_fieldname) def is_null(v): return isinstance(v, QVariant) and v.isNull() if self.__nodata_value is not None: # replace null values by a 'Nodata' value xy_values = [ (f[self.__x_fieldname], f[self.__y_fieldname] if not is_null(f[self.__y_fieldname]) else self.__nodata_value) for f in self.__layer.getFeatures(req) ] else: # do not include null values xy_values = [(f[self.__x_fieldname], f[self.__y_fieldname]) for f in self.__layer.getFeatures(req) if not is_null(f[self.__y_fieldname])] self.__x_values = [coord[0] for coord in xy_values] self.__y_values = [coord[1] for coord in xy_values] self.__x_min, self.__x_max = (min(self.__x_values), max( self.__x_values)) if self.__x_values else (None, None) self.__y_min, self.__y_max = (min(self.__y_values), max( self.__y_values)) if self.__y_values else (None, None) self.data_modified.emit()
def search_data_source(self, search_expression, sort_map): """ Searches the data source using the specified search expression. :param search_expression: Search expression either as a string or instance of QgsExpression. :type search_expression: str or QgsExpression :param sort_map: List containing a definition of column sorting. :type sort_map: list :return: Returns a list containing search results consisting of QgsFeature objects. :rtype: list """ results = [] if not self._vector_layer.isValid(): raise FltsSearchException( 'Search cannot be performed, data source is invalid.') if isinstance(search_expression, basestring): search_expression = QgsExpression(search_expression) # Assert if there are errors in the expression if search_expression.hasParserError(): raise FltsSearchException(search_expression.parserErrorString()) fr = QgsFeatureRequest(search_expression) if not self._config.limit: limit = -1 else: limit = self._config.limit fr.setLimit(limit) # Set sorting if specified. if sort_map: for s in sort_map: ascending = True if s[1] == 0 else False fr.addOrderBy(s[0], ascending) feat_iter = self._vector_layer.getFeatures(fr) for f in feat_iter: results.append(f) return results
def limit_features(self, new_feature): feature_count = self.pr.featureCount() if feature_count < self.limit: self.pr.addFeatures([new_feature]) progress = (feature_count * 100) / self.limit self.dlg.streamingPb.setValue(progress) else: self.dlg.streamingPb.setRange(0, 0) feats_request = QgsFeatureRequest() feats_request.addOrderBy('time', ascending=False) feats_request.setLimit(2000) features_iterator = self.pr.getFeatures(feats_request) if not features_iterator.isValid(): return last_feature = next( itertools.islice(features_iterator, feature_count - 1, feature_count)) last_feature_id = last_feature.id() self.startEditing() self.deleteFeature(last_feature_id) self.pr.addFeatures([new_feature])
def _populate_cache(self): req = QgsFeatureRequest() filter = self.__filter_expression or "" if filter: filter += " and " filter += "{} >= {} and {} <= {}".format(self.__min_x_field, self.__data_rect.x(), self.__max_x_field, self.__data_rect.right()) req.setFilterExpression(filter) req.setSubsetOfAttributes( [self.__min_x_field, self.__max_x_field, self.__y_field], self.__layer.fields()) req.addOrderBy(self.__min_x_field) # reset cache for picking self.__min_x_values = [] self.__max_x_values = [] self.__y_values = [] for f in self.__layer.getFeatures(req): self.__min_x_values.append(f[self.__min_x_field]) self.__max_x_values.append(f[self.__max_x_field]) self.__y_values.append(f[self.__y_field])
def generateFeatureRequest(self): ''' :return: A QgQgsFeatureRequests object with the orders defined in form ''' featureRequest = QgsFeatureRequest() field1 = self.fieldSelectCB.currentField() ascending1 = self.sortOrderCB.isChecked() if field1 != '': featureRequest.addOrderBy(field1, ascending1) field2 = self.fieldSelectCB2.currentField() ascending2 = self.sortOrderCB2.isChecked() if field2 != '': featureRequest.addOrderBy(field2, ascending2, True) field3 = self.fieldSelectCB3.currentField() ascending3 = self.sortOrderCB3.isChecked() if field3 != '': featureRequest.addOrderBy(field3, ascending3, True) return featureRequest
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) request = QgsFeatureRequest() request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes(self.fields, source.fields()) request.addOrderBy("|| ' - ' || ".join(self.fields)) unique_couples = [] non_unique_couples = [] for src_feature in source.getFeatures(request): couple = (src_feature[self.fields[0]], src_feature[self.fields[1]]) if couple not in unique_couples: unique_couples.append(couple) else: non_unique_couples.append(couple) if not non_unique_couples: feedback.pushInfo( 'L\'ensemble des couples noms/faciès sont uniques') _, dest_id = self.parameterAsSink(parameters, self.OUTPUT, context, source.fields(), source.wkbType(), source.sourceCrs()) return { self.OUTPUT: dest_id, self.NUMBER_OF_UNIQUE: len(unique_couples), self.NUMBER_OF_NON_UNIQUE: 0 } feedback.pushInfo('Certains couples ne sont pas uniques :') for couple in non_unique_couples: feedback.pushInfo(' {} - {}'.format(couple[0], couple[1])) expressions = [] for couple in non_unique_couples: exp = ' AND '.join([ QgsExpression.createFieldEqualityExpression( self.fields[0], couple[0]), QgsExpression.createFieldEqualityExpression( self.fields[1], couple[1]) ]) expressions.append(exp) exp = '(' exp += ') OR ('.join(expressions) exp += ')' feedback.pushDebugInfo(exp) exp_context = self.createExpressionContext(parameters, context, source) request = QgsFeatureRequest() request.setFilterExpression(exp) request.setExpressionContext(exp_context) layer = source.materialize(request) params = { 'ALL_PARTS': True, 'INPUT': layer, 'OUTPUT': 'TEMPORARY_OUTPUT' } results = processing.run( "native:pointonsurface", params, context=context, feedback=feedback, is_child_algorithm=True, ) params = { 'INPUT': results['OUTPUT'], 'FIELD': self.fields, 'OUTPUT': parameters[self.OUTPUT] } results = processing.run( "native:collect", params, context=context, feedback=feedback, is_child_algorithm=True, ) output_layer = results['OUTPUT'] if context.willLoadLayerOnCompletion(output_layer): layer_details = context.layerToLoadOnCompletionDetails( output_layer) output_def = self.parameterDefinition(self.OUTPUT) layer_details.name = output_def.description() layer_details.setPostProcessor( SetLabelingPostProcessor.create(self.fields)) return { self.OUTPUT: output_layer, self.NUMBER_OF_UNIQUE: len(unique_couples), self.NUMBER_OF_NON_UNIQUE: len(non_unique_couples) }
def test_add_feature_geometry(self): """ Test to add a feature with a geometry """ vl_pipes = QgsVectorLayer( self.dbconn + ' sslmode=disable key=\'pk\' table="qgis_test"."pipes" (geom) sql=', 'pipes', 'postgres') vl_leaks = QgsVectorLayer( self.dbconn + ' sslmode=disable key=\'pk\' table="qgis_test"."leaks" (geom) sql=', 'leaks', 'postgres') vl_leaks.startEditing() QgsProject.instance().addMapLayer(vl_pipes) QgsProject.instance().addMapLayer(vl_leaks) self.assertEqual(vl_pipes.featureCount(), 2) self.assertEqual(vl_leaks.featureCount(), 3) rel = QgsRelation() rel.setReferencingLayer(vl_leaks.id()) rel.setReferencedLayer(vl_pipes.id()) rel.addFieldPair('pipe', 'id') rel.setId('rel_pipe_leak') self.assertTrue(rel.isValid()) self.relMgr.addRelation(rel) # Mock vector layer tool to just set default value on created feature class DummyVlTools(QgsVectorLayerTools): def addFeature(self, layer, defaultValues, defaultGeometry): f = QgsFeature(layer.fields()) for idx, value in defaultValues.items(): f.setAttribute(idx, value) f.setGeometry(defaultGeometry) ok = layer.addFeature(f) return ok, f wrapper = QgsRelationWidgetWrapper(vl_leaks, rel) context = QgsAttributeEditorContext() vltool = DummyVlTools() context.setVectorLayerTools(vltool) context.setMapCanvas(self.mapCanvas) cadDockWidget = QgsAdvancedDigitizingDockWidget(self.mapCanvas) context.setCadDockWidget(cadDockWidget) wrapper.setContext(context) widget = wrapper.widget() widget.show() pipe = next(vl_pipes.getFeatures()) self.assertEqual(pipe.id(), 1) wrapper.setFeature(pipe) table_view = widget.findChild(QTableView) self.assertEqual(table_view.model().rowCount(), 1) btn = widget.findChild(QToolButton, 'mAddFeatureGeometryButton') self.assertTrue(btn.isVisible()) self.assertTrue(btn.isEnabled()) btn.click() self.assertTrue(self.mapCanvas.mapTool()) feature = QgsFeature(vl_leaks.fields()) feature.setGeometry(QgsGeometry.fromWkt('POINT(0 0.8)')) self.mapCanvas.mapTool().digitizingCompleted.emit(feature) self.assertEqual(table_view.model().rowCount(), 2) self.assertEqual(vl_leaks.featureCount(), 4) request = QgsFeatureRequest() request.addOrderBy("id", False) # get new created feature feat = next(vl_leaks.getFeatures('"id" is NULL')) self.assertTrue(feat.isValid()) self.assertTrue(feat.geometry().equals( QgsGeometry.fromWkt('POINT(0 0.8)'))) vl_leaks.rollBack()
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) name_field_name = self.parameterAsString(parameters, self.NAME_FIELD, context) elevation_field_name = self.parameterAsString(parameters, self.ELEVATION_FIELD, context) name_field_index = source.fields().lookupField(name_field_name) elevation_field_index = source.fields().lookupField( elevation_field_name) request = QgsFeatureRequest() request.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326'), context.transformContext()) expression_string = self.parameterAsString(parameters, self.ORDERBY_EXPRESSION, context) if expression_string: expression = QgsExpression(expression_string) if expression.hasParserError(): raise QgsProcessingException(expression.parserErrorString()) request.addOrderBy(expression_string) departure_point = QgsPointXY() destination_point = QgsPointXY() user_points = '' total = 100.0 / source.featureCount() if source.featureCount() else 0 features = source.getFeatures(request) for current, feature in enumerate(features): if feedback.isCanceled(): break if not feature.hasGeometry(): continue point = feature.geometry().asPoint() if departure_point.isEmpty(): departure_point = point destination_point = point name = 'UNTITLED' if name_field_index >= 0: name = feature[name_field_index] name = re.sub('[^0-9A-Za-z_]', '', re.sub('\s+', '_', name)) elevation = 1000.0 if elevation_field_index >= 0: elevation = feature[elevation_field_index] user_points += ' <ATCWaypoint id="{}">\n <ATCWaypointType>User</ATCWaypointType>\n <WorldPosition>{}</WorldPosition>\n </ATCWaypoint>\n'.format( name, self.formattedCoordinateElevation(point, elevation)) feedback.setProgress(int(current * total)) if departure_point.isEmpty(): raise QgsProcessingException('Error: departure point is missing') if destination_point.isEmpty(): raise QgsProcessingException('Error: destination point is missing') strips = QgsVectorLayer( os.path.join(os.path.dirname(__file__), 'data', 'strips.gpkg'), 'strips') index = QgsSpatialIndex(strips.getFeatures()) icao_index = strips.fields().lookupField('icao') name_short_index = strips.fields().lookupField('nameshort') departure_airport = self.parameterAsString(parameters, self.DEPARTURE_AIRPORT, context) if departure_airport: feature = QgsFeature() expression = QgsExpression( "icao ILIKE '{}'".format(departure_airport)) strips.getFeatures( QgsFeatureRequest(expression)).nextFeature(feature) if feature: departure_point = feature.geometry().asPoint() else: raise QgsProcessingException( 'Error: custom departure airport ICAO ID not found') destination_airport = self.parameterAsString(parameters, self.DESTINATION_AIRPORT, context) if destination_airport: feature = QgsFeature() expression = QgsExpression( "icao ILIKE '{}'".format(destination_airport)) strips.getFeatures( QgsFeatureRequest(expression)).nextFeature(feature) if feature: destination_point = feature.geometry().asPoint() else: raise QgsProcessingException( 'Error: custom destination airport ICAO ID not found') departure = '' departure_header = '' destination = '' destination_header = '' if not departure_point.isEmpty(): departure_id = index.nearestNeighbor(departure_point) feature = strips.getFeature(departure_id[0]) point = feature.geometry().asPoint() elevation = 50.0 departure = ' <ATCWaypoint id="{}">\n <ATCWaypointType>Airport</ATCWaypointType>\n <WorldPosition>{}</WorldPosition>\n <RunwayNumberFP>1</RunwayNumberFP>\n <ICAO>\n <ICAOIdent>{}</ICAOIdent>\n </ICAO>\n </ATCWaypoint>\n'.format( feature[icao_index], self.formattedCoordinateElevation(point, elevation), feature[icao_index]) departure_header = ' <DepartureID>{}</DepartureID>\n <DepartureLLA>{}</DepartureLLA>\n <DepartureName>{}</DepartureName>\n'.format( feature[icao_index], self.formattedCoordinateElevation(point, elevation), feature[name_short_index]) if not destination_point.isEmpty(): destination_id = index.nearestNeighbor(destination_point) feature = strips.getFeature(destination_id[0]) point = feature.geometry().asPoint() elevation = 50.0 destination = ' <ATCWaypoint id="{}">\n <ATCWaypointType>Airport</ATCWaypointType>\n <WorldPosition>{}</WorldPosition>\n <RunwayNumberFP>1</RunwayNumberFP>\n <ICAO>\n <ICAOIdent>{}</ICAOIdent>\n </ICAO>\n </ATCWaypoint>\n'.format( feature[icao_index], self.formattedCoordinateElevation(point, elevation), feature[icao_index]) destination_header = ' <DestinationID>{}</DestinationID>\n <DestinationLLA>{}</DestinationLLA>\n <DestinationName>{}</DestinationName>\n'.format( feature[icao_index], self.formattedCoordinateElevation(point, elevation), feature[name_short_index]) title = self.parameterAsString(parameters, self.TITLE, context) plan_file_path = self.parameterAsString(parameters, self.OUTPUT, context) plan_file = open(plan_file_path, 'w') plan_file.write( '<?xml version="1.0" encoding="UTF-8"?>\n\n<SimBase.Document Type="AceXML" version="1,0">\n <Descr>AceXML Document</Descr>\n <FlightPlan.FlightPlan>\n <Title>{}</Title>\n <FPType>IFR</FPType>\n <RouteType>LowAlt</RouteType>\n <CruisingAlt>11000.000</CruisingAlt>\n' .format(title)) plan_file.write(departure_header + destination_header) plan_file.write( ' <Descr>{}</Descr>\n <AppVersion>\n <AppVersionMajor>11</AppVersionMajor>\n <AppVersionBuild>282174</AppVersionBuild>\n </AppVersion>\n' .format(title)) plan_file.write(departure + user_points + destination) plan_file.write(' </FlightPlan.FlightPlan>\n</SimBase.Document>\n') plan_file.close() return {self.OUTPUT: plan_file_path}
def doStart(self): # first see if we can pull data from the predictions layer startTime = self.datetime endTime = self.datetime.addDays(1) featureRequest = QgsFeatureRequest() stationPt = QgsPointXY(self.stationFeature.geometry().vertexAt(0)) searchRect = QgsRectangle(stationPt, stationPt) searchRect.grow( 0.01 / 60 ) # in the neighborhood of .01 nm as 1/60 = 1 arc minute in this proj. featureRequest.setFilterRect(searchRect) # Create a time based query ctx = featureRequest.expressionContext() scope = QgsExpressionContextScope() scope.setVariable('startTime', startTime) scope.setVariable('endTime', endTime) scope.setVariable('station', self.stationFeature['station']) ctx.appendScope(scope) featureRequest.setFilterExpression( "station = @station and time >= @startTime and time < @endTime") featureRequest.addOrderBy('time') savedFeatureIterator = self.manager.predictionsLayer.getFeatures( featureRequest) savedFeatures = list(savedFeatureIterator) if len(savedFeatures) > 0: # We have some features, so go ahead and stash them in the layer and resolve this promise print('{}: retrieved {} features from layer'.format( self.stationFeature['station'], len(savedFeatures))) self.predictions = savedFeatures self.resolve() else: # The layer didn't have what we wanted, so we must request the data we need. # At this point, the situation falls into several possible cases. # Case 1: A Harmonic station with known flood/ebb directions. Here # we need two requests which can simply be combined and sorted: # 1a: EventType, i.e. slack, flood and ebb # 1b: SpeedDirType, as velocity can be calculated by projecting along flood/ebb # # Case 2: A Harmonic station with unknown flood and/or ebb. # We actually need to combine 3 requests: # 2a: EventType # 2b: SpeedDirType, which only provides vector magnitude/angle # 2c: VelocityMajorType, which only provides current velocity (but for same times as 2b) # Here we set up requests for cases 1 and 2 if self.stationFeature['type'] == 'H': self.speedDirRequest = CurrentPredictionRequest( self.manager, self.stationFeature, startTime, endTime, CurrentPredictionRequest.SpeedDirectionType) self.addDependency(self.speedDirRequest) self.eventRequest = CurrentPredictionRequest( self.manager, self.stationFeature, startTime, endTime, CurrentPredictionRequest.EventType) self.addDependency(self.eventRequest) floodDir = self.stationFeature['meanFloodDir'] ebbDir = self.stationFeature['meanEbbDir'] if floodDir == NULL or ebbDir == NULL: self.velocityRequest = CurrentPredictionRequest( self.manager, self.stationFeature, startTime, endTime, CurrentPredictionRequest.VelocityMajorType) self.addDependency(self.velocityRequest) else: self.velocityRequest = None # Case 3: A Subordinate station which only knows its events. Here we need the following: # 3a: PredictionEventPromises for this station in a 3-day window surrounding the date of interest # 3b: PredictionDataPromises for the reference station in the same 3-day window. else: self.eventPromises = [] self.refPromises = [] refStation = self.manager.getStation( self.stationFeature['refStation']) if refStation is None: print("Could not find ref station {} for {}".format( self.stationFeature['refStation'], self.stationFeature['station'])) else: for dayOffset in [-1, 0, 1]: windowDate = self.localDate.addDays(dayOffset) dataPromise = self.manager.getDataPromise( refStation, windowDate) self.refPromises.append(dataPromise) self.addDependency(dataPromise) eventPromise = self.manager.getEventPromise( self.stationFeature, windowDate) self.eventPromises.append(eventPromise) self.addDependency(eventPromise)
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context) if inputLyr is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) onlySelected = self.parameterAsBool(parameters, self.SELECTED, context) attributeName = self.parameterAsFields(parameters, self.IMAGE_ATTRIBUTE, context)[0] groupExpression = self.parameterAsExpression(parameters, self.GROUP_EXPRESSION, context) imageTag = self.parameterAsString(parameters, self.NAME_TAG, context) boundingBoxGeometry = self.parameterAsExtentGeometry( parameters, self.EXTENT, context) loadToCanvas = self.parameterAsBoolean(parameters, self.ADD_TO_CANVAS, context) uniqueLoad = self.parameterAsBoolean(parameters, self.UNIQUE_LOAD, context) loadedLayers = { i.dataProvider().dataSourceUri() : i.id() for i in iface.mapCanvas().layers()\ if isinstance(i, QgsRasterLayer) } if uniqueLoad else {} outputLayers = {} request = QgsFeatureRequest() if boundingBoxGeometry is not None: request.setFilterRect(boundingBoxGeometry.boundingBox()) request.setFlags(QgsFeatureRequest.NoGeometry) request.addOrderBy(attributeName, ascending=True) features = inputLyr.getFeatures(request) if not onlySelected \ else inputLyr.getSelectedFeatures(request) #calculate size featList = [i for i in features] listSize = len(featList) progressStep = 100 / listSize if listSize else 0 #remaining parameters if loadToCanvas: rootNode = QgsProject.instance().layerTreeRoot() datasetImageNode = self.createGroup(self.tr('Dataset Images'), rootNode) iface.mapCanvas().freeze(True) else: datasetImageNode = None for current, feat in enumerate(featList): if feedback.isCanceled(): break image_path = feat[attributeName] if image_path in loadedLayers: outputLayers[image_path] = loadedLayers[image_path] feedback.setProgress(current * progressStep) continue newImage = QgsRasterLayer( image_path, '_'.join( [imageTag, os.path.basename(image_path)] if imageTag != ''\ else [os.path.basename(image_path)] ) ) QgsProject.instance().addMapLayer(newImage, False) if datasetImageNode is not None: currentNode = datasetImageNode if groupExpression is None\ else self.getLayerCategoryNode( newImage, datasetImageNode, groupExpression ) currentNode.addLayer(newImage) outputLayers[image_path] = newImage.id() feedback.setProgress(current * progressStep) if loadToCanvas: iface.mapCanvas().freeze(False) iface.mapCanvas().refresh() return {self.OUTPUT: list(outputLayers.values())}
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 processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) axis = self.parameterAsSource(parameters, self.AXIS, context) self.first_section_abs_long = self.parameterAsDouble( parameters, self.FIRST_SECTION_ABS_LONG, context) if parameters.get(self.FIRST_AXIS_POINT_ABS_LONG, None) is None: self.first_axis_point_abs_long = None else: self.first_axis_point_abs_long = self.parameterAsDouble( parameters, self.FIRST_AXIS_POINT_ABS_LONG, context) group_field = self.parameterAsString(parameters, self.GROUP_FIELD, context) order_field = self.parameterAsString(parameters, self.ORDER_FIELD, context) self.axis = next(axis.getFeatures()) if axis else None request = QgsFeatureRequest() request.addOrderBy('"{}"'.format(group_field), True, True) file = PreCourlisFileLine(source) fields = PreCourlisFileLine.base_fields() for layer in file.layers(): fields.append(QgsField(layer, QVariant.String, len=100000)) (sink, dest_id) = self.parameterAsSink( parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, 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(request) group = None point_features = [] sec_id = 0 abs_long_offset = 0 for current, point_feature in enumerate(features): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): break if current == 0: if self.first_axis_point_abs_long is not None: abs_long_offset = self.first_axis_point_abs_long else: abs_long_offset = (self.first_section_abs_long - point_feature.attribute("abs_long")) if group is not None and point_feature.attribute( group_field) != group: sec_id += 1 sink.addFeature( self.line_feature_from_points( sorted(point_features, key=lambda f: f.attribute(order_field)), sec_id, point_features[0].attribute("abs_long") + abs_long_offset, ), QgsFeatureSink.FastInsert, ) group = None point_features = [] group = point_feature.attribute(group_field) point_features.append(point_feature) # Update the progress bar feedback.setProgress(int(current * total)) if group is not None: sec_id += 1 sink.addFeature( self.line_feature_from_points( sorted(point_features, key=lambda f: f.attribute(order_field)), sec_id, point_features[0].attribute("abs_long") + abs_long_offset, ), QgsFeatureSink.FastInsert, ) group = None return {self.OUTPUT: dest_id}
def apply_style(layer, style, is_new, name): """Apply the style to a new or existing layer :param layer: QGIS layer instance :type layer: QgsVectorLayer :param style: optional, dictionary with style properties: example {'color': [100, 50, 123], 'transparency': 0.5, 'stroke_width: 3 } :type style: dict :param is_new: True is the layer is a new layer :type is_new: bool :param name: name of the isochrone, if blank/None create a timestamp for the name if the layer is not new :type name: str """ if style is None: return def _set_labeling(): pal_layer = QgsPalLayerSettings() pal_layer.fieldName = 'value' pal_layer.enabled = True pal_layer.placementFlags = QgsLabeling.OnLine pal_layer.placement = QgsPalLayerSettings.PerimeterCurved text_format = pal_layer.format() buffer = text_format.buffer() buffer.setColor(QColor(255, 255, 255)) buffer.setOpacity(0.5) buffer.setEnabled(True) text_format.setBuffer(buffer) pal_layer.setFormat(text_format) labels = QgsVectorLayerSimpleLabeling(pal_layer) return labels def _set_rule(renderer): root_rule = renderer.rootRule() if is_new: rule = root_rule.children()[0] else: rule = root_rule.children()[0].clone() rule.setLabel(name) expression = '"name" = {}'.format(QgsExpression.quotedString(name)) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(*style['color'], 255)) rule.symbol().setOpacity(1 - style['transparency']) rule.symbol().symbolLayers()[0].setStrokeWidth(style['stroke_width']) rule.symbol().symbolLayers()[0].setStrokeColor(QColor(255, 255, 255)) if not is_new: root_rule.appendChild(rule) if is_new: # Create the new style symbol = QgsSymbol.defaultSymbol(layer.geometryType()) renderer = QgsRuleBasedRenderer(symbol) req = QgsFeatureRequest() req.addOrderBy('"value"', False, False) renderer.setOrderBy(req.orderBy()) renderer.setOrderByEnabled(True) _set_rule(renderer) # Delete first rule layer.setRenderer(renderer) labels = _set_labeling() layer.setLabeling(labels) layer.setCustomProperty("labeling/bufferDraw", True) layer.setLabelsEnabled(True) else: # Check for rule based renderer, pass if not present renderer = layer.renderer() if isinstance(renderer, QgsRuleBasedRenderer): _set_rule(renderer)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) decimate_by_distance = self.parameterAsBool(parameters, self.PrmDecimateByDistance, context) decimate_by_time = self.parameterAsBool(parameters, self.PrmDecimateByTime, context) preserve_final_pt = self.parameterAsBool(parameters, self.PrmPreserveFinalPoint, context) min_distance = self.parameterAsDouble(parameters, self.PrmMinDistance, context) units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) min_time = self.parameterAsDouble(parameters, self.PrmMinTime, context) time_units = self.parameterAsInt(parameters, self.PrmTimeUnits, context) is_or_condition = self.parameterAsInt(parameters, self.PrmTwoConditionResponnse, context) fields = source.fields() if self.PrmTimeField not in parameters or parameters[ self.PrmTimeField] is None or parameters[ self.PrmTimeField] == '': time_field = None time_idx = None else: time_field = self.parameterAsString(parameters, self.PrmTimeField, context) time_idx = fields.indexOf(time_field) if decimate_by_time and time_field is None: msg = tr('Please select a DateTime field when decimating by time') feedback.reportError(msg) raise QgsProcessingException(msg) if self.PrmOrderField not in parameters or parameters[ self.PrmOrderField] is None or parameters[ self.PrmOrderField] == '': order_field = None else: order_field = self.parameterAsString(parameters, self.PrmOrderField, context) if self.PrmGroupField not in parameters or parameters[ self.PrmGroupField] is None or parameters[ self.PrmGroupField] == '': group_field = None else: group_field = self.parameterAsString(parameters, self.PrmGroupField, context) wkbtype = source.wkbType() if QgsWkbTypes.isMultiType(wkbtype): msg = tr('Only supports single part Point geometry') feedback.reportError(msg) raise QgsProcessingException(msg) layercrs = source.sourceCrs() (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, wkbtype, layercrs) if layercrs != epsg4326: transto4326 = QgsCoordinateTransform(layercrs, epsg4326, QgsProject.instance()) num_pts = source.featureCount() total = 100.0 / num_pts if num_pts else 0 min_time_s = self.convert_time_to_s(min_time, time_units) min_distance = min_distance * conversionToMeters(units) if group_field: grp_indx = fields.indexOf(group_field) groups = source.uniqueValues(grp_indx) request = QgsFeatureRequest() if order_field: request.addOrderBy(order_field) index = 0 for group in groups: filter = '"{}" = \'{}\''.format(group_field, group) request.setFilterExpression(filter) iterator = source.getFeatures(request) last_decimated = False first_feature = True for feature in iterator: index += 1 if feedback.isCanceled(): break pt = feature.geometry().asPoint() if layercrs != epsg4326: # Convert to 4326 pt4326 = transto4326.transform(pt) else: pt4326 = pt if first_feature: first_feature = False sink.addFeature(feature) pt_last = pt4326 if decimate_by_time: last_time = feature[time_idx] else: d_keep = True t_keep = True if decimate_by_distance: gline = geod.InverseLine(pt_last.y(), pt_last.x(), pt4326.y(), pt4326.x()) if gline.s13 < min_distance: d_keep = False if decimate_by_time: cur_time = feature[time_idx] try: diff = abs( cur_time.toMSecsSinceEpoch() - last_time.toMSecsSinceEpoch()) / 1000.0 if diff < min_time_s: t_keep = False except Exception: pass if is_or_condition and (d_keep or t_keep): if decimate_by_distance: pt_last = pt4326 if decimate_by_time: last_time = cur_time last_decimated = False sink.addFeature(feature) elif d_keep and t_keep: if decimate_by_distance: pt_last = pt4326 if decimate_by_time: last_time = cur_time last_decimated = False sink.addFeature(feature) else: last_decimated = True if index % 100: feedback.setProgress(int(index * total)) if preserve_final_pt and last_decimated: # feature contains the last item from the above for loop which is valid in Python sink.addFeature(feature) else: if order_field: request = QgsFeatureRequest() request.addOrderBy(order_field) iterator = source.getFeatures(request) else: iterator = source.getFeatures() for cnt, feature in enumerate(iterator): if feedback.isCanceled(): break pt = feature.geometry().asPoint() if layercrs != epsg4326: # Convert to 4326 pt4326 = transto4326.transform(pt) else: pt4326 = pt if cnt == 0: # This is the first point so it is saved sink.addFeature(feature) pt_last = pt4326 if decimate_by_time: last_time = feature[time_idx] else: d_keep = True t_keep = True if decimate_by_distance: gline = geod.InverseLine(pt_last.y(), pt_last.x(), pt4326.y(), pt4326.x()) if gline.s13 < min_distance: d_keep = False if decimate_by_time: cur_time = feature[time_idx] try: diff = abs(cur_time.toMSecsSinceEpoch() - last_time.toMSecsSinceEpoch()) / 1000.0 if diff < min_time_s: t_keep = False except Exception: pass if is_or_condition and (d_keep or t_keep): if decimate_by_distance: pt_last = pt4326 if decimate_by_time: last_time = cur_time sink.addFeature(feature) elif d_keep and t_keep: if decimate_by_distance: pt_last = pt4326 if decimate_by_time: last_time = cur_time sink.addFeature(feature) elif preserve_final_pt and (cnt == num_pts - 1): sink.addFeature(feature) if cnt % 100: feedback.setProgress(int(cnt * total)) return {self.PrmOutputLayer: dest_id}