mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[processing] turn keep n biggest parts script into normal algorithm
This commit is contained in:
parent
54167bcaa6
commit
15a185dab0
@ -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})
|
||||
|
107
python/plugins/processing/algs/qgis/KeepNBiggestParts.py
Normal file
107
python/plugins/processing/algs/qgis/KeepNBiggestParts.py
Normal 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}
|
@ -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(),
|
||||
|
@ -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)
|
45
python/plugins/processing/tests/testdata/expected/biggest_parts.gml
vendored
Normal file
45
python/plugins/processing/tests/testdata/expected/biggest_parts.gml
vendored
Normal 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>
|
43
python/plugins/processing/tests/testdata/expected/biggest_parts.xsd
vendored
Normal file
43
python/plugins/processing/tests/testdata/expected/biggest_parts.xsd
vendored
Normal 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>
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user