mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-26 00:02:08 -05:00
Port processing combineFields to c++
This commit is contained in:
parent
cf636dcafa
commit
c41dca937c
@ -193,6 +193,15 @@ class QgsProcessingUtils
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
static QgsFields combineFields( const QgsFields &fieldsA, const QgsFields &fieldsB );
|
||||
%Docstring
|
||||
Combines two field lists, avoiding duplicate field names (in a case-insensitive manner).
|
||||
|
||||
Duplicate field names will be altered to "name_2", "name_3", etc, finding the first
|
||||
non-duplicate name.
|
||||
:rtype: QgsFields
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
class QgsProcessingFeatureSource : QgsFeatureSource
|
||||
|
@ -37,7 +37,8 @@ from qgis.core import (QgsFeature,
|
||||
QgsProcessingParameterField,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingException,
|
||||
QgsExpression)
|
||||
QgsExpression,
|
||||
QgsProcessingUtils)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.tools import vector
|
||||
|
||||
@ -89,7 +90,7 @@ class HubLines(QgisAlgorithm):
|
||||
field_spoke = self.parameterAsString(parameters, self.SPOKE_FIELD, context)
|
||||
field_spoke_index = hub_source.fields().lookupField(field_spoke)
|
||||
|
||||
fields = vector.combineFields(hub_source.fields(), spoke_source.fields())
|
||||
fields = QgsProcessingUtils.combineFields(hub_source.fields(), spoke_source.fields())
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.LineString, hub_source.sourceCrs())
|
||||
|
@ -82,7 +82,7 @@ class JoinAttributes(QgisAlgorithm):
|
||||
joinField1Index = input.fields().lookupField(field)
|
||||
joinField2Index = input2.fields().lookupField(field2)
|
||||
|
||||
outFields = vector.combineFields(input.fields(), input2.fields())
|
||||
outFields = QgsProcessingUtils.combineFields(input.fields(), input2.fields())
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
outFields, input.wkbType(), input.sourceCrs())
|
||||
|
@ -37,6 +37,7 @@ from qgis.core import (QgsFields,
|
||||
QgsFeatureRequest,
|
||||
QgsGeometry,
|
||||
QgsProcessing,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterBoolean,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterEnum,
|
||||
@ -148,7 +149,7 @@ class SpatialJoin(QgisAlgorithm):
|
||||
if idx >= 0:
|
||||
fields_to_join.append(join_source.fields().at(idx))
|
||||
|
||||
out_fields = vector.combineFields(source_fields, fields_to_join)
|
||||
out_fields = QgsProcessingUtils.combineFields(source_fields, fields_to_join)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
out_fields, source.wkbType(), source.sourceCrs())
|
||||
|
@ -43,6 +43,7 @@ from qgis.core import (NULL,
|
||||
QgsDateTimeStatisticalSummary,
|
||||
QgsStringStatisticalSummary,
|
||||
QgsProcessing,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterBoolean,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterEnum,
|
||||
@ -247,7 +248,7 @@ class SpatialJoinSummary(QgisAlgorithm):
|
||||
else:
|
||||
addFieldKeepType(join_field, f[0])
|
||||
|
||||
out_fields = vector.combineFields(source_fields, fields_to_join)
|
||||
out_fields = QgsProcessingUtils.combineFields(source_fields, fields_to_join)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
out_fields, source.wkbType(), source.sourceCrs())
|
||||
|
@ -36,6 +36,7 @@ from qgis.core import (QgsFeature,
|
||||
NULL,
|
||||
QgsWkbTypes,
|
||||
QgsMessageLog,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsSpatialIndex)
|
||||
@ -79,7 +80,7 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
|
||||
|
||||
geomType = QgsWkbTypes.multiType(sourceA.wkbType())
|
||||
fields = vector.combineFields(sourceA.fields(), sourceB.fields())
|
||||
fields = QgsProcessingUtils.combineFields(sourceA.fields(), sourceB.fields())
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, geomType, sourceA.sourceCrs())
|
||||
|
@ -34,7 +34,7 @@ from qgis.core import (QgsFeatureRequest,
|
||||
QgsFeatureSink,
|
||||
QgsGeometry,
|
||||
QgsWkbTypes,
|
||||
QgsMessageLog,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsSpatialIndex)
|
||||
@ -79,7 +79,7 @@ class Union(QgisAlgorithm):
|
||||
sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
|
||||
|
||||
geomType = QgsWkbTypes.multiType(sourceA.wkbType())
|
||||
fields = vector.combineFields(sourceA.fields(), sourceB.fields())
|
||||
fields = QgsProcessingUtils.combineFields(sourceA.fields(), sourceB.fields())
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, geomType, sourceA.sourceCrs())
|
||||
|
@ -174,29 +174,6 @@ def extractPoints(geom):
|
||||
return points
|
||||
|
||||
|
||||
def combineFields(fieldsA, fieldsB):
|
||||
"""Create single field map from two input field maps.
|
||||
"""
|
||||
fields = []
|
||||
fields.extend(fieldsA)
|
||||
namesA = [str(f.name()).lower() for f in fieldsA]
|
||||
for field in fieldsB:
|
||||
name = str(field.name()).lower()
|
||||
if name in namesA:
|
||||
idx = 2
|
||||
newName = name + '_' + str(idx)
|
||||
while newName in namesA:
|
||||
idx += 1
|
||||
newName = name + '_' + str(idx)
|
||||
field = QgsField(newName, field.type(), field.typeName())
|
||||
fields.append(field)
|
||||
|
||||
real_fields = QgsFields()
|
||||
for f in fields:
|
||||
real_fields.append(f)
|
||||
return real_fields
|
||||
|
||||
|
||||
def checkMinDistance(point, index, distance, points):
|
||||
"""Check if distance from given point to all other points is greater
|
||||
than given value.
|
||||
|
@ -555,6 +555,41 @@ QString QgsProcessingUtils::convertToCompatibleFormat( const QgsVectorLayer *vl,
|
||||
}
|
||||
}
|
||||
|
||||
QgsFields QgsProcessingUtils::combineFields( const QgsFields &fieldsA, const QgsFields &fieldsB )
|
||||
{
|
||||
QgsFields outFields = fieldsA;
|
||||
QSet< QString > usedNames;
|
||||
for ( const QgsField &f : fieldsA )
|
||||
{
|
||||
usedNames.insert( f.name().toLower() );
|
||||
}
|
||||
|
||||
for ( const QgsField &f : fieldsB )
|
||||
{
|
||||
if ( usedNames.contains( f.name().toLower() ) )
|
||||
{
|
||||
int idx = 2;
|
||||
QString newName = f.name() + '_' + QString::number( idx );
|
||||
while ( usedNames.contains( newName.toLower() ) )
|
||||
{
|
||||
idx++;
|
||||
newName = f.name() + '_' + QString::number( idx );
|
||||
}
|
||||
QgsField newField = f;
|
||||
newField.setName( newName );
|
||||
outFields.append( newField );
|
||||
usedNames.insert( newName.toLower() );
|
||||
}
|
||||
else
|
||||
{
|
||||
usedNames.insert( f.name().toLower() );
|
||||
outFields.append( f );
|
||||
}
|
||||
}
|
||||
|
||||
return outFields;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// QgsProcessingFeatureSource
|
||||
|
@ -224,6 +224,14 @@ class CORE_EXPORT QgsProcessingUtils
|
||||
QgsProcessingContext &context,
|
||||
QgsProcessingFeedback *feedback );
|
||||
|
||||
/**
|
||||
* Combines two field lists, avoiding duplicate field names (in a case-insensitive manner).
|
||||
*
|
||||
* Duplicate field names will be altered to "name_2", "name_3", etc, finding the first
|
||||
* non-duplicate name.
|
||||
*/
|
||||
static QgsFields combineFields( const QgsFields &fieldsA, const QgsFields &fieldsB );
|
||||
|
||||
private:
|
||||
|
||||
static bool canUseLayer( const QgsRasterLayer *layer );
|
||||
|
@ -352,6 +352,7 @@ class TestQgsProcessing: public QObject
|
||||
void tempUtils();
|
||||
void convertCompatible();
|
||||
void create();
|
||||
void combineFields();
|
||||
|
||||
private:
|
||||
|
||||
@ -5443,5 +5444,40 @@ void TestQgsProcessing::create()
|
||||
QCOMPARE( newInstance->provider(), &p );
|
||||
}
|
||||
|
||||
void TestQgsProcessing::combineFields()
|
||||
{
|
||||
QgsFields a;
|
||||
QgsFields b;
|
||||
// combine empty fields
|
||||
QgsFields res = QgsProcessingUtils::combineFields( a, b );
|
||||
QVERIFY( res.isEmpty() );
|
||||
|
||||
// fields in a
|
||||
a.append( QgsField( "name" ) );
|
||||
res = QgsProcessingUtils::combineFields( a, b );
|
||||
QCOMPARE( res.count(), 1 );
|
||||
QCOMPARE( res.at( 0 ).name(), QStringLiteral( "name" ) );
|
||||
b.append( QgsField( "name" ) );
|
||||
res = QgsProcessingUtils::combineFields( a, b );
|
||||
QCOMPARE( res.count(), 2 );
|
||||
QCOMPARE( res.at( 0 ).name(), QStringLiteral( "name" ) );
|
||||
QCOMPARE( res.at( 1 ).name(), QStringLiteral( "name_2" ) );
|
||||
|
||||
a.append( QgsField( "NEW" ) );
|
||||
res = QgsProcessingUtils::combineFields( a, b );
|
||||
QCOMPARE( res.count(), 3 );
|
||||
QCOMPARE( res.at( 0 ).name(), QStringLiteral( "name" ) );
|
||||
QCOMPARE( res.at( 1 ).name(), QStringLiteral( "NEW" ) );
|
||||
QCOMPARE( res.at( 2 ).name(), QStringLiteral( "name_2" ) );
|
||||
|
||||
b.append( QgsField( "new" ) );
|
||||
res = QgsProcessingUtils::combineFields( a, b );
|
||||
QCOMPARE( res.count(), 4 );
|
||||
QCOMPARE( res.at( 0 ).name(), QStringLiteral( "name" ) );
|
||||
QCOMPARE( res.at( 1 ).name(), QStringLiteral( "NEW" ) );
|
||||
QCOMPARE( res.at( 2 ).name(), QStringLiteral( "name_2" ) );
|
||||
QCOMPARE( res.at( 3 ).name(), QStringLiteral( "new_2" ) );
|
||||
}
|
||||
|
||||
QGSTEST_MAIN( TestQgsProcessing )
|
||||
#include "testqgsprocessing.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user