QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsalgorithmunion.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmunion.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 
16 #include "qgsalgorithmunion.h"
17 
18 #include "qgsoverlayutils.h"
19 
21 
22 
23 QString QgsUnionAlgorithm::name() const
24 {
25  return QStringLiteral( "union" );
26 }
27 
28 QString QgsUnionAlgorithm::displayName() const
29 {
30  return QObject::tr( "Union" );
31 }
32 
33 QString QgsUnionAlgorithm::group() const
34 {
35  return QObject::tr( "Vector overlay" );
36 }
37 
38 QString QgsUnionAlgorithm::groupId() const
39 {
40  return QStringLiteral( "vectoroverlay" );
41 }
42 
43 QString QgsUnionAlgorithm::shortHelpString() const
44 {
45  return QObject::tr( "This algorithm checks overlaps between features within the Input layer and creates separate features for overlapping "
46  "and non-overlapping parts. The area of overlap will create as many identical overlapping features as there are "
47  "features that participate in that overlap." )
48  + QStringLiteral( "\n\n" )
49  + QObject::tr( "An Overlay layer can also be used, in which case features from each layer are split at their overlap with features from "
50  "the other one, creating a layer containing all the portions from both Input and Overlay layers. "
51  "The attribute table of the Union layer is filled with attribute values from the respective original layer "
52  "for non-overlapping features, and attribute values from both layers for overlapping features." );
53 }
54 
55 QgsProcessingAlgorithm *QgsUnionAlgorithm::createInstance() const
56 {
57  return new QgsUnionAlgorithm();
58 }
59 
60 void QgsUnionAlgorithm::initAlgorithm( const QVariantMap & )
61 {
62  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
63  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "OVERLAY" ), QObject::tr( "Overlay layer" ), QList< int >(), QVariant(), true ) );
64 
65  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Union" ) ) );
66 }
67 
68 QVariantMap QgsUnionAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
69 {
70  std::unique_ptr< QgsFeatureSource > sourceA( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
71  if ( !sourceA )
72  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
73 
74  std::unique_ptr< QgsFeatureSource > sourceB( parameterAsSource( parameters, QStringLiteral( "OVERLAY" ), context ) );
75  if ( parameters.value( QStringLiteral( "OVERLAY" ) ).isValid() && !sourceB )
76  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "OVERLAY" ) ) );
77 
78  QgsWkbTypes::Type geomType = QgsWkbTypes::multiType( sourceA->wkbType() );
79 
80  QgsFields fields = sourceB ? QgsProcessingUtils::combineFields( sourceA->fields(), sourceB->fields() ) : sourceA->fields();
81 
82  QString dest;
83  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, geomType, sourceA->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) );
84  if ( !sink )
85  throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
86 
87  QVariantMap outputs;
88  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
89 
90  if ( !sourceB )
91  {
92  // we are doing single layer union
93  QgsOverlayUtils::resolveOverlaps( *sourceA, *sink, feedback );
94  return outputs;
95  }
96 
97  QList<int> fieldIndicesA = QgsProcessingUtils::fieldNamesToIndices( QStringList(), sourceA->fields() );
98  QList<int> fieldIndicesB = QgsProcessingUtils::fieldNamesToIndices( QStringList(), sourceB->fields() );
99 
100  int count = 0;
101  int total = sourceA->featureCount() * 2 + sourceB->featureCount();
102 
103  QgsOverlayUtils::intersection( *sourceA, *sourceB, *sink, context, feedback, count, total, fieldIndicesA, fieldIndicesB );
104 
105  QgsOverlayUtils::difference( *sourceA, *sourceB, *sink, context, feedback, count, total, QgsOverlayUtils::OutputAB );
106 
107  QgsOverlayUtils::difference( *sourceB, *sourceA, *sink, context, feedback, count, total, QgsOverlayUtils::OutputBA );
108 
109  return outputs;
110 }
111 
static Type multiType(Type type)
Returns the multi type for a WKB type.
Definition: qgswkbtypes.h:298
Base class for providing feedback from a processing algorithm.
Container of fields for a vector layer.
Definition: qgsfields.h:42
Abstract base class for processing algorithms.
A feature sink output for processing algorithms.
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
static QList< int > fieldNamesToIndices(const QStringList &fieldNames, const QgsFields &fields)
Returns a list of field indices parsed from the given list of field names.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
static QgsFields combineFields(const QgsFields &fieldsA, const QgsFields &fieldsB)
Combines two field lists, avoiding duplicate field names (in a case-insensitive manner).
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
An input feature source (such as vector layers) parameter for processing algorithms.
Contains information about the context in which a processing algorithm is executed.