I am trying to split polygons into equally sized pieces using a grid. The polygons are all image segments derived from 2.4 meter satellite imagery. So each polygon is a grouping of 2.4m x 2.4m squares. I want to produce a QGIS processing tool to simplify my current workflow of individually running the "Create Grid" and "Split with Lines" QGIS processing tools. The workflow should also edit the selected polygon in the existing layer, not create a new layer.
Example input polygon (with the polygon to be split selected):enter image description here
Expected output from processing tool: enter image description here
from qgis.core import *
from qgis.gui import *
import qgis.utils
import processing
import re
from PyQt5.QtCore import *
#the spacing of the cut grid
cell_size = 2.4
#get current layer, selection, CRS from QGIS map canvas
layer = qgis.utils.iface.activeLayer()
selected = layer.selectedFeatures()
crs = qgis.utils.iface.activeLayer().crs().authid()
for lay in selected:
#get the ID of the feature we've selected in QGIS map canvas
id = lay.id
print("working on: " + str(id))
#get the extent of the selected feature
x_max, y_max, x_min, y_min = re.split(":|,", lay.geometry().boundingBox().toString().replace(" ", ""))
extent = x_min + "," + x_max + "," + y_min + "," + y_max
print(extent)
#create our grid in memory
grid_parameters = {"TYPE": 1,
"EXTENT": extent,
"HSPACING": cell_size,
"VSPACING":cell_size,
"HOVERLAY": 0,
"VOVERLAY": 0,
"CRS": crs,
"OUTPUT": "memory_grid"}
grid = processing.run("qgis:creategrid", grid_parameters)
#split the selected feature, store the results in memory
split_parameters = {"INPUT": layer.getFeature(id),
"LINES": grid["OUTPUT"],
"OUTPUT": "memory_split"}
split = processing.run("qgis:splitwithlines", split_parameters)
#delete the original feature, add the split results to the original layer
with edit(layer):
layer.deleteFeature(id)
layer.addFeatures(split["OUTPUT"])
When I run this code I get an error on line 39 (split parameters dictionary) that reads: "TypeError: QgsVectorLayer.getFeature: argument 1 has unexpected type 'builtin_function_or_method"
I have tried several different approaches, including directly feeding my selection, the entire layer, layer.getFeatures(), etc. but nothing has been an acceptable input for the Split with Lines tool.
2 Answers 2
If you don't need a script, "Create Grid" and "Intersection" tool are enough to solve your problem.
"Create Grid" tool: For CRS, select your layer CRS. (In this case, CRS must be projected, not geographic)
Result of "Create Grid":
"Intersection" tool:
Final Result:
Output Attribute Table: ('Segment_x' comes from polygons and expresses that which segment/polygon the grid is in)
If pixel size is 2.4, result will be as you need.
-
Thanks for taking a look. This is essentially the approach I am currently using and attempting to implement in the script. However, I am performing this workflow 1000s of times, and hand-entering the parameters and executing the workflow is tedious. Also, I would like the approach to edit the existing layer, not produce a new layer.rosswin– rosswin2018年04月19日 02:03:30 +00:00Commented Apr 19, 2018 at 2:03
-
Have you tried using the Graphical Modeler to automate your process?csk– csk2018年04月23日 19:09:16 +00:00Commented Apr 23, 2018 at 19:09
Final, working code. I mimplemented this in QGIS 2.18.19 since there is more material on PyQGIS and it still suits my workflows.
from qgis.core import *
from qgis.gui import *
import qgis.utils
import processing
import re
from PyQt4.QtCore import *
cell_size = 2.4
layer = qgis.utils.iface.activeLayer()
selected = layer.selectedFeatures()
crs = qgis.utils.iface.activeLayer().crs().authid()
ids = []
x_maxs = []
x_mins = []
y_maxs = []
y_mins = []
for lay in selected:
id = lay.id()
ids.append(id)
print("working on: " + str(id))
x_min, y_min, x_max, y_max = re.split(":|,", lay.geometry().boundingBox().toString().replace(" ", ""))
x_mins.append(float(x_min))
x_maxs.append(float(x_max))
y_mins.append(float(y_min))
y_maxs.append(float(y_max))
extent = str(min(x_mins)) + "," + str(max(x_maxs)) + "," + str(min(y_mins)) + "," + str(max(y_maxs))
print(extent)
grid_parameters = {"TYPE": 1,
"EXTENT": extent,
"HSPACING": cell_size,
"VSPACING":cell_size,
#"HOVERLAY": 0,
#"VOVERLAY": 0,
"CRS": crs,
"OUTPUT": None}
grid = processing.runalg("qgis:creategrid", grid_parameters)
intersection_parameters = {"INPUT": layer,
"INPUT2": grid["OUTPUT"],
"IGNORE_NULL": True,
"OUTPUT": None}
intersect = processing.runalg("qgis:intersection", intersection_parameters)
mem_intersect = QgsVectorLayer(intersect["OUTPUT"], "lyr_intersect", "ogr")
fields_to_delete = []
fieldnames = set(["left", "right", "top", "bottom"])
for field in mem_intersect.fields():
if field.name() in fieldnames:
fields_to_delete.append(mem_intersect.fieldNameIndex(field.name()))
mem_intersect.dataProvider().deleteAttributes(fields_to_delete)
mem_intersect.updateFields()
features = []
for feat in mem_intersect.getFeatures():
features.append(feat)
with edit(layer):
layer.deleteFeatures(ids)
layer.dataProvider().addFeatures(features)
id = lay.id
withid = lay.id()