Skip to content

Commit

Permalink
makeFeatureCompatible on a single input feature
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso committed Sep 25, 2018
1 parent 7e8592b commit 8d82ce8
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 30 deletions.
20 changes: 19 additions & 1 deletion python/core/auto_generated/qgsvectorlayerutils.sip.in
Expand Up @@ -177,8 +177,26 @@ are padded with NULL values to match the required length).
.. versionadded:: 3.4
%End

static const QgsFeatureList makeFeatureCompatible( const QgsFeature &feature, const QgsVectorLayer &layer );
%Docstring
Converts input ``feature`` to be compatible with the given ``layer``.

This function returns a new list of transformed features compatible with the input
layer, note that the number of features returned might be greater than one.

The following operations will be performed to convert the input features:
- convert single geometries to multi part
- drop additional attributes
- drop geometry if layer is geometry-less
- add missing attribute fields
- add back M/Z values (initialized to 0)
- drop Z/M
- convert multi part geometries to single part

.. versionadded:: 3.4
%End

static QgsFeatureList makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer );
static const QgsFeatureList makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer );
%Docstring
Converts input ``features`` to be compatible with the given ``layer``.

Expand Down
68 changes: 40 additions & 28 deletions src/core/qgsvectorlayerutils.cpp
Expand Up @@ -561,31 +561,30 @@ void QgsVectorLayerUtils::matchAttributesToFields( QgsFeature &feature, const Qg
}
}

QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer )
const QgsFeatureList QgsVectorLayerUtils::makeFeatureCompatible( const QgsFeature &feature, const QgsVectorLayer &layer )
{
QgsWkbTypes::Type inputWkbType( layer.wkbType( ) );
QgsFeatureList resultFeatures;
for ( const QgsFeature &f : features )
QgsFeature newF( feature );
// Fix attributes
QgsVectorLayerUtils::matchAttributesToFields( newF, layer.fields( ) );
// Does geometry need tranformations?
QgsWkbTypes::GeometryType newFGeomType( QgsWkbTypes::geometryType( newF.geometry().wkbType() ) );
bool newFHasGeom = newFGeomType !=
QgsWkbTypes::GeometryType::UnknownGeometry &&
newFGeomType != QgsWkbTypes::GeometryType::NullGeometry;
bool layerHasGeom = inputWkbType !=
QgsWkbTypes::Type::NoGeometry &&
inputWkbType != QgsWkbTypes::Type::Unknown;
// Drop geometry if layer is geometry-less
if ( newFHasGeom && ! layerHasGeom )
{
QgsFeature _f = QgsFeature( layer.fields() );
_f.setAttributes( newF.attributes() );
resultFeatures.append( _f );
}
else
{
QgsFeature newF( f );
// Fix attributes
QgsVectorLayerUtils::matchAttributesToFields( newF, layer.fields( ) );
// Does geometry need tranformations?
QgsWkbTypes::GeometryType newFGeomType( QgsWkbTypes::geometryType( newF.geometry().wkbType() ) );
bool newFHasGeom = newFGeomType !=
QgsWkbTypes::GeometryType::UnknownGeometry &&
newFGeomType != QgsWkbTypes::GeometryType::NullGeometry;
bool layerHasGeom = inputWkbType !=
QgsWkbTypes::Type::NoGeometry &&
inputWkbType != QgsWkbTypes::Type::Unknown;
// Drop geometry if layer is geometry-less
if ( newFHasGeom && ! layerHasGeom )
{
QgsFeature _f = QgsFeature( layer.fields() );
_f.setAttributes( newF.attributes() );
resultFeatures.append( _f );
continue; // Skip the rest
}
// Geometry need fixing
if ( newFHasGeom && layerHasGeom && newF.geometry().wkbType() != inputWkbType )
{
Expand Down Expand Up @@ -627,15 +626,15 @@ QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList
{
QgsGeometry newGeom( newF.geometry( ) );
const QgsGeometryCollection *parts( static_cast< const QgsGeometryCollection * >( newGeom.constGet() ) );
QgsAttributeMap attrMap;
for ( int j = 0; j < newF.fields().count(); j++ )
{
attrMap[j] = newF.attribute( j );
}
for ( int i = 0; i < parts->partCount( ); i++ )
{
QgsGeometry g( parts->geometryN( i )->clone() );
QgsAttributeMap attrMap;
for ( int j = 0; j < newF.fields().count(); j++ )
{
attrMap[j] = newF.attribute( j );
}
QgsFeature _f( QgsVectorLayerUtils::createFeature( &layer, g, attrMap ) );
QgsFeature _f( createFeature( &layer, g, attrMap ) );
resultFeatures.append( _f );
}
}
Expand All @@ -649,7 +648,20 @@ QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList
resultFeatures.append( newF );
}
}
return resultFeatures;
return resultFeatures;
}

const QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer )
{
QgsFeatureList resultFeatures;
for ( const QgsFeature &f : features )
{
for ( const auto &_f : makeFeatureCompatible( f, layer ) )
{
resultFeatures.append( _f );
}
}
return resultFeatures;
}

QList<QgsVectorLayer *> QgsVectorLayerUtils::QgsDuplicateFeatureContext::layers() const
Expand Down
20 changes: 19 additions & 1 deletion src/core/qgsvectorlayerutils.h
Expand Up @@ -188,6 +188,24 @@ class CORE_EXPORT QgsVectorLayerUtils
*/
static void matchAttributesToFields( QgsFeature &feature, const QgsFields &fields );

/**
* Converts input \a feature to be compatible with the given \a layer.
*
* This function returns a new list of transformed features compatible with the input
* layer, note that the number of features returned might be greater than one.
*
* The following operations will be performed to convert the input features:
* - convert single geometries to multi part
* - drop additional attributes
* - drop geometry if layer is geometry-less
* - add missing attribute fields
* - add back M/Z values (initialized to 0)
* - drop Z/M
* - convert multi part geometries to single part
*
* \since QGIS 3.4
*/
static const QgsFeatureList makeFeatureCompatible( const QgsFeature &feature, const QgsVectorLayer &layer );

/**
* Converts input \a features to be compatible with the given \a layer.
Expand All @@ -207,7 +225,7 @@ class CORE_EXPORT QgsVectorLayerUtils
*
* \since QGIS 3.4
*/
static QgsFeatureList makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer );
static const QgsFeatureList makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer &layer );

};

Expand Down

0 comments on commit 8d82ce8

Please sign in to comment.