diff --git a/python/plugins/fTools/tools/doVectorGrid.py b/python/plugins/fTools/tools/doVectorGrid.py index f0afff97d4b0..ccc356c69f30 100644 --- a/python/plugins/fTools/tools/doVectorGrid.py +++ b/python/plugins/fTools/tools/doVectorGrid.py @@ -33,6 +33,7 @@ import ftools_utils from qgis.core import * from ui_frmVectorGrid import Ui_Dialog +import math class Dialog(QDialog, Ui_Dialog): def __init__(self, iface): @@ -44,6 +45,7 @@ def __init__(self, iface): #QObject.connect(self.inShape, SIGNAL("currentIndexChanged(QString)"), self.updateInput) QObject.connect(self.btnUpdate, SIGNAL("clicked()"), self.updateLayer) QObject.connect(self.btnCanvas, SIGNAL("clicked()"), self.updateCanvas) + QObject.connect(self.chkAlign, SIGNAL("toggled(bool)"), self.chkAlignToggled) self.buttonOk = self.buttonBox_2.button( QDialogButtonBox.Ok ) self.setWindowTitle(self.tr("Vector grid")) self.xMin.setValidator(QDoubleValidator(self.xMin)) @@ -57,6 +59,8 @@ def populateLayers( self ): layermap = QgsMapLayerRegistry.instance().mapLayers() for name, layer in layermap.iteritems(): self.inShape.addItem( unicode( layer.name() ) ) + if layer == self.iface.activeLayer(): + self.inShape.setCurrentIndex( self.inShape.count() -1 ) def offset(self, value): if self.chkLock.isChecked(): @@ -66,12 +70,50 @@ def updateLayer( self ): mLayerName = self.inShape.currentText() if not mLayerName == "": mLayer = ftools_utils.getMapLayerByName( unicode( mLayerName ) ) + # get layer extents boundBox = mLayer.extent() + # if "align extents and resolution..." button is checked + if self.chkAlign.isChecked(): + if not mLayer.type() == QgsMapLayer.RasterLayer: + QMessageBox.information(self, self.tr("Vector grid"), self.tr("Please select a raster layer")) + else: + dx = math.fabs(boundBox.xMaximum()-boundBox.xMinimum()) / mLayer.width() + dy = math.fabs(boundBox.yMaximum()-boundBox.yMinimum()) / mLayer.height() + self.spnX.setValue(dx) + self.spnY.setValue(dy) self.updateExtents( boundBox ) def updateCanvas( self ): canvas = self.iface.mapCanvas() boundBox = canvas.extent() + # if "align extents and resolution..." button is checked + if self.chkAlign.isChecked(): + mLayerName = self.inShape.currentText() + if not mLayerName == "": + mLayer = ftools_utils.getMapLayerByName( unicode( mLayerName ) ) + if not mLayer.type() == QgsMapLayer.RasterLayer: + QMessageBox.information(self, self.tr("Vector grid"), self.tr("Please select a raster layer")) + else: + # get extents and pixel size + xMin = boundBox.xMinimum() + yMin = boundBox.yMinimum() + xMax = boundBox.xMaximum() + yMax = boundBox.yMaximum() + boundBox2 = mLayer.extent() + dx = math.fabs(boundBox2.xMaximum()-boundBox2.xMinimum()) / mLayer.width() + dy = math.fabs(boundBox2.yMaximum()-boundBox2.yMinimum()) / mLayer.height() + # get pixels from the raster that are closest to the desired extent + newXMin = self.getClosestPixel( boundBox2.xMinimum(), boundBox.xMinimum(), dx, True ) + newXMax = self.getClosestPixel( boundBox2.xMaximum(), boundBox.xMaximum(), dx, False ) + newYMin = self.getClosestPixel( boundBox2.yMinimum(), boundBox.yMinimum(), dy, True ) + newYMax = self.getClosestPixel( boundBox2.yMaximum(), boundBox.yMaximum(), dy, False ) + # apply new values if found all min/max + if newXMin is not None and newXMax is not None and newYMin is not None and newYMax is not None: + boundBox.set( newXMin, newYMin, newXMax, newYMax ) + self.spnX.setValue(dx) + self.spnY.setValue(dy) + else: + QMessageBox.information(self, self.tr("Vector grid"), self.tr("Unable to compute extents aligned on selected raster layer")) self.updateExtents( boundBox ) def updateExtents( self, boundBox ): @@ -100,7 +142,9 @@ def accept(self): if self.rdoPolygons.isChecked(): polygon = True else: polygon = False self.outShape.clear() + QApplication.setOverrideCursor(Qt.WaitCursor) self.compute( boundBox, xSpace, ySpace, polygon ) + QApplication.restoreOverrideCursor() addToTOC = QMessageBox.question(self, self.tr("Generate Vector Grid"), self.tr("Created output shapefile:\n%1\n\nWould you like to add the new layer to the TOC?").arg(unicode(self.shapefileName)), QMessageBox.Yes, QMessageBox.No, QMessageBox.NoButton) if addToTOC == QMessageBox.Yes: ftools_utils.addShapeToCanvas( self.shapefileName ) @@ -131,8 +175,13 @@ def compute( self, bound, xOffset, yOffset, polygon ): outFeat = QgsFeature() outGeom = QgsGeometry() idVar = 0 - self.progressBar.setRange( 0, 0 ) +# self.progressBar.setRange( 0, 0 ) + self.progressBar.setValue( 0 ) if not polygon: + # counters for progressbar - update every 5% + count = 0 + count_max = (bound.yMaximum() - bound.yMinimum()) / yOffset + count_update = count_max * 0.10 y = bound.yMaximum() while y >= bound.yMinimum(): pt1 = QgsPoint(bound.xMinimum(), y) @@ -144,6 +193,15 @@ def compute( self, bound, xOffset, yOffset, polygon ): writer.addFeature(outFeat) y = y - yOffset idVar = idVar + 1 + count += 1 + if int( math.fmod( count, count_update ) ) == 0: + prog = int( count / count_max * 50 ) + self.progressBar.setValue( prog ) + self.progressBar.setValue( 50 ) + # counters for progressbar - update every 5% + count = 0 + count_max = (bound.xMaximum() - bound.xMinimum()) / xOffset + count_update = count_max * 0.10 x = bound.xMinimum() while x <= bound.xMaximum(): pt1 = QgsPoint(x, bound.yMaximum()) @@ -155,7 +213,15 @@ def compute( self, bound, xOffset, yOffset, polygon ): writer.addFeature(outFeat) x = x + xOffset idVar = idVar + 1 + count += 1 + if int( math.fmod( count, count_update ) ) == 0: + prog = 50 + int( count / count_max * 50 ) + self.progressBar.setValue( prog ) else: + # counters for progressbar - update every 5% + count = 0 + count_max = (bound.yMaximum() - bound.yMinimum()) / yOffset + count_update = count_max * 0.05 y = bound.yMaximum() while y >= bound.yMinimum(): x = bound.xMinimum() @@ -176,7 +242,12 @@ def compute( self, bound, xOffset, yOffset, polygon ): idVar = idVar + 1 x = x + xOffset y = y - yOffset - self.progressBar.setRange( 0, 100 ) + count += 1 + if int( math.fmod( count, count_update ) ) == 0: + prog = int( count / count_max * 100 ) + + self.progressBar.setValue( 100 ) + #self.progressBar.setRange( 0, 100 ) del writer def outFile(self): @@ -185,3 +256,39 @@ def outFile(self): if self.shapefileName is None or self.encoding is None: return self.outShape.setText( QString( self.shapefileName ) ) + + def chkAlignToggled(self): + if self.chkAlign.isChecked(): + self.spnX.setEnabled( False ) + self.lblX.setEnabled( False ) + self.spnY.setEnabled( False ) + self.lblY.setEnabled( False ) + else: + self.spnX.setEnabled( True ) + self.lblX.setEnabled( True ) + self.spnY.setEnabled( not self.chkLock.isChecked() ) + self.lblY.setEnabled( not self.chkLock.isChecked() ) + + def getClosestPixel(self, startVal, targetVal, step, isMin ): + foundVal = None + tmpVal = startVal + # find pixels covering the extent - slighlyt inneficient b/c loop on all elements before xMin + if targetVal < startVal: + backOneStep = not isMin + step = - step + while foundVal is None: + if tmpVal <= targetVal: + if backOneStep: + tmpVal -= step + foundVal = tmpVal + tmpVal += step + else: + backOneStep = isMin + while foundVal is None: + if tmpVal >= targetVal: + if backOneStep: + tmpVal -= step + foundVal = tmpVal + tmpVal += step + return foundVal + diff --git a/python/plugins/fTools/tools/frmVectorGrid.ui b/python/plugins/fTools/tools/frmVectorGrid.ui index f6a0e4d68f5e..2b899b3c007d 100644 --- a/python/plugins/fTools/tools/frmVectorGrid.ui +++ b/python/plugins/fTools/tools/frmVectorGrid.ui @@ -9,8 +9,8 @@ 0 0 - 438 - 459 + 489 + 475 @@ -29,7 +29,7 @@ - + @@ -42,7 +42,7 @@ - + @@ -55,7 +55,7 @@ - + @@ -82,7 +82,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -136,7 +136,7 @@ - + @@ -163,6 +163,13 @@ + + + + Align extents and resolution to selected raster layer + + + @@ -186,7 +193,7 @@ - + X @@ -245,7 +252,7 @@ - + false @@ -279,7 +286,7 @@ Output grid as polygons - true + false @@ -288,6 +295,9 @@ Output grid as lines + + true + @@ -385,7 +395,7 @@ chkLock - clicked(bool) + toggled(bool) spnY setDisabled(bool) @@ -402,7 +412,7 @@ chkLock toggled(bool) - label_8 + lblY setDisabled(bool)