Script em QGIS

122 views
Skip to first unread message

Eddison Araya

unread,
Feb 27, 2021, 3:23:48 PM2/27/21
to qgisb...@googlegroups.com
Olá, o script em QGIS que cito abaixo me dá esse erro e não sei o que acontece, esse script permite dividir uma fazenda agrícola em partes iguais, agradeço a ajuda para resolver o problema


Erro:

Consola de Python
Usa iface para acceder a la interfaz de la API de QGIS o digita help(iface) para más información
Aviso de advertencia: digitar instrucciones desde una fuente no confiable puede conllevar a pérdida o fuga de datos
exec(open('C:/Users/Dell/AppData/Local/Temp/tmpjwny47pg.py'.encode('utf-8')).read())
Traceback (most recent call last):
  File "C:\PROGRA~1\QGIS3~1.10\apps\Python37\lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
  File "<string>", line 202, in <module>
  File "<string>", line 151, in dissolve_result
  File "<string>", line 109, in categorize
  File "<string>", line 92, in clip_grid_and_layer
  File "<string>", line 76, in layer_2_grid
  File "C:/PROGRA~1/QGIS3~1.10/apps/qgis-ltr/./python/plugins\processing\tools\general.py", line 106, in run
    return Processing.runAlgorithm(algOrName, parameters, onFinish, feedback, context)
  File "C:/PROGRA~1/QGIS3~1.10/apps/qgis-ltr/./python/plugins\processing\core\Processing.py", line 181, in runAlgorithm
    raise QgsProcessingException(msg)
_core.QgsProcessingException: Hubo errores al ejecutar el algoritmo.



El script es este:


# defining required imports
import sys

# defining a class
class LayerIntoParts:

    # initiating layer's name to split and number of parts provided from user
    def __init__(self, layer_name, segments):
        self.layer_name = layer_name
        self.segments = segments

    # setting up the input layer and checking it's type
    def layer_geometry_check(self):
        # loading layer
        layer = QgsProject.instance().mapLayersByName(self.layer_name)[0]
        if not layer.isValid():
            raise ValueError("Layer failed to load!")
            sys.exit

        # checking geometry type, will work only with polygons and multipolygons
        if layer.wkbType() == QgsWkbTypes.Polygon:
            layer_valid = layer
        # converting multipart into single part
        elif layer.wkbType() == QgsWkbTypes.MultiPolygon:
            layer_valid = processing.run('native:multiparttosingleparts',
                {'INPUT': layer,
                'OUTPUT': "memory:"}
            )["OUTPUT"]
        # giving an error for not polygons and multipolygons
        else:
            raise ValueError("This geometry type is not supported!\Only Polygons/Multipolygons are allowed.")
            sys.exit

        # returning the validated layer
        return layer_valid

    # defining required parameters
    def layer_and_parameters(self):
        # inheriting the output from 'layer_geometry_check' method
        layer = self.layer_geometry_check()

        # getting the layer's area
        area_total = [f.geometry().area() for f in layer.getFeatures()]
        area_total = area_total[0]

        # getting the layer's extent and adjusting it for processing functions
        layer_extent = layer.extent()
        layer_extent_string = "{},{},{},{}".format(layer_extent.xMinimum(), layer_extent.xMaximum(), layer_extent.yMinimum(), layer_extent.yMaximum())

        # building a dictionary to store the output parameters
        param = {
        'layer': layer,
        'layer_crs': layer.crs(),
        'layer_extent': layer_extent_string,
        'layer_area_total': area_total,
        'area_segment': area_total / self.segments
        }

        # returning the dictionary with output parameters
        return param

    # creating grid for the input layer
    def layer_2_grid(self):
        # inheriting the output from 'layer_and_parameters' method
        param = self.layer_and_parameters()

        # creating grid for the layer with 'qgis:creategrid' algorithm
        layer_grid = processing.run('qgis:creategrid',
            {'TYPE': 2,
            'CRS': param['layer_crs'],
            'EXTENT': param['layer_extent'],
            'HSPACING': 10000,
            'VSPACING': 10000,
            'HOVERLAY': 0,
            'VOVERLAY': 0,
            'OUTPUT': "memory:"}
        )["OUTPUT"]

        # deleting redundant attributes (appear by default when using the algorithm to create a grid)
        layer_grid_clean = processing.run('qgis:deletecolumn',
            {'INPUT': layer_grid,
            'COLUMN': ['left', 'right', 'top', 'bottom'],
            'OUTPUT': "memory:"}
        )["OUTPUT"]

        # returning layer as a grid
        return layer_grid_clean

    # clipping the grid with the input layer
    def clip_grid_and_layer(self):
        # inheriting the output from 'layer_2_grid' method
        grid = self.layer_2_grid()
        # inheriting the output from 'layer_and_parameters' method
        layer = self.layer_and_parameters()['layer']

        # clipping the grid with the layer by means of 'qgis:clip' algorithm
        layer_clip = processing.run('qgis:clip',
            {'INPUT': grid,
            'OVERLAY': layer,
            'OUTPUT': "memory:"}
        )["OUTPUT"]

        # returning the clipped grid
        return layer_clip

    # categorizing the clipped grid layer
    def categorize(self):
        # inheriting the output from 'clip_grid_and_layer' method
        layer_clip = self.clip_grid_and_layer()
        # inheriting the output from 'layer_and_parameters' method
        param = self.layer_and_parameters()

        # transforming clipped grid layer's elements into a list with
        # id, calculated area, and geometry      
        elements = []
        for f in layer_clip.getFeatures():
            case = {"f_id": f.id(), "area": f.geometry().area(), "geom": f.geometry()}
            elements.append(case)

        # lists for used cells' ids
        used_ids_i = []
        used_ids_j = []
        # variable for categories
        n = 0

        # looping through all cells
        for i in elements:
            area_calc = i['area']
            used_ids_i.append(i['f_id'])

            for j in elements:

                # conditions: calculated area less than a "golden" area of a segment, no duplicates of cells, and sufficient intersection of edges between cells
                if area_calc <= param['area_segment'] and j['f_id'] not in used_ids_i and i['f_id'] not in used_ids_j and (i['geom'].intersection(i['geom'])).length() > 0:
                    used_ids_j.append(j['f_id'])
                    area_calc += j['area']
                    n += 1

                # signing a category to each cell
                i['cat'] = 'cat_' + str(n)
                i['area_calc'] = area_calc

        # returning categorized cells as list
        return elements

   # dissolving categorized cells and outputting the result
    def dissolve_result(self):
        # inheriting the output from 'layer_and_parameters' method
        param = self.layer_and_parameters()
        # inheriting the output from 'categorize' method
        elements_raw = self.categorize()

        # creating an empty later for output
        vl = QgsVectorLayer("Polygon?crs={}".format(param['layer_crs'].authid()), "output", "memory")

        # accessing the empty layer
        pr = vl.dataProvider()

        # embedding new field values
        pr.addAttributes([QgsField("id", QVariant.Int),
            QgsField("cat", QVariant.String),
            QgsField("area_calc", QVariant.Double),
            QgsField("area_gold", QVariant.Double)
            ])

        # updating the empty layer      
        vl.updateFields()

        # looping through a list of categorized cells and inserting them into the empty layer
        for elem in elements_raw:
            feat = QgsFeature()
            feat.setGeometry(elem['geom'])
            feat.setAttributes([elem['f_id'], elem['cat'], round(elem['area_calc'], 8), round(param['area_segment'], 8)])
            pr.addFeature(feat)

        vl.updateExtents()

        # dissolving by category by means of 'qgis:dissolve' algorithm
        layer_dissolved = processing.run('qgis:dissolve',
            {'FIELD': ['cat'],
            'INPUT': vl,
            'OUTPUT': 'memory:'}
        )["OUTPUT"]

        # deleting 'cat' attribute using 'qgis:deletecolumn' algorithm
        layer_dissolved_clean = processing.run('qgis:deletecolumn',
            {'INPUT': layer_dissolved,
            'COLUMN': ['cat'],
            'OUTPUT': "memory:"}
        )["OUTPUT"]

        # updating 'id' attribute
        with edit(layer_dissolved_clean):
            for feature in layer_dissolved_clean.getFeatures():
                feature.setAttribute(feature.fieldNameIndex('id'), feature.id())
                layer_dissolved_clean.updateFeature(feature)

        # returning function output
        return QgsProject.instance().addMapLayer(layer_dissolved_clean)

my_class = LayerIntoParts('test_area_4', 2)
my_class.dissolve_result()


Muito obrigado!!

EA






image.gif

test.dbf
test.shx
test.shp
test.prj

Hebert Azevedo Consultor Geo

unread,
Feb 28, 2021, 9:45:03 AM2/28/21
to qgisb...@googlegroups.com
Eddison, 

encontrei o problema. Nesta classe abaixo os espaçamentos horizontais e verticais, identificados em vermelho, estão muito grandes


        # creating grid for the layer with 'qgis:creategrid' algorithm
        layer_grid = processing.run('qgis:creategrid',
            {'TYPE': 2,
            'CRS': param['layer_crs'],
            'EXTENT': param['layer_extent'],
            'HSPACING': 10000,
            'VSPACING': 10000,
            'HOVERLAY': 0,
            'VOVERLAY': 0,
            'OUTPUT': "memory:"}
        )["OUTPUT"]

Tente trocar por um valor menor, 10, por exemplo.

Att

Hebert Guilherme de Azevedo - Consultor em Geotecnologias

Adquira nosso curso sobre customização de formulários no QGIS pelo link https://www.udemy.com/course/customizacao-de-formulario-qgis/?referralCode=C4191B7F6339523504BC
Veja nossos cursos na plataforma Udemy: https://www.udemy.com/user/hebert-azevedo-2/
Inscreva-se e acompanhe nosso blog: http://bit.ly/2CL63UZ
Inscreva-se e acompanhe nosso canal Youtube: http://bit.ly/2J0H2Wa
Curta e acompanhe nossa página no Facebook: http://bit.ly/2yGErMp
Acompanhe nosso twitter: https://twitter.com/consultorgeo


--
Comunidade QGIS Brasil: http://qgisbrasil.org/
---
You received this message because you are subscribed to the Google Groups "qgisbrasil" group.
To unsubscribe from this group and stop receiving emails from it, send an email to qgisbrasil+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/qgisbrasil/CAC-LqC%3DiTp77TZow3237dWvK9gR9pOO4woWPmT4d%3DeXV%3DCikyw%40mail.gmail.com.


--


Mailtrack Remetente notificado por
Mailtrack 28/02/21 11:44:26
Reply all
Reply to author
Forward
0 new messages