QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
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
20#include "qgslogger.h"
21
22#include <QString>
23
24using namespace Qt::StringLiterals;
25
28 , mDefinition( mappingDefinition )
29 , mSink( sink )
30 , mOwnsSink( ownsSink )
31{}
32
34{
35 if ( mOwnsSink )
36 delete mSink;
37}
38
40{
41 mContext = context;
42}
43
45{
46 mTransform = QgsCoordinateTransform( mDefinition.sourceCrs(), mDefinition.destinationCrs(), context );
47}
48
50{
52
53 mContext.setFeature( feature );
54
55 // remap fields first
56 QgsFeature f;
57 f.setFields( mDefinition.destinationFields(), true );
58 QgsAttributes attributes;
59 const QMap< QString, QgsProperty > fieldMap = mDefinition.fieldMap();
60 for ( const QgsField &field : mDefinition.destinationFields() )
61 {
62 if ( fieldMap.contains( field.name() ) )
63 {
64 attributes.append( fieldMap.value( field.name() ).value( mContext ) );
65 }
66 else
67 {
68 attributes.append( QVariant() );
69 }
70 }
71 f.setAttributes( attributes );
72
73 // make geometries compatible, and reproject if necessary
74 if ( feature.hasGeometry() )
75 {
76 const QVector< QgsGeometry > geometries = feature.geometry().coerceToType( mDefinition.destinationWkbType() );
77 if ( !geometries.isEmpty() )
78 {
79 res.reserve( geometries.size() );
80 for ( const QgsGeometry &geometry : geometries )
81 {
82 QgsFeature featurePart = f;
83
84 QgsGeometry reproject = geometry;
85 try
86 {
87 reproject.transform( mTransform );
88 featurePart.setGeometry( reproject );
89 }
90 catch ( QgsCsException & )
91 {
92 QgsLogger::warning( QObject::tr( "Error reprojecting feature geometry" ) );
93 featurePart.clearGeometry();
94 }
95 res << featurePart;
96 }
97 }
98 else
99 {
100 f.clearGeometry();
101 res << f;
102 }
103 }
104 else
105 {
106 res << f;
107 }
108 return res;
109}
110
112{
113 QgsFeatureList features = remapFeature( feature );
114 return mSink->addFeatures( features, flags );
115}
116
118{
119 bool res = true;
120 for ( QgsFeature &f : features )
121 {
122 res = addFeature( f, flags ) && res;
123 }
124 return res;
125}
126
128{
129 QgsFeature f;
130 bool res = true;
131 while ( iterator.nextFeature( f ) )
132 {
133 res = addFeature( f, flags ) && res;
134 }
135 return res;
136}
137
139{
140 return mSink->lastError();
141}
142
144{
145 QVariantMap map;
146 map.insert( u"wkb_type"_s, static_cast< quint32>( mDestinationWkbType ) );
147 // we only really care about names here
148 QVariantList fieldNames;
149 for ( const QgsField &field : mDestinationFields )
150 fieldNames << field.name();
151 map.insert( u"destination_field_names"_s, fieldNames );
152 map.insert( u"transform_source"_s, mSourceCrs.toWkt( Qgis::CrsWktVariant::Preferred ) );
153 map.insert( u"transform_dest"_s, mDestinationCrs.toWkt( Qgis::CrsWktVariant::Preferred ) );
154
155 QVariantMap fieldMap;
156 for ( auto it = mFieldMap.constBegin(); it != mFieldMap.constEnd(); ++it )
157 {
158 fieldMap.insert( it.key(), it.value().toVariant() );
159 }
160 map.insert( u"field_map"_s, fieldMap );
161
162 return map;
163}
164
165bool QgsRemappingSinkDefinition::loadVariant( const QVariantMap &map )
166{
167 mDestinationWkbType = static_cast< Qgis::WkbType >( map.value( u"wkb_type"_s, static_cast< quint32>( Qgis::WkbType::Unknown ) ).toInt() );
168
169 const QVariantList fieldNames = map.value( u"destination_field_names"_s ).toList();
170 QgsFields fields;
171 for ( const QVariant &field : fieldNames )
172 {
173 fields.append( QgsField( field.toString() ) );
174 }
175 mDestinationFields = fields;
176
177 mSourceCrs = QgsCoordinateReferenceSystem::fromWkt( map.value( u"transform_source"_s ).toString() );
178 mDestinationCrs = QgsCoordinateReferenceSystem::fromWkt( map.value( u"transform_dest"_s ).toString() );
179
180 const QVariantMap fieldMap = map.value( u"field_map"_s ).toMap();
181 mFieldMap.clear();
182 for ( auto it = fieldMap.constBegin(); it != fieldMap.constEnd(); ++it )
183 {
184 QgsProperty p;
185 p.loadVariant( it.value() );
186 mFieldMap.insert( it.key(), p );
187 }
188
189 return true;
190}
191
193{
194 return mDestinationWkbType == other.mDestinationWkbType
195 && mDestinationFields == other.mDestinationFields
196 && mFieldMap == other.mFieldMap
197 && mSourceCrs == other.mSourceCrs
198 && mDestinationCrs == other.mDestinationCrs;
199}
200
202{
203 return !( *this == other );
204}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:280
@ Unknown
Unknown.
Definition qgis.h:281
@ Preferred
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition qgis.h:2497
A vector of attributes.
static QgsCoordinateReferenceSystem fromWkt(const QString &wkt)
Creates a CRS from a WKT spatial ref sys definition string.
Contains information about the context in which a coordinate transform is executed.
Handles coordinate transforms between two coordinate systems.
Custom exception class for Coordinate Reference System related exceptions.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
An interface for objects which accept features via addFeature(s) methods.
QFlags< Flag > Flags
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
QgsGeometry geometry
Definition qgsfeature.h:71
void clearGeometry()
Removes any geometry associated with the feature.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:56
Container of fields for a vector layer.
Definition qgsfields.h:46
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Definition qgsfields.cpp:76
A geometry is the spatial representation of a feature.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
QVector< QgsGeometry > coerceToType(Qgis::WkbType type, double defaultZ=0, double defaultM=0, bool avoidDuplicates=true) const
Attempts to coerce this geometry into the specified destination type.
static void warning(const QString &msg)
Goes to qWarning.
A store for object properties.
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
QVariant toVariant() const
Saves this remapping definition to a QVariantMap, wrapped in a QVariant.
bool loadVariant(const QVariantMap &map)
Loads this remapping definition from a QVariantMap, wrapped in a QVariant.
QList< QgsFeature > QgsFeatureList