3

I want to create a custom processing tool for geocoding in QGIS.

It will reproduce the "Batch Nominatim geocoder" geoalgorithm, besides several things:

  • another URL of a geocoder will be used instead of the the Nominatim
  • there will be no limitations in requests

From the "Batch Nominatim geocoder" I would like to inherit: GUI, functionality and logic.

I tried to create a model in the Graphical Modeler and export it as a Python Processing Script, however it does not look like what I need.

"""
Model exported as python.
Name : geocoding
Group : STMA
With QGIS : 32205
"""

from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingMultiStepFeedback
from qgis.core import QgsProcessingParameterVectorLayer
from qgis.core import QgsProcessingParameterFeatureSink
import processing


class Geocoding(QgsProcessingAlgorithm):

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterVectorLayer('Adressen', 'adressen', types=[QgsProcessing.TypeVector], defaultValue=None))
        self.addParameter(QgsProcessingParameterFeatureSink('Geocodiert', 'geocodiert', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, supportsAppend=True, defaultValue=None))

    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(1, model_feedback)
        results = {}
        outputs = {}

        # Batch Nominatim geocoder
        alg_params = {
            'FIELD': 'Anschrift',
            'INPUT': parameters['Adressen'],
            'OUTPUT': parameters['Geocodiert']
        }
        outputs['BatchNominatimGeocoder'] = processing.run('native:batchnominatimgeocoder', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
        results['Geocodiert'] = outputs['BatchNominatimGeocoder']['OUTPUT']
        return results

    def name(self):
        return 'geocoding'

    def displayName(self):
        return 'geocoding'

    def group(self):
        return 'STMA'

    def groupId(self):
        return ''

    def createInstance(self):
        return Geocoding()

I could find this geoalgorithm in QGIS/src/core/geocoding/qgsnominatimgeocoder.cpp on the GitHub. This is the part with an URL:

QgsNominatimGeocoder::QgsNominatimGeocoder( const QString &countryCodes, const QString &endpoint )
  : QgsGeocoderInterface()
  , mCountryCodes( countryCodes )
  , mEndpoint( QStringLiteral( "https://nominatim.qgis.org/search" ) )

But C++ is simply beyond my programming skills.

Another (maybe a feasible) solution is to reproduce the "Google Maps Geocoder" plugin developed by @ndawson. It is basically a processing tool, similar to "Batch Nominatim geocoder" but implemented for Google Maps. This plugin is available on the GitHub: https://github.com/north-road/qgis-google-maps-geocoder. Unfortunately the geocoding in this plugin is dependent on the QgsGoogleMapsGeocoder class, not a simple request to Google Maps API.

What are my available approaches?

Perhaps it is in general impossible because I simply collide with copyrights of the core developer (Mathieu Pellerin @nirvn).

4
  • 1
    No colliding since QGIS project is in GPL2 : github.com/qgis/QGIS/blob/master/COPYING Jun 22, 2022 at 8:28
  • 1
  • 1
    Note that 90% of what these implementations do is stitching together core library classes to create request objects that conform with the respective API, sending and receiving http(s) requests, and parsing the respective API responses - some sanity checks aside. What this means for you is that you will either have to rewrite these 90% in C++ to suit your own API - or simply write an own, independent Python plugin to begin with.
    – geozelot
    Jun 22, 2022 at 9:43
  • 1
    I would just rewrite the script of batchnominatim from scratch in Python, thats probably the most straight forward option. Even if you don't know c++, you can still get the logic of the code. About license I dont see an issue. Even if you use parts of others code, most of them allow usage by naming the authors or under the same terms.
    – MrXsquared
    Jun 22, 2022 at 14:45

1 Answer 1

2

A good point to start is this tutorial: Building a Processing Plugin (QGIS3) by @spatialthoughts.

This reference shows how to develop a custom processing plugin using the "Plugin Builder" plugin for creating a plugin template which at the beginning can imitate the desired GUI of the "Batch Nominatim geocoder" geoalgorithm, see image below.

input

After one shall try to modify the .ui file of this processing plugin and embed the parameter of the 'Address field' using the Qt Creator, as also demonstrated in this tutorial Building a Python Plugin (QGIS3) by @spatialthoughts.

Last but not least adjust plugin functionality and logic correspondingly.


References:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.