[processing] turn keep n biggest parts script into normal algorithm

This commit is contained in:
Alexander Bruy 2018-02-04 14:46:01 +02:00
parent 54167bcaa6
commit 15a185dab0
7 changed files with 209 additions and 49 deletions

View File

@ -1,9 +1,4 @@
FILE(GLOB PY_FILES *.py)
FILE(GLOB HELP_FILES help/*.rst)
FILE(GLOB SCRIPT_FILES scripts/*.*)
ADD_SUBDIRECTORY(ui)
PLUGIN_INSTALL(processing algs/qgis ${PY_FILES})
PLUGIN_INSTALL(processing algs/qgis/help ${HELP_FILES})
PLUGIN_INSTALL(processing algs/qgis/scripts ${SCRIPT_FILES})

View File

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
KeepNBiggestParts.py
---------------------
Date : July 2014
Copyright : (C) 2014 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* 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. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'July 2014'
__copyright__ = '(C) 2014, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from operator import itemgetter
from qgis.core import (QgsGeometry,
QgsFeatureSink,
QgsProcessing,
QgsProcessingParameterFeatureSink,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterNumber,
)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
class KeepNBiggestParts(QgisAlgorithm):
POLYGONS = 'POLYGONS'
PARTS = 'PARTS'
OUTPUT = 'OUTPUT'
def group(self):
return self.tr('Vector geometry')
def groupId(self):
return 'vectorgeometry'
def __init__(self):
super().__init__()
def initAlgorithm(self, config=None):
self.addParameter(QgsProcessingParameterFeatureSource(self.POLYGONS,
self.tr('Polygons'), [QgsProcessing.TypeVectorPolygon]))
self.addParameter(QgsProcessingParameterNumber(self.PARTS,
self.tr('Parts to keep'),
QgsProcessingParameterNumber.Integer,
1, False, 1))
self.addParameter(
QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Parts'), QgsProcessing.TypeVectorPolygon))
def name(self):
return 'keepnbiggestparts'
def displayName(self):
return self.tr('Keep N biggest parts')
def processAlgorithm(self, parameters, context, feedback):
source = self.parameterAsSource(parameters, self.POLYGONS, context)
parts = self.parameterAsInt(parameters, self.PARTS, context)
fields = source.fields()
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
source.fields(), source.wkbType(), source.sourceCrs())
features = source.getFeatures()
total = 100.0 / source.featureCount() if source.featureCount() else 0
for current, feat in enumerate(features):
if feedback.isCanceled():
break
geom = feat.geometry()
if geom.isMultipart():
out_feature = feat
geoms = geom.asGeometryCollection()
geom_area = [(i, geoms[i].area()) for i in range(len(geoms))]
geom_area.sort(key=itemgetter(1))
if parts == 1:
out_feature.setGeometry(geoms[geom_area[-1][0]])
elif parts > len(geoms):
out_feature.setGeometry(geom)
else:
out_feature.setGeometry(geom)
geomres = [geoms[i].asPolygon() for i, a in geom_area[-1 * parts:]]
out_feature.setGeometry(QgsGeometry.fromMultiPolygonXY(geomres))
sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
else:
sink.addFeature(feat, QgsFeatureSink.FastInsert)
feedback.setProgress(int(current * total))
return {self.OUTPUT: dest_id}

View File

@ -80,6 +80,7 @@ from .IdwInterpolation import IdwInterpolation
from .ImportIntoPostGIS import ImportIntoPostGIS
from .ImportIntoSpatialite import ImportIntoSpatialite
from .Intersection import Intersection
from .KeepNBiggestParts import KeepNBiggestParts
from .LinesToPolygons import LinesToPolygons
from .MinimumBoundingGeometry import MinimumBoundingGeometry
from .NearestNeighbourAnalysis import NearestNeighbourAnalysis
@ -200,6 +201,7 @@ class QgisAlgorithmProvider(QgsProcessingProvider):
ImportIntoPostGIS(),
ImportIntoSpatialite(),
Intersection(),
KeepNBiggestParts(),
LinesToPolygons(),
MinimumBoundingGeometry(),
NearestNeighbourAnalysis(),

View File

@ -1,44 +0,0 @@
##Vector geometry=group
#inputs
##Polygons=source polygon
##To_keep=number 1
##Biggest parts=sink polygon
from qgis.core import QgsGeometry, QgsWkbTypes, QgsProcessingUtils
from operator import itemgetter
To_keep = int(To_keep)
if To_keep < 1:
feedback.pushInfo("'To keep' value has been modified to be at least 1.")
To_keep = 1
count = Polygons.featureCount()
(sink, Biggest_parts) = self.parameterAsSink(parameters, 'Biggest parts', context,
Polygons.fields(), QgsWkbTypes.MultiPolygon, Polygons.sourceCrs())
for n, feat in enumerate(Polygons.getFeatures()):
if feedback.isCanceled():
break
feedback.setProgress(int(100 * n / count))
geom = feat.geometry()
if geom.isMultipart():
features = feat
geoms = geom.asGeometryCollection()
geomarea = [(i, geoms[i].area()) for i in range(len(geoms))]
geomarea.sort(key=itemgetter(1))
if To_keep == 1:
features.setGeometry(geoms[geomarea[-1][0]])
elif To_keep > len(geoms):
features.setGeometry(geom)
else:
features.setGeometry(geom)
geomres = [geoms[i].asPolygon() for i, a in geomarea[-1 * To_keep:]]
features.setGeometry(QgsGeometry.fromMultiPolygonXY(geomres))
sink.addFeature(features)
else:
sink.addFeature(feat)

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ biggest_parts.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>0</gml:X><gml:Y>-1</gml:Y></gml:coord>
<gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<ogr:biggest_parts fid="multipolys.0">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,1 2,2 3,2 3,3 4,3 4,1 2,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:Bname>Test</ogr:Bname>
<ogr:Bintval>1</ogr:Bintval>
<ogr:Bfloatval>0.123</ogr:Bfloatval>
</ogr:biggest_parts>
</gml:featureMember>
<gml:featureMember>
<ogr:biggest_parts fid="multipolys.1">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>7,-1 8,-1 8,3 7,3 7,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:Bname xsi:nil="true"/>
<ogr:Bintval xsi:nil="true"/>
<ogr:Bfloatval xsi:nil="true"/>
</ogr:biggest_parts>
</gml:featureMember>
<gml:featureMember>
<ogr:biggest_parts fid="multipolys.2">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0,0 0,1 1,1 1,0 0,0</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:Bname>Test</ogr:Bname>
<ogr:Bintval>2</ogr:Bintval>
<ogr:Bfloatval>-0.123</ogr:Bfloatval>
</ogr:biggest_parts>
</gml:featureMember>
<gml:featureMember>
<ogr:biggest_parts fid="multipolys.3">
<ogr:Bname>Test</ogr:Bname>
<ogr:Bintval>3</ogr:Bintval>
<ogr:Bfloatval>0</ogr:Bfloatval>
</ogr:biggest_parts>
</gml:featureMember>
</ogr:FeatureCollection>

View File

@ -0,0 +1,43 @@
<?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="biggest_parts" type="ogr:biggest_parts_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="biggest_parts_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:MultiPolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
<xs:element name="Bname" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="4"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Bintval" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Bfloatval" 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>

View File

@ -4676,3 +4676,15 @@ tests:
OUTPUT:
name: expected/removed_duplicated_nodes_line.gml
type: vector
- algorithm: qgis:keepnbiggestparts
name: Keep N biggest parts
params:
PARTS: 1
POLYGONS:
name: multipolys.gml
type: vector
results:
OUTPUT:
name: expected/biggest_parts.gml
type: vector