QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsalgorithmaddxyfields.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmaddixyfields.cpp
3  -----------------------------------
4  begin : March 2019
5  copyright : (C) 2019 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 "qgsfeaturerequest.h"
20 #include "qgsvectorlayer.h"
21 
23 
24 QString QgsAddXYFieldsAlgorithm::name() const
25 {
26  return QStringLiteral( "addxyfields" );
27 }
28 
29 QString QgsAddXYFieldsAlgorithm::displayName() const
30 {
31  return QObject::tr( "Add X/Y fields to layer" );
32 }
33 
34 QString QgsAddXYFieldsAlgorithm::shortHelpString() const
35 {
36  return QObject::tr( "Adds X and Y (or latitude/longitude) fields to a point layer. The X/Y fields can be calculated in a different CRS to the layer (e.g. creating latitude/longitude fields for a layer in a project CRS)." );
37 }
38 
39 QString QgsAddXYFieldsAlgorithm::shortDescription() const
40 {
41  return QObject::tr( "Adds X and Y (or latitude/longitude) fields to a point layer." );
42 }
43 
44 QStringList QgsAddXYFieldsAlgorithm::tags() const
45 {
46  return QObject::tr( "add,create,latitude,longitude,columns,attributes" ).split( ',' );
47 }
48 
49 QString QgsAddXYFieldsAlgorithm::group() const
50 {
51  return QObject::tr( "Vector table" );
52 }
53 
54 QString QgsAddXYFieldsAlgorithm::groupId() const
55 {
56  return QStringLiteral( "vectortable" );
57 }
58 
59 QString QgsAddXYFieldsAlgorithm::outputName() const
60 {
61  return QObject::tr( "Added fields" );
62 }
63 
64 QList<int> QgsAddXYFieldsAlgorithm::inputLayerTypes() const
65 {
66  return QList<int>() << QgsProcessing::TypeVectorPoint;
67 }
68 
69 QgsAddXYFieldsAlgorithm *QgsAddXYFieldsAlgorithm::createInstance() const
70 {
71  return new QgsAddXYFieldsAlgorithm();
72 }
73 
74 QgsProcessingFeatureSource::Flag QgsAddXYFieldsAlgorithm::sourceFlags() const
75 {
77 }
78 
79 void QgsAddXYFieldsAlgorithm::initParameters( const QVariantMap &configuration )
80 {
81  mIsInPlace = configuration.value( QStringLiteral( "IN_PLACE" ) ).toBool();
82 
83  addParameter( new QgsProcessingParameterCrs( QStringLiteral( "CRS" ), QObject::tr( "Coordinate system" ), QStringLiteral( "EPSG:4326" ) ) );
84 
85  if ( !mIsInPlace )
86  addParameter( new QgsProcessingParameterString( QStringLiteral( "PREFIX" ), QObject::tr( "Field prefix" ), QVariant(), false, true ) );
87  else
88  {
89  addParameter( new QgsProcessingParameterField( QStringLiteral( "FIELD_X" ), QObject::tr( "X field" ), QVariant(), QStringLiteral( "INPUT" ) ) );
90  addParameter( new QgsProcessingParameterField( QStringLiteral( "FIELD_Y" ), QObject::tr( "Y field" ), QVariant(), QStringLiteral( "INPUT" ) ) );
91  }
92 }
93 
94 QgsFields QgsAddXYFieldsAlgorithm::outputFields( const QgsFields &inputFields ) const
95 {
96  if ( mIsInPlace )
97  {
98  mInPlaceXFieldIndex = inputFields.lookupField( mInPlaceXField );
99  mInPlaceYFieldIndex = inputFields.lookupField( mInPlaceYField );
100  return inputFields;
101  }
102  else
103  {
104  const QString xFieldName = mPrefix + 'x';
105  const QString yFieldName = mPrefix + 'y';
106 
107  QgsFields outFields = inputFields;
108  outFields.append( QgsField( xFieldName, QVariant::Double, QString(), 20, 10 ) );
109  outFields.append( QgsField( yFieldName, QVariant::Double, QString(), 20, 10 ) );
110  return outFields;
111  }
112 }
113 
115 {
116  mSourceCrs = inputCrs;
117  return inputCrs;
118 }
119 
120 bool QgsAddXYFieldsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
121 {
122  if ( !mIsInPlace )
123  mPrefix = parameterAsString( parameters, QStringLiteral( "PREFIX" ), context );
124  else
125  {
126  mInPlaceXField = parameterAsString( parameters, QStringLiteral( "FIELD_X" ), context );
127  mInPlaceYField = parameterAsString( parameters, QStringLiteral( "FIELD_Y" ), context );
128  }
129 
130  mCrs = parameterAsCrs( parameters, QStringLiteral( "CRS" ), context );
131  return true;
132 }
133 
134 QgsFeatureList QgsAddXYFieldsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
135 {
136  if ( mTransformNeedsInitialization )
137  {
138  mTransform = QgsCoordinateTransform( mSourceCrs, mCrs, context.transformContext() );
139  mTransformNeedsInitialization = false;
140  }
141  if ( mIsInPlace && mInPlaceXFieldIndex == -1 )
142  {
143  throw QgsProcessingException( QObject::tr( "Destination field not found" ) );
144  }
145 
146  QVariant x;
147  QVariant y;
148  if ( feature.hasGeometry() )
149  {
150  if ( feature.geometry().isMultipart() )
151  throw QgsProcessingException( QObject::tr( "Multipoint features are not supported - please convert to single point features first." ) );
152 
153  const QgsPointXY point = feature.geometry().asPoint();
154  try
155  {
156  const QgsPointXY transformed = mTransform.transform( point );
157  x = transformed.x();
158  y = transformed.y();
159  }
160  catch ( QgsCsException & )
161  {
162  feedback->reportError( QObject::tr( "Could not transform point to destination CRS" ) );
163  }
164  }
165  QgsFeature f = feature;
166  QgsAttributes attributes = f.attributes();
167  if ( !mIsInPlace )
168  {
169  attributes << x << y;
170  }
171  else
172  {
173  attributes[mInPlaceXFieldIndex] = x;
174  attributes[mInPlaceYFieldIndex] = y;
175  }
176  f.setAttributes( attributes );
177  return QgsFeatureList() << f;
178 }
179 
180 bool QgsAddXYFieldsAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
181 {
182  if ( const QgsVectorLayer *vl = qobject_cast< const QgsVectorLayer * >( layer ) )
183  {
184  return vl->geometryType() == QgsWkbTypes::PointGeometry;
185  }
186  return false;
187 }
188 
A vector of attributes.
Definition: qgsattributes.h:58
This class represents a coordinate reference system (CRS).
Class for doing transforms between two map coordinate systems.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsAttributes attributes
Definition: qgsfeature.h:65
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:135
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:205
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
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
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
bool isMultipart() const SIP_HOLDGIL
Returns true if WKB of the geometry is of WKBMulti* type.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Base class for all map layer types.
Definition: qgsmaplayer.h:70
A class to represent a 2D point.
Definition: qgspointxy.h:59
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
Contains information about the context in which a processing algorithm is executed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Custom exception class for processing related exceptions.
Definition: qgsexception.h:83
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Base class for providing feedback from a processing algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
A coordinate reference system parameter for processing algorithms.
A vector layer or feature source field parameter for processing algorithms.
A string parameter for processing algorithms.
@ TypeVectorPoint
Vector point layers.
Definition: qgsprocessing.h:49
Represents a vector layer which manages a vector based data sets.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:736
const QgsCoordinateReferenceSystem & outputCrs