mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-17 00:04:02 -04:00
Merge pull request #5241 from nyalldawson/clean_code
[processing] Code cleanups
This commit is contained in:
commit
53aba6109c
@ -294,14 +294,6 @@ qgis:listuniquevalues: >
|
||||
|
||||
qgis:meanandstandarddeviationplot:
|
||||
|
||||
|
||||
qgis:meancoordinates: >
|
||||
This algorithm computes a point layer with the center of mass of geometries in an input layer.
|
||||
|
||||
An attribute can be specified as containing weights to be applied to each feature when computing the center of mass.
|
||||
|
||||
If an attribute is selected in the <Unique ID field> parameters, features will be grouped according to values in this field. Instead of a single point with the center of mass of the whole layer, the output layer will contain a center of mass for the features in each category.
|
||||
|
||||
qgis:mergevectorlayers: >
|
||||
This algorithm combines multiple vector layers of the same geometry type into a single one.
|
||||
|
||||
|
@ -32,9 +32,11 @@ from qgis.PyQt.QtCore import QVariant
|
||||
|
||||
from qgis.core import (QgsCoordinateTransform,
|
||||
QgsField,
|
||||
QgsFields,
|
||||
QgsWkbTypes,
|
||||
QgsFeatureSink,
|
||||
QgsDistanceArea,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessingParameterFeatureSink)
|
||||
@ -89,28 +91,23 @@ class ExportGeometryInfo(QgisAlgorithm):
|
||||
wkb_type = source.wkbType()
|
||||
fields = source.fields()
|
||||
|
||||
new_fields = QgsFields()
|
||||
if QgsWkbTypes.geometryType(wkb_type) == QgsWkbTypes.PolygonGeometry:
|
||||
areaName = vector.createUniqueFieldName('area', fields)
|
||||
fields.append(QgsField(areaName, QVariant.Double))
|
||||
perimeterName = vector.createUniqueFieldName('perimeter', fields)
|
||||
fields.append(QgsField(perimeterName, QVariant.Double))
|
||||
new_fields.append(QgsField('area', QVariant.Double))
|
||||
new_fields.append(QgsField('perimeter', QVariant.Double))
|
||||
elif QgsWkbTypes.geometryType(wkb_type) == QgsWkbTypes.LineGeometry:
|
||||
lengthName = vector.createUniqueFieldName('length', fields)
|
||||
fields.append(QgsField(lengthName, QVariant.Double))
|
||||
new_fields.append(QgsField('length', QVariant.Double))
|
||||
else:
|
||||
xName = vector.createUniqueFieldName('xcoord', fields)
|
||||
fields.append(QgsField(xName, QVariant.Double))
|
||||
yName = vector.createUniqueFieldName('ycoord', fields)
|
||||
fields.append(QgsField(yName, QVariant.Double))
|
||||
new_fields.append(QgsField('xcoord', QVariant.Double))
|
||||
new_fields.append(QgsField('ycoord', QVariant.Double))
|
||||
if QgsWkbTypes.hasZ(source.wkbType()):
|
||||
self.export_z = True
|
||||
zName = vector.createUniqueFieldName('zcoord', fields)
|
||||
fields.append(QgsField(zName, QVariant.Double))
|
||||
new_fields.append(QgsField('zcoord', QVariant.Double))
|
||||
if QgsWkbTypes.hasM(source.wkbType()):
|
||||
self.export_m = True
|
||||
zName = vector.createUniqueFieldName('mvalue', fields)
|
||||
fields.append(QgsField(zName, QVariant.Double))
|
||||
new_fields.append(QgsField('mvalue', QVariant.Double))
|
||||
|
||||
fields = QgsProcessingUtils.combineFields(fields, new_fields)
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, wkb_type, source.sourceCrs())
|
||||
|
||||
|
@ -39,7 +39,8 @@ from qgis.core import (QgsFeatureRequest,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsSpatialIndex,
|
||||
QgsProcessingParameterField)
|
||||
QgsProcessingParameterField,
|
||||
QgsProcessingUtils)
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.tools import vector
|
||||
@ -122,12 +123,10 @@ class Intersection(QgisAlgorithm):
|
||||
fieldListB = sourceB.fields()
|
||||
field_indices_b = [i for i in range(0, fieldListB.count())]
|
||||
|
||||
fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
|
||||
for b in fieldListB:
|
||||
fieldListA.append(b)
|
||||
output_fields = QgsProcessingUtils.combineFields(fieldListA, fieldListB)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fieldListA, geomType, sourceA.sourceCrs())
|
||||
output_fields, geomType, sourceA.sourceCrs())
|
||||
|
||||
outFeat = QgsFeature()
|
||||
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
|
||||
|
@ -1,177 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
***************************************************************************
|
||||
MeanCoords.py
|
||||
---------------------
|
||||
Date : August 2012
|
||||
Copyright : (C) 2012 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. *
|
||||
* *
|
||||
***************************************************************************
|
||||
"""
|
||||
from builtins import str
|
||||
|
||||
__author__ = 'Victor Olaya'
|
||||
__date__ = 'August 2012'
|
||||
__copyright__ = '(C) 2012, Victor Olaya'
|
||||
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import os
|
||||
|
||||
from qgis.PyQt.QtGui import QIcon
|
||||
from qgis.PyQt.QtCore import QVariant
|
||||
|
||||
from qgis.core import (QgsField,
|
||||
QgsFeature,
|
||||
QgsGeometry,
|
||||
QgsPointXY,
|
||||
QgsWkbTypes,
|
||||
QgsFeatureRequest,
|
||||
QgsFeatureSink,
|
||||
QgsFields,
|
||||
QgsProcessing,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingParameterField,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingException)
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.tools import vector
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
|
||||
class MeanCoords(QgisAlgorithm):
|
||||
INPUT = 'INPUT'
|
||||
WEIGHT = 'WEIGHT'
|
||||
OUTPUT = 'OUTPUT'
|
||||
UID = 'UID'
|
||||
WEIGHT = 'WEIGHT'
|
||||
|
||||
def icon(self):
|
||||
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'mean.png'))
|
||||
|
||||
def group(self):
|
||||
return self.tr('Vector analysis')
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def initAlgorithm(self, config=None):
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
|
||||
self.tr('Input layer')))
|
||||
self.addParameter(QgsProcessingParameterField(self.WEIGHT, self.tr('Weight field'),
|
||||
parentLayerParameterName=MeanCoords.INPUT,
|
||||
type=QgsProcessingParameterField.Numeric,
|
||||
optional=True))
|
||||
self.addParameter(QgsProcessingParameterField(self.UID,
|
||||
self.tr('Unique ID field'),
|
||||
parentLayerParameterName=MeanCoords.INPUT,
|
||||
optional=True))
|
||||
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(MeanCoords.OUTPUT, self.tr('Mean coordinates'),
|
||||
QgsProcessing.TypeVectorPoint))
|
||||
|
||||
def name(self):
|
||||
return 'meancoordinates'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Mean coordinate(s)')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
|
||||
weight_field = self.parameterAsString(parameters, self.WEIGHT, context)
|
||||
unique_field = self.parameterAsString(parameters, self.UID, context)
|
||||
|
||||
attributes = []
|
||||
if not weight_field:
|
||||
weight_index = -1
|
||||
else:
|
||||
weight_index = source.fields().lookupField(weight_field)
|
||||
if weight_index >= 0:
|
||||
attributes.append(weight_index)
|
||||
|
||||
if not unique_field:
|
||||
unique_index = -1
|
||||
else:
|
||||
unique_index = source.fields().lookupField(unique_field)
|
||||
if unique_index >= 0:
|
||||
attributes.append(unique_index)
|
||||
|
||||
field_list = QgsFields()
|
||||
field_list.append(QgsField('MEAN_X', QVariant.Double, '', 24, 15))
|
||||
field_list.append(QgsField('MEAN_Y', QVariant.Double, '', 24, 15))
|
||||
if unique_index >= 0:
|
||||
field_list.append(QgsField('UID', QVariant.String, '', 255))
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
field_list, QgsWkbTypes.Point, source.sourceCrs())
|
||||
|
||||
features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(attributes))
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
means = {}
|
||||
for current, feat in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
if unique_index == -1:
|
||||
clazz = "Single class"
|
||||
else:
|
||||
clazz = str(feat.attributes()[unique_index]).strip()
|
||||
if weight_index == -1:
|
||||
weight = 1.00
|
||||
else:
|
||||
try:
|
||||
weight = float(feat.attributes()[weight_index])
|
||||
except:
|
||||
weight = 1.00
|
||||
|
||||
if weight < 0:
|
||||
raise QgsProcessingException(
|
||||
self.tr('Negative weight value found. Please fix your data and try again.'))
|
||||
|
||||
if clazz not in means:
|
||||
means[clazz] = (0, 0, 0)
|
||||
|
||||
(cx, cy, totalweight) = means[clazz]
|
||||
geom = QgsGeometry(feat.geometry())
|
||||
geom = vector.extractPoints(geom)
|
||||
for i in geom:
|
||||
cx += i.x() * weight
|
||||
cy += i.y() * weight
|
||||
totalweight += weight
|
||||
means[clazz] = (cx, cy, totalweight)
|
||||
|
||||
current = 0
|
||||
total = 100.0 / len(means) if means else 1
|
||||
for (clazz, values) in list(means.items()):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
outFeat = QgsFeature()
|
||||
cx = values[0] / values[2]
|
||||
cy = values[1] / values[2]
|
||||
meanPoint = QgsPointXY(cx, cy)
|
||||
|
||||
outFeat.setGeometry(QgsGeometry.fromPoint(meanPoint))
|
||||
attributes = [cx, cy]
|
||||
if unique_index >= 0:
|
||||
attributes.append(clazz)
|
||||
outFeat.setAttributes(attributes)
|
||||
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
current += 1
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
@ -92,7 +92,6 @@ from .ImportIntoSpatialite import ImportIntoSpatialite
|
||||
from .Intersection import Intersection
|
||||
from .JoinAttributes import JoinAttributes
|
||||
from .LinesToPolygons import LinesToPolygons
|
||||
from .MeanCoords import MeanCoords
|
||||
from .Merge import Merge
|
||||
from .MinimumBoundingGeometry import MinimumBoundingGeometry
|
||||
from .NearestNeighbourAnalysis import NearestNeighbourAnalysis
|
||||
@ -226,7 +225,6 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
Intersection(),
|
||||
JoinAttributes(),
|
||||
LinesToPolygons(),
|
||||
MeanCoords(),
|
||||
Merge(),
|
||||
MinimumBoundingGeometry(),
|
||||
NearestNeighbourAnalysis(),
|
||||
|
Binary file not shown.
38
python/plugins/processing/tests/testdata/expected/mean_coordinates_unique_grouped.gml
vendored
Normal file
38
python/plugins/processing/tests/testdata/expected/mean_coordinates_unique_grouped.gml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ mean_coordinates_unique_grouped.xsd"
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>3</gml:X><gml:Y>-1.2</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>3.5</gml:X><gml:Y>2</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:mean_coordinates_unique_grouped fid="mean_coordinates_unique_grouped.0">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3.0,1.5</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>3.000000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>1.500000000000000</ogr:MEAN_Y>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
</ogr:mean_coordinates_unique_grouped>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:mean_coordinates_unique_grouped fid="mean_coordinates_unique_grouped.1">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3.4,-1.2</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>3.400000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>-1.200000000000000</ogr:MEAN_Y>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
</ogr:mean_coordinates_unique_grouped>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:mean_coordinates_unique_grouped fid="mean_coordinates_unique_grouped.2">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3.5,2.0</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>3.500000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>2.000000000000000</ogr:MEAN_Y>
|
||||
<ogr:id2>1</ogr:id2>
|
||||
</ogr:mean_coordinates_unique_grouped>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
46
python/plugins/processing/tests/testdata/expected/mean_coordinates_unique_grouped.xsd
vendored
Normal file
46
python/plugins/processing/tests/testdata/expected/mean_coordinates_unique_grouped.xsd
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?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="mean_coordinates_unique_grouped" type="ogr:mean_coordinates_unique_grouped_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="mean_coordinates_unique_grouped_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MEAN_X" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:decimal">
|
||||
<xs:totalDigits value="25"/>
|
||||
<xs:fractionDigits value="15"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="MEAN_Y" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:decimal">
|
||||
<xs:totalDigits value="25"/>
|
||||
<xs:fractionDigits value="15"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="id2" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:integer">
|
||||
<xs:totalDigits value="10"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
86
python/plugins/processing/tests/testdata/expected/mean_coordinates_unique_grouped_2.gml
vendored
Normal file
86
python/plugins/processing/tests/testdata/expected/mean_coordinates_unique_grouped_2.gml
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ mean_coordinates_unique_grouped_2.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>-5</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:mean_coordinates_unique_grouped_2 fid="mean_coordinates_unique_grouped_2.0">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>3.000000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>3.000000000000000</ogr:MEAN_Y>
|
||||
<ogr:id>2</ogr:id>
|
||||
</ogr:mean_coordinates_unique_grouped_2>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:mean_coordinates_unique_grouped_2 fid="mean_coordinates_unique_grouped_2.1">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>2.000000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>2.000000000000000</ogr:MEAN_Y>
|
||||
<ogr:id>3</ogr:id>
|
||||
</ogr:mean_coordinates_unique_grouped_2>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:mean_coordinates_unique_grouped_2 fid="mean_coordinates_unique_grouped_2.2">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>5,2</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>5.000000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>2.000000000000000</ogr:MEAN_Y>
|
||||
<ogr:id>4</ogr:id>
|
||||
</ogr:mean_coordinates_unique_grouped_2>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:mean_coordinates_unique_grouped_2 fid="mean_coordinates_unique_grouped_2.3">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>4,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>4.000000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>1.000000000000000</ogr:MEAN_Y>
|
||||
<ogr:id>5</ogr:id>
|
||||
</ogr:mean_coordinates_unique_grouped_2>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:mean_coordinates_unique_grouped_2 fid="mean_coordinates_unique_grouped_2.4">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-5</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>0.000000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>-5.000000000000000</ogr:MEAN_Y>
|
||||
<ogr:id>6</ogr:id>
|
||||
</ogr:mean_coordinates_unique_grouped_2>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:mean_coordinates_unique_grouped_2 fid="mean_coordinates_unique_grouped_2.5">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>8.000000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>-1.000000000000000</ogr:MEAN_Y>
|
||||
<ogr:id>7</ogr:id>
|
||||
</ogr:mean_coordinates_unique_grouped_2>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:mean_coordinates_unique_grouped_2 fid="mean_coordinates_unique_grouped_2.6">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>7.000000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>-1.000000000000000</ogr:MEAN_Y>
|
||||
<ogr:id>8</ogr:id>
|
||||
</ogr:mean_coordinates_unique_grouped_2>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:mean_coordinates_unique_grouped_2 fid="mean_coordinates_unique_grouped_2.7">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>0.000000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>-1.000000000000000</ogr:MEAN_Y>
|
||||
<ogr:id>9</ogr:id>
|
||||
</ogr:mean_coordinates_unique_grouped_2>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:mean_coordinates_unique_grouped_2 fid="mean_coordinates_unique_grouped_2.8">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>1.000000000000000</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>1.000000000000000</ogr:MEAN_Y>
|
||||
<ogr:id>1</ogr:id>
|
||||
</ogr:mean_coordinates_unique_grouped_2>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
46
python/plugins/processing/tests/testdata/expected/mean_coordinates_unique_grouped_2.xsd
vendored
Normal file
46
python/plugins/processing/tests/testdata/expected/mean_coordinates_unique_grouped_2.xsd
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?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="mean_coordinates_unique_grouped_2" type="ogr:mean_coordinates_unique_grouped_2_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="mean_coordinates_unique_grouped_2_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MEAN_X" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:decimal">
|
||||
<xs:totalDigits value="25"/>
|
||||
<xs:fractionDigits value="15"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="MEAN_Y" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:decimal">
|
||||
<xs:totalDigits value="25"/>
|
||||
<xs:fractionDigits value="15"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="id" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:integer">
|
||||
<xs:totalDigits value="10"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
21
python/plugins/processing/tests/testdata/expected/unique_coordinates_weight.gml
vendored
Normal file
21
python/plugins/processing/tests/testdata/expected/unique_coordinates_weight.gml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ unique_coordinates_weight.xsd"
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>3.666666666666667</gml:X><gml:Y>-0.6222222222222222</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>3.666666666666667</gml:X><gml:Y>-0.6222222222222222</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:unique_coordinates_weight fid="unique_coordinates_weight.0">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3.66666666666667,-0.622222222222222</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:MEAN_X>3.666666666666667</ogr:MEAN_X>
|
||||
<ogr:MEAN_Y>-0.622222222222222</ogr:MEAN_Y>
|
||||
</ogr:unique_coordinates_weight>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
39
python/plugins/processing/tests/testdata/expected/unique_coordinates_weight.xsd
vendored
Normal file
39
python/plugins/processing/tests/testdata/expected/unique_coordinates_weight.xsd
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?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="unique_coordinates_weight" type="ogr:unique_coordinates_weight_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="unique_coordinates_weight_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MEAN_X" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:decimal">
|
||||
<xs:totalDigits value="25"/>
|
||||
<xs:fractionDigits value="15"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="MEAN_Y" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:decimal">
|
||||
<xs:totalDigits value="25"/>
|
||||
<xs:fractionDigits value="15"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
@ -2665,7 +2665,7 @@ tests:
|
||||
name: expected/points_along_lines.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:meancoordinates
|
||||
- algorithm: native:meancoordinates
|
||||
name: standard mean coordinates
|
||||
params:
|
||||
INPUT:
|
||||
@ -2676,6 +2676,53 @@ tests:
|
||||
name: expected/mean_coordinates.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:meancoordinates
|
||||
name: Mean coordinates, multiple grouped
|
||||
params:
|
||||
INPUT:
|
||||
name: points.gml
|
||||
type: vector
|
||||
UID: id2
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/mean_coordinates_unique_grouped.gml
|
||||
type: vector
|
||||
pk: id2
|
||||
compare:
|
||||
fields:
|
||||
fid: skip
|
||||
|
||||
- algorithm: native:meancoordinates
|
||||
name: Mean coordinates, unique field
|
||||
params:
|
||||
INPUT:
|
||||
name: points.gml
|
||||
type: vector
|
||||
UID: id
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/mean_coordinates_unique_grouped_2.gml
|
||||
type: vector
|
||||
pk: id
|
||||
compare:
|
||||
fields:
|
||||
fid: skip
|
||||
|
||||
- algorithm: native:meancoordinates
|
||||
name: Mean coordinates, weighted
|
||||
params:
|
||||
INPUT:
|
||||
name: points.gml
|
||||
type: vector
|
||||
WEIGHT: id
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/unique_coordinates_weight.gml
|
||||
type: vector
|
||||
compare:
|
||||
fields:
|
||||
fid: skip
|
||||
|
||||
- algorithm: native:collect
|
||||
name: single part to multipart
|
||||
params:
|
||||
|
@ -27,13 +27,8 @@ __revision__ = '$Format:%H$'
|
||||
|
||||
import csv
|
||||
|
||||
from qgis.PyQt.QtCore import QVariant
|
||||
from qgis.core import (QgsFields,
|
||||
QgsField,
|
||||
QgsGeometry,
|
||||
QgsWkbTypes,
|
||||
QgsFeatureRequest,
|
||||
QgsPointXY)
|
||||
from qgis.core import (QgsWkbTypes,
|
||||
QgsFeatureRequest)
|
||||
|
||||
|
||||
def resolveFieldIndex(source, attr):
|
||||
@ -95,85 +90,6 @@ def values(source, *attributes):
|
||||
return ret
|
||||
|
||||
|
||||
def testForUniqueness(fieldList1, fieldList2):
|
||||
'''Returns a modified version of fieldList2, removing naming
|
||||
collisions with fieldList1.'''
|
||||
changed = True
|
||||
while changed:
|
||||
changed = False
|
||||
for i in range(0, len(fieldList1)):
|
||||
for j in range(0, len(fieldList2)):
|
||||
if fieldList1[i].name() == fieldList2[j].name():
|
||||
field = fieldList2[j]
|
||||
name = createUniqueFieldName(field.name(), fieldList1)
|
||||
fieldList2[j] = QgsField(name, field.type(), len=field.length(), prec=field.precision(), comment=field.comment())
|
||||
changed = True
|
||||
return fieldList2
|
||||
|
||||
|
||||
def createUniqueFieldName(fieldName, fieldList):
|
||||
def nextname(name):
|
||||
num = 1
|
||||
while True:
|
||||
returnname = '{name}_{num}'.format(name=name[:8], num=num)
|
||||
yield returnname
|
||||
num += 1
|
||||
|
||||
def found(name):
|
||||
return any(f.name() == name for f in fieldList)
|
||||
|
||||
shortName = fieldName[:10]
|
||||
|
||||
if not fieldList:
|
||||
return shortName
|
||||
|
||||
if not found(shortName):
|
||||
return shortName
|
||||
|
||||
for newname in nextname(shortName):
|
||||
if not found(newname):
|
||||
return newname
|
||||
|
||||
|
||||
def findOrCreateField(layer, fieldList, fieldName, fieldLen=24, fieldPrec=15):
|
||||
idx = layer.fields().lookupField(fieldName)
|
||||
if idx == -1:
|
||||
fn = createUniqueFieldName(fieldName, fieldList)
|
||||
field = QgsField(fn, QVariant.Double, '', fieldLen, fieldPrec)
|
||||
idx = len(fieldList)
|
||||
fieldList.append(field)
|
||||
|
||||
return (idx, fieldList)
|
||||
|
||||
|
||||
def extractPoints(geom):
|
||||
points = []
|
||||
if geom.type() == QgsWkbTypes.PointGeometry:
|
||||
if geom.isMultipart():
|
||||
points = geom.asMultiPoint()
|
||||
else:
|
||||
points.append(geom.asPoint())
|
||||
elif geom.type() == QgsWkbTypes.LineGeometry:
|
||||
if geom.isMultipart():
|
||||
lines = geom.asMultiPolyline()
|
||||
for line in lines:
|
||||
points.extend(line)
|
||||
else:
|
||||
points = geom.asPolyline()
|
||||
elif geom.type() == QgsWkbTypes.PolygonGeometry:
|
||||
if geom.isMultipart():
|
||||
polygons = geom.asMultiPolygon()
|
||||
for poly in polygons:
|
||||
for line in poly:
|
||||
points.extend(line)
|
||||
else:
|
||||
polygon = geom.asPolygon()
|
||||
for line in polygon:
|
||||
points.extend(line)
|
||||
|
||||
return points
|
||||
|
||||
|
||||
def checkMinDistance(point, index, distance, points):
|
||||
"""Check if distance from given point to all other points is greater
|
||||
than given value.
|
||||
|
@ -87,6 +87,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
|
||||
addAlgorithm( new QgsExtentToLayerAlgorithm() );
|
||||
addAlgorithm( new QgsLineIntersectionAlgorithm() );
|
||||
addAlgorithm( new QgsSplitWithLinesAlgorithm() );
|
||||
addAlgorithm( new QgsMeanCoordinatesAlgorithm() );
|
||||
}
|
||||
|
||||
void QgsSaveSelectedFeatures::initAlgorithm( const QVariantMap & )
|
||||
@ -2412,6 +2413,179 @@ QVariantMap QgsSplitWithLinesAlgorithm::processAlgorithm( const QVariantMap &par
|
||||
}
|
||||
|
||||
|
||||
void QgsMeanCoordinatesAlgorithm::initAlgorithm( const QVariantMap & )
|
||||
{
|
||||
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ),
|
||||
QObject::tr( "Input layer" ), QList< int >() << QgsProcessing::TypeVectorAnyGeometry ) );
|
||||
addParameter( new QgsProcessingParameterField( QStringLiteral( "WEIGHT" ), QObject::tr( "Weight field" ),
|
||||
QVariant(), QStringLiteral( "INPUT" ),
|
||||
QgsProcessingParameterField::Numeric, false, true ) );
|
||||
addParameter( new QgsProcessingParameterField( QStringLiteral( "UID" ),
|
||||
QObject::tr( "Unique ID field" ), QVariant(),
|
||||
QStringLiteral( "INPUT" ), QgsProcessingParameterField::Any, false, true ) );
|
||||
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Mean coordinates" ), QgsProcessing::TypeVectorPoint ) );
|
||||
}
|
||||
|
||||
QString QgsMeanCoordinatesAlgorithm::shortHelpString() const
|
||||
{
|
||||
return QObject::tr( "This algorithm computes a point layer with the center of mass of geometries in an input layer.\n\n"
|
||||
"An attribute can be specified as containing weights to be applied to each feature when computing the center of mass.\n\n"
|
||||
"If an attribute is selected in the <Unique ID field> parameter, features will be grouped according "
|
||||
"to values in this field. Instead of a single point with the center of mass of the whole layer, "
|
||||
"the output layer will contain a center of mass for the features in each category." );
|
||||
}
|
||||
|
||||
QgsMeanCoordinatesAlgorithm *QgsMeanCoordinatesAlgorithm::createInstance() const
|
||||
{
|
||||
return new QgsMeanCoordinatesAlgorithm();
|
||||
}
|
||||
|
||||
QVariantMap QgsMeanCoordinatesAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !source )
|
||||
return QVariantMap();
|
||||
|
||||
QString weightFieldName = parameterAsString( parameters, QStringLiteral( "WEIGHT" ), context );
|
||||
QString uniqueFieldName = parameterAsString( parameters, QStringLiteral( "UID" ), context );
|
||||
|
||||
QgsAttributeList attributes;
|
||||
int weightIndex = -1;
|
||||
if ( !weightFieldName.isEmpty() )
|
||||
{
|
||||
weightIndex = source->fields().lookupField( weightFieldName );
|
||||
if ( weightIndex >= 0 )
|
||||
attributes.append( weightIndex );
|
||||
}
|
||||
|
||||
int uniqueFieldIndex = -1;
|
||||
if ( !uniqueFieldName.isEmpty() )
|
||||
{
|
||||
uniqueFieldIndex = source->fields().lookupField( uniqueFieldName );
|
||||
if ( uniqueFieldIndex >= 0 )
|
||||
attributes.append( uniqueFieldIndex );
|
||||
}
|
||||
|
||||
QgsFields fields;
|
||||
fields.append( QgsField( QStringLiteral( "MEAN_X" ), QVariant::Double, QString(), 24, 15 ) );
|
||||
fields.append( QgsField( QStringLiteral( "MEAN_Y" ), QVariant::Double, QString(), 24, 15 ) );
|
||||
if ( uniqueFieldIndex >= 0 )
|
||||
{
|
||||
QgsField uniqueField = source->fields().at( uniqueFieldIndex );
|
||||
fields.append( uniqueField );
|
||||
}
|
||||
|
||||
QString dest;
|
||||
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields,
|
||||
QgsWkbTypes::Point, source->sourceCrs() ) );
|
||||
if ( !sink )
|
||||
return QVariantMap();
|
||||
|
||||
QgsFeatureIterator features = source->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attributes ) );
|
||||
|
||||
double step = source->featureCount() > 0 ? 50.0 / source->featureCount() : 1;
|
||||
int i = 0;
|
||||
QgsFeature feat;
|
||||
|
||||
QHash< QVariant, QList< double > > means;
|
||||
while ( features.nextFeature( feat ) )
|
||||
{
|
||||
i++;
|
||||
if ( feedback->isCanceled() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
feedback->setProgress( i * step );
|
||||
if ( !feat.hasGeometry() )
|
||||
continue;
|
||||
|
||||
|
||||
QVariant featureClass;
|
||||
if ( uniqueFieldIndex >= 0 )
|
||||
{
|
||||
featureClass = feat.attribute( uniqueFieldIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
featureClass = QStringLiteral( "#####singleclass#####" );
|
||||
}
|
||||
|
||||
double weight = 1;
|
||||
if ( weightIndex >= 0 )
|
||||
{
|
||||
bool ok = false;
|
||||
weight = feat.attribute( weightIndex ).toDouble( &ok );
|
||||
if ( !ok )
|
||||
weight = 1.0;
|
||||
}
|
||||
|
||||
if ( weight < 0 )
|
||||
{
|
||||
throw QgsProcessingException( QObject::tr( "Negative weight value found. Please fix your data and try again." ) );
|
||||
}
|
||||
|
||||
QList< double > values = means.value( featureClass );
|
||||
double cx = 0;
|
||||
double cy = 0;
|
||||
double totalWeight = 0;
|
||||
if ( !values.empty() )
|
||||
{
|
||||
cx = values.at( 0 );
|
||||
cy = values.at( 1 );
|
||||
totalWeight = values.at( 2 );
|
||||
}
|
||||
|
||||
QgsVertexId vid;
|
||||
QgsPoint pt;
|
||||
const QgsAbstractGeometry *g = feat.geometry().geometry();
|
||||
// NOTE - should this be including the duplicate nodes for closed rings? currently it is,
|
||||
// but I suspect that the expected behavior would be to NOT include these
|
||||
while ( g->nextVertex( vid, pt ) )
|
||||
{
|
||||
cx += pt.x() * weight;
|
||||
cy += pt.y() * weight;
|
||||
totalWeight += weight;
|
||||
}
|
||||
|
||||
means[featureClass] = QList< double >() << cx << cy << totalWeight;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
step = !means.empty() ? 50.0 / means.count() : 1;
|
||||
for ( auto it = means.constBegin(); it != means.constEnd(); ++it )
|
||||
{
|
||||
i++;
|
||||
if ( feedback->isCanceled() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
feedback->setProgress( 50 + i * step );
|
||||
if ( qgsDoubleNear( it.value().at( 2 ), 0 ) )
|
||||
continue;
|
||||
|
||||
QgsFeature outFeat;
|
||||
double cx = it.value().at( 0 ) / it.value().at( 2 );
|
||||
double cy = it.value().at( 1 ) / it.value().at( 2 );
|
||||
|
||||
QgsPointXY meanPoint( cx, cy );
|
||||
outFeat.setGeometry( QgsGeometry::fromPoint( meanPoint ) );
|
||||
|
||||
QgsAttributes attributes;
|
||||
attributes << cx << cy;
|
||||
if ( uniqueFieldIndex >= 0 )
|
||||
attributes.append( it.key() );
|
||||
|
||||
outFeat.setAttributes( attributes );
|
||||
sink->addFeature( outFeat, QgsFeatureSink::FastInsert );
|
||||
}
|
||||
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
///@endcond
|
||||
|
||||
|
||||
|
@ -786,6 +786,30 @@ class QgsSplitWithLinesAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Native mean coordinates algorithm.
|
||||
*/
|
||||
class QgsMeanCoordinatesAlgorithm : public QgsProcessingAlgorithm
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
QgsMeanCoordinatesAlgorithm() = default;
|
||||
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
|
||||
QString name() const override { return QStringLiteral( "meancoordinates" ); }
|
||||
QString displayName() const override { return QObject::tr( "Mean coordinate(s)" ); }
|
||||
virtual QStringList tags() const override { return QObject::tr( "mean,average,coordinate" ).split( ',' ); }
|
||||
QString group() const override { return QObject::tr( "Vector analysis" ); }
|
||||
QString shortHelpString() const override;
|
||||
QgsMeanCoordinatesAlgorithm *createInstance() const override SIP_FACTORY;
|
||||
|
||||
protected:
|
||||
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
};
|
||||
|
||||
///@endcond PRIVATE
|
||||
|
||||
#endif // QGSNATIVEALGORITHMS_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user