QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgsalgorithmsymmetricaldifference.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmsymmetricaldifference.cpp
3 ---------------------
4 Date : April 2018
5 Copyright : (C) 2018 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include "qgsoverlayutils.h"
19
20#include <QString>
21
22using namespace Qt::StringLiterals;
23
25
26QString QgsSymmetricalDifferenceAlgorithm::name() const
27{
28 return u"symmetricaldifference"_s;
29}
30
31QString QgsSymmetricalDifferenceAlgorithm::displayName() const
32{
33 return QObject::tr( "Symmetrical difference" );
34}
35
36QStringList QgsSymmetricalDifferenceAlgorithm::tags() const
37{
38 return QObject::tr( "difference,symdiff,not overlap" ).split( ',' );
39}
40
41QString QgsSymmetricalDifferenceAlgorithm::group() const
42{
43 return QObject::tr( "Vector overlay" );
44}
45
46QString QgsSymmetricalDifferenceAlgorithm::groupId() const
47{
48 return u"vectoroverlay"_s;
49}
50
51QString QgsSymmetricalDifferenceAlgorithm::shortHelpString() const
52{
53 return QObject::tr(
54 "This algorithm extracts the portions of features from both the Input and Overlay layers that do not overlap. "
55 "Overlapping areas between the two layers are removed. The attribute table of the Symmetrical Difference layer "
56 "contains original attributes from both the Input and Overlay layers."
57 );
58}
59
60QString QgsSymmetricalDifferenceAlgorithm::shortDescription() const
61{
62 return QObject::tr( "Extracts the portions of features from two layers that do not overlap." );
63}
64
65Qgis::ProcessingAlgorithmDocumentationFlags QgsSymmetricalDifferenceAlgorithm::documentationFlags() const
66{
68}
69
70QgsProcessingAlgorithm *QgsSymmetricalDifferenceAlgorithm::createInstance() const
71{
72 return new QgsSymmetricalDifferenceAlgorithm();
73}
74
75void QgsSymmetricalDifferenceAlgorithm::initAlgorithm( const QVariantMap & )
76{
77 addParameter( new QgsProcessingParameterFeatureSource( u"INPUT"_s, QObject::tr( "Input layer" ) ) );
78 addParameter( new QgsProcessingParameterFeatureSource( u"OVERLAY"_s, QObject::tr( "Overlay layer" ) ) );
79
80 auto prefix = std::make_unique<QgsProcessingParameterString>( u"OVERLAY_FIELDS_PREFIX"_s, QObject::tr( "Overlay fields prefix" ), QString(), false, true );
81 prefix->setFlags( prefix->flags() | Qgis::ProcessingParameterFlag::Advanced );
82 addParameter( prefix.release() );
83
84 addParameter( new QgsProcessingParameterFeatureSink( u"OUTPUT"_s, QObject::tr( "Symmetrical difference" ) ) );
85
86 auto gridSize = std::make_unique<QgsProcessingParameterNumber>( u"GRID_SIZE"_s, QObject::tr( "Grid size" ), Qgis::ProcessingNumberParameterType::Double, QVariant(), true, 0 );
87 gridSize->setFlags( gridSize->flags() | Qgis::ProcessingParameterFlag::Advanced );
88 addParameter( gridSize.release() );
89}
90
91
92QVariantMap QgsSymmetricalDifferenceAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
93{
94 std::unique_ptr<QgsFeatureSource> sourceA( parameterAsSource( parameters, u"INPUT"_s, context ) );
95 if ( !sourceA )
96 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
97
98 std::unique_ptr<QgsFeatureSource> sourceB( parameterAsSource( parameters, u"OVERLAY"_s, context ) );
99 if ( !sourceB )
100 throw QgsProcessingException( invalidSourceError( parameters, u"OVERLAY"_s ) );
101
102 const Qgis::WkbType geomTypeA = QgsWkbTypes::promoteNonPointTypesToMulti( sourceA->wkbType() );
103 const Qgis::WkbType geomTypeB = QgsWkbTypes::promoteNonPointTypesToMulti( sourceB->wkbType() );
104
105 if ( geomTypeA != geomTypeB )
106 feedback->pushWarning(
107 QObject::tr( "Performing symmetrical difference between layers with different geometry types (INPUT has %1 and OVERLAY has %2) can lead to unexpected results" )
108 .arg( QgsWkbTypes::displayString( sourceA->wkbType() ), QgsWkbTypes::displayString( sourceB->wkbType() ) )
109 );
110
111 const QString overlayFieldsPrefix = parameterAsString( parameters, u"OVERLAY_FIELDS_PREFIX"_s, context );
112 const QgsFields fields = QgsProcessingUtils::combineFields( sourceA->fields(), sourceB->fields(), overlayFieldsPrefix );
113
114 QString dest;
115 std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, u"OUTPUT"_s, context, dest, fields, geomTypeA, sourceA->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) );
116 if ( !sink )
117 throw QgsProcessingException( invalidSinkError( parameters, u"OUTPUT"_s ) );
118
119 QVariantMap outputs;
120 outputs.insert( u"OUTPUT"_s, dest );
121
122 long count = 0;
123 const long total = sourceA->featureCount() + sourceB->featureCount();
124
125 QgsGeometryParameters geometryParameters;
126 if ( parameters.value( u"GRID_SIZE"_s ).isValid() )
127 {
128 geometryParameters.setGridSize( parameterAsDouble( parameters, u"GRID_SIZE"_s, context ) );
129 }
130
131 QgsOverlayUtils::difference( *sourceA, *sourceB, *sink, context, feedback, count, total, QgsOverlayUtils::OutputAB, geometryParameters, QgsOverlayUtils::SanitizeFlag::DontPromotePointGeometryToMultiPoint );
132 if ( feedback->isCanceled() )
133 return outputs;
134
135 QgsOverlayUtils::difference( *sourceB, *sourceA, *sink, context, feedback, count, total, QgsOverlayUtils::OutputBA, geometryParameters, QgsOverlayUtils::SanitizeFlag::DontPromotePointGeometryToMultiPoint );
136
137 sink->finalize();
138
139 return outputs;
140}
141
@ RegeneratesPrimaryKey
Algorithm always drops any existing primary keys or FID values and regenerates them in outputs.
Definition qgis.h:3734
QFlags< ProcessingAlgorithmDocumentationFlag > ProcessingAlgorithmDocumentationFlags
Flags describing algorithm behavior for documentation purposes.
Definition qgis.h:3745
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:294
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
Definition qgis.h:3880
@ Double
Double/float values.
Definition qgis.h:3921
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:56
Container of fields for a vector layer.
Definition qgsfields.h:46
Encapsulates parameters under which a geometry operation is performed.
void setGridSize(double size)
Sets the grid size which will be used to snap vertices of a geometry.
Abstract base class for processing algorithms.
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
virtual void pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
A feature sink output for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.
static QgsFields combineFields(const QgsFields &fieldsA, const QgsFields &fieldsB, const QString &fieldsBPrefix=QString())
Combines two field lists, avoiding duplicate field names (in a case-insensitive manner).
static Q_INVOKABLE QString displayString(Qgis::WkbType type)
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
static Qgis::WkbType promoteNonPointTypesToMulti(Qgis::WkbType type)
Promotes a WKB geometry type to its multi-type equivalent, with the exception of point geometry types...