QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
qgsremappingproxyfeaturesink.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsremappingproxyfeaturesink.cpp
3 ----------------------
4 begin : April 2020
5 copyright : (C) 2020 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "qgslogger.h"
20
23 , mDefinition( mappingDefinition )
24 , mSink( sink )
25 , mOwnsSink( ownsSink )
26{}
27
29{
30 if ( mOwnsSink )
31 delete mSink;
32}
33
35{
36 mContext = context;
37}
38
40{
41 mTransform = QgsCoordinateTransform( mDefinition.sourceCrs(), mDefinition.destinationCrs(), context );
42}
43
45{
47
48 mContext.setFeature( feature );
49
50 // remap fields first
51 QgsFeature f;
52 f.setFields( mDefinition.destinationFields(), true );
53 QgsAttributes attributes;
54 const QMap< QString, QgsProperty > fieldMap = mDefinition.fieldMap();
55 for ( const QgsField &field : mDefinition.destinationFields() )
56 {
57 if ( fieldMap.contains( field.name() ) )
58 {
59 attributes.append( fieldMap.value( field.name() ).value( mContext ) );
60 }
61 else
62 {
63 attributes.append( QVariant() );
64 }
65 }
66 f.setAttributes( attributes );
67
68 // make geometries compatible, and reproject if necessary
69 if ( feature.hasGeometry() )
70 {
71 const QVector< QgsGeometry > geometries = feature.geometry().coerceToType( mDefinition.destinationWkbType() );
72 if ( !geometries.isEmpty() )
73 {
74 res.reserve( geometries.size() );
75 for ( const QgsGeometry &geometry : geometries )
76 {
77 QgsFeature featurePart = f;
78
79 QgsGeometry reproject = geometry;
80 try
81 {
82 reproject.transform( mTransform );
83 featurePart.setGeometry( reproject );
84 }
85 catch ( QgsCsException & )
86 {
87 QgsLogger::warning( QObject::tr( "Error reprojecting feature geometry" ) );
88 featurePart.clearGeometry();
89 }
90 res << featurePart;
91 }
92 }
93 else
94 {
95 f.clearGeometry();
96 res << f;
97 }
98 }
99 else
100 {
101 res << f;
102 }
103 return res;
104}
105
106bool QgsRemappingProxyFeatureSink::addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags )
107{
108 QgsFeatureList features = remapFeature( feature );
109 return mSink->addFeatures( features, flags );
110}
111
112bool QgsRemappingProxyFeatureSink::addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags )
113{
114 bool res = true;
115 for ( QgsFeature &f : features )
116 {
117 res = addFeature( f, flags ) && res;
118 }
119 return res;
120}
121
122bool QgsRemappingProxyFeatureSink::addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags )
123{
124 QgsFeature f;
125 bool res = true;
126 while ( iterator.nextFeature( f ) )
127 {
128 res = addFeature( f, flags ) && res;
129 }
130 return res;
131}
132
134{
135 return mSink->lastError();
136}
137
139{
140 QVariantMap map;
141 map.insert( QStringLiteral( "wkb_type" ), static_cast< quint32>( mDestinationWkbType ) );
142 // we only really care about names here
143 QVariantList fieldNames;
144 for ( const QgsField &field : mDestinationFields )
145 fieldNames << field.name();
146 map.insert( QStringLiteral( "destination_field_names" ), fieldNames );
147 map.insert( QStringLiteral( "transform_source" ), mSourceCrs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ) );
148 map.insert( QStringLiteral( "transform_dest" ), mDestinationCrs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ) );
149
150 QVariantMap fieldMap;
151 for ( auto it = mFieldMap.constBegin(); it != mFieldMap.constEnd(); ++it )
152 {
153 fieldMap.insert( it.key(), it.value().toVariant() );
154 }
155 map.insert( QStringLiteral( "field_map" ), fieldMap );
156
157 return map;
158}
159
160bool QgsRemappingSinkDefinition::loadVariant( const QVariantMap &map )
161{
162 mDestinationWkbType = static_cast< Qgis::WkbType >( map.value( QStringLiteral( "wkb_type" ), static_cast< quint32>( Qgis::WkbType::Unknown ) ).toInt() );
163
164 const QVariantList fieldNames = map.value( QStringLiteral( "destination_field_names" ) ).toList();
165 QgsFields fields;
166 for ( const QVariant &field : fieldNames )
167 {
168 fields.append( QgsField( field.toString() ) );
169 }
170 mDestinationFields = fields;
171
172 mSourceCrs = QgsCoordinateReferenceSystem::fromWkt( map.value( QStringLiteral( "transform_source" ) ).toString() );
173 mDestinationCrs = QgsCoordinateReferenceSystem::fromWkt( map.value( QStringLiteral( "transform_dest" ) ).toString() );
174
175 const QVariantMap fieldMap = map.value( QStringLiteral( "field_map" ) ).toMap();
176 mFieldMap.clear();
177 for ( auto it = fieldMap.constBegin(); it != fieldMap.constEnd(); ++it )
178 {
179 QgsProperty p;
180 p.loadVariant( it.value() );
181 mFieldMap.insert( it.key(), p );
182 }
183
184 return true;
185}
186
188{
189 return mDestinationWkbType == other.mDestinationWkbType
190 && mDestinationFields == other.mDestinationFields
191 && mFieldMap == other.mFieldMap
192 && mSourceCrs == other.mSourceCrs
193 && mDestinationCrs == other.mDestinationCrs;
194}
195
197{
198 return !( *this == other );
199}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:155
@ Unknown
Unknown.
A vector of attributes.
Definition: qgsattributes.h:59
@ WKT_PREFERRED
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
static QgsCoordinateReferenceSystem fromWkt(const QString &wkt)
Creates a CRS from a WKT spatial ref sys definition string.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
An interface for objects which accept features via addFeature(s) methods.
virtual QString lastError() const
Returns the most recent error encountered by the sink, e.g.
virtual bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags())=0
Adds a list of features to the sink.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:160
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:198
QgsGeometry geometry
Definition: qgsfeature.h:67
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:184
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:233
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:170
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:52
QString name
Definition: qgsfield.h:61
Container of fields for a vector layer.
Definition: qgsfields.h:45
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition: qgsfields.cpp:59
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:164
QVector< QgsGeometry > coerceToType(Qgis::WkbType type, double defaultZ=0, double defaultM=0) const
Attempts to coerce this geometry into the specified destination type.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:122
A store for object properties.
Definition: qgsproperty.h:230
bool loadVariant(const QVariant &property)
Loads this property from a QVariantMap, wrapped in a QVariant.
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the transform context to use when reprojecting features.
void setExpressionContext(const QgsExpressionContext &context) const
Sets the expression context to use when evaluating mapped field values.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
QgsRemappingProxyFeatureSink(const QgsRemappingSinkDefinition &mappingDefinition, QgsFeatureSink *sink, bool ownsSink=false)
Constructor for QgsRemappingProxyFeatureSink, using the specified mappingDefinition to manipulate fea...
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
QgsFeatureList remapFeature(const QgsFeature &feature) const
Remaps a feature to a set of features compatible with the destination sink.
Defines the parameters used to remap features when creating a QgsRemappingProxyFeatureSink.
bool operator==(const QgsRemappingSinkDefinition &other) const
QMap< QString, QgsProperty > fieldMap() const
Returns the field mapping, which defines how to map the values from incoming features to destination ...
bool operator!=(const QgsRemappingSinkDefinition &other) const
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source CRS used for reprojecting incoming features to the sink's destination CRS.
QVariant toVariant() const
Saves this remapping definition to a QVariantMap, wrapped in a QVariant.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination CRS used for reprojecting incoming features to the sink's destination CRS.
bool loadVariant(const QVariantMap &map)
Loads this remapping definition from a QVariantMap, wrapped in a QVariant.
QgsFields destinationFields() const
Returns the fields for the destination sink.
Qgis::WkbType destinationWkbType() const
Returns the WKB geometry type for the destination.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:920
const QgsField & field
Definition: qgsfield.h:501