From 774a6ddd8be9e1529aa5ae5b1b931a8d73aab0a2 Mon Sep 17 00:00:00 2001 From: Jakob Schnell Date: Wed, 6 Dec 2023 16:22:09 +0100 Subject: [PATCH] feat: add smoothing to isochrone params (#199) Co-authored-by: Jakob Schnell Co-authored-by: mattamach <80196449+mattamach@users.noreply.github.com> Co-authored-by: Merydian Co-authored-by: Till Frankenbach <81414045+Merydian@users.noreply.github.com> --- CHANGELOG.md | 2 +- ORStools/common/__init__.py | 2 +- ORStools/i18n/orstools_de.qm | Bin 20758 -> 21242 bytes ORStools/i18n/orstools_de.ts | 32 +++++++++++++++-------- ORStools/proc/isochrones_layer_proc.py | 34 ++++++++++++++++++++----- ORStools/proc/isochrones_point_proc.py | 23 +++++++++++++++-- 6 files changed, 72 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdbbbb44..4f8e9bc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ RELEASING: ## Unreleased ### Added +- Additional parameter for the "smoothing factor" to isochrones processing algorithms ([#172](https://github.com/GIScience/orstools-qgis-plugin/issues/172)) - Mention omission of configuration options when using traveling salesman ## [1.6.0] - 2023-07-25 @@ -50,7 +51,6 @@ RELEASING: - translation mechanism ([#183](https://github.com/GIScience/orstools-qgis-plugin/pull/183)) - german translation ([#183](https://github.com/GIScience/orstools-qgis-plugin/pull/183)) - ## [1.5.3] - 2023-03-30 ### Fixed diff --git a/ORStools/common/__init__.py b/ORStools/common/__init__.py index b714c41f..5a1524d2 100644 --- a/ORStools/common/__init__.py +++ b/ORStools/common/__init__.py @@ -49,4 +49,4 @@ AVOID_BORDERS = ['all', 'controlled', 'none'] -ADVANCED_PARAMETERS = ["INPUT_AVOID_FEATURES", "INPUT_AVOID_BORDERS", "INPUT_AVOID_COUNTRIES", "INPUT_AVOID_POLYGONS"] +ADVANCED_PARAMETERS = ["INPUT_AVOID_FEATURES", "INPUT_AVOID_BORDERS", "INPUT_AVOID_COUNTRIES", "INPUT_AVOID_POLYGONS", 'INPUT_SMOOTHING'] diff --git a/ORStools/i18n/orstools_de.qm b/ORStools/i18n/orstools_de.qm index 3bd0286fab5eea96e065e4537fa149dcb14726b3..1185a50706d7e9a21837addf236c31228ac54aa2 100644 GIT binary patch delta 1293 zcmc&y{ZCV86n=Uy_qO-8+%g81Qm2;jeZOY`=*@B2RQ zInQ&>IdDw(@Dtr$Tj*_|s23=;0qZsb`HK-VlMcAXP;_7v$T^{*s|&@=D}nj3D0yK& zVIekO%LSg>3158_C|QVY?Q4OjAE4#SM%s6ycOS)m`6|Bsi{8D|h9ADz1FR0|xc5&3 zVzY)_-EpCUUv+PG+kscwb!QKD08d$TBeTx}iSf+BN3EpkD<);44KTQv)H!YQLrmqS zi^S_>nx+WNDH>WM%%O+?6dWepPUvKM{j`yP~v(4DSQhbm>#3Zvt5ky)X4g!19_taFqpe*N10xi$l46 z2KLe}D##@blO2YG)iac@%rKNt3rOz?deuih=V>^vNf28lpzwy^^;D5xQSd$<1oWS2 zSlA^TNzA0QRw457a%!e5{NoRk%xA=;w-x}7U1G)kkAS?L;#O%b71H=f^iGhTq8_pH zjuSA}h&`F~pm<0eXH>v+#TeK7J0MgTJNH{D@NdRX6Z)y6XN>(DCMm&oc(TJTRq3?ZESwO$BM|sbEplI|F3I#+ojEc$_BYzG?isMP$GkE0)ECNJ&=g=Pyo? zlRqTO?P=OiN|9^|xZ;8o>8EkcnU)65(!DUMp=pP7?ik%?ACi79|C>f`w}wfl%=zuq zsd!F9o6lUkG)iOqy?KX@9P10sM+XlB3DxGlzD7E?n{V9`?^265lFjmpXa~DDG1P`4 zcySLw`fY!ov)!GSg-o)J+~caC_Aj#S>m&Nr_smdCdRqsr0||R23ddmZKH6Z?gUc DfvH@3 delta 867 zcmXAndn}c47{|ZoeZB8F?|Y7OkmI1#PLt_IF{BV3ms}gIT9ndd(Kw4PblX`eo6A&$ zqLw4dCZ=YF=lM-H$SUh(mlvASfv9>Q zIttjj0|-lk&G;H1ZW2+IJ-~)xiE$m+oEr$Z1|r74f|!jx??M25GqTdHz~)#SFGvCw zOyShMqqKgC`m#JAWERi<(Y@eSj5d`5;Y~8Gs0|QvC0?nvGZ_}ij#PV*heg(2RS4MY zWZe@>0j&eGWabPxePHwh7XU>9<38`^+Qg*ndO_!knG=IVjb5UzpSflhfK9!`lSCs^ zZ=3)E=Gd?Ra*QsP81KR6BOyTQ;<+8m*QZc0;{-^$X*+)i$w=M}KBksIlzLLSMy z@9?|;_}IikPzU)fUfqCQ&^*Hd=jVJ)YYq@v$JeHP0d$EHLx1u^E)#$|$N%Um17bVm z`mrIv_mDix{Ttw9l;^x*fuM8c<1!CZ(0c{jcb*#3C(-$kqAGQq>g6dOJMIV67X^7n z7Ugu3s4Wr1Gin+NFJvCrO?gEjbIts4T5vv^pYM2%F=h?xWA6Y)|k9@zva_ldPWbRqJ)*w17Ds@F=p`d@&MtSqi@ zp|bFeAwhFmMhWE+nj4nufMcqrx%nu4=VZ;NPoGI3 bpHjsaP-J!-)>~|m*1EtojIoBeJ@Wex4`26t diff --git a/ORStools/i18n/orstools_de.ts b/ORStools/i18n/orstools_de.ts index 61f669aa..8707ee41 100644 --- a/ORStools/i18n/orstools_de.ts +++ b/ORStools/i18n/orstools_de.ts @@ -165,53 +165,63 @@ ORSIsochronesLayerAlgo - + Input Point layer Eingabelayer (Punkte) - + Input layer ID Field (mutually exclusive with Point option) ID-Attribut (schließt Punkt-Option aus) - + Dimension Dimension - + Comma-separated ranges [min or m] Komma-getrennte Reichweiten [min oder m] - + Isochrones from Point-Layer Isochronen aus Punkt-Layer + + + Smoothing factor between 0 [detailed] and 100 [generalized] + Glättungsfaktor zwischen 0 [detailliert] und 100 [verallgemeinert] + ORSIsochronesPointAlgo - + Input Point from map canvas (mutually exclusive with layer option) Eingabepunkt aus Kartenansicht (schließt Ebenen-Option aus) - + Dimension Dimension - + Comma-separated ranges [min or m] Komma-getrennte Reichweiten [min oder m] - + Isochrones from Point Isochronen von einzelnem Punkt + + + Smoothing factor between 0 [detailed] and 100 [generalized] + Glättungsfaktor zwischen 0 [detailliert] und 100 [verallgemeinert] + ORSMatrixAlgo @@ -244,12 +254,12 @@ ORStoolsDialog - + Apply Anwenden - + Close Schließen diff --git a/ORStools/proc/isochrones_layer_proc.py b/ORStools/proc/isochrones_layer_proc.py index 8fdd7367..7208c5ae 100644 --- a/ORStools/proc/isochrones_layer_proc.py +++ b/ORStools/proc/isochrones_layer_proc.py @@ -35,7 +35,9 @@ QgsProcessingParameterField, QgsProcessingParameterFeatureSource, QgsProcessingParameterString, - QgsProcessingParameterEnum + QgsProcessingParameterEnum, + QgsProcessingParameterNumber, + QgsProcessingParameterDefinition, ) from ORStools.common import isochrones_core, PROFILES, DIMENSIONS @@ -56,6 +58,8 @@ def __init__(self): self.IN_RANGES = 'INPUT_RANGES' self.IN_KEY = 'INPUT_APIKEY' self.IN_DIFFERENCE = 'INPUT_DIFFERENCE' + self.USE_SMOOTHING = 'USE_SMOOTHING' + self.IN_SMOOTHING = 'INPUT_SMOOTHING' self.PARAMETERS = [ QgsProcessingParameterFeatureSource( name=self.IN_POINTS, @@ -82,7 +86,16 @@ def __init__(self): name=self.IN_RANGES, description=self.tr("Comma-separated ranges [min or m]"), defaultValue="5, 10" - ) + ), + QgsProcessingParameterNumber( + name=self.IN_SMOOTHING, + description=self.tr("Smoothing factor between 0 [detailed] and 100 [generalized]"), + defaultValue=None, + minValue=0, + maxValue=100, + optional=True + ), + ] # Save some important references @@ -103,10 +116,12 @@ def processAlgorithm(self, parameters, context, feedback): factor = 60 if dimension == 'time' else 1 ranges_raw = parameters[self.IN_RANGES] ranges_proc = [x * factor for x in map(int, ranges_raw.split(','))] - + smoothing = parameters[self.IN_SMOOTHING] + # self.difference = self.parameterAsBool(parameters, self.IN_DIFFERENCE, context) source = self.parameterAsSource(parameters, self.IN_POINTS, context) + # get smoothness parameter value options = self.parseOptions(parameters, context) # Make the actual requests @@ -129,14 +144,21 @@ def processAlgorithm(self, parameters, context, feedback): if feedback.isCanceled(): break - requests.append({ + params = { "locations": locations, "range_type": dimension, "range": ranges_proc, "attributes": ['total_pop'], "id": id_value, - "options": options - }) + "options": options, + } + + # only include smoothing if set + if smoothing is not None: + params["smoothing"] = smoothing + + requests.append(params) + (sink, self.dest_id) = self.parameterAsSink(parameters, self.OUT, context, self.isochrones.get_fields(), diff --git a/ORStools/proc/isochrones_point_proc.py b/ORStools/proc/isochrones_point_proc.py index f1594ece..930523de 100644 --- a/ORStools/proc/isochrones_point_proc.py +++ b/ORStools/proc/isochrones_point_proc.py @@ -33,6 +33,8 @@ QgsProcessingParameterString, QgsProcessingParameterEnum, QgsProcessingParameterPoint, + QgsProcessingParameterNumber, + QgsProcessingParameterDefinition ) from ORStools.common import isochrones_core, PROFILES, DIMENSIONS @@ -51,6 +53,7 @@ def __init__(self): self.IN_RANGES = 'INPUT_RANGES' self.IN_KEY = 'INPUT_APIKEY' self.IN_DIFFERENCE = 'INPUT_DIFFERENCE' + self.IN_SMOOTHING = 'INPUT_SMOOTHING' self.PARAMETERS = [ QgsProcessingParameterPoint( name=self.IN_POINT, @@ -67,9 +70,21 @@ def __init__(self): name=self.IN_RANGES, description=self.tr("Comma-separated ranges [min or m]"), defaultValue="5, 10" - ) + ), + QgsProcessingParameterNumber( + name=self.IN_SMOOTHING, + description=self.tr("Smoothing factor between 0 [detailed] and 100 [generalized]"), + defaultValue=None, + minValue=0, + maxValue=100, + optional=True + ), ] + # Set flag of smoothness parameters to advanced + smooth_param = next((i for i in self.PARAMETERS if i.name() == self.IN_SMOOTHING), None) + smooth_param.setFlags(smooth_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) + # Save some important references # TODO bad style, refactor isochrones = isochrones_core.Isochrones() @@ -88,6 +103,7 @@ def processAlgorithm(self, parameters, context, feedback): factor = 60 if dimension == 'time' else 1 ranges_raw = parameters[self.IN_RANGES] ranges_proc = [x * factor for x in map(int, ranges_raw.split(','))] + smoothing = parameters[self.IN_SMOOTHING] options = self.parseOptions(parameters, context) @@ -102,9 +118,12 @@ def processAlgorithm(self, parameters, context, feedback): "range": ranges_proc, "attributes": ['total_pop'], "id": None, - "options": options + "options": options, } + if smoothing or smoothing == 0: + params["smoothing"] = smoothing + (sink, self.dest_id) = self.parameterAsSink(parameters, self.OUT, context, self.isochrones.get_fields(), QgsWkbTypes.Polygon,