Branch data Line data Source code
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 : :
20 : : ///@cond PRIVATE
21 : :
22 : :
23 : 0 : QString QgsUnionAlgorithm::name() const
24 : : {
25 : 0 : return QStringLiteral( "union" );
26 : : }
27 : :
28 : 0 : QString QgsUnionAlgorithm::displayName() const
29 : : {
30 : 0 : return QObject::tr( "Union" );
31 : : }
32 : :
33 : 0 : QString QgsUnionAlgorithm::group() const
34 : : {
35 : 0 : return QObject::tr( "Vector overlay" );
36 : : }
37 : :
38 : 0 : QString QgsUnionAlgorithm::groupId() const
39 : : {
40 : 0 : return QStringLiteral( "vectoroverlay" );
41 : : }
42 : :
43 : 0 : QString QgsUnionAlgorithm::shortHelpString() const
44 : : {
45 : 0 : 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 : 0 : + QStringLiteral( "\n\n" )
49 : 0 : + 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 : 0 : }
54 : :
55 : 0 : QgsProcessingAlgorithm *QgsUnionAlgorithm::createInstance() const
56 : : {
57 : 0 : return new QgsUnionAlgorithm();
58 : : }
59 : :
60 : 0 : void QgsUnionAlgorithm::initAlgorithm( const QVariantMap & )
61 : : {
62 : 0 : addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
63 : 0 : addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "OVERLAY" ), QObject::tr( "Overlay layer" ), QList< int >(), QVariant(), true ) );
64 : :
65 : 0 : std::unique_ptr< QgsProcessingParameterString > prefix = std::make_unique< QgsProcessingParameterString >( QStringLiteral( "OVERLAY_FIELDS_PREFIX" ), QObject::tr( "Overlay fields prefix" ), QString(), false, true );
66 : 0 : prefix->setFlags( prefix->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
67 : 0 : addParameter( prefix.release() );
68 : :
69 : 0 : addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Union" ) ) );
70 : 0 : }
71 : :
72 : 0 : QVariantMap QgsUnionAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
73 : : {
74 : 0 : std::unique_ptr< QgsFeatureSource > sourceA( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
75 : 0 : if ( !sourceA )
76 : 0 : throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
77 : :
78 : 0 : std::unique_ptr< QgsFeatureSource > sourceB( parameterAsSource( parameters, QStringLiteral( "OVERLAY" ), context ) );
79 : 0 : if ( parameters.value( QStringLiteral( "OVERLAY" ) ).isValid() && !sourceB )
80 : 0 : throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "OVERLAY" ) ) );
81 : :
82 : 0 : QgsWkbTypes::Type geomType = QgsWkbTypes::multiType( sourceA->wkbType() );
83 : :
84 : 0 : QString overlayFieldsPrefix = parameterAsString( parameters, QStringLiteral( "OVERLAY_FIELDS_PREFIX" ), context );
85 : 0 : QgsFields fields = sourceB ? QgsProcessingUtils::combineFields( sourceA->fields(), sourceB->fields(), overlayFieldsPrefix ) : sourceA->fields();
86 : :
87 : 0 : QString dest;
88 : 0 : std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, geomType, sourceA->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) );
89 : 0 : if ( !sink )
90 : 0 : throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
91 : :
92 : 0 : QVariantMap outputs;
93 : 0 : outputs.insert( QStringLiteral( "OUTPUT" ), dest );
94 : :
95 : 0 : if ( !sourceB )
96 : : {
97 : : // we are doing single layer union
98 : 0 : QgsOverlayUtils::resolveOverlaps( *sourceA, *sink, feedback );
99 : 0 : return outputs;
100 : : }
101 : :
102 : 0 : QList<int> fieldIndicesA = QgsProcessingUtils::fieldNamesToIndices( QStringList(), sourceA->fields() );
103 : 0 : QList<int> fieldIndicesB = QgsProcessingUtils::fieldNamesToIndices( QStringList(), sourceB->fields() );
104 : :
105 : 0 : int count = 0;
106 : 0 : int total = sourceA->featureCount() * 2 + sourceB->featureCount();
107 : :
108 : 0 : QgsOverlayUtils::intersection( *sourceA, *sourceB, *sink, context, feedback, count, total, fieldIndicesA, fieldIndicesB );
109 : :
110 : 0 : QgsOverlayUtils::difference( *sourceA, *sourceB, *sink, context, feedback, count, total, QgsOverlayUtils::OutputAB );
111 : :
112 : 0 : QgsOverlayUtils::difference( *sourceB, *sourceA, *sink, context, feedback, count, total, QgsOverlayUtils::OutputBA );
113 : :
114 : 0 : return outputs;
115 : 0 : }
116 : :
117 : : ///@endcond
|