Skip to content

Commit 0d92f96

Browse files
committedMar 6, 2018
[FEATURE][processing] allow to create points on all parts in centroids alg
1 parent 0630b1c commit 0d92f96

File tree

5 files changed

+171
-12
lines changed

5 files changed

+171
-12
lines changed
 
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://ogr.maptools.org/ centroid_multipoly_all_parts.xsd"
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>0.5</gml:X><gml:Y>0.5</gml:Y></gml:coord>
10+
<gml:coord><gml:X>7.904761904761905</gml:X><gml:Y>5.095238095238095</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:centroid_multipoly_all_parts fid="multipolys.0">
16+
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3.16666666666667,1.83333333333333</gml:coordinates></gml:Point></ogr:geometryProperty>
17+
<ogr:Bname>Test</ogr:Bname>
18+
<ogr:Bintval>1</ogr:Bintval>
19+
<ogr:Bfloatval>0.12300</ogr:Bfloatval>
20+
</ogr:centroid_multipoly_all_parts>
21+
</gml:featureMember>
22+
<gml:featureMember>
23+
<ogr:centroid_multipoly_all_parts fid="multipolys.1">
24+
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7.5,1.0</gml:coordinates></gml:Point></ogr:geometryProperty>
25+
<ogr:Bname xsi:nil="true"/>
26+
<ogr:Bintval xsi:nil="true"/>
27+
<ogr:Bfloatval xsi:nil="true"/>
28+
</ogr:centroid_multipoly_all_parts>
29+
</gml:featureMember>
30+
<gml:featureMember>
31+
<ogr:centroid_multipoly_all_parts fid="multipolys.1">
32+
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7.90476190476191,5.09523809523809</gml:coordinates></gml:Point></ogr:geometryProperty>
33+
<ogr:Bname xsi:nil="true"/>
34+
<ogr:Bintval xsi:nil="true"/>
35+
<ogr:Bfloatval xsi:nil="true"/>
36+
</ogr:centroid_multipoly_all_parts>
37+
</gml:featureMember>
38+
<gml:featureMember>
39+
<ogr:centroid_multipoly_all_parts fid="multipolys.2">
40+
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0.5,0.5</gml:coordinates></gml:Point></ogr:geometryProperty>
41+
<ogr:Bname>Test</ogr:Bname>
42+
<ogr:Bintval>2</ogr:Bintval>
43+
<ogr:Bfloatval>-0.12300</ogr:Bfloatval>
44+
</ogr:centroid_multipoly_all_parts>
45+
</gml:featureMember>
46+
</ogr:FeatureCollection>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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">
3+
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
4+
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
5+
<xs:complexType name="FeatureCollectionType">
6+
<xs:complexContent>
7+
<xs:extension base="gml:AbstractFeatureCollectionType">
8+
<xs:attribute name="lockId" type="xs:string" use="optional"/>
9+
<xs:attribute name="scope" type="xs:string" use="optional"/>
10+
</xs:extension>
11+
</xs:complexContent>
12+
</xs:complexType>
13+
<xs:element name="centroid_multipoly_all_parts" type="ogr:centroid_multipoly_all_parts_Type" substitutionGroup="gml:_Feature"/>
14+
<xs:complexType name="centroid_multipoly_all_parts_Type">
15+
<xs:complexContent>
16+
<xs:extension base="gml:AbstractFeatureType">
17+
<xs:sequence>
18+
<xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
19+
<xs:element name="Bname" nillable="true" minOccurs="0" maxOccurs="1">
20+
<xs:simpleType>
21+
<xs:restriction base="xs:string">
22+
<xs:maxLength value="4"/>
23+
</xs:restriction>
24+
</xs:simpleType>
25+
</xs:element>
26+
<xs:element name="Bintval" nillable="true" minOccurs="0" maxOccurs="1">
27+
<xs:simpleType>
28+
<xs:restriction base="xs:integer">
29+
<xs:totalDigits value="10"/>
30+
</xs:restriction>
31+
</xs:simpleType>
32+
</xs:element>
33+
<xs:element name="Bfloatval" nillable="true" minOccurs="0" maxOccurs="1">
34+
<xs:simpleType>
35+
<xs:restriction base="xs:decimal">
36+
<xs:totalDigits value="21"/>
37+
<xs:fractionDigits value="5"/>
38+
</xs:restriction>
39+
</xs:simpleType>
40+
</xs:element>
41+
</xs:sequence>
42+
</xs:extension>
43+
</xs:complexContent>
44+
</xs:complexType>
45+
</xs:schema>

‎python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,18 @@ tests:
11691169
geometry:
11701170
precision: 7
11711171

1172+
- algorithm: native:centroids
1173+
name: Centroid (multipolygons)
1174+
params:
1175+
INPUT:
1176+
name: multipolys.gml
1177+
type: vector
1178+
ALL_PARTS: true
1179+
results:
1180+
OUTPUT:
1181+
name: expected/centroid_multipoly_all_parts.gml
1182+
type: vector
1183+
11721184
- algorithm: native:centroids
11731185
name: Centroid (points)
11741186
params:

‎src/analysis/processing/qgsalgorithmcentroid.cpp

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
***************************************************************************/
1717

1818
#include "qgsalgorithmcentroid.h"
19+
#include "qgsgeometrycollection.h"
1920

2021
///@cond PRIVATE
2122

@@ -49,12 +50,6 @@ QString QgsCentroidAlgorithm::outputName() const
4950
return QObject::tr( "Centroids" );
5051
}
5152

52-
void QgsCentroidAlgorithm::initAlgorithm( const QVariantMap & )
53-
{
54-
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
55-
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Centroids" ), QgsProcessing::TypeVectorPoint ) );
56-
}
57-
5853
QString QgsCentroidAlgorithm::shortHelpString() const
5954
{
6055
return QObject::tr( "This algorithm creates a new point layer, with points representing the centroid of the geometries in an input layer.\n\n"
@@ -66,18 +61,72 @@ QgsCentroidAlgorithm *QgsCentroidAlgorithm::createInstance() const
6661
return new QgsCentroidAlgorithm();
6762
}
6863

69-
QgsFeatureList QgsCentroidAlgorithm::processFeature( const QgsFeature &f, QgsProcessingContext &, QgsProcessingFeedback *feedback )
64+
void QgsCentroidAlgorithm::initParameters( const QVariantMap & )
7065
{
66+
std::unique_ptr< QgsProcessingParameterBoolean> allParts = qgis::make_unique< QgsProcessingParameterBoolean >(
67+
QStringLiteral( "ALL_PARTS" ),
68+
QObject::tr( "Create point on surface for each part" ),
69+
false );
70+
allParts->setIsDynamic( true );
71+
allParts->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "All parts" ), QObject::tr( "Create point on surface for each part" ), QgsPropertyDefinition::Boolean ) );
72+
allParts->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
73+
addParameter( allParts.release() );
74+
}
75+
76+
bool QgsCentroidAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
77+
{
78+
mAllParts = parameterAsBool( parameters, QStringLiteral( "ALL_PARTS" ), context );
79+
mDynamicAllParts = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "ALL_PARTS" ) );
80+
if ( mDynamicAllParts )
81+
mAllPartsProperty = parameters.value( QStringLiteral( "ALL_PARTS" ) ).value< QgsProperty >();
82+
83+
return true;
84+
}
85+
86+
QgsFeatureList QgsCentroidAlgorithm::processFeature( const QgsFeature &f, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
87+
{
88+
QgsFeatureList list;
7189
QgsFeature feature = f;
7290
if ( feature.hasGeometry() )
7391
{
74-
feature.setGeometry( feature.geometry().centroid() );
75-
if ( !feature.geometry() )
92+
QgsGeometry geom = feature.geometry();
93+
94+
bool allParts = mAllParts;
95+
if ( mDynamicAllParts )
96+
allParts = mAllPartsProperty.valueAsBool( context.expressionContext(), allParts );
97+
98+
if ( allParts && geom.isMultipart() )
99+
{
100+
const QgsGeometryCollection *geomCollection = static_cast<const QgsGeometryCollection *>( geom.constGet() );
101+
102+
for ( int i = 0; i < geomCollection->partCount(); ++i )
103+
{
104+
QgsGeometry partGeometry( geomCollection->geometryN( i )->clone() );
105+
QgsGeometry outputGeometry = partGeometry.centroid();
106+
if ( !outputGeometry )
107+
{
108+
feedback->pushInfo( QObject::tr( "Error calculating centroid for feature %1 part %2: %3" ).arg( feature.id() ).arg( i ).arg( outputGeometry.lastError() ) );
109+
}
110+
feature.setGeometry( outputGeometry );
111+
list << feature;
112+
}
113+
}
114+
else
76115
{
77-
feedback->pushInfo( QObject::tr( "Error calculating centroid for feature %1" ).arg( feature.id() ) );
116+
QgsGeometry outputGeometry = feature.geometry().centroid();
117+
if ( !outputGeometry )
118+
{
119+
feedback->pushInfo( QObject::tr( "Error calculating centroid for feature %1: %2" ).arg( feature.id() ).arg( outputGeometry.lastError() ) );
120+
}
121+
feature.setGeometry( outputGeometry );
122+
list << feature;
78123
}
79124
}
80-
return QgsFeatureList() << feature;
125+
else
126+
{
127+
list << feature;
128+
}
129+
return list;
81130
}
82131

83132
///@endcond

‎src/analysis/processing/qgsalgorithmcentroid.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,29 @@ class QgsCentroidAlgorithm : public QgsProcessingFeatureBasedAlgorithm
3434
public:
3535

3636
QgsCentroidAlgorithm() = default;
37-
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
3837
QString name() const override;
3938
QString displayName() const override;
4039
QStringList tags() const override;
4140
QString group() const override;
4241
QString groupId() const override;
4342
QString shortHelpString() const override;
4443
QgsCentroidAlgorithm *createInstance() const override SIP_FACTORY;
44+
void initParameters( const QVariantMap &configuration = QVariantMap() ) override;
4545

4646
protected:
4747

4848
QString outputName() const override;
4949
QgsProcessing::SourceType outputLayerType() const override { return QgsProcessing::TypeVectorPoint; }
5050
QgsWkbTypes::Type outputWkbType( QgsWkbTypes::Type inputWkbType ) const override { Q_UNUSED( inputWkbType ); return QgsWkbTypes::Point; }
5151

52+
bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
5253
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
54+
55+
private:
56+
57+
bool mAllParts = false;
58+
bool mDynamicAllParts = false;
59+
QgsProperty mAllPartsProperty;
5360
};
5461

5562
///@endcond PRIVATE

0 commit comments

Comments
 (0)
Please sign in to comment.