Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE][processing] allow to create points on all parts in point on…
… surface alg
  • Loading branch information
nirvn committed Mar 6, 2018
1 parent a30403d commit 0630b1c
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 6 deletions.
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ point_on_multipoly.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>0.5</gml:X><gml:Y>0.5</gml:Y></gml:coord>
<gml:coord><gml:X>8</gml:X><gml:Y>5.5</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:point_on_multipoly fid="multipolys.0">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3.5,2.5</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:Bname>Test</ogr:Bname>
<ogr:Bintval>1</ogr:Bintval>
<ogr:Bfloatval>0.12300</ogr:Bfloatval>
</ogr:point_on_multipoly>
</gml:featureMember>
<gml:featureMember>
<ogr:point_on_multipoly fid="multipolys.1">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7.5,1.0</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:Bname xsi:nil="true"/>
<ogr:Bintval xsi:nil="true"/>
<ogr:Bfloatval xsi:nil="true"/>
</ogr:point_on_multipoly>
</gml:featureMember>
<gml:featureMember>
<ogr:point_on_multipoly fid="multipolys.1">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8.0,5.5</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:Bname xsi:nil="true"/>
<ogr:Bintval xsi:nil="true"/>
<ogr:Bfloatval xsi:nil="true"/>
</ogr:point_on_multipoly>
</gml:featureMember>
<gml:featureMember>
<ogr:point_on_multipoly fid="multipolys.2">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0.5,0.5</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:Bname>Test</ogr:Bname>
<ogr:Bintval>2</ogr:Bintval>
<ogr:Bfloatval>-0.12300</ogr:Bfloatval>
</ogr:point_on_multipoly>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,45 @@
<?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="point_on_multipoly" type="ogr:point_on_multipoly_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="point_on_multipoly_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="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:totalDigits value="21"/>
<xs:fractionDigits value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
12 changes: 12 additions & 0 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Expand Up @@ -881,6 +881,18 @@ tests:
name: expected/point_on_poly.gml
type: vector

- algorithm: native:pointonsurface
name: Point on all parts of multi polygon surface
params:
INPUT:
name: multipolys.gml
type: vector
ALL_PARTS: true
results:
OUTPUT:
name: expected/point_on_multipoly.gml
type: vector

- algorithm: qgis:pointonsurface
name: Point on multipoint surface
params:
Expand Down
66 changes: 60 additions & 6 deletions src/analysis/processing/qgsalgorithmpointonsurface.cpp
Expand Up @@ -16,6 +16,7 @@
***************************************************************************/

#include "qgsalgorithmpointonsurface.h"
#include "qgsgeometrycollection.h"

///@cond PRIVATE

Expand Down Expand Up @@ -59,19 +60,72 @@ QgsPointOnSurfaceAlgorithm *QgsPointOnSurfaceAlgorithm::createInstance() const
return new QgsPointOnSurfaceAlgorithm();
}

QgsFeatureList QgsPointOnSurfaceAlgorithm::processFeature( const QgsFeature &f, QgsProcessingContext &, QgsProcessingFeedback *feedback )
void QgsPointOnSurfaceAlgorithm::initParameters( const QVariantMap & )
{
std::unique_ptr< QgsProcessingParameterBoolean> allParts = qgis::make_unique< QgsProcessingParameterBoolean >(
QStringLiteral( "ALL_PARTS" ),
QObject::tr( "Create point on surface for each part" ),
false );
allParts->setIsDynamic( true );
allParts->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "All parts" ), QObject::tr( "Create point on surface for each part" ), QgsPropertyDefinition::Boolean ) );
allParts->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( allParts.release() );
}

bool QgsPointOnSurfaceAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
mAllParts = parameterAsBool( parameters, QStringLiteral( "ALL_PARTS" ), context );
mDynamicAllParts = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "ALL_PARTS" ) );
if ( mDynamicAllParts )
mAllPartsProperty = parameters.value( QStringLiteral( "ALL_PARTS" ) ).value< QgsProperty >();

return true;
}

QgsFeatureList QgsPointOnSurfaceAlgorithm::processFeature( const QgsFeature &f, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
QgsFeatureList list;
QgsFeature feature = f;
if ( feature.hasGeometry() )
{
QgsGeometry outputGeometry = feature.geometry().pointOnSurface();
if ( !outputGeometry )
QgsGeometry geom = feature.geometry();

bool allParts = mAllParts;
if ( mDynamicAllParts )
allParts = mAllPartsProperty.valueAsBool( context.expressionContext(), allParts );

if ( allParts && geom.isMultipart() )
{
feedback->pushInfo( QObject::tr( "Error calculating point on surface for feature %1: %2" ).arg( feature.id() ).arg( outputGeometry.lastError() ) );
const QgsGeometryCollection *geomCollection = static_cast<const QgsGeometryCollection *>( geom.constGet() );

for ( int i = 0; i < geomCollection->partCount(); ++i )
{
QgsGeometry partGeometry( geomCollection->geometryN( i )->clone() );
QgsGeometry outputGeometry = partGeometry.pointOnSurface();
if ( !outputGeometry )
{
feedback->pushInfo( QObject::tr( "Error calculating point on surface for feature %1 part %2: %3" ).arg( feature.id() ).arg( i ).arg( outputGeometry.lastError() ) );
}
feature.setGeometry( outputGeometry );
list << feature;
}
}
feature.setGeometry( outputGeometry );
else
{
QgsGeometry outputGeometry = feature.geometry().pointOnSurface();
if ( !outputGeometry )
{
feedback->pushInfo( QObject::tr( "Error calculating point on surface for feature %1: %2" ).arg( feature.id() ).arg( outputGeometry.lastError() ) );
}
feature.setGeometry( outputGeometry );
list << feature;
}
}
else
{
list << feature;
}
return QgsFeatureList() << feature;
return list;
}

///@endcond
9 changes: 9 additions & 0 deletions src/analysis/processing/qgsalgorithmpointonsurface.h
Expand Up @@ -41,14 +41,23 @@ class QgsPointOnSurfaceAlgorithm : public QgsProcessingFeatureBasedAlgorithm
QString groupId() const override;
QString shortHelpString() const override;
QgsPointOnSurfaceAlgorithm *createInstance() const override SIP_FACTORY;
void initParameters( const QVariantMap &configuration = QVariantMap() ) override;

protected:

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

bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;

private:

bool mAllParts = false;
bool mDynamicAllParts = false;
QgsProperty mAllPartsProperty;

};

///@endcond PRIVATE
Expand Down

0 comments on commit 0630b1c

Please sign in to comment.