Exemple #1
0
    def canvasPressEvent(self, event):
        """ handle click event on the canvas when tool is active """
        x = event.pos().x()
        y = event.pos().y()
        pos = self.toMapCoordinates(QPoint(x, y))
        # search for parcel layer
        poly_layers = QgsProject.instance().mapLayersByName(self.main.parcel)
        if len(poly_layers) == 0:
            QMessageBox.warning(
                None, self.tr("Area ratio"),
                self.tr("{} layer not found".format(self.main.parcel)))
            return
        poly_layer = poly_layers[0]
        # remove | layer: 0 tag from the end TODO not always good!
        poly_path = poly_layer.dataProvider().dataSourceUri().split('|')[0]
        # build index for polygon layer
        if self.index is None:
            self.index = QgsSpatialIndex()
            for feat in poly_layer.getFeatures():
                self.index.insertFeature(feat)

        in_poly_layers = self.main.buildings
        # find polygons which MBR cover point
        fids = self.index.nearestNeighbor(pos)
        request = QgsFeatureRequest()
        request.setFilterFids(fids)
        features = poly_layer.getFeatures(request)
        p_geom = QgsGeometry.fromPointXY(pos)
        f = None
        for feat in features:
            if feat.geometry().intersects(p_geom):
                f = feat
                break
        else:
            # No poly found
            QMessageBox.warning(
                None, self.tr("Area ratio"),
                self.tr("Feature not found on layer {} ".format(
                    self.main.parcel)))
            return
        # remove previous selection
        poly_layer.removeSelection()
        # select polygon clicked
        poly_layer.select(f.id())
        area1 = f.geometry().area()  # parcel area
        area2 = 0  # sum area for in_poly_layers
        msg = self.main.parcel + ": {:.1f}\n".format(area1)
        # go through building layers
        for name in in_poly_layers:
            layers = QgsProject.instance().mapLayersByName(name)
            if len(layers) == 0:
                QMessageBox.warning(None, self.tr("Area ratio"),
                                    self.tr("{} layer not found".format(name)))
                continue
            layer = layers[0]
            # remove | layer: 0 tag from the end
            layer_path = layer.dataProvider().dataSourceUri().split('|')[0]
            # select intersecting building
            processing.run(
                "native:selectbylocation", {
                    'INPUT':
                    layer_path,
                    'INTERSECT':
                    QgsProcessingFeatureSourceDefinition(poly_path, True),
                    'METHOD':
                    0,
                    'PREDICATE': [0]
                })
            features = layer.selectedFeatures()
            n = 0
            area3 = 0  # sum area for actual layer
            for feat in features:
                # accept intersecting buildings if an internal point is in the parcel
                p = feat.geometry().pointOnSurface()
                if p.intersects(f.geometry()):
                    warea = feat.geometry().area()
                    n += 1
                    area3 += warea  # total area in this layer
                    area2 += warea  # total area in all layers
            if n > 0:
                msg = msg + "\n{:d} {}: {:.1f}".format(n, name, area3)
            layer.removeSelection()
        msg = msg + "\n\n{:.1f} %".format(area2 / area1 * 100.0)
        QMessageBox.information(None, self.tr("Area ratio"), msg)
Exemple #2
0
def execute_in_place_run(alg,
                         parameters,
                         context=None,
                         feedback=None,
                         raise_exceptions=False):
    """Executes an algorithm modifying features in-place in the input layer.

    :param alg: algorithm to run
    :type alg: QgsProcessingAlgorithm
    :param parameters: parameters of the algorithm
    :type parameters: dict
    :param context: context, defaults to None
    :type context: QgsProcessingContext, optional
    :param feedback: feedback, defaults to None
    :type feedback: QgsProcessingFeedback, optional
    :param raise_exceptions: useful for testing, if True exceptions are raised, normally exceptions will be forwarded to the feedback
    :type raise_exceptions: boo, default to False
    :raises QgsProcessingException: raised when there is no active layer, or it cannot be made editable
    :return: a tuple with true if success and results
    :rtype: tuple
    """

    if feedback is None:
        feedback = QgsProcessingFeedback()
    if context is None:
        context = dataobjects.createContext(feedback)

    # Only feature based algs have sourceFlags
    try:
        if alg.sourceFlags(
        ) & QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks:
            context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck)
    except AttributeError:
        pass

    active_layer = parameters['INPUT']

    # Run some checks and prepare the layer for in-place execution by:
    # - getting the active layer and checking that it is a vector
    # - making the layer editable if it was not already
    # - selecting all features if none was selected
    # - checking in-place support for the active layer/alg/parameters
    # If one of the check fails and raise_exceptions is True an exception
    # is raised, else the execution is aborted and the error reported in
    # the feedback
    try:
        if active_layer is None:
            raise QgsProcessingException(tr("There is not active layer."))

        if not isinstance(active_layer, QgsVectorLayer):
            raise QgsProcessingException(
                tr("Active layer is not a vector layer."))

        if not active_layer.isEditable():
            if not active_layer.startEditing():
                raise QgsProcessingException(
                    tr("Active layer is not editable (and editing could not be turned on)."
                       ))

        if not alg.supportInPlaceEdit(active_layer):
            raise QgsProcessingException(
                tr("Selected algorithm and parameter configuration are not compatible with in-place modifications."
                   ))
    except QgsProcessingException as e:
        if raise_exceptions:
            raise e
        QgsMessageLog.logMessage(str(sys.exc_info()[0]), 'Processing',
                                 Qgis.Critical)
        if feedback is not None:
            feedback.reportError(getattr(e, 'msg', str(e)), fatalError=True)
        return False, {}

    if not active_layer.selectedFeatureIds():
        active_layer.selectAll()

    # Make sure we are working on selected features only
    parameters['INPUT'] = QgsProcessingFeatureSourceDefinition(
        active_layer.id(), True)
    parameters['OUTPUT'] = 'memory:'

    req = QgsFeatureRequest(QgsExpression(r"$id < 0"))
    req.setFlags(QgsFeatureRequest.NoGeometry)
    req.setSubsetOfAttributes([])

    # Start the execution
    # If anything goes wrong and raise_exceptions is True an exception
    # is raised, else the execution is aborted and the error reported in
    # the feedback
    try:
        new_feature_ids = []

        active_layer.beginEditCommand(alg.displayName())

        # Checks whether the algorithm has a processFeature method
        if hasattr(alg, 'processFeature'):  # in-place feature editing
            # Make a clone or it will crash the second time the dialog
            # is opened and run
            alg = alg.create()
            if not alg.prepare(parameters, context, feedback):
                raise QgsProcessingException(
                    tr("Could not prepare selected algorithm."))
            # Check again for compatibility after prepare
            if not alg.supportInPlaceEdit(active_layer):
                raise QgsProcessingException(
                    tr("Selected algorithm and parameter configuration are not compatible with in-place modifications."
                       ))
            field_idxs = range(len(active_layer.fields()))
            iterator_req = QgsFeatureRequest(active_layer.selectedFeatureIds())
            iterator_req.setInvalidGeometryCheck(
                context.invalidGeometryCheck())
            feature_iterator = active_layer.getFeatures(iterator_req)
            step = 100 / len(active_layer.selectedFeatureIds()
                             ) if active_layer.selectedFeatureIds() else 1
            for current, f in enumerate(feature_iterator):
                feedback.setProgress(current * step)
                if feedback.isCanceled():
                    break

                # need a deep copy, because python processFeature implementations may return
                # a shallow copy from processFeature
                input_feature = QgsFeature(f)
                new_features = alg.processFeature(input_feature, context,
                                                  feedback)
                new_features = QgsVectorLayerUtils.makeFeaturesCompatible(
                    new_features, active_layer)

                if len(new_features) == 0:
                    active_layer.deleteFeature(f.id())
                elif len(new_features) == 1:
                    new_f = new_features[0]
                    if not f.geometry().equals(new_f.geometry()):
                        active_layer.changeGeometry(f.id(), new_f.geometry())
                    if f.attributes() != new_f.attributes():
                        active_layer.changeAttributeValues(
                            f.id(), dict(zip(field_idxs, new_f.attributes())),
                            dict(zip(field_idxs, f.attributes())))
                    new_feature_ids.append(f.id())
                else:
                    active_layer.deleteFeature(f.id())
                    # Get the new ids
                    old_ids = set(
                        [f.id() for f in active_layer.getFeatures(req)])
                    if not active_layer.addFeatures(new_features):
                        raise QgsProcessingException(
                            tr("Error adding processed features back into the layer."
                               ))
                    new_ids = set(
                        [f.id() for f in active_layer.getFeatures(req)])
                    new_feature_ids += list(new_ids - old_ids)

            results, ok = {}, True

        else:  # Traditional 'run' with delete and add features cycle

            # There is no way to know if some features have been skipped
            # due to invalid geometries
            if context.invalidGeometryCheck(
            ) == QgsFeatureRequest.GeometrySkipInvalid:
                selected_ids = active_layer.selectedFeatureIds()
            else:
                selected_ids = []

            results, ok = alg.run(parameters, context, feedback)

            if ok:
                result_layer = QgsProcessingUtils.mapLayerFromString(
                    results['OUTPUT'], context)
                # TODO: check if features have changed before delete/add cycle

                new_features = []

                # Check if there are any skipped features
                if context.invalidGeometryCheck(
                ) == QgsFeatureRequest.GeometrySkipInvalid:
                    missing_ids = list(
                        set(selected_ids) - set(result_layer.allFeatureIds()))
                    if missing_ids:
                        for f in active_layer.getFeatures(
                                QgsFeatureRequest(missing_ids)):
                            if not f.geometry().isGeosValid():
                                new_features.append(f)

                active_layer.deleteFeatures(active_layer.selectedFeatureIds())

                for f in result_layer.getFeatures():
                    new_features.extend(
                        QgsVectorLayerUtils.makeFeaturesCompatible(
                            [f], active_layer))

                # Get the new ids
                old_ids = set([f.id() for f in active_layer.getFeatures(req)])
                if not active_layer.addFeatures(new_features):
                    raise QgsProcessingException(
                        tr("Error adding processed features back into the layer."
                           ))
                new_ids = set([f.id() for f in active_layer.getFeatures(req)])
                new_feature_ids += list(new_ids - old_ids)

        active_layer.endEditCommand()

        if ok and new_feature_ids:
            active_layer.selectByIds(new_feature_ids)
        elif not ok:
            active_layer.rollBack()

        return ok, results

    except QgsProcessingException as e:
        active_layer.endEditCommand()
        active_layer.rollBack()
        if raise_exceptions:
            raise e
        QgsMessageLog.logMessage(str(sys.exc_info()[0]), 'Processing',
                                 Qgis.Critical)
        if feedback is not None:
            feedback.reportError(getattr(e, 'msg', str(e)), fatalError=True)

    return False, {}
Exemple #3
0
    def testFeatureSourceInput(self):
        # create a memory layer and add to project and context
        layer = QgsVectorLayer(
            "Point?crs=epsg:3857&field=fldtxt:string&field=fldint:integer",
            "testmem", "memory")
        self.assertTrue(layer.isValid())
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes(["test", 123])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        f2 = QgsFeature()
        f2.setAttributes(["test2", 457])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(110, 200)))
        self.assertTrue(pr.addFeatures([f, f2]))
        self.assertEqual(layer.featureCount(), 2)

        # select first feature
        layer.selectByIds([next(layer.getFeatures()).id()])
        self.assertEqual(len(layer.selectedFeatureIds()), 1)

        QgsProject.instance().addMapLayer(layer)
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        alg = QgsApplication.processingRegistry().createAlgorithmById(
            'grass7:v.buffer')
        self.assertIsNotNone(alg)
        temp_file = os.path.join(self.temp_dir, 'grass_output_sel.shp')
        parameters = {
            'input': QgsProcessingFeatureSourceDefinition('testmem', True),
            'cats': '',
            'where': '',
            'type': [0, 1, 4],
            'distance': 1,
            'minordistance': None,
            'angle': 0,
            'column': None,
            'scale': 1,
            'tolerance': 0.01,
            '-s': False,
            '-c': False,
            '-t': False,
            'output': temp_file,
            'GRASS_REGION_PARAMETER': None,
            'GRASS_SNAP_TOLERANCE_PARAMETER': -1,
            'GRASS_MIN_AREA_PARAMETER': 0.0001,
            'GRASS_OUTPUT_TYPE_PARAMETER': 0,
            'GRASS_VECTOR_DSCO': '',
            'GRASS_VECTOR_LCO': ''
        }
        feedback = QgsProcessingFeedback()

        results, ok = alg.run(parameters, context, feedback)
        self.assertTrue(ok)
        self.assertTrue(os.path.exists(temp_file))

        # make sure that layer has correct features
        res = QgsVectorLayer(temp_file, 'res')
        self.assertTrue(res.isValid())
        self.assertEqual(res.featureCount(), 1)

        QgsProject.instance().removeMapLayer(layer)
    def __init__(self, id, gtotool, config, debug):
        super(run, self).__init__()
        self.debug = debug
        self.gtotool = gtotool
        self.info = gtotool.info
        self.iface = gtotool.iface
        if debug: self.info.log("mActionGTOprocessing")
        try:
            algs = config['algs']
            self.outlayer = None
            self.lastlayer = None  # last loaded outlayer
            QgsProject.instance().layerWasAdded.connect(self.LayerWasAdded)
            tmplayers = []
            i = 1
            for alg in algs:
                # run the algorithmn
                cmd = alg['cmd']
                parameters = alg.get('parameters', {})
                new_layer_name = alg.get('layer', None)
                loadLayer = alg.get('load', True)
                use_selection = alg.get("use_selection", [])
                group = alg.get('grouplayer', None)
                stylefile = alg.get('stylefile', None)
                # remove layers from previous tasks
                layers = QgsProject.instance().mapLayersByName(
                    new_layer_name
                )  # list because of possible duplicated names
                if debug: self.info.log("Step 1: delete previous")
                for layer in layers:
                    if debug:
                        self.info.log("Step 1: delete previous", layer.id())
                    if layer.isEditable(): layer.rollBack()
                    QgsProject.instance().removeMapLayer(layer.id())
                if self.debug:
                    self.info.log("step 2 run alg %i:" % i, cmd, parameters)
                # selection
                for p in use_selection:
                    if p in parameters:
                        parameters[p] = QgsProcessingFeatureSourceDefinition(
                            parameters[p], True)
                if not parameters:
                    processing.execAlgorithmDialog(cmd)
                else:
                    outputs = processing.runAndLoadResults(cmd, parameters)
                    if self.debug: self.info.log("Result:", outputs)
                outlayer_id = None
                if self.outlayer:
                    outlayer_id = self.outlayer.id()
                    if debug: self.info.log("outlayer id:", outlayer_id)
                    if new_layer_name is not None:
                        if self.debug:
                            self.info.log(
                                "step 4: rename outlayer <%s> to <%s>:" %
                                (self.outlayer.name(), new_layer_name),
                                outlayer_id)
                        self.outlayer.setName(
                            new_layer_name)  # input for next hardcoded alg
                    else:
                        new_layer_name = self.outlayer.name()
                    self.outlayer.setCrs(QgsProject.instance().crs())
                else:
                    loadLayer = False
                # postprocessing
                if not loadLayer:
                    if self.debug:
                        self.info.log("step 3: add outlayer for deleting: ",
                                      outlayer_id)
                    tmplayers.append(outlayer_id)
                else:
                    if group is not None:  # move the layer to the group
                        self.MoveToGroup(self.outlayer, group)
                    if stylefile is not None:
                        qgs_path = os.path.dirname(
                            QgsProject.instance().absoluteFilePath())
                        stylefile = os.path.join(qgs_path, stylefile)
                        if self.debug: self.info.log("stylefile", stylefile)
                        if os.path.isfile(stylefile):
                            try:
                                layer = QgsProject.instance().mapLayersByName(
                                    new_layer_name)[0]
                                layer.loadNamedStyle(stylefile)
                                layer.triggerRepaint()
                            except Exception as e:
                                self.info.gtoWarning(e.args)
                    self.lastlayer = outlayer_id
                i = i + 1
            # finally set the last outlayer active
            if self.lastlayer is not None:
                tmpLayer = QgsProject.instance().mapLayer(self.lastlayer)
                if tmpLayer is not None:
                    self.gtotool.iface.setActiveLayer(tmpLayer)
                    QgsProject.instance().layerTreeRoot().findLayer(
                        tmpLayer.id()).setItemVisibilityCheckedParentRecursive(
                            True)
            self.lastlayer = None
            self.outlayer = None
            QgsProject.instance().layerWasAdded.disconnect(self.LayerWasAdded)
        except Exception as e:
            self.info.gtoWarning(e.args)

        if not self.debug or 1 == 1:
            for id in tmplayers:
                try:
                    self.info.log("step 5:", "remove tmp layers:", id)
                    QgsProject.instance().removeMapLayer(id)
                except Exception as e:
                    self.info.gtoWarning(e.args)
    def fill_right_of_way_relations(self, db):
        # Load layers
        res_layers = self.qgis_utils.get_layers(db, {
            ADMINISTRATIVE_SOURCE_TABLE: {
                'name': ADMINISTRATIVE_SOURCE_TABLE,
                'geometry': None
            },
            PARCEL_TABLE: {
                'name': PARCEL_TABLE,
                'geometry': None
            },
            PLOT_TABLE: {
                'name': PLOT_TABLE,
                'geometry': QgsWkbTypes.PolygonGeometry
            },
            RESTRICTION_TABLE: {
                'name': RESTRICTION_TABLE,
                'geometry': None
            },
            RIGHT_OF_WAY_TABLE: {
                'name': RIGHT_OF_WAY_TABLE,
                'geometry': QgsWkbTypes.PolygonGeometry
            },
            RRR_SOURCE_RELATION_TABLE: {
                'name': RRR_SOURCE_RELATION_TABLE,
                'geometry': None
            },
            SURVEY_POINT_TABLE: {
                'name': SURVEY_POINT_TABLE,
                'geometry': None
            },
            UEBAUNIT_TABLE: {
                'name': UEBAUNIT_TABLE,
                'geometry': None
            }
        },
                                                load=True)

        self._administrative_source_layer = res_layers[
            ADMINISTRATIVE_SOURCE_TABLE]
        self._parcel_layer = res_layers[PARCEL_TABLE]
        self._plot_layer = res_layers[PLOT_TABLE]
        self._restriction_layer = res_layers[RESTRICTION_TABLE]
        self._right_of_way_layer = res_layers[RIGHT_OF_WAY_TABLE]
        self._survey_point_layer = res_layers[SURVEY_POINT_TABLE]
        self._rrr_source_relation_layer = res_layers[RRR_SOURCE_RELATION_TABLE]
        self._uebaunit_table = res_layers[UEBAUNIT_TABLE]

        if self._parcel_layer is None:
            self.qgis_utils.message_emitted.emit(
                QCoreApplication.translate(
                    "RightOfWay", "Table {} not found in the DB! {}").format(
                        PARCEL_TABLE, db.get_description()), Qgis.Warning)
            return

        if self._right_of_way_layer is None:
            self.qgis_utils.message_emitted.emit(
                QCoreApplication.translate(
                    "RightOfWay", "Table {} not found in the DB! {}").format(
                        RIGHT_OF_WAY_TABLE, db.get_description()),
                Qgis.Warning)
            return

        if self._uebaunit_table is None:
            self.iface.messageBar().pushMessage(
                "Asistente LADM_COL",
                QCoreApplication.translate(
                    "RightOfWay",
                    "UEBAUNIT table couldn't be found... {}").format(
                        self._db.get_description()), Qgis.Warning)
            return

        if self._plot_layer.selectedFeatureCount(
        ) == 0 or self._right_of_way_layer.selectedFeatureCount(
        ) == 0 or self._administrative_source_layer.selectedFeatureCount(
        ) == 0:
            if self.qgis_utils.get_layer_from_layer_tree(
                    PLOT_TABLE,
                    schema=db.schema,
                    geometry_type=QgsWkbTypes.PolygonGeometry) is None:
                self.qgis_utils.message_with_button_load_layer_emitted.emit(
                    QCoreApplication.translate(
                        "RightOfWay",
                        "First load the layer {} into QGIS and select at least one plot!"
                    ).format(PLOT_TABLE),
                    QCoreApplication.translate(
                        "RightOfWay", "Load layer {} now").format(PLOT_TABLE),
                    [PLOT_TABLE, None], Qgis.Warning)
            else:
                self.qgis_utils.message_emitted.emit(
                    QCoreApplication.translate(
                        "RightOfWay",
                        "Select at least one benefited plot, one right of way and at least one administrative source to create relations!"
                    ), Qgis.Warning)
                return
        else:
            ue_baunit_features = self._uebaunit_table.getFeatures()
            # Get unique pairs id_right_of_way-id_parcel
            existing_pairs = [
                (ue_baunit_feature[UEBAUNIT_TABLE_PARCEL_FIELD],
                 ue_baunit_feature[UEBAUNIT_TABLE_RIGHT_OF_WAY_FIELD])
                for ue_baunit_feature in ue_baunit_features
            ]
            existing_pairs = set(existing_pairs)

            plot_ids = [
                f[ID_FIELD] for f in self._plot_layer.selectedFeatures()
            ]

            right_of_way_id = self._right_of_way_layer.selectedFeatures(
            )[0].attribute(ID_FIELD)
            id_pairs = list()
            for plot in plot_ids:
                exp = "\"{uebaunit}\" = {plot}".format(
                    uebaunit=UEBAUNIT_TABLE_PLOT_FIELD, plot=plot)
                parcels = self._uebaunit_table.getFeatures(exp)
                for parcel in parcels:
                    id_pair = (parcel.attribute(UEBAUNIT_TABLE_PARCEL_FIELD),
                               right_of_way_id)
                    id_pairs.append(id_pair)

            if len(id_pairs) < len(plot_ids):
                # If any relationship plot-parcel is not found, we don't need to continue
                self.qgis_utils.message_emitted.emit(
                    QCoreApplication.translate(
                        "RightOfWay",
                        "One or more pairs id_plot-id_parcel weren't found, this is needed to create benefited and restriction relations."
                    ), Qgis.Warning)
                return

            if id_pairs:
                new_features = list()
                for id_pair in id_pairs:
                    if not id_pair in existing_pairs:
                        #Create feature
                        new_feature = QgsVectorLayerUtils().createFeature(
                            self._uebaunit_table)
                        new_feature.setAttribute(UEBAUNIT_TABLE_PARCEL_FIELD,
                                                 id_pair[0])
                        new_feature.setAttribute(
                            UEBAUNIT_TABLE_RIGHT_OF_WAY_FIELD, id_pair[1])
                        self.log.logMessage(
                            "Saving RightOfWay-Parcel: {}-{}".format(
                                id_pair[1], id_pair[0]), PLUGIN_NAME,
                            Qgis.Info)
                        new_features.append(new_feature)

                self._uebaunit_table.dataProvider().addFeatures(new_features)
                self.qgis_utils.message_emitted.emit(
                    QCoreApplication.translate(
                        "RightOfWay",
                        "{} out of {} records were saved into {}! {} out of {} records already existed in the database."
                    ).format(len(new_features), len(id_pairs), UEBAUNIT_TABLE,
                             len(id_pairs) - len(new_features), len(id_pairs)),
                    Qgis.Info)

            spatial_join_layer = processing.run(
                "qgis:joinattributesbylocation", {
                    'INPUT':
                    self._plot_layer,
                    'JOIN':
                    QgsProcessingFeatureSourceDefinition(
                        self._right_of_way_layer.id(), True),
                    'PREDICATE': [0],
                    'JOIN_FIELDS':
                    [ID_FIELD, RIGHT_OF_WAY_TABLE_IDENTIFICATOR_FIELD],
                    'METHOD':
                    0,
                    'DISCARD_NONMATCHING':
                    True,
                    'PREFIX':
                    '',
                    'OUTPUT':
                    'memory:'
                })['OUTPUT']

            restriction_features = self._restriction_layer.getFeatures()

            existing_restriction_pairs = [
                (restriction_feature[RESTRICTION_TABLE_PARCEL_FIELD],
                 restriction_feature[RESTRICTION_TABLE_DESCRIPTION_FIELD])
                for restriction_feature in restriction_features
            ]
            existing_restriction_pairs = set(existing_restriction_pairs)
            id_pairs_restriction = list()
            plot_ids = spatial_join_layer.getFeatures()

            for plot in plot_ids:
                exp = "\"uebaunit\" = {plot}".format(
                    uebaunit=UEBAUNIT_TABLE_PLOT_FIELD,
                    plot=plot.attribute(ID_FIELD))
                parcels = self._uebaunit_table.getFeatures(exp)
                for parcel in parcels:
                    id_pair_restriction = (
                        parcel.attribute(UEBAUNIT_TABLE_PARCEL_FIELD),
                        "Asociada a la servidumbre {}".format(
                            plot.attribute(
                                RIGHT_OF_WAY_TABLE_IDENTIFICATOR_FIELD)))
                    id_pairs_restriction.append(id_pair_restriction)

            new_restriction_features = list()
            if id_pairs_restriction:
                for id_pair in id_pairs_restriction:
                    if not id_pair in existing_restriction_pairs:
                        #Create feature
                        new_feature = QgsVectorLayerUtils().createFeature(
                            self._restriction_layer)
                        new_feature.setAttribute(
                            RESTRICTION_TABLE_PARCEL_FIELD, id_pair[0])
                        new_feature.setAttribute(
                            RESTRICTION_TABLE_DESCRIPTION_FIELD, id_pair[1])
                        new_feature.setAttribute(
                            TYPE_FIELD,
                            COL_RESTRICTION_TYPE_RIGHT_OF_WAY_VALUE)
                        self.log.logMessage(
                            "Saving RightOfWay-Parcel: {}-{}".format(
                                id_pair[1], id_pair[0]), PLUGIN_NAME,
                            Qgis.Info)
                        new_restriction_features.append(new_feature)

                self._restriction_layer.dataProvider().addFeatures(
                    new_restriction_features)
                self.qgis_utils.message_emitted.emit(
                    QCoreApplication.translate(
                        "RightOfWay",
                        "{} out of {} records were saved into {}! {} out of {} records already existed in the database."
                    ).format(
                        len(new_restriction_features),
                        len(id_pairs_restriction), RESTRICTION_TABLE,
                        len(id_pairs_restriction) -
                        len(new_restriction_features),
                        len(id_pairs_restriction)), Qgis.Info)

            administrative_source_ids = [
                f[ID_FIELD]
                for f in self._administrative_source_layer.selectedFeatures()
            ]

            source_relation_features = self._rrr_source_relation_layer.getFeatures(
            )

            existing_source_pairs = [
                (source_relation_feature[RRR_SOURCE_SOURCE_FIELD],
                 source_relation_feature[RRR_SOURCE_RESTRICTION_FIELD])
                for source_relation_feature in source_relation_features
            ]
            existing_source_pairs = set(existing_source_pairs)

            rrr_source_relation_pairs = list()

            for administrative_source_id in administrative_source_ids:
                for restriction_feature in new_restriction_features:
                    rrr_source_relation_pair = (
                        administrative_source_id,
                        restriction_feature.attribute(ID_FIELD))
                    rrr_source_relation_pairs.append(rrr_source_relation_pair)

            new_rrr_source_relation_features = list()
            if rrr_source_relation_pairs:
                for id_pair in rrr_source_relation_pairs:
                    if not id_pair in existing_source_pairs:
                        new_feature = QgsVectorLayerUtils().createFeature(
                            self._rrr_source_relation_layer)
                        new_feature.setAttribute(RRR_SOURCE_SOURCE_FIELD,
                                                 id_pair[0])
                        new_feature.setAttribute(RRR_SOURCE_RESTRICTION_FIELD,
                                                 id_pair[1])
                        self.log.logMessage(
                            "Saving Restriction-Source: {}-{}".format(
                                id_pair[1], id_pair[0]), PLUGIN_NAME,
                            Qgis.Info)
                        new_rrr_source_relation_features.append(new_feature)

                self._rrr_source_relation_layer.dataProvider().addFeatures(
                    new_rrr_source_relation_features)
                self.qgis_utils.message_emitted.emit(
                    QCoreApplication.translate(
                        "RightOfWay",
                        "{} out of {} records were saved into {}! {} out of {} records already existed in the database."
                    ).format(
                        len(new_rrr_source_relation_features),
                        len(rrr_source_relation_pairs),
                        RRR_SOURCE_RELATION_TABLE,
                        len(rrr_source_relation_pairs) -
                        len(new_rrr_source_relation_features),
                        len(rrr_source_relation_pairs)), Qgis.Info)
    def fill_right_of_way_relations(self, db):
        layers = {
            self.names.OP_ADMINISTRATIVE_SOURCE_T: {'name': self.names.OP_ADMINISTRATIVE_SOURCE_T, 'geometry': None, LAYER: None},
            self.names.OP_PARCEL_T: {'name': self.names.OP_PARCEL_T, 'geometry': None, LAYER: None},
            self.names.OP_PLOT_T: {'name': self.names.OP_PLOT_T, 'geometry': QgsWkbTypes.PolygonGeometry, LAYER: None},
            self.names.OP_RESTRICTION_T: {'name': self.names.OP_RESTRICTION_T, 'geometry': None, LAYER: None},
            self.names.OP_RESTRICTION_TYPE_D: {'name': self.names.OP_RESTRICTION_TYPE_D, 'geometry': None, LAYER: None},
            self.names.OP_RIGHT_OF_WAY_T: {'name': self.names.OP_RIGHT_OF_WAY_T, 'geometry': QgsWkbTypes.PolygonGeometry, LAYER: None},
            self.names.COL_RRR_SOURCE_T: {'name': self.names.COL_RRR_SOURCE_T, 'geometry': None, LAYER: None},
            self.names.OP_SURVEY_POINT_T: {'name': self.names.OP_SURVEY_POINT_T, 'geometry': None, LAYER: None},
            self.names.COL_UE_BAUNIT_T: {'name': self.names.COL_UE_BAUNIT_T, 'geometry': None, LAYER: None}
        }

        # Load layers
        self.qgis_utils.get_layers(db, layers, load=True)
        if not layers:
            return None

        exp = "\"{}\" = '{}'".format(self.names.ILICODE_F, LADMNames.RESTRICTION_TYPE_D_RIGHT_OF_WAY_ILICODE_VALUE)
        restriction_right_of_way_t_id = [feature for feature in layers[self.names.OP_RESTRICTION_TYPE_D][LAYER].getFeatures(exp)][0][self.names.T_ID_F]

        if layers[self.names.OP_PLOT_T][LAYER].selectedFeatureCount() == 0 or layers[self.names.OP_RIGHT_OF_WAY_T][LAYER].selectedFeatureCount() == 0 or layers[self.names.OP_ADMINISTRATIVE_SOURCE_T][LAYER].selectedFeatureCount() == 0:
            if self.qgis_utils.get_layer_from_layer_tree(db, self.names.OP_PLOT_T, geometry_type=QgsWkbTypes.PolygonGeometry) is None:
                self.logger.message_with_button_load_layer_emitted.emit(
                    QCoreApplication.translate("RightOfWay",
                                               "First load the layer {} into QGIS and select at least one plot!").format(self.names.OP_PLOT_T),
                    QCoreApplication.translate("RightOfWay", "Load layer {} now").format(self.names.OP_PLOT_T),
                    self.names.OP_PLOT_T,
                    Qgis.Warning)
            else:
                self.logger.warning_msg(__name__, QCoreApplication.translate("RightOfWay",
                    "Select at least one benefited plot, one right of way and at least one administrative source to create relations!"))
                return
        else:
            ue_baunit_features = layers[self.names.COL_UE_BAUNIT_T][LAYER].getFeatures()
            # Get unique pairs id_right_of_way-id_parcel
            existing_pairs = [(ue_baunit_feature[self.names.COL_UE_BAUNIT_T_PARCEL_F], ue_baunit_feature[self.names.COL_UE_BAUNIT_T_OP_RIGHT_OF_WAY_F]) for ue_baunit_feature in ue_baunit_features]
            existing_pairs = set(existing_pairs)

            plot_ids = [f[self.names.T_ID_F] for f in layers[self.names.OP_PLOT_T][LAYER].selectedFeatures()]

            right_of_way_id = layers[self.names.OP_RIGHT_OF_WAY_T][LAYER].selectedFeatures()[0].attribute(self.names.T_ID_F)
            id_pairs = list()
            for plot in plot_ids:
                exp = "\"{uebaunit}\" = {plot}".format(uebaunit=self.names.COL_UE_BAUNIT_T_OP_PLOT_F, plot=plot)
                parcels = layers[self.names.COL_UE_BAUNIT_T][LAYER].getFeatures(exp)
                for parcel in parcels:
                    id_pair = (parcel.attribute(self.names.COL_UE_BAUNIT_T_PARCEL_F), right_of_way_id)
                    id_pairs.append(id_pair)

            if len(id_pairs) < len(plot_ids):
                # If any relationship plot-parcel is not found, we don't need to continue
                self.qlogger.warning_msg(__name__, QCoreApplication.translate("RightOfWay",
                    "One or more pairs id_plot-id_parcel weren't found, this is needed to create benefited and restriction relations."))
                return

            if id_pairs:
                new_features = list()
                for id_pair in id_pairs:
                    if not id_pair in existing_pairs:
                        #Create feature
                        new_feature = QgsVectorLayerUtils().createFeature(layers[self.names.COL_UE_BAUNIT_T][LAYER])
                        new_feature.setAttribute(self.names.COL_UE_BAUNIT_T_PARCEL_F, id_pair[0])
                        new_feature.setAttribute(self.names.COL_UE_BAUNIT_T_OP_RIGHT_OF_WAY_F, id_pair[1])
                        self.logger.info(__name__, "Saving RightOfWay-Parcel: {}-{}".format(id_pair[1], id_pair[0]))
                        new_features.append(new_feature)

                layers[self.names.COL_UE_BAUNIT_T][LAYER].dataProvider().addFeatures(new_features)
                self.logger.info_msg(__name__, QCoreApplication.translate("RightOfWay",
                    "{} out of {} records were saved into {}! {} out of {} records already existed in the database.").format(
                        len(new_features),
                        len(id_pairs),
                        self.names.COL_UE_BAUNIT_T,
                        len(id_pairs) - len(new_features),
                        len(id_pairs)
                    ))

            spatial_join_layer = processing.run("qgis:joinattributesbylocation",
                                                {
                                                    'INPUT': layers[self.names.OP_PLOT_T][LAYER],
                                                    'JOIN': QgsProcessingFeatureSourceDefinition(layers[self.names.OP_RIGHT_OF_WAY_T][LAYER].id(), True),
                                                    'PREDICATE': [0],
                                                    'JOIN_FIELDS': [self.names.T_ID_F],
                                                    'METHOD': 0,
                                                    'DISCARD_NONMATCHING': True,
                                                    'PREFIX': '',
                                                    'OUTPUT': 'memory:'})['OUTPUT']

            restriction_features = layers[self.names.OP_RESTRICTION_T][LAYER].getFeatures()
            existing_restriction_pairs = [(restriction_feature[self.names.COL_BAUNIT_RRR_T_UNIT_F], restriction_feature[self.names.COL_RRR_T_DESCRIPTION_F]) for restriction_feature in restriction_features]
            existing_restriction_pairs = set(existing_restriction_pairs)
            id_pairs_restriction = list()
            plot_ids = spatial_join_layer.getFeatures()

            for plot in plot_ids:
                exp = "\"uebaunit\" = {plot}".format(uebaunit=self.names.COL_UE_BAUNIT_T_OP_PLOT_F, plot=plot.attribute(self.names.T_ID_F))
                parcels = layers[self.names.COL_UE_BAUNIT_T][LAYER].getFeatures(exp)
                for parcel in parcels:
                    id_pair_restriction = (parcel.attribute(self.names.COL_UE_BAUNIT_T_PARCEL_F), QCoreApplication.translate("RightOfWay", "Right of way"))
                    id_pairs_restriction.append(id_pair_restriction)

            new_restriction_features = list()
            if id_pairs_restriction:
                for id_pair in id_pairs_restriction:
                    if not id_pair in existing_restriction_pairs:
                        #Create feature
                        new_feature = QgsVectorLayerUtils().createFeature(layers[self.names.OP_RESTRICTION_T][LAYER])
                        new_feature.setAttribute(self.names.COL_BAUNIT_RRR_T_UNIT_F, id_pair[0])
                        new_feature.setAttribute(self.names.COL_RRR_T_DESCRIPTION_F, id_pair[1])
                        new_feature.setAttribute(self.names.OP_RESTRICTION_T_TYPE_F, restriction_right_of_way_t_id)
                        self.logger.info(__name__, "Saving RightOfWay-Parcel: {}-{}".format(id_pair[1], id_pair[0]))
                        new_restriction_features.append(new_feature)

                layers[self.names.OP_RESTRICTION_T][LAYER].dataProvider().addFeatures(new_restriction_features)
                self.logger.info_msg(__name__, QCoreApplication.translate("RightOfWay",
                    "{} out of {} records were saved into {}! {} out of {} records already existed in the database.").format(
                        len(new_restriction_features),
                        len(id_pairs_restriction),
                        self.names.OP_RESTRICTION_T,
                        len(id_pairs_restriction) - len(new_restriction_features),
                        len(id_pairs_restriction)
                    ))

            administrative_source_ids = [f[self.names.T_ID_F] for f in layers[self.names.OP_ADMINISTRATIVE_SOURCE_T][LAYER].selectedFeatures()]

            source_relation_features = layers[self.names.COL_RRR_SOURCE_T][LAYER].getFeatures()

            existing_source_pairs = [(source_relation_feature[self.names.COL_RRR_SOURCE_T_SOURCE_F], source_relation_feature[self.names.COL_RRR_SOURCE_T_OP_RESTRICTION_F]) for source_relation_feature in source_relation_features]
            existing_source_pairs = set(existing_source_pairs)

            rrr_source_relation_pairs = list()

            for administrative_source_id in administrative_source_ids:
                for restriction_feature in new_restriction_features:
                    rrr_source_relation_pair = (administrative_source_id, restriction_feature.attribute(self.names.T_ID_F))
                    rrr_source_relation_pairs.append(rrr_source_relation_pair)

            new_rrr_source_relation_features = list()
            if rrr_source_relation_pairs:
                for id_pair in rrr_source_relation_pairs:
                    if not id_pair in existing_source_pairs:
                        new_feature = QgsVectorLayerUtils().createFeature(layers[self.names.COL_RRR_SOURCE_T][LAYER])
                        new_feature.setAttribute(self.names.COL_RRR_SOURCE_T_SOURCE_F, id_pair[0])
                        new_feature.setAttribute(self.names.COL_RRR_SOURCE_T_OP_RESTRICTION_F, id_pair[1])
                        self.logger.info(__name__, "Saving Restriction-Source: {}-{}".format(id_pair[1], id_pair[0]))
                        new_rrr_source_relation_features.append(new_feature)

                layers[self.names.COL_RRR_SOURCE_T][LAYER].dataProvider().addFeatures(new_rrr_source_relation_features)
                self.logger.info_msg(__name__, QCoreApplication.translate("RightOfWay",
                    "{} out of {} records were saved into {}! {} out of {} records already existed in the database.").format(
                        len(new_rrr_source_relation_features),
                        len(rrr_source_relation_pairs),
                        self.names.COL_RRR_SOURCE_T,
                        len(rrr_source_relation_pairs) - len(new_rrr_source_relation_features),
                        len(rrr_source_relation_pairs)
                    ))
     def abideMinCases_func():
     
         # create container for information about processed features
         allProc = []
         
         # iterate over each feature
         feats = outTab.getFeatures()
         feat_iter_count = 0
         n_feats = outTab.featureCount()
         for feat in feats:
             
             feat_iter_count += 1
             QgsMessageLog.logMessage('Processing feature...(' + str(feat_iter_count) + '/' + str(n_feats) + ')', 'User notification', 0)
             
             # get attributes
             atts = feat.attributes()
             
             # iterate over fields of interest
             for a in list(range(0, len(atts))):
                 
                 QgsMessageLog.logMessage('Processing field...(' + str(a+1) + '/' + str(len(atts)) + ')', 'User notification', 0)
                 
                 # get active if current field is within the fields of interest
                 if a in fieldIdx:
                     
 
                     # extract value in question and area size for the respective features
                     to_val = atts[a]
                     
                     # get active if attribute value is lower than defined threshold
                     if atts[a] < thresh:
                         
                         # select current feature and create new layer
                         outTab.selectByIds([feat.id()])
                         temp_fileName = tempDir + '/temp_selected_' + str(feat_iter_count) + '_' + str(a) + '.gpkg'
                         QgsVectorFileWriter.writeAsVectorFormat(outTab, temp_fileName, 'ANSI', outTab.crs(), 'GPKG', 1)
         
                         
                         
                         # get adjacent features
                         params = {'INPUT' : outTab,
                                   'INTERSECT' : QgsProcessingFeatureSourceDefinition(temp_fileName, False),
                                   'METHOD' : 0,
                                   'PREDICATE' : [4] }
                         adjSel = processing.run('native:selectbylocation', params)['OUTPUT']
                         adj_feats = adjSel.selectedFeatures()
                         adjSel.removeSelection()
                         
                         
                         # get attribute values of adjacent features
                         adjIdx = []
                         adjAtts = []
                         for adj_feat in adj_feats:
                             adjIdx.append(adj_feat.id())
                             adjAtts.append(adj_feat[a])
                         
                         QgsMessageLog.logMessage('Feature comparison with ' + str(len(adjIdx)) + ' adjacent features...', 'User notification', 0)
                         
                         
                         # sort adjacent features by attribute values
                         adjIdx = [x for _, x in sorted(zip(adjAtts, adjIdx))]
                         adjAtts = sorted(adjAtts)
                                                     
                         
                         # iterate over each appropriate adjacent feature pair as long as the threshold is not reached
                         new_val = to_val
                         for p in list(range(0, len(adjIdx))):
                              
                              
                             # collect information about current feature pair
                             pair1 = str(feat.id()) + '_' + str(adjIdx[p])
                             pair2 = str(adjIdx[p]) + '_' + str(feat.id())
                              
                              
                             # get active if this feature pair has not been processed before
                             if (pair1 not in allProc) and (pair2 not in allProc) and (new_val < thresh):
                                    
                                 # get values of adjacent polygon 
                                 outTab.selectByIds([adjIdx[p]])
                                 comp_val = outTab.selectedFeatures()[0].attributes()[a]
                                 outTab.removeSelection()
    
                                 # calculate new value as mean
                                 new_val = (to_val + comp_val) / 2
                                     
                                                                     
                                 # update attribute values in respective features
                                 outTab.startEditing()
                                 outTab.changeAttributeValue(adjIdx[p], a, new_val)
                                 outTab.changeAttributeValue(feat.id(), a, new_val)
                                 outTab.commitChanges()
                                 
                                      
                                  
                                 # collect information about this processed feature pair
                                 allProc.append(pair1)
                                 
                                 # update value in question
                                 to_val = new_val
                                                             
                             
         return outTab
def input_to_processing( identifier: str, inp: WPSInput, alg: QgsProcessingAlgorithm, 
                         context: ProcessingContext ) -> Tuple[str, Any]:
    """ Convert wps input to processing param

        see https://qgis.org/api/classQgsProcessingOutputLayerDefinition.html
        see https://qgis.org/api/qgsprocessingparameters_8cpp_source.html#L272

        see ./python/plugins/processing/tools/general.py:111
        see ./python/plugins/processing/gui/Postprocessing.py:50
        see ./python/plugins/processing/core/Processing.py:126
    """
    param = alg.parameterDefinition(identifier)

    typ = param.type()

    if isinstance(param, DESTINATION_LAYER_TYPES):
        # Do not supports memory: layer since we are storing destination project to file
        param.setSupportsNonFileBasedOutput(False)
        # Enforce pushing created layers to layersToLoadOnCompletion list
        sink = "./%s.%s" % (param.name(), param.defaultFileExtension())
        value = QgsProcessingOutputLayerDefinition(sink, context.destination_project)
        value.destinationName = inp[0].data

    elif isinstance(param, QgsProcessingParameterFeatureSource):
        # Support feature selection
        value, has_selection = parse_layer_spec(inp[0].data, context, allow_selection=True)
        value = QgsProcessingFeatureSourceDefinition(value, selectedFeaturesOnly=has_selection)

    elif isinstance(param, INPUT_LAYER_TYPES):
        if len(inp) > 1:
            value = [parse_layer_spec(i.data, context)[0] for i in inp]
        else:
            value, _ = parse_layer_spec(inp[0].data, context)

    elif isinstance(param, QgsProcessingParameterPoint):
        value = input_to_point( inp[0] )

    elif typ == 'enum':
        # XXX Processing wants the index of the value in option list
        if param.allowMultiple() and len(inp) > 1:
            opts  = param.options()
            value = [opts.index(d.data) for d in inp] 
        else:
            value = param.options().index(inp[0].data)

    elif typ == 'extent':
        value = input_to_extent( inp[0] )

    elif typ == 'crs':
        # XXX CRS may be expressed as EPSG (or QgsProperty ?)
        value = inp[0].data

    elif typ in ('fileDestination','folderDestination'):
        # Normalize path
        value = basename(normpath(inp[0].data))
        if value != inp[0].data:
            LOGGER.warning("Value for file or folder destination '%s' has been truncated from '%s' to '%s'",
                    identifier, inp[0].data, value )

    elif typ == 'file':
        # Handle file input
        value = input_to_file( inp[0], param, context )

    elif len(inp):
        # Return raw value
        value = inp[0].data
    else:
        # Return undefined value
        if not _is_optional(param):
            LOGGER.warning("Required input %s has no value", identifier)
        value = None

    return param.name(), value
Exemple #9
0
    def processAlgorithm(
            self, parameters: Dict[str, Any], context: QgsProcessingContext,
            feedback: QgsProcessingFeedback) -> Union[dict, Dict[str, Any]]:

        # Словарь в котором будут сохраняться результаты работы алгоритма
        result = dict()

        # Получаем переданные на вход параметры
        source: QgsFeatureSource = self.parameterAsSource(
            parameters, self.SAMPLES, context)

        if self.MOSAIC in parameters and parameters[self.MOSAIC]:
            whole_mosaic: Optional[
                QgsRasterLayer] = self.parameterAsRasterLayer(
                    parameters, self.MOSAIC, context)
        else:
            whole_mosaic = None

        horresolution: float = self.parameterAsDouble(parameters,
                                                      self.HORRESOLUTION,
                                                      context)
        vertresolution: float = self.parameterAsDouble(parameters,
                                                       self.VERTRESOLUTION,
                                                       context)
        width: int = self.parameterAsInt(parameters, self.WIDTH, context)
        height: int = self.parameterAsInt(parameters, self.HEIGHT, context)
        dest_crs: QgsCoordinateReferenceSystem = self.parameterAsCrs(
            parameters, self.CRS, context)

        if self.FOLDER in parameters and parameters[self.FOLDER]:
            folder: Optional[str] = self.parameterAsFileOutput(
                parameters, self.FOLDER, context)
        else:
            folder = None

        saveonesample: bool = self.parameterAsBoolean(parameters,
                                                      self.SAVEONESAMPLE,
                                                      context)

        step = 0
        model_feedback = QgsProcessingMultiStepFeedback(4, feedback)
        if feedback.isCanceled():
            return result

        # Запускаем загруженный из файла алгоритм, который создает слои INTERSECTION и GRID
        temp_grid_id = processing.run(
            self.grid_model.model(), {
                'CRS':
                dest_crs,
                'SAMPLES':
                parameters[self.SAMPLES],
                'HORRESOLUTION':
                horresolution,
                'VERTRESOLUTION':
                vertresolution,
                'HEIGHT':
                height,
                'WIDTH':
                width,
                'VERBOSE_LOG':
                True,
                'native:renametablefield_1:{}'.format(self.GRID):
                'TEMPORARY_OUTPUT'
            },
            context=context,
            feedback=model_feedback,
            is_child_algorithm=True)['native:renametablefield_1:{}'.format(
                self.GRID)]

        step += 1
        model_feedback.setCurrentStep(step)
        if feedback.isCanceled():
            return result

        temp_grid: QgsVectorLayer = context.takeResultLayer(temp_grid_id)

        if whole_mosaic and folder:
            # Извлекаем екстент из мозаики и любую (первую) точку из грида, чтобы по ним вычислить смещение
            mosaic_extent: QgsRectangle = whole_mosaic.extent()
            first_point: QgsPoint = temp_grid.getFeatures().__next__(
            ).geometry().vertices().__next__()

            # вычисляем смещения и двигаем грид
            translated_grid_id = processing.run(
                "native:translategeometry", {
                    'INPUT': temp_grid,
                    'DELTA_X': (mosaic_extent.xMaximum() - first_point.x()) %
                    horresolution,
                    'DELTA_Y': (mosaic_extent.yMaximum() - first_point.y()) %
                    vertresolution,
                    'DELTA_Z': 0,
                    'DELTA_M': 0,
                    'OUTPUT': 'TEMPORARY_OUTPUT'
                },
                context=context,
                feedback=model_feedback,
                is_child_algorithm=True)['OUTPUT']

            translated_grid: QgsVectorLayer = context.takeResultLayer(
                translated_grid_id)
        else:
            translated_grid_id = temp_grid_id
            translated_grid = temp_grid

        step += 1
        model_feedback.setCurrentStep(step)
        if feedback.isCanceled():
            return result

        temp_intersection_id = processing.run(
            self.intersection_model.model(), {
                'CRS':
                dest_crs,
                'SAMPLES':
                parameters[self.SAMPLES],
                'GRID':
                translated_grid,
                'VERBOSE_LOG':
                True,
                'native:intersection_1:{}'.format(self.INTERSECTION):
                'TEMPORARY_OUTPUT'
            },
            context=context,
            feedback=model_feedback,
            is_child_algorithm=True)['native:intersection_1:{}'.format(
                self.INTERSECTION)]

        temp_intersection: QgsVectorLayer = context.takeResultLayer(
            temp_intersection_id)

        # Создаем выходные слои, записываем в них features и сохраняем с словарь результатов result
        (intersection,
         intersection_id) = self.parameterAsSink(parameters, self.INTERSECTION,
                                                 context,
                                                 temp_intersection.fields(),
                                                 temp_intersection.wkbType(),
                                                 temp_intersection.sourceCrs())

        (grid, grid_id) = self.parameterAsSink(parameters, self.GRID, context,
                                               translated_grid.fields(),
                                               translated_grid.wkbType(),
                                               translated_grid.sourceCrs())

        intersection.addFeatures(temp_intersection.getFeatures())
        grid.addFeatures(translated_grid.getFeatures())

        result.update({self.INTERSECTION: intersection_id, self.GRID: grid_id})

        step += 1
        model_feedback.setCurrentStep(step)
        if feedback.isCanceled():
            return result

        # Поля для выходного слоя RLE
        rle_fields = QgsFields()
        rle_fields.append(QgsField("Image_Label", QVariant.String))
        rle_fields.append(QgsField("EncodedPixels", QVariant.String))

        # Выходной слой RLE
        (rle, rle_id) = self.parameterAsSink(parameters, self.RLE, context,
                                             rle_fields,
                                             translated_grid.wkbType(),
                                             QgsCoordinateReferenceSystem())
        rle: QgsFeatureSink

        store: QgsMapLayerStore = QgsProject.instance().layerStore()

        # Добавляем слои в хранилище слоев проекта, чтобы их id видел QgsProcessingFeatureSourceDefinition
        store.addMapLayer(temp_intersection)
        store.addMapLayer(translated_grid)

        # Индикатор для сохранения одного растра с sample
        first = True

        # Цикл по каждому тайлу из GRID
        for current, tile_feat in enumerate(translated_grid.getFeatures()):

            tile_feat: QgsFeature

            if feedback.isCanceled():
                return result

            # для каждого тайла создаем запрос по которому будут запрошены соответствующие feature из INTERSECTION
            expression = QgsExpression().createFieldEqualityExpression(
                "tile_id", tile_feat["tile_id"])
            request = QgsFeatureRequest()
            request.setFilterExpression(expression)

            # Цикл по всем feature в INTERSECTION
            for samle_feat in temp_intersection.getFeatures(request):
                samle_feat: QgsFeature

                # выделяем в слое INTERSECTION текущую feature, чтобы только ее передать в алгоритм обрезки растра
                temp_intersection.selectByIds([samle_feat.id()])

                # Превращаем текущую feature из INTERSECTION в растр, экстент растра задаем по текущему тайлу
                bin_raster = processing.run("gdal:rasterize", {
                    'BURN':
                    1,
                    'DATA_TYPE':
                    0,
                    'EXTENT':
                    tile_feat.geometry().boundingBox(),
                    'EXTRA':
                    '',
                    'FIELD':
                    '',
                    'HEIGHT':
                    vertresolution,
                    'INIT':
                    None,
                    'INPUT':
                    QgsProcessingFeatureSourceDefinition(
                        temp_intersection.id(), selectedFeaturesOnly=True),
                    'INVERT':
                    False,
                    'NODATA':
                    0,
                    'OPTIONS':
                    'NBITS=1',
                    'OUTPUT':
                    'TEMPORARY_OUTPUT',
                    'UNITS':
                    1,
                    'WIDTH':
                    horresolution
                },
                                            context=context,
                                            feedback=model_feedback,
                                            is_child_algorithm=True)['OUTPUT']

                # Получаем результат работы алгоритма в виде растра
                bin_raster: QgsRasterLayer = QgsProcessingUtils.mapLayerFromString(
                    bin_raster, context)

                if first and folder and saveonesample:
                    first = False
                    save_raster(
                        bin_raster, folder,
                        str(tile_feat["tile_id"]).zfill(5) + '_sample.tif')

                # Получаем строку RLE
                raster_rle_string = rle_encode(
                    convertRasterToNumpyArray(bin_raster))

                # Записываем строку с описанием RLE в слой RLE
                feat = QgsFeature(rle_fields)
                feat["Image_Label"] = tile_feat["tile_id"]
                feat["EncodedPixels"] = raster_rle_string
                rle.addFeatures([feat])

                if feedback.isCanceled():
                    return result

            # если указаны мозаика и выходная папка, то обрезаем мозаику по текущему тайлу GRID
            if whole_mosaic and folder:

                if feedback.isCanceled():
                    return result

                # выделяем в слое GRID текущий тайл, чтобы только его передать в алгоритм обрезки растра
                translated_grid.selectByIds([tile_feat.id()])

                mosaic_tile_temp_raster = processing.run(
                    "gdal:cliprasterbymasklayer",
                    {
                        'ALPHA_BAND':
                        False,
                        'CROP_TO_CUTLINE':
                        True,
                        'DATA_TYPE':
                        0,
                        'EXTRA':
                        '',
                        'INPUT':
                        whole_mosaic,
                        'KEEP_RESOLUTION':
                        False,
                        # 'MASK': single_grid,
                        'MASK':
                        QgsProcessingFeatureSourceDefinition(
                            translated_grid.id(), selectedFeaturesOnly=True),
                        'MULTITHREADING':
                        False,
                        'NODATA':
                        None,
                        'OPTIONS':
                        '',
                        # 'OUTPUT': 'TEMPORARY_OUTPUT',
                        'OUTPUT':
                        os.path.join(folder,
                                     str(tile_feat["tile_id"]).zfill(5)) +
                        '.tif',
                        'SET_RESOLUTION':
                        True,
                        'SOURCE_CRS':
                        None,
                        'TARGET_CRS':
                        None,
                        'X_RESOLUTION':
                        abs(whole_mosaic.rasterUnitsPerPixelX()),
                        'Y_RESOLUTION':
                        abs(whole_mosaic.rasterUnitsPerPixelX())
                    },
                    context=context,
                    feedback=model_feedback,
                    is_child_algorithm=True)["OUTPUT"]

                if feedback.isCanceled():
                    return result

        store.removeMapLayer(temp_intersection)
        store.removeMapLayer(translated_grid)

        step += 1
        model_feedback.setCurrentStep(step)
        if feedback.isCanceled():
            return result

        result.update({self.RLE: rle_id})
        return result