Example #1
0
    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
Example #2
0
    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()
Example #3
0
    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()
Example #4
0
    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']
Example #5
0
    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()
Example #6
0
    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
Example #7
0
 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])
Example #8
0
    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])
Example #9
0
    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
Example #10
0
    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)
        }
Example #11
0
    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()
Example #12
0
    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())}
Example #15
0
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)
Example #16
0
    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}
Example #17
0
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)
Example #18
0
    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}