QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsalgorithmbatchgeocode.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmbatchgeocode.cpp
3  ------------------
4  begin : August 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 "qgsgeocoder.h"
20 #include "qgsgeocoderresult.h"
21 #include "qgsgeocodercontext.h"
22 #include "qgsvectorlayer.h"
23 
26  , mGeocoder( geocoder )
27 {
28 
29 }
30 
31 QStringList QgsBatchGeocodeAlgorithm::tags() const
32 {
33  return QObject::tr( "geocode" ).split( ',' );
34 }
35 
37 {
38  return QObject::tr( "Vector general" );
39 }
40 
42 {
43  return QStringLiteral( "vectorgeneral" );
44 }
45 
46 void QgsBatchGeocodeAlgorithm::initParameters( const QVariantMap &configuration )
47 {
48  mIsInPlace = configuration.value( QStringLiteral( "IN_PLACE" ) ).toBool();
49 
50  addParameter( new QgsProcessingParameterField( QStringLiteral( "FIELD" ), QObject::tr( "Address field" ), QVariant(), QStringLiteral( "INPUT" ), QgsProcessingParameterField::String ) );
51 
52  if ( mIsInPlace )
53  {
54  const QgsFields newFields = mGeocoder->appendedFields();
55  for ( const QgsField &newField : newFields )
56  addParameter( new QgsProcessingParameterField( newField.name(), QObject::tr( "%1 field" ).arg( newField.name() ), newField.name(), QStringLiteral( "INPUT" ), QgsProcessingParameterField::Any, false, true ) );
57  }
58 }
59 
61 {
62  return QList<int>() << QgsProcessing::TypeVector;
63 }
64 
66 {
67  if ( const QgsVectorLayer *vl = qobject_cast< const QgsVectorLayer * >( layer ) )
68  {
69  return vl->geometryType() == QgsWkbTypes::PointGeometry;
70  }
71  return false;
72 }
73 
75 {
76  return QObject::tr( "Geocoded" );
77 }
78 
80 {
81  mAddressField = parameterAsString( parameters, QStringLiteral( "FIELD" ), context );
82 
83  if ( mIsInPlace )
84  {
85  const QgsFields newFields = mGeocoder->appendedFields();
86  for ( const QgsField &newField : newFields )
87  mInPlaceFieldMap.insert( newField.name(), parameterAsString( parameters, newField.name(), context ) );
88  }
89 
90  return true;
91 }
92 
94 {
95  return QgsWkbTypes::Point;
96 }
97 
99 {
100  mOutputCrs = inputCrs;
101  return mOutputCrs;
102 }
103 
105 {
106  if ( !mIsInPlace )
107  {
108  // append any additional fields created by the geocoder
109  const QgsFields newFields = mGeocoder->appendedFields();
110  mAdditionalFields = newFields.names();
111 
112  return QgsProcessingUtils::combineFields( inputFields, newFields );
113  }
114  else
115  {
116  return inputFields;
117  }
118 }
119 
121 {
122  QgsFeature f = feature;
123 
124  const QString address = f.attribute( mAddressField ).toString();
125  if ( address.isEmpty() )
126  {
127  f.padAttributes( mAdditionalFields.count() );
128  feedback->pushWarning( QObject::tr( "Empty address field for feature %1" ).arg( feature.id() ) );
129  return QgsFeatureList() << f;
130  }
131 
132  QgsGeocoderContext geocodeContext( context.transformContext() );
133  const QList< QgsGeocoderResult > results = mGeocoder->geocodeString( address, geocodeContext, feedback );
134  if ( results.empty() )
135  {
136  f.padAttributes( mAdditionalFields.count() );
137  feedback->pushWarning( QObject::tr( "No result for %1" ).arg( address ) );
138  return QgsFeatureList() << f;
139  }
140 
141  if ( !results.at( 0 ).isValid() )
142  {
143  f.padAttributes( mAdditionalFields.count() );
144  feedback->reportError( QObject::tr( "Error geocoding %1: %2" ).arg( address, results.at( 0 ).error() ) );
145  return QgsFeatureList() << f;
146  }
147 
148  QgsAttributes attr = f.attributes();
149  const QVariantMap additionalAttributes = results.at( 0 ).additionalAttributes();
150  if ( !mIsInPlace )
151  {
152  for ( const QString &additionalField : mAdditionalFields )
153  {
154  attr.append( additionalAttributes.value( additionalField ) );
155  }
156  f.setAttributes( attr );
157  }
158  else
159  {
160  for ( auto it = mInPlaceFieldMap.constBegin(); it != mInPlaceFieldMap.constEnd(); ++it )
161  {
162  if ( !it.value().isEmpty() )
163  {
164  f.setAttribute( it.value(), additionalAttributes.value( it.key() ) );
165  }
166  }
167  }
168 
169  QgsCoordinateTransform transform = QgsCoordinateTransform( results.at( 0 ).crs(), mOutputCrs, context.transformContext() );
170  QgsGeometry g = results.at( 0 ).geometry();
171  try
172  {
173  g.transform( transform );
174  }
175  catch ( QgsCsException & )
176  {
177  feedback->reportError( QObject::tr( "Error transforming %1 to layer CRS" ).arg( address ) );
178  return QgsFeatureList() << f;
179  }
180 
181  f.setGeometry( g );
182  return QgsFeatureList() << f;
183 }
A vector of attributes.
Definition: qgsattributes.h:58
bool prepareAlgorithm(const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback) override
Prepares the algorithm to run using the specified parameters.
QgsFeatureList processFeature(const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback) override
Processes an individual input feature from the source.
void initParameters(const QVariantMap &configuration=QVariantMap()) override
Initializes any extra parameters added by the algorithm subclass.
QString group() const override
Returns the name of the group this algorithm belongs to.
QString outputName() const override
Returns the translated, user visible name for any layers created by this algorithm.
QgsCoordinateReferenceSystem outputCrs(const QgsCoordinateReferenceSystem &inputCrs) const override
Maps the input source coordinate reference system (inputCrs) to a corresponding output CRS generated ...
QgsBatchGeocodeAlgorithm(QgsGeocoderInterface *geocoder)
Constructor for QgsBatchGeocodeAlgorithm.
QgsWkbTypes::Type outputWkbType(QgsWkbTypes::Type inputWkbType) const override
Maps the input WKB geometry type (inputWkbType) to the corresponding output WKB type generated by the...
QgsFields outputFields(const QgsFields &inputFields) const override
Maps the input source fields (inputFields) to corresponding output fields generated by the algorithm.
QString groupId() const override
Returns the unique ID of the group this algorithm belongs to.
QStringList tags() const override
Returns a list of tags which relate to the algorithm, and are used to assist users in searching for s...
bool supportInPlaceEdit(const QgsMapLayer *layer) const override
Checks whether this algorithm supports in-place editing on the given layer Default implementation for...
QList< int > inputLayerTypes() const override
Returns the valid input layer types for the source layer for this algorithm.
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
bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
Definition: qgsfeature.cpp:237
QgsAttributes attributes
Definition: qgsfeature.h:65
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:135
void padAttributes(int count)
Resizes the attributes attached to this feature by appending the specified count of NULL values to th...
Definition: qgsfeature.cpp:228
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:302
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:145
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
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
QStringList names() const
Returns a list with field names.
Definition: qgsfields.cpp:143
Encapsulates the context of a geocoding operation.
Interface for geocoders.
Definition: qgsgeocoder.h:37
virtual QList< QgsGeocoderResult > geocodeString(const QString &string, const QgsGeocoderContext &context, QgsFeedback *feedback=nullptr) const
Geocodes a string.
Definition: qgsgeocoder.cpp:29
virtual QgsFields appendedFields() const
Returns a set of newly created fields which will be appended to existing features during the geocode ...
Definition: qgsgeocoder.cpp:25
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
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.
Base class for all map layer types.
Definition: qgsmaplayer.h:70
bool addParameter(QgsProcessingParameterDefinition *parameterDefinition, bool createOutput=true)
Adds a parameter definition to the algorithm.
QString parameterAsString(const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context) const
Evaluates the parameter with matching name to a static string value.
Contains information about the context in which a processing algorithm is executed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
An abstract QgsProcessingAlgorithm base class for processing algorithms which operate "feature-by-fea...
Base class for providing feedback from a processing algorithm.
virtual void pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
A vector layer or feature source field parameter for processing algorithms.
static QgsFields combineFields(const QgsFields &fieldsA, const QgsFields &fieldsB, const QString &fieldsBPrefix=QString())
Combines two field lists, avoiding duplicate field names (in a case-insensitive manner).
@ TypeVector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition: qgsprocessing.h:54
Represents a vector layer which manages a vector based data sets.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:736