Skip to content

Commit

Permalink
Refactor processing algorithm classes
Browse files Browse the repository at this point in the history
Removes redundancies in processing algorithm classes by
creating the ORSBaseProcessingAlgorithm class.

Moved to base class:
- basic attributes and functions
- provider and output parameter
- algorithm and ors_client initialization

Other notable changes:
- moved from class to instance attribute approach
- clean algorithm class naming
- build_default_parameters moved to directions_core
- easier access to input values in processAlgorithm()
- rename of help files for dynamic loading
- moved from lookupField() to indexOf()

closes #133
  • Loading branch information
TheGreatRefrigerator committed Jun 8, 2021
1 parent 1fe1e0c commit d48c21a
Show file tree
Hide file tree
Showing 18 changed files with 571 additions and 986 deletions.
32 changes: 32 additions & 0 deletions ORStools/common/directions_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
QgsFeature,
QgsFields,
QgsField)
from typing import List

from PyQt5.QtCore import QVariant

Expand Down Expand Up @@ -191,3 +192,34 @@ def get_output_features_optimization(response, profile, from_value=None):
])

return feat


def build_default_parameters(preference: str, point_list: List[QgsPointXY] = None, coordinates: list = None) -> dict:
"""
Build default parameters for directions endpoint. Either uses a list of QgsPointXY to create the coordinates
passed in point_list or an existing coordinate list within the coordinates parameter.
TODO no optimal solution, maybe let get_request_point_features() return QgsPointXY as well to only use point_list
:param preference: routing preference, shortest/fastest/recommended
:type preference: str
:param point_list:
:type point_list: list of QgsPointXY
:param coordinates:
:type coordinates: list
:returns: parameters for directions endpoint
:rtype: dict
"""
coords = coordinates if coordinates else [[round(point.x(), 6), round(point.y(), 6)] for point in point_list]
params = {
'coordinates': coords,
'preference': preference,
'geometry': 'true',
'instructions': 'false',
'elevation': True,
'id': None
}

return params
4 changes: 2 additions & 2 deletions ORStools/common/isochrones_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,11 @@ def stylePoly(self, layer):
"""

if self.dimension == 'time':
legend_suffix = ' mins'
legend_suffix = ' min'
else:
legend_suffix = ' m'

field = layer.fields().lookupField(self.field_dimension_name)
field = layer.fields().indexOf(self.field_dimension_name)
unique_values = sorted(layer.uniqueValues(field))

colors = {0: QColor('#2b83ba'),
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
5 changes: 0 additions & 5 deletions ORStools/proc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,3 @@
* *
***************************************************************************/
"""
import os.path

from ORStools import BASE_DIR

HELP_DIR = os.path.join(BASE_DIR, 'help')
148 changes: 148 additions & 0 deletions ORStools/proc/base_processing_algorithm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# -*- coding: utf-8 -*-
"""
/***************************************************************************
ORStools
A QGIS plugin
QGIS client to query openrouteservice
-------------------
begin : 2017-02-01
git sha : $Format:%H$
copyright : (C) 2021 by HeiGIT gGmbH
email : support@openrouteservice.heigit.org
***************************************************************************/
This plugin provides access to openrouteservice API functionalities
(https://openrouteservice.org), developed and
maintained by the openrouteservice team of HeiGIT gGmbH, Germany. By using
this plugin you agree to the ORS terms of service
(https://openrouteservice.org/terms-of-service/).
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
"""
from qgis.core import (QgsProcessingAlgorithm,
QgsProcessingParameterEnum,
QgsProcessingParameterFeatureSink,
QgsProcessingFeedback
)
from typing import Any

from PyQt5.QtGui import QIcon

from ORStools import RESOURCE_PREFIX, __help__
from ORStools.utils import configmanager
from ..common import client
from ..utils.processing import read_help_file


# noinspection PyPep8Naming
class ORSBaseProcessingAlgorithm(QgsProcessingAlgorithm):
"""Base algorithm class for ORS algorithms"""

def __init__(self):
"""
Default attributes used in all child classes
"""
super().__init__()
self.ALGO_NAME = ''
self.GROUP = ''
self.IN_PROVIDER = "INPUT_PROVIDER"
self.OUT = 'OUTPUT'
self.PARAMETERS = None

def createInstance(self) -> Any:
"""
Returns instance of any child class
"""
return self.__class__()

def group(self) -> str:
"""
Returns group name (Directions, Isochrones, Matrix) defined in child class
"""
return self.GROUP

def groupId(self) -> str:
return self.GROUP.lower()

def name(self) -> str:
"""
Returns algorithm name defined in child class
"""
return self.ALGO_NAME

def shortHelpString(self):
"""
Displays the sidebar help in the algorithm window
"""
return read_help_file(file_name=f'{self.ALGO_NAME}.help')

@staticmethod
def helpUrl():
"""
Will be connected to the Help button in the Algorithm window
"""
return __help__

def displayName(self) -> str:
"""
Algorithm name shown in QGIS toolbox
:return:
"""
return self.ALGO_NAME.capitalize().replace('_', ' ')

def icon(self) -> QIcon:
"""
Icon used for algorithm in QGIS toolbox
"""
return QIcon(RESOURCE_PREFIX + f'icon_{self.groupId()}.png')

def provider_parameter(self) -> QgsProcessingParameterEnum:
"""
Parameter definition for provider, used in all child classes
"""
providers = [provider['name'] for provider in configmanager.read_config()['providers']]
return QgsProcessingParameterEnum(
self.IN_PROVIDER,
"Provider",
providers,
defaultValue=providers[0]
)

def output_parameter(self) -> QgsProcessingParameterFeatureSink:
"""
Parameter definition for output, used in all child classes
"""
return QgsProcessingParameterFeatureSink(
name=self.OUT,
description=self.GROUP,
)

@staticmethod
def _get_ors_client_from_provider(provider: str, feedback: QgsProcessingFeedback) -> client.Client:
"""
Connects client to provider and returns a client instance for requests to the ors API
"""
providers = configmanager.read_config()['providers']
ors_provider = providers[provider]
ors_client = client.Client(ors_provider)
ors_client.overQueryLimit.connect(lambda: feedback.reportError("OverQueryLimit: Retrying..."))
return ors_client

# noinspection PyUnusedLocal
def initAlgorithm(self, configuration):
"""
Combines default and algorithm parameters and adds them in order to the
algorithm dialog window.
"""
parameters = [self.provider_parameter()] + self.PARAMETERS + [self.output_parameter()]
for param in parameters:
self.addParameter(
param
)
Loading

0 comments on commit d48c21a

Please sign in to comment.