QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 
22  : QgsFeatureSink()
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 {
46  QgsFeatureList res;
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 
106 bool QgsRemappingProxyFeatureSink::addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags )
107 {
108  QgsFeatureList features = remapFeature( feature );
109  return mSink->addFeatures( features, flags );
110 }
111 
112 bool 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 
122 bool 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  QVariantMap map;
136  map.insert( QStringLiteral( "wkb_type" ), mDestinationWkbType );
137  // we only really care about names here
138  QVariantList fieldNames;
139  for ( const QgsField &field : mDestinationFields )
140  fieldNames << field.name();
141  map.insert( QStringLiteral( "destination_field_names" ), fieldNames );
142  map.insert( QStringLiteral( "transform_source" ), mSourceCrs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ) );
143  map.insert( QStringLiteral( "transform_dest" ), mDestinationCrs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ) );
144 
145  QVariantMap fieldMap;
146  for ( auto it = mFieldMap.constBegin(); it != mFieldMap.constEnd(); ++it )
147  {
148  fieldMap.insert( it.key(), it.value().toVariant() );
149  }
150  map.insert( QStringLiteral( "field_map" ), fieldMap );
151 
152  return map;
153 }
154 
155 bool QgsRemappingSinkDefinition::loadVariant( const QVariantMap &map )
156 {
157  mDestinationWkbType = static_cast< QgsWkbTypes::Type >( map.value( QStringLiteral( "wkb_type" ), QgsWkbTypes::Unknown ).toInt() );
158 
159  const QVariantList fieldNames = map.value( QStringLiteral( "destination_field_names" ) ).toList();
160  QgsFields fields;
161  for ( const QVariant &field : fieldNames )
162  {
163  fields.append( QgsField( field.toString() ) );
164  }
165  mDestinationFields = fields;
166 
167  mSourceCrs = QgsCoordinateReferenceSystem::fromWkt( map.value( QStringLiteral( "transform_source" ) ).toString() );
168  mDestinationCrs = QgsCoordinateReferenceSystem::fromWkt( map.value( QStringLiteral( "transform_dest" ) ).toString() );
169 
170  const QVariantMap fieldMap = map.value( QStringLiteral( "field_map" ) ).toMap();
171  mFieldMap.clear();
172  for ( auto it = fieldMap.constBegin(); it != fieldMap.constEnd(); ++it )
173  {
174  QgsProperty p;
175  p.loadVariant( it.value() );
176  mFieldMap.insert( it.key(), p );
177  }
178 
179  return true;
180 }
181 
183 {
184  return mDestinationWkbType == other.mDestinationWkbType
185  && mDestinationFields == other.mDestinationFields
186  && mFieldMap == other.mFieldMap
187  && mSourceCrs == other.mSourceCrs
188  && mDestinationCrs == other.mDestinationCrs;
189 }
190 
192 {
193  return !( *this == other );
194 }
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:369
QgsRemappingProxyFeatureSink::addFeatures
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
Definition: qgsremappingproxyfeaturesink.cpp:112
QgsGeometry::transform
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Definition: qgsgeometry.cpp:2836
QgsCoordinateTransformContext
Definition: qgscoordinatetransformcontext.h:57
QgsProperty
A store for object properties.
Definition: qgsproperty.h:231
QgsRemappingSinkDefinition
Definition: qgsremappingproxyfeaturesink.h:37
QgsRemappingProxyFeatureSink::remapFeature
QgsFeatureList remapFeature(const QgsFeature &feature) const
Remaps a feature to a set of features compatible with the destination sink.
Definition: qgsremappingproxyfeaturesink.cpp:44
QgsRemappingSinkDefinition::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination CRS used for reprojecting incoming features to the sink's destination CRS.
Definition: qgsremappingproxyfeaturesink.h:95
QgsRemappingSinkDefinition::operator==
bool operator==(const QgsRemappingSinkDefinition &other) const
Definition: qgsremappingproxyfeaturesink.cpp:182
QgsRemappingSinkDefinition::operator!=
bool operator!=(const QgsRemappingSinkDefinition &other) const
Definition: qgsremappingproxyfeaturesink.cpp:191
QgsCoordinateReferenceSystem::WKT_PREFERRED
@ WKT_PREFERRED
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition: qgscoordinatereferencesystem.h:678
QgsFields
Definition: qgsfields.h:44
QgsRemappingProxyFeatureSink::setTransformContext
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the transform context to use when reprojecting features.
Definition: qgsremappingproxyfeaturesink.cpp:39
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsRemappingSinkDefinition::destinationWkbType
QgsWkbTypes::Type destinationWkbType() const
Returns the WKB geometry type for the destination.
Definition: qgsremappingproxyfeaturesink.h:109
QgsRemappingSinkDefinition::loadVariant
bool loadVariant(const QVariantMap &map)
Loads this remapping definition from a QVariantMap, wrapped in a QVariant.
Definition: qgsremappingproxyfeaturesink.cpp:155
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
QgsFields::append
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
QgsProperty::loadVariant
bool loadVariant(const QVariant &property)
Loads this property from a QVariantMap, wrapped in a QVariant.
Definition: qgsproperty.cpp:733
QgsGeometry::coerceToType
QVector< QgsGeometry > coerceToType(QgsWkbTypes::Type type) const
Attempts to coerce this geometry into the specified destination type.
Definition: qgsgeometry.cpp:1327
QgsRemappingSinkDefinition::fieldMap
QMap< QString, QgsProperty > fieldMap() const
Returns the field mapping, which defines how to map the values from incoming features to destination ...
Definition: qgsremappingproxyfeaturesink.h:51
QgsFeature::clearGeometry
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:151
QgsCsException
Definition: qgsexception.h:65
QgsWkbTypes::Unknown
@ Unknown
Definition: qgswkbtypes.h:70
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:137
QgsFeature::setFields
void setFields(const QgsFields &fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:162
QgsRemappingProxyFeatureSink::QgsRemappingProxyFeatureSink
QgsRemappingProxyFeatureSink(const QgsRemappingSinkDefinition &mappingDefinition, QgsFeatureSink *sink, bool ownsSink=false)
Constructor for QgsRemappingProxyFeatureSink, using the specified mappingDefinition to manipulate fea...
Definition: qgsremappingproxyfeaturesink.cpp:21
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:572
QgsCoordinateReferenceSystem::toWkt
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Definition: qgscoordinatereferencesystem.cpp:1931
QgsLogger::warning
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:122
QgsRemappingSinkDefinition::destinationFields
QgsFields destinationFields() const
Returns the fields for the destination sink.
Definition: qgsremappingproxyfeaturesink.h:123
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:373
QgsGeometry
Definition: qgsgeometry.h:122
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
QgsRemappingProxyFeatureSink::setExpressionContext
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context to use when evaluating mapped field values.
Definition: qgsremappingproxyfeaturesink.cpp:34
QgsFeatureSink::addFeatures
virtual bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags())=0
Adds a list of features to the sink.
QgsAttributes
Definition: qgsattributes.h:57
qgsremappingproxyfeaturesink.h
QgsFeature
Definition: qgsfeature.h:55
QgsRemappingSinkDefinition::sourceCrs
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source CRS used for reprojecting incoming features to the sink's destination CRS.
Definition: qgsremappingproxyfeaturesink.h:81
QgsRemappingProxyFeatureSink::addFeature
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
Definition: qgsremappingproxyfeaturesink.cpp:106
qgslogger.h
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:127
QgsRemappingSinkDefinition::toVariant
QVariant toVariant() const
Saves this remapping definition to a QVariantMap, wrapped in a QVariant.
Definition: qgsremappingproxyfeaturesink.cpp:133
QgsCoordinateTransform
Definition: qgscoordinatetransform.h:52
QgsRemappingProxyFeatureSink::~QgsRemappingProxyFeatureSink
~QgsRemappingProxyFeatureSink() override
Definition: qgsremappingproxyfeaturesink.cpp:28
QgsFeatureIterator
Definition: qgsfeatureiterator.h:263
QgsCoordinateReferenceSystem::fromWkt
static QgsCoordinateReferenceSystem fromWkt(const QString &wkt)
Creates a CRS from a WKT spatial ref sys definition string.
Definition: qgscoordinatereferencesystem.cpp:233
QgsFeatureSink
Definition: qgsfeaturesink.h:33
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:521
QgsField
Definition: qgsfield.h:49