123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- """
- ***************************************************************************
- Heatmap.py
- ---------------------
- Date : December 2016
- Copyright : (C) 2016 by Nyall Dawson
- Email : nyall dot dawson at gmail dot 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. *
- * *
- ***************************************************************************
- """
- __author__ = 'Nyall Dawson'
- __date__ = 'December 2016'
- __copyright__ = '(C) 2016, Nyall Dawson'
- from processing.gui.wrappers import WidgetWrapper, DIALOG_STANDARD
- from processing.tools import dataobjects
- import os
- from typing import Optional
- from qgis.PyQt import uic
- from qgis.gui import QgsDoubleSpinBox
- from qgis.core import (QgsRectangle,
- QgsProcessingUtils)
- pluginPath = os.path.dirname(__file__)
- WIDGET, BASE = uic.loadUiType(
- os.path.join(pluginPath, 'RasterResolutionWidget.ui'))
- class HeatmapPixelSizeWidget(BASE, WIDGET):
- def __init__(self):
- super().__init__(None)
- self.setupUi(self)
- self.layer_bounds: QgsRectangle = QgsRectangle()
- self.source = None
- self.raster_bounds: QgsRectangle = QgsRectangle()
- self.radius: float = 100
- self.radius_field: Optional[str] = None
- self.mCellXSpinBox.setShowClearButton(False)
- self.mCellYSpinBox.setShowClearButton(False)
- self.mRowsSpinBox.setShowClearButton(False)
- self.mColumnsSpinBox.setShowClearButton(False)
- self.mCellYSpinBox.valueChanged.connect(self.mCellXSpinBox.setValue)
- self.mCellXSpinBox.valueChanged.connect(self.pixelSizeChanged)
- self.mRowsSpinBox.valueChanged.connect(self.rowsChanged)
- self.mColumnsSpinBox.valueChanged.connect(self.columnsChanged)
- def setRadius(self, radius: float):
- self.radius = radius
- self.recalculate_bounds()
- def setRadiusField(self, radius_field: Optional[str]):
- self.radius_field = radius_field
- self.recalculate_bounds()
- def setSource(self, source):
- if not source:
- return
- bounds = source.sourceExtent()
- if bounds.isNull():
- return
- self.source = source
- self.layer_bounds = bounds
- self.recalculate_bounds()
- def recalculate_bounds(self):
- self.raster_bounds = QgsRectangle(self.layer_bounds)
- if not self.source:
- return
- max_radius = self.radius
- if self.radius_field:
- idx = self.source.fields().lookupField(self.radius_field)
- try:
- max_radius = float(self.source.maximumValue(idx))
- except:
- pass
- self.raster_bounds.setXMinimum(self.raster_bounds.xMinimum() - max_radius)
- self.raster_bounds.setYMinimum(self.raster_bounds.yMinimum() - max_radius)
- self.raster_bounds.setXMaximum(self.raster_bounds.xMaximum() + max_radius)
- self.raster_bounds.setYMaximum(self.raster_bounds.yMaximum() + max_radius)
- self.pixelSizeChanged()
- def pixelSizeChanged(self):
- cell_size = self.mCellXSpinBox.value()
- if cell_size <= 0 or self.raster_bounds.isNull():
- return
- self.mCellYSpinBox.blockSignals(True)
- self.mCellYSpinBox.setValue(cell_size)
- self.mCellYSpinBox.blockSignals(False)
- rows = max(round(self.raster_bounds.height() / cell_size) + 1, 1)
- cols = max(round(self.raster_bounds.width() / cell_size) + 1, 1)
- self.mRowsSpinBox.blockSignals(True)
- self.mRowsSpinBox.setValue(rows)
- self.mRowsSpinBox.blockSignals(False)
- self.mColumnsSpinBox.blockSignals(True)
- self.mColumnsSpinBox.setValue(cols)
- self.mColumnsSpinBox.blockSignals(False)
- def rowsChanged(self):
- rows = self.mRowsSpinBox.value()
- if rows <= 0 or self.raster_bounds.isNull():
- return
- cell_size = self.raster_bounds.height() / rows
- if cell_size == 0:
- return
- cols = max(round(self.raster_bounds.width() / cell_size) + 1, 1)
- self.mColumnsSpinBox.blockSignals(True)
- self.mColumnsSpinBox.setValue(cols)
- self.mColumnsSpinBox.blockSignals(False)
- for w in [self.mCellXSpinBox, self.mCellYSpinBox]:
- w.blockSignals(True)
- w.setValue(cell_size)
- w.blockSignals(False)
- def columnsChanged(self):
- cols = self.mColumnsSpinBox.value()
- if cols < 2 or self.raster_bounds.isNull():
- return
- cell_size = self.raster_bounds.width() / (cols - 1)
- if cell_size == 0:
- return
- rows = max(round(self.raster_bounds.height() / cell_size), 1)
- self.mRowsSpinBox.blockSignals(True)
- self.mRowsSpinBox.setValue(rows)
- self.mRowsSpinBox.blockSignals(False)
- for w in [self.mCellXSpinBox, self.mCellYSpinBox]:
- w.blockSignals(True)
- w.setValue(cell_size)
- w.blockSignals(False)
- def setValue(self, value):
- try:
- numeric_value = float(value)
- except:
- return False
- self.mCellXSpinBox.setValue(numeric_value)
- self.mCellYSpinBox.setValue(numeric_value)
- return True
- def value(self):
- return self.mCellXSpinBox.value()
- class HeatmapPixelSizeWidgetWrapper(WidgetWrapper):
- def __init__(self, param, dialog, row=0, col=0, **kwargs):
- super().__init__(param, dialog, row, col, **kwargs)
- self.context = dataobjects.createContext()
- def _panel(self):
- return HeatmapPixelSizeWidget()
- def createWidget(self):
- if self.dialogType == DIALOG_STANDARD:
- return self._panel()
- else:
- w = QgsDoubleSpinBox()
- w.setShowClearButton(False)
- w.setMinimum(0)
- w.setMaximum(99999999999)
- w.setDecimals(6)
- w.setToolTip(self.tr('Resolution of each pixel in output raster, in layer units'))
- return w
- def postInitialize(self, wrappers):
- if self.dialogType != DIALOG_STANDARD:
- return
- for wrapper in wrappers:
- if wrapper.parameterDefinition().name() == self.param.parent_layer:
- self.setSource(wrapper.parameterValue())
- wrapper.widgetValueHasChanged.connect(self.parentLayerChanged)
- elif wrapper.parameterDefinition().name() == self.param.radius_param:
- self.setRadius(wrapper.parameterValue())
- wrapper.widgetValueHasChanged.connect(self.radiusChanged)
- elif wrapper.parameterDefinition().name() == self.param.radius_field_param:
- self.setSource(wrapper.parameterValue())
- wrapper.widgetValueHasChanged.connect(self.radiusFieldChanged)
- def parentLayerChanged(self, wrapper):
- self.setSource(wrapper.parameterValue())
- def setSource(self, source):
- source = QgsProcessingUtils.variantToSource(source, self.context)
- self.widget.setSource(source)
- def radiusChanged(self, wrapper):
- self.setRadius(wrapper.parameterValue())
- def setRadius(self, radius: float):
- self.widget.setRadius(radius)
- def radiusFieldChanged(self, wrapper):
- self.setRadiusField(wrapper.parameterValue())
- def setRadiusField(self, radius_field: Optional[str]):
- self.widget.setRadiusField(radius_field)
- def setValue(self, value):
- return self.widget.setValue(value)
- def value(self):
- return self.widget.value()
|