Skip to content

Commit 8d82ce8

Browse files
committed
makeFeatureCompatible on a single input feature
1 parent 7e8592b commit 8d82ce8

File tree

3 files changed

+78
-30
lines changed

3 files changed

+78
-30
lines changed

python/core/auto_generated/qgsvectorlayerutils.sip.in

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,26 @@ are padded with NULL values to match the required length).
177177
.. versionadded:: 3.4
178178
%End
179179

180+
static const QgsFeatureList makeFeatureCompatible( const QgsFeature &feature, const QgsVectorLayer &layer );
181+
%Docstring
182+
Converts input ``feature`` to be compatible with the given ``layer``.
183+
184+
This function returns a new list of transformed features compatible with the input
185+
layer, note that the number of features returned might be greater than one.
186+
187+
The following operations will be performed to convert the input features:
188+
- convert single geometries to multi part
189+
- drop additional attributes
190+
- drop geometry if layer is geometry-less
191+
- add missing attribute fields
192+
- add back M/Z values (initialized to 0)
193+
- drop Z/M
194+
- convert multi part geometries to single part
195+
196+
.. versionadded:: 3.4
197+
%End
180198

181-
static QgsFeatureList makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer );
199+
static const QgsFeatureList makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer );
182200
%Docstring
183201
Converts input ``features`` to be compatible with the given ``layer``.
184202

src/core/qgsvectorlayerutils.cpp

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -561,31 +561,30 @@ void QgsVectorLayerUtils::matchAttributesToFields( QgsFeature &feature, const Qg
561561
}
562562
}
563563

564-
QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer )
564+
const QgsFeatureList QgsVectorLayerUtils::makeFeatureCompatible( const QgsFeature &feature, const QgsVectorLayer &layer )
565565
{
566566
QgsWkbTypes::Type inputWkbType( layer.wkbType( ) );
567567
QgsFeatureList resultFeatures;
568-
for ( const QgsFeature &f : features )
568+
QgsFeature newF( feature );
569+
// Fix attributes
570+
QgsVectorLayerUtils::matchAttributesToFields( newF, layer.fields( ) );
571+
// Does geometry need tranformations?
572+
QgsWkbTypes::GeometryType newFGeomType( QgsWkbTypes::geometryType( newF.geometry().wkbType() ) );
573+
bool newFHasGeom = newFGeomType !=
574+
QgsWkbTypes::GeometryType::UnknownGeometry &&
575+
newFGeomType != QgsWkbTypes::GeometryType::NullGeometry;
576+
bool layerHasGeom = inputWkbType !=
577+
QgsWkbTypes::Type::NoGeometry &&
578+
inputWkbType != QgsWkbTypes::Type::Unknown;
579+
// Drop geometry if layer is geometry-less
580+
if ( newFHasGeom && ! layerHasGeom )
581+
{
582+
QgsFeature _f = QgsFeature( layer.fields() );
583+
_f.setAttributes( newF.attributes() );
584+
resultFeatures.append( _f );
585+
}
586+
else
569587
{
570-
QgsFeature newF( f );
571-
// Fix attributes
572-
QgsVectorLayerUtils::matchAttributesToFields( newF, layer.fields( ) );
573-
// Does geometry need tranformations?
574-
QgsWkbTypes::GeometryType newFGeomType( QgsWkbTypes::geometryType( newF.geometry().wkbType() ) );
575-
bool newFHasGeom = newFGeomType !=
576-
QgsWkbTypes::GeometryType::UnknownGeometry &&
577-
newFGeomType != QgsWkbTypes::GeometryType::NullGeometry;
578-
bool layerHasGeom = inputWkbType !=
579-
QgsWkbTypes::Type::NoGeometry &&
580-
inputWkbType != QgsWkbTypes::Type::Unknown;
581-
// Drop geometry if layer is geometry-less
582-
if ( newFHasGeom && ! layerHasGeom )
583-
{
584-
QgsFeature _f = QgsFeature( layer.fields() );
585-
_f.setAttributes( newF.attributes() );
586-
resultFeatures.append( _f );
587-
continue; // Skip the rest
588-
}
589588
// Geometry need fixing
590589
if ( newFHasGeom && layerHasGeom && newF.geometry().wkbType() != inputWkbType )
591590
{
@@ -627,15 +626,15 @@ QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList
627626
{
628627
QgsGeometry newGeom( newF.geometry( ) );
629628
const QgsGeometryCollection *parts( static_cast< const QgsGeometryCollection * >( newGeom.constGet() ) );
629+
QgsAttributeMap attrMap;
630+
for ( int j = 0; j < newF.fields().count(); j++ )
631+
{
632+
attrMap[j] = newF.attribute( j );
633+
}
630634
for ( int i = 0; i < parts->partCount( ); i++ )
631635
{
632636
QgsGeometry g( parts->geometryN( i )->clone() );
633-
QgsAttributeMap attrMap;
634-
for ( int j = 0; j < newF.fields().count(); j++ )
635-
{
636-
attrMap[j] = newF.attribute( j );
637-
}
638-
QgsFeature _f( QgsVectorLayerUtils::createFeature( &layer, g, attrMap ) );
637+
QgsFeature _f( createFeature( &layer, g, attrMap ) );
639638
resultFeatures.append( _f );
640639
}
641640
}
@@ -649,7 +648,20 @@ QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList
649648
resultFeatures.append( newF );
650649
}
651650
}
652-
return resultFeatures;
651+
return resultFeatures;
652+
}
653+
654+
const QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer )
655+
{
656+
QgsFeatureList resultFeatures;
657+
for ( const QgsFeature &f : features )
658+
{
659+
for ( const auto &_f : makeFeatureCompatible( f, layer ) )
660+
{
661+
resultFeatures.append( _f );
662+
}
663+
}
664+
return resultFeatures;
653665
}
654666

655667
QList<QgsVectorLayer *> QgsVectorLayerUtils::QgsDuplicateFeatureContext::layers() const

src/core/qgsvectorlayerutils.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,24 @@ class CORE_EXPORT QgsVectorLayerUtils
188188
*/
189189
static void matchAttributesToFields( QgsFeature &feature, const QgsFields &fields );
190190

191+
/**
192+
* Converts input \a feature to be compatible with the given \a layer.
193+
*
194+
* This function returns a new list of transformed features compatible with the input
195+
* layer, note that the number of features returned might be greater than one.
196+
*
197+
* The following operations will be performed to convert the input features:
198+
* - convert single geometries to multi part
199+
* - drop additional attributes
200+
* - drop geometry if layer is geometry-less
201+
* - add missing attribute fields
202+
* - add back M/Z values (initialized to 0)
203+
* - drop Z/M
204+
* - convert multi part geometries to single part
205+
*
206+
* \since QGIS 3.4
207+
*/
208+
static const QgsFeatureList makeFeatureCompatible( const QgsFeature &feature, const QgsVectorLayer &layer );
191209

192210
/**
193211
* Converts input \a features to be compatible with the given \a layer.
@@ -207,7 +225,7 @@ class CORE_EXPORT QgsVectorLayerUtils
207225
*
208226
* \since QGIS 3.4
209227
*/
210-
static QgsFeatureList makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer );
228+
static const QgsFeatureList makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer );
211229

212230
};
213231

0 commit comments

Comments
 (0)