QGIS API Documentation 3.29.0-Master (8c80f25a4f)
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
21
22QString QgsSymmetricalDifferenceAlgorithm::name() const
23{
24 return QStringLiteral( "symmetricaldifference" );
25}
26
27QString QgsSymmetricalDifferenceAlgorithm::displayName() const
28{
29 return QObject::tr( "Symmetrical difference" );
30}
31
32QStringList QgsSymmetricalDifferenceAlgorithm::tags() const
33{
34 return QObject::tr( "difference,symdiff,not overlap" ).split( ',' );
35}
36
37QString QgsSymmetricalDifferenceAlgorithm::group() const
38{
39 return QObject::tr( "Vector overlay" );
40}
41
42QString QgsSymmetricalDifferenceAlgorithm::groupId() const
43{
44 return QStringLiteral( "vectoroverlay" );
45}
46
47QString QgsSymmetricalDifferenceAlgorithm::shortHelpString() const
48{
49 return QObject::tr( "This algorithm extracts the portions of features from both the Input and Overlay layers that do not overlap. "
50 "Overlapping areas between the two layers are removed. The attribute table of the Symmetrical Difference layer "
51 "contains original attributes from both the Input and Difference layers." );
52}
53
54QgsProcessingAlgorithm *QgsSymmetricalDifferenceAlgorithm::createInstance() const
55{
56 return new QgsSymmetricalDifferenceAlgorithm();
57}
58
59void QgsSymmetricalDifferenceAlgorithm::initAlgorithm( const QVariantMap & )
60{
61 addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
62 addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "OVERLAY" ), QObject::tr( "Overlay layer" ) ) );
63
64 std::unique_ptr< QgsProcessingParameterString > prefix = std::make_unique< QgsProcessingParameterString >( QStringLiteral( "OVERLAY_FIELDS_PREFIX" ), QObject::tr( "Overlay fields prefix" ), QString(), false, true );
65 prefix->setFlags( prefix->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
66 addParameter( prefix.release() );
67
68 addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Symmetrical difference" ) ) );
69
70 std::unique_ptr< QgsProcessingParameterNumber > gridSize = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "GRID_SIZE" ),
71 QObject::tr( "Grid size" ), QgsProcessingParameterNumber::Double, QVariant(), true, 0 );
72 gridSize->setFlags( gridSize->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
73 addParameter( gridSize.release() );
74}
75
76
77QVariantMap QgsSymmetricalDifferenceAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
78{
79 std::unique_ptr< QgsFeatureSource > sourceA( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
80 if ( !sourceA )
81 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
82
83 std::unique_ptr< QgsFeatureSource > sourceB( parameterAsSource( parameters, QStringLiteral( "OVERLAY" ), context ) );
84 if ( !sourceB )
85 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "OVERLAY" ) ) );
86
87 const QgsWkbTypes::Type geomTypeA = QgsWkbTypes::promoteNonPointTypesToMulti( sourceA->wkbType() );
88 const QgsWkbTypes::Type geomTypeB = QgsWkbTypes::promoteNonPointTypesToMulti( sourceB->wkbType() );
89
90 if ( geomTypeA != geomTypeB )
91 feedback->pushWarning( QObject::tr( "Performing symmetrical difference between layers with different geometry types (INPUT has %1 and OVERLAY has %2) can lead to unexpected results" ).arg( QgsWkbTypes::displayString( sourceA->wkbType() ), QgsWkbTypes::displayString( sourceB->wkbType() ) ) );
92
93 const QString overlayFieldsPrefix = parameterAsString( parameters, QStringLiteral( "OVERLAY_FIELDS_PREFIX" ), context );
94 const QgsFields fields = QgsProcessingUtils::combineFields( sourceA->fields(), sourceB->fields(), overlayFieldsPrefix );
95
96 QString dest;
97 std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, geomTypeA, sourceA->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) );
98 if ( !sink )
99 throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
100
101 QVariantMap outputs;
102 outputs.insert( QStringLiteral( "OUTPUT" ), dest );
103
104 long count = 0;
105 const long total = sourceA->featureCount() + sourceB->featureCount();
106
107 QgsGeometryParameters geometryParameters;
108 if ( parameters.value( QStringLiteral( "GRID_SIZE" ) ).isValid() )
109 {
110 geometryParameters.setGridSize( parameterAsDouble( parameters, QStringLiteral( "GRID_SIZE" ), context ) );
111 }
112
113 QgsOverlayUtils::difference( *sourceA, *sourceB, *sink, context, feedback, count, total, QgsOverlayUtils::OutputAB, geometryParameters, QgsOverlayUtils::SanitizeFlag::DontPromotePointGeometryToMultiPoint );
114 if ( feedback->isCanceled() )
115 return outputs;
116
117 QgsOverlayUtils::difference( *sourceB, *sourceA, *sink, context, feedback, count, total, QgsOverlayUtils::OutputBA, geometryParameters, QgsOverlayUtils::SanitizeFlag::DontPromotePointGeometryToMultiPoint );
118
119 return outputs;
120}
121
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
Container of fields for a vector layer.
Definition: qgsfields.h:45
Encapsulates parameters under which a geometry operation is performed.
Definition: qgsgeometry.h:111
void setGridSize(double size)
Sets the grid size which will be used to snap vertices of a geometry.
Definition: qgsgeometry.h:136
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.
Definition: qgsexception.h:83
Base class for providing feedback from a processing algorithm.
virtual void pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
@ FlagAdvanced
Parameter is an advanced parameter which should be hidden from users by default.
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 Type promoteNonPointTypesToMulti(Type type) SIP_HOLDGIL
Promotes a WKB geometry type to its multi-type equivalent, with the exception of point geometry types...
Definition: qgswkbtypes.h:451
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
static QString displayString(Type type) SIP_HOLDGIL
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...