Skip to content

Commit

Permalink
Merge pull request #9908 from raymondnijssen/roundextent
Browse files Browse the repository at this point in the history
Round values in ExtentFromLayer processing algorithm
  • Loading branch information
m-kuhn committed May 13, 2019
2 parents 84a9891 + 6e62c02 commit 6a3cd82
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 2 deletions.
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/help/qgis.yaml
Expand Up @@ -334,7 +334,7 @@ qgis:polygoncentroids: >
NOTE: This algorithm is deprecated and the generic "centroids" algorithm (which works for line and multi geometry layers) should be used instead.

qgis:polygonfromlayerextent: >
This algorithm takes a map layer and generates a new vector layer with the minimum bounding box (rectangle with N-S orientation) that covers the input layer.
This algorithm takes a map layer and generates a new vector layer with the minimum bounding box (rectangle polygon with N-S orientation) that covers the input layer. Optionally, the extent can be enlarged to a rounded value.

qgis:polygonize: >
This algorithm takes a lines layer and creates a polygon layer, with polygons generated from the lines in the input layer.
Expand Down
25 changes: 24 additions & 1 deletion python/plugins/processing/algs/qgis/ExtentFromLayer.py
Expand Up @@ -26,6 +26,7 @@
__revision__ = '$Format:%H$'

import os
from math import floor, ceil

from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtCore import QVariant
Expand All @@ -39,6 +40,8 @@
QgsProcessing,
QgsProcessingException,
QgsProcessingParameterMapLayer,
QgsProcessingParameterDistance,
QgsProcessingParameterDefinition,
QgsProcessingParameterFeatureSink,
QgsFields)

Expand All @@ -51,6 +54,7 @@ class ExtentFromLayer(QgisAlgorithm):

INPUT = 'INPUT'
BY_FEATURE = 'BY_FEATURE'
ROUND_TO = 'ROUND_TO'

OUTPUT = 'OUTPUT'

Expand All @@ -61,7 +65,7 @@ def svgIconPath(self):
return QgsApplication.iconPath("/algorithms/mAlgorithmExtractLayerExtent.svg")

def tags(self):
return self.tr('polygon,from,vector,raster,extent,envelope,bounds,bounding,boundary,layer').split(',')
return self.tr('polygon,vector,raster,extent,envelope,bounds,bounding,boundary,layer,round,rounded').split(',')

def group(self):
return self.tr('Layer tools')
Expand All @@ -74,6 +78,15 @@ def __init__(self):

def initAlgorithm(self, config=None):
self.addParameter(QgsProcessingParameterMapLayer(self.INPUT, self.tr('Input layer')))

round_to_parameter = QgsProcessingParameterDistance(self.ROUND_TO,
self.tr('Round values to'),
parentParameterName=self.INPUT,
minValue=0,
defaultValue=0)
round_to_parameter.setFlags(round_to_parameter.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
self.addParameter(round_to_parameter)

self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Extent'), type=QgsProcessing.TypeVectorPolygon))

def name(self):
Expand All @@ -85,6 +98,8 @@ def displayName(self):
def processAlgorithm(self, parameters, context, feedback):
layer = self.parameterAsLayer(parameters, self.INPUT, context)

round_to = self.parameterAsDouble(parameters, self.ROUND_TO, context)

fields = QgsFields()
fields.append(QgsField('MINX', QVariant.Double))
fields.append(QgsField('MINY', QVariant.Double))
Expand All @@ -109,7 +124,15 @@ def processAlgorithm(self, parameters, context, feedback):
pass

rect = layer.extent()

if round_to > 0:
rect.setXMinimum(floor(rect.xMinimum() / round_to) * round_to)
rect.setYMinimum(floor(rect.yMinimum() / round_to) * round_to)
rect.setXMaximum(ceil(rect.xMaximum() / round_to) * round_to)
rect.setYMaximum(ceil(rect.yMaximum() / round_to) * round_to)

geometry = QgsGeometry.fromRect(rect)

minx = rect.xMinimum()
miny = rect.yMinimum()
maxx = rect.xMaximum()
Expand Down
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ polygon_from_extent_rounded_2.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-2</gml:X><gml:Y>-4</gml:Y></gml:coord>
<gml:coord><gml:X>12</gml:X><gml:Y>6</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:polygon_from_extent_rounded_2 fid="polygon_from_extent_rounded_2.0">
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-2,-4 12,-4 12,6 -2,6 -2,-4</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
<ogr:MINX>-2</ogr:MINX>
<ogr:MINY>-4</ogr:MINY>
<ogr:MAXX>12</ogr:MAXX>
<ogr:MAXY>6</ogr:MAXY>
<ogr:CNTX>5</ogr:CNTX>
<ogr:CNTY>1</ogr:CNTY>
<ogr:AREA>140</ogr:AREA>
<ogr:PERIM>48</ogr:PERIM>
<ogr:HEIGHT>10</ogr:HEIGHT>
<ogr:WIDTH>14</ogr:WIDTH>
</ogr:polygon_from_extent_rounded_2>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
<xs:complexType name="FeatureCollectionType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureCollectionType">
<xs:attribute name="lockId" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="polygon_from_extent_rounded_2" type="ogr:polygon_from_extent_rounded_2_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="polygon_from_extent_rounded_2_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
<xs:element name="MINX" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="MINY" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="MAXX" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="MAXY" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="CNTX" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="CNTY" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="AREA" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="PERIM" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="HEIGHT" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="WIDTH" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
26 changes: 26 additions & 0 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Expand Up @@ -1801,4 +1801,30 @@ tests:
name: expected/multipoint_delaunay.gml
type: vector

- algorithm: qgis:polygonfromlayerextent
name: Polygon from layer extent rounded to 0
params:
BY_FEATURE: false
INPUT:
name: polys.gml
type: vector
ROUND_TO: 0.0
results:
OUTPUT:
name: expected/polygon_from_extent.gml
type: vector

- algorithm: qgis:polygonfromlayerextent
name: Polygon from layer extent rounded to 2
params:
BY_FEATURE: false
INPUT:
name: lines.gml
type: vector
ROUND_TO: 2.0
results:
OUTPUT:
name: expected/polygon_from_extent_rounded_2.gml
type: vector

# See ../README.md for a description of the file format

0 comments on commit 6a3cd82

Please sign in to comment.