Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[API] Add an adapter class QgsBatchGeocodeAlgorithm which creates
a batch geocoding algorithm from a QgsGeocoderInterface Example usage: # create a class which implements the QgsGeocoderInterface interface: class MyGeocoder(QgsGeocoderInterface): def geocodeString(self, string, context, feedback): # calculate and return results... my_geocoder = MyGeocoder() # create an algorithm which allows for batch geocoding operations using the custom geocoder interface # and implement the few required pure virtual methods class MyGeocoderAlgorithm(QgsBatchGeocodeAlgorithm): def __init__(self): super().__init__(my_geocoder) def displayName(self): return "My Geocoder" def name(self): return "my_geocoder_alg" def createInstance(self): return MyGeocoderAlgorithm() # optionally, the group(), groupId(), tags(), shortHelpString() and other metadata style methods can be overridden and customized: def tags(self): return 'geocode,my service,batch'
- Loading branch information
1 parent
55f5259
commit 6ae7a17
Showing
7 changed files
with
588 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
python/analysis/auto_generated/processing/qgsalgorithmbatchgeocode.sip.in
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/************************************************************************ | ||
* This file has been generated automatically from * | ||
* * | ||
* src/analysis/processing/qgsalgorithmbatchgeocode.h * | ||
* * | ||
* Do not edit manually ! Edit header and run scripts/sipify.pl again * | ||
************************************************************************/ | ||
|
||
|
||
|
||
|
||
|
||
class QgsBatchGeocodeAlgorithm : QgsProcessingFeatureBasedAlgorithm | ||
{ | ||
%Docstring | ||
|
||
A base class for batch geocoder algorithms, which takes a QgsGeocoderInterface object and exposes it as | ||
a Processing algorithm for batch geocoding operations. | ||
|
||
Example | ||
------- | ||
|
||
.. code-block:: python | ||
|
||
# create a class which implements the QgsGeocoderInterface interface: | ||
class MyGeocoder(QgsGeocoderInterface): | ||
|
||
def geocodeString(self, string, context, feedback): | ||
# calculate and return results... | ||
|
||
my_geocoder = MyGeocoder() | ||
|
||
# create an algorithm which allows for batch geocoding operations using the custom geocoder interface | ||
# and implement the few required pure virtual methods | ||
class MyGeocoderAlgorithm(QgsBatchGeocodeAlgorithm): | ||
|
||
def __init__(self): | ||
super().__init__(my_geocoder) | ||
|
||
def displayName(self): | ||
return "My Geocoder" | ||
|
||
def name(self): | ||
return "my_geocoder_alg" | ||
|
||
def createInstance(self): | ||
return MyGeocoderAlgorithm() | ||
|
||
# optionally, the group(), groupId(), tags(), shortHelpString() and other metadata style methods can be overridden and customized: | ||
def tags(self): | ||
return 'geocode,my service,batch' | ||
|
||
.. versionadded:: 3.18 | ||
%End | ||
|
||
%TypeHeaderCode | ||
#include "qgsalgorithmbatchgeocode.h" | ||
%End | ||
public: | ||
|
||
QgsBatchGeocodeAlgorithm( QgsGeocoderInterface *geocoder ); | ||
%Docstring | ||
Constructor for QgsBatchGeocodeAlgorithm. | ||
|
||
The ``geocoder`` must specify an instance of a class which implements the :py:class:`QgsGeocoderInterface` | ||
interface. Ownership of ``geocoder`` is not transferred, and the caller must ensure that ``geocoder`` | ||
exists for the lifetime of this algorithm. | ||
%End | ||
|
||
virtual void initParameters( const QVariantMap &configuration = QVariantMap() ); | ||
|
||
virtual QStringList tags() const; | ||
|
||
virtual QString group() const; | ||
|
||
virtual QString groupId() const; | ||
|
||
virtual QList<int> inputLayerTypes() const; | ||
|
||
|
||
protected: | ||
virtual QString outputName() const; | ||
|
||
virtual bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ); | ||
|
||
virtual QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback ); | ||
|
||
virtual QgsCoordinateReferenceSystem outputCrs( const QgsCoordinateReferenceSystem &inputCrs ) const; | ||
|
||
virtual QgsFields outputFields( const QgsFields &inputFields ) const; | ||
|
||
virtual QgsWkbTypes::Type outputWkbType( QgsWkbTypes::Type inputWkbType ) const; | ||
|
||
|
||
}; | ||
|
||
|
||
|
||
|
||
/************************************************************************ | ||
* This file has been generated automatically from * | ||
* * | ||
* src/analysis/processing/qgsalgorithmbatchgeocode.h * | ||
* * | ||
* Do not edit manually ! Edit header and run scripts/sipify.pl again * | ||
************************************************************************/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
/*************************************************************************** | ||
qgsalgorithmbatchgeocode.cpp | ||
------------------ | ||
begin : August 2020 | ||
copyright : (C) 2020 by Nyall Dawson | ||
email : nyall dot dawson at gmail dot com | ||
***************************************************************************/ | ||
|
||
/*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgsalgorithmbatchgeocode.h" | ||
#include "qgsgeocoder.h" | ||
#include "qgsgeocoderresult.h" | ||
#include "qgsgeocodercontext.h" | ||
|
||
QgsBatchGeocodeAlgorithm::QgsBatchGeocodeAlgorithm( QgsGeocoderInterface *geocoder ) | ||
: QgsProcessingFeatureBasedAlgorithm() | ||
, mGeocoder( geocoder ) | ||
{ | ||
|
||
} | ||
|
||
QStringList QgsBatchGeocodeAlgorithm::tags() const | ||
{ | ||
return QObject::tr( "geocode" ).split( ',' ); | ||
} | ||
|
||
QString QgsBatchGeocodeAlgorithm::group() const | ||
{ | ||
return QObject::tr( "Vector general" ); | ||
} | ||
|
||
QString QgsBatchGeocodeAlgorithm::groupId() const | ||
{ | ||
return QStringLiteral( "vectorgeneral" ); | ||
} | ||
|
||
void QgsBatchGeocodeAlgorithm::initParameters( const QVariantMap & ) | ||
{ | ||
addParameter( new QgsProcessingParameterField( QStringLiteral( "FIELD" ), QObject::tr( "Address field" ), QVariant(), QStringLiteral( "INPUT" ), QgsProcessingParameterField::String ) ); | ||
} | ||
|
||
QList<int> QgsBatchGeocodeAlgorithm::inputLayerTypes() const | ||
{ | ||
return QList<int>() << QgsProcessing::TypeVector; | ||
} | ||
|
||
QString QgsBatchGeocodeAlgorithm::outputName() const | ||
{ | ||
return QObject::tr( "Geocoded" ); | ||
} | ||
|
||
bool QgsBatchGeocodeAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * ) | ||
{ | ||
mAddressField = parameterAsString( parameters, QStringLiteral( "FIELD" ), context ); | ||
return true; | ||
} | ||
|
||
QgsWkbTypes::Type QgsBatchGeocodeAlgorithm::outputWkbType( QgsWkbTypes::Type ) const | ||
{ | ||
return QgsWkbTypes::Point; | ||
} | ||
|
||
QgsCoordinateReferenceSystem QgsBatchGeocodeAlgorithm::outputCrs( const QgsCoordinateReferenceSystem &inputCrs ) const | ||
{ | ||
mOutputCrs = inputCrs; | ||
return mOutputCrs; | ||
} | ||
|
||
QgsFields QgsBatchGeocodeAlgorithm::outputFields( const QgsFields &inputFields ) const | ||
{ | ||
// append any additional fields created by the geocoder | ||
QgsFields res = inputFields; | ||
const QgsFields newFields = mGeocoder->appendedFields(); | ||
mAdditionalFields = newFields.names(); | ||
res.extend( newFields ); | ||
return res; | ||
} | ||
|
||
QgsFeatureList QgsBatchGeocodeAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) | ||
{ | ||
QgsFeature f = feature; | ||
|
||
QgsAttributes attr = f.attributes(); | ||
|
||
const QString address = f.attribute( mAddressField ).toString(); | ||
if ( address.isEmpty() ) | ||
{ | ||
// append null attributes | ||
for ( int i = 0; i < mAdditionalFields.count(); ++ i ) | ||
attr.append( QVariant() ); | ||
f.setAttributes( attr ); | ||
feedback->reportError( QObject::tr( "Empty address field for feature %1" ).arg( feature.id() ) ); | ||
return QgsFeatureList() << f; | ||
} | ||
|
||
QgsGeocoderContext geocodeContext( context.transformContext() ); | ||
const QList< QgsGeocoderResult > results = mGeocoder->geocodeString( address, geocodeContext, feedback ); | ||
if ( results.empty() ) | ||
{ | ||
// append null attributes | ||
for ( int i = 0; i < mAdditionalFields.count(); ++ i ) | ||
attr.append( QVariant() ); | ||
f.setAttributes( attr ); | ||
feedback->reportError( QObject::tr( "No result for %1" ).arg( address ) ); | ||
return QgsFeatureList() << f; | ||
} | ||
|
||
if ( !results.at( 0 ).isValid() ) | ||
{ | ||
// append null attributes | ||
for ( int i = 0; i < mAdditionalFields.count(); ++ i ) | ||
attr.append( QVariant() ); | ||
f.setAttributes( attr ); | ||
|
||
feedback->reportError( QObject::tr( "Error geocoding %1: %2" ).arg( address, results.at( 0 ).error() ) ); | ||
return QgsFeatureList() << f; | ||
} | ||
|
||
const QVariantMap additionalAttributes = results.at( 0 ).additionalAttributes(); | ||
for ( const QString &additionalField : mAdditionalFields ) | ||
{ | ||
attr.append( additionalAttributes.value( additionalField ) ); | ||
} | ||
f.setAttributes( attr ); | ||
|
||
QgsCoordinateTransform transform = QgsCoordinateTransform( results.at( 0 ).crs(), mOutputCrs, context.transformContext() ); | ||
QgsGeometry g = results.at( 0 ).geometry(); | ||
try | ||
{ | ||
g.transform( transform ); | ||
} | ||
catch ( QgsCsException & ) | ||
{ | ||
feedback->reportError( QObject::tr( "Error transforming %1 to layer CRS" ).arg( address ) ); | ||
return QgsFeatureList() << f; | ||
} | ||
|
||
f.setGeometry( g ); | ||
return QgsFeatureList() << f; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/*************************************************************************** | ||
qgsalgorithmbatchgeocode.h | ||
------------------ | ||
begin : August 2020 | ||
copyright : (C) 2020 by Nyall Dawson | ||
email : nyall dot dawson at gmail dot com | ||
***************************************************************************/ | ||
|
||
/*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGSALGORITHMBATCHGEOCODE_H | ||
#define QGSALGORITHMBATCHGEOCODE_H | ||
|
||
#include "qgis_sip.h" | ||
#include "qgis_analysis.h" | ||
#include "qgsprocessingalgorithm.h" | ||
|
||
class QgsGeocoderInterface; | ||
|
||
/** | ||
* \ingroup analysis | ||
* | ||
* A base class for batch geocoder algorithms, which takes a QgsGeocoderInterface object and exposes it as | ||
* a Processing algorithm for batch geocoding operations. | ||
* | ||
* ### Example | ||
* | ||
* \code{.py} | ||
* # create a class which implements the QgsGeocoderInterface interface: | ||
* class MyGeocoder(QgsGeocoderInterface): | ||
* | ||
* def geocodeString(self, string, context, feedback): | ||
* # calculate and return results... | ||
* | ||
* my_geocoder = MyGeocoder() | ||
* | ||
* # create an algorithm which allows for batch geocoding operations using the custom geocoder interface | ||
* # and implement the few required pure virtual methods | ||
* class MyGeocoderAlgorithm(QgsBatchGeocodeAlgorithm): | ||
* | ||
* def __init__(self): | ||
* super().__init__(my_geocoder) | ||
* | ||
* def displayName(self): | ||
* return "My Geocoder" | ||
* | ||
* def name(self): | ||
* return "my_geocoder_alg" | ||
* | ||
* def createInstance(self): | ||
* return MyGeocoderAlgorithm() | ||
* | ||
* # optionally, the group(), groupId(), tags(), shortHelpString() and other metadata style methods can be overridden and customized: | ||
* def tags(self): | ||
* return 'geocode,my service,batch' | ||
* | ||
* \endcode | ||
* | ||
* \since QGIS 3.18 | ||
*/ | ||
class ANALYSIS_EXPORT QgsBatchGeocodeAlgorithm : public QgsProcessingFeatureBasedAlgorithm | ||
{ | ||
|
||
public: | ||
|
||
/** | ||
* Constructor for QgsBatchGeocodeAlgorithm. | ||
* | ||
* The \a geocoder must specify an instance of a class which implements the QgsGeocoderInterface | ||
* interface. Ownership of \a geocoder is not transferred, and the caller must ensure that \a geocoder | ||
* exists for the lifetime of this algorithm. | ||
*/ | ||
QgsBatchGeocodeAlgorithm( QgsGeocoderInterface *geocoder ); | ||
|
||
void initParameters( const QVariantMap &configuration = QVariantMap() ) override; | ||
QStringList tags() const override; | ||
QString group() const override; | ||
QString groupId() const override; | ||
QList<int> inputLayerTypes() const override; | ||
|
||
protected: | ||
QString outputName() const override; | ||
bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override; | ||
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback ) override; | ||
QgsCoordinateReferenceSystem outputCrs( const QgsCoordinateReferenceSystem &inputCrs ) const override; | ||
QgsFields outputFields( const QgsFields &inputFields ) const override; | ||
QgsWkbTypes::Type outputWkbType( QgsWkbTypes::Type inputWkbType ) const override; | ||
|
||
private: | ||
|
||
QString mAddressField; | ||
QgsGeocoderInterface *mGeocoder = nullptr; | ||
mutable QgsCoordinateReferenceSystem mOutputCrs; | ||
mutable QStringList mAdditionalFields; | ||
|
||
}; | ||
|
||
///@endcond PRIVATE | ||
|
||
#endif // QGSALGORITHMBATCHGEOCODE_H | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.