[Git][debian-gis-team/saga][master] 4 commits: New upstream version 9.9.3+dfsg

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Mon Oct 6 15:40:41 BST 2025



Bas Couwenberg pushed to branch master at Debian GIS Project / saga


Commits:
6db93e88 by Bas Couwenberg at 2025-10-06T16:32:28+02:00
New upstream version 9.9.3+dfsg
- - - - -
269c67b1 by Bas Couwenberg at 2025-10-06T16:32:38+02:00
Update upstream source from tag 'upstream/9.9.3+dfsg'

Update to upstream version '9.9.3+dfsg'
with Debian dir 567dac747974bcb9a16ec7818c881c57ff906584
- - - - -
ab74eeea by Bas Couwenberg at 2025-10-06T16:33:27+02:00
New upstream release.

- - - - -
f14b4859 by Bas Couwenberg at 2025-10-06T16:33:58+02:00
Set distribution to unstable.

- - - - -


20 changed files:

- debian/changelog
- saga-gis/src/accessories/helper/doxygen_saga_api_chm
- saga-gis/src/accessories/helper/doxygen_saga_api_html
- saga-gis/src/accessories/helper/make_saga_release.bat
- saga-gis/src/accessories/helper/saga_setup_x64.iss
- saga-gis/src/accessories/python/tools/climate_tools.py
- saga-gis/src/accessories/python/tools/io_webservices.py
- saga-gis/src/accessories/python/tools/shapes_polygons.py
- saga-gis/src/accessories/python/tools/ta_lighting.py
- saga-gis/src/saga_core/saga_api/dataobject.cpp
- saga-gis/src/saga_core/saga_api/grids.cpp
- saga-gis/src/saga_core/saga_api/metadata.cpp
- saga-gis/src/saga_core/saga_api/saga_api.h
- saga-gis/src/saga_core/saga_cmd/man/saga_cmd.1
- saga-gis/src/saga_core/saga_gui/man/saga_gui.1
- saga-gis/src/tools/io/io_webservices/global_tiles.cpp
- saga-gis/src/tools/shapes/shapes_grid/Grid_To_Contour.cpp
- saga-gis/src/tools/shapes/shapes_polygons/polygon_generalization.cpp
- saga-gis/src/tools/shapes/shapes_polygons/polygon_generalization.h
- saga-gis/version.cmake


Changes:

=====================================
debian/changelog
=====================================
@@ -1,9 +1,10 @@
-saga (9.9.2+dfsg-2) UNRELEASED; urgency=medium
+saga (9.9.3+dfsg-1) unstable; urgency=medium
 
   * Team upload.
+  * New upstream release.
   * Drop Rules-Requires-Root: no, default since dpkg 1.22.13.
 
- -- Bas Couwenberg <sebastic at debian.org>  Wed, 01 Oct 2025 08:53:06 +0200
+ -- Bas Couwenberg <sebastic at debian.org>  Mon, 06 Oct 2025 16:33:50 +0200
 
 saga (9.9.2+dfsg-1) unstable; urgency=medium
 


=====================================
saga-gis/src/accessories/helper/doxygen_saga_api_chm
=====================================
@@ -38,7 +38,7 @@ PROJECT_NAME           = "SAGA API"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-#PROJECT_NUMBER        = v9.9.2 # omit patch number
+#PROJECT_NUMBER        = v9.9.3 # omit patch number
 PROJECT_NUMBER         = v9.9
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
@@ -59,7 +59,7 @@ PROJECT_LOGO           = ../../../saga_core/saga_gui/res/saga_icon_64.png
 # entered, it will be relative to the location where doxygen was started. If
 # left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = saga-9.9.2_api_doc
+OUTPUT_DIRECTORY       = saga-9.9.3_api_doc
 
 # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
 # directories (in 2 levels) under the output directory of each output format and
@@ -1372,7 +1372,7 @@ GENERATE_HTMLHELP      = YES
 # written to the html output directory.
 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
-CHM_FILE               = ../../saga-9.9.2_api.chm
+CHM_FILE               = ../../saga-9.9.3_api.chm
 
 # The HHC_LOCATION tag can be used to specify the location (absolute path
 # including file name) of the HTML help compiler (hhc.exe). If non-empty,


=====================================
saga-gis/src/accessories/helper/doxygen_saga_api_html
=====================================
@@ -38,7 +38,7 @@ PROJECT_NAME           = "SAGA API"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-#PROJECT_NUMBER        = v9.9.2 # omit patch number
+#PROJECT_NUMBER        = v9.9.3 # omit patch number
 PROJECT_NUMBER         = v9.9
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
@@ -59,7 +59,7 @@ PROJECT_LOGO           = ../../../saga_core/saga_gui/res/saga_icon_64.png
 # entered, it will be relative to the location where doxygen was started. If
 # left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = saga-9.9.2_api_doc
+OUTPUT_DIRECTORY       = saga-9.9.3_api_doc
 
 # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
 # directories (in 2 levels) under the output directory of each output format and
@@ -1372,7 +1372,7 @@ GENERATE_HTMLHELP      = NO
 # written to the html output directory.
 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
-CHM_FILE               = ../../saga-9.9.2_api.chm
+CHM_FILE               = ../../saga-9.9.3_api.chm
 
 # The HHC_LOCATION tag can be used to specify the location (absolute path
 # including file name) of the HTML help compiler (hhc.exe). If non-empty,


=====================================
saga-gis/src/accessories/helper/make_saga_release.bat
=====================================
@@ -30,9 +30,9 @@ REM ___________________________________
 REM Version
 
 SET SAGA_VERSION=9.9
-SET SAGA_RELEASE=9.9.2
+SET SAGA_RELEASE=9.9.3
 SET SAGA_VERSION_NEXT=9.9
-SET SAGA_RELEASE_NEXT=9.9.3
+SET SAGA_RELEASE_NEXT=9.9.4
 SET SAGA_RELEASE_NAME=saga-%SAGA_RELEASE%
 
 REM !!! For all bug-fix-releases !!!


=====================================
saga-gis/src/accessories/helper/saga_setup_x64.iss
=====================================
@@ -1,5 +1,5 @@
-; To build installer (for example, saga-9.9.2_setup.exe).
-; - Unzip the SAGA binary files in their own folder (for example, saga-9.9.2.zip).
+; To build installer (for example, saga-9.9.3_setup.exe).
+; - Unzip the SAGA binary files in their own folder (for example, saga-9.9.3.zip).
 ; - Place saga.iss and saga_readme.rtf in the SAGA folder (contains saga_gui.exe, etc.).
 ; - Open saga.iss in Inno Setup.
 ; - Choose Build | Compile.
@@ -7,7 +7,7 @@
 
 [Setup]
 AppName=SAGA - System for Automated Geoscientific Analyses
-AppVerName=SAGA 9.9.2
+AppVerName=SAGA 9.9.3
 
 ArchitecturesAllowed=x64
 ArchitecturesInstallIn64BitMode=x64
@@ -22,9 +22,9 @@ Compression=lzma
 SolidCompression=yes
 
 OutputDir=.
-OutputBaseFilename=saga-9.9.2_x64_setup
+OutputBaseFilename=saga-9.9.3_x64_setup
 
-VersionInfoVersion=9.9.2.0
+VersionInfoVersion=9.9.3.0
 VersionInfoCompany=SAGA User Group Association
 VersionInfoCopyright=(c) 2005-2023 by O. Conrad
 VersionInfoDescription=SAGA single-file installer
@@ -51,5 +51,5 @@ Name: "{commondesktop}\SAGA"; Filename: "{app}\saga_gui.exe"; WorkingDir: "{app}
 Root: HKLM; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\saga_gui.exe"; ValueType: string; ValueName: ""; ValueData: "{app}\saga_gui.exe"; Flags: uninsdeletekey
 Root: HKLM; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\saga_gui.exe"; ValueType: string; ValueName: "Path"; ValueData: "{app}"
 
-Root: HKLM; Subkey: "SOFTWARE\SAGA User Group Association\SAGA\9.9.2"; ValueType: string; ValueName: "InstallDir"; ValueData: "{app}"; Flags: uninsdeletekey
-Root: HKLM; Subkey: "SOFTWARE\SAGA User Group Association\SAGA\9.9.2"; ValueType: string; ValueName: "Version"; ValueData: "9.9.2.0"
+Root: HKLM; Subkey: "SOFTWARE\SAGA User Group Association\SAGA\9.9.3"; ValueType: string; ValueName: "InstallDir"; ValueData: "{app}"; Flags: uninsdeletekey
+Root: HKLM; Subkey: "SOFTWARE\SAGA User Group Association\SAGA\9.9.3"; ValueType: string; ValueName: "Version"; ValueData: "9.9.3.0"


=====================================
saga-gis/src/accessories/python/tools/climate_tools.py
=====================================
@@ -775,8 +775,8 @@ def Evapotranspiration_Grid(
     - SR_EST [`boolean`] : Estimate Solar Radiation. Default: 0 Estimate solar radiation from date, latitudinal position and sunshine duration as percentage of its potential maximum.
     - SUNSHINE [`floating point number`] : Sunshine Duration. Minimum: 0.000000 Maximum: 100.000000 Default: 50.000000 Daily sunshine duration as percentage of its potential maximum.
     - TIME [`choice`] : Time. Available Choices: [0] day [1] month Default: 0
-    - MONTH [`choice`] : Month. Available Choices: [0] January [1] February [2] March [3] April [4] May [5] June [6] July [7] August [8] September [9] October [10] November [11] December Default: 8
-    - DAY [`integer number`] : Day of Month. Minimum: 1 Maximum: 31 Default: 16
+    - MONTH [`choice`] : Month. Available Choices: [0] January [1] February [2] March [3] April [4] May [5] June [6] July [7] August [8] September [9] October [10] November [11] December Default: 9
+    - DAY [`integer number`] : Day of Month. Minimum: 1 Maximum: 31 Default: 6
     - LAT [`floating point number`] : Latitude. Minimum: -90.000000 Maximum: 90.000000 Default: 53.000000 [Degree]
 
     - Verbose [`integer number`] : Verbosity level, 0=silent, 1=tool name and success notification, 2=complete tool output.\n
@@ -860,8 +860,8 @@ def run_tool_climate_tools_8(
     - SR_EST [`boolean`] : Estimate Solar Radiation. Default: 0 Estimate solar radiation from date, latitudinal position and sunshine duration as percentage of its potential maximum.
     - SUNSHINE [`floating point number`] : Sunshine Duration. Minimum: 0.000000 Maximum: 100.000000 Default: 50.000000 Daily sunshine duration as percentage of its potential maximum.
     - TIME [`choice`] : Time. Available Choices: [0] day [1] month Default: 0
-    - MONTH [`choice`] : Month. Available Choices: [0] January [1] February [2] March [3] April [4] May [5] June [6] July [7] August [8] September [9] October [10] November [11] December Default: 8
-    - DAY [`integer number`] : Day of Month. Minimum: 1 Maximum: 31 Default: 16
+    - MONTH [`choice`] : Month. Available Choices: [0] January [1] February [2] March [3] April [4] May [5] June [6] July [7] August [8] September [9] October [10] November [11] December Default: 9
+    - DAY [`integer number`] : Day of Month. Minimum: 1 Maximum: 31 Default: 6
     - LAT [`floating point number`] : Latitude. Minimum: -90.000000 Maximum: 90.000000 Default: 53.000000 [Degree]
 
     - Verbose [`integer number`] : Verbosity level, 0=silent, 1=tool name and success notification, 2=complete tool output.\n
@@ -914,7 +914,7 @@ def Sunrise_and_Sunset(
     - SUNRISE [`output grid`] : Sunrise
     - SUNSET [`output grid`] : Sunset
     - LENGTH [`output grid`] : Day Length
-    - DAY [`date`] : Day of Month. Default: 2025-09-16
+    - DAY [`date`] : Day of Month. Default: 2025-10-06
     - TIME [`choice`] : Time. Available Choices: [0] local [1] world Default: 0
 
     - Verbose [`integer number`] : Verbosity level, 0=silent, 1=tool name and success notification, 2=complete tool output.\n
@@ -951,7 +951,7 @@ def run_tool_climate_tools_9(
     - SUNRISE [`output grid`] : Sunrise
     - SUNSET [`output grid`] : Sunset
     - LENGTH [`output grid`] : Day Length
-    - DAY [`date`] : Day of Month. Default: 2025-09-16
+    - DAY [`date`] : Day of Month. Default: 2025-10-06
     - TIME [`choice`] : Time. Available Choices: [0] local [1] world Default: 0
 
     - Verbose [`integer number`] : Verbosity level, 0=silent, 1=tool name and success notification, 2=complete tool output.\n
@@ -2449,7 +2449,7 @@ def PhenIps_Grids_Days(
     - YD_END_ONSET [`date`] : End of Breeding. Default: 2025-08-31
     - YD_END [`date`] : End of Development. Default: 2025-10-31
     - RESET [`boolean`] : Reset. Default: 1
-    - DAY [`date`] : Start Day. Default: 2025-09-16
+    - DAY [`date`] : Start Day. Default: 2025-10-06
 
     - Verbose [`integer number`] : Verbosity level, 0=silent, 1=tool name and success notification, 2=complete tool output.\n
     Returns
@@ -2570,7 +2570,7 @@ def run_tool_climate_tools_23(
     - YD_END_ONSET [`date`] : End of Breeding. Default: 2025-08-31
     - YD_END [`date`] : End of Development. Default: 2025-10-31
     - RESET [`boolean`] : Reset. Default: 1
-    - DAY [`date`] : Start Day. Default: 2025-09-16
+    - DAY [`date`] : Start Day. Default: 2025-10-06
 
     - Verbose [`integer number`] : Verbosity level, 0=silent, 1=tool name and success notification, 2=complete tool output.\n
     Returns
@@ -2653,7 +2653,7 @@ def Soil_Water_Balance_Days(
     - SWC_SURFACE [`floating point number`] : Top Soil Water Capacity. Minimum: 0.000000 Default: 30.000000
     - SWT_RESIST [`floating point number`] : Transpiration Resistance. Minimum: 0.010000 Default: 0.500000
     - RESET [`boolean`] : Reset. Default: 1
-    - DAY [`date`] : Start Day. Default: 2025-09-16
+    - DAY [`date`] : Start Day. Default: 2025-10-06
 
     - Verbose [`integer number`] : Verbosity level, 0=silent, 1=tool name and success notification, 2=complete tool output.\n
     Returns
@@ -2717,7 +2717,7 @@ def run_tool_climate_tools_24(
     - SWC_SURFACE [`floating point number`] : Top Soil Water Capacity. Minimum: 0.000000 Default: 30.000000
     - SWT_RESIST [`floating point number`] : Transpiration Resistance. Minimum: 0.010000 Default: 0.500000
     - RESET [`boolean`] : Reset. Default: 1
-    - DAY [`date`] : Start Day. Default: 2025-09-16
+    - DAY [`date`] : Start Day. Default: 2025-10-06
 
     - Verbose [`integer number`] : Verbosity level, 0=silent, 1=tool name and success notification, 2=complete tool output.\n
     Returns
@@ -3468,8 +3468,8 @@ def Daily_Solar_Radiation(
     ----------
     - LATITUDE [`input grid`] : Latitude. [Degree]
     - SOLARRAD [`output grid`] : Solar Radiation. [J/cm²]
-    - MONTH [`choice`] : Month. Available Choices: [0] January [1] February [2] March [3] April [4] May [5] June [6] July [7] August [8] September [9] October [10] November [11] December Default: 8
-    - DAY [`integer number`] : Day of Month. Minimum: 1 Maximum: 31 Default: 16
+    - MONTH [`choice`] : Month. Available Choices: [0] January [1] February [2] March [3] April [4] May [5] June [6] July [7] August [8] September [9] October [10] November [11] December Default: 9
+    - DAY [`integer number`] : Day of Month. Minimum: 1 Maximum: 31 Default: 6
     - SUNSHINE [`floating point number`] : Sunshine Duration. Minimum: 0.000000 Maximum: 100.000000 Default: 50.000000 Daily sunshine duration as percentage of its potential maximum.
 
     - Verbose [`integer number`] : Verbosity level, 0=silent, 1=tool name and success notification, 2=complete tool output.\n
@@ -3503,8 +3503,8 @@ def run_tool_climate_tools_31(
     ----------
     - LATITUDE [`input grid`] : Latitude. [Degree]
     - SOLARRAD [`output grid`] : Solar Radiation. [J/cm²]
-    - MONTH [`choice`] : Month. Available Choices: [0] January [1] February [2] March [3] April [4] May [5] June [6] July [7] August [8] September [9] October [10] November [11] December Default: 8
-    - DAY [`integer number`] : Day of Month. Minimum: 1 Maximum: 31 Default: 16
+    - MONTH [`choice`] : Month. Available Choices: [0] January [1] February [2] March [3] April [4] May [5] June [6] July [7] August [8] September [9] October [10] November [11] December Default: 9
+    - DAY [`integer number`] : Day of Month. Minimum: 1 Maximum: 31 Default: 6
     - SUNSHINE [`floating point number`] : Sunshine Duration. Minimum: 0.000000 Maximum: 100.000000 Default: 50.000000 Daily sunshine duration as percentage of its potential maximum.
 
     - Verbose [`integer number`] : Verbosity level, 0=silent, 1=tool name and success notification, 2=complete tool output.\n


=====================================
saga-gis/src/accessories/python/tools/io_webservices.py
=====================================
@@ -427,8 +427,8 @@ def USGS_Earthquake_Catalog(
     - SHAPES [`input shapes`] : Shapes
     - GRID [`optional input grid`] : Grid
     - EARTHQUAKES [`output shapes`] : Earthquakes
-    - DATE_START [`date`] : Start. Default: 2025-09-09
-    - DATE_END [`date`] : End. Default: 2025-09-16
+    - DATE_START [`date`] : Start. Default: 2025-09-29
+    - DATE_END [`date`] : End. Default: 2025-10-06
     - MAGNITUDE [`value range`] : Magnitude
     - EXTENT [`choice`] : Extent. Available Choices: [0] user defined [1] shapes extent [2] grid system extent Default: 0
     - GRID_SYSTEM [`grid system`] : Grid System
@@ -488,8 +488,8 @@ def run_tool_io_webservices_5(
     - SHAPES [`input shapes`] : Shapes
     - GRID [`optional input grid`] : Grid
     - EARTHQUAKES [`output shapes`] : Earthquakes
-    - DATE_START [`date`] : Start. Default: 2025-09-09
-    - DATE_END [`date`] : End. Default: 2025-09-16
+    - DATE_START [`date`] : Start. Default: 2025-09-29
+    - DATE_END [`date`] : End. Default: 2025-10-06
     - MAGNITUDE [`value range`] : Magnitude
     - EXTENT [`choice`] : Extent. Available Choices: [0] user defined [1] shapes extent [2] grid system extent Default: 0
     - GRID_SYSTEM [`grid system`] : Grid System


=====================================
saga-gis/src/accessories/python/tools/shapes_polygons.py
=====================================
@@ -1599,7 +1599,7 @@ def Polygon_Generalization(
     Polygon Generalization
     ----------
     [shapes_polygons.23]\n
-    A simple generalization tool for polygons. The tool joins polygons with an area size smaller than the specified threshold to a neighbouring polygon. Either the neighbouring polygon with the largest area or the one with which the largest edge length is shared wins.\n
+    A simple generalization tool for polygons. The tool joins polygons with an area size smaller than the specified threshold to a neighbouring polygon. Either the neighbouring polygon with the largest area or the one with the longest shared edge wins.\n
     Arguments
     ----------
     - POLYGONS [`input shapes`] : Shapes. The input polygons.
@@ -1636,7 +1636,7 @@ def run_tool_shapes_polygons_23(
     Polygon Generalization
     ----------
     [shapes_polygons.23]\n
-    A simple generalization tool for polygons. The tool joins polygons with an area size smaller than the specified threshold to a neighbouring polygon. Either the neighbouring polygon with the largest area or the one with which the largest edge length is shared wins.\n
+    A simple generalization tool for polygons. The tool joins polygons with an area size smaller than the specified threshold to a neighbouring polygon. Either the neighbouring polygon with the largest area or the one with the longest shared edge wins.\n
     Arguments
     ----------
     - POLYGONS [`input shapes`] : Shapes. The input polygons.


=====================================
saga-gis/src/accessories/python/tools/ta_lighting.py
=====================================
@@ -41,7 +41,7 @@ def Analytical_Hillshading(
     - POSITION [`choice`] : Sun's Position. Available Choices: [0] azimuth and height [1] date and time Default: 0
     - AZIMUTH [`floating point number`] : Azimuth. Minimum: 0.000000 Maximum: 360.000000 Default: 315.000000 Direction of the light source, measured in degree clockwise from the North direction.
     - DECLINATION [`floating point number`] : Height. Minimum: 0.000000 Maximum: 90.000000 Default: 45.000000 Height of the light source, measured in degree above the horizon.
-    - DATE [`date`] : Day. Default: 2025-09-16
+    - DATE [`date`] : Day. Default: 2025-10-06
     - TIME [`floating point number`] : Hour. Minimum: 0.000000 Maximum: 24.000000 Default: 12.000000
     - EXAGGERATION [`floating point number`] : Exaggeration. Default: 1.000000 The terrain exaggeration factor allows one to increase the shading contrasts in flat areas.
     - UNIT [`choice`] : Unit. Available Choices: [0] radians [1] degree Default: 0
@@ -99,7 +99,7 @@ def run_tool_ta_lighting_0(
     - POSITION [`choice`] : Sun's Position. Available Choices: [0] azimuth and height [1] date and time Default: 0
     - AZIMUTH [`floating point number`] : Azimuth. Minimum: 0.000000 Maximum: 360.000000 Default: 315.000000 Direction of the light source, measured in degree clockwise from the North direction.
     - DECLINATION [`floating point number`] : Height. Minimum: 0.000000 Maximum: 90.000000 Default: 45.000000 Height of the light source, measured in degree above the horizon.
-    - DATE [`date`] : Day. Default: 2025-09-16
+    - DATE [`date`] : Day. Default: 2025-10-06
     - TIME [`floating point number`] : Hour. Minimum: 0.000000 Maximum: 24.000000 Default: 12.000000
     - EXAGGERATION [`floating point number`] : Exaggeration. Default: 1.000000 The terrain exaggeration factor allows one to increase the shading contrasts in flat areas.
     - UNIT [`choice`] : Unit. Available Choices: [0] radians [1] degree Default: 0
@@ -193,8 +193,8 @@ def Potential_Incoming_Solar_Radiation(
     - LOCATION [`choice`] : Location. Available Choices: [0] constant latitude [1] calculate from grid system Default: 0
     - LATITUDE [`degree`] : Latitude. Minimum: -90.000000 Maximum: 90.000000 Default: 53.000000
     - PERIOD [`choice`] : Time Period. Available Choices: [0] moment [1] day [2] range of days Default: 1 Momentum output will be in units of power [W/m²], time span will be in units of energy, either [kWh/m²], [kJ/m²], or [J/cm²].
-    - DAY [`date`] : Day. Default: 2025-09-16
-    - DAY_STOP [`date`] : Last Day. Default: 2025-09-16
+    - DAY [`date`] : Day. Default: 2025-10-06
+    - DAY_STOP [`date`] : Last Day. Default: 2025-10-06
     - DAYS_STEP [`integer number`] : Resolution [d]. Minimum: 1 Default: 5 Time step size for a range of days calculation given in days.
     - MOMENT [`floating point number`] : Moment [h]. Minimum: 0.000000 Maximum: 24.000000 Default: 12.000000
     - HOUR_RANGE [`value range`] : Time Span [h]. Time span used for the calculation of daily radiation sums.
@@ -312,8 +312,8 @@ def run_tool_ta_lighting_2(
     - LOCATION [`choice`] : Location. Available Choices: [0] constant latitude [1] calculate from grid system Default: 0
     - LATITUDE [`degree`] : Latitude. Minimum: -90.000000 Maximum: 90.000000 Default: 53.000000
     - PERIOD [`choice`] : Time Period. Available Choices: [0] moment [1] day [2] range of days Default: 1 Momentum output will be in units of power [W/m²], time span will be in units of energy, either [kWh/m²], [kJ/m²], or [J/cm²].
-    - DAY [`date`] : Day. Default: 2025-09-16
-    - DAY_STOP [`date`] : Last Day. Default: 2025-09-16
+    - DAY [`date`] : Day. Default: 2025-10-06
+    - DAY_STOP [`date`] : Last Day. Default: 2025-10-06
     - DAYS_STEP [`integer number`] : Resolution [d]. Minimum: 1 Default: 5 Time step size for a range of days calculation given in days.
     - MOMENT [`floating point number`] : Moment [h]. Minimum: 0.000000 Maximum: 24.000000 Default: 12.000000
     - HOUR_RANGE [`value range`] : Time Span [h]. Time span used for the calculation of daily radiation sums.


=====================================
saga-gis/src/saga_core/saga_api/dataobject.cpp
=====================================
@@ -374,15 +374,19 @@ void CSG_Data_Object::Set_File_Name(const CSG_String &FileName, bool bNative)
 	if( FileName.is_Empty() )
 	{
 		m_FileName      .Clear();
-		m_File_bNative	= false;
-		m_bModified		= true;
+		m_File_bNative = false;
+		m_bModified    = true;
 	}
 	else
 	{
-		m_FileName		= FileName;
-		m_File_bNative	= bNative;
-		m_bModified		= false;
-		m_Name			= SG_File_Get_Name(FileName, false);
+		m_FileName     = FileName;
+		m_File_bNative = bNative;
+		m_bModified    = false;
+
+		if( m_Name.is_Empty() || m_Name.Cmp(_TL("Data")) == 0 )
+		{
+			m_Name = SG_File_Get_Name(FileName, false);
+		}
 	}
 }
 


=====================================
saga-gis/src/saga_core/saga_api/grids.cpp
=====================================
@@ -1775,8 +1775,6 @@ bool CSG_Grids::Load(const CSG_String &File, bool bLoadData)
 	{
 		Set_Modified(false);
 
-		Set_Name(SG_File_Get_Name(File, false));
-
 		SG_UI_Process_Set_Ready();
 		SG_UI_Msg_Add(_TL("okay"), false, SG_UI_MSG_STYLE_SUCCESS);
 
@@ -1948,6 +1946,8 @@ bool CSG_Grids::_Load_PGSQL(const CSG_String &File)
 
 				Set_File_Name(File);
 
+				Set_Name(SG_File_Get_Name(File, false));
+
 				Create(pGrids);
 
 				for(int i=0; i<pGrids->Get_Grid_Count(); i++)
@@ -1975,6 +1975,8 @@ bool CSG_Grids::_Load_PGSQL(const CSG_String &File)
 //---------------------------------------------------------
 bool CSG_Grids::_Load_Normal(const CSG_String &_File)
 {
+	Set_File_Name(_File, true);
+
 	if( !SG_File_Cmp_Extension(_File, "sg-gds") ) // GRIDS_FILETYPE_Normal
 	{
 		return( false );
@@ -2008,8 +2010,6 @@ bool CSG_Grids::_Load_Normal(const CSG_String &_File)
 	}
 
 	//-----------------------------------------------------
-	Set_File_Name(_File, true);
-
 	Load_MetaData(File);
 
 	Get_Projection().Load(SG_File_Make_Path("", File, "sg-prj"));
@@ -2064,6 +2064,8 @@ bool CSG_Grids::_Save_Normal(const CSG_String &_File)
 //---------------------------------------------------------
 bool CSG_Grids::_Load_Compressed(const CSG_String &_File)
 {
+	Set_File_Name(_File, true);
+
 	if( !SG_File_Cmp_Extension(_File, "sg-gds-z") ) // GRIDS_FILETYPE_Compressed
 	{
 		return( false );
@@ -2071,8 +2073,22 @@ bool CSG_Grids::_Load_Compressed(const CSG_String &_File)
 
 	CSG_Archive Stream(_File, SG_FILE_R);
 
+	//-----------------------------------------------------
 	CSG_String File(SG_File_Get_Name(_File, false) + ".");
 
+	if( !Stream.Get_File(File + "sg-gds") )
+	{
+		File.Clear();
+
+		for(size_t i=0; File.is_Empty() && i<Stream.Get_File_Count(); i++)
+		{
+			if( SG_File_Cmp_Extension(Stream.Get_File_Name(i), "sg-gds") )
+			{
+				File = SG_File_Get_Name(Stream.Get_File_Name(i), false) + ".";
+			}
+		}
+	}
+
 	//-----------------------------------------------------
 	if( !Stream.Get_File(File + "sg-gds") || !_Load_Header(Stream) )
 	{
@@ -2095,8 +2111,6 @@ bool CSG_Grids::_Load_Compressed(const CSG_String &_File)
 	}
 
 	//-----------------------------------------------------
-	Set_File_Name(_File, true);
-
 	if( Stream.Get_File(File + "sg-info") )
 	{
 		Load_MetaData(Stream);
@@ -2159,7 +2173,7 @@ bool CSG_Grids::_Save_Compressed(const CSG_String &_File)
 //---------------------------------------------------------
 bool CSG_Grids::_Load_Header(CSG_File &Stream)
 {
-	CSG_MetaData	Header;
+	CSG_MetaData Header;
 
 	if( !Header.Load(Stream) )
 	{
@@ -2177,7 +2191,7 @@ bool CSG_Grids::_Load_Header(CSG_File &Stream)
 		Header["NX"  ].Get_Content().asInt   (), Header["NY"  ].Get_Content().asInt   ()
 	);
 
-	TSG_Data_Type	Type	= SG_Data_Type_Get_Type(Header["TYPE"].Get_Content());
+	TSG_Data_Type Type = SG_Data_Type_Get_Type(Header["TYPE"].Get_Content());
 
 	if( !System.is_Valid() || Type == SG_DATATYPE_Undefined || !m_pGrids[0]->Create(System, Type) )
 	{
@@ -2185,9 +2199,9 @@ bool CSG_Grids::_Load_Header(CSG_File &Stream)
 	}
 
 	//-----------------------------------------------------
-	if( Header("NAME"       ) ) Set_Name       (Header["NAME"       ].Get_Content());
-	if( Header("DESCRIPTION") ) Set_Description(Header["DESCRIPTION"].Get_Content());
-	if( Header("UNIT"       ) ) Set_Unit       (Header["UNIT"       ].Get_Content());
+	if( Header("NAME"       ) ) { Set_Name       (Header["NAME"       ].Get_Content()); } else { Set_Name(SG_File_Get_Name(Stream.Get_File_Name(), false)); }
+	if( Header("DESCRIPTION") ) { Set_Description(Header["DESCRIPTION"].Get_Content()); }
+	if( Header("UNIT"       ) ) { Set_Unit       (Header["UNIT"       ].Get_Content()); }
 
 	Set_Scaling(
 		Header("SCALE" ) ? Header["SCALE" ].Get_Content().asDouble() : 1.,
@@ -2216,7 +2230,7 @@ bool CSG_Grids::_Load_Header(CSG_File &Stream)
 
 	if( Header("ATTRIBUTES") && Header["ATTRIBUTES"]("FIELDS") == NULL )
 	{
-		const CSG_MetaData	&Fields	= Header["ATTRIBUTES"];
+		const CSG_MetaData &Fields = Header["ATTRIBUTES"];
 
 		for(int iField=0; iField<Fields.Get_Children_Count(); iField++)
 		{
@@ -2228,12 +2242,12 @@ bool CSG_Grids::_Load_Header(CSG_File &Stream)
 
 		if( !Fields.Get_Property("Z_FIELD", m_Z_Attribute) || m_Z_Attribute >= m_Attributes.Get_Field_Count() )
 		{
-			m_Z_Attribute	= 0;
+			m_Z_Attribute = 0;
 		}
 
 		if( !Fields.Get_Property("Z_NAME", m_Z_Name      ) || m_Z_Name      >= m_Attributes.Get_Field_Count() )
 		{
-			m_Z_Name	= -1;	// same as m_Z_Attribute
+			m_Z_Name = -1;	// same as m_Z_Attribute
 		}
 	}
 
@@ -2243,14 +2257,12 @@ bool CSG_Grids::_Load_Header(CSG_File &Stream)
 	{
 		if( !Header["ATTRIBUTES"].Get_Property("ZATTRIBUTE", m_Z_Attribute) )
 		{
-			m_Z_Attribute	= 0;
+			m_Z_Attribute = 0;
 		}
 
-		int		iField;
-
 		const CSG_MetaData	&Fields	= Header["ATTRIBUTES"]["FIELDS"];
 
-		for(iField=0; iField<Fields.Get_Children_Count(); iField++)
+		for(int iField=0; iField<Fields.Get_Children_Count(); iField++)
 		{
 			if( Fields[iField].Cmp_Name("FIELD") && Fields[iField].Get_Property("TYPE") )
 			{
@@ -2260,19 +2272,19 @@ bool CSG_Grids::_Load_Header(CSG_File &Stream)
 
 		if( m_Attributes.Get_Field_Count() > 0 && Header["ATTRIBUTES"]("RECORDS") )
 		{
-			CSG_Table	Attributes(m_Attributes);
+			CSG_Table Attributes(m_Attributes);
 
-			const CSG_MetaData	&Records	= Header["ATTRIBUTES"]["RECORDS"];
+			const CSG_MetaData &Records = Header["ATTRIBUTES"]["RECORDS"];
 
 			for(int iRecord=0; iRecord<Records.Get_Children_Count(); iRecord++)
 			{
 				if( Records[iRecord].Cmp_Name("RECORD") )
 				{
-					CSG_String_Tokenizer	Values(Records[iRecord].Get_Content(), ";");
+					CSG_String_Tokenizer Values(Records[iRecord].Get_Content(), ";");
 
 					if( Values.Get_Tokens_Count() == (size_t)Attributes.Get_Field_Count() )
 					{
-						CSG_Table_Record	*pRecord	= Attributes.Add_Record();
+						CSG_Table_Record *pRecord = Attributes.Add_Record();
 
 						for(int iField=0; iField<m_Attributes.Get_Field_Count(); iField++)
 						{


=====================================
saga-gis/src/saga_core/saga_api/metadata.cpp
=====================================
@@ -1093,28 +1093,46 @@ bool CSG_MetaData::from_JSON(const CSG_String &JSON)
 
 	Set_Name("root");
 
-	CSG_MetaData	*pNode	= this;
-
-	const SG_Char	*pc	= JSON.c_str();
+	CSG_MetaData *pNode = this; const SG_Char *pc = JSON.c_str();
 
 	while( *pc )
 	{
-		CSG_String	Element;
+		CSG_String Element;
 
-		for(bool bQuota=false;;)
+		for(bool bQuota=false; *pc; )
 		{
 			SG_Char c = *pc++;
 			
-			if( !c || c == '\n' ) { break; } else
+			if( c == '\0' || c == ',' )
+			{
+				break;
+			}
+			else if( c == '{' || c == '[' )
+			{
+				Element += c;
+
+				break;
+			}
+			else if( c == '}' || c == ']' )
 			{
-				if( c == '\"' )
+				if( Element.is_Empty() )
 				{
-					Element += c; bQuota = !bQuota;
+					Element = c;
 				}
-				else if( bQuota || (c != ' ' && c != '\t' && c != ',') )
+				else
 				{
-					Element += c;
+					pc--;
 				}
+
+				break;
+			}
+			else if( c == '\"' )
+			{
+				Element += c; bQuota = !bQuota;
+			}
+			else if( bQuota || (c != ' ' && c != '\n' && c != '\t') )
+			{
+				Element += c;
 			}
 		}
 
@@ -1125,7 +1143,7 @@ bool CSG_MetaData::from_JSON(const CSG_String &JSON)
 		}
 		else if( Element.Find('[') >= 0 )	// array begins
 		{
-			pNode	= pNode->Add_Child(Element.AfterFirst('\"').BeforeFirst('\"'));
+			pNode = pNode->Add_Child(Element.AfterFirst('\"').BeforeFirst('\"'));
 
 			pNode->Add_Property("array", 1);
 		}
@@ -1133,40 +1151,40 @@ bool CSG_MetaData::from_JSON(const CSG_String &JSON)
 		{
 			if( pNode != this )
 			{
-				pNode	= pNode->Get_Parent();
+				pNode = pNode->Get_Parent();
 			}
 		}
 		else if( Element.Find('{') >= 0 )	// object begins
 		{
-			Element	= Element.AfterFirst('\"').BeforeFirst('\"');
+			Element = Element.AfterFirst('\"').BeforeFirst('\"');
 
 			if( !Element.is_Empty() )
 			{
-				pNode	= pNode->Add_Child(Element);
+				pNode = pNode->Add_Child(Element);
 			}
 			else if( pNode->Get_Property("array") )
 			{
-				pNode	= pNode->Add_Child(CSG_String::Format("%d", pNode->Get_Children_Count()));
+				pNode = pNode->Add_Child(CSG_String::Format("%d", pNode->Get_Children_Count()));
 			}
 		}
 		else if( Element.Find('}') >= 0 )	// object ends
 		{
 			if( pNode != this )
 			{
-				pNode	= pNode->Get_Parent();
+				pNode = pNode->Get_Parent();
 			}
 		}
 		else
 		{
-			CSG_String	Key  (Element.AfterFirst('\"').BeforeFirst('\"'));
-			CSG_String	Value(Element.AfterFirst(':'));
+			CSG_String key(Element.AfterFirst('\"').BeforeFirst('\"'));
+			CSG_String val(Element.AfterFirst(':')); val.Trim();
 
-			if( Value.Find('\"') > -1 )
+			if( val.Find('\"') == 0 )
 			{
-				Value	= Value.AfterFirst('\"').BeforeFirst('\"');
+				val = val.AfterFirst('\"').BeforeFirst('\"');
 			}
 
-			pNode->Add_Child(Key, Value);
+			pNode->Add_Child(key, val);
 		}
 	}
 
@@ -1174,9 +1192,35 @@ bool CSG_MetaData::from_JSON(const CSG_String &JSON)
 }
 
 //---------------------------------------------------------
-bool CSG_MetaData::to_JSON(CSG_String &JSON)	const
+bool CSG_MetaData::to_JSON(CSG_String &JSON) const
 {
-	return( false );
+	if( Get_Parent() )
+	{
+		JSON += "\"" + Get_Name() + "\": ";
+	}
+
+	if( Get_Children_Count() )
+	{
+		JSON += "{";
+
+		for(int i=0; i<Get_Children_Count(); i++)
+		{
+			if( i > 0 )
+			{
+				JSON += ",";
+			}
+
+			Get_Child(i)->to_JSON(JSON);
+		}
+
+		JSON += "}";
+	}
+	else
+	{
+		JSON += " \"" + Get_Content() + "\"";
+	}
+
+	return( true );
 }
 
 


=====================================
saga-gis/src/saga_core/saga_api/saga_api.h
=====================================
@@ -86,8 +86,8 @@
 //---------------------------------------------------------
 #define SAGA_MAJOR_VERSION		9
 #define SAGA_MINOR_VERSION		9
-#define SAGA_RELEASE_NUMBER		2
-#define SAGA_VERSION			SG_T("9.9.2")
+#define SAGA_RELEASE_NUMBER		3
+#define SAGA_VERSION			SG_T("9.9.3")
 
 
 ///////////////////////////////////////////////////////////


=====================================
saga-gis/src/saga_core/saga_cmd/man/saga_cmd.1
=====================================
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "SAGA_CMD 1"
-.TH SAGA_CMD 1 "2021-07-07" "9.9.2" " "
+.TH SAGA_CMD 1 "2021-07-07" "9.9.3" " "
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l


=====================================
saga-gis/src/saga_core/saga_gui/man/saga_gui.1
=====================================
@@ -124,7 +124,7 @@
 .\" ========================================================================
 .\"
 .IX Title "SAGA_GUI 1"
-.TH SAGA_GUI 1 "2021-07-07" "9.9.2" " "
+.TH SAGA_GUI 1 "2021-07-07" "9.9.3" " "
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l


=====================================
saga-gis/src/tools/io/io_webservices/global_tiles.cpp
=====================================
@@ -227,9 +227,11 @@ int CTiles_Provider::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Param
 
 		pParameters->Set_Enabled("CRS_PICKER", !Projection.is_Okay());
 
-		if( !Projection.is_Okay() )
+		if( !Projection.is_Okay() && (*pParameters)("CRS_PICKER") )
 		{
-			Projection.Create((*pParameters)("CRS_STRING")->asString());
+			CSG_Parameters &Picker = *(*pParameters)("CRS_PICKER")->asParameters();
+
+			Projection.Create(Picker["CRS_WKT"].asString(), Picker["CRS_PROJ"].asString());
 		}
 
 		pParameters->Set_Enabled("CELLSIZE", Projection.is_Projection());


=====================================
saga-gis/src/tools/shapes/shapes_grid/Grid_To_Contour.cpp
=====================================
@@ -389,6 +389,8 @@ bool CGrid_To_Contour::On_Execute(void)
 
 		if( Parameters("POLY_OMP")->asBool() )
 		{
+			m_pGrid->Update(true); // ensur statistics is up-to-date before entering parallelization! otherwise requesting e.g. grid's maximum value will likely be incorrect!
+
 			pPolygons->Set_Count(pContours->Get_Count() + 1);
 
 			#pragma omp parallel for


=====================================
saga-gis/src/tools/shapes/shapes_polygons/polygon_generalization.cpp
=====================================
@@ -47,7 +47,7 @@
 
 //---------------------------------------------------------
 #include "polygon_generalization.h"
-#include <vector>
+
 
 ///////////////////////////////////////////////////////////
 //														 //
@@ -67,30 +67,30 @@ CPolygon_Generalization::CPolygon_Generalization(void)
 		"The tool joins polygons with an area size smaller than "
 		"the specified threshold to a neighbouring polygon. "
 		"Either the neighbouring polygon with the largest area or "
-		"the one with which the largest edge length is shared wins."
+		"the one with the longest shared edge wins."
 	));
 
 	//-----------------------------------------------------
 	Parameters.Add_Shapes("",
-		"POLYGONS", _TL("Shapes"),
+		"POLYGONS"   , _TL("Shapes"),
 		_TL("The input polygons."),
 		PARAMETER_INPUT, SHAPE_TYPE_Polygon
 	);
 
 	Parameters.Add_Shapes("",
-		"GENERALIZED"	, _TL("Generalized Shapes"),
+		"GENERALIZED", _TL("Generalized Shapes"),
 		_TL("The generalized output polygons."),
 		PARAMETER_OUTPUT_OPTIONAL, SHAPE_TYPE_Polygon
 	);
 
 	Parameters.Add_Double("",
-		"THRESHOLD"	, _TL("Area Threshold"),
+		"THRESHOLD"  , _TL("Area Threshold"),
 		_TL("The maximum area of a polygon to get joined [map units squared]."),
 		100., 0., true
 	);
 
 	Parameters.Add_Choice("",
-		"JOIN_TO"	, _TL("Join to Neighbour with ..."),
+		"JOIN_TO"    , _TL("Join to Neighbour with ..."),
 		_TL("Choose the method to determine the winner polygon."),
 		CSG_String::Format("%s|%s",
 			_TL("largest area"),
@@ -99,13 +99,13 @@ CPolygon_Generalization::CPolygon_Generalization(void)
 	);
 
 	Parameters.Add_Bool("",
-		"VERTICES"	, _TL("Check Vertices"),
+		"VERTICES"   , _TL("Check Vertices"),
 		_TL(""),
 		false
 	);
 
 	Parameters.Add_Double("VERTICES",
-		"EPSILON"	, _TL("Tolerance"),
+		"EPSILON"    , _TL("Tolerance"),
 		_TL(""),
 		0.00001, 0., true
 	);
@@ -149,6 +149,13 @@ bool CPolygon_Generalization::On_Execute(void)
 		return( false );
 	}
 
+	if( pPolygons->Get_Count() <= 1 )
+	{
+		Error_Set(_TL("nothing to join"));
+
+		return( false );
+	}
+
 	//-----------------------------------------------------
 	if( Parameters("GENERALIZED")->asShapes() && Parameters("GENERALIZED")->asShapes() != pPolygons )
 	{
@@ -162,25 +169,14 @@ bool CPolygon_Generalization::On_Execute(void)
 	}
 
 	//-----------------------------------------------------
-	sLong i = 0, n = pPolygons->Get_Count();
-
-	do
-	{
-		Process_Set_Text(CSG_String::Format("%s %lld", _TL("pass"), ++i));
-	}
-	while( Set_JoinTos(pPolygons) && Process_Get_Okay() );
+	bool bResult = Set_Joins(pPolygons);
 
-	//-----------------------------------------------------
 	if( pPolygons == Parameters("POLYGONS")->asShapes() )
 	{	// output is always updated automatically - but if input has been modified, this needs a manual update!
 		DataObject_Update(pPolygons);
 	}
 
-	n -= pPolygons->Get_Count();
-
-	Message_Fmt("\n%s: %lld", _TL("total number of removed polygons"), n);
-
-	return( n > 0 );
+	return( bResult );
 }
 
 
@@ -189,58 +185,102 @@ bool CPolygon_Generalization::On_Execute(void)
 ///////////////////////////////////////////////////////////
 
 //---------------------------------------------------------
-bool CPolygon_Generalization::Set_JoinTos(CSG_Shapes *pPolygons)
+enum { FIELD_AREA = 0, FIELD_JOIN, FIELD_JOINS };
+
+//---------------------------------------------------------
+bool CPolygon_Generalization::Get_Joins(CSG_Shapes *pPolygons, CSG_Table &Joins)
 {
-	CSG_Array_sLong JoinTo;
+	double Threshold = Parameters["THRESHOLD"].asDouble();
 
-	if( !Get_JoinTos(pPolygons, JoinTo) )
+	if( Threshold <= 0. )
 	{
+		Error_Set(_TL("nothing to join, threshold should be greater zero"));
+
 		return( false );
 	}
 
-	sLong nCandidate = 0, nRemoved = 0;
+	//-----------------------------------------------------
+	Joins.Destroy();
+
+	Joins.Add_Field("AREA" , SG_DATATYPE_Double);
+	Joins.Add_Field("JOIN" , SG_DATATYPE_Long  );
+	Joins.Add_Field("JOINS", SG_DATATYPE_Int   );
 
-	for(sLong i=0; i<pPolygons->Get_Count() && Set_Progress(i, pPolygons->Get_Count()); i++)
+	for(sLong i=0; i<pPolygons->Get_Count(); i++)
 	{
-		if( JoinTo[i] < 0 )
-		{
-			nCandidate++;
-		}
-		else if( JoinTo[i] != i )
+		CSG_Table_Record &Join = *Joins.Add_Record();
+
+		Join.Set_Value(FIELD_AREA , pPolygons->Get_Shape(i)->asPolygon()->Get_Area());
+		Join.Set_Value(FIELD_JOIN , -1);
+		Join.Set_Value(FIELD_JOINS, 0.);
+	}
+
+	CSG_Index Index;
+
+	if( !Joins.Set_Index(Index, FIELD_AREA) )
+	{
+		Error_Set(_TL("index creation failed"));
+
+		return( false );
+	}
+
+	//-----------------------------------------------------
+	int     Method = Parameters["JOIN_TO" ].asInt   ();
+	bool bVertices = Parameters["VERTICES"].asBool  ();
+	double Epsilon = Parameters["EPSILON" ].asDouble();
+
+	sLong nJoins = 0;
+
+	for(sLong i=0; i<Joins.Get_Count() && Set_Progress(i, Joins.Get_Count()); i++)
+	{
+		CSG_Table_Record &Join = Joins[Index[i]];
+
+		if( Join.asDouble(FIELD_AREA) < Threshold )
 		{
-			nRemoved++;
+			CSG_Shape_Polygon *pPolygon = pPolygons->Get_Shape(Join.Get_Index())->asPolygon();
 
-			CSG_Shape_Polygon *pJoinTo = (CSG_Shape_Polygon *)pPolygons->Get_Shape(JoinTo[i]);
-			CSG_Shape_Polygon *pRemove = (CSG_Shape_Polygon *)pPolygons->Get_Shape(       i );
+			sLong maxPolygon = -1; double maxValue = 0.;
 
-			for(int iPart=0; iPart<pJoinTo->Get_Part_Count(); iPart++)
+			for(sLong j=0; j<pPolygons->Get_Count(); j++)
 			{
-				if( pJoinTo->is_Lake(iPart) == pJoinTo->is_Clockwise(iPart) )
+				CSG_Shape_Polygon *pNeighbour = pPolygons->Get_Shape(j)->asPolygon();
+
+				if( pPolygon != pNeighbour )
 				{
-					pJoinTo->Revert_Points(iPart);
+					if( Method == 0 ) // largest area
+					{
+						if( maxValue < pNeighbour->Get_Area() && pPolygon->is_Neighbour(pNeighbour) )
+						{
+							maxValue = pNeighbour->Get_Area(); maxPolygon = j;
+						}
+					}
+					else if( pPolygon->is_Neighbour(pNeighbour) ) // largest shared edge length
+					{
+						double sharedLength = pPolygon->Get_Shared_Length(pNeighbour, bVertices, Epsilon);
+
+						if( maxValue < sharedLength )
+						{
+							maxValue = sharedLength; maxPolygon = j;
+						}
+					}
 				}
 			}
 
-			for(int iPart=0; iPart<pRemove->Get_Part_Count(); iPart++)
+			if( maxPolygon >= 0 )
 			{
-				pJoinTo->Add_Part(pRemove->Get_Part(iPart), pRemove->is_Lake(iPart) == pRemove->is_Clockwise(iPart));
-			}
+				Join.Set_Value(FIELD_JOIN, maxPolygon);
 
-			SG_Shape_Get_Dissolve(pJoinTo);
-		}
-	}
+				CSG_Table_Record &JoinTo = Joins[maxPolygon];
 
-	for(sLong i=pPolygons->Get_Count()-1; i>=0; i--)
-	{
-		if( JoinTo[i] >= 0 && JoinTo[i] != i )
-		{
-			pPolygons->Del_Shape(i);
+				JoinTo.Add_Value(FIELD_AREA , Join.asDouble(FIELD_AREA));
+				JoinTo.Add_Value(FIELD_JOINS, 1);
+
+				nJoins++;
+			}
 		}
 	}
 
-	Message_Fmt("\n%s: %lld; %s: %lld", _TL("candidates"), nRemoved + nCandidate, _TL("eliminated"), nRemoved);
-
-	return( nRemoved > 0 );
+	return( nJoins > 0 );
 }
 
 
@@ -249,71 +289,83 @@ bool CPolygon_Generalization::Set_JoinTos(CSG_Shapes *pPolygons)
 ///////////////////////////////////////////////////////////
 
 //---------------------------------------------------------
-bool CPolygon_Generalization::Get_JoinTos(CSG_Shapes *pPolygons, CSG_Array_sLong &JoinTo)
+bool CPolygon_Generalization::Set_Joins(CSG_Shapes *pPolygons)
 {
-	double Threshold = Parameters("THRESHOLD")->asDouble();
-	int       Method = Parameters("JOIN_TO")->asInt();
-	bool   bVertices = Parameters("VERTICES")->asBool();
-	double   Epsilon = Parameters("EPSILON")->asDouble();
+	CSG_Table Joins;
 
-	if( Threshold <= 0. || !JoinTo.Create(pPolygons->Get_Count()) )
+	if( !Get_Joins(pPolygons, Joins) )
 	{
 		return( false );
 	}
 
-	sLong n = 0;
-	std::vector<bool> Has_Join(pPolygons->Get_Count(), false);
-
+	//-----------------------------------------------------
 	for(sLong i=0; i<pPolygons->Get_Count() && Set_Progress(i, pPolygons->Get_Count()); i++)
 	{
-		CSG_Shape_Polygon *pPolygon = (CSG_Shape_Polygon *)pPolygons->Get_Shape(i);
-
-		if( Has_Join[i] || Threshold <= pPolygon->Get_Area() )
+		if( Joins[i].asInt(FIELD_JOINS) > 0 )
 		{
-			JoinTo[i] = i;
+			CSG_Shape_Polygon *pPolygon = pPolygons->Get_Shape(i)->asPolygon();
+
+			for(int iPart=0; iPart<pPolygon->Get_Part_Count(); iPart++)
+			{
+				if( pPolygon->is_Lake(iPart) == pPolygon->is_Clockwise(iPart) )
+				{
+					pPolygon->Revert_Points(iPart);
+				}
+			}
+
+			Add_Joins(pPolygons, Joins, pPolygon, i);
+
+			SG_Shape_Get_Dissolve(pPolygon);
 		}
-		else // if( Threshold > pPolygon->Get_Area() )
+	}
+
+	//-----------------------------------------------------
+	for(sLong i=pPolygons->Get_Count()-1; i>=0; i--)
+	{
+		if( pPolygons->Get_Shape(i)->Get_Part_Count() < 1 )
 		{
-			JoinTo[i] = -1;
+			pPolygons->Del_Shape(i);
+		}
+	}
 
-			double maxValue = 0.;
+	sLong nJoined = Joins.Get_Count() - pPolygons->Get_Count();
 
-			for(sLong j=0; j<pPolygons->Get_Count(); j++)
-			{
-				if( j != i )
-				{
-					CSG_Shape_Polygon *pNeighbour = (CSG_Shape_Polygon *)pPolygons->Get_Shape(j);
+	Message_Fmt("\n%s: %lld", _TL("total number of removed polygons"), nJoined);
 
-					if( Method == 0 ) // largest area
-					{
-						if( maxValue <= pNeighbour->Get_Area() && pPolygon->is_Neighbour(pNeighbour) )
-						{
-							maxValue   = pNeighbour->Get_Area();
+	return( nJoined > 0 );
+}
 
-							JoinTo[i]   = j;
-							Has_Join[j] = true;
-						}
-					}
-					else if( pPolygon->is_Neighbour(pNeighbour) ) // largest shared edge length
-					{
-						double sharedLength = pPolygon->Get_Shared_Length(pNeighbour, bVertices, Epsilon);
-						
-						if( sharedLength > maxValue )
-						{
-							maxValue  = sharedLength;
 
-							JoinTo[i]   = j;
-							Has_Join[j] = true;
-						}
-					}
-				}
+///////////////////////////////////////////////////////////
+//														 //
+///////////////////////////////////////////////////////////
+
+//---------------------------------------------------------
+bool CPolygon_Generalization::Add_Joins(CSG_Shapes *pPolygons, CSG_Table &Joins, CSG_Shape *pPolygon, sLong id)
+{
+	for(sLong i=0; i<Joins.Get_Count(); i++)
+	{
+		if( pPolygon->Get_Index() != i && Joins[i].asInt(FIELD_JOIN) == id )
+		{
+			CSG_Shape_Polygon *pJoin = pPolygons->Get_Shape(i)->asPolygon();
+
+			for(int iPart=0; iPart<pJoin->Get_Part_Count(); iPart++)
+			{
+				pPolygon->Add_Part(pJoin->Get_Part(iPart), pJoin->is_Lake(iPart) == pJoin->is_Clockwise(iPart));
 			}
 
-			n++;
+			pJoin->Del_Parts();
+
+			if( Joins[i].asInt(FIELD_JOINS) )
+			{
+				Joins[i].Set_Value(FIELD_JOINS, 0.);
+
+				Add_Joins(pPolygons, Joins, pPolygon, i); // recursive!
+			}
 		}
 	}
 
-	return( n > 0 );
+	return( true );
 }
 
 


=====================================
saga-gis/src/tools/shapes/shapes_polygons/polygon_generalization.h
=====================================
@@ -82,9 +82,11 @@ protected:
 
 private:
 
-	bool					Set_JoinTos				(CSG_Shapes *pPolygons);
+	bool					Set_Joins				(CSG_Shapes *pPolygons);
 
-	bool					Get_JoinTos				(CSG_Shapes *pPolygons, CSG_Array_sLong &JoinTo);
+	bool					Get_Joins				(CSG_Shapes *pPolygons, CSG_Table &Joins);
+
+	bool					Add_Joins				(CSG_Shapes *pPolygons, CSG_Table &Joins, CSG_Shape *pPolygon, sLong id);
 
 };
 


=====================================
saga-gis/version.cmake
=====================================
@@ -1,7 +1,7 @@
 # The version number.
 set (SAGA_VERSION_MAJOR 9)
 set (SAGA_VERSION_MINOR 9)
-set (SAGA_VERSION_PATCH 2)
+set (SAGA_VERSION_PATCH 3)
 
 # get git commit hash (or dirty if git is not installed)
 



View it on GitLab: https://salsa.debian.org/debian-gis-team/saga/-/compare/02d4d63d2c66c3e1c36fec8c198fd8a294048af5...f14b4859a98e74c836648742b36e98f728278748

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/saga/-/compare/02d4d63d2c66c3e1c36fec8c198fd8a294048af5...f14b4859a98e74c836648742b36e98f728278748
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20251006/bc94cba9/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list