Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[FEATURE][API] Add new QgsFeatureSink subclass QgsRemappingProxyFeatu…
…reSink This sink allows for transformation of incoming features to match the requirements of storing in an existing destination layer, e.g. by reprojecting the features to the destination's CRS, by coercing geometries to the format required by the destination sink, and by mapping field values from the source to the destination.
- Loading branch information
1 parent
78c86ef
commit 93f714d
Showing
7 changed files
with
559 additions
and
2 deletions.
There are no files selected for viewing
170 changes: 170 additions & 0 deletions
170
python/core/auto_generated/qgsremappingproxyfeaturesink.sip.in
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
/************************************************************************ | ||
* This file has been generated automatically from * | ||
* * | ||
* src/core/qgsremappingproxyfeaturesink.h * | ||
* * | ||
* Do not edit manually ! Edit header and run scripts/sipify.pl again * | ||
************************************************************************/ | ||
|
||
|
||
|
||
|
||
class QgsRemappingSinkDefinition | ||
{ | ||
%Docstring | ||
Defines the parameters used to remap features when creating a QgsRemappingProxyFeatureSink. | ||
|
||
The definition includes parameters required to correctly map incoming features to the structure | ||
of the destination sink, e.g. information about how to create output field values and how to transform | ||
geometries to match the destination CRS. | ||
|
||
.. versionadded:: 3.14 | ||
%End | ||
|
||
%TypeHeaderCode | ||
#include "qgsremappingproxyfeaturesink.h" | ||
%End | ||
public: | ||
|
||
QMap< QString, QgsProperty > fieldMap() const; | ||
%Docstring | ||
Returns the field mapping, which defines how to map the values from incoming features to destination | ||
field values. | ||
|
||
Field values are mapped using a QgsProperty source object, which allows either direct field value to field value | ||
mapping or use of QgsExpression expressions to transform values to the destination field. | ||
|
||
.. seealso:: :py:func:`setFieldMap` | ||
|
||
.. seealso:: :py:func:`addMappedField` | ||
%End | ||
|
||
void setFieldMap( const QMap< QString, QgsProperty > &map ); | ||
%Docstring | ||
Sets the field mapping, which defines how to map the values from incoming features to destination | ||
field values. | ||
|
||
Field values are mapped using a QgsProperty source object, which allows either direct field value to field value | ||
mapping or use of QgsExpression expressions to transform values to the destination field. | ||
|
||
.. seealso:: :py:func:`fieldMap` | ||
|
||
.. seealso:: :py:func:`addMappedField` | ||
%End | ||
|
||
void addMappedField( const QString &destinationField, const QgsProperty &property ); | ||
%Docstring | ||
Adds a mapping for a destination field. | ||
|
||
Field values are mapped using a QgsProperty source object, which allows either direct field value to field value | ||
mapping or use of QgsExpression expressions to transform values to the destination field. | ||
|
||
.. seealso:: :py:func:`setFieldMap` | ||
|
||
.. seealso:: :py:func:`fieldMap` | ||
%End | ||
|
||
QgsCoordinateTransform transform() const; | ||
%Docstring | ||
Returns the transform used for reprojecting incoming features to the sink's destination CRS. | ||
|
||
.. seealso:: :py:func:`setTransform` | ||
%End | ||
|
||
void setTransform( const QgsCoordinateTransform &transform ); | ||
%Docstring | ||
Sets the ``transform`` used for reprojecting incoming features to the sink's destination CRS. | ||
|
||
.. seealso:: :py:func:`transform` | ||
%End | ||
|
||
QgsWkbTypes::Type destinationWkbType() const; | ||
%Docstring | ||
Returns the WKB geometry type for the destination. | ||
|
||
.. seealso:: :py:func:`setDestinationWkbType` | ||
%End | ||
|
||
void setDestinationWkbType( QgsWkbTypes::Type type ); | ||
%Docstring | ||
Sets the WKB geometry ``type`` for the destination. | ||
|
||
.. seealso:: :py:func:`setDestinationWkbType` | ||
%End | ||
|
||
QgsFields destinationFields() const; | ||
%Docstring | ||
Returns the fields for the destination sink. | ||
|
||
.. seealso:: :py:func:`setDestinationFields` | ||
%End | ||
|
||
void setDestinationFields( const QgsFields &fields ); | ||
%Docstring | ||
Sets the ``fields`` for the destination sink. | ||
|
||
.. seealso:: :py:func:`destinationFields` | ||
%End | ||
|
||
}; | ||
|
||
|
||
class QgsRemappingProxyFeatureSink : QgsFeatureSink | ||
{ | ||
%Docstring | ||
A QgsFeatureSink which proxies incoming features to a destination feature sink, after applying | ||
transformations and field value mappings. | ||
|
||
This sink allows for transformation of incoming features to match the requirements of storing | ||
in an existing destination layer, e.g. by reprojecting the features to the destination's CRS | ||
and by coercing geometries to the format required by the destination sink. | ||
|
||
.. versionadded:: 3.14 | ||
%End | ||
|
||
%TypeHeaderCode | ||
#include "qgsremappingproxyfeaturesink.h" | ||
%End | ||
public: | ||
|
||
QgsRemappingProxyFeatureSink( const QgsRemappingSinkDefinition &mappingDefinition, QgsFeatureSink *sink ); | ||
%Docstring | ||
Constructor for QgsRemappingProxyFeatureSink, using the specified ``mappingDefinition`` | ||
to manipulate features before sending them to the destination ``sink``. | ||
%End | ||
|
||
void setExpressionContext( const QgsExpressionContext &context ); | ||
%Docstring | ||
Sets the expression ``context`` to use when evaluating mapped field values. | ||
%End | ||
|
||
QgsFeatureList remapFeature( const QgsFeature &feature ) const; | ||
%Docstring | ||
Remaps a ``feature`` to a set of features compatible with the destination sink. | ||
%End | ||
|
||
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 ); | ||
|
||
virtual bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 ); | ||
|
||
virtual bool addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags = 0 ); | ||
|
||
|
||
QgsFeatureSink *destinationSink(); | ||
%Docstring | ||
Returns the destination QgsFeatureSink which the proxy will forward features to. | ||
%End | ||
|
||
}; | ||
|
||
|
||
|
||
|
||
|
||
/************************************************************************ | ||
* This file has been generated automatically from * | ||
* * | ||
* src/core/qgsremappingproxyfeaturesink.h * | ||
* * | ||
* Do not edit manually ! Edit header and run scripts/sipify.pl again * | ||
************************************************************************/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
/*************************************************************************** | ||
qgsremappingproxyfeaturesink.cpp | ||
---------------------- | ||
begin : April 2020 | ||
copyright : (C) 2020 by Nyall Dawson | ||
email : nyall dot dawson 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 "qgsremappingproxyfeaturesink.h" | ||
#include "qgslogger.h" | ||
|
||
QgsRemappingProxyFeatureSink::QgsRemappingProxyFeatureSink( const QgsRemappingSinkDefinition &mappingDefinition, QgsFeatureSink *sink ) | ||
: QgsFeatureSink() | ||
, mDefinition( mappingDefinition ) | ||
, mSink( sink ) | ||
{} | ||
|
||
void QgsRemappingProxyFeatureSink::setExpressionContext( const QgsExpressionContext &context ) | ||
{ | ||
mContext = context; | ||
} | ||
|
||
QgsFeatureList QgsRemappingProxyFeatureSink::remapFeature( const QgsFeature &feature ) const | ||
{ | ||
QgsFeatureList res; | ||
|
||
mContext.setFeature( feature ); | ||
|
||
// remap fields first | ||
QgsFeature f; | ||
f.setFields( mDefinition.destinationFields(), true ); | ||
QgsAttributes attributes; | ||
const QMap< QString, QgsProperty > fieldMap = mDefinition.fieldMap(); | ||
for ( const QgsField &field : mDefinition.destinationFields() ) | ||
{ | ||
if ( fieldMap.contains( field.name() ) ) | ||
{ | ||
attributes.append( fieldMap.value( field.name() ).value( mContext ) ); | ||
} | ||
else | ||
{ | ||
attributes.append( QVariant() ); | ||
} | ||
} | ||
f.setAttributes( attributes ); | ||
|
||
// make geometries compatible, and reproject if necessary | ||
if ( feature.hasGeometry() ) | ||
{ | ||
const QVector< QgsGeometry > geometries = feature.geometry().coerceToType( mDefinition.destinationWkbType() ); | ||
if ( !geometries.isEmpty() ) | ||
{ | ||
res.reserve( geometries.size() ); | ||
for ( const QgsGeometry &geometry : geometries ) | ||
{ | ||
QgsFeature featurePart = f; | ||
|
||
QgsGeometry reproject = geometry; | ||
try | ||
{ | ||
reproject.transform( mDefinition.transform() ); | ||
featurePart.setGeometry( reproject ); | ||
} | ||
catch ( QgsCsException & ) | ||
{ | ||
QgsLogger::warning( QObject::tr( "Error reprojecting feature geometry" ) ); | ||
featurePart.clearGeometry(); | ||
} | ||
res << featurePart; | ||
} | ||
} | ||
else | ||
{ | ||
f.clearGeometry(); | ||
res << f; | ||
} | ||
} | ||
else | ||
{ | ||
res << f; | ||
} | ||
return res; | ||
} | ||
|
||
bool QgsRemappingProxyFeatureSink::addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags ) | ||
{ | ||
QgsFeatureList features = remapFeature( feature ); | ||
return mSink->addFeatures( features, flags ); | ||
} | ||
|
||
bool QgsRemappingProxyFeatureSink::addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags ) | ||
{ | ||
bool res = true; | ||
for ( QgsFeature &f : features ) | ||
{ | ||
res = addFeature( f, flags ) && res; | ||
} | ||
return res; | ||
} | ||
|
||
bool QgsRemappingProxyFeatureSink::addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags ) | ||
{ | ||
QgsFeature f; | ||
bool res = true; | ||
while ( iterator.nextFeature( f ) ) | ||
{ | ||
res = addFeature( f, flags ) && res; | ||
} | ||
return res; | ||
} |
Oops, something went wrong.