Skip to content

Commit 0630b1c

Browse files
committed
[FEATURE][processing] allow to create points on all parts in point on surface alg
1 parent a30403d commit 0630b1c

File tree

5 files changed

+172
-6
lines changed

5 files changed

+172
-6
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/ point_on_multipoly.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>8</gml:X><gml:Y>5.5</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:point_on_multipoly fid="multipolys.0">
16+
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3.5,2.5</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:point_on_multipoly>
21+
</gml:featureMember>
22+
<gml:featureMember>
23+
<ogr:point_on_multipoly 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:point_on_multipoly>
29+
</gml:featureMember>
30+
<gml:featureMember>
31+
<ogr:point_on_multipoly fid="multipolys.1">
32+
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8.0,5.5</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:point_on_multipoly>
37+
</gml:featureMember>
38+
<gml:featureMember>
39+
<ogr:point_on_multipoly 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:point_on_multipoly>
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="point_on_multipoly" type="ogr:point_on_multipoly_Type" substitutionGroup="gml:_Feature"/>
14+
<xs:complexType name="point_on_multipoly_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
@@ -881,6 +881,18 @@ tests:
881881
name: expected/point_on_poly.gml
882882
type: vector
883883

884+
- algorithm: native:pointonsurface
885+
name: Point on all parts of multi polygon surface
886+
params:
887+
INPUT:
888+
name: multipolys.gml
889+
type: vector
890+
ALL_PARTS: true
891+
results:
892+
OUTPUT:
893+
name: expected/point_on_multipoly.gml
894+
type: vector
895+
884896
- algorithm: qgis:pointonsurface
885897
name: Point on multipoint surface
886898
params:

src/analysis/processing/qgsalgorithmpointonsurface.cpp

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

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

2021
///@cond PRIVATE
2122

@@ -59,19 +60,72 @@ QgsPointOnSurfaceAlgorithm *QgsPointOnSurfaceAlgorithm::createInstance() const
5960
return new QgsPointOnSurfaceAlgorithm();
6061
}
6162

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

77131
///@endcond

src/analysis/processing/qgsalgorithmpointonsurface.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,23 @@ class QgsPointOnSurfaceAlgorithm : public QgsProcessingFeatureBasedAlgorithm
4141
QString groupId() const override;
4242
QString shortHelpString() const override;
4343
QgsPointOnSurfaceAlgorithm *createInstance() const override SIP_FACTORY;
44+
void initParameters( const QVariantMap &configuration = QVariantMap() ) override;
4445

4546
protected:
4647

4748
QString outputName() const override;
4849
QgsProcessing::SourceType outputLayerType() const override { return QgsProcessing::TypeVectorPoint; }
4950
QgsWkbTypes::Type outputWkbType( QgsWkbTypes::Type inputWkbType ) const override { Q_UNUSED( inputWkbType ); return QgsWkbTypes::Point; }
5051

52+
bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
5153
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;
60+
5261
};
5362

5463
///@endcond PRIVATE

0 commit comments

Comments
 (0)