From aca64347ccaf82392c5f3fcc0c9d1cceb531b5c1 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 6 Nov 2019 09:11:03 +0400 Subject: [PATCH 01/43] Update dialogs.py --- dialogs.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dialogs.py b/dialogs.py index f13d061..6209e40 100644 --- a/dialogs.py +++ b/dialogs.py @@ -1,5 +1,6 @@ -from PyQt4.QtGui import * -from PyQt4.QtCore import * +from builtins import str +from PyQt5.QtGui import * +from PyQt5.QtCore import * from os.path import splitext, dirname @@ -10,8 +11,8 @@ def saveDialog(parent): outDir = settings.value(key) filter = 'Shapefiles (*.shp)' - outFilePath = QFileDialog.getSaveFileName(parent, parent.tr('Save output shapefile'), outDir, filter) - outFilePath = unicode(outFilePath) + outFilePath, __ = QFileDialog.getSaveFileName(parent, parent.tr('Save output shapefile'), outDir, filter) + outFilePath = str(outFilePath) if outFilePath: root, ext = splitext(outFilePath) From b3b8e2ae60246192699a7670126528ad46b308fa Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 6 Nov 2019 09:11:46 +0400 Subject: [PATCH 02/43] Update generalizer.py --- generalizer.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/generalizer.py b/generalizer.py index 3f69971..8cdadad 100644 --- a/generalizer.py +++ b/generalizer.py @@ -18,16 +18,22 @@ * * ***************************************************************************/ """ +from __future__ import absolute_import # Import the PyQt and QGIS libraries -from PyQt4.QtCore import * -from PyQt4.QtGui import * +from builtins import object +from PyQt5.QtCore import * +from PyQt5.QtGui import * + +from PyQt5.QtWidgets import QAction + + from qgis.core import * # Initialize Qt resources from file resources.py -import resources +from . import resources # Import the code for the dialog -from generalizerdialog import generalizerDialog, getLayersNames +from .generalizerdialog import generalizerDialog, getLayersNames -class generalizer: +class generalizer(object): def __init__(self, iface): # Save reference to the QGIS interface From 808f98e8949a7bb009618b91bddeaed9c5346a6a Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 6 Nov 2019 09:12:14 +0400 Subject: [PATCH 03/43] Update generalizerdialog.py --- generalizerdialog.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/generalizerdialog.py b/generalizerdialog.py index c09aff0..635b44e 100644 --- a/generalizerdialog.py +++ b/generalizerdialog.py @@ -18,17 +18,23 @@ * * ***************************************************************************/ """ +from __future__ import absolute_import -from PyQt4.QtCore import * -from PyQt4.QtGui import * +from builtins import str +from builtins import range +from PyQt5.QtCore import * +from PyQt5.QtGui import * + +from PyQt5.QtWidgets import QAction, QDialog, QMessageBox +from qgis.utils import Qgis from qgis.core import * from qgis.gui import * -import smooth, simplify, points -from dialogs import * +from . import smooth, simplify, points +from .dialogs import * -from ui_generalizer import Ui_generalizer +from .ui_generalizer import Ui_generalizer #global variable with short to full algorithm names algorithm = {'remove':'Remove small objects', @@ -484,7 +490,7 @@ def doGeneralize(self, iLayerName, iLayer, oPath, func, arguments): fields = iProvider.fields() if oPath == 'memory': #create memory layer - if iLayer.wkbType() == QGis.WKBLineString: + if iLayer.wkbType() == QgsWkbTypes.LineString: mLayer = QgsVectorLayer('LineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') else: mLayer = QgsVectorLayer('MultiLineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') @@ -594,7 +600,7 @@ def batchGeneralize(self, layers): vLayer = self.doGeneralize(layer, vLayer, 'memory', func, arguments) if not self.ui.cbOutDir.isChecked(): - QgsMapLayerRegistry.instance().addMapLayer(vLayer) + QgsProject.instance().addMapLayer(vLayer) if self.ui.cbOutDir.isChecked(): self.LoadLayers(outNames) @@ -631,7 +637,7 @@ def generalize(self): self.LoadLayers([filePath]) else: mLayer = self.doGeneralize(self.ui.cbInput.currentText(), getMapLayerByName(self.ui.cbInput.currentText()), 'memory', func, arguments) - QgsMapLayerRegistry.instance().addMapLayer(mLayer) + QgsProject.instance().addMapLayer(mLayer) #self.close() #refresh layer list @@ -746,18 +752,18 @@ def reumann_witkam(self,l, **kwargs): def getLayersNames(): - layermap = QgsMapLayerRegistry.instance().mapLayers() + layermap = QgsProject.instance().mapLayers() layerlist = [] - for name, layer in layermap.iteritems(): + for name, layer in layermap.items(): if layer.type() == QgsMapLayer.VectorLayer: - if layer.geometryType() == QGis.Line: - layerlist.append( unicode( layer.name() ) ) + if layer.geometryType() == QgsWkbTypes.LineGeometry: + layerlist.append( str( layer.name() ) ) return layerlist def getMapLayerByName(myName): - layermap = QgsMapLayerRegistry.instance().mapLayers() - for name, layer in layermap.iteritems(): + layermap = QgsProject.instance().mapLayers() + for name, layer in layermap.items(): if layer.name() == myName: if layer.isValid(): return layer From 8ddf0e3ff07c70fc3486e99fe3c7902d66205974 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 6 Nov 2019 09:12:55 +0400 Subject: [PATCH 04/43] Update __init__.py --- __init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index 7f2a335..fcf688b 100644 --- a/__init__.py +++ b/__init__.py @@ -19,7 +19,8 @@ ***************************************************************************/ This script initializes the plugin, making it known to QGIS. """ +from __future__ import absolute_import def classFactory(iface): # load generalizer class from file generalizer - from generalizer import generalizer + from .generalizer import generalizer return generalizer(iface) From ea9a25856d723a6356b8d5a0e8b4a1c7d7912159 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 6 Nov 2019 09:13:25 +0400 Subject: [PATCH 05/43] Update points.py --- points.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/points.py b/points.py index 382b57f..973e465 100644 --- a/points.py +++ b/points.py @@ -1,4 +1,5 @@ -from PyQt4.QtGui import * +from builtins import object +from PyQt5.QtGui import * from math import sqrt, acos, pi, fabs class line_pnts(object): @@ -160,4 +161,4 @@ def compare_points(a, b): tmp = line_pnts(pts) pts.add_point(p2) -print tmp.n_points, pts.n_points""" \ No newline at end of file +print tmp.n_points, pts.n_points""" From 316e806bb4fbafbfbb24a26b7bf92596d9655879 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 6 Nov 2019 09:14:29 +0400 Subject: [PATCH 06/43] Update metadata.txt --- metadata.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/metadata.txt b/metadata.txt index 0bfca62..7539bc4 100644 --- a/metadata.txt +++ b/metadata.txt @@ -10,9 +10,9 @@ [general] name=Generalizer -qgisMinimumVersion=2.0 +qgisMinimumVersion=3.0 description=Lines generalization and smoothing (partially based on v.generalize GRASS module) -version=0.5 +version=0.6 author=Piotr Pociask email= From a0fff073131495e01b5e718c9296e697573299f2 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 6 Nov 2019 09:15:02 +0400 Subject: [PATCH 07/43] Update simplify.py --- simplify.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/simplify.py b/simplify.py index 787b5a6..72a4a88 100644 --- a/simplify.py +++ b/simplify.py @@ -1,5 +1,7 @@ -from PyQt4.QtGui import * -from points import * +from __future__ import absolute_import +from builtins import range +from PyQt5.QtGui import * +from .points import * import math @@ -270,4 +272,4 @@ def reumann_witkam(points, thresh): print l print 'X,Y' for i in range(len(p.x)): - print p.x[i], ',', p.y[i]""" \ No newline at end of file + print p.x[i], ',', p.y[i]""" From 1dc0fccee6edb9e7df2a5b27bf23b1c9b86ac8d4 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 6 Nov 2019 09:15:34 +0400 Subject: [PATCH 08/43] Update smooth.py --- smooth.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/smooth.py b/smooth.py index c6640b9..6d3085b 100644 --- a/smooth.py +++ b/smooth.py @@ -1,6 +1,9 @@ -from PyQt4.QtGui import * -from points import * -from matrix import * +from __future__ import print_function +from __future__ import absolute_import +from builtins import range +from qgis.PyQt.QtWidgets import * +from .points import * +from .matrix import * GRASS_EPSILON = 1.0e-15 @@ -386,14 +389,19 @@ def snakes(points, alpha, beta): g.a[i][i]= g.a[i][i] + 1. i = i+1 - print 2 + # fix_print_with_import + print(2) ginv = matrix_inverse(g) - print 3 + # fix_print_with_import + # fix_print_with_import + print(3) xout = matrix_mult(ginv, xcoord) yout = matrix_mult(ginv, ycoord) - print 4 + # fix_print_with_import + # fix_print_with_import + print(4) i = 1 while i < n-1: @@ -412,4 +420,4 @@ def snakes(points, alpha, beta): print l print 'X;Y' for i in range(len(p.x)): - print p.x[i], ';', p.y[i]""" \ No newline at end of file + print p.x[i], ';', p.y[i]""" From ca79a9030a16063a042890e0bde007d22eeba9e4 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 6 Nov 2019 09:17:03 +0400 Subject: [PATCH 09/43] Update ui_generalizer.py --- ui_generalizer.py | 324 +++++++++++++++++++++++----------------------- 1 file changed, 164 insertions(+), 160 deletions(-) diff --git a/ui_generalizer.py b/ui_generalizer.py index ee4aa1f..b88c781 100644 --- a/ui_generalizer.py +++ b/ui_generalizer.py @@ -1,25 +1,26 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file 'C:\Documents and Settings\Pocisk\.qgis\python\plugins\generalizer\ui_generalizer.ui' +# Form implementation generated from reading ui file 'ui_generalizer.ui' # -# Created: Tue Sep 13 17:03:23 2011 -# by: PyQt4 UI code generator 4.8.3 +# Created by: PyQt5 UI code generator 5.13.1 # # WARNING! All changes made in this file will be lost! -from PyQt4 import QtCore, QtGui + +from PyQt5 import QtCore, QtGui, QtWidgets + class Ui_generalizer(object): def setupUi(self, generalizer): generalizer.setObjectName("generalizer") generalizer.resize(493, 348) - self.gridLayout_20 = QtGui.QGridLayout(generalizer) + self.gridLayout_20 = QtWidgets.QGridLayout(generalizer) self.gridLayout_20.setObjectName("gridLayout_20") - self.cbBatch = QtGui.QCheckBox(generalizer) + self.cbBatch = QtWidgets.QCheckBox(generalizer) self.cbBatch.setObjectName("cbBatch") self.gridLayout_20.addWidget(self.cbBatch, 0, 0, 1, 1) - self.bHelp = QtGui.QPushButton(generalizer) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Fixed) + self.bHelp = QtWidgets.QPushButton(generalizer) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.bHelp.sizePolicy().hasHeightForWidth()) @@ -27,38 +28,38 @@ def setupUi(self, generalizer): self.bHelp.setFlat(True) self.bHelp.setObjectName("bHelp") self.gridLayout_20.addWidget(self.bHelp, 0, 2, 1, 1) - self.bOk = QtGui.QPushButton(generalizer) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Fixed) + self.bOk = QtWidgets.QPushButton(generalizer) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.bOk.sizePolicy().hasHeightForWidth()) self.bOk.setSizePolicy(sizePolicy) self.bOk.setObjectName("bOk") self.gridLayout_20.addWidget(self.bOk, 2, 1, 1, 1) - self.bCancel = QtGui.QPushButton(generalizer) + self.bCancel = QtWidgets.QPushButton(generalizer) self.bCancel.setObjectName("bCancel") self.gridLayout_20.addWidget(self.bCancel, 2, 2, 1, 1) - self.stackBatch = QtGui.QStackedWidget(generalizer) + self.stackBatch = QtWidgets.QStackedWidget(generalizer) self.stackBatch.setObjectName("stackBatch") - self.page_6 = QtGui.QWidget() + self.page_6 = QtWidgets.QWidget() self.page_6.setObjectName("page_6") - self.gridLayout_19 = QtGui.QGridLayout(self.page_6) + self.gridLayout_19 = QtWidgets.QGridLayout(self.page_6) self.gridLayout_19.setObjectName("gridLayout_19") - self.label = QtGui.QLabel(self.page_6) + self.label = QtWidgets.QLabel(self.page_6) self.label.setObjectName("label") self.gridLayout_19.addWidget(self.label, 0, 0, 1, 1) - self.cbInput = QtGui.QComboBox(self.page_6) + self.cbInput = QtWidgets.QComboBox(self.page_6) self.cbInput.setObjectName("cbInput") self.gridLayout_19.addWidget(self.cbInput, 1, 0, 1, 2) - self.groupBox = QtGui.QGroupBox(self.page_6) + self.groupBox = QtWidgets.QGroupBox(self.page_6) self.groupBox.setObjectName("groupBox") - self.gridLayout_2 = QtGui.QGridLayout(self.groupBox) + self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox) self.gridLayout_2.setObjectName("gridLayout_2") - self.label_3 = QtGui.QLabel(self.groupBox) + self.label_3 = QtWidgets.QLabel(self.groupBox) self.label_3.setObjectName("label_3") self.gridLayout_2.addWidget(self.label_3, 0, 0, 1, 1) - self.cbAlgorithm = QtGui.QComboBox(self.groupBox) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed) + self.cbAlgorithm = QtWidgets.QComboBox(self.groupBox) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.cbAlgorithm.sizePolicy().hasHeightForWidth()) @@ -80,16 +81,16 @@ def setupUi(self, generalizer): self.cbAlgorithm.addItem("") self.cbAlgorithm.addItem("") self.gridLayout_2.addWidget(self.cbAlgorithm, 0, 1, 1, 1) - self.stackOptions = QtGui.QStackedWidget(self.groupBox) + self.stackOptions = QtWidgets.QStackedWidget(self.groupBox) self.stackOptions.setObjectName("stackOptions") - self.page_11 = QtGui.QWidget() + self.page_11 = QtWidgets.QWidget() self.page_11.setObjectName("page_11") - self.gridLayout_11 = QtGui.QGridLayout(self.page_11) + self.gridLayout_11 = QtWidgets.QGridLayout(self.page_11) self.gridLayout_11.setObjectName("gridLayout_11") - self.label_12 = QtGui.QLabel(self.page_11) + self.label_12 = QtWidgets.QLabel(self.page_11) self.label_12.setObjectName("label_12") self.gridLayout_11.addWidget(self.label_12, 0, 0, 1, 1) - self.sbRemove_thresh = QtGui.QDoubleSpinBox(self.page_11) + self.sbRemove_thresh = QtWidgets.QDoubleSpinBox(self.page_11) self.sbRemove_thresh.setDecimals(4) self.sbRemove_thresh.setMinimum(0.0001) self.sbRemove_thresh.setMaximum(9999999.9999) @@ -97,14 +98,14 @@ def setupUi(self, generalizer): self.sbRemove_thresh.setObjectName("sbRemove_thresh") self.gridLayout_11.addWidget(self.sbRemove_thresh, 0, 1, 1, 1) self.stackOptions.addWidget(self.page_11) - self.page_12 = QtGui.QWidget() + self.page_12 = QtWidgets.QWidget() self.page_12.setObjectName("page_12") - self.gridLayout_12 = QtGui.QGridLayout(self.page_12) + self.gridLayout_12 = QtWidgets.QGridLayout(self.page_12) self.gridLayout_12.setObjectName("gridLayout_12") - self.label_18 = QtGui.QLabel(self.page_12) + self.label_18 = QtWidgets.QLabel(self.page_12) self.label_18.setObjectName("label_18") self.gridLayout_12.addWidget(self.label_18, 0, 0, 1, 1) - self.sbDP_thresh = QtGui.QDoubleSpinBox(self.page_12) + self.sbDP_thresh = QtWidgets.QDoubleSpinBox(self.page_12) self.sbDP_thresh.setDecimals(4) self.sbDP_thresh.setMinimum(0.0001) self.sbDP_thresh.setMaximum(9999999.9999) @@ -112,152 +113,152 @@ def setupUi(self, generalizer): self.sbDP_thresh.setObjectName("sbDP_thresh") self.gridLayout_12.addWidget(self.sbDP_thresh, 0, 1, 1, 1) self.stackOptions.addWidget(self.page_12) - self.page_2 = QtGui.QWidget() + self.page_2 = QtWidgets.QWidget() self.page_2.setObjectName("page_2") - self.gridLayout_4 = QtGui.QGridLayout(self.page_2) + self.gridLayout_4 = QtWidgets.QGridLayout(self.page_2) self.gridLayout_4.setObjectName("gridLayout_4") - self.label_7 = QtGui.QLabel(self.page_2) + self.label_7 = QtWidgets.QLabel(self.page_2) self.label_7.setObjectName("label_7") self.gridLayout_4.addWidget(self.label_7, 0, 0, 1, 1) - self.sbJenks_thresh = QtGui.QDoubleSpinBox(self.page_2) + self.sbJenks_thresh = QtWidgets.QDoubleSpinBox(self.page_2) self.sbJenks_thresh.setDecimals(4) self.sbJenks_thresh.setMaximum(9999999.9999) self.sbJenks_thresh.setProperty("value", 0.0001) self.sbJenks_thresh.setObjectName("sbJenks_thresh") self.gridLayout_4.addWidget(self.sbJenks_thresh, 0, 1, 1, 1) - self.label_8 = QtGui.QLabel(self.page_2) + self.label_8 = QtWidgets.QLabel(self.page_2) self.label_8.setObjectName("label_8") self.gridLayout_4.addWidget(self.label_8, 1, 0, 1, 1) - self.sbJenks_angle = QtGui.QDoubleSpinBox(self.page_2) + self.sbJenks_angle = QtWidgets.QDoubleSpinBox(self.page_2) self.sbJenks_angle.setMaximum(180.0) self.sbJenks_angle.setProperty("value", 3.0) self.sbJenks_angle.setObjectName("sbJenks_angle") self.gridLayout_4.addWidget(self.sbJenks_angle, 1, 1, 1, 1) self.stackOptions.addWidget(self.page_2) - self.page_13 = QtGui.QWidget() + self.page_13 = QtWidgets.QWidget() self.page_13.setObjectName("page_13") - self.gridLayout_3 = QtGui.QGridLayout(self.page_13) + self.gridLayout_3 = QtWidgets.QGridLayout(self.page_13) self.gridLayout_3.setObjectName("gridLayout_3") - self.label_13 = QtGui.QLabel(self.page_13) + self.label_13 = QtWidgets.QLabel(self.page_13) self.label_13.setObjectName("label_13") self.gridLayout_3.addWidget(self.label_13, 0, 0, 1, 1) - self.sbLang_thresh = QtGui.QDoubleSpinBox(self.page_13) + self.sbLang_thresh = QtWidgets.QDoubleSpinBox(self.page_13) self.sbLang_thresh.setDecimals(4) self.sbLang_thresh.setMinimum(0.0001) self.sbLang_thresh.setMaximum(9999999.9999) self.sbLang_thresh.setProperty("value", 0.0001) self.sbLang_thresh.setObjectName("sbLang_thresh") self.gridLayout_3.addWidget(self.sbLang_thresh, 0, 1, 1, 1) - self.label_19 = QtGui.QLabel(self.page_13) + self.label_19 = QtWidgets.QLabel(self.page_13) self.label_19.setObjectName("label_19") self.gridLayout_3.addWidget(self.label_19, 1, 0, 1, 1) - self.sbLang_LA = QtGui.QSpinBox(self.page_13) + self.sbLang_LA = QtWidgets.QSpinBox(self.page_13) self.sbLang_LA.setMinimum(1) self.sbLang_LA.setMaximum(9999) self.sbLang_LA.setProperty("value", 8) self.sbLang_LA.setObjectName("sbLang_LA") self.gridLayout_3.addWidget(self.sbLang_LA, 1, 1, 1, 1) self.stackOptions.addWidget(self.page_13) - self.page_4 = QtGui.QWidget() + self.page_4 = QtWidgets.QWidget() self.page_4.setObjectName("page_4") - self.gridLayout_6 = QtGui.QGridLayout(self.page_4) + self.gridLayout_6 = QtWidgets.QGridLayout(self.page_4) self.gridLayout_6.setObjectName("gridLayout_6") - self.label_11 = QtGui.QLabel(self.page_4) + self.label_11 = QtWidgets.QLabel(self.page_4) self.label_11.setObjectName("label_11") self.gridLayout_6.addWidget(self.label_11, 0, 0, 1, 1) - self.sbRW_thresh = QtGui.QDoubleSpinBox(self.page_4) + self.sbRW_thresh = QtWidgets.QDoubleSpinBox(self.page_4) self.sbRW_thresh.setDecimals(4) self.sbRW_thresh.setMaximum(9999999.9999) self.sbRW_thresh.setProperty("value", 0.0001) self.sbRW_thresh.setObjectName("sbRW_thresh") self.gridLayout_6.addWidget(self.sbRW_thresh, 0, 1, 1, 1) self.stackOptions.addWidget(self.page_4) - self.page_14 = QtGui.QWidget() + self.page_14 = QtWidgets.QWidget() self.page_14.setObjectName("page_14") - self.gridLayout_14 = QtGui.QGridLayout(self.page_14) + self.gridLayout_14 = QtWidgets.QGridLayout(self.page_14) self.gridLayout_14.setObjectName("gridLayout_14") - self.label_20 = QtGui.QLabel(self.page_14) + self.label_20 = QtWidgets.QLabel(self.page_14) self.label_20.setObjectName("label_20") self.gridLayout_14.addWidget(self.label_20, 0, 0, 1, 1) - self.sbReduction_thresh = QtGui.QDoubleSpinBox(self.page_14) + self.sbReduction_thresh = QtWidgets.QDoubleSpinBox(self.page_14) self.sbReduction_thresh.setDecimals(4) self.sbReduction_thresh.setMinimum(0.0001) self.sbReduction_thresh.setMaximum(9999999.9999) self.sbReduction_thresh.setObjectName("sbReduction_thresh") self.gridLayout_14.addWidget(self.sbReduction_thresh, 0, 1, 1, 1) self.stackOptions.addWidget(self.page_14) - self.page_15 = QtGui.QWidget() + self.page_15 = QtWidgets.QWidget() self.page_15.setObjectName("page_15") - self.gridLayout_15 = QtGui.QGridLayout(self.page_15) + self.gridLayout_15 = QtWidgets.QGridLayout(self.page_15) self.gridLayout_15.setObjectName("gridLayout_15") - self.label_21 = QtGui.QLabel(self.page_15) + self.label_21 = QtWidgets.QLabel(self.page_15) self.label_21.setObjectName("label_21") self.gridLayout_15.addWidget(self.label_21, 0, 0, 1, 1) - self.sbBoyle_LA = QtGui.QSpinBox(self.page_15) + self.sbBoyle_LA = QtWidgets.QSpinBox(self.page_15) self.sbBoyle_LA.setMinimum(2) self.sbBoyle_LA.setMaximum(999) self.sbBoyle_LA.setProperty("value", 7) self.sbBoyle_LA.setObjectName("sbBoyle_LA") self.gridLayout_15.addWidget(self.sbBoyle_LA, 0, 1, 1, 1) self.stackOptions.addWidget(self.page_15) - self.page_16 = QtGui.QWidget() + self.page_16 = QtWidgets.QWidget() self.page_16.setObjectName("page_16") - self.gridLayout_16 = QtGui.QGridLayout(self.page_16) + self.gridLayout_16 = QtWidgets.QGridLayout(self.page_16) self.gridLayout_16.setObjectName("gridLayout_16") - self.label_22 = QtGui.QLabel(self.page_16) + self.label_22 = QtWidgets.QLabel(self.page_16) self.label_22.setObjectName("label_22") self.gridLayout_16.addWidget(self.label_22, 0, 0, 1, 1) - self.sbChaiken_level = QtGui.QSpinBox(self.page_16) + self.sbChaiken_level = QtWidgets.QSpinBox(self.page_16) self.sbChaiken_level.setMinimum(1) self.sbChaiken_level.setMaximum(99) self.sbChaiken_level.setObjectName("sbChaiken_level") self.gridLayout_16.addWidget(self.sbChaiken_level, 0, 1, 1, 1) - self.label_23 = QtGui.QLabel(self.page_16) + self.label_23 = QtWidgets.QLabel(self.page_16) self.label_23.setObjectName("label_23") self.gridLayout_16.addWidget(self.label_23, 1, 0, 1, 1) - self.sbChaiken_weight = QtGui.QDoubleSpinBox(self.page_16) + self.sbChaiken_weight = QtWidgets.QDoubleSpinBox(self.page_16) self.sbChaiken_weight.setMinimum(1.0) self.sbChaiken_weight.setProperty("value", 3.0) self.sbChaiken_weight.setObjectName("sbChaiken_weight") self.gridLayout_16.addWidget(self.sbChaiken_weight, 1, 1, 1, 1) self.stackOptions.addWidget(self.page_16) - self.page = QtGui.QWidget() + self.page = QtWidgets.QWidget() self.page.setObjectName("page") - self.gridLayout = QtGui.QGridLayout(self.page) + self.gridLayout = QtWidgets.QGridLayout(self.page) self.gridLayout.setObjectName("gridLayout") - self.label_2 = QtGui.QLabel(self.page) + self.label_2 = QtWidgets.QLabel(self.page) self.label_2.setObjectName("label_2") self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1) - self.label_4 = QtGui.QLabel(self.page) + self.label_4 = QtWidgets.QLabel(self.page) self.label_4.setObjectName("label_4") self.gridLayout.addWidget(self.label_4, 1, 0, 1, 1) - self.sbHermite_tightness = QtGui.QDoubleSpinBox(self.page) + self.sbHermite_tightness = QtWidgets.QDoubleSpinBox(self.page) self.sbHermite_tightness.setProperty("value", 0.5) self.sbHermite_tightness.setObjectName("sbHermite_tightness") self.gridLayout.addWidget(self.sbHermite_tightness, 1, 1, 1, 1) - self.sbHermite_steps = QtGui.QDoubleSpinBox(self.page) + self.sbHermite_steps = QtWidgets.QDoubleSpinBox(self.page) self.sbHermite_steps.setDecimals(4) self.sbHermite_steps.setMaximum(9999999.9999) self.sbHermite_steps.setProperty("value", 0.0001) self.sbHermite_steps.setObjectName("sbHermite_steps") self.gridLayout.addWidget(self.sbHermite_steps, 0, 1, 1, 1) self.stackOptions.addWidget(self.page) - self.page_17 = QtGui.QWidget() + self.page_17 = QtWidgets.QWidget() self.page_17.setObjectName("page_17") - self.gridLayout_17 = QtGui.QGridLayout(self.page_17) + self.gridLayout_17 = QtWidgets.QGridLayout(self.page_17) self.gridLayout_17.setObjectName("gridLayout_17") - self.label_24 = QtGui.QLabel(self.page_17) + self.label_24 = QtWidgets.QLabel(self.page_17) self.label_24.setObjectName("label_24") self.gridLayout_17.addWidget(self.label_24, 0, 0, 1, 1) - self.sbDist_slide = QtGui.QDoubleSpinBox(self.page_17) + self.sbDist_slide = QtWidgets.QDoubleSpinBox(self.page_17) self.sbDist_slide.setSingleStep(0.1) self.sbDist_slide.setProperty("value", 0.5) self.sbDist_slide.setObjectName("sbDist_slide") self.gridLayout_17.addWidget(self.sbDist_slide, 0, 1, 1, 1) - self.label_25 = QtGui.QLabel(self.page_17) + self.label_25 = QtWidgets.QLabel(self.page_17) self.label_25.setObjectName("label_25") self.gridLayout_17.addWidget(self.label_25, 1, 0, 1, 1) - self.sbDist_LA = QtGui.QSpinBox(self.page_17) + self.sbDist_LA = QtWidgets.QSpinBox(self.page_17) self.sbDist_LA.setMinimum(3) self.sbDist_LA.setMaximum(999) self.sbDist_LA.setSingleStep(2) @@ -265,22 +266,22 @@ def setupUi(self, generalizer): self.sbDist_LA.setObjectName("sbDist_LA") self.gridLayout_17.addWidget(self.sbDist_LA, 1, 1, 1, 1) self.stackOptions.addWidget(self.page_17) - self.page_18 = QtGui.QWidget() + self.page_18 = QtWidgets.QWidget() self.page_18.setObjectName("page_18") - self.gridLayout_18 = QtGui.QGridLayout(self.page_18) + self.gridLayout_18 = QtWidgets.QGridLayout(self.page_18) self.gridLayout_18.setObjectName("gridLayout_18") - self.label_26 = QtGui.QLabel(self.page_18) + self.label_26 = QtWidgets.QLabel(self.page_18) self.label_26.setObjectName("label_26") self.gridLayout_18.addWidget(self.label_26, 0, 0, 1, 1) - self.sbSlide_slide = QtGui.QDoubleSpinBox(self.page_18) + self.sbSlide_slide = QtWidgets.QDoubleSpinBox(self.page_18) self.sbSlide_slide.setSingleStep(0.1) self.sbSlide_slide.setProperty("value", 0.5) self.sbSlide_slide.setObjectName("sbSlide_slide") self.gridLayout_18.addWidget(self.sbSlide_slide, 0, 1, 1, 1) - self.label_27 = QtGui.QLabel(self.page_18) + self.label_27 = QtWidgets.QLabel(self.page_18) self.label_27.setObjectName("label_27") self.gridLayout_18.addWidget(self.label_27, 1, 0, 1, 1) - self.sbSlide_LA = QtGui.QSpinBox(self.page_18) + self.sbSlide_LA = QtWidgets.QSpinBox(self.page_18) self.sbSlide_LA.setMinimum(3) self.sbSlide_LA.setMaximum(999) self.sbSlide_LA.setSingleStep(2) @@ -288,22 +289,22 @@ def setupUi(self, generalizer): self.sbSlide_LA.setObjectName("sbSlide_LA") self.gridLayout_18.addWidget(self.sbSlide_LA, 1, 1, 1, 1) self.stackOptions.addWidget(self.page_18) - self.page_3 = QtGui.QWidget() + self.page_3 = QtWidgets.QWidget() self.page_3.setObjectName("page_3") - self.gridLayout_5 = QtGui.QGridLayout(self.page_3) + self.gridLayout_5 = QtWidgets.QGridLayout(self.page_3) self.gridLayout_5.setObjectName("gridLayout_5") - self.label_9 = QtGui.QLabel(self.page_3) + self.label_9 = QtWidgets.QLabel(self.page_3) self.label_9.setObjectName("label_9") self.gridLayout_5.addWidget(self.label_9, 0, 0, 1, 1) - self.sbSnakes_alpha = QtGui.QDoubleSpinBox(self.page_3) + self.sbSnakes_alpha = QtWidgets.QDoubleSpinBox(self.page_3) self.sbSnakes_alpha.setMaximum(9999.99) self.sbSnakes_alpha.setProperty("value", 1.0) self.sbSnakes_alpha.setObjectName("sbSnakes_alpha") self.gridLayout_5.addWidget(self.sbSnakes_alpha, 0, 1, 1, 1) - self.label_10 = QtGui.QLabel(self.page_3) + self.label_10 = QtWidgets.QLabel(self.page_3) self.label_10.setObjectName("label_10") self.gridLayout_5.addWidget(self.label_10, 1, 0, 1, 1) - self.sbSnakes_beta = QtGui.QDoubleSpinBox(self.page_3) + self.sbSnakes_beta = QtWidgets.QDoubleSpinBox(self.page_3) self.sbSnakes_beta.setMaximum(9999.99) self.sbSnakes_beta.setProperty("value", 0.5) self.sbSnakes_beta.setObjectName("sbSnakes_beta") @@ -311,32 +312,32 @@ def setupUi(self, generalizer): self.stackOptions.addWidget(self.page_3) self.gridLayout_2.addWidget(self.stackOptions, 1, 0, 1, 2) self.gridLayout_19.addWidget(self.groupBox, 2, 0, 1, 2) - self.eOutput = QtGui.QLineEdit(self.page_6) + self.eOutput = QtWidgets.QLineEdit(self.page_6) self.eOutput.setEnabled(False) self.eOutput.setObjectName("eOutput") self.gridLayout_19.addWidget(self.eOutput, 4, 0, 1, 1) - self.bBrowse = QtGui.QPushButton(self.page_6) + self.bBrowse = QtWidgets.QPushButton(self.page_6) self.bBrowse.setEnabled(False) self.bBrowse.setObjectName("bBrowse") self.gridLayout_19.addWidget(self.bBrowse, 4, 1, 1, 1) - self.cbOutFile = QtGui.QCheckBox(self.page_6) + self.cbOutFile = QtWidgets.QCheckBox(self.page_6) self.cbOutFile.setObjectName("cbOutFile") self.gridLayout_19.addWidget(self.cbOutFile, 3, 0, 1, 1) self.stackBatch.addWidget(self.page_6) - self.page_10 = QtGui.QWidget() + self.page_10 = QtWidgets.QWidget() self.page_10.setObjectName("page_10") - self.gridLayout_21 = QtGui.QGridLayout(self.page_10) + self.gridLayout_21 = QtWidgets.QGridLayout(self.page_10) self.gridLayout_21.setObjectName("gridLayout_21") - self.lstLayers = QtGui.QListWidget(self.page_10) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + self.lstLayers = QtWidgets.QListWidget(self.page_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.lstLayers.sizePolicy().hasHeightForWidth()) self.lstLayers.setSizePolicy(sizePolicy) self.lstLayers.setObjectName("lstLayers") self.gridLayout_21.addWidget(self.lstLayers, 1, 0, 1, 1) - self.tblBatchAlg = QtGui.QTableWidget(self.page_10) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + self.tblBatchAlg = QtWidgets.QTableWidget(self.page_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.tblBatchAlg.sizePolicy().hasHeightForWidth()) @@ -344,37 +345,37 @@ def setupUi(self, generalizer): self.tblBatchAlg.setObjectName("tblBatchAlg") self.tblBatchAlg.setColumnCount(3) self.tblBatchAlg.setRowCount(0) - item = QtGui.QTableWidgetItem() + item = QtWidgets.QTableWidgetItem() self.tblBatchAlg.setHorizontalHeaderItem(0, item) - item = QtGui.QTableWidgetItem() + item = QtWidgets.QTableWidgetItem() self.tblBatchAlg.setHorizontalHeaderItem(1, item) - item = QtGui.QTableWidgetItem() + item = QtWidgets.QTableWidgetItem() self.tblBatchAlg.setHorizontalHeaderItem(2, item) self.gridLayout_21.addWidget(self.tblBatchAlg, 3, 0, 3, 1) - self.bAddAlg = QtGui.QPushButton(self.page_10) + self.bAddAlg = QtWidgets.QPushButton(self.page_10) self.bAddAlg.setObjectName("bAddAlg") self.gridLayout_21.addWidget(self.bAddAlg, 3, 1, 1, 1) - self.bDelAlg = QtGui.QPushButton(self.page_10) + self.bDelAlg = QtWidgets.QPushButton(self.page_10) self.bDelAlg.setObjectName("bDelAlg") self.gridLayout_21.addWidget(self.bDelAlg, 4, 1, 1, 1) - self.bEditAlg = QtGui.QPushButton(self.page_10) + self.bEditAlg = QtWidgets.QPushButton(self.page_10) self.bEditAlg.setObjectName("bEditAlg") self.gridLayout_21.addWidget(self.bEditAlg, 5, 1, 1, 1) - self.eDir = QtGui.QLineEdit(self.page_10) + self.eDir = QtWidgets.QLineEdit(self.page_10) self.eDir.setEnabled(False) self.eDir.setObjectName("eDir") self.gridLayout_21.addWidget(self.eDir, 7, 0, 1, 1) - self.bBrowseDir = QtGui.QPushButton(self.page_10) + self.bBrowseDir = QtWidgets.QPushButton(self.page_10) self.bBrowseDir.setEnabled(False) self.bBrowseDir.setObjectName("bBrowseDir") self.gridLayout_21.addWidget(self.bBrowseDir, 7, 1, 1, 1) - self.cbOutDir = QtGui.QCheckBox(self.page_10) + self.cbOutDir = QtWidgets.QCheckBox(self.page_10) self.cbOutDir.setObjectName("cbOutDir") self.gridLayout_21.addWidget(self.cbOutDir, 6, 0, 1, 1) - self.label_5 = QtGui.QLabel(self.page_10) + self.label_5 = QtWidgets.QLabel(self.page_10) self.label_5.setObjectName("label_5") self.gridLayout_21.addWidget(self.label_5, 2, 0, 1, 1) - self.label_6 = QtGui.QLabel(self.page_10) + self.label_6 = QtWidgets.QLabel(self.page_10) self.label_6.setObjectName("label_6") self.gridLayout_21.addWidget(self.label_6, 0, 0, 1, 1) self.stackBatch.addWidget(self.page_10) @@ -386,7 +387,7 @@ def setupUi(self, generalizer): self.stackBatch.setCurrentIndex(0) self.cbAlgorithm.setCurrentIndex(1) self.stackOptions.setCurrentIndex(0) - self.bCancel.clicked.connect( generalizer.close ) + self.bCancel.clicked.connect(generalizer.close) QtCore.QMetaObject.connectSlotsByName(generalizer) generalizer.setTabOrder(self.cbBatch, self.cbInput) generalizer.setTabOrder(self.cbInput, self.cbAlgorithm) @@ -420,58 +421,61 @@ def setupUi(self, generalizer): generalizer.setTabOrder(self.bBrowseDir, self.cbOutDir) def retranslateUi(self, generalizer): - generalizer.setWindowTitle(QtGui.QApplication.translate("generalizer", "Generalizer", None, QtGui.QApplication.UnicodeUTF8)) - self.cbBatch.setText(QtGui.QApplication.translate("generalizer", "Batch mode", None, QtGui.QApplication.UnicodeUTF8)) - self.bHelp.setText(QtGui.QApplication.translate("generalizer", "?", None, QtGui.QApplication.UnicodeUTF8)) - self.bOk.setText(QtGui.QApplication.translate("generalizer", "OK", None, QtGui.QApplication.UnicodeUTF8)) - self.bCancel.setText(QtGui.QApplication.translate("generalizer", "Close", None, QtGui.QApplication.UnicodeUTF8)) - self.label.setText(QtGui.QApplication.translate("generalizer", "Input line layer:", None, QtGui.QApplication.UnicodeUTF8)) - self.groupBox.setTitle(QtGui.QApplication.translate("generalizer", "Options", None, QtGui.QApplication.UnicodeUTF8)) - self.label_3.setText(QtGui.QApplication.translate("generalizer", "Alghoritm:", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(0, QtGui.QApplication.translate("generalizer", "-----Generalizing-----", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(1, QtGui.QApplication.translate("generalizer", "Remove small objects", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(2, QtGui.QApplication.translate("generalizer", "-----Simplifying-----", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(3, QtGui.QApplication.translate("generalizer", "Douglas-Peucker Algorithm", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(4, QtGui.QApplication.translate("generalizer", "Jenk\'s Algorithm", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(5, QtGui.QApplication.translate("generalizer", "Lang Algorithm", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(6, QtGui.QApplication.translate("generalizer", "Reumann-Witkam Algorithm", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(7, QtGui.QApplication.translate("generalizer", "Vertex Reduction", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(8, QtGui.QApplication.translate("generalizer", "-----Smoothing-----", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(9, QtGui.QApplication.translate("generalizer", "Boyle\'s Forward-Looking Algorithm", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(10, QtGui.QApplication.translate("generalizer", "Chaiken\'s Algorithm", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(11, QtGui.QApplication.translate("generalizer", "Hermite Spline Interpolation", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(12, QtGui.QApplication.translate("generalizer", "McMaster\'s Distance-Weighting Algorithm", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(13, QtGui.QApplication.translate("generalizer", "McMaster\'s Sliding Averaging Algorithm", None, QtGui.QApplication.UnicodeUTF8)) - self.cbAlgorithm.setItemText(14, QtGui.QApplication.translate("generalizer", "Snakes Algorithm", None, QtGui.QApplication.UnicodeUTF8)) - self.label_12.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_18.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_7.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_8.setText(QtGui.QApplication.translate("generalizer", "Angle threshold:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_13.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_19.setText(QtGui.QApplication.translate("generalizer", "Looka ahead:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_11.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_20.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_21.setText(QtGui.QApplication.translate("generalizer", "Look ahead:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_22.setText(QtGui.QApplication.translate("generalizer", "Level:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_23.setText(QtGui.QApplication.translate("generalizer", "Weight:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_2.setText(QtGui.QApplication.translate("generalizer", "Threshold:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_4.setText(QtGui.QApplication.translate("generalizer", "Thightness:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_24.setText(QtGui.QApplication.translate("generalizer", "Slide:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_25.setText(QtGui.QApplication.translate("generalizer", "Look ahead:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_26.setText(QtGui.QApplication.translate("generalizer", "Slide:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_27.setText(QtGui.QApplication.translate("generalizer", "Look ahead:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_9.setText(QtGui.QApplication.translate("generalizer", "Alpha:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_10.setText(QtGui.QApplication.translate("generalizer", "Beta:", None, QtGui.QApplication.UnicodeUTF8)) - self.bBrowse.setText(QtGui.QApplication.translate("generalizer", "Browse", None, QtGui.QApplication.UnicodeUTF8)) - self.cbOutFile.setText(QtGui.QApplication.translate("generalizer", "Save output layer", None, QtGui.QApplication.UnicodeUTF8)) - self.tblBatchAlg.horizontalHeaderItem(0).setText(QtGui.QApplication.translate("generalizer", "Algorithm", None, QtGui.QApplication.UnicodeUTF8)) - self.tblBatchAlg.horizontalHeaderItem(1).setText(QtGui.QApplication.translate("generalizer", "Parameter 1", None, QtGui.QApplication.UnicodeUTF8)) - self.tblBatchAlg.horizontalHeaderItem(2).setText(QtGui.QApplication.translate("generalizer", "Parameter 2", None, QtGui.QApplication.UnicodeUTF8)) - self.bAddAlg.setText(QtGui.QApplication.translate("generalizer", "Add", None, QtGui.QApplication.UnicodeUTF8)) - self.bDelAlg.setText(QtGui.QApplication.translate("generalizer", "Delete", None, QtGui.QApplication.UnicodeUTF8)) - self.bEditAlg.setText(QtGui.QApplication.translate("generalizer", "Edit", None, QtGui.QApplication.UnicodeUTF8)) - self.bBrowseDir.setText(QtGui.QApplication.translate("generalizer", "Browse", None, QtGui.QApplication.UnicodeUTF8)) - self.cbOutDir.setText(QtGui.QApplication.translate("generalizer", "Save output layer(s) to folder", None, QtGui.QApplication.UnicodeUTF8)) - self.label_5.setText(QtGui.QApplication.translate("generalizer", "Algorithm(s)", None, QtGui.QApplication.UnicodeUTF8)) - self.label_6.setText(QtGui.QApplication.translate("generalizer", "Choose layer(s)", None, QtGui.QApplication.UnicodeUTF8)) - + _translate = QtCore.QCoreApplication.translate + generalizer.setWindowTitle(_translate("generalizer", "Generalizer")) + self.cbBatch.setText(_translate("generalizer", "Batch mode")) + self.bHelp.setText(_translate("generalizer", "?")) + self.bOk.setText(_translate("generalizer", "OK")) + self.bCancel.setText(_translate("generalizer", "Close")) + self.label.setText(_translate("generalizer", "Input line layer:")) + self.groupBox.setTitle(_translate("generalizer", "Options")) + self.label_3.setText(_translate("generalizer", "Alghoritm:")) + self.cbAlgorithm.setItemText(0, _translate("generalizer", "-----Generalizing-----")) + self.cbAlgorithm.setItemText(1, _translate("generalizer", "Remove small objects")) + self.cbAlgorithm.setItemText(2, _translate("generalizer", "-----Simplifying-----")) + self.cbAlgorithm.setItemText(3, _translate("generalizer", "Douglas-Peucker Algorithm")) + self.cbAlgorithm.setItemText(4, _translate("generalizer", "Jenk\'s Algorithm")) + self.cbAlgorithm.setItemText(5, _translate("generalizer", "Lang Algorithm")) + self.cbAlgorithm.setItemText(6, _translate("generalizer", "Reumann-Witkam Algorithm")) + self.cbAlgorithm.setItemText(7, _translate("generalizer", "Vertex Reduction")) + self.cbAlgorithm.setItemText(8, _translate("generalizer", "-----Smoothing-----")) + self.cbAlgorithm.setItemText(9, _translate("generalizer", "Boyle\'s Forward-Looking Algorithm")) + self.cbAlgorithm.setItemText(10, _translate("generalizer", "Chaiken\'s Algorithm")) + self.cbAlgorithm.setItemText(11, _translate("generalizer", "Hermite Spline Interpolation")) + self.cbAlgorithm.setItemText(12, _translate("generalizer", "McMaster\'s Distance-Weighting Algorithm")) + self.cbAlgorithm.setItemText(13, _translate("generalizer", "McMaster\'s Sliding Averaging Algorithm")) + self.cbAlgorithm.setItemText(14, _translate("generalizer", "Snakes Algorithm")) + self.label_12.setText(_translate("generalizer", "Threshold:")) + self.label_18.setText(_translate("generalizer", "Threshold:")) + self.label_7.setText(_translate("generalizer", "Threshold:")) + self.label_8.setText(_translate("generalizer", "Angle threshold:")) + self.label_13.setText(_translate("generalizer", "Threshold:")) + self.label_19.setText(_translate("generalizer", "Looka ahead:")) + self.label_11.setText(_translate("generalizer", "Threshold:")) + self.label_20.setText(_translate("generalizer", "Threshold:")) + self.label_21.setText(_translate("generalizer", "Look ahead:")) + self.label_22.setText(_translate("generalizer", "Level:")) + self.label_23.setText(_translate("generalizer", "Weight:")) + self.label_2.setText(_translate("generalizer", "Threshold:")) + self.label_4.setText(_translate("generalizer", "Thightness:")) + self.label_24.setText(_translate("generalizer", "Slide:")) + self.label_25.setText(_translate("generalizer", "Look ahead:")) + self.label_26.setText(_translate("generalizer", "Slide:")) + self.label_27.setText(_translate("generalizer", "Look ahead:")) + self.label_9.setText(_translate("generalizer", "Alpha:")) + self.label_10.setText(_translate("generalizer", "Beta:")) + self.bBrowse.setText(_translate("generalizer", "Browse")) + self.cbOutFile.setText(_translate("generalizer", "Save output layer")) + item = self.tblBatchAlg.horizontalHeaderItem(0) + item.setText(_translate("generalizer", "Algorithm")) + item = self.tblBatchAlg.horizontalHeaderItem(1) + item.setText(_translate("generalizer", "Parameter 1")) + item = self.tblBatchAlg.horizontalHeaderItem(2) + item.setText(_translate("generalizer", "Parameter 2")) + self.bAddAlg.setText(_translate("generalizer", "Add")) + self.bDelAlg.setText(_translate("generalizer", "Delete")) + self.bEditAlg.setText(_translate("generalizer", "Edit")) + self.bBrowseDir.setText(_translate("generalizer", "Browse")) + self.cbOutDir.setText(_translate("generalizer", "Save output layer(s) to folder")) + self.label_5.setText(_translate("generalizer", "Algorithm(s)")) + self.label_6.setText(_translate("generalizer", "Choose layer(s)")) From 5e3805c9aee9baf75f62cc17f04af71cb76e485f Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 6 Nov 2019 09:17:46 +0400 Subject: [PATCH 10/43] Update matrix.py --- matrix.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/matrix.py b/matrix.py index d67f8c0..10f24e1 100644 --- a/matrix.py +++ b/matrix.py @@ -1,3 +1,4 @@ +from builtins import object class MATRIX(object): def __init__(self, rows, cols): self.rows = rows @@ -104,4 +105,4 @@ def matrix_mult(a, b): i = i+1 - return res \ No newline at end of file + return res From e666f2e116a5df6f11d29c8b2e618abce36617fe Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 6 Nov 2019 09:18:31 +0400 Subject: [PATCH 11/43] Update resources.py --- resources.py | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/resources.py b/resources.py index a45ea74..9d97926 100644 --- a/resources.py +++ b/resources.py @@ -2,14 +2,13 @@ # Resource object code # -# Created: N 28. sie 10:51:26 2011 -# by: The Resource Compiler for PyQt (Qt v4.7.1) +# Created by: The Resource Compiler for PyQt5 (Qt v5.13.1) # # WARNING! All changes made in this file will be lost! -from PyQt4 import QtCore +from PyQt5 import QtCore -qt_resource_data = "\ +qt_resource_data = b"\ \x00\x00\x17\xc5\ \x89\ \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ @@ -395,7 +394,7 @@ \xae\x42\x60\x82\ " -qt_resource_name = "\ +qt_resource_name = b"\ \x00\x07\ \x07\x3b\xe0\xb3\ \x00\x70\ @@ -410,17 +409,36 @@ \x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\ " -qt_resource_struct = "\ +qt_resource_struct_v1 = b"\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ \x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\ \x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ " +qt_resource_struct_v2 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01\x42\x89\xb8\xd4\xc8\ +" + +qt_version = [int(v) for v in QtCore.qVersion().split('.')] +if qt_version < [5, 8, 0]: + rcc_version = 1 + qt_resource_struct = qt_resource_struct_v1 +else: + rcc_version = 2 + qt_resource_struct = qt_resource_struct_v2 + def qInitResources(): - QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) def qCleanupResources(): - QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) qInitResources() From de4e4589e603b3523e6e63149d66994d9eb9ba6d Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Fri, 8 Nov 2019 10:11:32 +0400 Subject: [PATCH 12/43] Create README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..9081acc --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Generalizer +Generalizer plugin for QGIS 3. Originally written by Piotr Pociask + +Plugin to Generalize, Simplify or Smooth lines in QGIS + From a1b8c90c895adb9ffe4f628ac9dec8c069c4a7e5 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Fri, 8 Nov 2019 10:19:43 +0400 Subject: [PATCH 13/43] Update README.md --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 9081acc..80c0342 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,21 @@ Generalizer plugin for QGIS 3. Originally written by Piotr Pociask Plugin to Generalize, Simplify or Smooth lines in QGIS +Functions : +- Remove small objects + +- Simplify : + * Douglas-Peucker Algorithm + * Jenk's Algorithm + * Lang Algorithm + * Reumann-Witkam Algorithm + * Vertex Reduction + + - Smooth : + * Boyle's Forward-Looking Algorithm + * Chaiken's Algorithm + * Hermite Spline Interpolation + * McMaster's Distance-Weighting Algorithm + * McMaster's Sliding Averaging Algorithm + * Snakes Algorithm + From b24406a6c075d605bcdd8c9f5f67bb6963b5d72f Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 11:55:40 +0400 Subject: [PATCH 14/43] Better readme based on Grass GIS doc --- README.md | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 80c0342..3ada28d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Generalizer +# ![Logo Generalizer](icon.png)Generalizer Generalizer plugin for QGIS 3. Originally written by Piotr Pociask Plugin to Generalize, Simplify or Smooth lines in QGIS @@ -8,6 +8,9 @@ Functions : - Simplify : * Douglas-Peucker Algorithm + + ![Douglas](https://grass.osgeo.org/grass79/manuals/v_generalize_simplify.png "Original line is black") + * Jenk's Algorithm * Lang Algorithm * Reumann-Witkam Algorithm @@ -15,9 +18,36 @@ Functions : - Smooth : * Boyle's Forward-Looking Algorithm + + ![Boyle's](https://grasswiki.osgeo.org/w/images/thumb/V.generalize.pic15.png/400px-V.generalize.pic15.png "Original line is black") + * Chaiken's Algorithm + + ![Chaiken's smooth](https://grass.osgeo.org/grass79/manuals/v_generalize_smooth.png "Original line is black") + + ![Chaiken's](https://grasswiki.osgeo.org/w/images/thumb/V.generalize.pic7.png/400px-V.generalize.pic7.png "Original is black") + * Hermite Spline Interpolation + + ![Hermite](https://grasswiki.osgeo.org/w/images/thumb/V.generalize.pic8.png/400px-V.generalize.pic8.png "Original is black") + + ![Hermite and Chaiken](https://grasswiki.osgeo.org/w/images/thumb/V.generalize.pic9.png/400px-V.generalize.pic9.png "Original = black, Green = Chaiken, Blue = Hermite") + * McMaster's Distance-Weighting Algorithm + + ![Distance Weighting](https://grasswiki.osgeo.org/w/images/thumb/V.generalize.pic13.png/400px-V.generalize.pic13.png "Original line is black") + * McMaster's Sliding Averaging Algorithm - * Snakes Algorithm + + ![Sliding](https://grasswiki.osgeo.org/w/images/thumb/V.generalize.pic11.png/400px-V.generalize.pic11.png "Original line is black") + + ![Sliding2](https://grasswiki.osgeo.org/w/images/thumb/V.generalize.pic12.png/400px-V.generalize.pic12.png "Original line is black") + + * Snakes Algorithm : + Slowest smoothing algorithm + + ![Snakes](https://grasswiki.osgeo.org/w/images/thumb/V.generalize.pic14.png/400px-V.generalize.pic14.png "Original line is black") + + +Which algorithm to choose : https://grasswiki.osgeo.org/wiki/V.generalize_tutorial From 0b2945ec297ac721bd4c2a8723e5ed96a52a5c13 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 12:23:18 +0400 Subject: [PATCH 15/43] Correction to make sliding working --- smooth.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/smooth.py b/smooth.py index 6d3085b..ca8b7e2 100644 --- a/smooth.py +++ b/smooth.py @@ -80,7 +80,7 @@ def sliding_averaging(points, slide, look_ahead): point_assign(points, i, s) point_scalar(s, 1. - slide, s) point_scalar(p, sc*slide, tmp) - points_add(tmp, s, res[i]) + points_add(tmp, s, res[int(i)]) if i+half+1 < n: point_assign(points, i-half, tmp) point_substract(p, tmp, p) @@ -90,7 +90,7 @@ def sliding_averaging(points, slide, look_ahead): i = half while i+half < n: - points.repleace_point(i, res[i]) + points.repleace_point(i, res[int(i)]) i = i + 1 @@ -156,12 +156,12 @@ def distance_weighting(points, slide, look_ahead): else: point_scalar(s, slide/dists, tmp) point_scalar(c, 1.-slide, s) - points_add(s, tmp, res[i]) + points_add(s, tmp, res[int(i)]) i = i + 1 i = half while i+half < n: - points.repleace_point(i, res[i]) + points.repleace_point(i, res[int(i)]) i = i + 1 From ac113163b5cce48839a7c48889f9062eb9836b79 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 12:23:51 +0400 Subject: [PATCH 16/43] Correction to make sliding working --- points.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/points.py b/points.py index 973e465..566955c 100644 --- a/points.py +++ b/points.py @@ -29,8 +29,8 @@ def add_points(self, pts): self.n_points = len(self.x) def repleace_point(self, index, p): - self.x[index] = p.x - self.y[index] = p.y + self.x[int(index)] = p.x + self.y[int(index)] = p.y def repleace_all_pts(self, pts): self.x = pts.x[:] @@ -74,8 +74,8 @@ def point_substract(a, b, res): res.y = a.y - b.y def point_assign(points, index, res): - res.x = points.x[index] - res.y = points.y[index] + res.x = points.x[int(index)] + res.y = points.y[int(index)] def point_dist(a, b): From 658800e5a23fdf3db44f7d313a9125b4f5e0ff28 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 12:26:08 +0400 Subject: [PATCH 17/43] Comments update --- generalizer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/generalizer.py b/generalizer.py index 8cdadad..646943e 100644 --- a/generalizer.py +++ b/generalizer.py @@ -7,6 +7,8 @@ begin : 2011-08-17 copyright : (C) 2011 by Piotr Pociask email : ppociask (at) o2 pl + adapted to QGIS 3 : 2019-11-10 by Sylvain POULAIN + email : sylvain.poulain (at) giscan.com ***************************************************************************/ /*************************************************************************** From ef69350f70447977cdd41b8292693f6e4740699c Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 12:26:42 +0400 Subject: [PATCH 18/43] Comments update --- generalizerdialog.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/generalizerdialog.py b/generalizerdialog.py index 635b44e..ff482d8 100644 --- a/generalizerdialog.py +++ b/generalizerdialog.py @@ -7,6 +7,8 @@ begin : 2011-08-17 copyright : (C) 2011 by Piotr Pociask email : ppociask (at) o2 pl + adapted to QGIS 3 : 2019-11-10 by Sylvain POULAIN + email : sylvain.poulain (at) giscan.com ***************************************************************************/ /*************************************************************************** @@ -51,6 +53,7 @@ 'RW':'Reumann-Witkam Algorithm' } +crs = QgsProject.instance().crs() class generalizerDialog(QDialog): def __init__(self, iface): @@ -490,10 +493,14 @@ def doGeneralize(self, iLayerName, iLayer, oPath, func, arguments): fields = iProvider.fields() if oPath == 'memory': #create memory layer + #if iLayer.wkbType() == QgsWkbTypes.LineString: + # mLayer = QgsVectorLayer('LineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') + #else: + # mLayer = QgsVectorLayer('MultiLineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') if iLayer.wkbType() == QgsWkbTypes.LineString: - mLayer = QgsVectorLayer('LineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') + mLayer = QgsVectorLayer('LineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') else: - mLayer = QgsVectorLayer('MultiLineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') + mLayer = QgsVectorLayer('MultiLineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') mProvider = mLayer.dataProvider() mProvider.addAttributes( [key for key in fields] ) From 8948aab07238bc8a642c80a7c73fe168ebd02d37 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 12:41:05 +0400 Subject: [PATCH 19/43] Correct error on first load --- generalizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generalizer.py b/generalizer.py index 646943e..3715647 100644 --- a/generalizer.py +++ b/generalizer.py @@ -26,7 +26,7 @@ from PyQt5.QtCore import * from PyQt5.QtGui import * -from PyQt5.QtWidgets import QAction +from PyQt5.QtWidgets import QAction, QMessageBox from qgis.core import * From ec1ebf6851ea0ee75ac62889fd57a4f610c3a4ed Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 12:44:39 +0400 Subject: [PATCH 20/43] Release 0.6 --- CHANGELOG | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 701cf30..c257e8d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +0.6 (10.11.2019) +- updated to QGIS 3.x +- fix projection according to project coordinates + 0.5 (24.11.2013) -updated to QGIS 2.0 API (thanks to Matthew Petroff) -fix unicode error @@ -21,4 +25,4 @@ smoothing: Hermite Spline Interpolation -supported algorithms: generalization: Remove small objects simplifying: Douglas-Peucker, Lang, Vertex Reduction -smoothing: Boyle's Forward-Looking, Chaiken's, McMaster's Distance-Weighting, McMaster's Sliding Averaging \ No newline at end of file +smoothing: Boyle's Forward-Looking, Chaiken's, McMaster's Distance-Weighting, McMaster's Sliding Averaging From 31f4ba2b95ba6202e31d97afcc4da45255c252c6 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 12:46:49 +0400 Subject: [PATCH 21/43] release 0.6 --- metadata.txt | 52 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/metadata.txt b/metadata.txt index 7539bc4..75e8e87 100644 --- a/metadata.txt +++ b/metadata.txt @@ -1,32 +1,52 @@ -# This file contains metadata for your plugin. Beginning -# with version 1.8 this is the preferred way to supply information about a -# plugin. The current method of embedding metadata in __init__.py will -# be supported until version 2.0 - -# This file should be included when you package your plugin. - -# Mandatory items: - - [general] name=Generalizer qgisMinimumVersion=3.0 description=Lines generalization and smoothing (partially based on v.generalize GRASS module) version=0.6 -author=Piotr Pociask -email= +author=Piotr Pociask, Matthew Petroff, Sylvain POULAIN +email=sylvain.poulain (at) giscan.com # end of mandatory metadata # Optional items: -homepage=https://github.com/p0cisk/Generalizer -tracker=https://github.com/p0cisk/Generalizer/issues -repository=https://github.com/p0cisk/Generalizer +homepage=https://github.com/giscan/Generalizer +tracker=https://github.com/giscan/Generalizer/issues +repository=https://github.com/giscan/Generalizer icon=icon.png # experimental flag -experimental=True +experimental=False # deprecated flag (applies to the whole plugin, not just a single version deprecated=False + +changelog= +0.6 (10.11.2019) +- updated to QGIS 3.x +- fix projection according to project coordinates + +0.5 (24.11.2013) +-updated to QGIS 2.0 API (thanks to Matthew Petroff) +-fix unicode error + +0.4 (27.10.2013) +-add setDecimal() method in batch mode. Added by Bakhtiar Hasmanan + +0.3 (15.09.2011) +-new algorithms: +smoothing: Snakes Algorithm +simplifying: Jenk's Algorithm, Reumann-Witkam Algorithm + +0.2 (11.09.2011) +-added batch mode +-choose to save layer(s) on disk or to store in memory +-new algorithms: +smoothing: Hermite Spline Interpolation + +0.1 (28.08.2011) +-first release +-supported algorithms: +generalization: Remove small objects +simplifying: Douglas-Peucker, Lang, Vertex Reduction +smoothing: Boyle's Forward-Looking, Chaiken's, McMaster's Distance-Weighting, McMaster's Sliding Averaging From 2d4a4eaa7f9bf1015bbae482c2a7eba162688860 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 12:48:45 +0400 Subject: [PATCH 22/43] Update metadata.txt --- metadata.txt | 53 ++++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/metadata.txt b/metadata.txt index 75e8e87..e8d8aab 100644 --- a/metadata.txt +++ b/metadata.txt @@ -16,37 +16,32 @@ repository=https://github.com/giscan/Generalizer icon=icon.png # experimental flag -experimental=False +experimental=True # deprecated flag (applies to the whole plugin, not just a single version deprecated=False changelog= -0.6 (10.11.2019) -- updated to QGIS 3.x -- fix projection according to project coordinates - -0.5 (24.11.2013) --updated to QGIS 2.0 API (thanks to Matthew Petroff) --fix unicode error - -0.4 (27.10.2013) --add setDecimal() method in batch mode. Added by Bakhtiar Hasmanan - -0.3 (15.09.2011) --new algorithms: -smoothing: Snakes Algorithm -simplifying: Jenk's Algorithm, Reumann-Witkam Algorithm - -0.2 (11.09.2011) --added batch mode --choose to save layer(s) on disk or to store in memory --new algorithms: -smoothing: Hermite Spline Interpolation - -0.1 (28.08.2011) --first release --supported algorithms: -generalization: Remove small objects -simplifying: Douglas-Peucker, Lang, Vertex Reduction -smoothing: Boyle's Forward-Looking, Chaiken's, McMaster's Distance-Weighting, McMaster's Sliding Averaging + 0.6 (10.11.2019) + - updated to QGIS 3.x + - fix projection according to project coordinates + 0.5 (24.11.2013) + -updated to QGIS 2.0 API (thanks to Matthew Petroff) + -fix unicode error + 0.4 (27.10.2013) + -add setDecimal() method in batch mode. Added by Bakhtiar Hasmanan + 0.3 (15.09.2011) + -new algorithms: + smoothing: Snakes Algorithm + simplifying: Jenk's Algorithm, Reumann-Witkam Algorithm + 0.2 (11.09.2011) + -added batch mode + -choose to save layer(s) on disk or to store in memory + -new algorithms: + smoothing: Hermite Spline Interpolation + 0.1 (28.08.2011) + -first release + -supported algorithms: + generalization: Remove small objects + simplifying: Douglas-Peucker, Lang, Vertex Reduction + smoothing: Boyle's Forward-Looking, Chaiken's, McMaster's Distance-Weighting, McMaster's Sliding Averaging From 96c5d0646d95e1ad1789d2f5b17c94fabe9fe4f1 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 12:49:40 +0400 Subject: [PATCH 23/43] release 0.6 --- generalizerdialog.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/generalizerdialog.py b/generalizerdialog.py index ff482d8..3fad443 100644 --- a/generalizerdialog.py +++ b/generalizerdialog.py @@ -327,16 +327,15 @@ def BatchOn(self, state): def showHelp(self): #show information about plugin QMessageBox.information(self, 'Generalizer', """Generalizer -Version 0.5 +Version 0.6 -Created by +Originally created by Piotr Pociask +Adapted to QGIS3 by +Sylvain POULAIN -This plugin is marked as experimental. -If you find any bugs or have suggestions, -please contact with me: -opengis84 (at) gmail (dot) com - +Documentation available : +https://github.com/giscan/Generalizer/wiki """) def outFile(self): From 528f42d2658c4cd0e26a11b124ad6abc2710b352 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 13:01:32 +0400 Subject: [PATCH 24/43] Update CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index c257e8d..8b8a2b9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ 0.6 (10.11.2019) - updated to QGIS 3.x - fix projection according to project coordinates +- quick documentation 0.5 (24.11.2013) -updated to QGIS 2.0 API (thanks to Matthew Petroff) From 5c748edadcaedc1ffc05e4750bc225b2d3e90e52 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 10 Nov 2019 13:06:28 +0400 Subject: [PATCH 25/43] 0.6 release --- metadata.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/metadata.txt b/metadata.txt index e8d8aab..f5b789e 100644 --- a/metadata.txt +++ b/metadata.txt @@ -25,6 +25,7 @@ changelog= 0.6 (10.11.2019) - updated to QGIS 3.x - fix projection according to project coordinates + - quick documentation 0.5 (24.11.2013) -updated to QGIS 2.0 API (thanks to Matthew Petroff) -fix unicode error From 8eb82eaa9ce246188dc5ad92c3153040f2819534 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Mon, 11 Nov 2019 16:47:07 +0400 Subject: [PATCH 26/43] Delete resources.py --- resources.py | 444 --------------------------------------------------- 1 file changed, 444 deletions(-) delete mode 100644 resources.py diff --git a/resources.py b/resources.py deleted file mode 100644 index 9d97926..0000000 --- a/resources.py +++ /dev/null @@ -1,444 +0,0 @@ -# -*- coding: utf-8 -*- - -# Resource object code -# -# Created by: The Resource Compiler for PyQt5 (Qt v5.13.1) -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore - -qt_resource_data = b"\ -\x00\x00\x17\xc5\ -\x89\ -\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ -\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\ -\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\ -\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\x0d\xd7\ -\x01\x42\x28\x9b\x78\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\ -\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\ -\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x17\x42\x49\x44\ -\x41\x54\x78\x9c\xed\x9b\x5b\x6c\x5d\xd7\x9d\xde\x7f\xdf\xda\xfb\ -\x5c\x78\x48\xf1\x4e\x91\x12\x69\x49\xb6\x25\xcb\x36\x6d\xc7\x36\ -\xed\xf8\x96\xd8\x72\x9a\x66\xea\x41\x9b\x5e\x50\x69\x8a\x4e\xd1\ -\x87\x00\x35\x50\x14\x19\xa0\x83\xe9\xbc\x8a\x7c\x9d\x87\x0e\xd0\ -\x3c\x65\x80\x62\xda\x87\xbe\x48\x40\x81\xa6\xd3\x64\x92\x60\x12\ -\x66\x9a\x9b\xe3\xc8\x76\xe2\x50\x96\x2d\x59\x17\x8b\xa4\x28\x91\ -\xa2\xc4\x8b\x78\x6e\x7b\xaf\xaf\x0f\xe7\x50\x17\x5b\x96\x25\xc5\ -\x99\x04\x98\xfe\x81\x03\xf0\x90\xe7\xec\xf5\x5f\xdf\xfa\xfe\xf7\ -\x45\xd9\xe6\xef\xb3\x84\xdf\xb6\x02\xbf\x6d\xf9\xff\x00\xfc\xb6\ -\x15\xf8\x6d\xcb\xdf\x7b\x00\xd2\xdb\xf9\x90\x84\x00\x6c\x7e\x27\ -\x3c\x66\x5b\x9f\xcd\x97\x41\xf6\x5d\x7a\x73\xdd\xea\x7b\x12\x7a\ -\xf5\xd5\x23\x29\x9c\x2b\x74\x76\x0e\xf8\xca\x95\x62\xb6\x7d\xfb\ -\x5f\xe5\x93\x93\x93\x77\xbd\xe0\xaf\x2b\x12\x9a\x98\x20\x5d\x5c\ -\xfc\xa0\x4b\xaa\x94\xed\x8d\xda\xd0\xd0\x8e\xf5\x23\x47\xc8\xee\ -\xe6\x80\x6e\x09\xc0\xd4\xd4\x74\x3a\x3b\xdb\x31\x10\x42\x63\x34\ -\x0f\xa4\x49\x4c\x2e\xe6\xf9\xda\xa5\x4a\xe5\xfe\x2b\x0b\x0b\x6f\ -\x66\x87\x0f\xef\x8f\x7f\x97\xac\x90\xd0\xee\xdd\x14\xab\xd5\xe5\ -\x21\xf0\x03\x0e\x61\x6b\xb0\x16\x6a\xca\xde\x5b\x3a\x7b\x61\x09\ -\x1e\x6e\xde\xa9\x3e\x1f\x0b\x80\x84\xbe\xf2\x95\x6f\x74\x25\x49\ -\xef\xa3\x04\xbe\x60\x6b\x20\x5a\x67\x9d\xf1\x9e\x1d\xcf\xd4\xeb\ -\xa5\x0b\x5b\xb6\xa4\x6b\xef\x6d\x5f\x6b\x4c\x4f\xee\xcb\x7f\xd3\ -\x40\x48\x68\xd7\xae\xd3\x25\x28\x8f\xd8\x85\x27\x73\xf3\x12\xd6\ -\x3d\x79\xe4\x94\x89\xdf\xcb\xea\xbc\xb1\xb4\x34\xb8\x04\x77\xc6\ -\x84\x8f\x05\xe0\xc0\x81\xc3\xc9\xf0\x70\xef\x70\xb3\x59\xfa\x62\ -\x84\x3f\x88\xd6\xfd\x8e\x61\xd5\x91\x53\x46\xef\xc4\x2c\xbc\x93\ -\xe1\x53\xb1\x91\x9e\xdb\xa8\x34\x2e\x8f\xa4\xe5\xda\x6f\xca\x3c\ -\x5a\x9b\xa7\x14\x8b\x17\xb6\x87\x3c\x7c\xd6\xb9\xbf\x14\xa3\x9e\ -\xc9\xad\x7e\xa2\x16\x72\xf8\x81\x23\xdf\x22\x2f\xbd\x75\xe1\xc2\ -\xb1\x65\x78\x2a\xbb\x5d\x1d\x3e\xd6\x09\x8e\x8c\x74\xa5\xb5\x98\ -\xf6\x49\xdc\x2b\x73\x8f\x60\xcc\x20\xa3\x9d\xd1\x7a\xd8\xf0\x01\ -\xd6\xbb\x4a\x7d\xb4\x54\x2d\x1e\x5f\x89\xcc\xce\xad\xff\x83\xe5\ -\x57\x5e\xf9\xc3\x8d\xa9\x29\x9a\x93\x93\xf8\xd3\x62\xc5\xbe\x7d\ -\x24\xf3\xf3\xb3\x03\xcd\x58\x7a\xd2\xf6\xef\x21\x9e\x47\x8c\x2a\ -\x52\x8a\xa2\xa2\xa8\x68\x87\x46\xae\x2c\x1b\x19\xd9\xfb\xcb\x85\ -\x05\x5f\x02\xb2\xdb\x79\xf6\x4d\xc3\xa0\x24\xe5\x79\x47\x21\x8d\ -\x0c\x02\x3b\xc0\xfd\x12\x25\x70\x07\x30\x80\xbd\xc7\xf0\x9c\xac\ -\x7f\x62\xeb\x0f\x05\xff\x26\xb3\xbf\xdc\xd1\xe8\x7c\xb6\x52\xb9\ -\xb2\xfb\xc8\xbb\xef\xf5\xef\xdb\x37\x5d\x9a\x9a\xfa\x74\xc2\xec\ -\xec\xec\x89\x24\xc6\xb4\x47\xb0\x1b\xf1\x20\x30\x02\x74\x20\x52\ -\x4c\xa7\xe1\x3e\xf0\x4b\xc0\x17\xb2\x2c\x7b\x78\x74\x74\xad\x47\ -\x9a\xbe\xad\x08\x77\xd3\x0f\xed\xdf\x7f\x28\xc4\x58\xac\x84\x90\ -\x8d\x08\x46\x8d\xba\x1c\x49\x68\x85\x9d\x04\x42\x00\x15\x0c\x5d\ -\xc2\xc3\xb2\xee\x17\x3c\x16\xf1\x49\x94\x1d\x4d\xaa\x1b\x6f\x77\ -\x76\x76\xbf\xfb\xd6\x5b\x6f\x9d\x7b\xf9\xe5\xc7\xd7\xa7\xa7\xf9\ -\xb5\x7c\x44\x4f\xcf\x4a\xbc\x78\xb1\x6b\x23\x84\x78\x41\x84\x45\ -\xc3\x06\xd0\x01\x6a\xe9\x63\xb6\x18\xf6\x60\x65\x11\x35\xab\x55\ -\x9a\x3d\x3b\x9e\x78\x47\x62\xd5\x26\xbf\x63\x00\xfa\xfa\xee\x0b\ -\x79\x72\xb9\x57\xa4\x3b\x40\x43\x98\x52\x7b\xf3\x6d\x71\x3b\x06\ -\x2b\xd8\xa4\x86\x16\x33\xe4\x9d\x31\x0f\x0f\x45\x78\x24\x84\xf0\ -\x7a\x9e\xfb\xf5\xee\xee\x77\x8f\xef\xdb\x57\x5a\x96\x76\x35\x6c\ -\xe2\xdd\x00\x70\xe4\xc8\x44\x36\x3e\xbe\xb8\x74\xe5\x0a\x6f\x48\ -\xea\x03\x2a\xc6\x8f\x81\xfb\x40\x69\x0b\x04\x6d\x01\xf6\x1a\x65\ -\x88\x86\xaf\x14\xb3\xde\xde\xcb\xef\x49\xbd\x6b\xb7\x02\xe1\x23\ -\x14\x95\x24\xa0\x10\x48\x07\xc0\x3b\xb1\xfb\x3f\x04\x94\x41\xb1\ -\xf5\xc2\x6d\x60\x52\xa0\x03\x33\x08\x3c\x80\xfd\xa2\xc5\x3f\x37\ -\xe1\x5f\x34\x63\xed\xf3\x1d\x1d\x97\xee\xfb\xe2\x17\x8f\x6c\x79\ -\xf9\xe5\xe9\x74\x33\xa9\xba\x13\xb1\xf1\xcc\xcc\x74\x35\x84\xf4\ -\x94\xa4\xbf\x8d\xd1\xdf\x13\x3a\x0a\xac\x80\xda\xb6\xee\x14\xd3\ -\x03\x3c\x64\x87\x2f\x28\x66\x2f\xd9\xc5\xfb\xfa\xfb\xe9\x94\x3e\ -\xde\x14\x3f\xc2\x80\xc9\xc9\x49\xad\xac\x34\xca\xb5\x9a\x87\x15\ -\x18\x03\xba\x41\x9b\x0f\x30\xb8\x01\xae\xba\xc5\x80\x22\x50\x80\ -\xeb\xcd\x83\x32\x52\x01\xab\x12\xcd\x00\x0e\xdb\xad\x30\x9a\x24\ -\x7e\xbd\x9e\x0c\x9f\xd8\xb7\xef\xf4\xa5\xbb\x61\x83\xbd\x3f\x97\ -\x58\xdf\xb1\x63\xe5\x44\x50\xbd\x90\x5b\x05\xa3\x14\xfc\x30\xa8\ -\xbb\xbd\x76\x82\xd5\x6b\xfc\x88\x63\xc8\xb0\x1a\xf5\xfa\x95\x1c\ -\xaa\x27\xa5\xc1\x2b\x37\x5b\xf3\x26\x26\xf0\x52\xb0\xeb\xdd\x4a\ -\x19\xb3\x19\x96\x28\xdb\x0e\x6d\x0b\xc8\x8c\x17\x11\xef\x83\x6a\ -\x88\x41\x60\x18\xdc\x0b\x2a\xb5\x9f\x27\x20\x95\xd4\x05\xda\x69\ -\xd3\xed\xa8\x91\xdc\x8c\x15\xf1\x8f\x63\xb9\xfe\xf6\x2b\xaf\x9c\ -\x38\xf7\xf2\xcb\xb3\x1b\xd3\xd3\x77\x96\x3f\xd8\xe4\x52\xcf\xea\ -\xe8\xe8\xdc\xbb\x21\x14\x53\x47\x15\x8c\x53\xc3\x5e\xd0\x16\x70\ -\xd2\x62\x82\xfa\x11\x8f\xd9\x31\x93\xd4\xec\xea\xea\xce\xd6\xd7\ -\x39\x2d\x51\xfd\x30\x08\x1f\x01\x60\x66\x66\xb1\x30\x38\xd8\x33\ -\xa0\xa4\xb8\x13\x34\x40\xeb\x84\xa1\x45\xf7\x9a\xa4\x93\x96\xbf\ -\x45\xce\x9c\x1d\xb7\xe1\xe4\x41\xa3\x3d\x46\xf7\x00\x03\xb4\xfc\ -\x41\xd2\x02\x8d\x12\x68\xc8\x50\x81\x30\x00\xda\xee\x66\x1c\xad\ -\xdb\xaf\xc3\xd6\x93\xaf\xbc\x72\xe2\x92\xf4\x3f\x9a\xf6\xc1\xdb\ -\x66\x43\x0b\x84\xd1\x95\x91\x91\x85\x77\x9c\x84\x54\x56\x51\x28\ -\xb5\xbd\x07\xd4\x45\xcb\xac\x53\xcc\x80\x1d\x3e\x03\x34\x63\x8c\ -\xcd\x62\xb1\x91\x37\x1a\xc5\x0f\xa4\xa9\xda\xf5\xeb\xdd\x00\x40\ -\x2b\xf7\xef\x2b\xaa\xa0\x21\xcc\x3d\x32\x3d\x6e\xfb\x09\x89\x1c\ -\xb1\x2a\xf4\x7e\xc0\x6f\x34\x92\x70\xcc\xf5\x66\x87\x93\xf0\x73\ -\xe5\xc9\x5e\xe1\xc7\x23\xe1\x31\xc1\xbd\x40\x9f\xa4\xc2\xa6\x32\ -\x12\x5b\x80\x7b\xb1\x7b\xa4\x30\x92\xa3\x51\x2b\xfc\x74\x6d\x2d\ -\xfb\xd5\x0b\x2f\xfc\x87\x73\x2f\xbf\x3c\x5d\xbd\x13\x36\xd8\x64\ -\xd2\xdc\xe5\xe1\xe1\xbd\xbf\x8a\x49\x23\x15\xb1\x00\x21\x05\xdd\ -\x07\x74\xb6\xd7\x2d\x00\x43\xd1\x3c\x69\x9c\x85\x10\x9b\xa5\x52\ -\x3d\xaf\xd7\x0f\xce\x4a\xd4\x36\xd7\xba\x01\x80\x7d\xfb\xa6\x93\ -\x52\x29\xdd\x62\x31\x1a\xa3\xb7\xd1\x3a\xb9\xd0\x3e\xff\x5c\xe6\ -\x92\xed\xd3\x39\xcd\x73\x65\x8f\x2e\x5e\x89\xaf\xc7\x62\xba\x63\ -\x21\x0f\xcd\x53\xce\x8b\xef\x39\xc6\x93\x26\x7d\x16\x34\x6e\x7b\ -\x1b\xa8\xcd\x06\x02\x50\x32\xde\x6a\xbb\x42\x64\xd0\x84\x31\x8b\ -\xed\x8e\x97\x8f\x54\xab\x83\x27\x77\xef\x3e\x71\xf9\xce\xd8\x30\ -\x91\x9d\x3f\xcf\xa5\xc1\xc1\xa5\xb7\x49\x93\x82\x50\xd1\xa6\x00\ -\xda\x45\x8b\x85\x02\x17\x21\x6c\xb5\x99\x00\x9a\xb6\x9a\x94\xeb\ -\x39\xb5\xd2\xbc\x44\xdd\xc6\x37\x00\xf0\xe8\xa3\xd5\xc4\x69\xa1\ -\x8f\x3c\xd9\x29\x31\xd8\x7a\xa0\x05\xb2\xa1\x81\x58\x94\xf4\x41\ -\x21\x2f\x2c\x9f\x3c\xfd\xdf\xb3\xef\x7f\xff\x60\x26\xd1\x7c\xf5\ -\xd5\x23\xd5\xb9\xf5\x8d\x95\x72\xdc\x72\x3e\x27\x9e\x35\x9a\xc3\ -\x9a\x68\x9f\x48\xef\x35\x36\x28\x95\xd4\x1d\x51\x49\x76\x2f\xd2\ -\x48\x0c\x8c\x41\xf9\x27\x43\x43\x9a\x49\x86\xff\xd5\xf9\x03\x07\ -\xd8\x38\x7c\x58\xf1\x93\x52\x59\x1b\x4b\x64\x5d\x5d\xeb\x97\xaa\ -\xd5\x8e\xa3\x79\x2c\xf6\xa2\x74\x08\xd3\xdb\x76\xce\x6d\x7f\xe4\ -\x12\x68\x9b\xad\xa7\x0d\xcd\x24\xaa\x99\x53\x7b\x0d\xca\x0b\x12\ -\x8d\xab\x00\x48\xe8\x2b\x7f\xda\x5d\xec\xca\xb2\xc1\x18\xe2\x0e\ -\x22\xbd\xf6\x55\x86\x44\xf0\x86\x61\x81\x3c\x9b\xaf\xd7\x4b\xeb\ -\xd3\xd3\x07\xf3\x4d\x45\x60\xa2\x39\x35\xc5\xca\xcc\xcc\x4f\x6a\ -\x81\xca\xe5\x7a\x93\x05\xe3\x59\xcc\x73\x58\xe3\xb6\x87\x37\xd9\ -\xd4\x66\x43\xd9\x66\x18\x87\x8a\xd0\x20\x78\x34\xb3\xb6\x6f\x89\ -\xc5\x23\x27\x16\x16\x4e\x8d\x8f\xcf\xac\x48\x7c\x6c\x65\xd7\x0a\ -\xd5\xd6\xee\xdd\x14\xaa\xd5\x42\x27\x14\x3b\x5b\x24\xa5\x8a\xdd\ -\x68\xfd\x78\x35\xda\xaa\xc5\x3e\xb6\x83\x9e\xc1\xb1\x99\x24\x85\ -\x66\x9e\xf3\x3a\x70\xe1\x2a\x00\xfb\xf7\x1f\x0e\x5b\xea\xfd\x95\ -\x28\xb6\x63\x6d\xbf\xce\xa1\x00\xca\x11\x97\x65\x7d\x80\xbc\x58\ -\x28\x54\x1b\x1f\x56\xee\xe0\x41\xa2\xf4\x5c\x6d\xdf\x24\xe7\x3b\ -\x5f\x7f\x7b\xc3\x66\x29\x2a\xce\xa1\x30\xe7\xa8\x09\xe0\x5e\x70\ -\xaf\x14\xd2\x4d\x36\x80\x7b\x30\x65\xa3\x5e\xf0\x36\x72\x8d\x29\ -\x6f\xfc\xa4\x52\xe9\x3a\x3a\x3e\xbe\x78\xe1\xc0\x81\xa1\xea\x87\ -\xd9\x20\x11\x76\xef\x3e\x5e\xa8\xd5\x56\x3b\xd7\x1b\xd9\x88\x29\ -\xdd\x67\xf1\x10\x41\x8f\x06\xfb\x91\x28\xf5\x62\x7d\x38\xee\xab\ -\x05\xba\xc7\x44\x78\xc6\xc4\x8d\x34\xf5\x95\x2c\x4b\x6b\xd7\x4c\ -\x60\x9c\x24\x5f\xcb\xfb\x92\x98\xde\x93\xb7\xb2\xbf\xa2\x5a\xc5\ -\x8f\xc1\x19\xe6\xa2\xc4\x19\x93\x2d\xef\xda\x15\x6e\x5a\x68\xb4\ -\x41\xc9\xa6\xa6\x1e\x5d\x99\x99\x99\xad\xad\xac\x5c\xbe\xec\x10\ -\xcf\x41\x98\x33\x7a\x16\xf3\x70\x8b\x0d\xea\x68\xe7\x16\x01\x28\ -\x63\x46\x84\xba\xa2\x19\x74\x8c\xa3\x4d\x87\x1f\xab\x58\x7b\xe3\ -\xe4\xc9\x73\xa7\xc7\xc7\x67\x56\xa5\x56\x61\x33\x3e\x7e\x34\xdd\ -\xb5\x6b\x7b\x25\xcf\x7b\x87\x49\xf2\xfb\x13\xfb\x33\x39\xc9\x63\ -\x48\xbb\x05\xdb\xdc\x0a\xc7\xe5\x56\x38\xbc\x21\xdf\x72\xfb\x15\ -\x0c\xdd\x48\x3b\xec\x6c\x07\x64\xc7\xd3\x4d\x4a\xfd\xc9\x9f\x7c\ -\xbb\x90\xe5\x85\x81\x9c\xb8\x4b\xa6\x1f\x94\xfa\xea\x97\x5d\x95\ -\x74\x3e\xa2\xd9\x6a\xb1\xb8\x0a\x7f\x13\x61\xdf\xcd\x30\xb8\x8e\ -\x0d\x63\xb5\x89\x89\xf3\x0b\x23\x23\xc5\xf5\x5a\x5e\x58\x14\x71\ -\x36\xca\xcf\x63\x9e\xc4\xec\x32\xee\x01\x15\xda\xa7\x53\x70\x2b\ -\x8b\xdb\x23\xe8\x8b\xb0\x4d\x91\xb1\x46\xd6\xf8\x69\x96\x74\xbe\ -\x73\xdf\x7d\x27\x97\x63\x77\xbf\xea\xeb\x83\x03\x52\xe3\xbe\x48\ -\x78\x0c\xe2\x13\x36\x0f\x4a\x1e\x35\xee\x41\x49\x01\x6b\x33\x21\ -\xdb\x94\x08\xe4\x40\x43\x62\x15\x58\xc4\x3a\x25\xe2\xdb\x46\x73\ -\x90\x55\x53\x68\x65\x7f\x6b\x6b\x8d\x0e\x92\xc2\x70\x30\xa3\x31\ -\x67\xcb\x35\xfa\x6f\x86\x3f\xce\xc6\xc8\x85\xae\xfc\x72\xfd\xe0\ -\xc1\x4f\xf6\xd4\xd7\xfb\x86\x23\x47\x8e\xd4\xab\xd5\x8e\xcb\xd1\ -\x3a\x27\x6b\x16\xf1\x1c\xd6\x83\xc0\x56\x5a\x45\xcd\x26\x1b\x3a\ -\x0c\xdb\x84\x3a\xc1\x43\x26\x19\x4d\xad\xd7\x5c\x2a\x9c\xcc\x37\ -\x6a\x05\x4b\x7b\x2c\x1e\xc7\x3c\x2c\x7c\x8f\x50\xaf\x4d\xa9\xf5\ -\x7d\xab\xbd\x77\xb7\x37\x9e\x81\xab\x48\xcb\xe0\x73\x26\x9c\x44\ -\xbc\x8b\xe2\xbb\xb2\x4e\x65\x59\x71\x1e\x4a\x97\x53\x80\xf9\xf9\ -\x6d\x49\x67\x7f\x47\xb7\x9a\xf1\x9e\x68\x6d\x45\x94\xdb\xce\x0a\ -\x20\x93\x75\x31\x3a\x9c\x09\x79\x76\x91\x64\x5b\xf3\x93\x36\xff\ -\x51\x36\x4c\x54\x27\x26\x8e\x9c\x1b\x1c\xec\x58\xaf\xd7\xf3\x45\ -\x53\x98\x05\x3d\x0f\x7e\xd2\xb0\x13\xdc\x7d\x8d\x0d\x2a\x00\xbd\ -\x10\xca\x96\xfa\x9c\x7b\x57\x20\xcc\x3a\x50\x8c\x19\x3b\xa4\x70\ -\x4f\x8c\xee\x87\x50\xe2\x5a\x0a\xbe\xb9\xf1\x1c\xdc\x40\x5a\x97\ -\xb8\x20\xe9\xac\x22\xc7\x83\x7c\x0c\x87\xe3\x10\xe7\x1a\x8d\xc6\ -\x52\x4e\xd7\x3a\xd0\x04\xf2\x14\xa0\xb3\xb3\x2f\x0d\xcd\xe6\x40\ -\x24\xdd\x29\x31\x60\x2b\x6d\x3f\xd1\x92\xeb\x51\x2c\x2a\xe6\x67\ -\x63\x4c\x56\x56\x57\x4f\x46\x98\xb8\x13\x0c\xae\xb2\xe1\xc0\x81\ -\xc3\x2b\x2b\x2b\x7b\x8f\x67\x99\x2e\x35\x9b\x3a\x17\x1d\xe6\x20\ -\x3c\x03\x3c\x04\x1a\x6a\xd9\x2f\x89\xed\x04\xa8\x60\x8f\x5a\xea\ -\x33\xf1\x21\x48\x02\xa2\x53\x76\x59\x52\x62\xdf\x70\xe2\x39\x50\ -\x45\xbe\x04\x3a\x87\x39\x65\x74\xcc\xc4\x77\x93\x24\x39\xd5\x68\ -\x84\x85\x5a\x2d\xbd\x04\xd4\xa0\x98\xc1\xb5\x66\x4d\x3a\x35\x35\ -\x15\xdc\xf3\x52\xc9\x57\x9a\x43\x8e\xbe\x07\xab\x67\xd3\x89\x48\ -\xe4\x31\x6a\x0d\x7b\x2e\x49\x58\x48\xd3\xbc\xfa\x97\x7f\x79\x20\ -\x72\x97\xa5\xfd\xa1\x43\xfb\x73\x89\x8d\x89\x09\xe6\x7b\x7b\x8f\ -\xad\x5f\x69\x84\x45\xe5\x9e\x8d\x84\xe7\x8c\x9f\x00\x6d\xb2\x21\ -\xbd\xca\x06\x6b\x0b\xa8\xab\xbd\x64\xf0\x47\x4e\x9c\x1a\xb0\x8c\ -\x38\x63\x73\x2c\x84\xf0\xab\xdc\x7a\x2f\x2a\x3d\x4b\x56\x5c\xec\ -\xea\x66\x7d\x7e\x9e\x06\xdc\xbc\x27\x91\xc2\x4b\x41\x2b\xeb\x9d\ -\xa4\xa5\xad\x40\x7f\xab\xcb\xa2\x96\xd7\x34\x19\xf8\x92\xe4\x33\ -\x4d\x85\xa5\xb9\x53\x1b\xcd\x5f\xb7\xdf\xd7\x56\xa2\x79\xe0\xc0\ -\xdb\x97\x17\x57\x5e\xac\x55\x56\xab\xcb\x91\x7c\x1e\x27\xb3\x86\ -\x67\x5b\xbe\x41\x83\x52\x8b\x0d\x5c\xf5\x45\x9b\x95\xf7\xa6\x8d\ -\xbb\x0e\xba\x24\xf8\x00\xf9\x28\xe6\xcd\x10\x99\x69\x26\x85\x0f\ -\x42\xb3\xba\xbc\x7a\xb9\xb3\x0a\x64\xeb\xeb\xdc\xb2\x73\xdd\x8e\ -\x02\xc5\x80\xc9\xa4\x70\x21\x9a\xf9\x76\x95\x57\x01\xea\x88\xf3\ -\x92\xce\x84\xa6\x2e\x77\x75\xad\xdf\x56\x9f\xed\x76\x64\x93\x0d\ -\xe3\xe3\x47\xe7\xcb\x43\xe9\xba\xab\x85\x0b\x64\xf9\x9c\xe1\x79\ -\xf0\xe3\x36\x3b\x80\x2d\xd7\xd8\x70\xd5\xb9\x35\x68\xf5\x01\x66\ -\x11\xef\x08\xde\x44\xc9\x2f\x83\x39\xd5\x8c\xf9\xd2\xca\x52\xa9\ -\x0a\xa5\xfc\x76\xcb\xed\x14\x7e\x10\x0b\x85\x17\x56\x9b\x4d\x66\ -\x10\x89\xcc\x99\x08\x3b\x41\xc3\x88\x20\xc7\x63\x44\x3e\xc8\xb2\ -\x74\xfd\xf0\xe1\xfd\x77\xd5\xd1\xf9\x38\x69\xa5\xb3\xe3\xcd\xfd\ -\xfb\x7d\xe9\xe8\xd1\xa3\xb5\x4a\xa5\xeb\x52\x74\x98\x23\xf7\xac\ -\xe1\x19\xd0\x5e\x60\xb0\xed\x18\x73\x60\x15\x31\x2f\x78\x57\xd2\ -\x9b\x92\x7e\x41\x4c\xdf\x6f\x14\xf3\x0b\x97\xe6\xfa\x36\xb8\xc3\ -\x96\x38\xb4\xc7\x4b\x87\x0e\x1d\x0a\x3f\xff\x79\xa9\xb2\x9e\x95\ -\x7b\x89\x1a\x28\x38\x0c\x65\xd6\x08\x4e\xba\x4c\x3c\x1f\x9c\xbc\ -\x79\xfe\xfc\xf9\xb9\x43\x87\xf6\x37\x3e\x4d\x00\x6e\x50\x44\x68\ -\x7c\xfc\x68\xa1\x58\x2c\xf6\x34\x5c\xda\x15\x1c\x9e\x8c\x79\x7c\ -\x3e\x3a\x3c\x1a\xa3\xfa\x1c\xb5\x96\x47\x1d\xb7\xc3\x2f\x9c\xfb\ -\xad\x18\xd3\xe3\x79\x5e\x3d\xdf\xd3\x33\xb6\x3e\x33\x43\x76\xb7\ -\xed\xb6\xb4\x6d\xd3\xf9\xfe\xfd\xac\x4f\x4d\x4d\x57\x2f\x5e\xac\ -\x5e\x28\x75\x74\xbf\xdf\x5c\x6f\x76\xc6\xe8\x72\x9a\x66\x8d\x95\ -\x95\xe6\xca\xf8\xf8\xd1\x4f\x8d\xfe\x37\x93\xeb\xd8\xb0\x7c\xf4\ -\xe8\x62\xd5\xaa\x2d\xe7\x84\x39\x11\x4f\x88\x64\x38\xb7\x2e\x04\ -\x3c\x93\xa7\x7e\xaf\x1e\xe2\xb9\x4a\x1c\x58\x3b\x73\x86\xe6\xd9\ -\xb3\x77\xb7\xf1\x4d\xf9\xb8\xc1\x88\x0e\x1c\x38\x1c\xc6\xc7\x87\ -\x34\x3d\x0d\xdf\xff\xfe\xbe\x9c\xbb\x75\xfd\x77\xa3\x94\xa6\xc2\ -\xf8\xf8\xc1\xb4\x59\x3e\xd7\x5d\xa8\x69\x2b\xd0\x55\xaf\xb3\x6e\ -\x6b\x29\xcf\xab\xab\xa7\x4f\xbf\xde\x84\x4f\x67\x2c\x77\xcb\xd9\ -\xe0\x47\x15\x93\x30\x30\x85\x98\x41\x8c\x23\x66\x30\xe3\x98\x83\ -\xd8\x7c\x7a\x13\xa1\xcd\x09\xf0\xf8\x38\xe9\xca\xca\x6c\xd2\xd3\ -\x33\x96\xcf\xcc\x1c\xce\x3f\xad\x8d\x5f\x5d\xe7\x76\x00\x10\x12\ -\x53\x24\x63\x2b\x63\x85\x62\xf1\x4a\xd1\xb5\x42\x59\xa4\xa5\x2c\ -\xe4\x69\x12\x42\x4e\x96\xd7\x54\x6e\xd6\x62\x47\x4f\xfd\x34\xa7\ -\x33\x0e\x92\x7f\xba\x60\x48\xb7\x0a\xbf\x9a\x52\xd8\xc7\xbe\x00\ -\xb0\x8f\xe9\x38\x79\x07\x87\x71\xeb\xf1\xf8\x94\xc2\xf8\x0c\xe9\ -\x95\xd1\xde\x4a\xa6\x38\x18\x63\x32\x82\xc2\x60\x82\xfb\x45\xe8\ -\x26\xa8\x64\xb9\x11\xac\x15\x85\x70\x31\x49\xbc\x98\x34\xb4\x10\ -\x7b\x9a\x4b\x3d\xf3\xcb\xd5\x23\x5f\x27\xfb\x34\x81\xb8\x99\x1c\ -\x38\x7c\x20\x39\xb7\x74\xac\x3b\x75\x61\xa0\x90\x44\xd5\xaa\xc9\ -\x7a\x52\xac\xad\xb1\x38\x54\x9b\x3e\x38\xfd\x89\x07\xf1\xf1\xd3\ -\xe1\x03\x4a\xfa\xfa\xfa\xba\x3a\x8a\x61\x5b\x54\xbc\x5f\xe2\x31\ -\xc4\xc3\x01\x6d\x97\xd4\x25\x42\x59\xc1\x89\xa4\x5c\xa8\x26\xb4\ -\x46\xd0\x5c\x80\xb7\x83\xc2\x2f\x14\xf2\xf7\x15\xf3\xc5\x77\x2b\ -\x4b\x55\x26\xc9\x7f\x13\xf7\x09\x84\xf4\xc2\x9f\xed\xed\x2a\x76\ -\x76\x3d\x8c\xb3\xe7\xa5\xd0\x19\x60\x5e\x81\xf7\x93\xba\xcf\xc4\ -\x81\xb8\xd8\x53\xde\x5b\x3b\xb4\xff\xd0\xc7\x0e\x46\x3e\x02\x80\ -\x24\x31\x49\x32\x72\xb1\xab\x2f\xcb\x78\x38\x09\xc9\xf3\x0a\x7a\ -\x2a\xa0\x3d\x04\x0d\x0b\xba\x24\xa5\x52\xab\x2f\x23\x09\x21\x4b\ -\xca\xd4\x2a\x42\xe6\x24\xbd\x83\xf8\x39\xf8\xcd\x90\xa4\xc7\xe3\ -\x70\x79\xe9\xc4\x57\x4f\x34\x3e\x6d\x36\x1c\x38\x7c\x20\xb9\x38\ -\xfb\xde\x08\x05\xbe\x04\xda\x0f\xdc\x13\xa4\x15\x05\x4e\x58\xc9\ -\xcf\x43\xa2\x37\xc8\x0b\x27\x2e\x86\xfa\xa5\x23\xaf\x1e\xb9\x29\ -\x1b\x3f\xd4\x15\x96\x78\x95\x74\x70\xa9\x32\x94\xe5\xe1\x89\x44\ -\x7c\x49\xf0\x3c\xb0\xcb\x78\x8b\x4c\x81\xd6\xe4\xe8\x66\xd3\x9d\ -\x02\x50\x06\xba\x81\xed\x88\x07\x82\xc3\xc3\xca\xf3\xe9\xd2\x72\ -\xed\xb5\xb1\x3f\x1f\x9b\xd3\x7f\x54\xed\xd3\x04\xe1\xe4\xa5\x93\ -\xa1\xb3\x94\x74\x27\x31\xbf\x17\x74\xaf\xc4\x4e\x84\xdd\xea\x45\ -\x3e\xe0\x3c\xee\x49\x92\xc6\xdf\xf4\xe4\xd9\x91\xfd\x87\xc7\x17\ -\x75\x40\x1f\x49\xe5\x6f\x9c\x0b\xec\x23\x19\x4a\x3b\x07\x82\xc3\ -\xd3\x11\xff\x63\xd0\xe7\x8c\xc6\x64\x2a\xdc\x62\xbc\xd4\x96\x4d\ -\x60\x4a\xc0\xa0\xd0\x16\xc4\x90\xa5\x81\x3c\xa3\xd2\xb1\x9c\xff\ -\x70\xf8\x3f\x0d\x7f\xa0\x2e\x55\x7d\xd0\x9f\x4a\x46\xb9\xe5\xdc\ -\xc5\x84\xfe\xee\x1e\xd0\x28\xa2\x07\x51\xb4\x08\x42\x25\xf0\x16\ -\x49\xfd\xb6\xb6\x14\x55\x4c\xab\x17\x2b\xaf\x4d\x7c\x7d\xe2\x02\ -\xad\x32\xf8\xaa\x5c\xdd\x94\x90\xfa\x1e\xe8\xeb\x74\xa6\x87\xf2\ -\xdc\xbf\x07\xbc\x68\xb4\x13\xbb\xf3\xba\xcf\x6d\x56\x60\x4d\x5a\ -\x75\x42\x0d\xa8\xb7\xdf\x6f\xe6\x0a\x9b\x13\xdb\x0e\xa4\x6d\x42\ -\xcf\x62\xff\x53\x91\x7e\xa1\xbf\x58\xbc\x77\xfc\xc2\x50\x45\x53\ -\x1f\xe9\xd9\xdd\xb1\x48\x52\xb3\xa3\x54\xc0\xf4\x1a\x86\x90\x2b\ -\x32\xc2\x08\x9c\x08\x3a\xdd\x1a\xed\x7f\xde\x09\xaf\xe4\xc5\xe6\ -\x63\xbd\xe5\xa4\x7b\x8a\x1b\xd7\xbe\xc6\x80\x3f\xa2\x28\x35\x47\ -\x8d\x9e\x15\x7c\x16\x34\x86\x5d\x26\x68\x93\xee\x91\x56\xe9\x79\ -\x09\x74\x11\x58\x73\xa4\x29\x51\x90\xe8\x06\x06\x81\x5e\xa0\xd8\ -\x06\x4c\x98\x02\x62\x08\x78\x2a\x98\x02\x41\x69\x3e\x50\xfa\xde\ -\x63\x9d\xc3\x27\x35\xf5\x6b\x32\x61\x12\xf5\x6e\x29\xa6\x1b\xcd\ -\x50\x32\xe4\x58\x55\x07\x95\x02\xbe\xba\xbe\xa0\x6c\x34\x2a\x78\ -\x96\x18\x2e\x14\x9b\xc9\xc2\xcc\x9f\x3f\xb7\xa1\x3f\x56\x6d\xd3\ -\x14\x5a\xd5\xe0\x94\x42\xd7\x7a\x57\x37\x45\x1e\x06\x3f\xa3\x56\ -\x5d\x5e\x6e\xdb\x3b\xb4\x9a\x92\x2b\xc2\x27\x8d\x7e\x89\xe3\x4c\ -\x50\x32\x07\xae\x86\x40\x07\xe6\x1e\xc9\x8f\x80\xc6\x69\x15\x52\ -\xbd\xed\xcd\xb7\x27\xc7\x1a\x90\x78\x02\xa1\xa0\x10\xb3\xd5\x52\ -\x9c\x48\xb6\x9f\x12\xaa\xde\xb5\x4f\x38\x88\x2f\xff\x59\x23\x2b\ -\x96\x4a\x0b\x84\xe4\x35\x20\x6f\x5f\xdc\x18\x93\xe8\x46\xad\x6e\ -\x51\x68\xb5\xc4\xc7\x10\x4f\x05\xc7\x77\xae\xf4\xc5\x73\xfb\x0f\ -\xb5\xfa\x03\x57\x01\x60\x9e\xa4\x58\x64\x08\xf3\x18\xf0\x80\xa1\ -\xfb\xba\x91\x72\x8e\xbd\x22\xe9\x2d\x5b\xdf\x8d\x8e\x3f\x25\xe1\ -\x4c\x52\xca\x57\x36\x62\x21\xab\x84\x46\xaa\xac\xdc\x5b\x48\x74\ -\x84\x4c\x4f\x5a\x7e\x01\xfc\x04\xd2\x36\x4c\xe9\x1a\x08\xf4\x05\ -\xe9\x33\x98\x5c\x52\xd6\x4c\x4a\xd9\xd8\x1f\x8f\x7d\xa0\xff\x7c\ -\x97\x8e\x51\x50\xf8\xfe\xb6\x6a\xf1\xcd\xc5\xe3\x59\x48\xd6\x2c\ -\x7e\x81\xfc\xa4\x08\x2f\x82\x1f\x6f\x0f\x48\x53\x43\xc0\x74\x02\ -\xf7\x5b\x7e\xc2\x79\x3a\xb3\xbe\xb0\xfb\xd2\x0d\x00\x6c\x87\x42\ -\x23\x32\x64\xf9\x7e\x05\x0d\x72\xcd\x34\x0c\x54\x0d\xc7\x63\xd4\ -\xb7\x93\xe0\xef\x34\x08\xa7\x96\x7b\x97\x37\x38\x48\x7e\xb5\x4a\ -\x9f\x5a\x59\xdb\xbb\x31\xb8\xd4\x8c\xa5\xf9\x34\xc9\xe6\x73\xc2\ -\x6a\x68\x45\x8f\x7b\x30\xe5\x36\x08\x89\xed\x7e\x49\x8f\xd3\x1a\ -\x58\x36\x7a\x7a\xf8\x41\x3a\xb5\x6b\x56\x07\x55\xbf\x53\x10\x6c\ -\x5b\x52\x3e\x39\xc9\xe5\xc3\x8c\xaf\x6f\xdb\x56\x9e\x73\xee\x39\ -\x47\xaf\xb5\x27\x51\x4f\x8a\x56\x73\x57\xad\xfd\x0c\xda\xec\x21\ -\x78\x04\x06\xde\x97\xd4\xb0\xed\x54\x53\x0a\xdd\x9d\xdd\xe5\xf4\ -\x4a\xdc\x2a\x31\x62\xab\x72\xdd\x25\x86\x08\x2c\x0b\xde\x52\xe0\ -\xa7\x5d\x1d\xe9\xc9\xb9\xca\xd2\x95\xab\xb6\xbb\xa9\xf2\x41\x32\ -\xa1\xf5\xdd\x7f\xb4\xfb\x4c\x4c\xab\x1b\x92\xab\xa0\x06\xe2\x45\ -\xc4\xce\xeb\x41\xc0\x0c\x28\x78\xc2\xa6\x99\x50\x68\x76\x27\xf1\ -\xff\xee\xfe\xda\xee\x79\x7d\x55\x77\x9c\x27\xb4\xed\xd8\x07\xa1\ -\x31\x35\xa5\x6c\x7a\x68\xfc\x64\x21\x2d\x16\x31\xa3\x88\x31\x43\ -\x45\x9b\xfe\x08\x4a\x82\x01\xc8\x87\xd3\x8e\xd0\x31\x39\xc9\x3a\ -\xe0\xc0\x0c\x4a\xb3\x66\x45\xad\x16\x75\x8f\xe4\xcd\x0e\x0c\x98\ -\xdc\xb0\x64\x74\x54\x81\x33\xef\x56\x96\x3e\xd6\x71\x19\xfb\xc4\ -\xd7\x4e\x34\x7a\x2e\xcf\x9d\x6f\x26\x85\x9f\x59\xfc\x6f\xc4\xdf\ -\x0a\xce\x22\xea\xb8\x1d\x21\x5a\xb4\x1c\x14\x7a\x1a\xf9\xf7\xed\ -\xe4\xb9\xca\x4a\x73\xfb\xae\xff\xb6\xab\xf4\xeb\x44\x87\x83\x07\ -\x1d\xa7\x87\x66\xaa\xcd\x3c\x9d\x05\xde\x91\xb5\x04\xd7\x5d\x8d\ -\x11\xa1\x75\xd7\x29\x0c\x18\x57\xa6\xdb\xb5\x43\x60\x1c\xe5\x99\ -\x8b\x11\x57\x6c\x8a\xf6\x0d\x77\x81\x22\xb0\x2e\xbc\x90\x36\xe2\ -\x1a\x93\xb7\xae\xbd\x6d\xfb\xc8\x5f\x90\x0d\x2e\x9d\x59\x4a\x55\ -\x3f\xa2\xe0\xff\x63\xf4\x43\xc1\xdc\x87\x40\x28\x00\x5b\x41\xcf\ -\x06\xfb\xcb\x22\xd9\xd7\x3d\x9f\xec\x9e\x28\xdf\xb7\xe5\xe5\xa9\ -\x97\x53\x49\x37\x4b\xb4\x3e\x59\x0e\x10\x9b\xe5\xe2\x15\x89\x8b\ -\x86\x0d\xae\xab\x1a\x6d\x24\x28\x48\xea\xc8\x4d\x81\x97\x5a\xbf\ -\x6f\x21\x5e\x07\xf9\xea\xf8\xe8\x9a\x08\x0b\x62\xb4\xb2\xb5\x3c\ -\xc4\x8f\xfc\xfd\x16\x20\x54\x96\x96\x96\xec\x70\x44\xe2\x9b\x11\ -\x7e\x0c\x9c\xa3\xd5\xcf\x73\x2b\x56\x53\x04\xb6\x21\x7d\x0e\xe9\ -\x0f\x12\xf3\xcf\x6c\x4d\x5c\x4a\xe7\x87\xf7\x4d\xde\x25\x1b\x0c\ -\x1d\x59\x2d\xd8\xa4\x12\xe1\x23\xf9\xaa\x94\x63\x67\x69\x48\xae\ -\xbb\x20\x31\x83\x93\x21\x35\x95\xa9\x06\xce\x3e\xfc\x0d\xec\x72\ -\x40\x3d\x85\x8e\x46\x99\xfd\xac\xc3\xad\xaf\x9d\x6d\x82\x20\x29\ -\x1b\x9f\x9c\x5d\xac\x35\xb7\xff\xac\x08\x29\x24\x29\xd2\x0b\xc0\ -\x48\x9b\x01\x9b\x4c\x18\x96\x5d\x91\xb4\xd5\x51\x3b\xd3\xc0\x0f\ -\x57\xca\xc5\xb7\x3e\x1b\x1f\x9c\xdd\xf3\xb5\x3d\xeb\x27\x96\x4f\ -\x34\x99\xe4\xb6\x6e\x9f\x4e\xfc\xc5\x44\x1a\x9b\xb1\x37\x24\x1a\ -\xb5\xdd\x13\xa4\xe4\xea\x4e\x5a\x6a\x35\x50\x58\x57\x28\xd4\x87\ -\x16\x87\x0c\x2d\x13\x70\xda\x08\x0d\x72\xaf\x59\xda\xd0\xb5\x8c\ -\x2e\x82\x6c\xa9\x03\x79\xb8\xd8\x4c\xb6\x30\x7e\xfb\x37\xbc\x6c\ -\x7b\x66\x92\xa6\x56\x2b\x17\x9c\xc7\xd7\x24\x7f\x13\xfc\x33\x99\ -\x45\x4c\x13\x5d\x65\x42\x0a\xea\x31\x3c\x28\xf1\x25\xf0\xbf\x0e\ -\xd1\xff\x12\xc5\x17\x7b\xeb\xde\x33\xd1\xf5\x40\xff\xbe\xc9\x5d\ -\xa5\x03\x87\x0f\x24\xe2\xe6\xa6\x21\x49\x2f\x4f\xbd\x9c\xf6\x36\ -\x93\xee\x10\xd8\x23\xeb\xf1\xb6\x4f\x4b\xda\xbb\x37\xad\x51\xd9\ -\x9a\x60\xb9\x81\x6b\xe3\x47\xc7\xdd\x06\x06\x0d\x7e\x85\xae\x58\ -\xe8\x7c\x41\xe8\xdf\x09\x5e\x24\xd0\x09\xaa\x05\x69\x11\x71\x0c\ -\xf1\x6d\x15\xf4\xd7\xe7\x7b\x56\x3e\xf0\xc1\x0f\xb3\xe4\xd6\x22\ -\x49\xbb\xff\xcb\xee\x22\x17\xea\x63\xa5\x94\xcf\x2b\x86\x2f\x13\ -\xf4\x94\xc4\x56\xa1\xa2\xda\x65\xa5\x02\x16\xca\x5b\x15\xa5\x16\ -\x04\x27\x14\xf4\x8b\x60\x7e\x99\x88\x93\x4e\xc2\x62\x68\xa6\xab\ -\x79\xa9\xab\xb6\xba\xba\x9a\x97\xb7\x95\x5d\x3b\x57\xd3\x8e\xfe\ -\xba\xf2\x7a\x25\xcd\xba\xd4\x9b\x66\xc9\xde\x18\xfc\x0f\x51\xf8\ -\x47\x12\x0f\x48\xea\x90\xa4\x20\x22\xd2\x12\xf0\xdd\x10\xf4\x5f\ -\x9b\x85\x9e\x9f\x7d\xe7\xdf\x7e\x67\xc3\xb6\x53\xdb\xd6\xef\xab\ -\xd1\xb7\x8b\x79\x22\x47\x05\xc3\x58\x05\xc1\x9c\xf1\xb1\x80\xde\ -\x76\x9a\xcc\x34\x33\x2d\xb5\x58\x71\x67\x62\xdb\x42\x8d\x5d\x53\ -\xbb\xe6\x4a\x64\x3f\x74\x22\x07\x7b\x03\x6b\x02\x31\x0a\xed\x42\ -\xcb\xad\x08\x41\xab\x9a\xac\x20\x46\x30\x0f\x38\xe8\xe9\x0c\x1d\ -\x0f\xe2\x44\x2c\xc6\xb3\x8a\xeb\x8b\xfd\x3d\x71\xdd\xeb\xb5\xbc\ -\xb3\x3f\x0d\x6b\x31\x29\x16\x3a\xe8\x72\x43\xf7\xe6\x89\x9f\x02\ -\x9e\x11\xbe\x4f\xad\x31\xdb\xe6\x24\xa5\x29\x7c\x41\x4a\x8e\xe5\ -\x64\xf3\x17\xab\x17\x1b\x37\xa4\xc2\x74\x91\x35\xad\x85\x22\xfe\ -\x11\x70\xc9\x50\x95\x7d\x2a\xa0\x59\xec\x0b\x95\xbe\xfe\xd5\xd3\ -\x9c\x6e\xdc\x6d\xee\x6e\x6c\x1d\x54\x7d\xd7\xd4\xae\xd9\x8e\x44\ -\xd3\x49\x43\xcb\x04\xe6\x81\x67\x0d\x7b\x64\xfa\x10\xc5\xb6\xc2\ -\x81\x96\x83\x2c\x20\x3a\x11\x23\x82\x87\x64\x2d\x23\x2f\x4b\xf1\ -\x82\x63\xb2\x4c\x12\x9a\xb6\x0b\x89\x54\x8e\xa6\x57\x81\x11\x60\ -\x94\x56\x4d\x52\x76\x2b\x01\x82\xf6\x3c\xc1\xf0\x9e\xec\xb7\x9b\ -\x85\xb0\x74\xe4\xec\xcf\xae\xfa\x31\xd9\x6e\xf5\x01\xf6\x53\xe8\ -\x1a\xe9\xea\xa9\xd4\x93\xee\x2c\x36\xea\x74\x74\xac\x2e\x2f\x2c\ -\xd7\x18\x27\xbb\x5d\x27\xf4\x49\x22\x49\x13\x5f\x9f\x48\xd7\xce\ -\x9d\xeb\x29\xe4\xe5\x7b\x93\x02\x4f\x07\xf1\x39\xa4\xcf\x08\x46\ -\x25\x75\x4a\x4a\x6e\x68\xb6\x48\x96\x88\x52\xc8\x25\x32\x05\x55\ -\x65\xd5\x24\x45\x49\x41\x22\x95\x54\x6a\xbf\x0a\x12\xc9\x55\xb3\ -\x6a\x7d\x66\x4d\xe2\x57\xa0\xff\x19\xe0\xaf\x5c\x5b\x3e\xf3\xcd\ -\xaf\x1e\xaf\xdf\x00\xc0\xa6\x72\x4c\xb6\x4f\x60\x06\x73\x98\x4f\ -\xbc\xa8\x74\xd7\x40\x1c\x50\xf2\xd8\xce\xe1\x32\x3d\xe5\xad\x22\ -\x19\x17\x3c\x2f\xe9\x69\x89\xdd\x41\x61\x00\xa9\xe3\x43\x1b\xe1\ -\x3a\x3f\x61\x11\xbc\x09\x50\xab\xc0\x6a\x19\xba\xb8\x01\xb8\x5c\ -\xd2\x15\x49\xc7\xc1\x7f\x5d\x48\x0a\xdf\x08\x17\xc3\x3b\xdf\xf8\ -\xd3\x1f\xad\x5f\x9f\x71\x5e\x2d\x87\x37\xd3\x4a\xee\xc2\xce\xef\ -\x54\x7c\xc8\xb9\xa4\x8d\x89\xaf\x4f\xcc\x5e\xb9\xb8\xb0\x5a\xca\ -\x3a\xe6\x14\x7c\x4c\x0a\x13\x46\x8f\xa8\x95\x3e\x0f\x21\xca\x40\ -\xca\xe6\x3f\x49\xb5\xfc\x84\xae\x1b\x94\x5e\x0b\x4b\xed\x5f\xe9\ -\xea\xe5\x08\x56\x80\x13\x86\x1f\x24\xd2\x77\xdd\x48\x8e\x3f\x59\ -\xfd\xe1\x95\xff\xc5\xad\x3a\x42\x7f\x87\xd2\x06\xbc\xa9\x29\x5d\ -\x7a\x6e\x65\x6c\xa3\x31\x98\x2c\xc4\x98\x1c\x4d\x55\x78\x10\xf8\ -\x0c\xc1\x8f\x60\xed\x40\xf4\x63\xba\x0c\x45\x89\x70\x9d\x6d\xb7\ -\xf6\x2c\xf9\xea\x5b\x91\x59\x6c\xc8\x5c\x40\xbc\x63\xfb\x47\x69\ -\x8c\x3f\x8a\xc5\xd2\x7b\x5d\x83\xdb\x56\x0f\xfe\xfb\x8f\xfa\xb0\ -\x3b\x1a\x8c\xfc\xa6\x44\x92\x38\x44\x78\x6e\x76\xac\x18\xab\x85\ -\xee\x3c\x24\xdb\x93\x90\xdc\x6f\xd8\x2b\x85\xfb\x24\x6d\x57\xf0\ -\xa0\x50\xaf\xa4\xae\xd0\xaa\xf6\x80\x90\x87\x40\x16\x14\x32\x89\ -\x3a\xd2\x65\x82\xce\x82\x8e\x26\xf2\x1b\x99\xc3\x51\x0f\x56\xe7\ -\x86\x0e\x3f\x5c\x3d\x74\xe8\xe6\x9d\xe1\xdf\x09\x00\x36\x65\xd3\ -\x0f\xed\x62\x57\x71\x6b\xb1\xdc\x99\x94\x93\x3e\xe7\x1e\x90\xc3\ -\x90\x0a\xde\xde\xbe\xbe\xbb\x4d\x84\x8a\x02\x91\x10\x1a\xc2\xf5\ -\x40\xa8\x2b\x78\x55\x0e\xe7\x94\xe8\x54\x74\x7e\xd6\x85\xf4\x7c\ -\x47\x7d\x65\xed\x5b\x9f\xd0\x8d\xfe\x9d\x02\x60\x53\x36\x81\xd8\ -\xc7\xbe\xd0\xd1\x3f\x9b\x2c\x43\x29\xad\x26\x5d\x31\x29\x76\x87\ -\xe0\xae\x68\x8a\x0a\x72\xe2\x90\x53\x74\x96\xc6\x24\xb7\xb2\x7a\ -\x48\xc3\x5a\xa9\x59\x5e\xfb\x60\x79\xbd\xb6\x9f\x99\x6c\xf2\x36\ -\xa2\xd7\xef\x24\x00\x1f\x16\x21\xed\x3f\x40\x58\x1c\xdf\xa7\x45\ -\x16\xc3\x8e\xfe\xba\x00\xba\x46\x4a\x3e\x7a\x14\xca\xdb\xca\xde\ -\xf2\xc0\x16\x0f\x2d\x0e\xf9\xf0\xfe\xc3\xf1\x4e\xfa\x0a\xff\x0f\ -\xc1\xea\x47\x68\xcb\x86\x1c\x37\x00\x00\x00\x00\x49\x45\x4e\x44\ -\xae\x42\x60\x82\ -" - -qt_resource_name = b"\ -\x00\x07\ -\x07\x3b\xe0\xb3\ -\x00\x70\ -\x00\x6c\x00\x75\x00\x67\x00\x69\x00\x6e\x00\x73\ -\x00\x0b\ -\x08\xd8\x99\x42\ -\x00\x67\ -\x00\x65\x00\x6e\x00\x65\x00\x72\x00\x61\x00\x6c\x00\x69\x00\x7a\x00\x65\x00\x72\ -\x00\x08\ -\x0a\x61\x5a\xa7\ -\x00\x69\ -\x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\ -" - -qt_resource_struct_v1 = b"\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ -\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\ -\x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -" - -qt_resource_struct_v2 = b"\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x42\x89\xb8\xd4\xc8\ -" - -qt_version = [int(v) for v in QtCore.qVersion().split('.')] -if qt_version < [5, 8, 0]: - rcc_version = 1 - qt_resource_struct = qt_resource_struct_v1 -else: - rcc_version = 2 - qt_resource_struct = qt_resource_struct_v2 - -def qInitResources(): - QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) - -def qCleanupResources(): - QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) - -qInitResources() From 10df34001837f919fce24cf31611d68e98f0c239 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Mon, 11 Nov 2019 16:47:32 +0400 Subject: [PATCH 27/43] Delete ui_generalizer.py --- ui_generalizer.py | 481 ---------------------------------------------- 1 file changed, 481 deletions(-) delete mode 100644 ui_generalizer.py diff --git a/ui_generalizer.py b/ui_generalizer.py deleted file mode 100644 index b88c781..0000000 --- a/ui_generalizer.py +++ /dev/null @@ -1,481 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'ui_generalizer.ui' -# -# Created by: PyQt5 UI code generator 5.13.1 -# -# WARNING! All changes made in this file will be lost! - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_generalizer(object): - def setupUi(self, generalizer): - generalizer.setObjectName("generalizer") - generalizer.resize(493, 348) - self.gridLayout_20 = QtWidgets.QGridLayout(generalizer) - self.gridLayout_20.setObjectName("gridLayout_20") - self.cbBatch = QtWidgets.QCheckBox(generalizer) - self.cbBatch.setObjectName("cbBatch") - self.gridLayout_20.addWidget(self.cbBatch, 0, 0, 1, 1) - self.bHelp = QtWidgets.QPushButton(generalizer) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.bHelp.sizePolicy().hasHeightForWidth()) - self.bHelp.setSizePolicy(sizePolicy) - self.bHelp.setFlat(True) - self.bHelp.setObjectName("bHelp") - self.gridLayout_20.addWidget(self.bHelp, 0, 2, 1, 1) - self.bOk = QtWidgets.QPushButton(generalizer) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.bOk.sizePolicy().hasHeightForWidth()) - self.bOk.setSizePolicy(sizePolicy) - self.bOk.setObjectName("bOk") - self.gridLayout_20.addWidget(self.bOk, 2, 1, 1, 1) - self.bCancel = QtWidgets.QPushButton(generalizer) - self.bCancel.setObjectName("bCancel") - self.gridLayout_20.addWidget(self.bCancel, 2, 2, 1, 1) - self.stackBatch = QtWidgets.QStackedWidget(generalizer) - self.stackBatch.setObjectName("stackBatch") - self.page_6 = QtWidgets.QWidget() - self.page_6.setObjectName("page_6") - self.gridLayout_19 = QtWidgets.QGridLayout(self.page_6) - self.gridLayout_19.setObjectName("gridLayout_19") - self.label = QtWidgets.QLabel(self.page_6) - self.label.setObjectName("label") - self.gridLayout_19.addWidget(self.label, 0, 0, 1, 1) - self.cbInput = QtWidgets.QComboBox(self.page_6) - self.cbInput.setObjectName("cbInput") - self.gridLayout_19.addWidget(self.cbInput, 1, 0, 1, 2) - self.groupBox = QtWidgets.QGroupBox(self.page_6) - self.groupBox.setObjectName("groupBox") - self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox) - self.gridLayout_2.setObjectName("gridLayout_2") - self.label_3 = QtWidgets.QLabel(self.groupBox) - self.label_3.setObjectName("label_3") - self.gridLayout_2.addWidget(self.label_3, 0, 0, 1, 1) - self.cbAlgorithm = QtWidgets.QComboBox(self.groupBox) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.cbAlgorithm.sizePolicy().hasHeightForWidth()) - self.cbAlgorithm.setSizePolicy(sizePolicy) - self.cbAlgorithm.setObjectName("cbAlgorithm") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.cbAlgorithm.addItem("") - self.gridLayout_2.addWidget(self.cbAlgorithm, 0, 1, 1, 1) - self.stackOptions = QtWidgets.QStackedWidget(self.groupBox) - self.stackOptions.setObjectName("stackOptions") - self.page_11 = QtWidgets.QWidget() - self.page_11.setObjectName("page_11") - self.gridLayout_11 = QtWidgets.QGridLayout(self.page_11) - self.gridLayout_11.setObjectName("gridLayout_11") - self.label_12 = QtWidgets.QLabel(self.page_11) - self.label_12.setObjectName("label_12") - self.gridLayout_11.addWidget(self.label_12, 0, 0, 1, 1) - self.sbRemove_thresh = QtWidgets.QDoubleSpinBox(self.page_11) - self.sbRemove_thresh.setDecimals(4) - self.sbRemove_thresh.setMinimum(0.0001) - self.sbRemove_thresh.setMaximum(9999999.9999) - self.sbRemove_thresh.setProperty("value", 0.0001) - self.sbRemove_thresh.setObjectName("sbRemove_thresh") - self.gridLayout_11.addWidget(self.sbRemove_thresh, 0, 1, 1, 1) - self.stackOptions.addWidget(self.page_11) - self.page_12 = QtWidgets.QWidget() - self.page_12.setObjectName("page_12") - self.gridLayout_12 = QtWidgets.QGridLayout(self.page_12) - self.gridLayout_12.setObjectName("gridLayout_12") - self.label_18 = QtWidgets.QLabel(self.page_12) - self.label_18.setObjectName("label_18") - self.gridLayout_12.addWidget(self.label_18, 0, 0, 1, 1) - self.sbDP_thresh = QtWidgets.QDoubleSpinBox(self.page_12) - self.sbDP_thresh.setDecimals(4) - self.sbDP_thresh.setMinimum(0.0001) - self.sbDP_thresh.setMaximum(9999999.9999) - self.sbDP_thresh.setProperty("value", 0.0001) - self.sbDP_thresh.setObjectName("sbDP_thresh") - self.gridLayout_12.addWidget(self.sbDP_thresh, 0, 1, 1, 1) - self.stackOptions.addWidget(self.page_12) - self.page_2 = QtWidgets.QWidget() - self.page_2.setObjectName("page_2") - self.gridLayout_4 = QtWidgets.QGridLayout(self.page_2) - self.gridLayout_4.setObjectName("gridLayout_4") - self.label_7 = QtWidgets.QLabel(self.page_2) - self.label_7.setObjectName("label_7") - self.gridLayout_4.addWidget(self.label_7, 0, 0, 1, 1) - self.sbJenks_thresh = QtWidgets.QDoubleSpinBox(self.page_2) - self.sbJenks_thresh.setDecimals(4) - self.sbJenks_thresh.setMaximum(9999999.9999) - self.sbJenks_thresh.setProperty("value", 0.0001) - self.sbJenks_thresh.setObjectName("sbJenks_thresh") - self.gridLayout_4.addWidget(self.sbJenks_thresh, 0, 1, 1, 1) - self.label_8 = QtWidgets.QLabel(self.page_2) - self.label_8.setObjectName("label_8") - self.gridLayout_4.addWidget(self.label_8, 1, 0, 1, 1) - self.sbJenks_angle = QtWidgets.QDoubleSpinBox(self.page_2) - self.sbJenks_angle.setMaximum(180.0) - self.sbJenks_angle.setProperty("value", 3.0) - self.sbJenks_angle.setObjectName("sbJenks_angle") - self.gridLayout_4.addWidget(self.sbJenks_angle, 1, 1, 1, 1) - self.stackOptions.addWidget(self.page_2) - self.page_13 = QtWidgets.QWidget() - self.page_13.setObjectName("page_13") - self.gridLayout_3 = QtWidgets.QGridLayout(self.page_13) - self.gridLayout_3.setObjectName("gridLayout_3") - self.label_13 = QtWidgets.QLabel(self.page_13) - self.label_13.setObjectName("label_13") - self.gridLayout_3.addWidget(self.label_13, 0, 0, 1, 1) - self.sbLang_thresh = QtWidgets.QDoubleSpinBox(self.page_13) - self.sbLang_thresh.setDecimals(4) - self.sbLang_thresh.setMinimum(0.0001) - self.sbLang_thresh.setMaximum(9999999.9999) - self.sbLang_thresh.setProperty("value", 0.0001) - self.sbLang_thresh.setObjectName("sbLang_thresh") - self.gridLayout_3.addWidget(self.sbLang_thresh, 0, 1, 1, 1) - self.label_19 = QtWidgets.QLabel(self.page_13) - self.label_19.setObjectName("label_19") - self.gridLayout_3.addWidget(self.label_19, 1, 0, 1, 1) - self.sbLang_LA = QtWidgets.QSpinBox(self.page_13) - self.sbLang_LA.setMinimum(1) - self.sbLang_LA.setMaximum(9999) - self.sbLang_LA.setProperty("value", 8) - self.sbLang_LA.setObjectName("sbLang_LA") - self.gridLayout_3.addWidget(self.sbLang_LA, 1, 1, 1, 1) - self.stackOptions.addWidget(self.page_13) - self.page_4 = QtWidgets.QWidget() - self.page_4.setObjectName("page_4") - self.gridLayout_6 = QtWidgets.QGridLayout(self.page_4) - self.gridLayout_6.setObjectName("gridLayout_6") - self.label_11 = QtWidgets.QLabel(self.page_4) - self.label_11.setObjectName("label_11") - self.gridLayout_6.addWidget(self.label_11, 0, 0, 1, 1) - self.sbRW_thresh = QtWidgets.QDoubleSpinBox(self.page_4) - self.sbRW_thresh.setDecimals(4) - self.sbRW_thresh.setMaximum(9999999.9999) - self.sbRW_thresh.setProperty("value", 0.0001) - self.sbRW_thresh.setObjectName("sbRW_thresh") - self.gridLayout_6.addWidget(self.sbRW_thresh, 0, 1, 1, 1) - self.stackOptions.addWidget(self.page_4) - self.page_14 = QtWidgets.QWidget() - self.page_14.setObjectName("page_14") - self.gridLayout_14 = QtWidgets.QGridLayout(self.page_14) - self.gridLayout_14.setObjectName("gridLayout_14") - self.label_20 = QtWidgets.QLabel(self.page_14) - self.label_20.setObjectName("label_20") - self.gridLayout_14.addWidget(self.label_20, 0, 0, 1, 1) - self.sbReduction_thresh = QtWidgets.QDoubleSpinBox(self.page_14) - self.sbReduction_thresh.setDecimals(4) - self.sbReduction_thresh.setMinimum(0.0001) - self.sbReduction_thresh.setMaximum(9999999.9999) - self.sbReduction_thresh.setObjectName("sbReduction_thresh") - self.gridLayout_14.addWidget(self.sbReduction_thresh, 0, 1, 1, 1) - self.stackOptions.addWidget(self.page_14) - self.page_15 = QtWidgets.QWidget() - self.page_15.setObjectName("page_15") - self.gridLayout_15 = QtWidgets.QGridLayout(self.page_15) - self.gridLayout_15.setObjectName("gridLayout_15") - self.label_21 = QtWidgets.QLabel(self.page_15) - self.label_21.setObjectName("label_21") - self.gridLayout_15.addWidget(self.label_21, 0, 0, 1, 1) - self.sbBoyle_LA = QtWidgets.QSpinBox(self.page_15) - self.sbBoyle_LA.setMinimum(2) - self.sbBoyle_LA.setMaximum(999) - self.sbBoyle_LA.setProperty("value", 7) - self.sbBoyle_LA.setObjectName("sbBoyle_LA") - self.gridLayout_15.addWidget(self.sbBoyle_LA, 0, 1, 1, 1) - self.stackOptions.addWidget(self.page_15) - self.page_16 = QtWidgets.QWidget() - self.page_16.setObjectName("page_16") - self.gridLayout_16 = QtWidgets.QGridLayout(self.page_16) - self.gridLayout_16.setObjectName("gridLayout_16") - self.label_22 = QtWidgets.QLabel(self.page_16) - self.label_22.setObjectName("label_22") - self.gridLayout_16.addWidget(self.label_22, 0, 0, 1, 1) - self.sbChaiken_level = QtWidgets.QSpinBox(self.page_16) - self.sbChaiken_level.setMinimum(1) - self.sbChaiken_level.setMaximum(99) - self.sbChaiken_level.setObjectName("sbChaiken_level") - self.gridLayout_16.addWidget(self.sbChaiken_level, 0, 1, 1, 1) - self.label_23 = QtWidgets.QLabel(self.page_16) - self.label_23.setObjectName("label_23") - self.gridLayout_16.addWidget(self.label_23, 1, 0, 1, 1) - self.sbChaiken_weight = QtWidgets.QDoubleSpinBox(self.page_16) - self.sbChaiken_weight.setMinimum(1.0) - self.sbChaiken_weight.setProperty("value", 3.0) - self.sbChaiken_weight.setObjectName("sbChaiken_weight") - self.gridLayout_16.addWidget(self.sbChaiken_weight, 1, 1, 1, 1) - self.stackOptions.addWidget(self.page_16) - self.page = QtWidgets.QWidget() - self.page.setObjectName("page") - self.gridLayout = QtWidgets.QGridLayout(self.page) - self.gridLayout.setObjectName("gridLayout") - self.label_2 = QtWidgets.QLabel(self.page) - self.label_2.setObjectName("label_2") - self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1) - self.label_4 = QtWidgets.QLabel(self.page) - self.label_4.setObjectName("label_4") - self.gridLayout.addWidget(self.label_4, 1, 0, 1, 1) - self.sbHermite_tightness = QtWidgets.QDoubleSpinBox(self.page) - self.sbHermite_tightness.setProperty("value", 0.5) - self.sbHermite_tightness.setObjectName("sbHermite_tightness") - self.gridLayout.addWidget(self.sbHermite_tightness, 1, 1, 1, 1) - self.sbHermite_steps = QtWidgets.QDoubleSpinBox(self.page) - self.sbHermite_steps.setDecimals(4) - self.sbHermite_steps.setMaximum(9999999.9999) - self.sbHermite_steps.setProperty("value", 0.0001) - self.sbHermite_steps.setObjectName("sbHermite_steps") - self.gridLayout.addWidget(self.sbHermite_steps, 0, 1, 1, 1) - self.stackOptions.addWidget(self.page) - self.page_17 = QtWidgets.QWidget() - self.page_17.setObjectName("page_17") - self.gridLayout_17 = QtWidgets.QGridLayout(self.page_17) - self.gridLayout_17.setObjectName("gridLayout_17") - self.label_24 = QtWidgets.QLabel(self.page_17) - self.label_24.setObjectName("label_24") - self.gridLayout_17.addWidget(self.label_24, 0, 0, 1, 1) - self.sbDist_slide = QtWidgets.QDoubleSpinBox(self.page_17) - self.sbDist_slide.setSingleStep(0.1) - self.sbDist_slide.setProperty("value", 0.5) - self.sbDist_slide.setObjectName("sbDist_slide") - self.gridLayout_17.addWidget(self.sbDist_slide, 0, 1, 1, 1) - self.label_25 = QtWidgets.QLabel(self.page_17) - self.label_25.setObjectName("label_25") - self.gridLayout_17.addWidget(self.label_25, 1, 0, 1, 1) - self.sbDist_LA = QtWidgets.QSpinBox(self.page_17) - self.sbDist_LA.setMinimum(3) - self.sbDist_LA.setMaximum(999) - self.sbDist_LA.setSingleStep(2) - self.sbDist_LA.setProperty("value", 7) - self.sbDist_LA.setObjectName("sbDist_LA") - self.gridLayout_17.addWidget(self.sbDist_LA, 1, 1, 1, 1) - self.stackOptions.addWidget(self.page_17) - self.page_18 = QtWidgets.QWidget() - self.page_18.setObjectName("page_18") - self.gridLayout_18 = QtWidgets.QGridLayout(self.page_18) - self.gridLayout_18.setObjectName("gridLayout_18") - self.label_26 = QtWidgets.QLabel(self.page_18) - self.label_26.setObjectName("label_26") - self.gridLayout_18.addWidget(self.label_26, 0, 0, 1, 1) - self.sbSlide_slide = QtWidgets.QDoubleSpinBox(self.page_18) - self.sbSlide_slide.setSingleStep(0.1) - self.sbSlide_slide.setProperty("value", 0.5) - self.sbSlide_slide.setObjectName("sbSlide_slide") - self.gridLayout_18.addWidget(self.sbSlide_slide, 0, 1, 1, 1) - self.label_27 = QtWidgets.QLabel(self.page_18) - self.label_27.setObjectName("label_27") - self.gridLayout_18.addWidget(self.label_27, 1, 0, 1, 1) - self.sbSlide_LA = QtWidgets.QSpinBox(self.page_18) - self.sbSlide_LA.setMinimum(3) - self.sbSlide_LA.setMaximum(999) - self.sbSlide_LA.setSingleStep(2) - self.sbSlide_LA.setProperty("value", 7) - self.sbSlide_LA.setObjectName("sbSlide_LA") - self.gridLayout_18.addWidget(self.sbSlide_LA, 1, 1, 1, 1) - self.stackOptions.addWidget(self.page_18) - self.page_3 = QtWidgets.QWidget() - self.page_3.setObjectName("page_3") - self.gridLayout_5 = QtWidgets.QGridLayout(self.page_3) - self.gridLayout_5.setObjectName("gridLayout_5") - self.label_9 = QtWidgets.QLabel(self.page_3) - self.label_9.setObjectName("label_9") - self.gridLayout_5.addWidget(self.label_9, 0, 0, 1, 1) - self.sbSnakes_alpha = QtWidgets.QDoubleSpinBox(self.page_3) - self.sbSnakes_alpha.setMaximum(9999.99) - self.sbSnakes_alpha.setProperty("value", 1.0) - self.sbSnakes_alpha.setObjectName("sbSnakes_alpha") - self.gridLayout_5.addWidget(self.sbSnakes_alpha, 0, 1, 1, 1) - self.label_10 = QtWidgets.QLabel(self.page_3) - self.label_10.setObjectName("label_10") - self.gridLayout_5.addWidget(self.label_10, 1, 0, 1, 1) - self.sbSnakes_beta = QtWidgets.QDoubleSpinBox(self.page_3) - self.sbSnakes_beta.setMaximum(9999.99) - self.sbSnakes_beta.setProperty("value", 0.5) - self.sbSnakes_beta.setObjectName("sbSnakes_beta") - self.gridLayout_5.addWidget(self.sbSnakes_beta, 1, 1, 1, 1) - self.stackOptions.addWidget(self.page_3) - self.gridLayout_2.addWidget(self.stackOptions, 1, 0, 1, 2) - self.gridLayout_19.addWidget(self.groupBox, 2, 0, 1, 2) - self.eOutput = QtWidgets.QLineEdit(self.page_6) - self.eOutput.setEnabled(False) - self.eOutput.setObjectName("eOutput") - self.gridLayout_19.addWidget(self.eOutput, 4, 0, 1, 1) - self.bBrowse = QtWidgets.QPushButton(self.page_6) - self.bBrowse.setEnabled(False) - self.bBrowse.setObjectName("bBrowse") - self.gridLayout_19.addWidget(self.bBrowse, 4, 1, 1, 1) - self.cbOutFile = QtWidgets.QCheckBox(self.page_6) - self.cbOutFile.setObjectName("cbOutFile") - self.gridLayout_19.addWidget(self.cbOutFile, 3, 0, 1, 1) - self.stackBatch.addWidget(self.page_6) - self.page_10 = QtWidgets.QWidget() - self.page_10.setObjectName("page_10") - self.gridLayout_21 = QtWidgets.QGridLayout(self.page_10) - self.gridLayout_21.setObjectName("gridLayout_21") - self.lstLayers = QtWidgets.QListWidget(self.page_10) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.lstLayers.sizePolicy().hasHeightForWidth()) - self.lstLayers.setSizePolicy(sizePolicy) - self.lstLayers.setObjectName("lstLayers") - self.gridLayout_21.addWidget(self.lstLayers, 1, 0, 1, 1) - self.tblBatchAlg = QtWidgets.QTableWidget(self.page_10) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.tblBatchAlg.sizePolicy().hasHeightForWidth()) - self.tblBatchAlg.setSizePolicy(sizePolicy) - self.tblBatchAlg.setObjectName("tblBatchAlg") - self.tblBatchAlg.setColumnCount(3) - self.tblBatchAlg.setRowCount(0) - item = QtWidgets.QTableWidgetItem() - self.tblBatchAlg.setHorizontalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.tblBatchAlg.setHorizontalHeaderItem(1, item) - item = QtWidgets.QTableWidgetItem() - self.tblBatchAlg.setHorizontalHeaderItem(2, item) - self.gridLayout_21.addWidget(self.tblBatchAlg, 3, 0, 3, 1) - self.bAddAlg = QtWidgets.QPushButton(self.page_10) - self.bAddAlg.setObjectName("bAddAlg") - self.gridLayout_21.addWidget(self.bAddAlg, 3, 1, 1, 1) - self.bDelAlg = QtWidgets.QPushButton(self.page_10) - self.bDelAlg.setObjectName("bDelAlg") - self.gridLayout_21.addWidget(self.bDelAlg, 4, 1, 1, 1) - self.bEditAlg = QtWidgets.QPushButton(self.page_10) - self.bEditAlg.setObjectName("bEditAlg") - self.gridLayout_21.addWidget(self.bEditAlg, 5, 1, 1, 1) - self.eDir = QtWidgets.QLineEdit(self.page_10) - self.eDir.setEnabled(False) - self.eDir.setObjectName("eDir") - self.gridLayout_21.addWidget(self.eDir, 7, 0, 1, 1) - self.bBrowseDir = QtWidgets.QPushButton(self.page_10) - self.bBrowseDir.setEnabled(False) - self.bBrowseDir.setObjectName("bBrowseDir") - self.gridLayout_21.addWidget(self.bBrowseDir, 7, 1, 1, 1) - self.cbOutDir = QtWidgets.QCheckBox(self.page_10) - self.cbOutDir.setObjectName("cbOutDir") - self.gridLayout_21.addWidget(self.cbOutDir, 6, 0, 1, 1) - self.label_5 = QtWidgets.QLabel(self.page_10) - self.label_5.setObjectName("label_5") - self.gridLayout_21.addWidget(self.label_5, 2, 0, 1, 1) - self.label_6 = QtWidgets.QLabel(self.page_10) - self.label_6.setObjectName("label_6") - self.gridLayout_21.addWidget(self.label_6, 0, 0, 1, 1) - self.stackBatch.addWidget(self.page_10) - self.gridLayout_20.addWidget(self.stackBatch, 1, 0, 1, 3) - self.label.setBuddy(self.cbInput) - self.label_12.setBuddy(self.sbRemove_thresh) - - self.retranslateUi(generalizer) - self.stackBatch.setCurrentIndex(0) - self.cbAlgorithm.setCurrentIndex(1) - self.stackOptions.setCurrentIndex(0) - self.bCancel.clicked.connect(generalizer.close) - QtCore.QMetaObject.connectSlotsByName(generalizer) - generalizer.setTabOrder(self.cbBatch, self.cbInput) - generalizer.setTabOrder(self.cbInput, self.cbAlgorithm) - generalizer.setTabOrder(self.cbAlgorithm, self.sbRemove_thresh) - generalizer.setTabOrder(self.sbRemove_thresh, self.cbOutFile) - generalizer.setTabOrder(self.cbOutFile, self.eOutput) - generalizer.setTabOrder(self.eOutput, self.bBrowse) - generalizer.setTabOrder(self.bBrowse, self.bOk) - generalizer.setTabOrder(self.bOk, self.bCancel) - generalizer.setTabOrder(self.bCancel, self.sbLang_LA) - generalizer.setTabOrder(self.sbLang_LA, self.sbReduction_thresh) - generalizer.setTabOrder(self.sbReduction_thresh, self.sbBoyle_LA) - generalizer.setTabOrder(self.sbBoyle_LA, self.sbChaiken_level) - generalizer.setTabOrder(self.sbChaiken_level, self.sbChaiken_weight) - generalizer.setTabOrder(self.sbChaiken_weight, self.sbHermite_steps) - generalizer.setTabOrder(self.sbHermite_steps, self.sbHermite_tightness) - generalizer.setTabOrder(self.sbHermite_tightness, self.sbDist_slide) - generalizer.setTabOrder(self.sbDist_slide, self.sbDist_LA) - generalizer.setTabOrder(self.sbDist_LA, self.sbSlide_slide) - generalizer.setTabOrder(self.sbSlide_slide, self.sbSlide_LA) - generalizer.setTabOrder(self.sbSlide_LA, self.bHelp) - generalizer.setTabOrder(self.bHelp, self.sbLang_thresh) - generalizer.setTabOrder(self.sbLang_thresh, self.sbDP_thresh) - generalizer.setTabOrder(self.sbDP_thresh, self.lstLayers) - generalizer.setTabOrder(self.lstLayers, self.tblBatchAlg) - generalizer.setTabOrder(self.tblBatchAlg, self.bAddAlg) - generalizer.setTabOrder(self.bAddAlg, self.bDelAlg) - generalizer.setTabOrder(self.bDelAlg, self.bEditAlg) - generalizer.setTabOrder(self.bEditAlg, self.eDir) - generalizer.setTabOrder(self.eDir, self.bBrowseDir) - generalizer.setTabOrder(self.bBrowseDir, self.cbOutDir) - - def retranslateUi(self, generalizer): - _translate = QtCore.QCoreApplication.translate - generalizer.setWindowTitle(_translate("generalizer", "Generalizer")) - self.cbBatch.setText(_translate("generalizer", "Batch mode")) - self.bHelp.setText(_translate("generalizer", "?")) - self.bOk.setText(_translate("generalizer", "OK")) - self.bCancel.setText(_translate("generalizer", "Close")) - self.label.setText(_translate("generalizer", "Input line layer:")) - self.groupBox.setTitle(_translate("generalizer", "Options")) - self.label_3.setText(_translate("generalizer", "Alghoritm:")) - self.cbAlgorithm.setItemText(0, _translate("generalizer", "-----Generalizing-----")) - self.cbAlgorithm.setItemText(1, _translate("generalizer", "Remove small objects")) - self.cbAlgorithm.setItemText(2, _translate("generalizer", "-----Simplifying-----")) - self.cbAlgorithm.setItemText(3, _translate("generalizer", "Douglas-Peucker Algorithm")) - self.cbAlgorithm.setItemText(4, _translate("generalizer", "Jenk\'s Algorithm")) - self.cbAlgorithm.setItemText(5, _translate("generalizer", "Lang Algorithm")) - self.cbAlgorithm.setItemText(6, _translate("generalizer", "Reumann-Witkam Algorithm")) - self.cbAlgorithm.setItemText(7, _translate("generalizer", "Vertex Reduction")) - self.cbAlgorithm.setItemText(8, _translate("generalizer", "-----Smoothing-----")) - self.cbAlgorithm.setItemText(9, _translate("generalizer", "Boyle\'s Forward-Looking Algorithm")) - self.cbAlgorithm.setItemText(10, _translate("generalizer", "Chaiken\'s Algorithm")) - self.cbAlgorithm.setItemText(11, _translate("generalizer", "Hermite Spline Interpolation")) - self.cbAlgorithm.setItemText(12, _translate("generalizer", "McMaster\'s Distance-Weighting Algorithm")) - self.cbAlgorithm.setItemText(13, _translate("generalizer", "McMaster\'s Sliding Averaging Algorithm")) - self.cbAlgorithm.setItemText(14, _translate("generalizer", "Snakes Algorithm")) - self.label_12.setText(_translate("generalizer", "Threshold:")) - self.label_18.setText(_translate("generalizer", "Threshold:")) - self.label_7.setText(_translate("generalizer", "Threshold:")) - self.label_8.setText(_translate("generalizer", "Angle threshold:")) - self.label_13.setText(_translate("generalizer", "Threshold:")) - self.label_19.setText(_translate("generalizer", "Looka ahead:")) - self.label_11.setText(_translate("generalizer", "Threshold:")) - self.label_20.setText(_translate("generalizer", "Threshold:")) - self.label_21.setText(_translate("generalizer", "Look ahead:")) - self.label_22.setText(_translate("generalizer", "Level:")) - self.label_23.setText(_translate("generalizer", "Weight:")) - self.label_2.setText(_translate("generalizer", "Threshold:")) - self.label_4.setText(_translate("generalizer", "Thightness:")) - self.label_24.setText(_translate("generalizer", "Slide:")) - self.label_25.setText(_translate("generalizer", "Look ahead:")) - self.label_26.setText(_translate("generalizer", "Slide:")) - self.label_27.setText(_translate("generalizer", "Look ahead:")) - self.label_9.setText(_translate("generalizer", "Alpha:")) - self.label_10.setText(_translate("generalizer", "Beta:")) - self.bBrowse.setText(_translate("generalizer", "Browse")) - self.cbOutFile.setText(_translate("generalizer", "Save output layer")) - item = self.tblBatchAlg.horizontalHeaderItem(0) - item.setText(_translate("generalizer", "Algorithm")) - item = self.tblBatchAlg.horizontalHeaderItem(1) - item.setText(_translate("generalizer", "Parameter 1")) - item = self.tblBatchAlg.horizontalHeaderItem(2) - item.setText(_translate("generalizer", "Parameter 2")) - self.bAddAlg.setText(_translate("generalizer", "Add")) - self.bDelAlg.setText(_translate("generalizer", "Delete")) - self.bEditAlg.setText(_translate("generalizer", "Edit")) - self.bBrowseDir.setText(_translate("generalizer", "Browse")) - self.cbOutDir.setText(_translate("generalizer", "Save output layer(s) to folder")) - self.label_5.setText(_translate("generalizer", "Algorithm(s)")) - self.label_6.setText(_translate("generalizer", "Choose layer(s)")) From 6ed7e1e83819057974a3f08660252aa4dd30b3c3 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 17 May 2020 22:09:55 +0400 Subject: [PATCH 28/43] fix save layer and unattended column 0.7 (17.05.2020) - fix save layer to file - remove unattended column in temporary layer --- CHANGELOG | 4 ++++ dialogs.py | 9 +++++---- generalizerdialog.py | 21 ++++++++++++--------- metadata.txt | 28 +++++++++++++++++++++++++--- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8b8a2b9..e2c3265 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +0.7 (17.05.2020) +- fix save layer to file +- remove unattended column in temporary layer + 0.6 (10.11.2019) - updated to QGIS 3.x - fix projection according to project coordinates diff --git a/dialogs.py b/dialogs.py index 6209e40..5f4f0b9 100644 --- a/dialogs.py +++ b/dialogs.py @@ -1,6 +1,7 @@ from builtins import str from PyQt5.QtGui import * from PyQt5.QtCore import * +from PyQt5.QtWidgets import * from os.path import splitext, dirname @@ -10,14 +11,14 @@ def saveDialog(parent): key = '/UI/lastShapefileDir' outDir = settings.value(key) - filter = 'Shapefiles (*.shp)' - outFilePath, __ = QFileDialog.getSaveFileName(parent, parent.tr('Save output shapefile'), outDir, filter) + filter = 'GeoPackage (*.gpkg)' + outFilePath, __ = QFileDialog.getSaveFileName(parent, parent.tr('Save output GeoPackage'), outDir, filter) outFilePath = str(outFilePath) if outFilePath: root, ext = splitext(outFilePath) - if ext.upper() != '.SHP': - outFilePath = '%s.shp' % outFilePath + if ext.upper() != '.GPKG': + outFilePath = '%s.gpkg' % outFilePath outDir = dirname(outFilePath) settings.setValue(key, outDir) diff --git a/generalizerdialog.py b/generalizerdialog.py index 3fad443..928247e 100644 --- a/generalizerdialog.py +++ b/generalizerdialog.py @@ -478,8 +478,8 @@ def LoadLayers(self, fileList): else: out_name = filePath[(len(filePath) - filePath.rfind("/")) - 1:] - if out_name.endswith(".shp"): - out_name = out_name[:len(out_name) - 4] + if out_name.endswith(".gpkg"): + out_name = out_name[:len(out_name) - 5] self.iface.addVectorLayer(filePath, out_name, "ogr") @@ -497,9 +497,11 @@ def doGeneralize(self, iLayerName, iLayer, oPath, func, arguments): #else: # mLayer = QgsVectorLayer('MultiLineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') if iLayer.wkbType() == QgsWkbTypes.LineString: - mLayer = QgsVectorLayer('LineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') + #mLayer = QgsVectorLayer('LineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') + mLayer = QgsVectorLayer('LineString?crs=' + crs.authid(), iLayerName + '_memory', 'memory') else: - mLayer = QgsVectorLayer('MultiLineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') + #mLayer = QgsVectorLayer('MultiLineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') + mLayer = QgsVectorLayer('MultiLineString?crs=' + crs.authid(), iLayerName + '_memory', 'memory') mProvider = mLayer.dataProvider() mProvider.addAttributes( [key for key in fields] ) @@ -517,7 +519,7 @@ def doGeneralize(self, iLayerName, iLayer, oPath, func, arguments): if len(l2) > 1: l.append(l2) if len(l) > 1: - fet.setGeometry(QgsGeometry.fromMultiPolyline(l)) + fet.setGeometry(QgsGeometry.fromMultiPolylineXY(l)) elif len(l) == 1: #jesli z obiektu wieloczesciowego zostaje tylko jedna linia (np. przy usuwaniu malych obiektow) fet.setGeometry(QgsGeometry.fromPolyline(l[0])) else: @@ -537,7 +539,8 @@ def doGeneralize(self, iLayerName, iLayer, oPath, func, arguments): return mLayer else: #write shapefile on disk - writer = QgsVectorFileWriter(oPath, iProvider.encoding(), fields, QGis.WKBLineString, iLayer.crs()) + #writer = QgsVectorFileWriter(oPath, iProvider.encoding(), fields, QGis.WKBLineString, iLayer.crs()) + writer = QgsVectorFileWriter(oPath, iProvider.encoding(), fields, QgsWkbTypes.LineString, iLayer.crs()) if writer.hasError() != QgsVectorFileWriter.NoError: QMessageBox.critical(None, 'Generalizer', 'Error when creating shapefile: %s' % (writer.hasError())) @@ -557,7 +560,7 @@ def doGeneralize(self, iLayerName, iLayer, oPath, func, arguments): l.append(l2) if len(l) > 1: #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(l) ) - fet.setGeometry(QgsGeometry.fromMultiPolyline(l)) + fet.setGeometry(QgsGeometry.fromMultiPolylineXY(l)) else: ls = geom.asPolyline() #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(ls) ) @@ -597,9 +600,9 @@ def batchGeneralize(self, layers): #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(i) ) path = self.ui.eDir.text() if path.contains("\\"): - out_name = path + '\\' + layer + '_new.shp' + out_name = path + '\\' + layer + '_new.gpkg' else: - out_name = path + '/' + layer + '_new.shp' + out_name = path + '/' + layer + '_new.gpkg' outNames.append(out_name) vLayer = self.doGeneralize(layer, vLayer, out_name, func, arguments) else: diff --git a/metadata.txt b/metadata.txt index f5b789e..1a396f3 100644 --- a/metadata.txt +++ b/metadata.txt @@ -1,10 +1,28 @@ [general] -name=Generalizer +name=Generalizer3 +email=sylvain.poulain@giscan.com qgisMinimumVersion=3.0 description=Lines generalization and smoothing (partially based on v.generalize GRASS module) -version=0.6 +about=Plugin to Generalize, Simplify or Smooth lines in QGIS + Functions : + Remove small objects + Simplify : + Douglas-Peucker Algorithm + Jenk's Algorithm + Lang Algorithm + Reumann-Witkam Algorithm + Vertex Reduction + Smooth : + Boyle's Forward-Looking Algorithm + Chaiken's Algorithm + Hermite Spline Interpolation + McMaster's Distance-Weighting Algorithm + Distance Weighting + McMaster's Sliding Averaging Algorithm + Snakes Algorithm : Slowest smoothing algorithm +version=0.7 author=Piotr Pociask, Matthew Petroff, Sylvain POULAIN -email=sylvain.poulain (at) giscan.com + # end of mandatory metadata @@ -14,6 +32,7 @@ homepage=https://github.com/giscan/Generalizer tracker=https://github.com/giscan/Generalizer/issues repository=https://github.com/giscan/Generalizer icon=icon.png +tags=line,vector,smooth,simplify # experimental flag experimental=True @@ -22,6 +41,9 @@ experimental=True deprecated=False changelog= + 0.7 (17.05.2020) + - fix save layer to file + - remove unattended column in temporary layer 0.6 (10.11.2019) - updated to QGIS 3.x - fix projection according to project coordinates From d99840d8cc04cfcd8f164d6a97e5479db4e7cfff Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sat, 23 May 2020 21:44:46 +0400 Subject: [PATCH 29/43] Add files via upload --- generalizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generalizer.py b/generalizer.py index 3715647..6235c3f 100644 --- a/generalizer.py +++ b/generalizer.py @@ -31,7 +31,7 @@ from qgis.core import * # Initialize Qt resources from file resources.py -from . import resources +from .resources import * # Import the code for the dialog from .generalizerdialog import generalizerDialog, getLayersNames From 496c8288c0ea584ae3ba02ccd61e345d505c14c8 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sat, 23 May 2020 21:46:23 +0400 Subject: [PATCH 30/43] Add files via upload --- resources.py | 444 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 444 insertions(+) create mode 100644 resources.py diff --git a/resources.py b/resources.py new file mode 100644 index 0000000..ffa3fb2 --- /dev/null +++ b/resources.py @@ -0,0 +1,444 @@ +# -*- coding: utf-8 -*- + +# Resource object code +# +# Created by: The Resource Compiler for PyQt5 (Qt v5.13.1) +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore + +qt_resource_data = b"\ +\x00\x00\x17\xc5\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\ +\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\ +\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0d\xd7\x00\x00\x0d\xd7\ +\x01\x42\x28\x9b\x78\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\ +\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x17\x42\x49\x44\ +\x41\x54\x78\x9c\xed\x9b\x5b\x6c\x5d\xd7\x9d\xde\x7f\xdf\xda\xfb\ +\x5c\x78\x48\xf1\x4e\x91\x12\x69\x49\xb6\x25\xcb\x36\x6d\xc7\x36\ +\xed\xf8\x96\xd8\x72\x9a\x66\xea\x41\x9b\x5e\x50\x69\x8a\x4e\xd1\ +\x87\x00\x35\x50\x14\x19\xa0\x83\xe9\xbc\x8a\x7c\x9d\x87\x0e\xd0\ +\x3c\x65\x80\x62\xda\x87\xbe\x48\x40\x81\xa6\xd3\x64\x92\x60\x12\ +\x66\x9a\x9b\xe3\xc8\x76\xe2\x50\x96\x2d\x59\x17\x8b\xa4\x28\x91\ +\xa2\xc4\x8b\x78\x6e\x7b\xaf\xaf\x0f\xe7\x50\x17\x5b\x96\x25\xc5\ +\x99\x04\x98\xfe\x81\x03\xf0\x90\xe7\xec\xf5\x5f\xdf\xfa\xfe\xf7\ +\x45\xd9\xe6\xef\xb3\x84\xdf\xb6\x02\xbf\x6d\xf9\xff\x00\xfc\xb6\ +\x15\xf8\x6d\xcb\xdf\x7b\x00\xd2\xdb\xf9\x90\x84\x00\x6c\x7e\x27\ +\x3c\x66\x5b\x9f\xcd\x97\x41\xf6\x5d\x7a\x73\xdd\xea\x7b\x12\x7a\ +\xf5\xd5\x23\x29\x9c\x2b\x74\x76\x0e\xf8\xca\x95\x62\xb6\x7d\xfb\ +\x5f\xe5\x93\x93\x93\x77\xbd\xe0\xaf\x2b\x12\x9a\x98\x20\x5d\x5c\ +\xfc\xa0\x4b\xaa\x94\xed\x8d\xda\xd0\xd0\x8e\xf5\x23\x47\xc8\xee\ +\xe6\x80\x6e\x09\xc0\xd4\xd4\x74\x3a\x3b\xdb\x31\x10\x42\x63\x34\ +\x0f\xa4\x49\x4c\x2e\xe6\xf9\xda\xa5\x4a\xe5\xfe\x2b\x0b\x0b\x6f\ +\x66\x87\x0f\xef\x8f\x7f\x97\xac\x90\xd0\xee\xdd\x14\xab\xd5\xe5\ +\x21\xf0\x03\x0e\x61\x6b\xb0\x16\x6a\xca\xde\x5b\x3a\x7b\x61\x09\ +\x1e\x6e\xde\xa9\x3e\x1f\x0b\x80\x84\xbe\xf2\x95\x6f\x74\x25\x49\ +\xef\xa3\x04\xbe\x60\x6b\x20\x5a\x67\x9d\xf1\x9e\x1d\xcf\xd4\xeb\ +\xa5\x0b\x5b\xb6\xa4\x6b\xef\x6d\x5f\x6b\x4c\x4f\xee\xcb\x7f\xd3\ +\x40\x48\x68\xd7\xae\xd3\x25\x28\x8f\xd8\x85\x27\x73\xf3\x12\xd6\ +\x3d\x79\xe4\x94\x89\xdf\xcb\xea\xbc\xb1\xb4\x34\xb8\x04\x77\xc6\ +\x84\x8f\x05\xe0\xc0\x81\xc3\xc9\xf0\x70\xef\x70\xb3\x59\xfa\x62\ +\x84\x3f\x88\xd6\xfd\x8e\x61\xd5\x91\x53\x46\xef\xc4\x2c\xbc\x93\ +\xe1\x53\xb1\x91\x9e\xdb\xa8\x34\x2e\x8f\xa4\xe5\xda\x6f\xca\x3c\ +\x5a\x9b\xa7\x14\x8b\x17\xb6\x87\x3c\x7c\xd6\xb9\xbf\x14\xa3\x9e\ +\xc9\xad\x7e\xa2\x16\x72\xf8\x81\x23\xdf\x22\x2f\xbd\x75\xe1\xc2\ +\xb1\x65\x78\x2a\xbb\x5d\x1d\x3e\xd6\x09\x8e\x8c\x74\xa5\xb5\x98\ +\xf6\x49\xdc\x2b\x73\x8f\x60\xcc\x20\xa3\x9d\xd1\x7a\xd8\xf0\x01\ +\xd6\xbb\x4a\x7d\xb4\x54\x2d\x1e\x5f\x89\xcc\xce\xad\xff\x83\xe5\ +\x57\x5e\xf9\xc3\x8d\xa9\x29\x9a\x93\x93\xf8\xd3\x62\xc5\xbe\x7d\ +\x24\xf3\xf3\xb3\x03\xcd\x58\x7a\xd2\xf6\xef\x21\x9e\x47\x8c\x2a\ +\x52\x8a\xa2\xa2\xa8\x68\x87\x46\xae\x2c\x1b\x19\xd9\xfb\xcb\x85\ +\x05\x5f\x02\xb2\xdb\x79\xf6\x4d\xc3\xa0\x24\xe5\x79\x47\x21\x8d\ +\x0c\x02\x3b\xc0\xfd\x12\x25\x70\x07\x30\x80\xbd\xc7\xf0\x9c\xac\ +\x7f\x62\xeb\x0f\x05\xff\x26\xb3\xbf\xdc\xd1\xe8\x7c\xb6\x52\xb9\ +\xb2\xfb\xc8\xbb\xef\xf5\xef\xdb\x37\x5d\x9a\x9a\xfa\x74\xc2\xec\ +\xec\xec\x89\x24\xc6\xb4\x47\xb0\x1b\xf1\x20\x30\x02\x74\x20\x52\ +\x4c\xa7\xe1\x3e\xf0\x4b\xc0\x17\xb2\x2c\x7b\x78\x74\x74\xad\x47\ +\x9a\xbe\xad\x08\x77\xd3\x0f\xed\xdf\x7f\x28\xc4\x58\xac\x84\x90\ +\x8d\x08\x46\x8d\xba\x1c\x49\x68\x85\x9d\x04\x42\x00\x15\x0c\x5d\ +\xc2\xc3\xb2\xee\x17\x3c\x16\xf1\x49\x94\x1d\x4d\xaa\x1b\x6f\x77\ +\x76\x76\xbf\xfb\xd6\x5b\x6f\x9d\x7b\xf9\xe5\xc7\xd7\xa7\xa7\xf9\ +\xb5\x7c\x44\x4f\xcf\x4a\xbc\x78\xb1\x6b\x23\x84\x78\x41\x84\x45\ +\xc3\x06\xd0\x01\x6a\xe9\x63\xb6\x18\xf6\x60\x65\x11\x35\xab\x55\ +\x9a\x3d\x3b\x9e\x78\x47\x62\xd5\x26\xbf\x63\x00\xfa\xfa\xee\x0b\ +\x79\x72\xb9\x57\xa4\x3b\x40\x43\x98\x52\x7b\xf3\x6d\x71\x3b\x06\ +\x2b\xd8\xa4\x86\x16\x33\xe4\x9d\x31\x0f\x0f\x45\x78\x24\x84\xf0\ +\x7a\x9e\xfb\xf5\xee\xee\x77\x8f\xef\xdb\x57\x5a\x96\x76\x35\x6c\ +\xe2\xdd\x00\x70\xe4\xc8\x44\x36\x3e\xbe\xb8\x74\xe5\x0a\x6f\x48\ +\xea\x03\x2a\xc6\x8f\x81\xfb\x40\x69\x0b\x04\x6d\x01\xf6\x1a\x65\ +\x88\x86\xaf\x14\xb3\xde\xde\xcb\xef\x49\xbd\x6b\xb7\x02\xe1\x23\ +\x14\x95\x24\xa0\x10\x48\x07\xc0\x3b\xb1\xfb\x3f\x04\x94\x41\xb1\ +\xf5\xc2\x6d\x60\x52\xa0\x03\x33\x08\x3c\x80\xfd\xa2\xc5\x3f\x37\ +\xe1\x5f\x34\x63\xed\xf3\x1d\x1d\x97\xee\xfb\xe2\x17\x8f\x6c\x79\ +\xf9\xe5\xe9\x74\x33\xa9\xba\x13\xb1\xf1\xcc\xcc\x74\x35\x84\xf4\ +\x94\xa4\xbf\x8d\xd1\xdf\x13\x3a\x0a\xac\x80\xda\xb6\xee\x14\xd3\ +\x03\x3c\x64\x87\x2f\x28\x66\x2f\xd9\xc5\xfb\xfa\xfb\xe9\x94\x3e\ +\xde\x14\x3f\xc2\x80\xc9\xc9\x49\xad\xac\x34\xca\xb5\x9a\x87\x15\ +\x18\x03\xba\x41\x9b\x0f\x30\xb8\x01\xae\xba\xc5\x80\x22\x50\x80\ +\xeb\xcd\x83\x32\x52\x01\xab\x12\xcd\x00\x0e\xdb\xad\x30\x9a\x24\ +\x7e\xbd\x9e\x0c\x9f\xd8\xb7\xef\xf4\xa5\xbb\x61\x83\xbd\x3f\x97\ +\x58\xdf\xb1\x63\xe5\x44\x50\xbd\x90\x5b\x05\xa3\x14\xfc\x30\xa8\ +\xbb\xbd\x76\x82\xd5\x6b\xfc\x88\x63\xc8\xb0\x1a\xf5\xfa\x95\x1c\ +\xaa\x27\xa5\xc1\x2b\x37\x5b\xf3\x26\x26\xf0\x52\xb0\xeb\xdd\x4a\ +\x19\xb3\x19\x96\x28\xdb\x0e\x6d\x0b\xc8\x8c\x17\x11\xef\x83\x6a\ +\x88\x41\x60\x18\xdc\x0b\x2a\xb5\x9f\x27\x20\x95\xd4\x05\xda\x69\ +\xd3\xed\xa8\x91\xdc\x8c\x15\xf1\x8f\x63\xb9\xfe\xf6\x2b\xaf\x9c\ +\x38\xf7\xf2\xcb\xb3\x1b\xd3\xd3\x77\x96\x3f\xd8\xe4\x52\xcf\xea\ +\xe8\xe8\xdc\xbb\x21\x14\x53\x47\x15\x8c\x53\xc3\x5e\xd0\x16\x70\ +\xd2\x62\x82\xfa\x11\x8f\xd9\x31\x93\xd4\xec\xea\xea\xce\xd6\xd7\ +\x39\x2d\x51\xfd\x30\x08\x1f\x01\x60\x66\x66\xb1\x30\x38\xd8\x33\ +\xa0\xa4\xb8\x13\x34\x40\xeb\x84\xa1\x45\xf7\x9a\xa4\x93\x96\xbf\ +\x45\xce\x9c\x1d\xb7\xe1\xe4\x41\xa3\x3d\x46\xf7\x00\x03\xb4\xfc\ +\x41\xd2\x02\x8d\x12\x68\xc8\x50\x81\x30\x00\xda\xee\x66\x1c\xad\ +\xdb\xaf\xc3\xd6\x93\xaf\xbc\x72\xe2\x92\xf4\x3f\x9a\xf6\xc1\xdb\ +\x66\x43\x0b\x84\xd1\x95\x91\x91\x85\x77\x9c\x84\x54\x56\x51\x28\ +\xb5\xbd\x07\xd4\x45\xcb\xac\x53\xcc\x80\x1d\x3e\x03\x34\x63\x8c\ +\xcd\x62\xb1\x91\x37\x1a\xc5\x0f\xa4\xa9\xda\xf5\xeb\xdd\x00\x40\ +\x2b\xf7\xef\x2b\xaa\xa0\x21\xcc\x3d\x32\x3d\x6e\xfb\x09\x89\x1c\ +\xb1\x2a\xf4\x7e\xc0\x6f\x34\x92\x70\xcc\xf5\x66\x87\x93\xf0\x73\ +\xe5\xc9\x5e\xe1\xc7\x23\xe1\x31\xc1\xbd\x40\x9f\xa4\xc2\xa6\x32\ +\x12\x5b\x80\x7b\xb1\x7b\xa4\x30\x92\xa3\x51\x2b\xfc\x74\x6d\x2d\ +\xfb\xd5\x0b\x2f\xfc\x87\x73\x2f\xbf\x3c\x5d\xbd\x13\x36\xd8\x64\ +\xd2\xdc\xe5\xe1\xe1\xbd\xbf\x8a\x49\x23\x15\xb1\x00\x21\x05\xdd\ +\x07\x74\xb6\xd7\x2d\x00\x43\xd1\x3c\x69\x9c\x85\x10\x9b\xa5\x52\ +\x3d\xaf\xd7\x0f\xce\x4a\xd4\x36\xd7\xba\x01\x80\x7d\xfb\xa6\x93\ +\x52\x29\xdd\x62\x31\x1a\xa3\xb7\xd1\x3a\xb9\xd0\x3e\xff\x5c\xe6\ +\x92\xed\xd3\x39\xcd\x73\x65\x8f\x2e\x5e\x89\xaf\xc7\x62\xba\x63\ +\x21\x0f\xcd\x53\xce\x8b\xef\x39\xc6\x93\x26\x7d\x16\x34\x6e\x7b\ +\x1b\xa8\xcd\x06\x02\x50\x32\xde\x6a\xbb\x42\x64\xd0\x84\x31\x8b\ +\xed\x8e\x97\x8f\x54\xab\x83\x27\x77\xef\x3e\x71\xf9\xce\xd8\x30\ +\x91\x9d\x3f\xcf\xa5\xc1\xc1\xa5\xb7\x49\x93\x82\x50\xd1\xa6\x00\ +\xda\x45\x8b\x85\x02\x17\x21\x6c\xb5\x99\x00\x9a\xb6\x9a\x94\xeb\ +\x39\xb5\xd2\xbc\x44\xdd\xc6\x37\x00\xf0\xe8\xa3\xd5\xc4\x69\xa1\ +\x8f\x3c\xd9\x29\x31\xd8\x7a\xa0\x05\xb2\xa1\x81\x58\x94\xf4\x41\ +\x21\x2f\x2c\x9f\x3c\xfd\xdf\xb3\xef\x7f\xff\x60\x26\xd1\x7c\xf5\ +\xd5\x23\xd5\xb9\xf5\x8d\x95\x72\xdc\x72\x3e\x27\x9e\x35\x9a\xc3\ +\x9a\x68\x9f\x48\xef\x35\x36\x28\x95\xd4\x1d\x51\x49\x76\x2f\xd2\ +\x48\x0c\x8c\x41\xf9\x27\x43\x43\x9a\x49\x86\xff\xd5\xf9\x03\x07\ +\xd8\x38\x7c\x58\xf1\x93\x52\x59\x1b\x4b\x64\x5d\x5d\xeb\x97\xaa\ +\xd5\x8e\xa3\x79\x2c\xf6\xa2\x74\x08\xd3\xdb\x76\xce\x6d\x7f\xe4\ +\x12\x68\x9b\xad\xa7\x0d\xcd\x24\xaa\x99\x53\x7b\x0d\xca\x0b\x12\ +\x8d\xab\x00\x48\xe8\x2b\x7f\xda\x5d\xec\xca\xb2\xc1\x18\xe2\x0e\ +\x22\xbd\xf6\x55\x86\x44\xf0\x86\x61\x81\x3c\x9b\xaf\xd7\x4b\xeb\ +\xd3\xd3\x07\xf3\x4d\x45\x60\xa2\x39\x35\xc5\xca\xcc\xcc\x4f\x6a\ +\x81\xca\xe5\x7a\x93\x05\xe3\x59\xcc\x73\x58\xe3\xb6\x87\x37\xd9\ +\xd4\x66\x43\xd9\x66\x18\x87\x8a\xd0\x20\x78\x34\xb3\xb6\x6f\x89\ +\xc5\x23\x27\x16\x16\x4e\x8d\x8f\xcf\xac\x48\x7c\x6c\x65\xd7\x0a\ +\xd5\xd6\xee\xdd\x14\xaa\xd5\x42\x27\x14\x3b\x5b\x24\xa5\x8a\xdd\ +\x68\xfd\x78\x35\xda\xaa\xc5\x3e\xb6\x83\x9e\xc1\xb1\x99\x24\x85\ +\x66\x9e\xf3\x3a\x70\xe1\x2a\x00\xfb\xf7\x1f\x0e\x5b\xea\xfd\x95\ +\x28\xb6\x63\x6d\xbf\xce\xa1\x00\xca\x11\x97\x65\x7d\x80\xbc\x58\ +\x28\x54\x1b\x1f\x56\xee\xe0\x41\xa2\xf4\x5c\x6d\xdf\x24\xe7\x3b\ +\x5f\x7f\x7b\xc3\x66\x29\x2a\xce\xa1\x30\xe7\xa8\x09\xe0\x5e\x70\ +\xaf\x14\xd2\x4d\x36\x80\x7b\x30\x65\xa3\x5e\xf0\x36\x72\x8d\x29\ +\x6f\xfc\xa4\x52\xe9\x3a\x3a\x3e\xbe\x78\xe1\xc0\x81\xa1\xea\x87\ +\xd9\x20\x11\x76\xef\x3e\x5e\xa8\xd5\x56\x3b\xd7\x1b\xd9\x88\x29\ +\xdd\x67\xf1\x10\x41\x8f\x06\xfb\x91\x28\xf5\x62\x7d\x38\xee\xab\ +\x05\xba\xc7\x44\x78\xc6\xc4\x8d\x34\xf5\x95\x2c\x4b\x6b\xd7\x4c\ +\x60\x9c\x24\x5f\xcb\xfb\x92\x98\xde\x93\xb7\xb2\xbf\xa2\x5a\xc5\ +\x8f\xc1\x19\xe6\xa2\xc4\x19\x93\x2d\xef\xda\x15\x6e\x5a\x68\xb4\ +\x41\xc9\xa6\xa6\x1e\x5d\x99\x99\x99\xad\xad\xac\x5c\xbe\xec\x10\ +\xcf\x41\x98\x33\x7a\x16\xf3\x70\x8b\x0d\xea\x68\xe7\x16\x01\x28\ +\x63\x46\x84\xba\xa2\x19\x74\x8c\xa3\x4d\x87\x1f\xab\x58\x7b\xe3\ +\xe4\xc9\x73\xa7\xc7\xc7\x67\x56\xa5\x56\x61\x33\x3e\x7e\x34\xdd\ +\xb5\x6b\x7b\x25\xcf\x7b\x87\x49\xf2\xfb\x13\xfb\x33\x39\xc9\x63\ +\x48\xbb\x05\xdb\xdc\x0a\xc7\xe5\x56\x38\xbc\x21\xdf\x72\xfb\x15\ +\x0c\xdd\x48\x3b\xec\x6c\x07\x64\xc7\xd3\x4d\x4a\xfd\xc9\x9f\x7c\ +\xbb\x90\xe5\x85\x81\x9c\xb8\x4b\xa6\x1f\x94\xfa\xea\x97\x5d\x95\ +\x74\x3e\xa2\xd9\x6a\xb1\xb8\x0a\x7f\x13\x61\xdf\xcd\x30\xb8\x8e\ +\x0d\x63\xb5\x89\x89\xf3\x0b\x23\x23\xc5\xf5\x5a\x5e\x58\x14\x71\ +\x36\xca\xcf\x63\x9e\xc4\xec\x32\xee\x01\x15\xda\xa7\x53\x70\x2b\ +\x8b\xdb\x23\xe8\x8b\xb0\x4d\x91\xb1\x46\xd6\xf8\x69\x96\x74\xbe\ +\x73\xdf\x7d\x27\x97\x63\x77\xbf\xea\xeb\x83\x03\x52\xe3\xbe\x48\ +\x78\x0c\xe2\x13\x36\x0f\x4a\x1e\x35\xee\x41\x49\x01\x6b\x33\x21\ +\xdb\x94\x08\xe4\x40\x43\x62\x15\x58\xc4\x3a\x25\xe2\xdb\x46\x73\ +\x90\x55\x53\x68\x65\x7f\x6b\x6b\x8d\x0e\x92\xc2\x70\x30\xa3\x31\ +\x67\xcb\x35\xfa\x6f\x86\x3f\xce\xc6\xc8\x85\xae\xfc\x72\xfd\xe0\ +\xc1\x4f\xf6\xd4\xd7\xfb\x86\x23\x47\x8e\xd4\xab\xd5\x8e\xcb\xd1\ +\x3a\x27\x6b\x16\xf1\x1c\xd6\x83\xc0\x56\x5a\x45\xcd\x26\x1b\x3a\ +\x0c\xdb\x84\x3a\xc1\x43\x26\x19\x4d\xad\xd7\x5c\x2a\x9c\xcc\x37\ +\x6a\x05\x4b\x7b\x2c\x1e\xc7\x3c\x2c\x7c\x8f\x50\xaf\x4d\xa9\xf5\ +\x7d\xab\xbd\x77\xb7\x37\x9e\x81\xab\x48\xcb\xe0\x73\x26\x9c\x44\ +\xbc\x8b\xe2\xbb\xb2\x4e\x65\x59\x71\x1e\x4a\x97\x53\x80\xf9\xf9\ +\x6d\x49\x67\x7f\x47\xb7\x9a\xf1\x9e\x68\x6d\x45\x94\xdb\xce\x0a\ +\x20\x93\x75\x31\x3a\x9c\x09\x79\x76\x91\x64\x5b\xf3\x93\x36\xff\ +\x51\x36\x4c\x54\x27\x26\x8e\x9c\x1b\x1c\xec\x58\xaf\xd7\xf3\x45\ +\x53\x98\x05\x3d\x0f\x7e\xd2\xb0\x13\xdc\x7d\x8d\x0d\x2a\x00\xbd\ +\x10\xca\x96\xfa\x9c\x7b\x57\x20\xcc\x3a\x50\x8c\x19\x3b\xa4\x70\ +\x4f\x8c\xee\x87\x50\xe2\x5a\x0a\xbe\xb9\xf1\x1c\xdc\x40\x5a\x97\ +\xb8\x20\xe9\xac\x22\xc7\x83\x7c\x0c\x87\xe3\x10\xe7\x1a\x8d\xc6\ +\x52\x4e\xd7\x3a\xd0\x04\xf2\x14\xa0\xb3\xb3\x2f\x0d\xcd\xe6\x40\ +\x24\xdd\x29\x31\x60\x2b\x6d\x3f\xd1\x92\xeb\x51\x2c\x2a\xe6\x67\ +\x63\x4c\x56\x56\x57\x4f\x46\x98\xb8\x13\x0c\xae\xb2\xe1\xc0\x81\ +\xc3\x2b\x2b\x2b\x7b\x8f\x67\x99\x2e\x35\x9b\x3a\x17\x1d\xe6\x20\ +\x3c\x03\x3c\x04\x1a\x6a\xd9\x2f\x89\xed\x04\xa8\x60\x8f\x5a\xea\ +\x33\xf1\x21\x48\x02\xa2\x53\x76\x59\x52\x62\xdf\x70\xe2\x39\x50\ +\x45\xbe\x04\x3a\x87\x39\x65\x74\xcc\xc4\x77\x93\x24\x39\xd5\x68\ +\x84\x85\x5a\x2d\xbd\x04\xd4\xa0\x98\xc1\xb5\x66\x4d\x3a\x35\x35\ +\x15\xdc\xf3\x52\xc9\x57\x9a\x43\x8e\xbe\x07\xab\x67\xd3\x89\x48\ +\xe4\x31\x6a\x0d\x7b\x2e\x49\x58\x48\xd3\xbc\xfa\x97\x7f\x79\x20\ +\x72\x97\xa5\xfd\xa1\x43\xfb\x73\x89\x8d\x89\x09\xe6\x7b\x7b\x8f\ +\xad\x5f\x69\x84\x45\xe5\x9e\x8d\x84\xe7\x8c\x9f\x00\x6d\xb2\x21\ +\xbd\xca\x06\x6b\x0b\xa8\xab\xbd\x64\xf0\x47\x4e\x9c\x1a\xb0\x8c\ +\x38\x63\x73\x2c\x84\xf0\xab\xdc\x7a\x2f\x2a\x3d\x4b\x56\x5c\xec\ +\xea\x66\x7d\x7e\x9e\x06\xdc\xbc\x27\x91\xc2\x4b\x41\x2b\xeb\x9d\ +\xa4\xa5\xad\x40\x7f\xab\xcb\xa2\x96\xd7\x34\x19\xf8\x92\xe4\x33\ +\x4d\x85\xa5\xb9\x53\x1b\xcd\x5f\xb7\xdf\xd7\x56\xa2\x79\xe0\xc0\ +\xdb\x97\x17\x57\x5e\xac\x55\x56\xab\xcb\x91\x7c\x1e\x27\xb3\x86\ +\x67\x5b\xbe\x41\x83\x52\x8b\x0d\x5c\xf5\x45\x9b\x95\xf7\xa6\x8d\ +\xbb\x0e\xba\x24\xf8\x00\xf9\x28\xe6\xcd\x10\x99\x69\x26\x85\x0f\ +\x42\xb3\xba\xbc\x7a\xb9\xb3\x0a\x64\xeb\xeb\xdc\xb2\x73\xdd\x8e\ +\x02\xc5\x80\xc9\xa4\x70\x21\x9a\xf9\x76\x95\x57\x01\xea\x88\xf3\ +\x92\xce\x84\xa6\x2e\x77\x75\xad\xdf\x56\x9f\xed\x76\x64\x93\x0d\ +\xe3\xe3\x47\xe7\xcb\x43\xe9\xba\xab\x85\x0b\x64\xf9\x9c\xe1\x79\ +\xf0\xe3\x36\x3b\x80\x2d\xd7\xd8\x70\xd5\xb9\x35\x68\xf5\x01\x66\ +\x11\xef\x08\xde\x44\xc9\x2f\x83\x39\xd5\x8c\xf9\xd2\xca\x52\xa9\ +\x0a\xa5\xfc\x76\xcb\xed\x14\x7e\x10\x0b\x85\x17\x56\x9b\x4d\x66\ +\x10\x89\xcc\x99\x08\x3b\x41\xc3\x88\x20\xc7\x63\x44\x3e\xc8\xb2\ +\x74\xfd\xf0\xe1\xfd\x77\xd5\xd1\xf9\x38\x69\xa5\xb3\xe3\xcd\xfd\ +\xfb\x7d\xe9\xe8\xd1\xa3\xb5\x4a\xa5\xeb\x52\x74\x98\x23\xf7\xac\ +\xe1\x19\xd0\x5e\x60\xb0\xed\x18\x73\x60\x15\x31\x2f\x78\x57\xd2\ +\x9b\x92\x7e\x41\x4c\xdf\x6f\x14\xf3\x0b\x97\xe6\xfa\x36\xb8\xc3\ +\x96\x38\xb4\xc7\x4b\x87\x0e\x1d\x0a\x3f\xff\x79\xa9\xb2\x9e\x95\ +\x7b\x89\x1a\x28\x38\x0c\x65\xd6\x08\x4e\xba\x4c\x3c\x1f\x9c\xbc\ +\x79\xfe\xfc\xf9\xb9\x43\x87\xf6\x37\x3e\x4d\x00\x6e\x50\x44\x68\ +\x7c\xfc\x68\xa1\x58\x2c\xf6\x34\x5c\xda\x15\x1c\x9e\x8c\x79\x7c\ +\x3e\x3a\x3c\x1a\xa3\xfa\x1c\xb5\x96\x47\x1d\xb7\xc3\x2f\x9c\xfb\ +\xad\x18\xd3\xe3\x79\x5e\x3d\xdf\xd3\x33\xb6\x3e\x33\x43\x76\xb7\ +\xed\xb6\xb4\x6d\xd3\xf9\xfe\xfd\xac\x4f\x4d\x4d\x57\x2f\x5e\xac\ +\x5e\x28\x75\x74\xbf\xdf\x5c\x6f\x76\xc6\xe8\x72\x9a\x66\x8d\x95\ +\x95\xe6\xca\xf8\xf8\xd1\x4f\x8d\xfe\x37\x93\xeb\xd8\xb0\x7c\xf4\ +\xe8\x62\xd5\xaa\x2d\xe7\x84\x39\x11\x4f\x88\x64\x38\xb7\x2e\x04\ +\x3c\x93\xa7\x7e\xaf\x1e\xe2\xb9\x4a\x1c\x58\x3b\x73\x86\xe6\xd9\ +\xb3\x77\xb7\xf1\x4d\xf9\xb8\xc1\x88\x0e\x1c\x38\x1c\xc6\xc7\x87\ +\x34\x3d\x0d\xdf\xff\xfe\xbe\x9c\xbb\x75\xfd\x77\xa3\x94\xa6\xc2\ +\xf8\xf8\xc1\xb4\x59\x3e\xd7\x5d\xa8\x69\x2b\xd0\x55\xaf\xb3\x6e\ +\x6b\x29\xcf\xab\xab\xa7\x4f\xbf\xde\x84\x4f\x67\x2c\x77\xcb\xd9\ +\xe0\x47\x15\x93\x30\x30\x85\x98\x41\x8c\x23\x66\x30\xe3\x98\x83\ +\xd8\x7c\x7a\x13\xa1\xcd\x09\xf0\xf8\x38\xe9\xca\xca\x6c\xd2\xd3\ +\x33\x96\xcf\xcc\x1c\xce\x3f\xad\x8d\x5f\x5d\xe7\x76\x00\x10\x12\ +\x53\x24\x63\x2b\x63\x85\x62\xf1\x4a\xd1\xb5\x42\x59\xa4\xa5\x2c\ +\xe4\x69\x12\x42\x4e\x96\xd7\x54\x6e\xd6\x62\x47\x4f\xfd\x34\xa7\ +\x33\x0e\x92\x7f\xba\x60\x48\xb7\x0a\xbf\x9a\x52\xd8\xc7\xbe\x00\ +\xb0\x8f\xe9\x38\x79\x07\x87\x71\xeb\xf1\xf8\x94\xc2\xf8\x0c\xe9\ +\x95\xd1\xde\x4a\xa6\x38\x18\x63\x32\x82\xc2\x60\x82\xfb\x45\xe8\ +\x26\xa8\x64\xb9\x11\xac\x15\x85\x70\x31\x49\xbc\x98\x34\xb4\x10\ +\x7b\x9a\x4b\x3d\xf3\xcb\xd5\x23\x5f\x27\xfb\x34\x81\xb8\x99\x1c\ +\x38\x7c\x20\x39\xb7\x74\xac\x3b\x75\x61\xa0\x90\x44\xd5\xaa\xc9\ +\x7a\x52\xac\xad\xb1\x38\x54\x9b\x3e\x38\xfd\x89\x07\xf1\xf1\xd3\ +\xe1\x03\x4a\xfa\xfa\xfa\xba\x3a\x8a\x61\x5b\x54\xbc\x5f\xe2\x31\ +\xc4\xc3\x01\x6d\x97\xd4\x25\x42\x59\xc1\x89\xa4\x5c\xa8\x26\xb4\ +\x46\xd0\x5c\x80\xb7\x83\xc2\x2f\x14\xf2\xf7\x15\xf3\xc5\x77\x2b\ +\x4b\x55\x26\xc9\x7f\x13\xf7\x09\x84\xf4\xc2\x9f\xed\xed\x2a\x76\ +\x76\x3d\x8c\xb3\xe7\xa5\xd0\x19\x60\x5e\x81\xf7\x93\xba\xcf\xc4\ +\x81\xb8\xd8\x53\xde\x5b\x3b\xb4\xff\xd0\xc7\x0e\x46\x3e\x02\x80\ +\x24\x31\x49\x32\x72\xb1\xab\x2f\xcb\x78\x38\x09\xc9\xf3\x0a\x7a\ +\x2a\xa0\x3d\x04\x0d\x0b\xba\x24\xa5\x52\xab\x2f\x23\x09\x21\x4b\ +\xca\xd4\x2a\x42\xe6\x24\xbd\x83\xf8\x39\xf8\xcd\x90\xa4\xc7\xe3\ +\x70\x79\xe9\xc4\x57\x4f\x34\x3e\x6d\x36\x1c\x38\x7c\x20\xb9\x38\ +\xfb\xde\x08\x05\xbe\x04\xda\x0f\xdc\x13\xa4\x15\x05\x4e\x58\xc9\ +\xcf\x43\xa2\x37\xc8\x0b\x27\x2e\x86\xfa\xa5\x23\xaf\x1e\xb9\x29\ +\x1b\x3f\xd4\x15\x96\x78\x95\x74\x70\xa9\x32\x94\xe5\xe1\x89\x44\ +\x7c\x49\xf0\x3c\xb0\xcb\x78\x8b\x4c\x81\xd6\xe4\xe8\x66\xd3\x9d\ +\x02\x50\x06\xba\x81\xed\x88\x07\x82\xc3\xc3\xca\xf3\xe9\xd2\x72\ +\xed\xb5\xb1\x3f\x1f\x9b\xd3\x7f\x54\xed\xd3\x04\xe1\xe4\xa5\x93\ +\xa1\xb3\x94\x74\x27\x31\xbf\x17\x74\xaf\xc4\x4e\x84\xdd\xea\x45\ +\x3e\xe0\x3c\xee\x49\x92\xc6\xdf\xf4\xe4\xd9\x91\xfd\x87\xc7\x17\ +\x75\x40\x1f\x49\xe5\x6f\x9c\x0b\xec\x23\x19\x4a\x3b\x07\x82\xc3\ +\xd3\x11\xff\x63\xd0\xe7\x8c\xc6\x64\x2a\xdc\x62\xbc\xd4\x96\x4d\ +\x60\x4a\xc0\xa0\xd0\x16\xc4\x90\xa5\x81\x3c\xa3\xd2\xb1\x9c\xff\ +\x70\xf8\x3f\x0d\x7f\xa0\x2e\x55\x7d\xd0\x9f\x4a\x46\xb9\xe5\xdc\ +\xc5\x84\xfe\xee\x1e\xd0\x28\xa2\x07\x51\xb4\x08\x42\x25\xf0\x16\ +\x49\xfd\xb6\xb6\x14\x55\x4c\xab\x17\x2b\xaf\x4d\x7c\x7d\xe2\x02\ +\xad\x32\xf8\xaa\x5c\xdd\x94\x90\xfa\x1e\xe8\xeb\x74\xa6\x87\xf2\ +\xdc\xbf\x07\xbc\x68\xb4\x13\xbb\xf3\xba\xcf\x6d\x56\x60\x4d\x5a\ +\x75\x42\x0d\xa8\xb7\xdf\x6f\xe6\x0a\x9b\x13\xdb\x0e\xa4\x6d\x42\ +\xcf\x62\xff\x53\x91\x7e\xa1\xbf\x58\xbc\x77\xfc\xc2\x50\x45\x53\ +\x1f\xe9\xd9\xdd\xb1\x48\x52\xb3\xa3\x54\xc0\xf4\x1a\x86\x90\x2b\ +\x32\xc2\x08\x9c\x08\x3a\xdd\x1a\xed\x7f\xde\x09\xaf\xe4\xc5\xe6\ +\x63\xbd\xe5\xa4\x7b\x8a\x1b\xd7\xbe\xc6\x80\x3f\xa2\x28\x35\x47\ +\x8d\x9e\x15\x7c\x16\x34\x86\x5d\x26\x68\x93\xee\x91\x56\xe9\x79\ +\x09\x74\x11\x58\x73\xa4\x29\x51\x90\xe8\x06\x06\x81\x5e\xa0\xd8\ +\x06\x4c\x98\x02\x62\x08\x78\x2a\x98\x02\x41\x69\x3e\x50\xfa\xde\ +\x63\x9d\xc3\x27\x35\xf5\x6b\x32\x61\x12\xf5\x6e\x29\xa6\x1b\xcd\ +\x50\x32\xe4\x58\x55\x07\x95\x02\xbe\xba\xbe\xa0\x6c\x34\x2a\x78\ +\x96\x18\x2e\x14\x9b\xc9\xc2\xcc\x9f\x3f\xb7\xa1\x3f\x56\x6d\xd3\ +\x14\x5a\xd5\xe0\x94\x42\xd7\x7a\x57\x37\x45\x1e\x06\x3f\xa3\x56\ +\x5d\x5e\x6e\xdb\x3b\xb4\x9a\x92\x2b\xc2\x27\x8d\x7e\x89\xe3\x4c\ +\x50\x32\x07\xae\x86\x40\x07\xe6\x1e\xc9\x8f\x80\xc6\x69\x15\x52\ +\xbd\xed\xcd\xb7\x27\xc7\x1a\x90\x78\x02\xa1\xa0\x10\xb3\xd5\x52\ +\x9c\x48\xb6\x9f\x12\xaa\xde\xb5\x4f\x38\x88\x2f\xff\x59\x23\x2b\ +\x96\x4a\x0b\x84\xe4\x35\x20\x6f\x5f\xdc\x18\x93\xe8\x46\xad\x6e\ +\x51\x68\xb5\xc4\xc7\x10\x4f\x05\xc7\x77\xae\xf4\xc5\x73\xfb\x0f\ +\xb5\xfa\x03\x57\x01\x60\x9e\xa4\x58\x64\x08\xf3\x18\xf0\x80\xa1\ +\xfb\xba\x91\x72\x8e\xbd\x22\xe9\x2d\x5b\xdf\x8d\x8e\x3f\x25\xe1\ +\x4c\x52\xca\x57\x36\x62\x21\xab\x84\x46\xaa\xac\xdc\x5b\x48\x74\ +\x84\x4c\x4f\x5a\x7e\x01\xfc\x04\xd2\x36\x4c\xe9\x1a\x08\xf4\x05\ +\xe9\x33\x98\x5c\x52\xd6\x4c\x4a\xd9\xd8\x1f\x8f\x7d\xa0\xff\x7c\ +\x97\x8e\x51\x50\xf8\xfe\xb6\x6a\xf1\xcd\xc5\xe3\x59\x48\xd6\x2c\ +\x7e\x81\xfc\xa4\x08\x2f\x82\x1f\x6f\x0f\x48\x53\x43\xc0\x74\x02\ +\xf7\x5b\x7e\xc2\x79\x3a\xb3\xbe\xb0\xfb\xd2\x0d\x00\x6c\x87\x42\ +\x23\x32\x64\xf9\x7e\x05\x0d\x72\xcd\x34\x0c\x54\x0d\xc7\x63\xd4\ +\xb7\x93\xe0\xef\x34\x08\xa7\x96\x7b\x97\x37\x38\x48\x7e\xb5\x4a\ +\x9f\x5a\x59\xdb\xbb\x31\xb8\xd4\x8c\xa5\xf9\x34\xc9\xe6\x73\xc2\ +\x6a\x68\x45\x8f\x7b\x30\xe5\x36\x08\x89\xed\x7e\x49\x8f\xd3\x1a\ +\x58\x36\x7a\x7a\xf8\x41\x3a\xb5\x6b\x56\x07\x55\xbf\x53\x10\x6c\ +\x5b\x52\x3e\x39\xc9\xe5\xc3\x8c\xaf\x6f\xdb\x56\x9e\x73\xee\x39\ +\x47\xaf\xb5\x27\x51\x4f\x8a\x56\x73\x57\xad\xfd\x0c\xda\xec\x21\ +\x78\x04\x06\xde\x97\xd4\xb0\xed\x54\x53\x0a\xdd\x9d\xdd\xe5\xf4\ +\x4a\xdc\x2a\x31\x62\xab\x72\xdd\x25\x86\x08\x2c\x0b\xde\x52\xe0\ +\xa7\x5d\x1d\xe9\xc9\xb9\xca\xd2\x95\xab\xb6\xbb\xa9\xf2\x41\x32\ +\xa1\xf5\xdd\x7f\xb4\xfb\x4c\x4c\xab\x1b\x92\xab\xa0\x06\xe2\x45\ +\xc4\xce\xeb\x41\xc0\x0c\x28\x78\xc2\xa6\x99\x50\x68\x76\x27\xf1\ +\xff\xee\xfe\xda\xee\x79\x7d\x55\x77\x9c\x27\xb4\xed\xd8\x07\xa1\ +\x31\x35\xa5\x6c\x7a\x68\xfc\x64\x21\x2d\x16\x31\xa3\x88\x31\x43\ +\x45\x9b\xfe\x08\x4a\x82\x01\xc8\x87\xd3\x8e\xd0\x31\x39\xc9\x3a\ +\xe0\xc0\x0c\x4a\xb3\x66\x45\xad\x16\x75\x8f\xe4\xcd\x0e\x0c\x98\ +\xdc\xb0\x64\x74\x54\x81\x33\xef\x56\x96\x3e\xd6\x71\x19\xfb\xc4\ +\xd7\x4e\x34\x7a\x2e\xcf\x9d\x6f\x26\x85\x9f\x59\xfc\x6f\xc4\xdf\ +\x0a\xce\x22\xea\xb8\x1d\x21\x5a\xb4\x1c\x14\x7a\x1a\xf9\xf7\xed\ +\xe4\xb9\xca\x4a\x73\xfb\xae\xff\xb6\xab\xf4\xeb\x44\x87\x83\x07\ +\x1d\xa7\x87\x66\xaa\xcd\x3c\x9d\x05\xde\x91\xb5\x04\xd7\x5d\x8d\ +\x11\xa1\x75\xd7\x29\x0c\x18\x57\xa6\xdb\xb5\x43\x60\x1c\xe5\x99\ +\x8b\x11\x57\x6c\x8a\xf6\x0d\x77\x81\x22\xb0\x2e\xbc\x90\x36\xe2\ +\x1a\x93\xb7\xae\xbd\x6d\xfb\xc8\x5f\x90\x0d\x2e\x9d\x59\x4a\x55\ +\x3f\xa2\xe0\xff\x63\xf4\x43\xc1\xdc\x87\x40\x28\x00\x5b\x41\xcf\ +\x06\xfb\xcb\x22\xd9\xd7\x3d\x9f\xec\x9e\x28\xdf\xb7\xe5\xe5\xa9\ +\x97\x53\x49\x37\x4b\xb4\x3e\x59\x0e\x10\x9b\xe5\xe2\x15\x89\x8b\ +\x86\x0d\xae\xab\x1a\x6d\x24\x28\x48\xea\xc8\x4d\x81\x97\x5a\xbf\ +\x6f\x21\x5e\x07\xf9\xea\xf8\xe8\x9a\x08\x0b\x62\xb4\xb2\xb5\x3c\ +\xc4\x8f\xfc\xfd\x16\x20\x54\x96\x96\x96\xec\x70\x44\xe2\x9b\x11\ +\x7e\x0c\x9c\xa3\xd5\xcf\x73\x2b\x56\x53\x04\xb6\x21\x7d\x0e\xe9\ +\x0f\x12\xf3\xcf\x6c\x4d\x5c\x4a\xe7\x87\xf7\x4d\xde\x25\x1b\x0c\ +\x1d\x59\x2d\xd8\xa4\x12\xe1\x23\xf9\xaa\x94\x63\x67\x69\x48\xae\ +\xbb\x20\x31\x83\x93\x21\x35\x95\xa9\x06\xce\x3e\xfc\x0d\xec\x72\ +\x40\x3d\x85\x8e\x46\x99\xfd\xac\xc3\xad\xaf\x9d\x6d\x82\x20\x29\ +\x1b\x9f\x9c\x5d\xac\x35\xb7\xff\xac\x08\x29\x24\x29\xd2\x0b\xc0\ +\x48\x9b\x01\x9b\x4c\x18\x96\x5d\x91\xb4\xd5\x51\x3b\xd3\xc0\x0f\ +\x57\xca\xc5\xb7\x3e\x1b\x1f\x9c\xdd\xf3\xb5\x3d\xeb\x27\x96\x4f\ +\x34\x99\xe4\xb6\x6e\x9f\x4e\xfc\xc5\x44\x1a\x9b\xb1\x37\x24\x1a\ +\xb5\xdd\x13\xa4\xe4\xea\x4e\x5a\x6a\x35\x50\x58\x57\x28\xd4\x87\ +\x16\x87\x0c\x2d\x13\x70\xda\x08\x0d\x72\xaf\x59\xda\xd0\xb5\x8c\ +\x2e\x82\x6c\xa9\x03\x79\xb8\xd8\x4c\xb6\x30\x7e\xfb\x37\xbc\x6c\ +\x7b\x66\x92\xa6\x56\x2b\x17\x9c\xc7\xd7\x24\x7f\x13\xfc\x33\x99\ +\x45\x4c\x13\x5d\x65\x42\x0a\xea\x31\x3c\x28\xf1\x25\xf0\xbf\x0e\ +\xd1\xff\x12\xc5\x17\x7b\xeb\xde\x33\xd1\xf5\x40\xff\xbe\xc9\x5d\ +\xa5\x03\x87\x0f\x24\xe2\xe6\xa6\x21\x49\x2f\x4f\xbd\x9c\xf6\x36\ +\x93\xee\x10\xd8\x23\xeb\xf1\xb6\x4f\x4b\xda\xbb\x37\xad\x51\xd9\ +\x9a\x60\xb9\x81\x6b\xe3\x47\xc7\xdd\x06\x06\x0d\x7e\x85\xae\x58\ +\xe8\x7c\x41\xe8\xdf\x09\x5e\x24\xd0\x09\xaa\x05\x69\x11\x71\x0c\ +\xf1\x6d\x15\xf4\xd7\xe7\x7b\x56\x3e\xf0\xc1\x0f\xb3\xe4\xd6\x22\ +\x49\xbb\xff\xcb\xee\x22\x17\xea\x63\xa5\x94\xcf\x2b\x86\x2f\x13\ +\xf4\x94\xc4\x56\xa1\xa2\xda\x65\xa5\x02\x16\xca\x5b\x15\xa5\x16\ +\x04\x27\x14\xf4\x8b\x60\x7e\x99\x88\x93\x4e\xc2\x62\x68\xa6\xab\ +\x79\xa9\xab\xb6\xba\xba\x9a\x97\xb7\x95\x5d\x3b\x57\xd3\x8e\xfe\ +\xba\xf2\x7a\x25\xcd\xba\xd4\x9b\x66\xc9\xde\x18\xfc\x0f\x51\xf8\ +\x47\x12\x0f\x48\xea\x90\xa4\x20\x22\xd2\x12\xf0\xdd\x10\xf4\x5f\ +\x9b\x85\x9e\x9f\x7d\xe7\xdf\x7e\x67\xc3\xb6\x53\xdb\xd6\xef\xab\ +\xd1\xb7\x8b\x79\x22\x47\x05\xc3\x58\x05\xc1\x9c\xf1\xb1\x80\xde\ +\x76\x9a\xcc\x34\x33\x2d\xb5\x58\x71\x67\x62\xdb\x42\x8d\x5d\x53\ +\xbb\xe6\x4a\x64\x3f\x74\x22\x07\x7b\x03\x6b\x02\x31\x0a\xed\x42\ +\xcb\xad\x08\x41\xab\x9a\xac\x20\x46\x30\x0f\x38\xe8\xe9\x0c\x1d\ +\x0f\xe2\x44\x2c\xc6\xb3\x8a\xeb\x8b\xfd\x3d\x71\xdd\xeb\xb5\xbc\ +\xb3\x3f\x0d\x6b\x31\x29\x16\x3a\xe8\x72\x43\xf7\xe6\x89\x9f\x02\ +\x9e\x11\xbe\x4f\xad\x31\xdb\xe6\x24\xa5\x29\x7c\x41\x4a\x8e\xe5\ +\x64\xf3\x17\xab\x17\x1b\x37\xa4\xc2\x74\x91\x35\xad\x85\x22\xfe\ +\x11\x70\xc9\x50\x95\x7d\x2a\xa0\x59\xec\x0b\x95\xbe\xfe\xd5\xd3\ +\x9c\x6e\xdc\x6d\xee\x6e\x6c\x1d\x54\x7d\xd7\xd4\xae\xd9\x8e\x44\ +\xd3\x49\x43\xcb\x04\xe6\x81\x67\x0d\x7b\x64\xfa\x10\xc5\xb6\xc2\ +\x81\x96\x83\x2c\x20\x3a\x11\x23\x82\x87\x64\x2d\x23\x2f\x4b\xf1\ +\x82\x63\xb2\x4c\x12\x9a\xb6\x0b\x89\x54\x8e\xa6\x57\x81\x11\x60\ +\x94\x56\x4d\x52\x76\x2b\x01\x82\xf6\x3c\xc1\xf0\x9e\xec\xb7\x9b\ +\x85\xb0\x74\xe4\xec\xcf\xae\xfa\x31\xd9\x6e\xf5\x01\xf6\x53\xe8\ +\x1a\xe9\xea\xa9\xd4\x93\xee\x2c\x36\xea\x74\x74\xac\x2e\x2f\x2c\ +\xd7\x18\x27\xbb\x5d\x27\xf4\x49\x22\x49\x13\x5f\x9f\x48\xd7\xce\ +\x9d\xeb\x29\xe4\xe5\x7b\x93\x02\x4f\x07\xf1\x39\xa4\xcf\x08\x46\ +\x25\x75\x4a\x4a\x6e\x68\xb6\x48\x96\x88\x52\xc8\x25\x32\x05\x55\ +\x65\xd5\x24\x45\x49\x41\x22\x95\x54\x6a\xbf\x0a\x12\xc9\x55\xb3\ +\x6a\x7d\x66\x4d\xe2\x57\xa0\xff\x19\xe0\xaf\x5c\x5b\x3e\xf3\xcd\ +\xaf\x1e\xaf\xdf\x00\xc0\xa6\x72\x4c\xb6\x4f\x60\x06\x73\x98\x4f\ +\xbc\xa8\x74\xd7\x40\x1c\x50\xf2\xd8\xce\xe1\x32\x3d\xe5\xad\x22\ +\x19\x17\x3c\x2f\xe9\x69\x89\xdd\x41\x61\x00\xa9\xe3\x43\x1b\xe1\ +\x3a\x3f\x61\x11\xbc\x09\x50\xab\xc0\x6a\x19\xba\xb8\x01\xb8\x5c\ +\xd2\x15\x49\xc7\xc1\x7f\x5d\x48\x0a\xdf\x08\x17\xc3\x3b\xdf\xf8\ +\xd3\x1f\xad\x5f\x9f\x71\x5e\x2d\x87\x37\xd3\x4a\xee\xc2\xce\xef\ +\x54\x7c\xc8\xb9\xa4\x8d\x89\xaf\x4f\xcc\x5e\xb9\xb8\xb0\x5a\xca\ +\x3a\xe6\x14\x7c\x4c\x0a\x13\x46\x8f\xa8\x95\x3e\x0f\x21\xca\x40\ +\xca\xe6\x3f\x49\xb5\xfc\x84\xae\x1b\x94\x5e\x0b\x4b\xed\x5f\xe9\ +\xea\xe5\x08\x56\x80\x13\x86\x1f\x24\xd2\x77\xdd\x48\x8e\x3f\x59\ +\xfd\xe1\x95\xff\xc5\xad\x3a\x42\x7f\x87\xd2\x06\xbc\xa9\x29\x5d\ +\x7a\x6e\x65\x6c\xa3\x31\x98\x2c\xc4\x98\x1c\x4d\x55\x78\x10\xf8\ +\x0c\xc1\x8f\x60\xed\x40\xf4\x63\xba\x0c\x45\x89\x70\x9d\x6d\xb7\ +\xf6\x2c\xf9\xea\x5b\x91\x59\x6c\xc8\x5c\x40\xbc\x63\xfb\x47\x69\ +\x8c\x3f\x8a\xc5\xd2\x7b\x5d\x83\xdb\x56\x0f\xfe\xfb\x8f\xfa\xb0\ +\x3b\x1a\x8c\xfc\xa6\x44\x92\x38\x44\x78\x6e\x76\xac\x18\xab\x85\ +\xee\x3c\x24\xdb\x93\x90\xdc\x6f\xd8\x2b\x85\xfb\x24\x6d\x57\xf0\ +\xa0\x50\xaf\xa4\xae\xd0\xaa\xf6\x80\x90\x87\x40\x16\x14\x32\x89\ +\x3a\xd2\x65\x82\xce\x82\x8e\x26\xf2\x1b\x99\xc3\x51\x0f\x56\xe7\ +\x86\x0e\x3f\x5c\x3d\x74\xe8\xe6\x9d\xe1\xdf\x09\x00\x36\x65\xd3\ +\x0f\xed\x62\x57\x71\x6b\xb1\xdc\x99\x94\x93\x3e\xe7\x1e\x90\xc3\ +\x90\x0a\xde\xde\xbe\xbe\xbb\x4d\x84\x8a\x02\x91\x10\x1a\xc2\xf5\ +\x40\xa8\x2b\x78\x55\x0e\xe7\x94\xe8\x54\x74\x7e\xd6\x85\xf4\x7c\ +\x47\x7d\x65\xed\x5b\x9f\xd0\x8d\xfe\x9d\x02\x60\x53\x36\x81\xd8\ +\xc7\xbe\xd0\xd1\x3f\x9b\x2c\x43\x29\xad\x26\x5d\x31\x29\x76\x87\ +\xe0\xae\x68\x8a\x0a\x72\xe2\x90\x53\x74\x96\xc6\x24\xb7\xb2\x7a\ +\x48\xc3\x5a\xa9\x59\x5e\xfb\x60\x79\xbd\xb6\x9f\x99\x6c\xf2\x36\ +\xa2\xd7\xef\x24\x00\x1f\x16\x21\xed\x3f\x40\x58\x1c\xdf\xa7\x45\ +\x16\xc3\x8e\xfe\xba\x00\xba\x46\x4a\x3e\x7a\x14\xca\xdb\xca\xde\ +\xf2\xc0\x16\x0f\x2d\x0e\xf9\xf0\xfe\xc3\xf1\x4e\xfa\x0a\xff\x0f\ +\xc1\xea\x47\x68\xcb\x86\x1c\x37\x00\x00\x00\x00\x49\x45\x4e\x44\ +\xae\x42\x60\x82\ +" + +qt_resource_name = b"\ +\x00\x07\ +\x07\x3b\xe0\xb3\ +\x00\x70\ +\x00\x6c\x00\x75\x00\x67\x00\x69\x00\x6e\x00\x73\ +\x00\x0b\ +\x08\xd8\x99\x42\ +\x00\x67\ +\x00\x65\x00\x6e\x00\x65\x00\x72\x00\x61\x00\x6c\x00\x69\x00\x7a\x00\x65\x00\x72\ +\x00\x08\ +\x0a\x61\x5a\xa7\ +\x00\x69\ +\x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\ +" + +qt_resource_struct_v1 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\ +\x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +" + +qt_resource_struct_v2 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01\x6e\x54\x90\x86\x20\ +" + +qt_version = [int(v) for v in QtCore.qVersion().split('.')] +if qt_version < [5, 8, 0]: + rcc_version = 1 + qt_resource_struct = qt_resource_struct_v1 +else: + rcc_version = 2 + qt_resource_struct = qt_resource_struct_v2 + +def qInitResources(): + QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() From cf749b2ceea4d1ef42773baac1f512f777cbc65c Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sat, 23 May 2020 22:01:51 +0400 Subject: [PATCH 31/43] 0.8 --- metadata.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/metadata.txt b/metadata.txt index 1a396f3..cd300b9 100644 --- a/metadata.txt +++ b/metadata.txt @@ -20,7 +20,7 @@ about=Plugin to Generalize, Simplify or Smooth lines in QGIS Distance Weighting McMaster's Sliding Averaging Algorithm Snakes Algorithm : Slowest smoothing algorithm -version=0.7 +version=0.8 author=Piotr Pociask, Matthew Petroff, Sylvain POULAIN @@ -41,9 +41,11 @@ experimental=True deprecated=False changelog= - 0.7 (17.05.2020) - - fix save layer to file - - remove unattended column in temporary layer + 0.8 (23.05.2020) + - fix import resources + 0.7 (17.05.2020) + - fix save layer to file + - remove unattended column in temporary layer 0.6 (10.11.2019) - updated to QGIS 3.x - fix projection according to project coordinates From 9c296c883263db23421460480aaf39291baef238 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sat, 23 May 2020 22:02:35 +0400 Subject: [PATCH 32/43] 0.8 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index e2c3265..608e2e1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +0.8 (23.05.2020) +- fix import resources + 0.7 (17.05.2020) - fix save layer to file - remove unattended column in temporary layer From 6bce7fc19240692b97af1511642cb1c8a62717b4 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Sun, 24 May 2020 00:00:17 +0400 Subject: [PATCH 33/43] generated py from ui --- ui_generalizer.py | 481 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 481 insertions(+) create mode 100644 ui_generalizer.py diff --git a/ui_generalizer.py b/ui_generalizer.py new file mode 100644 index 0000000..b88c781 --- /dev/null +++ b/ui_generalizer.py @@ -0,0 +1,481 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui_generalizer.ui' +# +# Created by: PyQt5 UI code generator 5.13.1 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_generalizer(object): + def setupUi(self, generalizer): + generalizer.setObjectName("generalizer") + generalizer.resize(493, 348) + self.gridLayout_20 = QtWidgets.QGridLayout(generalizer) + self.gridLayout_20.setObjectName("gridLayout_20") + self.cbBatch = QtWidgets.QCheckBox(generalizer) + self.cbBatch.setObjectName("cbBatch") + self.gridLayout_20.addWidget(self.cbBatch, 0, 0, 1, 1) + self.bHelp = QtWidgets.QPushButton(generalizer) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.bHelp.sizePolicy().hasHeightForWidth()) + self.bHelp.setSizePolicy(sizePolicy) + self.bHelp.setFlat(True) + self.bHelp.setObjectName("bHelp") + self.gridLayout_20.addWidget(self.bHelp, 0, 2, 1, 1) + self.bOk = QtWidgets.QPushButton(generalizer) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.bOk.sizePolicy().hasHeightForWidth()) + self.bOk.setSizePolicy(sizePolicy) + self.bOk.setObjectName("bOk") + self.gridLayout_20.addWidget(self.bOk, 2, 1, 1, 1) + self.bCancel = QtWidgets.QPushButton(generalizer) + self.bCancel.setObjectName("bCancel") + self.gridLayout_20.addWidget(self.bCancel, 2, 2, 1, 1) + self.stackBatch = QtWidgets.QStackedWidget(generalizer) + self.stackBatch.setObjectName("stackBatch") + self.page_6 = QtWidgets.QWidget() + self.page_6.setObjectName("page_6") + self.gridLayout_19 = QtWidgets.QGridLayout(self.page_6) + self.gridLayout_19.setObjectName("gridLayout_19") + self.label = QtWidgets.QLabel(self.page_6) + self.label.setObjectName("label") + self.gridLayout_19.addWidget(self.label, 0, 0, 1, 1) + self.cbInput = QtWidgets.QComboBox(self.page_6) + self.cbInput.setObjectName("cbInput") + self.gridLayout_19.addWidget(self.cbInput, 1, 0, 1, 2) + self.groupBox = QtWidgets.QGroupBox(self.page_6) + self.groupBox.setObjectName("groupBox") + self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox) + self.gridLayout_2.setObjectName("gridLayout_2") + self.label_3 = QtWidgets.QLabel(self.groupBox) + self.label_3.setObjectName("label_3") + self.gridLayout_2.addWidget(self.label_3, 0, 0, 1, 1) + self.cbAlgorithm = QtWidgets.QComboBox(self.groupBox) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.cbAlgorithm.sizePolicy().hasHeightForWidth()) + self.cbAlgorithm.setSizePolicy(sizePolicy) + self.cbAlgorithm.setObjectName("cbAlgorithm") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.cbAlgorithm.addItem("") + self.gridLayout_2.addWidget(self.cbAlgorithm, 0, 1, 1, 1) + self.stackOptions = QtWidgets.QStackedWidget(self.groupBox) + self.stackOptions.setObjectName("stackOptions") + self.page_11 = QtWidgets.QWidget() + self.page_11.setObjectName("page_11") + self.gridLayout_11 = QtWidgets.QGridLayout(self.page_11) + self.gridLayout_11.setObjectName("gridLayout_11") + self.label_12 = QtWidgets.QLabel(self.page_11) + self.label_12.setObjectName("label_12") + self.gridLayout_11.addWidget(self.label_12, 0, 0, 1, 1) + self.sbRemove_thresh = QtWidgets.QDoubleSpinBox(self.page_11) + self.sbRemove_thresh.setDecimals(4) + self.sbRemove_thresh.setMinimum(0.0001) + self.sbRemove_thresh.setMaximum(9999999.9999) + self.sbRemove_thresh.setProperty("value", 0.0001) + self.sbRemove_thresh.setObjectName("sbRemove_thresh") + self.gridLayout_11.addWidget(self.sbRemove_thresh, 0, 1, 1, 1) + self.stackOptions.addWidget(self.page_11) + self.page_12 = QtWidgets.QWidget() + self.page_12.setObjectName("page_12") + self.gridLayout_12 = QtWidgets.QGridLayout(self.page_12) + self.gridLayout_12.setObjectName("gridLayout_12") + self.label_18 = QtWidgets.QLabel(self.page_12) + self.label_18.setObjectName("label_18") + self.gridLayout_12.addWidget(self.label_18, 0, 0, 1, 1) + self.sbDP_thresh = QtWidgets.QDoubleSpinBox(self.page_12) + self.sbDP_thresh.setDecimals(4) + self.sbDP_thresh.setMinimum(0.0001) + self.sbDP_thresh.setMaximum(9999999.9999) + self.sbDP_thresh.setProperty("value", 0.0001) + self.sbDP_thresh.setObjectName("sbDP_thresh") + self.gridLayout_12.addWidget(self.sbDP_thresh, 0, 1, 1, 1) + self.stackOptions.addWidget(self.page_12) + self.page_2 = QtWidgets.QWidget() + self.page_2.setObjectName("page_2") + self.gridLayout_4 = QtWidgets.QGridLayout(self.page_2) + self.gridLayout_4.setObjectName("gridLayout_4") + self.label_7 = QtWidgets.QLabel(self.page_2) + self.label_7.setObjectName("label_7") + self.gridLayout_4.addWidget(self.label_7, 0, 0, 1, 1) + self.sbJenks_thresh = QtWidgets.QDoubleSpinBox(self.page_2) + self.sbJenks_thresh.setDecimals(4) + self.sbJenks_thresh.setMaximum(9999999.9999) + self.sbJenks_thresh.setProperty("value", 0.0001) + self.sbJenks_thresh.setObjectName("sbJenks_thresh") + self.gridLayout_4.addWidget(self.sbJenks_thresh, 0, 1, 1, 1) + self.label_8 = QtWidgets.QLabel(self.page_2) + self.label_8.setObjectName("label_8") + self.gridLayout_4.addWidget(self.label_8, 1, 0, 1, 1) + self.sbJenks_angle = QtWidgets.QDoubleSpinBox(self.page_2) + self.sbJenks_angle.setMaximum(180.0) + self.sbJenks_angle.setProperty("value", 3.0) + self.sbJenks_angle.setObjectName("sbJenks_angle") + self.gridLayout_4.addWidget(self.sbJenks_angle, 1, 1, 1, 1) + self.stackOptions.addWidget(self.page_2) + self.page_13 = QtWidgets.QWidget() + self.page_13.setObjectName("page_13") + self.gridLayout_3 = QtWidgets.QGridLayout(self.page_13) + self.gridLayout_3.setObjectName("gridLayout_3") + self.label_13 = QtWidgets.QLabel(self.page_13) + self.label_13.setObjectName("label_13") + self.gridLayout_3.addWidget(self.label_13, 0, 0, 1, 1) + self.sbLang_thresh = QtWidgets.QDoubleSpinBox(self.page_13) + self.sbLang_thresh.setDecimals(4) + self.sbLang_thresh.setMinimum(0.0001) + self.sbLang_thresh.setMaximum(9999999.9999) + self.sbLang_thresh.setProperty("value", 0.0001) + self.sbLang_thresh.setObjectName("sbLang_thresh") + self.gridLayout_3.addWidget(self.sbLang_thresh, 0, 1, 1, 1) + self.label_19 = QtWidgets.QLabel(self.page_13) + self.label_19.setObjectName("label_19") + self.gridLayout_3.addWidget(self.label_19, 1, 0, 1, 1) + self.sbLang_LA = QtWidgets.QSpinBox(self.page_13) + self.sbLang_LA.setMinimum(1) + self.sbLang_LA.setMaximum(9999) + self.sbLang_LA.setProperty("value", 8) + self.sbLang_LA.setObjectName("sbLang_LA") + self.gridLayout_3.addWidget(self.sbLang_LA, 1, 1, 1, 1) + self.stackOptions.addWidget(self.page_13) + self.page_4 = QtWidgets.QWidget() + self.page_4.setObjectName("page_4") + self.gridLayout_6 = QtWidgets.QGridLayout(self.page_4) + self.gridLayout_6.setObjectName("gridLayout_6") + self.label_11 = QtWidgets.QLabel(self.page_4) + self.label_11.setObjectName("label_11") + self.gridLayout_6.addWidget(self.label_11, 0, 0, 1, 1) + self.sbRW_thresh = QtWidgets.QDoubleSpinBox(self.page_4) + self.sbRW_thresh.setDecimals(4) + self.sbRW_thresh.setMaximum(9999999.9999) + self.sbRW_thresh.setProperty("value", 0.0001) + self.sbRW_thresh.setObjectName("sbRW_thresh") + self.gridLayout_6.addWidget(self.sbRW_thresh, 0, 1, 1, 1) + self.stackOptions.addWidget(self.page_4) + self.page_14 = QtWidgets.QWidget() + self.page_14.setObjectName("page_14") + self.gridLayout_14 = QtWidgets.QGridLayout(self.page_14) + self.gridLayout_14.setObjectName("gridLayout_14") + self.label_20 = QtWidgets.QLabel(self.page_14) + self.label_20.setObjectName("label_20") + self.gridLayout_14.addWidget(self.label_20, 0, 0, 1, 1) + self.sbReduction_thresh = QtWidgets.QDoubleSpinBox(self.page_14) + self.sbReduction_thresh.setDecimals(4) + self.sbReduction_thresh.setMinimum(0.0001) + self.sbReduction_thresh.setMaximum(9999999.9999) + self.sbReduction_thresh.setObjectName("sbReduction_thresh") + self.gridLayout_14.addWidget(self.sbReduction_thresh, 0, 1, 1, 1) + self.stackOptions.addWidget(self.page_14) + self.page_15 = QtWidgets.QWidget() + self.page_15.setObjectName("page_15") + self.gridLayout_15 = QtWidgets.QGridLayout(self.page_15) + self.gridLayout_15.setObjectName("gridLayout_15") + self.label_21 = QtWidgets.QLabel(self.page_15) + self.label_21.setObjectName("label_21") + self.gridLayout_15.addWidget(self.label_21, 0, 0, 1, 1) + self.sbBoyle_LA = QtWidgets.QSpinBox(self.page_15) + self.sbBoyle_LA.setMinimum(2) + self.sbBoyle_LA.setMaximum(999) + self.sbBoyle_LA.setProperty("value", 7) + self.sbBoyle_LA.setObjectName("sbBoyle_LA") + self.gridLayout_15.addWidget(self.sbBoyle_LA, 0, 1, 1, 1) + self.stackOptions.addWidget(self.page_15) + self.page_16 = QtWidgets.QWidget() + self.page_16.setObjectName("page_16") + self.gridLayout_16 = QtWidgets.QGridLayout(self.page_16) + self.gridLayout_16.setObjectName("gridLayout_16") + self.label_22 = QtWidgets.QLabel(self.page_16) + self.label_22.setObjectName("label_22") + self.gridLayout_16.addWidget(self.label_22, 0, 0, 1, 1) + self.sbChaiken_level = QtWidgets.QSpinBox(self.page_16) + self.sbChaiken_level.setMinimum(1) + self.sbChaiken_level.setMaximum(99) + self.sbChaiken_level.setObjectName("sbChaiken_level") + self.gridLayout_16.addWidget(self.sbChaiken_level, 0, 1, 1, 1) + self.label_23 = QtWidgets.QLabel(self.page_16) + self.label_23.setObjectName("label_23") + self.gridLayout_16.addWidget(self.label_23, 1, 0, 1, 1) + self.sbChaiken_weight = QtWidgets.QDoubleSpinBox(self.page_16) + self.sbChaiken_weight.setMinimum(1.0) + self.sbChaiken_weight.setProperty("value", 3.0) + self.sbChaiken_weight.setObjectName("sbChaiken_weight") + self.gridLayout_16.addWidget(self.sbChaiken_weight, 1, 1, 1, 1) + self.stackOptions.addWidget(self.page_16) + self.page = QtWidgets.QWidget() + self.page.setObjectName("page") + self.gridLayout = QtWidgets.QGridLayout(self.page) + self.gridLayout.setObjectName("gridLayout") + self.label_2 = QtWidgets.QLabel(self.page) + self.label_2.setObjectName("label_2") + self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1) + self.label_4 = QtWidgets.QLabel(self.page) + self.label_4.setObjectName("label_4") + self.gridLayout.addWidget(self.label_4, 1, 0, 1, 1) + self.sbHermite_tightness = QtWidgets.QDoubleSpinBox(self.page) + self.sbHermite_tightness.setProperty("value", 0.5) + self.sbHermite_tightness.setObjectName("sbHermite_tightness") + self.gridLayout.addWidget(self.sbHermite_tightness, 1, 1, 1, 1) + self.sbHermite_steps = QtWidgets.QDoubleSpinBox(self.page) + self.sbHermite_steps.setDecimals(4) + self.sbHermite_steps.setMaximum(9999999.9999) + self.sbHermite_steps.setProperty("value", 0.0001) + self.sbHermite_steps.setObjectName("sbHermite_steps") + self.gridLayout.addWidget(self.sbHermite_steps, 0, 1, 1, 1) + self.stackOptions.addWidget(self.page) + self.page_17 = QtWidgets.QWidget() + self.page_17.setObjectName("page_17") + self.gridLayout_17 = QtWidgets.QGridLayout(self.page_17) + self.gridLayout_17.setObjectName("gridLayout_17") + self.label_24 = QtWidgets.QLabel(self.page_17) + self.label_24.setObjectName("label_24") + self.gridLayout_17.addWidget(self.label_24, 0, 0, 1, 1) + self.sbDist_slide = QtWidgets.QDoubleSpinBox(self.page_17) + self.sbDist_slide.setSingleStep(0.1) + self.sbDist_slide.setProperty("value", 0.5) + self.sbDist_slide.setObjectName("sbDist_slide") + self.gridLayout_17.addWidget(self.sbDist_slide, 0, 1, 1, 1) + self.label_25 = QtWidgets.QLabel(self.page_17) + self.label_25.setObjectName("label_25") + self.gridLayout_17.addWidget(self.label_25, 1, 0, 1, 1) + self.sbDist_LA = QtWidgets.QSpinBox(self.page_17) + self.sbDist_LA.setMinimum(3) + self.sbDist_LA.setMaximum(999) + self.sbDist_LA.setSingleStep(2) + self.sbDist_LA.setProperty("value", 7) + self.sbDist_LA.setObjectName("sbDist_LA") + self.gridLayout_17.addWidget(self.sbDist_LA, 1, 1, 1, 1) + self.stackOptions.addWidget(self.page_17) + self.page_18 = QtWidgets.QWidget() + self.page_18.setObjectName("page_18") + self.gridLayout_18 = QtWidgets.QGridLayout(self.page_18) + self.gridLayout_18.setObjectName("gridLayout_18") + self.label_26 = QtWidgets.QLabel(self.page_18) + self.label_26.setObjectName("label_26") + self.gridLayout_18.addWidget(self.label_26, 0, 0, 1, 1) + self.sbSlide_slide = QtWidgets.QDoubleSpinBox(self.page_18) + self.sbSlide_slide.setSingleStep(0.1) + self.sbSlide_slide.setProperty("value", 0.5) + self.sbSlide_slide.setObjectName("sbSlide_slide") + self.gridLayout_18.addWidget(self.sbSlide_slide, 0, 1, 1, 1) + self.label_27 = QtWidgets.QLabel(self.page_18) + self.label_27.setObjectName("label_27") + self.gridLayout_18.addWidget(self.label_27, 1, 0, 1, 1) + self.sbSlide_LA = QtWidgets.QSpinBox(self.page_18) + self.sbSlide_LA.setMinimum(3) + self.sbSlide_LA.setMaximum(999) + self.sbSlide_LA.setSingleStep(2) + self.sbSlide_LA.setProperty("value", 7) + self.sbSlide_LA.setObjectName("sbSlide_LA") + self.gridLayout_18.addWidget(self.sbSlide_LA, 1, 1, 1, 1) + self.stackOptions.addWidget(self.page_18) + self.page_3 = QtWidgets.QWidget() + self.page_3.setObjectName("page_3") + self.gridLayout_5 = QtWidgets.QGridLayout(self.page_3) + self.gridLayout_5.setObjectName("gridLayout_5") + self.label_9 = QtWidgets.QLabel(self.page_3) + self.label_9.setObjectName("label_9") + self.gridLayout_5.addWidget(self.label_9, 0, 0, 1, 1) + self.sbSnakes_alpha = QtWidgets.QDoubleSpinBox(self.page_3) + self.sbSnakes_alpha.setMaximum(9999.99) + self.sbSnakes_alpha.setProperty("value", 1.0) + self.sbSnakes_alpha.setObjectName("sbSnakes_alpha") + self.gridLayout_5.addWidget(self.sbSnakes_alpha, 0, 1, 1, 1) + self.label_10 = QtWidgets.QLabel(self.page_3) + self.label_10.setObjectName("label_10") + self.gridLayout_5.addWidget(self.label_10, 1, 0, 1, 1) + self.sbSnakes_beta = QtWidgets.QDoubleSpinBox(self.page_3) + self.sbSnakes_beta.setMaximum(9999.99) + self.sbSnakes_beta.setProperty("value", 0.5) + self.sbSnakes_beta.setObjectName("sbSnakes_beta") + self.gridLayout_5.addWidget(self.sbSnakes_beta, 1, 1, 1, 1) + self.stackOptions.addWidget(self.page_3) + self.gridLayout_2.addWidget(self.stackOptions, 1, 0, 1, 2) + self.gridLayout_19.addWidget(self.groupBox, 2, 0, 1, 2) + self.eOutput = QtWidgets.QLineEdit(self.page_6) + self.eOutput.setEnabled(False) + self.eOutput.setObjectName("eOutput") + self.gridLayout_19.addWidget(self.eOutput, 4, 0, 1, 1) + self.bBrowse = QtWidgets.QPushButton(self.page_6) + self.bBrowse.setEnabled(False) + self.bBrowse.setObjectName("bBrowse") + self.gridLayout_19.addWidget(self.bBrowse, 4, 1, 1, 1) + self.cbOutFile = QtWidgets.QCheckBox(self.page_6) + self.cbOutFile.setObjectName("cbOutFile") + self.gridLayout_19.addWidget(self.cbOutFile, 3, 0, 1, 1) + self.stackBatch.addWidget(self.page_6) + self.page_10 = QtWidgets.QWidget() + self.page_10.setObjectName("page_10") + self.gridLayout_21 = QtWidgets.QGridLayout(self.page_10) + self.gridLayout_21.setObjectName("gridLayout_21") + self.lstLayers = QtWidgets.QListWidget(self.page_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.lstLayers.sizePolicy().hasHeightForWidth()) + self.lstLayers.setSizePolicy(sizePolicy) + self.lstLayers.setObjectName("lstLayers") + self.gridLayout_21.addWidget(self.lstLayers, 1, 0, 1, 1) + self.tblBatchAlg = QtWidgets.QTableWidget(self.page_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.tblBatchAlg.sizePolicy().hasHeightForWidth()) + self.tblBatchAlg.setSizePolicy(sizePolicy) + self.tblBatchAlg.setObjectName("tblBatchAlg") + self.tblBatchAlg.setColumnCount(3) + self.tblBatchAlg.setRowCount(0) + item = QtWidgets.QTableWidgetItem() + self.tblBatchAlg.setHorizontalHeaderItem(0, item) + item = QtWidgets.QTableWidgetItem() + self.tblBatchAlg.setHorizontalHeaderItem(1, item) + item = QtWidgets.QTableWidgetItem() + self.tblBatchAlg.setHorizontalHeaderItem(2, item) + self.gridLayout_21.addWidget(self.tblBatchAlg, 3, 0, 3, 1) + self.bAddAlg = QtWidgets.QPushButton(self.page_10) + self.bAddAlg.setObjectName("bAddAlg") + self.gridLayout_21.addWidget(self.bAddAlg, 3, 1, 1, 1) + self.bDelAlg = QtWidgets.QPushButton(self.page_10) + self.bDelAlg.setObjectName("bDelAlg") + self.gridLayout_21.addWidget(self.bDelAlg, 4, 1, 1, 1) + self.bEditAlg = QtWidgets.QPushButton(self.page_10) + self.bEditAlg.setObjectName("bEditAlg") + self.gridLayout_21.addWidget(self.bEditAlg, 5, 1, 1, 1) + self.eDir = QtWidgets.QLineEdit(self.page_10) + self.eDir.setEnabled(False) + self.eDir.setObjectName("eDir") + self.gridLayout_21.addWidget(self.eDir, 7, 0, 1, 1) + self.bBrowseDir = QtWidgets.QPushButton(self.page_10) + self.bBrowseDir.setEnabled(False) + self.bBrowseDir.setObjectName("bBrowseDir") + self.gridLayout_21.addWidget(self.bBrowseDir, 7, 1, 1, 1) + self.cbOutDir = QtWidgets.QCheckBox(self.page_10) + self.cbOutDir.setObjectName("cbOutDir") + self.gridLayout_21.addWidget(self.cbOutDir, 6, 0, 1, 1) + self.label_5 = QtWidgets.QLabel(self.page_10) + self.label_5.setObjectName("label_5") + self.gridLayout_21.addWidget(self.label_5, 2, 0, 1, 1) + self.label_6 = QtWidgets.QLabel(self.page_10) + self.label_6.setObjectName("label_6") + self.gridLayout_21.addWidget(self.label_6, 0, 0, 1, 1) + self.stackBatch.addWidget(self.page_10) + self.gridLayout_20.addWidget(self.stackBatch, 1, 0, 1, 3) + self.label.setBuddy(self.cbInput) + self.label_12.setBuddy(self.sbRemove_thresh) + + self.retranslateUi(generalizer) + self.stackBatch.setCurrentIndex(0) + self.cbAlgorithm.setCurrentIndex(1) + self.stackOptions.setCurrentIndex(0) + self.bCancel.clicked.connect(generalizer.close) + QtCore.QMetaObject.connectSlotsByName(generalizer) + generalizer.setTabOrder(self.cbBatch, self.cbInput) + generalizer.setTabOrder(self.cbInput, self.cbAlgorithm) + generalizer.setTabOrder(self.cbAlgorithm, self.sbRemove_thresh) + generalizer.setTabOrder(self.sbRemove_thresh, self.cbOutFile) + generalizer.setTabOrder(self.cbOutFile, self.eOutput) + generalizer.setTabOrder(self.eOutput, self.bBrowse) + generalizer.setTabOrder(self.bBrowse, self.bOk) + generalizer.setTabOrder(self.bOk, self.bCancel) + generalizer.setTabOrder(self.bCancel, self.sbLang_LA) + generalizer.setTabOrder(self.sbLang_LA, self.sbReduction_thresh) + generalizer.setTabOrder(self.sbReduction_thresh, self.sbBoyle_LA) + generalizer.setTabOrder(self.sbBoyle_LA, self.sbChaiken_level) + generalizer.setTabOrder(self.sbChaiken_level, self.sbChaiken_weight) + generalizer.setTabOrder(self.sbChaiken_weight, self.sbHermite_steps) + generalizer.setTabOrder(self.sbHermite_steps, self.sbHermite_tightness) + generalizer.setTabOrder(self.sbHermite_tightness, self.sbDist_slide) + generalizer.setTabOrder(self.sbDist_slide, self.sbDist_LA) + generalizer.setTabOrder(self.sbDist_LA, self.sbSlide_slide) + generalizer.setTabOrder(self.sbSlide_slide, self.sbSlide_LA) + generalizer.setTabOrder(self.sbSlide_LA, self.bHelp) + generalizer.setTabOrder(self.bHelp, self.sbLang_thresh) + generalizer.setTabOrder(self.sbLang_thresh, self.sbDP_thresh) + generalizer.setTabOrder(self.sbDP_thresh, self.lstLayers) + generalizer.setTabOrder(self.lstLayers, self.tblBatchAlg) + generalizer.setTabOrder(self.tblBatchAlg, self.bAddAlg) + generalizer.setTabOrder(self.bAddAlg, self.bDelAlg) + generalizer.setTabOrder(self.bDelAlg, self.bEditAlg) + generalizer.setTabOrder(self.bEditAlg, self.eDir) + generalizer.setTabOrder(self.eDir, self.bBrowseDir) + generalizer.setTabOrder(self.bBrowseDir, self.cbOutDir) + + def retranslateUi(self, generalizer): + _translate = QtCore.QCoreApplication.translate + generalizer.setWindowTitle(_translate("generalizer", "Generalizer")) + self.cbBatch.setText(_translate("generalizer", "Batch mode")) + self.bHelp.setText(_translate("generalizer", "?")) + self.bOk.setText(_translate("generalizer", "OK")) + self.bCancel.setText(_translate("generalizer", "Close")) + self.label.setText(_translate("generalizer", "Input line layer:")) + self.groupBox.setTitle(_translate("generalizer", "Options")) + self.label_3.setText(_translate("generalizer", "Alghoritm:")) + self.cbAlgorithm.setItemText(0, _translate("generalizer", "-----Generalizing-----")) + self.cbAlgorithm.setItemText(1, _translate("generalizer", "Remove small objects")) + self.cbAlgorithm.setItemText(2, _translate("generalizer", "-----Simplifying-----")) + self.cbAlgorithm.setItemText(3, _translate("generalizer", "Douglas-Peucker Algorithm")) + self.cbAlgorithm.setItemText(4, _translate("generalizer", "Jenk\'s Algorithm")) + self.cbAlgorithm.setItemText(5, _translate("generalizer", "Lang Algorithm")) + self.cbAlgorithm.setItemText(6, _translate("generalizer", "Reumann-Witkam Algorithm")) + self.cbAlgorithm.setItemText(7, _translate("generalizer", "Vertex Reduction")) + self.cbAlgorithm.setItemText(8, _translate("generalizer", "-----Smoothing-----")) + self.cbAlgorithm.setItemText(9, _translate("generalizer", "Boyle\'s Forward-Looking Algorithm")) + self.cbAlgorithm.setItemText(10, _translate("generalizer", "Chaiken\'s Algorithm")) + self.cbAlgorithm.setItemText(11, _translate("generalizer", "Hermite Spline Interpolation")) + self.cbAlgorithm.setItemText(12, _translate("generalizer", "McMaster\'s Distance-Weighting Algorithm")) + self.cbAlgorithm.setItemText(13, _translate("generalizer", "McMaster\'s Sliding Averaging Algorithm")) + self.cbAlgorithm.setItemText(14, _translate("generalizer", "Snakes Algorithm")) + self.label_12.setText(_translate("generalizer", "Threshold:")) + self.label_18.setText(_translate("generalizer", "Threshold:")) + self.label_7.setText(_translate("generalizer", "Threshold:")) + self.label_8.setText(_translate("generalizer", "Angle threshold:")) + self.label_13.setText(_translate("generalizer", "Threshold:")) + self.label_19.setText(_translate("generalizer", "Looka ahead:")) + self.label_11.setText(_translate("generalizer", "Threshold:")) + self.label_20.setText(_translate("generalizer", "Threshold:")) + self.label_21.setText(_translate("generalizer", "Look ahead:")) + self.label_22.setText(_translate("generalizer", "Level:")) + self.label_23.setText(_translate("generalizer", "Weight:")) + self.label_2.setText(_translate("generalizer", "Threshold:")) + self.label_4.setText(_translate("generalizer", "Thightness:")) + self.label_24.setText(_translate("generalizer", "Slide:")) + self.label_25.setText(_translate("generalizer", "Look ahead:")) + self.label_26.setText(_translate("generalizer", "Slide:")) + self.label_27.setText(_translate("generalizer", "Look ahead:")) + self.label_9.setText(_translate("generalizer", "Alpha:")) + self.label_10.setText(_translate("generalizer", "Beta:")) + self.bBrowse.setText(_translate("generalizer", "Browse")) + self.cbOutFile.setText(_translate("generalizer", "Save output layer")) + item = self.tblBatchAlg.horizontalHeaderItem(0) + item.setText(_translate("generalizer", "Algorithm")) + item = self.tblBatchAlg.horizontalHeaderItem(1) + item.setText(_translate("generalizer", "Parameter 1")) + item = self.tblBatchAlg.horizontalHeaderItem(2) + item.setText(_translate("generalizer", "Parameter 2")) + self.bAddAlg.setText(_translate("generalizer", "Add")) + self.bDelAlg.setText(_translate("generalizer", "Delete")) + self.bEditAlg.setText(_translate("generalizer", "Edit")) + self.bBrowseDir.setText(_translate("generalizer", "Browse")) + self.cbOutDir.setText(_translate("generalizer", "Save output layer(s) to folder")) + self.label_5.setText(_translate("generalizer", "Algorithm(s)")) + self.label_6.setText(_translate("generalizer", "Choose layer(s)")) From cf4c775bb072c8ffb5592d41810b468cfdcec83d Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Mon, 9 Nov 2020 17:15:47 +0400 Subject: [PATCH 34/43] Move plugin to his self toolbar 0.9 (09.11.2020) - Move plugin to his self toolbar --- CHANGELOG | 3 + generalizer.py | 161 +++++++++++++++++++++++++++++++++++++++++++++---- metadata.txt | 4 +- resources.py | 16 ++--- resources.qrc | 2 +- 5 files changed, 164 insertions(+), 22 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 608e2e1..9108364 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +0.9 (09.11.2020) +- Move plugin to his self toolbar + 0.8 (23.05.2020) - fix import resources diff --git a/generalizer.py b/generalizer.py index 6235c3f..e371e3e 100644 --- a/generalizer.py +++ b/generalizer.py @@ -34,28 +34,165 @@ from .resources import * # Import the code for the dialog from .generalizerdialog import generalizerDialog, getLayersNames +import os.path -class generalizer(object): + +class generalizer: def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface + + self.canvas = iface.mapCanvas() + + # initialize plugin directory + self.plugin_dir = os.path.dirname(__file__) + + # Declare instance attributes + self.actions = [] + self.menu = self.tr(u'&Generalizer') + # TODO: We are going to let the user set this up in a future iteration + self.toolbar = self.iface.addToolBar(u'Generalizer') + self.toolbar.setObjectName(u'Generalizer') + + #print "** INITIALIZING Generalizer" + + self.pluginIsActive = False + self.dockwidget = None + + self.output_layer = None + + # noinspection PyMethodMayBeStatic + def tr(self, message): + """Get the translation for a string using Qt translation API. + + We implement this ourselves since we do not inherit QObject. + + :param message: String for translation. + :type message: str, QString + + :returns: Translated version of message. + :rtype: QString + """ + # noinspection PyTypeChecker,PyArgumentList,PyCallByClass + return QCoreApplication.translate('Generalizer', message) + + def add_action( + self, + icon_path, + text, + callback, + enabled_flag=True, + add_to_menu=True, + add_to_toolbar=True, + status_tip=None, + whats_this=None, + parent=None): + """Add a toolbar icon to the toolbar. + + :param icon_path: Path to the icon for this action. Can be a resource + path (e.g. ':/plugins/foo/bar.png') or a normal file system path. + :type icon_path: str + + :param text: Text that should be shown in menu items for this action. + :type text: str + + :param callback: Function to be called when the action is triggered. + :type callback: function + + :param enabled_flag: A flag indicating if the action should be enabled + by default. Defaults to True. + :type enabled_flag: bool + + :param add_to_menu: Flag indicating whether the action should also + be added to the menu. Defaults to True. + :type add_to_menu: bool + + :param add_to_toolbar: Flag indicating whether the action should also + be added to the toolbar. Defaults to True. + :type add_to_toolbar: bool + + :param status_tip: Optional text to show in a popup when mouse pointer + hovers over the action. + :type status_tip: str + + :param parent: Parent widget for the new action. Defaults None. + :type parent: QWidget + + :param whats_this: Optional text to show in the status bar when the + mouse pointer hovers over the action. + + :returns: The action that was created. Note that the action is also + added to self.actions list. + :rtype: QAction + """ + + icon = QIcon(icon_path) + text = "Generalizer" + action = QAction(icon, text, parent) + action.triggered.connect(callback) + action.setEnabled(enabled_flag) + + if status_tip is not None: + action.setStatusTip(status_tip) + + if whats_this is not None: + action.setWhatsThis(whats_this) + + if add_to_toolbar: + self.toolbar.addAction(action) + + if add_to_menu: + self.iface.addPluginToVectorMenu( + self.menu, + action) + + self.actions.append(action) + + return action + def initGui(self): - # Create action that will start plugin configuration - self.action = QAction(QIcon(":/plugins/generalizer/icon.png"), \ - "Generalizer", self.iface.mainWindow()) - # connect the action to the run method - self.action.triggered.connect( self.run ) + """Create the menu entries and toolbar icons inside the QGIS GUI.""" + + icon_path = ':/plugins/Generalizer3/icon.png' + self.add_action( + icon_path, + text=self.tr(u''), + callback=self.run, + parent=self.iface.mainWindow()) + + #-------------------------------------------------------------------------- + + def onClosePlugin(self): + """Cleanup necessary items here when plugin dockwidget is closed""" + + #print "** CLOSING Generalizer" + + # disconnects + self.dockwidget.closingPlugin.disconnect(self.onClosePlugin) + + # remove this statement if dockwidget is to remain + # for reuse if plugin is reopened + # Commented next statement since it causes QGIS crashe + # when closing the docked window: + # self.dockwidget = None + + self.pluginIsActive = False - # Add toolbar button and menu item - self.iface.addToolBarIcon(self.action) - self.iface.addPluginToMenu("&Generalizer", self.action) def unload(self): - # Remove the plugin menu item and icon - self.iface.removePluginMenu("&Generalizer",self.action) - self.iface.removeToolBarIcon(self.action) + """Removes the plugin menu item and icon from QGIS GUI.""" + + #print "** UNLOAD Generalizer" + + for action in self.actions: + self.iface.removePluginVectorMenu( + self.tr(u'&Generalizer'), + action) + self.iface.removeToolBarIcon(action) + # remove the toolbar + del self.toolbar # run method that performs all the real work def run(self): diff --git a/metadata.txt b/metadata.txt index cd300b9..a9531c2 100644 --- a/metadata.txt +++ b/metadata.txt @@ -35,12 +35,14 @@ icon=icon.png tags=line,vector,smooth,simplify # experimental flag -experimental=True +experimental=False # deprecated flag (applies to the whole plugin, not just a single version deprecated=False changelog= + 0.9 (09.11.2020) + - Move plugin to his self toolbar 0.8 (23.05.2020) - fix import resources 0.7 (17.05.2020) diff --git a/resources.py b/resources.py index ffa3fb2..2d7ba17 100644 --- a/resources.py +++ b/resources.py @@ -2,7 +2,7 @@ # Resource object code # -# Created by: The Resource Compiler for PyQt5 (Qt v5.13.1) +# Created by: The Resource Compiler for PyQt5 (Qt v5.15.1) # # WARNING! All changes made in this file will be lost! @@ -399,10 +399,10 @@ \x07\x3b\xe0\xb3\ \x00\x70\ \x00\x6c\x00\x75\x00\x67\x00\x69\x00\x6e\x00\x73\ -\x00\x0b\ -\x08\xd8\x99\x42\ -\x00\x67\ -\x00\x65\x00\x6e\x00\x65\x00\x72\x00\x61\x00\x6c\x00\x69\x00\x7a\x00\x65\x00\x72\ +\x00\x0c\ +\x01\x89\x95\x73\ +\x00\x47\ +\x00\x65\x00\x6e\x00\x65\x00\x72\x00\x61\x00\x6c\x00\x69\x00\x7a\x00\x65\x00\x72\x00\x33\ \x00\x08\ \x0a\x61\x5a\xa7\ \x00\x69\ @@ -413,7 +413,7 @@ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ \x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\ -\x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x00\x32\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ " qt_resource_struct_v2 = b"\ @@ -423,8 +423,8 @@ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x6e\x54\x90\x86\x20\ +\x00\x00\x00\x32\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01\x73\x87\x86\xe3\x8a\ " qt_version = [int(v) for v in QtCore.qVersion().split('.')] diff --git a/resources.qrc b/resources.qrc index dd94b82..adf8cb0 100644 --- a/resources.qrc +++ b/resources.qrc @@ -1,5 +1,5 @@ - + icon.png From ddd0ccbaa74b4997fe72f84babdc0daeb199b5ee Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Mon, 9 Nov 2020 13:27:14 +0000 Subject: [PATCH 35/43] Update metadata.txt --- metadata.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata.txt b/metadata.txt index a9531c2..8827fa8 100644 --- a/metadata.txt +++ b/metadata.txt @@ -20,7 +20,7 @@ about=Plugin to Generalize, Simplify or Smooth lines in QGIS Distance Weighting McMaster's Sliding Averaging Algorithm Snakes Algorithm : Slowest smoothing algorithm -version=0.8 +version=0.9 author=Piotr Pociask, Matthew Petroff, Sylvain POULAIN From 5716f1188d0df43f6c6676892233502b25273c4d Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Mon, 9 Nov 2020 13:51:24 +0000 Subject: [PATCH 36/43] Update generalizer.py --- generalizer.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/generalizer.py b/generalizer.py index e371e3e..083ad9a 100644 --- a/generalizer.py +++ b/generalizer.py @@ -162,24 +162,6 @@ def initGui(self): callback=self.run, parent=self.iface.mainWindow()) - #-------------------------------------------------------------------------- - - def onClosePlugin(self): - """Cleanup necessary items here when plugin dockwidget is closed""" - - #print "** CLOSING Generalizer" - - # disconnects - self.dockwidget.closingPlugin.disconnect(self.onClosePlugin) - - # remove this statement if dockwidget is to remain - # for reuse if plugin is reopened - # Commented next statement since it causes QGIS crashe - # when closing the docked window: - # self.dockwidget = None - - self.pluginIsActive = False - def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" From 1acb04c3ff70408353b6f73e6a0dbd8ffd7f7d5b Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Tue, 17 Nov 2020 17:26:34 +0000 Subject: [PATCH 37/43] Fix https://github.com/giscan/Generalizer/issues/7 Fix https://github.com/giscan/Generalizer/issues/7 Multipart fix --- generalizerdialog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generalizerdialog.py b/generalizerdialog.py index 928247e..91f1cc0 100644 --- a/generalizerdialog.py +++ b/generalizerdialog.py @@ -515,13 +515,13 @@ def doGeneralize(self, iLayerName, iLayer, oPath, func, arguments): p = func(ls, **arguments) l2 = [] for n in range(p.n_points): - l2.append(QgsPoint(p.x[n], p.y[n])) + l2.append(QgsPointXY(p.x[n], p.y[n])) if len(l2) > 1: l.append(l2) if len(l) > 1: fet.setGeometry(QgsGeometry.fromMultiPolylineXY(l)) elif len(l) == 1: #jesli z obiektu wieloczesciowego zostaje tylko jedna linia (np. przy usuwaniu malych obiektow) - fet.setGeometry(QgsGeometry.fromPolyline(l[0])) + fet.setGeometry(QgsGeometry.fromPolylineXY(l[0])) else: ls = geom.asPolyline() p = func(ls, **arguments) From 7cb62e68e1936064bd7d535e8d04c3ee38ed8657 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Tue, 17 Nov 2020 17:30:52 +0000 Subject: [PATCH 38/43] Update generalizerdialog.py --- generalizerdialog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generalizerdialog.py b/generalizerdialog.py index 91f1cc0..b64c4aa 100644 --- a/generalizerdialog.py +++ b/generalizerdialog.py @@ -498,10 +498,10 @@ def doGeneralize(self, iLayerName, iLayer, oPath, func, arguments): # mLayer = QgsVectorLayer('MultiLineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') if iLayer.wkbType() == QgsWkbTypes.LineString: #mLayer = QgsVectorLayer('LineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') - mLayer = QgsVectorLayer('LineString?crs=' + crs.authid(), iLayerName + '_memory', 'memory') + mLayer = QgsVectorLayer("LineString?crs=" + crs.authid(), iLayerName + "_memory", "memory") else: #mLayer = QgsVectorLayer('MultiLineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') - mLayer = QgsVectorLayer('MultiLineString?crs=' + crs.authid(), iLayerName + '_memory', 'memory') + mLayer = QgsVectorLayer("MultiLineString?crs=" + crs.authid(), iLayerName + "_memory", "memory") mProvider = mLayer.dataProvider() mProvider.addAttributes( [key for key in fields] ) From 2cf5d4fea988f7782073330220f355aa87529a54 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Wed, 18 Nov 2020 05:44:57 +0000 Subject: [PATCH 39/43] Update generalizerdialog.py --- generalizerdialog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generalizerdialog.py b/generalizerdialog.py index b64c4aa..b3ad45d 100644 --- a/generalizerdialog.py +++ b/generalizerdialog.py @@ -498,10 +498,10 @@ def doGeneralize(self, iLayerName, iLayer, oPath, func, arguments): # mLayer = QgsVectorLayer('MultiLineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') if iLayer.wkbType() == QgsWkbTypes.LineString: #mLayer = QgsVectorLayer('LineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') - mLayer = QgsVectorLayer("LineString?crs=" + crs.authid(), iLayerName + "_memory", "memory") + mLayer = QgsVectorLayer("LineString?crs=" + QgsProject.instance().crs().authid(), iLayerName + "_memory", "memory") else: #mLayer = QgsVectorLayer('MultiLineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') - mLayer = QgsVectorLayer("MultiLineString?crs=" + crs.authid(), iLayerName + "_memory", "memory") + mLayer = QgsVectorLayer("MultiLineString?crs=" + QgsProject.instance().crs().authid(), iLayerName + "_memory", "memory") mProvider = mLayer.dataProvider() mProvider.addAttributes( [key for key in fields] ) From 37c4782b94fa6e52d9b908f0379e154535e6f7d1 Mon Sep 17 00:00:00 2001 From: kikislater Date: Tue, 12 May 2026 21:49:01 +0400 Subject: [PATCH 40/43] Add compatibility with QGIS4 --- CHANGELOG | 7 + __init__.py | 14 +- dialogs.py | 9 +- generalizer.py | 34 +- generalizerdialog.py | 995 +++++++++++++------------------------------ metadata.txt | 12 +- points.py | 18 +- resources.py | 5 +- simplify.py | 5 +- smooth.py | 10 +- ui_generalizer.py | 155 ++++--- ui_generalizer.ui | 12 +- 12 files changed, 467 insertions(+), 809 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 9108364..7daf450 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +2.0 (03.04/2026) +- Compatibility to Qgis 4 & Qt6 +- Push algorithm to processing +- Ui launch processing algs +1.0 (18.11.2020) +- Fix unkown projection when new layer is created +- Multipart lines supported 0.9 (09.11.2020) - Move plugin to his self toolbar diff --git a/__init__.py b/__init__.py index fcf688b..133adc7 100644 --- a/__init__.py +++ b/__init__.py @@ -2,11 +2,12 @@ /*************************************************************************** generalizer A QGIS plugin -"Lines generalization and smoothing (partially based on v.generalize GRASS module)" +"Lines generalization and smoothing (inpired from v.generalize GRASS module)" ------------------- begin : 2011-08-17 copyright : (C) 2011 by Piotr Pociask - email : ppociask (at) o2 pl + (C) 2019 - 2026 by Sylvain POULAIN + email : sylvain dot poulain (at) giscan dot com ***************************************************************************/ /*************************************************************************** @@ -19,8 +20,13 @@ ***************************************************************************/ This script initializes the plugin, making it known to QGIS. """ -from __future__ import absolute_import + + def classFactory(iface): - # load generalizer class from file generalizer + """Load generalizer class from file generalizer. + + :param iface: A QGIS interface instance. + :type iface: QgsInterface + """ from .generalizer import generalizer return generalizer(iface) diff --git a/dialogs.py b/dialogs.py index 5f4f0b9..4afc5ce 100644 --- a/dialogs.py +++ b/dialogs.py @@ -1,7 +1,6 @@ -from builtins import str -from PyQt5.QtGui import * -from PyQt5.QtCore import * -from PyQt5.QtWidgets import * +from qgis.PyQt.QtCore import * +from qgis.PyQt.QtGui import * +from qgis.PyQt.QtWidgets import * from os.path import splitext, dirname @@ -29,5 +28,5 @@ def openDir(parent): key = '/UI/lastShapefileDir' outDir = settings.value(key) - outPath = QFileDialog.getExistingDirectory(parent, 'Generalizer', outDir)#, QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) + outPath = QFileDialog.getExistingDirectory(parent, 'Generalizer', outDir) return outPath diff --git a/generalizer.py b/generalizer.py index 083ad9a..ebd8ac2 100644 --- a/generalizer.py +++ b/generalizer.py @@ -2,8 +2,7 @@ /*************************************************************************** generalizer A QGIS plugin - Lines generalization (smooth and simplify) based on v.generalize GRASS module - ------------------- +Lines generalization and smoothing (inpired from v.generalize GRASS module) ------------------- begin : 2011-08-17 copyright : (C) 2011 by Piotr Pociask email : ppociask (at) o2 pl @@ -20,20 +19,20 @@ * * ***************************************************************************/ """ -from __future__ import absolute_import -# Import the PyQt and QGIS libraries -from builtins import object -from PyQt5.QtCore import * -from PyQt5.QtGui import * -from PyQt5.QtWidgets import QAction, QMessageBox +# Import the PyQt and QGIS libraries +from builtins import object +from qgis.PyQt.QtCore import * +from qgis.PyQt.QtGui import * +from qgis.PyQt.QtWidgets import QAction, QMessageBox from qgis.core import * # Initialize Qt resources from file resources.py from .resources import * # Import the code for the dialog from .generalizerdialog import generalizerDialog, getLayersNames +from .generalizer_provider import GeneralizerProvider import os.path @@ -59,8 +58,8 @@ def __init__(self, iface): self.pluginIsActive = False self.dockwidget = None - self.output_layer = None + self.provider = None # noinspection PyMethodMayBeStatic def tr(self, message): @@ -154,7 +153,7 @@ def add_action( def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" - + from qgis.core import QgsApplication icon_path = ':/plugins/Generalizer3/icon.png' self.add_action( icon_path, @@ -162,19 +161,21 @@ def initGui(self): callback=self.run, parent=self.iface.mainWindow()) + self.provider = GeneralizerProvider() + QgsApplication.processingRegistry().addProvider(self.provider) + def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" - - #print "** UNLOAD Generalizer" - + from qgis.core import QgsApplication for action in self.actions: self.iface.removePluginVectorMenu( self.tr(u'&Generalizer'), action) self.iface.removeToolBarIcon(action) - # remove the toolbar del self.toolbar + if self.provider: + QgsApplication.processingRegistry().removeProvider(self.provider) # run method that performs all the real work def run(self): @@ -187,7 +188,10 @@ def run(self): dlg = generalizerDialog(self.iface) # show the dialog dlg.show() - result = dlg.exec_() + try: + result = dlg.exec() + except: + result = dlg.exec_() # See if OK was pressed if result == 1: # do something useful (delete the line containing pass and diff --git a/generalizerdialog.py b/generalizerdialog.py index b3ad45d..33925d9 100644 --- a/generalizerdialog.py +++ b/generalizerdialog.py @@ -1,64 +1,94 @@ """ /*************************************************************************** - generalizerDialog - A QGIS plugin - Lines generalization (smooth and simplify) based on v.generalize GRASS module - ------------------- + generalizerDialog — QGIS 4 +Lines generalization and smoothing (inpired from v.generalize GRASS module) begin : 2011-08-17 copyright : (C) 2011 by Piotr Pociask - email : ppociask (at) o2 pl - adapted to QGIS 3 : 2019-11-10 by Sylvain POULAIN - email : sylvain.poulain (at) giscan.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. * - * * + adapted to QGIS 3 & 4: 2019 - 2026 by Sylvain POULAIN + email : sylvain dot poulain (at) giscan dotcom ***************************************************************************/ """ -from __future__ import absolute_import - -from builtins import str -from builtins import range -from PyQt5.QtCore import * -from PyQt5.QtGui import * +from qgis.PyQt.QtCore import Qt +from qgis.PyQt.QtWidgets import (QDialog, QMessageBox, QInputDialog, + QDoubleSpinBox, QSpinBox, QTableWidgetItem) +from qgis.core import QgsProject, QgsMapLayer, QgsMessageLog, Qgis -from PyQt5.QtWidgets import QAction, QDialog, QMessageBox -from qgis.utils import Qgis - -from qgis.core import * -from qgis.gui import * - -from . import smooth, simplify, points -from .dialogs import * +import processing +from .dialogs import saveDialog, openDir from .ui_generalizer import Ui_generalizer -#global variable with short to full algorithm names -algorithm = {'remove':'Remove small objects', - 'DP':'Douglas-Peucker Algorithm', - 'lang':'Lang Algorithm', - 'reduction':'Vertex Reduction', - 'boyle':'Boyle\'s Forward-Looking Algorithm', - 'chaiken':'Chaiken\'s Algorithm', - 'hermite':'Hermite Spline Interpolation', - 'distance':'McMaster\'s Distance-Weighting Algorithm', - 'sliding':'McMaster\'s Sliding Averaging Algorithm', - 'snakes':'Snakes Algorithm', - 'jenks':'Jenk\'s Algorithm', - 'RW':'Reumann-Witkam Algorithm' - } - -crs = QgsProject.instance().crs() +try: + UNCHECKED = Qt.CheckState.Unchecked + CHECKED = Qt.CheckState.Checked +except AttributeError: + UNCHECKED = Qt.Unchecked + CHECKED = Qt.Checked + +ALGO_ID = { + 'Remove small objects': 'generalizer3:remove_small_objects', + 'Douglas-Peucker Algorithm': 'generalizer3:douglas_peucker', + "Jenk's Algorithm": 'generalizer3:jenks', + 'Lang Algorithm': 'generalizer3:lang', + 'Reumann-Witkam Algorithm': 'generalizer3:reumann_witkam', + 'Vertex Reduction': 'generalizer3:vertex_reduction', + "Boyle's Forward-Looking Algorithm": 'generalizer3:boyle', + "Chaiken's Algorithm": 'generalizer3:chaiken', + 'Hermite Spline Interpolation': 'generalizer3:hermite', + "McMaster's Distance-Weighting Algorithm": 'generalizer3:distance_weighting', + "McMaster's Sliding Averaging Algorithm": 'generalizer3:sliding_averaging', + 'Snakes Algorithm': 'generalizer3:snakes', +} + +def _params_from_ui(alg_name, ui): + """Builds the Processing parameters from the dialog's widgets.""" + mapping = { + 'Remove small objects': lambda: {'THRESHOLD': ui.sbRemove_thresh.value()}, + 'Douglas-Peucker Algorithm': lambda: {'THRESHOLD': ui.sbDP_thresh.value()}, + "Jenk's Algorithm": lambda: {'THRESHOLD': ui.sbJenks_thresh.value(), + 'ANGLE_THRESHOLD': ui.sbJenks_angle.value()}, + 'Lang Algorithm': lambda: {'THRESHOLD': ui.sbLang_thresh.value(), + 'LOOK_AHEAD': ui.sbLang_LA.value()}, + 'Reumann-Witkam Algorithm': lambda: {'THRESHOLD': ui.sbRW_thresh.value()}, + 'Vertex Reduction': lambda: {'THRESHOLD': ui.sbReduction_thresh.value()}, + "Boyle's Forward-Looking Algorithm": lambda: {'LOOK_AHEAD': ui.sbBoyle_LA.value()}, + "Chaiken's Algorithm": lambda: {'LEVEL': ui.sbChaiken_level.value(), + 'WEIGHT': ui.sbChaiken_weight.value()}, + 'Hermite Spline Interpolation': lambda: {'THRESHOLD': ui.sbHermite_steps.value(), + 'TIGHTNESS': ui.sbHermite_tightness.value()}, + "McMaster's Distance-Weighting Algorithm": lambda: {'SLIDE': ui.sbDist_slide.value(), + 'LOOK_AHEAD': ui.sbDist_LA.value()}, + "McMaster's Sliding Averaging Algorithm": lambda: {'SLIDE': ui.sbSlide_slide.value(), + 'LOOK_AHEAD': ui.sbSlide_LA.value()}, + 'Snakes Algorithm': lambda: {'ALPHA': ui.sbSnakes_alpha.value(), + 'BETA': ui.sbSnakes_beta.value()}, + } + return mapping[alg_name]() + + +def _params_from_table(alg_name, par1, par2): + """Constructs the Processing parameters from the values in the batch array.""" + mapping = { + 'Remove small objects': lambda: {'THRESHOLD': par1}, + 'Douglas-Peucker Algorithm': lambda: {'THRESHOLD': par1}, + "Jenk's Algorithm": lambda: {'THRESHOLD': par1, 'ANGLE_THRESHOLD': par2 if par2 != -1 else 3.0}, + 'Lang Algorithm': lambda: {'THRESHOLD': par1, 'LOOK_AHEAD': int(par2)}, + 'Reumann-Witkam Algorithm': lambda: {'THRESHOLD': par1}, + 'Vertex Reduction': lambda: {'THRESHOLD': par1}, + "Boyle's Forward-Looking Algorithm": lambda: {'LOOK_AHEAD': int(par1)}, + "Chaiken's Algorithm": lambda: {'LEVEL': int(par1), 'WEIGHT': par2}, + 'Hermite Spline Interpolation': lambda: {'THRESHOLD': par1, 'TIGHTNESS': par2}, + "McMaster's Distance-Weighting Algorithm": lambda: {'SLIDE': par1, 'LOOK_AHEAD': int(par2)}, + "McMaster's Sliding Averaging Algorithm": lambda: {'SLIDE': par1, 'LOOK_AHEAD': int(par2)}, + 'Snakes Algorithm': lambda: {'ALPHA': par1, 'BETA': par2}, + } + return mapping[alg_name]() + class generalizerDialog(QDialog): + def __init__(self, iface): QDialog.__init__(self) - # Set up the user interface from Designer. self.ui = Ui_generalizer() self.ui.setupUi(self) self.iface = iface @@ -66,715 +96,296 @@ def __init__(self, iface): self.ui.sbJenks_angle.setVisible(False) self.ui.label_8.setVisible(False) - #set signals - self.ui.bBrowse.clicked.connect( self.outFile ) - self.ui.bBrowseDir.clicked.connect( self.outDir ) - self.ui.bOk.clicked.connect( self.generalize ) - self.ui.cbAlgorithm.currentIndexChanged.connect( self.cbChange ) - self.ui.bHelp.clicked.connect( self.showHelp ) - self.ui.cbBatch.stateChanged.connect( self.BatchOn ) - self.ui.bAddAlg.clicked.connect( self.AddAlgorithm ) - self.ui.bDelAlg.clicked.connect( self.DelAlgorithm ) - self.ui.bEditAlg.clicked.connect( self.EditAlgorithm ) - self.ui.cbOutFile.stateChanged.connect( self.FileEnabled ) - self.ui.cbOutDir.stateChanged.connect( self.DirEnabled ) - - #load line layers to lists + self.ui.bBrowse.clicked.connect(self.outFile) + self.ui.bBrowseDir.clicked.connect(self.outDir) + self.ui.bOk.clicked.connect(self.generalize) + self.ui.cbAlgorithm.currentIndexChanged.connect(self.cbChange) + self.ui.bHelp.clicked.connect(self.showHelp) + self.ui.cbBatch.stateChanged.connect(self.BatchOn) + self.ui.bAddAlg.clicked.connect(self.AddAlgorithm) + self.ui.bDelAlg.clicked.connect(self.DelAlgorithm) + self.ui.bEditAlg.clicked.connect(self.EditAlgorithm) + self.ui.cbOutFile.stateChanged.connect(self.FileEnabled) + self.ui.cbOutDir.stateChanged.connect(self.DirEnabled) + + self.cbChange(self.ui.cbAlgorithm.currentIndex()) + self.layerList = getLayersNames() self.ui.cbInput.addItems(self.layerList) self.ui.lstLayers.addItems(self.layerList) - [self.ui.lstLayers.item(i).setCheckState(Qt.Unchecked) for i in range(self.ui.lstLayers.count()) ] + [self.ui.lstLayers.item(i).setCheckState(UNCHECKED) for i in range(self.ui.lstLayers.count())] + def FileEnabled(self, state): - #enable or disable path to file enabled = self.ui.eOutput.isEnabled() self.ui.eOutput.setEnabled(not enabled) self.ui.bBrowse.setEnabled(not enabled) def DirEnabled(self, state): - #enable/disable directory enabled = self.ui.eDir.isEnabled() self.ui.eDir.setEnabled(not enabled) self.ui.bBrowseDir.setEnabled(not enabled) + def BatchOn(self, state): + self.ui.stackBatch.setCurrentIndex(0 if state == 0 else 1) + + def showHelp(self): + QMessageBox.information(self, 'Generalizer', ( + 'Generalizer v2.0\n\n' + 'Adapted to QGIS 4 by Sylvain POULAIN\n' + 'Originally writtent by Piotr Pociask\n\n' + 'Docs: https://github.com/giscan/Generalizer/wiki' + )) + + def outFile(self): + path = saveDialog(self) + if path: + self.ui.eOutput.setText(path) + + def outDir(self): + path = openDir(self) + if path: + self.ui.eDir.setText(path) + + def cbChange(self, index): + combo_to_stack = { + 1: 0, 3: 1, 4: 2, 5: 3, 6: 4, 7: 5, + 9: 6, 10: 7, 11: 8, 12: 9, 13: 10, 14: 11, + } + if index in {0, 2, 8}: + self.ui.cbAlgorithm.setCurrentIndex(index + 1) + return + if index in combo_to_stack: + self.ui.stackOptions.setCurrentIndex(combo_to_stack[index]) + def AddAlgorithm(self): - #add new algorithm in batch mode self.doAddAlgorithm(self.ui.tblBatchAlg.rowCount()) def EditAlgorithm(self): - #edit algorithm in batch mode if self.ui.tblBatchAlg.currentRow() == -1: QMessageBox.warning(self, 'Generalizer', 'Select algorithm to edit!') return - self.doAddAlgorithm(self.ui.tblBatchAlg.currentRow()) def doAddAlgorithm(self, index): - #add new algorithm in batch mode - global algorithm - - new = index > self.ui.tblBatchAlg.rowCount()-1 - items = [self.ui.cbAlgorithm.itemText(i) for i in range(self.ui.cbAlgorithm.count())] - algName = QInputDialog.getItem(None, 'Generalizer', 'Choose algorithm:', items, 1, False) - if not algName[1] or algName[0].startswith('-'): return - #QMessageBox.question(self, 'Generalizer', str(alg)) - par1 = None - par2 = None - - if algName[0] == algorithm['boyle']:#Boyle\'s Forward-Looking Algorithm': - par1 = QSpinBox() - par1.setRange(2, 999) - msg = QInputDialog.getInt(None, 'Generalizer', 'Look ahead:', 7, 2) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Look ahead') - - elif algName[0] == algorithm['sliding']:#'McMaster\'s Sliding Averaging Algorithm': - par1 = QDoubleSpinBox() - par1.setDecimals(2) - par1.setRange(0, 99.99) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Slide:', 0.5, 0, 99.99) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Slide') - - par2 = QSpinBox() - par2.setRange(3, 999) - par2.setSingleStep(2) - par2.setValue(6) - while par2.value()%2 == 0: - msg = QInputDialog.getInt(None, 'Generalizer', 'Look ahead (must be odd number):', par2.value()+1, 3, 999) - if not msg[1]: return - par2.setValue(msg[0]) - par2.setToolTip('Look ahead') - - - elif algName[0] == algorithm['distance']:#'McMaster\'s Distance-Weighting Algorithm': - par1 = QDoubleSpinBox() - par1.setDecimals(2) - par1.setRange(0, 99.99) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Slide:', 0.5, 0, 99.99) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Slide') - - par2 = QSpinBox() - par2.setRange(3, 999) - par2.setSingleStep(2) - par2.setValue(6) - while par2.value()%2 == 0: - msg = QInputDialog.getInt(None, 'Generalizer', 'Look ahead (must be odd number):', par2.value()+1, 3, 999) - if not msg[1]: return - par2.setValue(msg[0]) - par2.setToolTip('Look ahead') - - elif algName[0] == algorithm['chaiken']: #'Chaiken\'s Algorithm': - par1 = QSpinBox() - par1.setRange(0, 99) - msg = QInputDialog.getInt(None, 'Generalizer', 'Level:', 1, 0, 99) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Level') - - par2 = QDoubleSpinBox() - par2.setDecimals(2) - par2.setRange(1, 99.99) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Weight:', 3., 1, 99.99) - if not msg[1]: return - par2.setValue(msg[0]) - par2.setToolTip('Weight') - - elif algName[0] == algorithm['reduction']:#'Vertex Reduction': - par1 = QDoubleSpinBox() - par1.setDecimals(4) - par1.setRange(0.0001, 9999999.9999) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.0001, 9999999.9999, 4) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Threshold') - - elif algName[0] == algorithm['DP']:#'Douglas-Peucker Algorithm': - par1 = QDoubleSpinBox() - par1.setDecimals(4) - par1.setRange(0.0001, 9999999.9999) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.0001, 9999999.9999, 4) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Threshold') - - elif algName[0] == algorithm['remove']:#'Remove small objects': - par1 = QDoubleSpinBox() - par1.setDecimals(4) - par1.setRange(0.0001, 9999999.9999) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.0001, 9999999.9999, 4) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Threshold') - - elif algName[0] == algorithm['lang']:#'Lang Algorithm': - par1 = QDoubleSpinBox() - par1.setDecimals(2) - par1.setRange(0.0001, 9999999.9999) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.0001, 9999999.9999, 4) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Threshold') - - par2 = QSpinBox() - par2.setRange(1, 9999) - msg = QInputDialog.getInt(None, 'Generalizer', 'Look ahead:', 8, 1, 999) - if not msg[1]: return - par2.setValue(msg[0]) - par2.setToolTip('Look ahead') - - - elif algName[0] == algorithm['hermite']:#'Hermite Spline Interpolation': - par1 = QDoubleSpinBox() - par1.setDecimals(4) - par1.setRange(0.0001, 9999999.9999) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 2., 0.0001, 9999999.9999, 4) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Threshold') - - par2 = QDoubleSpinBox() - par2.setDecimals(2) - par2.setRange(0, 1) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Thightness:', 0.5, 0, 1, 2) - if not msg[1]: return - par2.setValue(msg[0]) - par2.setToolTip('Thightness') - - elif algName[0] == algorithm['snakes']:#'Snakes algorithm': - par1 = QDoubleSpinBox() - par1.setDecimals(2) - par1.setRange(0, 9999.99) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Alpha:', 1., 0.00, 9999.99, 2) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Alpha') - - par2 = QDoubleSpinBox() - par2.setDecimals(2) - par2.setRange(0, 9999.99) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Beta:', 0.5, 0., 9999.99, 2) - if not msg[1]: return - par2.setValue(msg[0]) - par2.setToolTip('Beta') - - elif algName[0] == algorithm['jenks']:#'Snakes algorithm': - par1 = QDoubleSpinBox() - par1.setDecimals(4) - par1.setRange(0, 9999999.9999) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.00, 9999999.9999, 4) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Threshold') - - """par2 = QDoubleSpinBox() - par2.setRange(0, 180) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Angle threshold:', 3, 0., 180, 2) - if not msg[1]: return - par2.setValue(msg[0]) - par2.setToolTip('Angle threshold') """ - - elif algName[0] == algorithm['RW']:#Reumann-Witkam Algorithm - par1 = QDoubleSpinBox() - par1.setDecimals(4) - par1.setRange(0, 9999999.9999) - msg = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 0.0001, 0.00, 9999999.9999, 4) - if not msg[1]: return - par1.setValue(msg[0]) - par1.setToolTip('Threshold') - - #QMessageBox.question(self, 'Generalizer', str(type(par1))) - itemAlg = QTableWidgetItem(algName[0]) - itemAlg.setFlags(Qt.ItemIsEnabled) - + choice = QInputDialog.getItem(None, 'Generalizer', 'Choose algorithm:', items, 1, False) + if not choice[1] or choice[0].startswith('-'): + return + name = choice[0] + par1 = par2 = None + + if name in ('Remove small objects', 'Douglas-Peucker Algorithm', + 'Reumann-Witkam Algorithm', 'Vertex Reduction'): + v = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 1.0, 0.0001, 9999999.0, 4) + if not v[1]: return + par1 = QDoubleSpinBox(); par1.setDecimals(4); par1.setRange(0.0001, 9999999.0) + par1.setValue(v[0]); par1.setToolTip('Threshold') + + elif name == "Boyle's Forward-Looking Algorithm": + v = QInputDialog.getInt(None, 'Generalizer', 'Look ahead:', 7, 2, 999) + if not v[1]: return + par1 = QSpinBox(); par1.setRange(2, 999); par1.setValue(v[0]); par1.setToolTip('Look ahead') + + elif name == "Chaiken's Algorithm": + v = QInputDialog.getInt(None, 'Generalizer', 'Level:', 1, 1, 99) + if not v[1]: return + par1 = QSpinBox(); par1.setRange(1, 99); par1.setValue(v[0]); par1.setToolTip('Level') + v2 = QInputDialog.getDouble(None, 'Generalizer', 'Weight:', 3.0, 1.0, 99.99, 2) + if not v2[1]: return + par2 = QDoubleSpinBox(); par2.setRange(1.0, 99.99); par2.setValue(v2[0]); par2.setToolTip('Weight') + + elif name == 'Hermite Spline Interpolation': + v = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 1.0, 0.0001, 9999999.0, 4) + if not v[1]: return + par1 = QDoubleSpinBox(); par1.setDecimals(4); par1.setRange(0.0001, 9999999.0) + par1.setValue(v[0]); par1.setToolTip('Threshold') + v2 = QInputDialog.getDouble(None, 'Generalizer', 'Tightness:', 0.5, 0.0, 1.0, 2) + if not v2[1]: return + par2 = QDoubleSpinBox(); par2.setRange(0.0, 1.0); par2.setValue(v2[0]); par2.setToolTip('Tightness') + + elif name == 'Lang Algorithm': + v = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 1.0, 0.0001, 9999999.0, 4) + if not v[1]: return + par1 = QDoubleSpinBox(); par1.setDecimals(4); par1.setRange(0.0001, 9999999.0) + par1.setValue(v[0]); par1.setToolTip('Threshold') + v2 = QInputDialog.getInt(None, 'Generalizer', 'Look ahead:', 8, 1, 9999) + if not v2[1]: return + par2 = QSpinBox(); par2.setRange(1, 9999); par2.setValue(v2[0]); par2.setToolTip('Look ahead') + + elif name in ("McMaster's Distance-Weighting Algorithm", + "McMaster's Sliding Averaging Algorithm"): + v = QInputDialog.getDouble(None, 'Generalizer', 'Slide:', 0.5, 0.0, 99.99, 2) + if not v[1]: return + par1 = QDoubleSpinBox(); par1.setRange(0.0, 99.99); par1.setValue(v[0]); par1.setToolTip('Slide') + la = 6 + while la % 2 == 0: + v2 = QInputDialog.getInt(None, 'Generalizer', 'Look ahead (odd):', la + 1, 3, 999) + if not v2[1]: return + la = v2[0] + par2 = QSpinBox(); par2.setRange(3, 999); par2.setSingleStep(2) + par2.setValue(la); par2.setToolTip('Look ahead') + + elif name == 'Snakes Algorithm': + v = QInputDialog.getDouble(None, 'Generalizer', 'Alpha:', 1.0, 0.0, 9999.99, 2) + if not v[1]: return + par1 = QDoubleSpinBox(); par1.setRange(0.0, 9999.99); par1.setValue(v[0]); par1.setToolTip('Alpha') + v2 = QInputDialog.getDouble(None, 'Generalizer', 'Beta:', 0.5, 0.0, 9999.99, 2) + if not v2[1]: return + par2 = QDoubleSpinBox(); par2.setRange(0.0, 9999.99); par2.setValue(v2[0]); par2.setToolTip('Beta') + + elif name == "Jenk's Algorithm": + v = QInputDialog.getDouble(None, 'Generalizer', 'Threshold:', 1.0, 0.0, 9999999.0, 4) + if not v[1]: return + par1 = QDoubleSpinBox(); par1.setDecimals(4); par1.setRange(0.0, 9999999.0) + par1.setValue(v[0]); par1.setToolTip('Threshold') + + new = index > self.ui.tblBatchAlg.rowCount() - 1 if new: - self.ui.tblBatchAlg.setRowCount(self.ui.tblBatchAlg.rowCount()+1) + self.ui.tblBatchAlg.setRowCount(self.ui.tblBatchAlg.rowCount() + 1) - self.ui.tblBatchAlg.setItem(index, 0, itemAlg) + item = QTableWidgetItem(name) + item.setFlags(Qt.ItemFlag.ItemIsEnabled) + self.ui.tblBatchAlg.setItem(index, 0, item) self.ui.tblBatchAlg.setCellWidget(index, 1, par1) - if par2 == None: + if par2 is None: self.ui.tblBatchAlg.setCellWidget(index, 2, None) - par2 = QTableWidgetItem(0) - par2.setFlags(Qt.ItemIsSelectable) - self.ui.tblBatchAlg.setItem(index, 2, par2) + empty = QTableWidgetItem('') + empty.setFlags(Qt.ItemFlag.ItemIsSelectable) + self.ui.tblBatchAlg.setItem(index, 2, empty) else: self.ui.tblBatchAlg.setCellWidget(index, 2, par2) def DelAlgorithm(self): - #del algorithm in batch mode if self.ui.tblBatchAlg.currentRow() == -1: QMessageBox.warning(self, 'Generalizer', 'Select algorithm to delete!') return - alg = self.ui.tblBatchAlg.item(self.ui.tblBatchAlg.currentRow(), 0).text() - msg = QMessageBox.question(self, 'Generalizer', 'Do you want to delete %s' % (alg), QMessageBox.Yes | QMessageBox.No) - - if msg == QMessageBox.Yes: + msg = QMessageBox.question(self, 'Generalizer', f'Delete {alg}?', + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No) + if msg == QMessageBox.StandardButton.Yes: self.ui.tblBatchAlg.removeRow(self.ui.tblBatchAlg.currentRow()) - def BatchOn(self, state): - #set batch mode on/off - if state == 0: - self.ui.stackBatch.setCurrentIndex(0) - else: - self.ui.stackBatch.setCurrentIndex(1) - - def showHelp(self): - #show information about plugin - QMessageBox.information(self, 'Generalizer', """Generalizer -Version 0.6 - -Originally created by -Piotr Pociask -Adapted to QGIS3 by -Sylvain POULAIN - -Documentation available : -https://github.com/giscan/Generalizer/wiki -""") - - def outFile(self): - """Open a file save dialog and set the output file path.""" - outFilePath = saveDialog(self) - if not outFilePath: - return - self.ui.eOutput.setText(outFilePath) - - def outDir(self): - #select directory to save layer(s) in created batch mode - outPath = openDir(self) - if outPath: - self.ui.eDir.setText(outPath) - - def cbChange(self, index): - #set parameters after algorithm change - if index == 0: self.ui.cbAlgorithm.setCurrentIndex(1) - elif index == 1: self.ui.stackOptions.setCurrentIndex(index-1) #generalization - elif index == 2: self.ui.cbAlgorithm.setCurrentIndex(3) - elif index < 8: self.ui.stackOptions.setCurrentIndex(index-2) #simplify - elif index == 8: self.ui.cbAlgorithm.setCurrentIndex(9) - else: self.ui.stackOptions.setCurrentIndex(index-3) #smooth - - - def GetArguments(self, par1=-1, par2=-1): - #set parameters to algorithm - if not self.ui.cbBatch.checkState(): - arguments = {} - arguments['remove_thresh'] = self.ui.sbRemove_thresh.value() - arguments['dp_thresh'] = self.ui.sbDP_thresh.value() - arguments['lang_thresh'] = self.ui.sbLang_thresh.value() - arguments['lang_LA'] = self.ui.sbLang_LA.value() - arguments['reduction_thresh'] = self.ui.sbReduction_thresh.value() - arguments['boyle_LA'] = self.ui.sbBoyle_LA.value() - arguments['slide_slide'] = self.ui.sbSlide_slide.value() - arguments['slide_LA'] = self.ui.sbSlide_LA.value() - arguments['dist_slide'] = self.ui.sbDist_slide.value() - arguments['dist_LA'] = self.ui.sbDist_LA.value() - arguments['chaiken_level'] = self.ui.sbChaiken_level.value() - arguments['chaiken_weight'] = self.ui.sbChaiken_weight.value() - arguments['hermite_thresh'] = self.ui.sbHermite_steps.value() - arguments['hermite_tightness'] = self.ui.sbHermite_tightness.value() - arguments['jenks_thresh'] = self.ui.sbJenks_thresh.value() - arguments['jenks_angle'] = self.ui.sbJenks_angle.value() - arguments['snakes_alpha'] = self.ui.sbSnakes_alpha.value() - arguments['snakes_beta'] = self.ui.sbSnakes_beta.value() - arguments['rw_thresh'] = self.ui.sbRW_thresh.value() - else: - arguments = {} - arguments['remove_thresh'] = par1 - arguments['dp_thresh'] = par1 - arguments['lang_thresh'] = par1 - arguments['lang_LA'] = par2 - arguments['reduction_thresh'] = par1 - arguments['boyle_LA'] = par1 - arguments['slide_slide'] = par1 - arguments['slide_LA'] = par2 - arguments['dist_slide'] = par1 - arguments['dist_LA'] = par2 - arguments['chaiken_level'] = par1 - arguments['chaiken_weight'] = par2 - arguments['hermite_thresh'] = par1 - arguments['hermite_tightness'] = par2 - arguments['jenks_thresh'] = par1 - arguments['jenks_angle'] = par2 - arguments['snakes_alpha'] = par1 - arguments['snakes_beta'] = par2 - arguments['rw_thresh'] = par1 - - if (arguments['slide_LA']%2 == 0) or (arguments['dist_LA']%2 == 0): - QMessageBox.critical(None, 'Generalizer', 'Look ehead parameter must be odd number!') + def _run(self, alg_name, layer, params, output='TEMPORARY_OUTPUT'): + """Calls processing.run() and returns the result layer or None.""" + proc_id = ALGO_ID.get(alg_name) + if proc_id is None: + QMessageBox.critical(None, 'Generalizer', f'Unknown algorithm: {alg_name}') + return None + try: + result = processing.run(proc_id, {'INPUT': layer, 'OUTPUT': output, **params}) + return result['OUTPUT'] + except Exception as e: + QgsMessageLog.logMessage(str(e), 'Generalizer3', level=Qgis.Critical) + QMessageBox.critical(None, 'Generalizer', f'Error in {alg_name}:\n{e}') return None - else: - return arguments - - def GetFunction(self, funcName): - #set function from name - global algorithm - - if funcName == algorithm['boyle']:#'Boyle\'s Forward-Looking Algorithm': - return self.boyle - elif funcName == algorithm['sliding']:#'McMaster\'s Sliding Averaging Algorithm': - return self.sliding_averaging - elif funcName == algorithm['distance']:#'McMaster\'s Distance-Weighting Algorithm': - return self.distance_weighting - elif funcName == algorithm['chaiken']:#'Chaiken\'s Algorithm': - return self.chaiken - elif funcName == algorithm['reduction']:#'Vertex Reduction': - return self.vertex_reduction - elif funcName == algorithm['DP']:#'Douglas-Peucker Algorithm': - return self.douglas_peucker - elif funcName == algorithm['remove']:#'Remove small objects': - return self.remove - elif funcName == algorithm['lang']:#'Lang Algorithm': - return self.lang - elif funcName == algorithm['hermite']:#'Hermite Spline Interpolation': - return self.hermite - elif funcName == algorithm['jenks']:#'Jenk's Algorithm': - return self.jenks - elif funcName == algorithm['snakes']:#'Snakes': - return self.snakes - elif funcName == algorithm['RW']:#'Reumann-Witkam Algorithm': - return self.reumann_witkam - - def NameFromFunc(self, func, arguments): - if func == self.boyle: - return '-boyle_LA-' + str(arguments['boyle_LA']) - elif func == self.sliding_averaging: - return '-slide_slide-' + str(arguments['slide_slide']) + '_LA-' + str(arguments['slide_LA']) - elif func == self.distance_weighting: - return '-dist_slide-' + str(arguments['dist_slide']) + '_LA-' + str(arguments['dist_LA']) - elif func == self.chaiken: - return '-chaiken_level-' + str(arguments['chaiken_level']) + '_weight-' + str(arguments['chaiken_weight']) - elif func == self.vertex_reduction: - return '-reduction_thresh-' + str(arguments['reduction_thresh']) - elif func == self.douglas_peucker: - return '-DP_thresh-' + str(arguments['dp_thresh']) - elif func == self.remove: - return '-remove_thresh-' + str(arguments['remove_thresh']) - elif func == self.lang: - return '-lang_thresh-' + str(arguments['lang_thresh']) + '_LA-' + str(arguments['lang_LA']) - elif func == self.hermite: - return '-hermite_thresh-' + str(arguments['hermite_thresh']) + '_tight-' + str(arguments['hermite_tightness']) - elif func == self.jenks: - return '-jenks_thresh-' + str(arguments['jenks_thresh']) + '_angle-' + str(arguments['jenks_angle']) - elif func == self.snakes: - return '-snakes_alpha-' + str(arguments['snakes_alpha']) + '_beta-' + str(arguments['snakes_beta']) - elif func == self.reumann_witkam: - return '-RW_thresh-' + str(arguments['rw_thresh']) - - - def LoadLayers(self, fileList): - #load created layer - msg = QMessageBox.question(self, 'Generalizer', 'New layer(s) created. \n Add to TOC?', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) - if msg == QMessageBox.Yes: - for filePath in fileList: - if "\\" in filePath: - out_name = filePath[(len(filePath) - filePath.rfind("\\")) - 1:] - else: - out_name = filePath[(len(filePath) - filePath.rfind("/")) - 1:] - - if out_name.endswith(".gpkg"): - out_name = out_name[:len(out_name) - 5] - - self.iface.addVectorLayer(filePath, out_name, "ogr") - - def doGeneralize(self, iLayerName, iLayer, oPath, func, arguments): - #do calculations - fet = QgsFeature() + def generalize(self): + if self.ui.cbBatch.isChecked(): + if self.ui.cbOutDir.isChecked() and self.ui.eDir.text() == '': + QMessageBox.critical(None, 'Generalizer', 'Enter output directory!') + return - iProvider = iLayer.dataProvider() - fields = iProvider.fields() + layers = [ + self.ui.lstLayers.item(i).text() + for i in range(self.ui.lstLayers.count()) + if self.ui.lstLayers.item(i).checkState() == CHECKED + ] + if not layers: + QMessageBox.warning(None, 'Generalizer', 'Select at least one layer!') + return - if oPath == 'memory': #create memory layer - #if iLayer.wkbType() == QgsWkbTypes.LineString: - # mLayer = QgsVectorLayer('LineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') - #else: - # mLayer = QgsVectorLayer('MultiLineString', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') - if iLayer.wkbType() == QgsWkbTypes.LineString: - #mLayer = QgsVectorLayer('LineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') - mLayer = QgsVectorLayer("LineString?crs=" + QgsProject.instance().crs().authid(), iLayerName + "_memory", "memory") - else: - #mLayer = QgsVectorLayer('MultiLineString?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', iLayerName + '_memory', 'memory')#self.NameFromFunc(func, arguments), 'memory') - mLayer = QgsVectorLayer("MultiLineString?crs=" + QgsProject.instance().crs().authid(), iLayerName + "_memory", "memory") - - mProvider = mLayer.dataProvider() - mProvider.addAttributes( [key for key in fields] ) - - for feat in iProvider.getFeatures(): - geom = feat.geometry() - if geom.isMultipart(): - lm = geom.asMultiPolyline() - l = [] - for ls in lm: - p = func(ls, **arguments) - l2 = [] - for n in range(p.n_points): - l2.append(QgsPointXY(p.x[n], p.y[n])) - if len(l2) > 1: - l.append(l2) - if len(l) > 1: - fet.setGeometry(QgsGeometry.fromMultiPolylineXY(l)) - elif len(l) == 1: #jesli z obiektu wieloczesciowego zostaje tylko jedna linia (np. przy usuwaniu malych obiektow) - fet.setGeometry(QgsGeometry.fromPolylineXY(l[0])) - else: - ls = geom.asPolyline() - p = func(ls, **arguments) - l = [] - for n in range(p.n_points): - l.append(QgsPoint(p.x[n], p.y[n])) - if len(l) > 1: - fet.setGeometry(QgsGeometry.fromPolyline(l)) + outNames = [] + for layer_name in layers: + layer = getMapLayerByName(layer_name) + if layer is None: + continue + + current = layer + n_algs = self.ui.tblBatchAlg.rowCount() + for i in range(n_algs): + alg_name = self.ui.tblBatchAlg.item(i, 0).text() + w1 = self.ui.tblBatchAlg.cellWidget(i, 1) + w2 = self.ui.tblBatchAlg.cellWidget(i, 2) + par1 = w1.value() if w1 else 1.0 + par2 = w2.value() if w2 else -1 + params = _params_from_table(alg_name, par1, par2) + + is_last = (i == n_algs - 1) + if self.ui.cbOutDir.isChecked() and is_last: + sep = '\\' if '\\' in self.ui.eDir.text() else '/' + out_path = f"{self.ui.eDir.text()}{sep}{layer_name}_new.gpkg" + outNames.append(out_path) + output = out_path else: - continue #jak linia jest pusta to przejdz do nastepnej - fet.setAttributes(feat.attributes()) - mProvider.addFeatures([fet]) - mLayer.updateFields() - mLayer.updateExtents() - return mLayer - - else: #write shapefile on disk - #writer = QgsVectorFileWriter(oPath, iProvider.encoding(), fields, QGis.WKBLineString, iLayer.crs()) - writer = QgsVectorFileWriter(oPath, iProvider.encoding(), fields, QgsWkbTypes.LineString, iLayer.crs()) - if writer.hasError() != QgsVectorFileWriter.NoError: - QMessageBox.critical(None, 'Generalizer', 'Error when creating shapefile: %s' % (writer.hasError())) - - for feat in iProvider.getFeatures(): - geom = feat.geometry() - if geom.isMultipart(): - lm = geom.asMultiPolyline() - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(lm) ) - l = [] - for ls in lm: - p = func(ls, **arguments) - l2 = [] - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(p.n_points) ) - for n in range(p.n_points): - l2.append(QgsPoint(p.x[n], p.y[n])) - if len(l2) > 1: - l.append(l2) - if len(l) > 1: - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(l) ) - fet.setGeometry(QgsGeometry.fromMultiPolylineXY(l)) - else: - ls = geom.asPolyline() - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(ls) ) - p = func(ls, **arguments) - l = [] - for n in range(p.n_points): - l.append(QgsPoint(p.x[n], p.y[n])) - - if len(l) > 1: - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(l) ) - fet.setGeometry(QgsGeometry.fromPolyline(l)) - fet.setAttributes(feat.attributes()) - writer.addFeature(fet) - - del writer - return self.ui.eOutput.text() - - - def batchGeneralize(self, layers): - outNames = [] - for layer in layers: - vLayer = getMapLayerByName(layer) - for i in range(self.ui.tblBatchAlg.rowCount()): - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(i) ) - alg = self.ui.tblBatchAlg.item(i, 0).text() - func = self.GetFunction(alg) - - par1 = self.ui.tblBatchAlg.cellWidget(i,1).value() - if not func in [self.remove, self.douglas_peucker, self.vertex_reduction, self.boyle, self.jenks, self.reumann_witkam]: - par2 = self.ui.tblBatchAlg.cellWidget(i,2).value() - else: - par2 = -1 - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(par2) ) - - arguments = self.GetArguments(par1, par2) - if self.ui.cbOutDir.isChecked() and i == self.ui.tblBatchAlg.rowCount()-1: - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(i) ) - path = self.ui.eDir.text() - if path.contains("\\"): - out_name = path + '\\' + layer + '_new.gpkg' - else: - out_name = path + '/' + layer + '_new.gpkg' - outNames.append(out_name) - vLayer = self.doGeneralize(layer, vLayer, out_name, func, arguments) - else: - vLayer = self.doGeneralize(layer, vLayer, 'memory', func, arguments) - - if not self.ui.cbOutDir.isChecked(): - QgsProject.instance().addMapLayer(vLayer) - - if self.ui.cbOutDir.isChecked(): - self.LoadLayers(outNames) - + output = 'TEMPORARY_OUTPUT' + current = self._run(alg_name, current, params, output) + if current is None: + break + else: + if not self.ui.cbOutDir.isChecked(): + QgsProject.instance().addMapLayer(current) - def generalize(self): - if self.ui.cbBatch.isChecked(): - if self.ui.cbOutDir.isChecked(): - if self.ui.eDir.text() == '': - QMessageBox.critical(None, 'Generalizer', 'Enter output directory!') - return - + if self.ui.cbOutDir.isChecked() and outNames: + self._loadLayers(outNames) - layers = [self.ui.lstLayers.item(i).text() for i in range(self.ui.lstLayers.count()) if self.ui.lstLayers.item(i).checkState() ] - self.batchGeneralize(layers) - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(layers) ) else: - if self.ui.cbInput.currentText() == '': + if not self.ui.cbInput.currentText(): QMessageBox.critical(None, 'Generalizer', 'No line layers!') return - arguments = self.GetArguments() - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(arguments) ) - if arguments == None: - return + alg_name = self.ui.cbAlgorithm.currentText() + layer = getMapLayerByName(self.ui.cbInput.currentText()) + params = _params_from_ui(alg_name, self.ui) - func = self.GetFunction(self.ui.cbAlgorithm.currentText()) if self.ui.cbOutFile.isChecked(): - if self.ui.eOutput.text() == '': + if not self.ui.eOutput.text(): QMessageBox.critical(None, 'Generalizer', 'Enter output file name!') return - filePath = self.doGeneralize(self.ui.cbInput.currentText(), getMapLayerByName(self.ui.cbInput.currentText()), self.ui.eOutput.text(), func, arguments) - self.LoadLayers([filePath]) + result = self._run(alg_name, layer, params, self.ui.eOutput.text()) + if result: + self._loadLayers([self.ui.eOutput.text()]) else: - mLayer = self.doGeneralize(self.ui.cbInput.currentText(), getMapLayerByName(self.ui.cbInput.currentText()), 'memory', func, arguments) - QgsProject.instance().addMapLayer(mLayer) + result = self._run(alg_name, layer, params) + if result: + QgsProject.instance().addMapLayer(result) - #self.close() - #refresh layer list self.layerList = getLayersNames() self.ui.cbInput.clear() self.ui.lstLayers.clear() self.ui.cbInput.addItems(self.layerList) self.ui.lstLayers.addItems(self.layerList) - [self.ui.lstLayers.item(i).setCheckState(Qt.Unchecked) for i in range(self.ui.lstLayers.count()) ] - - def remove(self, l, **kwargs): - #Remove Small Objects - thresh = kwargs['remove_thresh'] - length = 0. - p = points.Vect_new_line_struct(l) - p1 = points.point() - p2 = points.point() - - for i in range(p.n_points-1): - points.point_assign(p, i, p1) - points.point_assign(p, i+1, p2) - length = length + points.point_dist(p1, p2) - - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str( length ) ) - if length < thresh: - p.x = [] - p.y = [] - p.n_points = 0 - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str( p.x ) ) - - return p - - def boyle(self,l, **kwargs): - #Boyle's Forward-Looking Algorithm - p = points.Vect_new_line_struct(l) - n = smooth.boyle(p, kwargs['boyle_LA']) - - return p + [self.ui.lstLayers.item(i).setCheckState(UNCHECKED) for i in range(self.ui.lstLayers.count())] - def sliding_averaging(self,l, **kwargs): - #McMaster's Sliding Averaging Algorithm - p = points.Vect_new_line_struct(l) - n = smooth.sliding_averaging(p, kwargs['slide_slide'], kwargs['slide_LA']) - - return p - - def distance_weighting(self,l, **kwargs): - #McMaster's Distance Weighting Algorithm - p = points.Vect_new_line_struct(l) - n = smooth.distance_weighting(p, kwargs['dist_slide'], kwargs['dist_LA']) - - return p - - def chaiken(self,l, **kwargs): - #Chaiken's Algorithm - p = points.Vect_new_line_struct(l) - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(p.n_points) ) - n = smooth.chaiken(p, kwargs['chaiken_level'], kwargs['chaiken_weight']) - - return p - - def vertex_reduction(self,l, **kwargs): - #Vertex Reduction - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(l) ) - p = points.Vect_new_line_struct(l) - n = simplify.vertex_reduction(p, kwargs['reduction_thresh']) - - return p - - def douglas_peucker(self,l, **kwargs): - #Douglas-peucker Algorithm - tmp = simplify.douglas_peucker(l, kwargs['dp_thresh']) - p = points.Vect_new_line_struct(tmp) - - return p - - def lang(self,l, **kwargs): - #Vertex Reduction - p = points.Vect_new_line_struct(l) - n = simplify.lang(p, kwargs['lang_thresh'], kwargs['lang_LA']) - - return p - - def hermite(self,l, **kwargs): - #Vertex Reduction - p = points.Vect_new_line_struct(l) - n = smooth.hermite(p, kwargs['hermite_thresh'], kwargs['hermite_tightness']) - - return p - - def jenks(self,l, **kwargs): - #Jenk's Algorithm - #QInputDialog.getText( self.iface.mainWindow(), "m", "e", QLineEdit.Normal, str(kwargs['jenks_angle']) ) - p = points.Vect_new_line_struct(l) - n = simplify.jenks(p, kwargs['jenks_thresh'], kwargs['jenks_angle']) - - return p - - def snakes(self,l, **kwargs): - #Snakes - p = points.Vect_new_line_struct(l) - n = smooth.snakes(p, kwargs['snakes_alpha'], kwargs['snakes_beta']) - - return p - - def reumann_witkam(self,l, **kwargs): - #Snakes - p = points.Vect_new_line_struct(l) - n = simplify.reumann_witkam(p, kwargs['rw_thresh']) - - return p + def _loadLayers(self, fileList): + msg = QMessageBox.question(self, 'Generalizer', 'New layer(s) created.\nAdd to TOC?', + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, + QMessageBox.StandardButton.Yes) + if msg == QMessageBox.StandardButton.Yes: + for filePath in fileList: + sep = '\\' if '\\' in filePath else '/' + out_name = filePath.split(sep)[-1].removesuffix('.gpkg') + self.iface.addVectorLayer(filePath, out_name, 'ogr') def getLayersNames(): layermap = QgsProject.instance().mapLayers() - layerlist = [] - for name, layer in layermap.items(): - if layer.type() == QgsMapLayer.VectorLayer: - if layer.geometryType() == QgsWkbTypes.LineGeometry: - layerlist.append( str( layer.name() ) ) - - return layerlist - -def getMapLayerByName(myName): - layermap = QgsProject.instance().mapLayers() - for name, layer in layermap.items(): - if layer.name() == myName: - if layer.isValid(): - return layer - else: - return None + result = [] + for layer in layermap.values(): + if layer.type() == QgsMapLayer.LayerType.VectorLayer: + try: + is_line = layer.geometryType() == Qgis.GeometryType.Line + except AttributeError: + from qgis.core import QgsWkbTypes + is_line = layer.geometryType() == QgsWkbTypes.LineGeometry + if is_line: + result.append(str(layer.name())) + return result + + +def getMapLayerByName(name): + for layer in QgsProject.instance().mapLayers().values(): + if layer.name() == name and layer.isValid(): + return layer + return None diff --git a/metadata.txt b/metadata.txt index 8827fa8..ede5cbf 100644 --- a/metadata.txt +++ b/metadata.txt @@ -1,7 +1,8 @@ [general] name=Generalizer3 email=sylvain.poulain@giscan.com -qgisMinimumVersion=3.0 +qgisMinimumVersion=4.0 +qgisMaximumVersion=4.99 description=Lines generalization and smoothing (partially based on v.generalize GRASS module) about=Plugin to Generalize, Simplify or Smooth lines in QGIS Functions : @@ -20,7 +21,7 @@ about=Plugin to Generalize, Simplify or Smooth lines in QGIS Distance Weighting McMaster's Sliding Averaging Algorithm Snakes Algorithm : Slowest smoothing algorithm -version=0.9 +version=2.0 author=Piotr Pociask, Matthew Petroff, Sylvain POULAIN @@ -41,6 +42,13 @@ experimental=False deprecated=False changelog= + 2.0 (03.04/2026) + - Compatibility to Qgis 4 & Qt6 + - Push algorithm to processing + - Ui launch processing algs + 1.0 (18.11.2020) + - Fix unkown projection when new layer is created + - Multipart lines supported 0.9 (09.11.2020) - Move plugin to his self toolbar 0.8 (23.05.2020) diff --git a/points.py b/points.py index 566955c..1e1f5d8 100644 --- a/points.py +++ b/points.py @@ -1,5 +1,10 @@ from builtins import object -from PyQt5.QtGui import * + +try: + from qgis.PyQt.QtGui import * +except ImportError: + from PyQt5.QtGui import * + from math import sqrt, acos, pi, fabs class line_pnts(object): @@ -132,9 +137,14 @@ def Vect_new_line_struct(l): res = line_pnts() for i in l: - res.x.append(i[0]) - res.y.append(i[1]) - res.n_points = len(l) + # QGIS 4: asPolyline() retourne des QgsPointXY — accepter les deux formats + if hasattr(i, 'x') and callable(i.x): + res.x.append(i.x()) + res.y.append(i.y()) + else: + res.x.append(i[0]) + res.y.append(i[1]) + res.n_points = len(res.x) return res diff --git a/resources.py b/resources.py index 2d7ba17..78a7745 100644 --- a/resources.py +++ b/resources.py @@ -6,7 +6,10 @@ # # WARNING! All changes made in this file will be lost! -from PyQt5 import QtCore +try: + from qgis.PyQt import QtCore +except ImportError: + from PyQt5 import QtCore qt_resource_data = b"\ \x00\x00\x17\xc5\ diff --git a/simplify.py b/simplify.py index 72a4a88..6320595 100644 --- a/simplify.py +++ b/simplify.py @@ -1,6 +1,9 @@ from __future__ import absolute_import from builtins import range -from PyQt5.QtGui import * +try: + from qgis.PyQt.QtGui import * +except ImportError: + from PyQt5.QtGui import * from .points import * import math diff --git a/smooth.py b/smooth.py index ca8b7e2..3c9e910 100644 --- a/smooth.py +++ b/smooth.py @@ -1,7 +1,10 @@ from __future__ import print_function from __future__ import absolute_import from builtins import range -from qgis.PyQt.QtWidgets import * +try: + from qgis.PyQt.QtWidgets import * +except ImportError: + from PyQt5.QtWidgets import * from .points import * from .matrix import * @@ -169,6 +172,10 @@ def distance_weighting(points, slide, look_ahead): def chaiken(points, level, weight): + from qgis.core import QgsMessageLog, Qgis + QgsMessageLog.logMessage(f"chaiken weight: {weight} ({type(weight)})", + "Generalizer3", + level=Qgis.Info) n = 0 i = 0 j = 0 @@ -184,6 +191,7 @@ def chaiken(points, level, weight): if n < 3: return n + weight = float(weight) d1 = 1./(1+weight) d2 = float(weight)/(1+weight) diff --git a/ui_generalizer.py b/ui_generalizer.py index b88c781..3d25e0a 100644 --- a/ui_generalizer.py +++ b/ui_generalizer.py @@ -1,26 +1,25 @@ -# -*- coding: utf-8 -*- - # Form implementation generated from reading ui file 'ui_generalizer.ui' # -# Created by: PyQt5 UI code generator 5.13.1 +# Created by: PyQt6 UI code generator 6.10.2 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic6 is +# run again. Do not edit this file unless you know what you are doing. -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_generalizer(object): def setupUi(self, generalizer): generalizer.setObjectName("generalizer") - generalizer.resize(493, 348) + generalizer.resize(493, 427) self.gridLayout_20 = QtWidgets.QGridLayout(generalizer) self.gridLayout_20.setObjectName("gridLayout_20") - self.cbBatch = QtWidgets.QCheckBox(generalizer) + self.cbBatch = QtWidgets.QCheckBox(parent=generalizer) self.cbBatch.setObjectName("cbBatch") self.gridLayout_20.addWidget(self.cbBatch, 0, 0, 1, 1) - self.bHelp = QtWidgets.QPushButton(generalizer) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) + self.bHelp = QtWidgets.QPushButton(parent=generalizer) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.bHelp.sizePolicy().hasHeightForWidth()) @@ -28,38 +27,38 @@ def setupUi(self, generalizer): self.bHelp.setFlat(True) self.bHelp.setObjectName("bHelp") self.gridLayout_20.addWidget(self.bHelp, 0, 2, 1, 1) - self.bOk = QtWidgets.QPushButton(generalizer) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) + self.bOk = QtWidgets.QPushButton(parent=generalizer) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.bOk.sizePolicy().hasHeightForWidth()) self.bOk.setSizePolicy(sizePolicy) self.bOk.setObjectName("bOk") self.gridLayout_20.addWidget(self.bOk, 2, 1, 1, 1) - self.bCancel = QtWidgets.QPushButton(generalizer) + self.bCancel = QtWidgets.QPushButton(parent=generalizer) self.bCancel.setObjectName("bCancel") self.gridLayout_20.addWidget(self.bCancel, 2, 2, 1, 1) - self.stackBatch = QtWidgets.QStackedWidget(generalizer) + self.stackBatch = QtWidgets.QStackedWidget(parent=generalizer) self.stackBatch.setObjectName("stackBatch") self.page_6 = QtWidgets.QWidget() self.page_6.setObjectName("page_6") self.gridLayout_19 = QtWidgets.QGridLayout(self.page_6) self.gridLayout_19.setObjectName("gridLayout_19") - self.label = QtWidgets.QLabel(self.page_6) + self.label = QtWidgets.QLabel(parent=self.page_6) self.label.setObjectName("label") self.gridLayout_19.addWidget(self.label, 0, 0, 1, 1) - self.cbInput = QtWidgets.QComboBox(self.page_6) + self.cbInput = QtWidgets.QComboBox(parent=self.page_6) self.cbInput.setObjectName("cbInput") self.gridLayout_19.addWidget(self.cbInput, 1, 0, 1, 2) - self.groupBox = QtWidgets.QGroupBox(self.page_6) + self.groupBox = QtWidgets.QGroupBox(parent=self.page_6) self.groupBox.setObjectName("groupBox") self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox) self.gridLayout_2.setObjectName("gridLayout_2") - self.label_3 = QtWidgets.QLabel(self.groupBox) + self.label_3 = QtWidgets.QLabel(parent=self.groupBox) self.label_3.setObjectName("label_3") self.gridLayout_2.addWidget(self.label_3, 0, 0, 1, 1) - self.cbAlgorithm = QtWidgets.QComboBox(self.groupBox) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed) + self.cbAlgorithm = QtWidgets.QComboBox(parent=self.groupBox) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.cbAlgorithm.sizePolicy().hasHeightForWidth()) @@ -81,16 +80,16 @@ def setupUi(self, generalizer): self.cbAlgorithm.addItem("") self.cbAlgorithm.addItem("") self.gridLayout_2.addWidget(self.cbAlgorithm, 0, 1, 1, 1) - self.stackOptions = QtWidgets.QStackedWidget(self.groupBox) + self.stackOptions = QtWidgets.QStackedWidget(parent=self.groupBox) self.stackOptions.setObjectName("stackOptions") self.page_11 = QtWidgets.QWidget() self.page_11.setObjectName("page_11") self.gridLayout_11 = QtWidgets.QGridLayout(self.page_11) self.gridLayout_11.setObjectName("gridLayout_11") - self.label_12 = QtWidgets.QLabel(self.page_11) + self.label_12 = QtWidgets.QLabel(parent=self.page_11) self.label_12.setObjectName("label_12") self.gridLayout_11.addWidget(self.label_12, 0, 0, 1, 1) - self.sbRemove_thresh = QtWidgets.QDoubleSpinBox(self.page_11) + self.sbRemove_thresh = QtWidgets.QDoubleSpinBox(parent=self.page_11) self.sbRemove_thresh.setDecimals(4) self.sbRemove_thresh.setMinimum(0.0001) self.sbRemove_thresh.setMaximum(9999999.9999) @@ -102,10 +101,10 @@ def setupUi(self, generalizer): self.page_12.setObjectName("page_12") self.gridLayout_12 = QtWidgets.QGridLayout(self.page_12) self.gridLayout_12.setObjectName("gridLayout_12") - self.label_18 = QtWidgets.QLabel(self.page_12) + self.label_18 = QtWidgets.QLabel(parent=self.page_12) self.label_18.setObjectName("label_18") self.gridLayout_12.addWidget(self.label_18, 0, 0, 1, 1) - self.sbDP_thresh = QtWidgets.QDoubleSpinBox(self.page_12) + self.sbDP_thresh = QtWidgets.QDoubleSpinBox(parent=self.page_12) self.sbDP_thresh.setDecimals(4) self.sbDP_thresh.setMinimum(0.0001) self.sbDP_thresh.setMaximum(9999999.9999) @@ -117,19 +116,19 @@ def setupUi(self, generalizer): self.page_2.setObjectName("page_2") self.gridLayout_4 = QtWidgets.QGridLayout(self.page_2) self.gridLayout_4.setObjectName("gridLayout_4") - self.label_7 = QtWidgets.QLabel(self.page_2) + self.label_7 = QtWidgets.QLabel(parent=self.page_2) self.label_7.setObjectName("label_7") self.gridLayout_4.addWidget(self.label_7, 0, 0, 1, 1) - self.sbJenks_thresh = QtWidgets.QDoubleSpinBox(self.page_2) + self.sbJenks_thresh = QtWidgets.QDoubleSpinBox(parent=self.page_2) self.sbJenks_thresh.setDecimals(4) self.sbJenks_thresh.setMaximum(9999999.9999) self.sbJenks_thresh.setProperty("value", 0.0001) self.sbJenks_thresh.setObjectName("sbJenks_thresh") self.gridLayout_4.addWidget(self.sbJenks_thresh, 0, 1, 1, 1) - self.label_8 = QtWidgets.QLabel(self.page_2) + self.label_8 = QtWidgets.QLabel(parent=self.page_2) self.label_8.setObjectName("label_8") self.gridLayout_4.addWidget(self.label_8, 1, 0, 1, 1) - self.sbJenks_angle = QtWidgets.QDoubleSpinBox(self.page_2) + self.sbJenks_angle = QtWidgets.QDoubleSpinBox(parent=self.page_2) self.sbJenks_angle.setMaximum(180.0) self.sbJenks_angle.setProperty("value", 3.0) self.sbJenks_angle.setObjectName("sbJenks_angle") @@ -139,20 +138,20 @@ def setupUi(self, generalizer): self.page_13.setObjectName("page_13") self.gridLayout_3 = QtWidgets.QGridLayout(self.page_13) self.gridLayout_3.setObjectName("gridLayout_3") - self.label_13 = QtWidgets.QLabel(self.page_13) + self.label_13 = QtWidgets.QLabel(parent=self.page_13) self.label_13.setObjectName("label_13") self.gridLayout_3.addWidget(self.label_13, 0, 0, 1, 1) - self.sbLang_thresh = QtWidgets.QDoubleSpinBox(self.page_13) + self.sbLang_thresh = QtWidgets.QDoubleSpinBox(parent=self.page_13) self.sbLang_thresh.setDecimals(4) self.sbLang_thresh.setMinimum(0.0001) self.sbLang_thresh.setMaximum(9999999.9999) self.sbLang_thresh.setProperty("value", 0.0001) self.sbLang_thresh.setObjectName("sbLang_thresh") self.gridLayout_3.addWidget(self.sbLang_thresh, 0, 1, 1, 1) - self.label_19 = QtWidgets.QLabel(self.page_13) + self.label_19 = QtWidgets.QLabel(parent=self.page_13) self.label_19.setObjectName("label_19") self.gridLayout_3.addWidget(self.label_19, 1, 0, 1, 1) - self.sbLang_LA = QtWidgets.QSpinBox(self.page_13) + self.sbLang_LA = QtWidgets.QSpinBox(parent=self.page_13) self.sbLang_LA.setMinimum(1) self.sbLang_LA.setMaximum(9999) self.sbLang_LA.setProperty("value", 8) @@ -163,10 +162,10 @@ def setupUi(self, generalizer): self.page_4.setObjectName("page_4") self.gridLayout_6 = QtWidgets.QGridLayout(self.page_4) self.gridLayout_6.setObjectName("gridLayout_6") - self.label_11 = QtWidgets.QLabel(self.page_4) + self.label_11 = QtWidgets.QLabel(parent=self.page_4) self.label_11.setObjectName("label_11") self.gridLayout_6.addWidget(self.label_11, 0, 0, 1, 1) - self.sbRW_thresh = QtWidgets.QDoubleSpinBox(self.page_4) + self.sbRW_thresh = QtWidgets.QDoubleSpinBox(parent=self.page_4) self.sbRW_thresh.setDecimals(4) self.sbRW_thresh.setMaximum(9999999.9999) self.sbRW_thresh.setProperty("value", 0.0001) @@ -177,10 +176,10 @@ def setupUi(self, generalizer): self.page_14.setObjectName("page_14") self.gridLayout_14 = QtWidgets.QGridLayout(self.page_14) self.gridLayout_14.setObjectName("gridLayout_14") - self.label_20 = QtWidgets.QLabel(self.page_14) + self.label_20 = QtWidgets.QLabel(parent=self.page_14) self.label_20.setObjectName("label_20") self.gridLayout_14.addWidget(self.label_20, 0, 0, 1, 1) - self.sbReduction_thresh = QtWidgets.QDoubleSpinBox(self.page_14) + self.sbReduction_thresh = QtWidgets.QDoubleSpinBox(parent=self.page_14) self.sbReduction_thresh.setDecimals(4) self.sbReduction_thresh.setMinimum(0.0001) self.sbReduction_thresh.setMaximum(9999999.9999) @@ -191,10 +190,10 @@ def setupUi(self, generalizer): self.page_15.setObjectName("page_15") self.gridLayout_15 = QtWidgets.QGridLayout(self.page_15) self.gridLayout_15.setObjectName("gridLayout_15") - self.label_21 = QtWidgets.QLabel(self.page_15) + self.label_21 = QtWidgets.QLabel(parent=self.page_15) self.label_21.setObjectName("label_21") self.gridLayout_15.addWidget(self.label_21, 0, 0, 1, 1) - self.sbBoyle_LA = QtWidgets.QSpinBox(self.page_15) + self.sbBoyle_LA = QtWidgets.QSpinBox(parent=self.page_15) self.sbBoyle_LA.setMinimum(2) self.sbBoyle_LA.setMaximum(999) self.sbBoyle_LA.setProperty("value", 7) @@ -205,18 +204,18 @@ def setupUi(self, generalizer): self.page_16.setObjectName("page_16") self.gridLayout_16 = QtWidgets.QGridLayout(self.page_16) self.gridLayout_16.setObjectName("gridLayout_16") - self.label_22 = QtWidgets.QLabel(self.page_16) + self.label_22 = QtWidgets.QLabel(parent=self.page_16) self.label_22.setObjectName("label_22") self.gridLayout_16.addWidget(self.label_22, 0, 0, 1, 1) - self.sbChaiken_level = QtWidgets.QSpinBox(self.page_16) + self.sbChaiken_level = QtWidgets.QSpinBox(parent=self.page_16) self.sbChaiken_level.setMinimum(1) self.sbChaiken_level.setMaximum(99) self.sbChaiken_level.setObjectName("sbChaiken_level") self.gridLayout_16.addWidget(self.sbChaiken_level, 0, 1, 1, 1) - self.label_23 = QtWidgets.QLabel(self.page_16) + self.label_23 = QtWidgets.QLabel(parent=self.page_16) self.label_23.setObjectName("label_23") self.gridLayout_16.addWidget(self.label_23, 1, 0, 1, 1) - self.sbChaiken_weight = QtWidgets.QDoubleSpinBox(self.page_16) + self.sbChaiken_weight = QtWidgets.QDoubleSpinBox(parent=self.page_16) self.sbChaiken_weight.setMinimum(1.0) self.sbChaiken_weight.setProperty("value", 3.0) self.sbChaiken_weight.setObjectName("sbChaiken_weight") @@ -226,17 +225,17 @@ def setupUi(self, generalizer): self.page.setObjectName("page") self.gridLayout = QtWidgets.QGridLayout(self.page) self.gridLayout.setObjectName("gridLayout") - self.label_2 = QtWidgets.QLabel(self.page) + self.label_2 = QtWidgets.QLabel(parent=self.page) self.label_2.setObjectName("label_2") self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1) - self.label_4 = QtWidgets.QLabel(self.page) + self.label_4 = QtWidgets.QLabel(parent=self.page) self.label_4.setObjectName("label_4") self.gridLayout.addWidget(self.label_4, 1, 0, 1, 1) - self.sbHermite_tightness = QtWidgets.QDoubleSpinBox(self.page) + self.sbHermite_tightness = QtWidgets.QDoubleSpinBox(parent=self.page) self.sbHermite_tightness.setProperty("value", 0.5) self.sbHermite_tightness.setObjectName("sbHermite_tightness") self.gridLayout.addWidget(self.sbHermite_tightness, 1, 1, 1, 1) - self.sbHermite_steps = QtWidgets.QDoubleSpinBox(self.page) + self.sbHermite_steps = QtWidgets.QDoubleSpinBox(parent=self.page) self.sbHermite_steps.setDecimals(4) self.sbHermite_steps.setMaximum(9999999.9999) self.sbHermite_steps.setProperty("value", 0.0001) @@ -247,18 +246,18 @@ def setupUi(self, generalizer): self.page_17.setObjectName("page_17") self.gridLayout_17 = QtWidgets.QGridLayout(self.page_17) self.gridLayout_17.setObjectName("gridLayout_17") - self.label_24 = QtWidgets.QLabel(self.page_17) + self.label_24 = QtWidgets.QLabel(parent=self.page_17) self.label_24.setObjectName("label_24") self.gridLayout_17.addWidget(self.label_24, 0, 0, 1, 1) - self.sbDist_slide = QtWidgets.QDoubleSpinBox(self.page_17) + self.sbDist_slide = QtWidgets.QDoubleSpinBox(parent=self.page_17) self.sbDist_slide.setSingleStep(0.1) self.sbDist_slide.setProperty("value", 0.5) self.sbDist_slide.setObjectName("sbDist_slide") self.gridLayout_17.addWidget(self.sbDist_slide, 0, 1, 1, 1) - self.label_25 = QtWidgets.QLabel(self.page_17) + self.label_25 = QtWidgets.QLabel(parent=self.page_17) self.label_25.setObjectName("label_25") self.gridLayout_17.addWidget(self.label_25, 1, 0, 1, 1) - self.sbDist_LA = QtWidgets.QSpinBox(self.page_17) + self.sbDist_LA = QtWidgets.QSpinBox(parent=self.page_17) self.sbDist_LA.setMinimum(3) self.sbDist_LA.setMaximum(999) self.sbDist_LA.setSingleStep(2) @@ -270,18 +269,18 @@ def setupUi(self, generalizer): self.page_18.setObjectName("page_18") self.gridLayout_18 = QtWidgets.QGridLayout(self.page_18) self.gridLayout_18.setObjectName("gridLayout_18") - self.label_26 = QtWidgets.QLabel(self.page_18) + self.label_26 = QtWidgets.QLabel(parent=self.page_18) self.label_26.setObjectName("label_26") self.gridLayout_18.addWidget(self.label_26, 0, 0, 1, 1) - self.sbSlide_slide = QtWidgets.QDoubleSpinBox(self.page_18) + self.sbSlide_slide = QtWidgets.QDoubleSpinBox(parent=self.page_18) self.sbSlide_slide.setSingleStep(0.1) self.sbSlide_slide.setProperty("value", 0.5) self.sbSlide_slide.setObjectName("sbSlide_slide") self.gridLayout_18.addWidget(self.sbSlide_slide, 0, 1, 1, 1) - self.label_27 = QtWidgets.QLabel(self.page_18) + self.label_27 = QtWidgets.QLabel(parent=self.page_18) self.label_27.setObjectName("label_27") self.gridLayout_18.addWidget(self.label_27, 1, 0, 1, 1) - self.sbSlide_LA = QtWidgets.QSpinBox(self.page_18) + self.sbSlide_LA = QtWidgets.QSpinBox(parent=self.page_18) self.sbSlide_LA.setMinimum(3) self.sbSlide_LA.setMaximum(999) self.sbSlide_LA.setSingleStep(2) @@ -293,18 +292,18 @@ def setupUi(self, generalizer): self.page_3.setObjectName("page_3") self.gridLayout_5 = QtWidgets.QGridLayout(self.page_3) self.gridLayout_5.setObjectName("gridLayout_5") - self.label_9 = QtWidgets.QLabel(self.page_3) + self.label_9 = QtWidgets.QLabel(parent=self.page_3) self.label_9.setObjectName("label_9") self.gridLayout_5.addWidget(self.label_9, 0, 0, 1, 1) - self.sbSnakes_alpha = QtWidgets.QDoubleSpinBox(self.page_3) + self.sbSnakes_alpha = QtWidgets.QDoubleSpinBox(parent=self.page_3) self.sbSnakes_alpha.setMaximum(9999.99) self.sbSnakes_alpha.setProperty("value", 1.0) self.sbSnakes_alpha.setObjectName("sbSnakes_alpha") self.gridLayout_5.addWidget(self.sbSnakes_alpha, 0, 1, 1, 1) - self.label_10 = QtWidgets.QLabel(self.page_3) + self.label_10 = QtWidgets.QLabel(parent=self.page_3) self.label_10.setObjectName("label_10") self.gridLayout_5.addWidget(self.label_10, 1, 0, 1, 1) - self.sbSnakes_beta = QtWidgets.QDoubleSpinBox(self.page_3) + self.sbSnakes_beta = QtWidgets.QDoubleSpinBox(parent=self.page_3) self.sbSnakes_beta.setMaximum(9999.99) self.sbSnakes_beta.setProperty("value", 0.5) self.sbSnakes_beta.setObjectName("sbSnakes_beta") @@ -312,15 +311,15 @@ def setupUi(self, generalizer): self.stackOptions.addWidget(self.page_3) self.gridLayout_2.addWidget(self.stackOptions, 1, 0, 1, 2) self.gridLayout_19.addWidget(self.groupBox, 2, 0, 1, 2) - self.eOutput = QtWidgets.QLineEdit(self.page_6) + self.eOutput = QtWidgets.QLineEdit(parent=self.page_6) self.eOutput.setEnabled(False) self.eOutput.setObjectName("eOutput") self.gridLayout_19.addWidget(self.eOutput, 4, 0, 1, 1) - self.bBrowse = QtWidgets.QPushButton(self.page_6) + self.bBrowse = QtWidgets.QPushButton(parent=self.page_6) self.bBrowse.setEnabled(False) self.bBrowse.setObjectName("bBrowse") self.gridLayout_19.addWidget(self.bBrowse, 4, 1, 1, 1) - self.cbOutFile = QtWidgets.QCheckBox(self.page_6) + self.cbOutFile = QtWidgets.QCheckBox(parent=self.page_6) self.cbOutFile.setObjectName("cbOutFile") self.gridLayout_19.addWidget(self.cbOutFile, 3, 0, 1, 1) self.stackBatch.addWidget(self.page_6) @@ -328,16 +327,16 @@ def setupUi(self, generalizer): self.page_10.setObjectName("page_10") self.gridLayout_21 = QtWidgets.QGridLayout(self.page_10) self.gridLayout_21.setObjectName("gridLayout_21") - self.lstLayers = QtWidgets.QListWidget(self.page_10) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + self.lstLayers = QtWidgets.QListWidget(parent=self.page_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.lstLayers.sizePolicy().hasHeightForWidth()) self.lstLayers.setSizePolicy(sizePolicy) self.lstLayers.setObjectName("lstLayers") self.gridLayout_21.addWidget(self.lstLayers, 1, 0, 1, 1) - self.tblBatchAlg = QtWidgets.QTableWidget(self.page_10) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + self.tblBatchAlg = QtWidgets.QTableWidget(parent=self.page_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.tblBatchAlg.sizePolicy().hasHeightForWidth()) @@ -352,30 +351,30 @@ def setupUi(self, generalizer): item = QtWidgets.QTableWidgetItem() self.tblBatchAlg.setHorizontalHeaderItem(2, item) self.gridLayout_21.addWidget(self.tblBatchAlg, 3, 0, 3, 1) - self.bAddAlg = QtWidgets.QPushButton(self.page_10) + self.bAddAlg = QtWidgets.QPushButton(parent=self.page_10) self.bAddAlg.setObjectName("bAddAlg") self.gridLayout_21.addWidget(self.bAddAlg, 3, 1, 1, 1) - self.bDelAlg = QtWidgets.QPushButton(self.page_10) + self.bDelAlg = QtWidgets.QPushButton(parent=self.page_10) self.bDelAlg.setObjectName("bDelAlg") self.gridLayout_21.addWidget(self.bDelAlg, 4, 1, 1, 1) - self.bEditAlg = QtWidgets.QPushButton(self.page_10) + self.bEditAlg = QtWidgets.QPushButton(parent=self.page_10) self.bEditAlg.setObjectName("bEditAlg") self.gridLayout_21.addWidget(self.bEditAlg, 5, 1, 1, 1) - self.eDir = QtWidgets.QLineEdit(self.page_10) + self.eDir = QtWidgets.QLineEdit(parent=self.page_10) self.eDir.setEnabled(False) self.eDir.setObjectName("eDir") self.gridLayout_21.addWidget(self.eDir, 7, 0, 1, 1) - self.bBrowseDir = QtWidgets.QPushButton(self.page_10) + self.bBrowseDir = QtWidgets.QPushButton(parent=self.page_10) self.bBrowseDir.setEnabled(False) self.bBrowseDir.setObjectName("bBrowseDir") self.gridLayout_21.addWidget(self.bBrowseDir, 7, 1, 1, 1) - self.cbOutDir = QtWidgets.QCheckBox(self.page_10) + self.cbOutDir = QtWidgets.QCheckBox(parent=self.page_10) self.cbOutDir.setObjectName("cbOutDir") self.gridLayout_21.addWidget(self.cbOutDir, 6, 0, 1, 1) - self.label_5 = QtWidgets.QLabel(self.page_10) + self.label_5 = QtWidgets.QLabel(parent=self.page_10) self.label_5.setObjectName("label_5") self.gridLayout_21.addWidget(self.label_5, 2, 0, 1, 1) - self.label_6 = QtWidgets.QLabel(self.page_10) + self.label_6 = QtWidgets.QLabel(parent=self.page_10) self.label_6.setObjectName("label_6") self.gridLayout_21.addWidget(self.label_6, 0, 0, 1, 1) self.stackBatch.addWidget(self.page_10) @@ -387,7 +386,7 @@ def setupUi(self, generalizer): self.stackBatch.setCurrentIndex(0) self.cbAlgorithm.setCurrentIndex(1) self.stackOptions.setCurrentIndex(0) - self.bCancel.clicked.connect(generalizer.close) + self.bCancel.clicked.connect(generalizer.close) # type: ignore QtCore.QMetaObject.connectSlotsByName(generalizer) generalizer.setTabOrder(self.cbBatch, self.cbInput) generalizer.setTabOrder(self.cbInput, self.cbAlgorithm) @@ -429,12 +428,12 @@ def retranslateUi(self, generalizer): self.bCancel.setText(_translate("generalizer", "Close")) self.label.setText(_translate("generalizer", "Input line layer:")) self.groupBox.setTitle(_translate("generalizer", "Options")) - self.label_3.setText(_translate("generalizer", "Alghoritm:")) + self.label_3.setText(_translate("generalizer", "Algorithm:")) self.cbAlgorithm.setItemText(0, _translate("generalizer", "-----Generalizing-----")) self.cbAlgorithm.setItemText(1, _translate("generalizer", "Remove small objects")) self.cbAlgorithm.setItemText(2, _translate("generalizer", "-----Simplifying-----")) self.cbAlgorithm.setItemText(3, _translate("generalizer", "Douglas-Peucker Algorithm")) - self.cbAlgorithm.setItemText(4, _translate("generalizer", "Jenk\'s Algorithm")) + self.cbAlgorithm.setItemText(4, _translate("generalizer", "Jenks\' Algorithm")) self.cbAlgorithm.setItemText(5, _translate("generalizer", "Lang Algorithm")) self.cbAlgorithm.setItemText(6, _translate("generalizer", "Reumann-Witkam Algorithm")) self.cbAlgorithm.setItemText(7, _translate("generalizer", "Vertex Reduction")) @@ -450,14 +449,14 @@ def retranslateUi(self, generalizer): self.label_7.setText(_translate("generalizer", "Threshold:")) self.label_8.setText(_translate("generalizer", "Angle threshold:")) self.label_13.setText(_translate("generalizer", "Threshold:")) - self.label_19.setText(_translate("generalizer", "Looka ahead:")) + self.label_19.setText(_translate("generalizer", "Look ahead:")) self.label_11.setText(_translate("generalizer", "Threshold:")) self.label_20.setText(_translate("generalizer", "Threshold:")) self.label_21.setText(_translate("generalizer", "Look ahead:")) self.label_22.setText(_translate("generalizer", "Level:")) self.label_23.setText(_translate("generalizer", "Weight:")) self.label_2.setText(_translate("generalizer", "Threshold:")) - self.label_4.setText(_translate("generalizer", "Thightness:")) + self.label_4.setText(_translate("generalizer", "Tightness:")) self.label_24.setText(_translate("generalizer", "Slide:")) self.label_25.setText(_translate("generalizer", "Look ahead:")) self.label_26.setText(_translate("generalizer", "Slide:")) diff --git a/ui_generalizer.ui b/ui_generalizer.ui index 06189d1..d79eb2a 100644 --- a/ui_generalizer.ui +++ b/ui_generalizer.ui @@ -7,7 +7,7 @@ 0 0 493 - 348 + 427 @@ -86,7 +86,7 @@ - Alghoritm: + Algorithm: @@ -123,7 +123,7 @@ - Jenk's Algorithm + Jenks' Algorithm @@ -181,7 +181,7 @@ - 0 + 7 @@ -309,7 +309,7 @@ - Looka ahead: + Look ahead: @@ -450,7 +450,7 @@ - Thightness: + Tightness: From 178a2e90288f2e6f0606e6d7e79173639c28894d Mon Sep 17 00:00:00 2001 From: kikislater Date: Tue, 12 May 2026 21:50:09 +0400 Subject: [PATCH 41/43] Add compatibility with QGIS4 --- generalizer_algorithms.py | 500 ++++++++++++++++++++++++++++++++++++++ generalizer_provider.py | 54 ++++ 2 files changed, 554 insertions(+) create mode 100644 generalizer_algorithms.py create mode 100644 generalizer_provider.py diff --git a/generalizer_algorithms.py b/generalizer_algorithms.py new file mode 100644 index 0000000..e945f4f --- /dev/null +++ b/generalizer_algorithms.py @@ -0,0 +1,500 @@ +from qgis.core import ( + QgsProcessing, + QgsProcessingAlgorithm, + QgsProcessingParameterFeatureSource, + QgsProcessingParameterFeatureSink, + QgsProcessingParameterNumber, + QgsProcessingUtils, + QgsFeatureSink, + QgsWkbTypes, + QgsGeometry, + QgsFeature, + QgsPointXY, + QgsPoint, + QgsProcessingException, + Qgis, +) +from qgis.PyQt.QtGui import QIcon +import os + +from . import smooth, simplify, points as pts_module + + +def _icon(): + return QIcon(os.path.join(os.path.dirname(__file__), 'icon.png')) + + +def _layer_to_line_pnts(geom_part): + """Converts a list of QgsPointXY (QGIS 4) or tuples into line_pnts.""" + return pts_module.Vect_new_line_struct(geom_part) + + +def _process_layer(source, sink, feedback, process_func, **kwargs): + """A common loop over all features, applying process_func to each one.""" + features = list(source.getFeatures()) + total = len(features) + for i, feat in enumerate(features): + if feedback.isCanceled(): + break + feedback.setProgress(int(i / total * 100)) + + geom = feat.geometry() + out_feat = QgsFeature(feat) + + if geom is None or geom.isEmpty(): + sink.addFeature(out_feat, QgsFeatureSink.Flag.FastInsert) + continue + + if geom.isMultipart(): + parts = geom.asMultiPolyline() + new_parts = [] + for part in parts: + p = process_func(part, **kwargs) + coords = [QgsPointXY(p.x[n], p.y[n]) for n in range(p.n_points)] + if len(coords) > 1: + new_parts.append(coords) + if len(new_parts) > 1: + out_feat.setGeometry(QgsGeometry.fromMultiPolylineXY(new_parts)) + elif len(new_parts) == 1: + out_feat.setGeometry(QgsGeometry.fromPolylineXY(new_parts[0])) + else: + continue + else: + part = geom.asPolyline() + p = process_func(part, **kwargs) + coords = [QgsPointXY(p.x[n], p.y[n]) for n in range(p.n_points)] + if len(coords) < 2: + continue + out_feat.setGeometry(QgsGeometry.fromPolylineXY(coords)) + + sink.addFeature(out_feat, QgsFeatureSink.Flag.FastInsert) + + +def _run_remove(part, **kw): + p = pts_module.Vect_new_line_struct(part) + p1 = pts_module.point(); p2 = pts_module.point() + length = 0. + for i in range(p.n_points - 1): + pts_module.point_assign(p, i, p1) + pts_module.point_assign(p, i + 1, p2) + length += pts_module.point_dist(p1, p2) + if length < kw['threshold']: + p.x = []; p.y = []; p.n_points = 0 + return p + +def _run_dp(part, **kw): + l_tuples = [(pt.x(), pt.y()) if hasattr(pt, 'x') else (pt[0], pt[1]) for pt in part] + tmp = simplify.douglas_peucker(l_tuples, kw['threshold']) + return pts_module.Vect_new_line_struct(tmp) + +def _run_jenks(part, **kw): + p = pts_module.Vect_new_line_struct(part) + simplify.jenks(p, kw['threshold'], kw['angle_threshold']) + return p + +def _run_lang(part, **kw): + p = pts_module.Vect_new_line_struct(part) + simplify.lang(p, kw['threshold'], kw['look_ahead']) + return p + +def _run_rw(part, **kw): + p = pts_module.Vect_new_line_struct(part) + simplify.reumann_witkam(p, kw['threshold']) + return p + +def _run_reduction(part, **kw): + p = pts_module.Vect_new_line_struct(part) + simplify.vertex_reduction(p, kw['threshold']) + return p + +def _run_boyle(part, **kw): + p = pts_module.Vect_new_line_struct(part) + smooth.boyle(p, kw['look_ahead']) + return p + +def _run_chaiken(part, **kw): + p = pts_module.Vect_new_line_struct(part) + smooth.chaiken(p, kw['level'], kw['weight']) + return p + +def _run_hermite(part, **kw): + p = pts_module.Vect_new_line_struct(part) + smooth.hermite(p, kw['threshold'], kw['tightness']) + return p + +def _run_distance(part, **kw): + p = pts_module.Vect_new_line_struct(part) + smooth.distance_weighting(p, kw['slide'], kw['look_ahead']) + return p + +def _run_sliding(part, **kw): + p = pts_module.Vect_new_line_struct(part) + smooth.sliding_averaging(p, kw['slide'], kw['look_ahead']) + return p + +def _run_snakes(part, **kw): + p = pts_module.Vect_new_line_struct(part) + smooth.snakes(p, kw['alpha'], kw['beta']) + return p + + +class _BaseGeneralizerAlgorithm(QgsProcessingAlgorithm): + INPUT = 'INPUT' + OUTPUT = 'OUTPUT' + + def icon(self): + return _icon() + + def group(self): + return self.groupName() + + def groupId(self): + return self.group().lower().replace(' ', '_').replace("'", '') + + def groupName(self): + raise NotImplementedError + + def createInstance(self): + return self.__class__() + + def _add_io_params(self): + self.addParameter(QgsProcessingParameterFeatureSource( + self.INPUT, 'Input line layer', + [QgsProcessing.TypeVectorLine])) + self.addParameter(QgsProcessingParameterFeatureSink( + self.OUTPUT, 'Output layer')) + + def processAlgorithm(self, parameters, context, feedback): + source = self.parameterAsSource(parameters, self.INPUT, context) + if source is None: + raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) + + (sink, dest_id) = self.parameterAsSink( + parameters, self.OUTPUT, context, + source.fields(), source.wkbType(), source.sourceCrs()) + if sink is None: + raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) + + kwargs = self._get_kwargs(parameters, context) + _process_layer(source, sink, feedback, self._run_func, **kwargs) + return {self.OUTPUT: dest_id} + + def _get_kwargs(self, parameters, context): + raise NotImplementedError + + def _run_func(self, part, **kw): + raise NotImplementedError + + +class RemoveSmallObjectsAlgorithm(_BaseGeneralizerAlgorithm): + THRESHOLD = 'THRESHOLD' + + def name(self): return 'remove_small_objects' + def displayName(self): return 'Remove small objects' + def groupName(self): return 'Generalize' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.THRESHOLD, 'Threshold', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0001, defaultValue=1.0)) + + def _get_kwargs(self, p, c): + return {'threshold': self.parameterAsDouble(p, self.THRESHOLD, c)} + + def _run_func(self, part, **kw): return _run_remove(part, **kw) + + def shortHelpString(self): + return 'Removes line features shorter than the threshold distance.' + + +class DouglasPeuckerAlgorithm(_BaseGeneralizerAlgorithm): + THRESHOLD = 'THRESHOLD' + + def name(self): return 'douglas_peucker' + def displayName(self): return 'Douglas-Peucker' + def groupName(self): return 'Simplify' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.THRESHOLD, 'Threshold', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0001, defaultValue=1.0)) + + def _get_kwargs(self, p, c): + return {'threshold': self.parameterAsDouble(p, self.THRESHOLD, c)} + + def _run_func(self, part, **kw): return _run_dp(part, **kw) + + def shortHelpString(self): + return 'Simplifies lines using the Douglas-Peucker algorithm. Higher threshold = more simplification.' + + +class JenksAlgorithm(_BaseGeneralizerAlgorithm): + THRESHOLD = 'THRESHOLD' + ANGLE_THRESHOLD = 'ANGLE_THRESHOLD' + + def name(self): return 'jenks' + def displayName(self): return "Jenks' algorithm" + def groupName(self): return 'Simplify' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.THRESHOLD, 'Threshold', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0, defaultValue=1.0)) + self.addParameter(QgsProcessingParameterNumber( + self.ANGLE_THRESHOLD, 'Angle threshold (degrees)', + type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0, maxValue=180.0, defaultValue=3.0)) + + def _get_kwargs(self, p, c): + return { + 'threshold': self.parameterAsDouble(p, self.THRESHOLD, c), + 'angle_threshold': self.parameterAsDouble(p, self.ANGLE_THRESHOLD, c), + } + + def _run_func(self, part, **kw): return _run_jenks(part, **kw) + + def shortHelpString(self): + return "Simplifies lines using Jenks' algorithm." + + +class LangAlgorithm(_BaseGeneralizerAlgorithm): + THRESHOLD = 'THRESHOLD' + LOOK_AHEAD = 'LOOK_AHEAD' + + def name(self): return 'lang' + def displayName(self): return 'Lang algorithm' + def groupName(self): return 'Simplify' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.THRESHOLD, 'Threshold', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0001, defaultValue=1.0)) + self.addParameter(QgsProcessingParameterNumber( + self.LOOK_AHEAD, 'Look ahead', type=QgsProcessingParameterNumber.Type.Integer, + minValue=1, defaultValue=8)) + + def _get_kwargs(self, p, c): + return { + 'threshold': self.parameterAsDouble(p, self.THRESHOLD, c), + 'look_ahead': self.parameterAsInt(p, self.LOOK_AHEAD, c), + } + + def _run_func(self, part, **kw): return _run_lang(part, **kw) + + def shortHelpString(self): + return 'Simplifies lines using the Lang algorithm.' + + +class ReumannWitkamAlgorithm(_BaseGeneralizerAlgorithm): + THRESHOLD = 'THRESHOLD' + + def name(self): return 'reumann_witkam' + def displayName(self): return 'Reumann-Witkam algorithm' + def groupName(self): return 'Simplify' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.THRESHOLD, 'Threshold', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0001, defaultValue=1.0)) + + def _get_kwargs(self, p, c): + return {'threshold': self.parameterAsDouble(p, self.THRESHOLD, c)} + + def _run_func(self, part, **kw): return _run_rw(part, **kw) + + def shortHelpString(self): + return 'Simplifies lines using the Reumann-Witkam algorithm.' + + +class VertexReductionAlgorithm(_BaseGeneralizerAlgorithm): + THRESHOLD = 'THRESHOLD' + + def name(self): return 'vertex_reduction' + def displayName(self): return 'Vertex reduction' + def groupName(self): return 'Simplify' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.THRESHOLD, 'Threshold', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0001, defaultValue=1.0)) + + def _get_kwargs(self, p, c): + return {'threshold': self.parameterAsDouble(p, self.THRESHOLD, c)} + + def _run_func(self, part, **kw): return _run_reduction(part, **kw) + + def shortHelpString(self): + return 'Removes vertices closer than the threshold distance.' + + +class BoyleAlgorithm(_BaseGeneralizerAlgorithm): + LOOK_AHEAD = 'LOOK_AHEAD' + + def name(self): return 'boyle' + def displayName(self): return "Boyle's forward-looking algorithm" + def groupName(self): return 'Smooth' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.LOOK_AHEAD, 'Look ahead', type=QgsProcessingParameterNumber.Type.Integer, + minValue=2, defaultValue=7)) + + def _get_kwargs(self, p, c): + return {'look_ahead': self.parameterAsInt(p, self.LOOK_AHEAD, c)} + + def _run_func(self, part, **kw): return _run_boyle(part, **kw) + + def shortHelpString(self): + return "Smooths lines using Boyle's forward-looking algorithm." + + +class ChaikenAlgorithm(_BaseGeneralizerAlgorithm): + LEVEL = 'LEVEL' + WEIGHT = 'WEIGHT' + + def name(self): return 'chaiken' + def displayName(self): return "Chaiken's algorithm" + def groupName(self): return 'Smooth' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.LEVEL, 'Level', type=QgsProcessingParameterNumber.Type.Integer, + minValue=1, defaultValue=1)) + self.addParameter(QgsProcessingParameterNumber( + self.WEIGHT, 'Weight', type=QgsProcessingParameterNumber.Type.Double, + minValue=1.0, defaultValue=3.0)) + + def _get_kwargs(self, p, c): + return { + 'level': self.parameterAsInt(p, self.LEVEL, c), + 'weight': self.parameterAsDouble(p, self.WEIGHT, c), + } + + def _run_func(self, part, **kw): return _run_chaiken(part, **kw) + + def shortHelpString(self): + return "Smooths lines using Chaiken's algorithm (corner cutting)." + + +class HermiteAlgorithm(_BaseGeneralizerAlgorithm): + THRESHOLD = 'THRESHOLD' + TIGHTNESS = 'TIGHTNESS' + + def name(self): return 'hermite' + def displayName(self): return 'Hermite spline interpolation' + def groupName(self): return 'Smooth' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.THRESHOLD, 'Threshold', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0001, defaultValue=1.0)) + self.addParameter(QgsProcessingParameterNumber( + self.TIGHTNESS, 'Tightness', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0, maxValue=1.0, defaultValue=0.5)) + + def _get_kwargs(self, p, c): + return { + 'threshold': self.parameterAsDouble(p, self.THRESHOLD, c), + 'tightness': self.parameterAsDouble(p, self.TIGHTNESS, c), + } + + def _run_func(self, part, **kw): return _run_hermite(part, **kw) + + def shortHelpString(self): + return 'Smooths lines using Hermite spline interpolation.' + + +class DistanceWeightingAlgorithm(_BaseGeneralizerAlgorithm): + SLIDE = 'SLIDE' + LOOK_AHEAD = 'LOOK_AHEAD' + + def name(self): return 'distance_weighting' + def displayName(self): return "McMaster's distance-weighting algorithm" + def groupName(self): return 'Smooth' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.SLIDE, 'Slide', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0, maxValue=1.0, defaultValue=0.5)) + self.addParameter(QgsProcessingParameterNumber( + self.LOOK_AHEAD, 'Look ahead (odd number)', type=QgsProcessingParameterNumber.Type.Integer, + minValue=3, defaultValue=7)) + + def _get_kwargs(self, p, c): + la = self.parameterAsInt(p, self.LOOK_AHEAD, c) + if la % 2 == 0: + la += 1 # forcer impair silencieusement + return {'slide': self.parameterAsDouble(p, self.SLIDE, c), 'look_ahead': la} + + def _run_func(self, part, **kw): return _run_distance(part, **kw) + + def shortHelpString(self): + return "Smooths lines using McMaster's distance-weighting algorithm. Look ahead must be odd." + + +class SlidingAveragingAlgorithm(_BaseGeneralizerAlgorithm): + SLIDE = 'SLIDE' + LOOK_AHEAD = 'LOOK_AHEAD' + + def name(self): return 'sliding_averaging' + def displayName(self): return "McMaster's sliding averaging algorithm" + def groupName(self): return 'Smooth' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.SLIDE, 'Slide', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0, maxValue=1.0, defaultValue=0.5)) + self.addParameter(QgsProcessingParameterNumber( + self.LOOK_AHEAD, 'Look ahead (odd number)', type=QgsProcessingParameterNumber.Type.Integer, + minValue=3, defaultValue=7)) + + def _get_kwargs(self, p, c): + la = self.parameterAsInt(p, self.LOOK_AHEAD, c) + if la % 2 == 0: + la += 1 + return {'slide': self.parameterAsDouble(p, self.SLIDE, c), 'look_ahead': la} + + def _run_func(self, part, **kw): return _run_sliding(part, **kw) + + def shortHelpString(self): + return "Smooths lines using McMaster's sliding averaging algorithm. Look ahead must be odd." + + +class SnakesAlgorithm(_BaseGeneralizerAlgorithm): + ALPHA = 'ALPHA' + BETA = 'BETA' + + def name(self): return 'snakes' + def displayName(self): return 'Snakes algorithm' + def groupName(self): return 'Smooth' + + def initAlgorithm(self, config=None): + self._add_io_params() + self.addParameter(QgsProcessingParameterNumber( + self.ALPHA, 'Alpha', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0, defaultValue=1.0)) + self.addParameter(QgsProcessingParameterNumber( + self.BETA, 'Beta', type=QgsProcessingParameterNumber.Type.Double, + minValue=0.0, defaultValue=0.5)) + + def _get_kwargs(self, p, c): + return { + 'alpha': self.parameterAsDouble(p, self.ALPHA, c), + 'beta': self.parameterAsDouble(p, self.BETA, c), + } + + def _run_func(self, part, **kw): return _run_snakes(part, **kw) + + def shortHelpString(self): + return 'Smooths lines using the Snakes algorithm (slowest but highest quality).' diff --git a/generalizer_provider.py b/generalizer_provider.py new file mode 100644 index 0000000..e84436d --- /dev/null +++ b/generalizer_provider.py @@ -0,0 +1,54 @@ +from qgis.core import QgsProcessingProvider +from qgis.PyQt.QtGui import QIcon +import os + +from .generalizer_algorithms import ( + RemoveSmallObjectsAlgorithm, + DouglasPeuckerAlgorithm, + JenksAlgorithm, + LangAlgorithm, + ReumannWitkamAlgorithm, + VertexReductionAlgorithm, + BoyleAlgorithm, + ChaikenAlgorithm, + HermiteAlgorithm, + DistanceWeightingAlgorithm, + SlidingAveragingAlgorithm, + SnakesAlgorithm, +) + + +class GeneralizerProvider(QgsProcessingProvider): + + def __init__(self): + super().__init__() + + def id(self): + return 'generalizer3' + + def name(self): + return 'Generalizer' + + def longName(self): + return 'Generalizer - line simplification and smoothing' + + def icon(self): + icon_path = os.path.join(os.path.dirname(__file__), 'icon.png') + return QIcon(icon_path) + + def loadAlgorithms(self): + for alg in [ + RemoveSmallObjectsAlgorithm(), + DouglasPeuckerAlgorithm(), + JenksAlgorithm(), + LangAlgorithm(), + ReumannWitkamAlgorithm(), + VertexReductionAlgorithm(), + BoyleAlgorithm(), + ChaikenAlgorithm(), + HermiteAlgorithm(), + DistanceWeightingAlgorithm(), + SlidingAveragingAlgorithm(), + SnakesAlgorithm(), + ]: + self.addAlgorithm(alg) From 519ec2e0bf9e3a929c67e0f7e2ca7c6536786f5d Mon Sep 17 00:00:00 2001 From: kikislater Date: Tue, 12 May 2026 22:03:08 +0400 Subject: [PATCH 42/43] Add LICENSE --- LICENSE | 341 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 341 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..33b3621 --- /dev/null +++ b/LICENSE @@ -0,0 +1,341 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (c) 2019, GISCAN / QGIS + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. From be1b58d5ab3f002dbba3762644a4c1fc2413c0a0 Mon Sep 17 00:00:00 2001 From: Sylvain POULAIN Date: Tue, 12 May 2026 22:11:07 +0400 Subject: [PATCH 43/43] Create codeql.yml --- .github/workflows/codeql.yml | 99 ++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..7f8ac9e --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,99 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: '38 1 * * 2' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: python + build-mode: none + # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - name: Run manual build steps + if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{matrix.language}}"