Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Algoritmo utils ExportFeaturesByAttribute #813

Merged
merged 4 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>

<body>

<div>
<p>Help versão 1.0</p>
<hr/>
<h2>Descrição:</h2>
<h4 style="text-align: center; padding: 6px;">
Exporta feições de uma camada com base em um atributo específico e um operador. Permite selecionar e exportar feições filtradas, como aquelas que contêm, começam com ou não contêm um valor específico.
</h4>
<hr />
</div>

<div>
<h2>Parâmetros:</h2>
<p>
<span style="margin-bottom: 10px;">
&#8226; Camada de entrada &rarr; Camada vetorial que será processada para identificar feições com base em um atributo específico.
</span>

<span style="margin-bottom: 10px;">
&#8226; Atributo de seleção &rarr; Nome do atributo que será utilizado para a filtragem.
</span>

<span style="margin-bottom: 10px;">
&#8226; Operador &rarr; Operador de comparação a ser utilizado para selecionar feições (ex.: igual, diferente, contém, não contém, etc.).
</span>

<span style="margin-bottom: 10px;">
&#8226; Valor &rarr; Valor a ser comparado com o atributo selecionado.
</span>

<span style="margin-bottom: 10px;">
&#8226; Camada de saída &rarr; Nova camada onde as feições filtradas serão exportadas.
</span>

<span style="color:#ff0000; font-weight: bold;"><u>Atenção</u>: certifique-se de usar o operador correto para garantir que as feições desejadas sejam exportadas corretamente. Caso utilize a opção "Contém" ou "Não contém", o valor deve ser ajustado para a string apropriada.</span>

</p>
<hr />
</div>

<div>
<h2>Exemplo de uso: </h2>
<h4>Filtrando feições em uma camada de pontos de interesse na modelagem EDGV3.0 (EPSG:4674)</h4>

<span style="margin-bottom: 10px;">&#8226; Camada de entrada &rarr; cobter_massa_dagua_a</span><br>
<span style="margin-bottom: 10px;">&#8226; Atributo de seleção &rarr; tipo</span><br>
<span style="margin-bottom: 10px;">&#8226; Operador &rarr; igual '='</span><br>
<span style="margin-bottom: 10px;">&#8226; Valor &rarr; 7</span><br>
<span style="margin-bottom: 10px;">&#8226; Camada de saída &rarr; Output layer</span>

<hr />
</div>


<div>
<h2>Nota sobre o uso em models:</h2>
<p style="text-align: justify;">
Este algoritmo também pode ser utilizado em models quando houver necessidade de filtrar feições com base em seus atributos.
No entanto, deve ser usado <strong>restritamente</strong> quando a camada é opcional para o processamento.
isso evita que o modelo aplique o filtro em camadas essenciais ou obrigatórias sem supervisão.
</p>
<hr />
</div>

</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# -*- coding: utf-8 -*-
"""
/***************************************************************************
DsgTools
A QGIS plugin
Brazilian Army Cartographic Production Tools
-------------------
begin : 2024-11-06
git sha : $Format:%H$
copyright : (C) 2024 by Jean Michael Estevez Alvarez- Brazilian Army
email : jeanalvarez@id.uff.br
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""

from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsProcessing,
QgsProcessingException,
QgsProcessingAlgorithm,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterField,
QgsProcessingParameterEnum,
QgsProcessingParameterString,
QgsProcessingParameterFeatureSink,
QgsExpression,
QgsFeatureSink,
QgsVectorLayer,
QgsFeatureRequest)
from qgis import processing

from ..Help.algorithmHelpCreator import HTMLHelpCreator as help



class ExportFeaturesByAttributeAlgorithm(QgsProcessingAlgorithm):
INPUT = 'INPUT'
FIELD = 'FIELD'
OPERATOR = 'OPERATOR'
VALUE = 'VALUE'
OUTPUT = 'OUTPUT'

OPERATORS = ['=',
'<>',
'>',
'>=',
'<',
'<=',
'begins with',
'contains',
'is null',
'is not null',
'does not contain'
]
STRING_OPERATORS = ['begins with', 'contains', 'does not contain']

def createInstance(self):
return ExportFeaturesByAttributeAlgorithm()

def name(self):
return 'exportfeaturesbyattribute'

def displayName(self):
return self.tr('Export Features by Attribute')


def group(self):
"""
Returns the name of the group this algorithm belongs to. This string
should be localised.
"""
return self.tr("Utils")

def groupId(self):
"""
Returns the unique ID of the group this algorithm belongs to. This
string should be fixed for the algorithm, and must not be localised.
The group id should be unique within each provider. Group id should
contain lowercase alphanumeric characters only and no spaces or other
formatting characters.
"""
return "DSGTools - Utils"

def tr(self, string):
return QCoreApplication.translate("ExportFeaturesByAttribute", string
)
def shortHelpString(self):
return help().shortHelpString(self.name())

def initAlgorithm(self, config=None):
self.addParameter(
QgsProcessingParameterVectorLayer(
self.INPUT,
self.tr('Input layer'),
[QgsProcessing.TypeVector]
)
)

self.addParameter(
QgsProcessingParameterField(
self.FIELD,
self.tr('Selection attribute'),
parentLayerParameterName=self.INPUT
)
)

self.addParameter(
QgsProcessingParameterEnum(
self.OPERATOR,
self.tr('Operator'),
options=self.OPERATORS,
defaultValue=0
)
)

self.addParameter(
QgsProcessingParameterString(
self.VALUE,
self.tr('Value'),
optional=True
)
)

self.addParameter(
QgsProcessingParameterFeatureSink(
self.OUTPUT,
self.tr('Output layer')
)
)

def processAlgorithm(self, parameters, context, feedback):
layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
fieldName = self.parameterAsString(parameters, self.FIELD, context)
operator = self.OPERATORS[self.parameterAsEnum(parameters, self.OPERATOR, context)]
value = self.parameterAsString(parameters, self.VALUE, context)

if layer is None:
feedback.pushInfo("Camada inválida ou não encontrada.")
return {self.OUTPUT: None}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Não é o caso retornar None, vai dar erro em model que depende disso. Tem que definir a sink loco agós a linha 140 e retornar o sink_id, mesmo que não seja populado nada


if fieldName not in layer.fields().names():
feedback.pushInfo(f"O atributo '{fieldName}' não foi encontrado na camada. Nenhuma exportação realizada.")
return {self.OUTPUT: None}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Não é o caso retornar None, vai dar erro em model que depende disso. Tem que definir a sink loco agós a linha 140 e retornar o sink_id, mesmo que não seja populado nada


# Construindo a expressão de seleção
field_ref = QgsExpression.quotedColumnRef(fieldName)
if operator == 'is null':
expression_string = f"{field_ref} IS NULL"
elif operator == 'is not null':
expression_string = f"{field_ref} IS NOT NULL"
elif operator == 'begins with':
expression_string = f"{field_ref} LIKE '{value}%'"
elif operator == 'contains':
expression_string = f"{field_ref} LIKE '%{value}%'"
elif operator == 'does not contain':
expression_string = f"{field_ref} NOT LIKE '%{value}%'"
else:
quoted_val = QgsExpression.quotedValue(value)
expression_string = f"{field_ref} {operator} {quoted_val}"

expression = QgsExpression(expression_string)
if expression.hasParserError():
feedback.pushInfo(f"Erro na expressão: {expression.parserErrorString()}")
return {self.OUTPUT: None}
phborba marked this conversation as resolved.
Show resolved Hide resolved

# Configurando o sink para a camada de saída
(sink, dest_id) = self.parameterAsSink(
phborba marked this conversation as resolved.
Show resolved Hide resolved
parameters,
self.OUTPUT,
context,
layer.fields(),
layer.wkbType(),
layer.sourceCrs()
)

# Verificando se há features que correspondem ao filtro
features = layer.getFeatures(QgsFeatureRequest(expression))
matched_features = [f for f in features]
if not matched_features:
feedback.pushInfo("Nenhum recurso encontrado com o valor especificado.")
return {self.OUTPUT: dest_id}

# Adiciona as features que correspondem ao filtro no sink
for feature in matched_features:
if feedback.isCanceled():
break
sink.addFeature(feature, QgsFeatureSink.FastInsert)
phborba marked this conversation as resolved.
Show resolved Hide resolved

feedback.pushInfo("Exportação concluída com sucesso.")
return {self.OUTPUT: dest_id}
Empty file.
Loading