diff --git a/python/plugins/processing/algs/help/qgis.yaml b/python/plugins/processing/algs/help/qgis.yaml
index e78e76eca37..95b929848c0 100644
--- a/python/plugins/processing/algs/help/qgis.yaml
+++ b/python/plugins/processing/algs/help/qgis.yaml
@@ -530,10 +530,6 @@ qgis:truncatetable: >
Warning - this algorithm modifies the layer in place, and deleted features cannot be restored!
-qgis:union: >
- This algorithm creates a layer containing all the features from both input layers. In the case of polygon layers, separate features are created for overlapping and non-overlapping features. The attribute table of the union layer contains attribute values from the respective input layer for non-overlapping features, and attribute values from both input layers for overlapping features.
-
-
qgis:variabledistancebuffer: >
This algorithm computes a buffer area for all the features in an input layer. The size of the buffer for a given feature is defined by an attribute, so it allows different features to have different buffer sizes.
diff --git a/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py b/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
index 924f625ebbd..5cd7565827e 100644
--- a/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
+++ b/python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
@@ -137,7 +137,6 @@ from .TextToFloat import TextToFloat
from .TinInterpolation import TinInterpolation
from .TopoColors import TopoColor
from .TruncateTable import TruncateTable
-from .Union import Union
from .UniqueValues import UniqueValues
from .VariableDistanceBuffer import VariableDistanceBuffer
from .VectorSplit import VectorSplit
@@ -253,7 +252,6 @@ class QgisAlgorithmProvider(QgsProcessingProvider):
TinInterpolation(),
TopoColor(),
TruncateTable(),
- Union(),
UniqueValues(),
VariableDistanceBuffer(),
VectorSplit(),
diff --git a/python/plugins/processing/algs/qgis/Union.py b/python/plugins/processing/algs/qgis/Union.py
deleted file mode 100644
index 2cf9c05327f..00000000000
--- a/python/plugins/processing/algs/qgis/Union.py
+++ /dev/null
@@ -1,250 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-***************************************************************************
- Union.py
- ---------------------
- Date : August 2012
- Copyright : (C) 2012 by Victor Olaya
- Email : volayaf 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. *
-* *
-***************************************************************************
-"""
-
-__author__ = 'Victor Olaya'
-__date__ = 'August 2012'
-__copyright__ = '(C) 2012, Victor Olaya'
-
-# This will get replaced with a git SHA1 when you do a git archive
-
-__revision__ = '$Format:%H$'
-
-import os
-
-from qgis.PyQt.QtGui import QIcon
-
-from qgis.core import (QgsFeatureRequest,
- QgsFeature,
- QgsFeatureSink,
- QgsGeometry,
- QgsWkbTypes,
- QgsProcessingUtils,
- QgsProcessingParameterFeatureSource,
- QgsProcessingParameterFeatureSink,
- QgsSpatialIndex)
-
-from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
-from processing.tools import vector
-
-pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
-
-
-class Union(QgisAlgorithm):
-
- INPUT = 'INPUT'
- OVERLAY = 'OVERLAY'
- OUTPUT = 'OUTPUT'
-
- def icon(self):
- return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'union.png'))
-
- def group(self):
- return self.tr('Vector overlay')
-
- def groupId(self):
- return 'vectoroverlay'
-
- def __init__(self):
- super().__init__()
-
- def initAlgorithm(self, config=None):
- self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
- self.tr('Input layer')))
- self.addParameter(QgsProcessingParameterFeatureSource(self.OVERLAY,
- self.tr('Union layer')))
-
- self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Union')))
-
- def name(self):
- return 'union'
-
- def displayName(self):
- return self.tr('Union')
-
- def processAlgorithm(self, parameters, context, feedback):
- sourceA = self.parameterAsSource(parameters, self.INPUT, context)
- sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
-
- geomType = QgsWkbTypes.multiType(sourceA.wkbType())
- fields = QgsProcessingUtils.combineFields(sourceA.fields(), sourceB.fields())
-
- (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
- fields, geomType, sourceA.sourceCrs())
-
- featA = QgsFeature()
- featB = QgsFeature()
- outFeat = QgsFeature()
-
- indexA = QgsSpatialIndex(sourceA, feedback)
- indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs(), context.transformContext())), feedback)
-
- total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
- count = 0
-
- for featA in sourceA.getFeatures():
- if feedback.isCanceled():
- break
-
- lstIntersectingB = []
- geom = featA.geometry()
- atMapA = featA.attributes()
- intersects = indexB.intersects(geom.boundingBox())
- if len(intersects) < 1:
- try:
- geom.convertToMultiType()
- outFeat.setGeometry(geom)
- outFeat.setAttributes(atMapA)
- sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
- except:
- # This really shouldn't happen, as we haven't
- # edited the input geom at all
- feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
- else:
- request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
- request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext())
-
- engine = QgsGeometry.createGeometryEngine(geom.constGet())
- engine.prepareGeometry()
-
- for featB in sourceB.getFeatures(request):
- atMapB = featB.attributes()
- tmpGeom = featB.geometry()
-
- if engine.intersects(tmpGeom.constGet()):
- int_geom = geom.intersection(tmpGeom)
- lstIntersectingB.append(tmpGeom)
-
- if not int_geom:
- # There was a problem creating the intersection
- feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
- int_geom = QgsGeometry()
- else:
- int_geom = QgsGeometry(int_geom)
-
- if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.wkbType()) == QgsWkbTypes.GeometryCollection:
- # Intersection produced different geomety types
- temp_list = int_geom.asGeometryCollection()
- for i in temp_list:
- if i.type() == geom.type():
- int_geom = QgsGeometry(i)
- try:
- int_geom.convertToMultiType()
- outFeat.setGeometry(int_geom)
- outFeat.setAttributes(atMapA + atMapB)
- sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
- except:
- feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
- else:
- # Geometry list: prevents writing error
- # in geometries of different types
- # produced by the intersection
- # fix #3549
- if QgsWkbTypes.geometryType(int_geom.wkbType()) == QgsWkbTypes.geometryType(geomType):
- try:
- int_geom.convertToMultiType()
- outFeat.setGeometry(int_geom)
- outFeat.setAttributes(atMapA + atMapB)
- sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
- except:
- feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
-
- # the remaining bit of featA's geometry
- # if there is nothing left, this will just silently fail and we're good
- diff_geom = QgsGeometry(geom)
- if len(lstIntersectingB) != 0:
- intB = QgsGeometry.unaryUnion(lstIntersectingB)
- diff_geom = diff_geom.difference(intB)
-
- if diff_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(diff_geom.wkbType()) == QgsWkbTypes.GeometryCollection:
- temp_list = diff_geom.asGeometryCollection()
- for i in temp_list:
- if i.type() == geom.type():
- diff_geom = QgsGeometry(i)
- try:
- diff_geom.convertToMultiType()
- outFeat.setGeometry(diff_geom)
- outFeat.setAttributes(atMapA)
- sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
- except:
- feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
-
- count += 1
- feedback.setProgress(int(count * total))
-
- length = len(sourceA.fields())
- atMapA = [None] * length
-
- for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs(), context.transformContext())):
- if feedback.isCanceled():
- break
-
- add = False
- geom = featA.geometry()
- diff_geom = QgsGeometry(geom)
- atMap = [None] * length
- atMap.extend(featA.attributes())
- intersects = indexA.intersects(geom.boundingBox())
-
- if len(intersects) < 1:
- try:
- geom.convertToMultiType()
- outFeat.setGeometry(geom)
- outFeat.setAttributes(atMap)
- sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
- except:
- feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
- else:
- request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
- request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext())
-
- # use prepared geometries for faster intersection tests
- engine = QgsGeometry.createGeometryEngine(diff_geom.constGet())
- engine.prepareGeometry()
-
- for featB in sourceA.getFeatures(request):
- atMapB = featB.attributes()
- tmpGeom = featB.geometry()
-
- if engine.intersects(tmpGeom.constGet()):
- add = True
- diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
- else:
- try:
- # Ihis only happens if the bounding box
- # intersects, but the geometry doesn't
- diff_geom.convertToMultiType()
- outFeat.setGeometry(diff_geom)
- outFeat.setAttributes(atMap)
- sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
- except:
- feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
-
- if add:
- try:
- diff_geom.convertToMultiType()
- outFeat.setGeometry(diff_geom)
- outFeat.setAttributes(atMap)
- sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
- except:
- feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
-
- count += 1
- feedback.setProgress(int(count * total))
-
- return {self.OUTPUT: dest_id}
diff --git a/python/plugins/processing/tests/testdata/expected/union1.gml b/python/plugins/processing/tests/testdata/expected/union1.gml
new file mode 100644
index 00000000000..f2434b728f4
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/union1.gml
@@ -0,0 +1,98 @@
+
+
+
+
+ 01
+ 911
+
+
+
+
+
+ 2,6 2,5 1,5 1,6 2,6
+ A1
+ B2
+
+
+
+
+ 4,5 3,5 3,6 4,6 4,5
+ A2
+ B2
+
+
+
+
+ 8,7 7,7 7,8 8,8 8,7
+ A3
+ B1
+
+
+
+
+ 6,7 5,7 5,8 6,8 6,7
+ A3
+ B3
+
+
+
+
+ 2,5 2,3 1,3 1,5 2,51,6 1,11 8,11 8,10 2,10 2,6 1,6
+ A1
+
+
+
+
+
+ 3,3 3,4 4,4 4,3 3,3
+ A4
+
+
+
+
+
+ 4,6 6,6 6,5 4,5 4,6
+ A2
+
+
+
+
+
+ 7,7 6,7 6,8 7,8 7,78,8 9,8 9,7 8,7 8,8
+ A3
+
+
+
+
+
+ 8,7 8,1 1,1 1,2 7,2 7,7 8,77,8 7,9 8,9 8,8 7,8
+
+ B1
+
+
+
+
+ 5,3 6,3 6,4 5,4 5,3
+
+ B4
+
+
+
+
+ 1,5 0,5 0,6 1,6 1,53,5 2,5 2,6 3,6 3,5
+
+ B2
+
+
+
+
+ 5,7 3,7 3,8 5,8 5,7
+
+ B3
+
+
+
diff --git a/python/plugins/processing/tests/testdata/expected/union1.xsd b/python/plugins/processing/tests/testdata/expected/union1.xsd
new file mode 100644
index 00000000000..50a20418bbd
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/union1.xsd
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/python/plugins/processing/tests/testdata/expected/union3.gml b/python/plugins/processing/tests/testdata/expected/union3.gml
new file mode 100644
index 00000000000..a20c283db9a
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/union3.gml
@@ -0,0 +1,63 @@
+
+
+
+
+ 11
+ 85
+
+
+
+
+
+ 6,2 5,2 5,3 6,3 6,2
+ A1
+ B4
+
+
+
+
+ 3,2 2,2 2,3 3,3 3,2
+ A1
+ B1
+
+
+
+
+ 4,2 3,2 3,3 4,3 5,3 5,2 4,27,2 6,2 6,3 7,3 7,2
+ A1
+
+
+
+
+
+ 4,2 4,1 2,1 2,2 3,2 4,2
+
+ B1
+
+
+
+
+ 2,3 1,3 1,4 2,4 2,3
+
+ B2
+
+
+
+
+ 7,3 7,4 8,4 8,1 7,1 7,2 7,3
+
+ B3
+
+
+
+
+ 4,3 4,5 6,5 6,3 5,3 5,4 4,3
+
+ B4
+
+
+
diff --git a/python/plugins/processing/tests/testdata/expected/union3.xsd b/python/plugins/processing/tests/testdata/expected/union3.xsd
new file mode 100644
index 00000000000..0c59b769085
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/union3.xsd
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
index 00d1997282b..ed1eafb8846 100644
--- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
+++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
@@ -5328,4 +5328,40 @@ tests:
fields:
fid: skip
+ - algorithm: native:union
+ name: Test Union (basic)
+ params:
+ INPUT:
+ name: custom/overlay1_a.geojson
+ type: vector
+ OVERLAY:
+ name: custom/overlay1_b.geojson
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/union1.gml
+ type: vector
+ pk: [id_a, id_b]
+ compare:
+ fields:
+ fid: skip
+
+ - algorithm: native:union
+ name: Test Union (geom types)
+ params:
+ INPUT:
+ name: custom/overlay3_a.geojson
+ type: vector
+ OVERLAY:
+ name: custom/overlay3_b.geojson
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/union3.gml
+ type: vector
+ pk: [id_a, id_b]
+ compare:
+ fields:
+ fid: skip
+
# See ../README.md for a description of the file format
diff --git a/src/analysis/CMakeLists.txt b/src/analysis/CMakeLists.txt
index e73ca4de634..f67db0b79eb 100755
--- a/src/analysis/CMakeLists.txt
+++ b/src/analysis/CMakeLists.txt
@@ -78,6 +78,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmtransect.cpp
processing/qgsalgorithmtransform.cpp
processing/qgsalgorithmtranslate.cpp
+ processing/qgsalgorithmunion.cpp
processing/qgsalgorithmuniquevalueindex.cpp
processing/qgsalgorithmwedgebuffers.cpp
diff --git a/src/analysis/processing/qgsalgorithmunion.cpp b/src/analysis/processing/qgsalgorithmunion.cpp
new file mode 100644
index 00000000000..e380fb7ea01
--- /dev/null
+++ b/src/analysis/processing/qgsalgorithmunion.cpp
@@ -0,0 +1,97 @@
+/***************************************************************************
+ qgsalgorithmunion.cpp
+ ---------------------
+ Date : April 2018
+ Copyright : (C) 2018 by Martin Dobias
+ Email : wonder dot sk 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 "qgsalgorithmunion.h"
+
+#include "qgsoverlayutils.h"
+
+///@cond PRIVATE
+
+
+QString QgsUnionAlgorithm::name() const
+{
+ return QStringLiteral( "union" );
+}
+
+QString QgsUnionAlgorithm::displayName() const
+{
+ return QObject::tr( "Union" );
+}
+
+QString QgsUnionAlgorithm::group() const
+{
+ return QObject::tr( "Vector overlay" );
+}
+
+QString QgsUnionAlgorithm::groupId() const
+{
+ return QStringLiteral( "vectoroverlay" );
+}
+
+QString QgsUnionAlgorithm::shortHelpString() const
+{
+ return QObject::tr( "This algorithm creates a layer containing all the features from both input layers. In the case of polygon layers, separate features are created for overlapping and non-overlapping features. The attribute table of the union layer contains attribute values from the respective input layer for non-overlapping features, and attribute values from both input layers for overlapping features." );
+}
+
+QgsProcessingAlgorithm *QgsUnionAlgorithm::createInstance() const
+{
+ return new QgsUnionAlgorithm();
+}
+
+void QgsUnionAlgorithm::initAlgorithm( const QVariantMap & )
+{
+ addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
+ addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "OVERLAY" ), QObject::tr( "Union layer" ) ) );
+
+ addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Union" ) ) );
+}
+
+
+QVariantMap QgsUnionAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
+{
+ std::unique_ptr< QgsFeatureSource > sourceA( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
+ if ( !sourceA )
+ throw QgsProcessingException( QObject::tr( "Could not load source layer for INPUT" ) );
+
+ std::unique_ptr< QgsFeatureSource > sourceB( parameterAsSource( parameters, QStringLiteral( "OVERLAY" ), context ) );
+ if ( !sourceB )
+ throw QgsProcessingException( QObject::tr( "Could not load source layer for OVERLAY" ) );
+
+ QgsWkbTypes::Type geomType = QgsWkbTypes::multiType( sourceA->wkbType() );
+
+ QgsFields fields = QgsProcessingUtils::combineFields( sourceA->fields(), sourceB->fields() );
+
+ QString dest;
+ std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, geomType, sourceA->sourceCrs() ) );
+
+ QVariantMap outputs;
+ outputs.insert( QStringLiteral( "OUTPUT" ), dest );
+
+ QList fieldIndicesA = QgsOverlayUtils::fieldNamesToIndices( QStringList(), sourceA->fields() );
+ QList fieldIndicesB = QgsOverlayUtils::fieldNamesToIndices( QStringList(), sourceB->fields() );
+
+ int count = 0;
+ int total = sourceA->featureCount() * 2 + sourceB->featureCount();
+
+ QgsOverlayUtils::intersection( *sourceA.get(), *sourceB.get(), *sink.get(), context, feedback, count, total, fieldIndicesA, fieldIndicesB );
+
+ QgsOverlayUtils::difference( *sourceA.get(), *sourceB.get(), *sink.get(), context, feedback, count, total, QgsOverlayUtils::OutputAB );
+
+ QgsOverlayUtils::difference( *sourceB.get(), *sourceA.get(), *sink.get(), context, feedback, count, total, QgsOverlayUtils::OutputBA );
+
+ return outputs;
+}
+
+///@endcond
diff --git a/src/analysis/processing/qgsalgorithmunion.h b/src/analysis/processing/qgsalgorithmunion.h
new file mode 100644
index 00000000000..35e4d0fc5b3
--- /dev/null
+++ b/src/analysis/processing/qgsalgorithmunion.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ qgsalgorithmunion.h
+ ---------------------
+ Date : April 2018
+ Copyright : (C) 2018 by Martin Dobias
+ Email : wonder dot sk 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 QGSALGORITHMUNION_H
+#define QGSALGORITHMUNION_H
+
+
+#define SIP_NO_FILE
+
+#include "qgsprocessingalgorithm.h"
+
+///@cond PRIVATE
+
+class QgsUnionAlgorithm : public QgsProcessingAlgorithm
+{
+ public:
+ QgsUnionAlgorithm() = default;
+
+ virtual QString name() const override;
+ virtual QString displayName() const override;
+ virtual QString group() const override;
+ virtual QString groupId() const override;
+ QString shortHelpString() const override;
+
+ protected:
+ virtual QgsProcessingAlgorithm *createInstance() const override;
+ virtual void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
+ virtual QVariantMap processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
+
+};
+
+///@endcond PRIVATE
+
+#endif // QGSALGORITHMUNION_H
diff --git a/src/analysis/processing/qgsnativealgorithms.cpp b/src/analysis/processing/qgsnativealgorithms.cpp
index 4778320a616..d2ff0517b37 100644
--- a/src/analysis/processing/qgsnativealgorithms.cpp
+++ b/src/analysis/processing/qgsnativealgorithms.cpp
@@ -75,6 +75,7 @@
#include "qgsalgorithmtransect.h"
#include "qgsalgorithmtransform.h"
#include "qgsalgorithmtranslate.h"
+#include "qgsalgorithmunion.h"
#include "qgsalgorithmuniquevalueindex.h"
#include "qgsalgorithmwedgebuffers.h"
@@ -180,6 +181,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsTransectAlgorithm() );
addAlgorithm( new QgsTransformAlgorithm() );
addAlgorithm( new QgsTranslateAlgorithm() );
+ addAlgorithm( new QgsUnionAlgorithm() );
addAlgorithm( new QgsWedgeBuffersAlgorithm() );
}