Resurrect grid polygon algorithm

This commit is contained in:
Nyall Dawson 2017-06-09 15:31:25 +10:00
parent d8260b8c47
commit ea18e8e9db
5 changed files with 172 additions and 153 deletions

View File

@ -37,15 +37,17 @@ from qgis.core import (QgsRectangle,
QgsGeometry,
QgsPointXY,
QgsWkbTypes,
QgsProcessingParameterEnum,
QgsProcessingParameterExtent,
QgsProcessingParameterNumber,
QgsProcessingParameterCrs,
QgsProcessingParameterFeatureSink,
QgsProcessingOutputVectorLayer,
QgsProcessingParameterDefinition,
QgsFields)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterExtent
from processing.core.parameters import ParameterNumber
from processing.core.parameters import ParameterSelection
from processing.core.parameters import ParameterCrs
from processing.core.outputs import OutputVector
from processing.tools import dataobjects
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
@ -76,21 +78,28 @@ class GridPolygon(QgisAlgorithm):
self.tr('Diamond (polygon)'),
self.tr('Hexagon (polygon)')]
self.addParameter(ParameterSelection(self.TYPE,
self.tr('Grid type'), self.types))
self.addParameter(ParameterExtent(self.EXTENT,
self.tr('Grid extent'), optional=False))
self.addParameter(ParameterNumber(self.HSPACING,
self.tr('Horizontal spacing'), 0.0, 1000000000.0, 0.0001))
self.addParameter(ParameterNumber(self.VSPACING,
self.tr('Vertical spacing'), 0.0, 1000000000.0, 0.0001))
self.addParameter(ParameterNumber(self.HOVERLAY,
self.tr('Horizontal overlay'), 0.0, 1000000000.0, 0.0))
self.addParameter(ParameterNumber(self.VOVERLAY,
self.tr('Vertical overlay'), 0.0, 1000000000.0, 0.0))
self.addParameter(ParameterCrs(self.CRS, 'Grid CRS', 'EPSG:4326'))
self.addParameter(QgsProcessingParameterEnum(self.TYPE,
self.tr('Grid type'), self.types))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Grid'), datatype=[dataobjects.TYPE_VECTOR_POLYGON]))
self.addParameter(QgsProcessingParameterExtent(self.EXTENT, self.tr('Grid extent')))
self.addParameter(QgsProcessingParameterNumber(self.HSPACING,
self.tr('Horizontal spacing'), QgsProcessingParameterNumber.Double,
0.0001, False, 0, 1000000000.0))
self.addParameter(QgsProcessingParameterNumber(self.VSPACING,
self.tr('Vertical spacing'), QgsProcessingParameterNumber.Double,
0.0001, False, 0, 1000000000.0))
self.addParameter(QgsProcessingParameterNumber(self.HOVERLAY,
self.tr('Horizontal overlay'), QgsProcessingParameterNumber.Double,
0.0, False, 0, 1000000000.0))
self.addParameter(QgsProcessingParameterNumber(self.VOVERLAY,
self.tr('Vertical overlay'), QgsProcessingParameterNumber.Double,
0.0, False, 0, 1000000000.0))
self.addParameter(QgsProcessingParameterCrs(self.CRS, 'Grid CRS', 'ProjectCrs'))
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Grid')))
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Grid'), QgsProcessingParameterDefinition.TypeVectorPolygon))
def name(self):
return 'creategridpolygon'
@ -99,16 +108,15 @@ class GridPolygon(QgisAlgorithm):
return self.tr('Create grid (polygon)')
def processAlgorithm(self, parameters, context, feedback):
idx = self.getParameterValue(self.TYPE)
extent = self.getParameterValue(self.EXTENT).split(',')
hSpacing = self.getParameterValue(self.HSPACING)
vSpacing = self.getParameterValue(self.VSPACING)
hOverlay = self.getParameterValue(self.HOVERLAY)
vOverlay = self.getParameterValue(self.VOVERLAY)
crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.CRS))
idx = self.parameterAsEnum(parameters, self.TYPE, context)
bbox = QgsRectangle(float(extent[0]), float(extent[2]),
float(extent[1]), float(extent[3]))
hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context)
vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context)
hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context)
vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context)
bbox = self.parameterAsExtent(parameters, self.EXTENT, context)
crs = self.parameterAsCrs(parameters, self.CRS, context)
width = bbox.width()
height = bbox.height()
@ -138,21 +146,22 @@ class GridPolygon(QgisAlgorithm):
fields.append(QgsField('bottom', QVariant.Double, '', 24, 16))
fields.append(QgsField('id', QVariant.Int, '', 10, 0))
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Polygon, crs, context)
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, QgsWkbTypes.Polygon, crs)
if idx == 0:
self._rectangleGrid(
writer, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
elif idx == 1:
self._diamondGrid(
writer, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
elif idx == 2:
self._hexagonGrid(
writer, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
del writer
return {self.OUTPUT: dest_id}
def _rectangleGrid(self, writer, width, height, originX, originY,
def _rectangleGrid(self, sink, width, height, originX, originY,
hSpacing, vSpacing, hOverlay, vOverlay, feedback):
ft = QgsFeature()
@ -166,6 +175,9 @@ class GridPolygon(QgisAlgorithm):
count = 0
for col in range(columns):
if feedback.isCanceled():
break
x1 = originX + (col * hSpacing - col * hOverlay)
x2 = x1 + hSpacing
@ -182,14 +194,14 @@ class GridPolygon(QgisAlgorithm):
ft.setGeometry(QgsGeometry.fromPolygon([polyline]))
ft.setAttributes([x1, y1, x2, y2, id])
writer.addFeature(ft)
sink.addFeature(ft)
id += 1
count += 1
if int(math.fmod(count, count_update)) == 0:
feedback.setProgress(int(count / cells * 100))
def _diamondGrid(self, writer, width, height, originX, originY,
def _diamondGrid(self, sink, width, height, originX, originY,
hSpacing, vSpacing, hOverlay, vOverlay, feedback):
ft = QgsFeature()
@ -209,6 +221,9 @@ class GridPolygon(QgisAlgorithm):
count = 0
for col in range(columns):
if feedback.isCanceled():
break
x = originX - (col * halfHOverlay)
x1 = x + ((col + 0) * halfHSpacing)
x2 = x + ((col + 1) * halfHSpacing)
@ -234,13 +249,13 @@ class GridPolygon(QgisAlgorithm):
ft.setGeometry(QgsGeometry.fromPolygon([polyline]))
ft.setAttributes([x1, y1, x3, y3, id])
writer.addFeature(ft)
sink.addFeature(ft)
id += 1
count += 1
if int(math.fmod(count, count_update)) == 0:
feedback.setProgress(int(count / cells * 100))
def _hexagonGrid(self, writer, width, height, originX, originY,
def _hexagonGrid(self, sink, width, height, originX, originY,
hSpacing, vSpacing, hOverlay, vOverlay, feedback):
ft = QgsFeature()
@ -269,6 +284,9 @@ class GridPolygon(QgisAlgorithm):
count = 0
for col in range(columns):
if feedback.isCanceled():
break
# (column + 1) and (row + 1) calculation is used to maintain
# topology between adjacent shapes and avoid overlaps/holes
# due to rounding errors
@ -298,7 +316,7 @@ class GridPolygon(QgisAlgorithm):
ft.setGeometry(QgsGeometry.fromPolygon([polyline]))
ft.setAttributes([x1, y1, x4, y3, id])
writer.addFeature(ft)
sink.addFeature(ft)
id += 1
count += 1
if int(math.fmod(count, count_update)) == 0:

View File

@ -92,7 +92,7 @@ from .DeleteColumn import DeleteColumn
# from .TextToFloat import TextToFloat
# from .ExtractByAttribute import ExtractByAttribute
# from .SelectByAttribute import SelectByAttribute
# from .GridPolygon import GridPolygon
from .GridPolygon import GridPolygon
# from .GridLine import GridLine
# from .Gridify import Gridify
# from .HubDistancePoints import HubDistancePoints
@ -217,7 +217,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
# SpatialJoin(), RegularPoints(), SymmetricalDifference(),
# VectorSplit(), VectorGridLines(), VectorGridPolygons(),
# DeleteDuplicateGeometries(), TextToFloat(),
# ExtractByAttribute(), SelectByAttribute(), GridPolygon(),
# ExtractByAttribute(), SelectByAttribute(),
# GridLine(), Gridify(), HubDistancePoints(),
# HubDistanceLines(), HubLines(), Merge(),
# GeometryConvert(), FieldsCalculator(),
@ -269,7 +269,8 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
Clip(),
DeleteColumn(),
ExtentFromLayer(),
ExtractByExpression()
ExtractByExpression(),
GridPolygon()
]
if hasPlotly:

View File

@ -515,7 +515,7 @@ class ParameterNumber(Parameter):
def _layerVariables(self, element, alg=None):
variables = {}
context = dataobjects.createContext()
context = createContext()
layer = QgsProcessingUtils.mapLayerFromString(element.value, context)
if layer is not None:
name = element.name if alg is None else "%s_%s" % (alg.name, element.name)

View File

@ -39,6 +39,7 @@ from qgis.core import (QgsProcessingUtils,
QgsProject)
from processing.gui.RectangleMapTool import RectangleMapTool
from processing.core.ProcessingConfig import ProcessingConfig
from processing.tools.dataobjects import createContext
pluginPath = os.path.split(os.path.dirname(__file__))[0]
WIDGET, BASE = uic.loadUiType(
@ -65,15 +66,14 @@ class ExtentSelectionPanel(BASE, WIDGET):
self.tool = RectangleMapTool(canvas)
self.tool.rectangleCreated.connect(self.updateExtent)
if param.default:
tokens = param.default.split(',')
if len(tokens) == 4:
if param.defaultValue() is not None:
context = createContext()
rect = QgsProcessingParameters.parameterAsExtent(param, {param.name(): param.defaultValue()}, context)
if not rect.isNull():
try:
float(tokens[0])
float(tokens[1])
float(tokens[2])
float(tokens[3])
self.leText.setText(param.default)
s = '{},{},{},{}'.format(
rect.xMinimum(), rect.xMaximum(), rect.yMinimum(), rect.yMaximum())
self.leText.setText(s)
except:
pass

View File

@ -1692,54 +1692,54 @@ tests:
# geometry:
# precision: 7
#
# - algorithm: qgis:creategridpolygon
# name: Create grid (rectangles)
# params:
# CRS: EPSG:4326
# EXTENT: -1,11.2,-4,6.5
# HSPACING: 5.0
# TYPE: '0'
# VSPACING: 3.0
# results:
# OUTPUT:
# name: expected/grid_rectangles.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: qgis:creategridpolygon
# name: Create grid (diamond)
# params:
# CRS: EPSG:4326
# EXTENT: -1,11.2,-4,6.5
# HSPACING: 5.0
# TYPE: '1'
# VSPACING: 3.0
# results:
# OUTPUT:
# name: expected/grid_diamond.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: qgis:creategridpolygon
# name: Create grid (hexagon)
# params:
# CRS: EPSG:4326
# EXTENT: -1,11.2,-4,6.5
# HSPACING: 5.0
# TYPE: '2'
# VSPACING: 5.0
# results:
# OUTPUT:
# name: expected/grid_hexagon.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
- algorithm: qgis:creategridpolygon
name: Create grid (rectangles)
params:
CRS: EPSG:4326
EXTENT: -1,11.2,-4,6.5
HSPACING: 5.0
TYPE: '0'
VSPACING: 3.0
results:
OUTPUT:
name: expected/grid_rectangles.gml
type: vector
compare:
geometry:
precision: 7
- algorithm: qgis:creategridpolygon
name: Create grid (diamond)
params:
CRS: EPSG:4326
EXTENT: -1,11.2,-4,6.5
HSPACING: 5.0
TYPE: '1'
VSPACING: 3.0
results:
OUTPUT:
name: expected/grid_diamond.gml
type: vector
compare:
geometry:
precision: 7
- algorithm: qgis:creategridpolygon
name: Create grid (hexagon)
params:
CRS: EPSG:4326
EXTENT: -1,11.2,-4,6.5
HSPACING: 5.0
TYPE: '2'
VSPACING: 5.0
results:
OUTPUT:
name: expected/grid_hexagon.gml
type: vector
compare:
geometry:
precision: 7
# - algorithm: qgis:creategridlines
# name: Create grid (lines with overlay)
# params:
@ -1754,60 +1754,60 @@ tests:
# name: expected/grid_lines_overlay.gml
# type: vector
#
# - algorithm: qgis:creategridpolygon
# name: Create grid (rectangle with overlay)
# params:
# CRS: EPSG:4326
# EXTENT: -1,11.2,-4,6.5
# HOVERLAY: 2.0
# HSPACING: 5.0
# TYPE: '0'
# VOVERLAY: 1.0
# VSPACING: 3.0
# results:
# OUTPUT:
# name: expected/grid_rectangle_overlay.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: qgis:creategridpolygon
# name: Create grid (diamond with overlay)
# params:
# CRS: EPSG:4326
# EXTENT: -1,11.2,-4,6.5
# HOVERLAY: 2.0
# HSPACING: 5.0
# TYPE: '1'
# VOVERLAY: 1.0
# VSPACING: 3.0
# results:
# OUTPUT:
# name: expected/grid_diamond_overlay.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: qgis:creategridpolygon
# name: Create grid (hexagon with overlay)
# params:
# CRS: EPSG:4326
# EXTENT: -1,11.2,-4,6.5
# HOVERLAY: 2.0
# HSPACING: 5.0
# TYPE: '2'
# VOVERLAY: 1.0
# VSPACING: 5.0
# results:
# OUTPUT:
# name: expected/grid_hexagon_overlay.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
- algorithm: qgis:creategridpolygon
name: Create grid (rectangle with overlay)
params:
CRS: EPSG:4326
EXTENT: -1,11.2,-4,6.5
HOVERLAY: 2.0
HSPACING: 5.0
TYPE: '0'
VOVERLAY: 1.0
VSPACING: 3.0
results:
OUTPUT:
name: expected/grid_rectangle_overlay.gml
type: vector
compare:
geometry:
precision: 7
- algorithm: qgis:creategridpolygon
name: Create grid (diamond with overlay)
params:
CRS: EPSG:4326
EXTENT: -1,11.2,-4,6.5
HOVERLAY: 2.0
HSPACING: 5.0
TYPE: '1'
VOVERLAY: 1.0
VSPACING: 3.0
results:
OUTPUT:
name: expected/grid_diamond_overlay.gml
type: vector
compare:
geometry:
precision: 7
- algorithm: qgis:creategridpolygon
name: Create grid (hexagon with overlay)
params:
CRS: EPSG:4326
EXTENT: -1,11.2,-4,6.5
HOVERLAY: 2.0
HSPACING: 5.0
TYPE: '2'
VOVERLAY: 1.0
VSPACING: 5.0
results:
OUTPUT:
name: expected/grid_hexagon_overlay.gml
type: vector
compare:
geometry:
precision: 7
# - algorithm: qgis:deleteholes
# name: Delete holes (no min)
# params: