-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6501 from alexbruy/multi-ring
[processing][FEATURE] add multi-ring buffer algorithm
- Loading branch information
Showing
7 changed files
with
541 additions
and
0 deletions.
There are no files selected for viewing
257 changes: 257 additions & 0 deletions
257
python/plugins/processing/tests/testdata/expected/multiring_buffer.gml
Large diffs are not rendered by default.
Oops, something went wrong.
52 changes: 52 additions & 0 deletions
52
python/plugins/processing/tests/testdata/expected/multiring_buffer.xsd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
<?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="multiring_buffer" type="ogr:multiring_buffer_Type" substitutionGroup="gml:_Feature"/> | ||
<xs:complexType name="multiring_buffer_Type"> | ||
<xs:complexContent> | ||
<xs:extension base="gml:AbstractFeatureType"> | ||
<xs:sequence> | ||
<xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/> | ||
<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: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:element name="ringId" 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="distance" nillable="true" minOccurs="0" maxOccurs="1"> | ||
<xs:simpleType> | ||
<xs:restriction base="xs:decimal"> | ||
<xs:totalDigits value="21"/> | ||
<xs:fractionDigits value="6"/> | ||
</xs:restriction> | ||
</xs:simpleType> | ||
</xs:element> | ||
</xs:sequence> | ||
</xs:extension> | ||
</xs:complexContent> | ||
</xs:complexType> | ||
</xs:schema> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
147 changes: 147 additions & 0 deletions
147
src/analysis/processing/qgsalgorithmmultiringconstantbuffer.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
/*************************************************************************** | ||
qgsalgorithmnultitingconstantbuffer.cpp | ||
-------------------------- | ||
begin : February 2018 | ||
copyright : (C) 2018 by Alexander Bruy | ||
email : alexander dot bruy 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. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgsalgorithmmultiringconstantbuffer.h" | ||
|
||
///@cond PRIVATE | ||
|
||
QString QgsMultiRingConstantBufferAlgorithm::name() const | ||
{ | ||
return QStringLiteral( "multiringconstantbuffer" ); | ||
} | ||
|
||
QString QgsMultiRingConstantBufferAlgorithm::displayName() const | ||
{ | ||
return QObject::tr( "Multi-ring buffer (constant distance)" ); | ||
} | ||
|
||
QStringList QgsMultiRingConstantBufferAlgorithm::tags() const | ||
{ | ||
return QObject::tr( "buffer,grow,multiple,rings,distance,donut" ).split( ',' ); | ||
} | ||
|
||
QString QgsMultiRingConstantBufferAlgorithm::group() const | ||
{ | ||
return QObject::tr( "Vector geometry" ); | ||
} | ||
|
||
QString QgsMultiRingConstantBufferAlgorithm::groupId() const | ||
{ | ||
return QStringLiteral( "vectorgeometry" ); | ||
} | ||
|
||
QString QgsMultiRingConstantBufferAlgorithm::outputName() const | ||
{ | ||
return QObject::tr( "Multi-ring buffer (constant distance)" ); | ||
} | ||
|
||
QString QgsMultiRingConstantBufferAlgorithm::shortHelpString() const | ||
{ | ||
return QObject::tr( "This algorithm computes multi-ring ('donuts') buffer for all the features in an input layer, using a fixed or dynamic distance and rings number." ); | ||
} | ||
|
||
QgsMultiRingConstantBufferAlgorithm *QgsMultiRingConstantBufferAlgorithm::createInstance() const | ||
{ | ||
return new QgsMultiRingConstantBufferAlgorithm(); | ||
} | ||
|
||
void QgsMultiRingConstantBufferAlgorithm::initParameters( const QVariantMap & ) | ||
{ | ||
std::unique_ptr< QgsProcessingParameterNumber> rings = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "RINGS" ), | ||
QObject::tr( "Number of rings" ), QgsProcessingParameterNumber::Integer, | ||
1, false, 0 ); | ||
rings->setIsDynamic( true ); | ||
rings->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "RINGS" ), QObject::tr( "Number of rings" ), QgsPropertyDefinition::IntegerPositive ) ); | ||
rings->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) ); | ||
addParameter( rings.release() ); | ||
|
||
std::unique_ptr< QgsProcessingParameterNumber> distance = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "DISTANCE" ), | ||
QObject::tr( "Distance between rings" ), QgsProcessingParameterNumber::Double, | ||
1, false, 0 ); | ||
distance->setIsDynamic( true ); | ||
distance->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "DISTANCE" ), QObject::tr( "Distance between rings" ), QgsPropertyDefinition::DoublePositive ) ); | ||
distance->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) ); | ||
addParameter( distance.release() ); | ||
} | ||
|
||
bool QgsMultiRingConstantBufferAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * ) | ||
{ | ||
mRingsNumber = parameterAsInt( parameters, QStringLiteral( "RINGS" ), context ); | ||
mDynamicRingsNumber = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "RINGS" ) ); | ||
if ( mDynamicRingsNumber ) | ||
mRingsNumberProperty = parameters.value( QStringLiteral( "RINGS" ) ).value< QgsProperty >(); | ||
|
||
mDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context ); | ||
mDynamicDistance = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) ); | ||
if ( mDynamicDistance ) | ||
mDistanceProperty = parameters.value( QStringLiteral( "DISTANCE" ) ).value< QgsProperty >(); | ||
|
||
return true; | ||
} | ||
|
||
QgsFields QgsMultiRingConstantBufferAlgorithm::outputFields( const QgsFields &inputFields ) const | ||
{ | ||
QgsFields fields = inputFields; | ||
fields.append( QgsField( QStringLiteral( "ringId" ), QVariant::Int, QString(), 10, 0 ) ); | ||
fields.append( QgsField( QStringLiteral( "distance" ), QVariant::Double, QString(), 20, 6 ) ); | ||
return fields; | ||
} | ||
|
||
QgsFeatureList QgsMultiRingConstantBufferAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) | ||
{ | ||
double currentDistance = 0; | ||
QgsGeometry outputGeometry, previousGeometry; | ||
|
||
int rings = mRingsNumber; | ||
if ( mDynamicRingsNumber ) | ||
rings = mRingsNumberProperty.valueAsInt( context.expressionContext(), rings ); | ||
|
||
double distance = mDistance; | ||
if ( mDynamicDistance ) | ||
distance = mDistanceProperty.valueAsDouble( context.expressionContext(), distance ); | ||
|
||
QgsFeatureList outputs; | ||
|
||
for ( int i = 1; i <= mRingsNumber; ++i ) | ||
{ | ||
QgsFeature out; | ||
currentDistance = i * distance; | ||
outputGeometry = feature.geometry().buffer( currentDistance, 40 ); | ||
if ( !outputGeometry ) | ||
{ | ||
feedback->reportError( QObject::tr( "Error calculating buffer for feature %1" ).arg( feature.id() ) ); | ||
continue; | ||
} | ||
|
||
if ( i == 1 ) | ||
{ | ||
out.setGeometry( outputGeometry ); | ||
} | ||
else | ||
{ | ||
out.setGeometry( outputGeometry.symDifference( previousGeometry ) ); | ||
} | ||
previousGeometry = outputGeometry; | ||
QgsAttributes attrs = feature.attributes(); | ||
attrs << i << currentDistance; | ||
out.setAttributes( attrs ); | ||
outputs.append( out ); | ||
} | ||
return outputs; | ||
} | ||
|
||
///@endcond |
69 changes: 69 additions & 0 deletions
69
src/analysis/processing/qgsalgorithmmultiringconstantbuffer.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/*************************************************************************** | ||
qgsalgorithmmultiringconstantbuffer.h | ||
------------------------- | ||
begin : February 2018 | ||
copyright : (C) 2018 by Alexander Bruy | ||
email : alexander dot bruy 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. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGSALGORITHMMULTIRINGCONSTANTBUFFER_H | ||
#define QGSALGORITHMMULTIRINGCONSTANTBUFFER_H | ||
|
||
#define SIP_NO_FILE | ||
|
||
#include "qgis.h" | ||
#include "qgsprocessingalgorithm.h" | ||
|
||
///@cond PRIVATE | ||
|
||
/** | ||
* Native multiring buffer algorithm. | ||
*/ | ||
class QgsMultiRingConstantBufferAlgorithm : public QgsProcessingFeatureBasedAlgorithm | ||
{ | ||
|
||
public: | ||
|
||
QgsMultiRingConstantBufferAlgorithm() = default; | ||
QString name() const override; | ||
QString displayName() const override; | ||
QStringList tags() const override; | ||
QString group() const override; | ||
QString groupId() const override; | ||
QString shortHelpString() const override; | ||
QgsMultiRingConstantBufferAlgorithm *createInstance() const override SIP_FACTORY; | ||
void initParameters( const QVariantMap &configuration = QVariantMap() ) override; | ||
|
||
protected: | ||
|
||
QString outputName() const override; | ||
QgsFields outputFields( const QgsFields &inputFields ) const override; | ||
QgsProcessing::SourceType outputLayerType() const override { return QgsProcessing::TypeVectorPolygon; } | ||
QgsWkbTypes::Type outputWkbType( QgsWkbTypes::Type inputWkbType ) const override { Q_UNUSED( inputWkbType ); return QgsWkbTypes::Polygon; } | ||
bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override; | ||
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override; | ||
|
||
private: | ||
int mRingsNumber = 0; | ||
bool mDynamicRingsNumber = false; | ||
QgsProperty mRingsNumberProperty; | ||
|
||
double mDistance = 0.0; | ||
bool mDynamicDistance = false; | ||
QgsProperty mDistanceProperty; | ||
}; | ||
|
||
///@endcond PRIVATE | ||
|
||
#endif // QGSALGORITHMMULTIRINGCONSTANTBUFFER_H | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters