add cutline option to clipper to fix #3066

git-svn-id: http://svn.osgeo.org/qgis/trunk@15712 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
brushtyler 2011-04-15 17:58:00 +00:00
parent aeb751988b
commit adbcbcbb76
5 changed files with 225 additions and 63 deletions

View File

@ -1,10 +1,6 @@
# -*- coding: utf-8 -*-
# Utility functions
# -------------------------------------------------
# getLastUsedDir()
# setLastUsedDir( QString *file_or_dir path )
# -------------------------------------------------
from PyQt4.QtCore import *
from PyQt4.QtGui import *
@ -137,27 +133,31 @@ class LayerRegistry(QObject):
LayerRegistry.layers = []
self.emit( SIGNAL( "layersChanged" ) )
def getRasterLayers(self):
layers = []
names = []
@classmethod
def isRaster(self, layer):
# only gdal raster layers
if layer.type() != layer.RasterLayer:
return False
if layer.usesProvider() and layer.providerKey() != 'gdal':
return False
return True
for layer in LayerRegistry.layers:
# only gdal raster layers
if layer.type() == layer.RasterLayer:
if layer.usesProvider() and layer.providerKey() != 'gdal':
continue
layers.append(layer)
names.append(layer.name())
return (layers, names)
def getRasterLayers(self):
layers = filter( self.isRaster, LayerRegistry.layers )
names = map( lambda x: x.name(), layers )
return ( layers, names )
@classmethod
def isVector(self, layer):
if layer.type() != layer.VectorLayer:
return False
return True
def getVectorLayers(self):
layers = []
names = []
for layer in LayerRegistry.layers:
if layer.type() == layer.VectorLayer:
layers.append(layer)
names.append(layer.name())
return (layers, names)
layers = filter( self.isVector, LayerRegistry.layers )
names = map( lambda x: x.name(), layers )
return ( layers, names )
def getRasterFiles(path, recursive=False):
rasters = QStringList()
@ -271,6 +271,30 @@ def getRasterSRS( parent, fileName ):
srs = info[ 0 ] + ":" + info[ 1 ]
return srs
def getRasterExtent(parent, fileName):
processSRS = QProcess( parent )
processSRS.start( "gdalinfo", QStringList() << fileName, QIODevice.ReadOnly )
arr = QByteArray()
if processSRS.waitForFinished():
arr = processSRS.readAllStandardOutput()
processSRS.close()
if arr.isEmpty():
return
info = QString( arr ).split( "\n" )
ulCoord = info[ info.indexOf( QRegExp( "^Upper\sLeft.*" ) ) ].simplified()
lrCoord = info[ info.indexOf( QRegExp( "^Lower\sRight.*" ) ) ].simplified()
ulCoord = ulCoord[ulCoord.indexOf( "(" ) + 1 : ulCoord.indexOf( ")" ) - 1].split( "," )
lrCoord = lrCoord[lrCoord.indexOf( "(" ) + 1 : lrCoord.indexOf( ")" ) - 1].split( "," )
xUL = ulCoord[0].toDouble()[0]
yUL = ulCoord[1].toDouble()[0]
xLR = lrCoord[0].toDouble()[0]
yLR = lrCoord[1].toDouble()[0]
return QgsRectangle( xUL, yLR, xLR, yUL )
# This class is used to replace the QFileDialog class.
# Its static methods are used in place of the respective QFileDialog ones to:
# 1. set the last used directory

View File

@ -37,6 +37,7 @@ class GdalToolsBaseDialog(QDialog, Ui_Dialog):
self.connect(self.process, SIGNAL("finished(int, QProcess::ExitStatus)"), self.processFinished)
self.setupUi(self)
self.arguments = QStringList()
self.connect(self.buttonBox, SIGNAL("rejected()"), self.reject)
self.connect(self.buttonBox, SIGNAL("accepted()"), self.accept)
@ -51,19 +52,19 @@ class GdalToolsBaseDialog(QDialog, Ui_Dialog):
self.plugin.setFocus()
self.setWindowTitle(pluginName)
self.setPluginCommand(pluginCommand)
def setPluginCommand(self, cmd):
# on Windows replace the .py with .bat extension
if platform.system() == "Windows" and pluginCommand[-3:] == ".py":
self.command = pluginCommand[:-3] + ".bat"
if platform.system() == "Windows" and cmd[-3:] == ".py":
self.command = cmd[:-3] + ".bat"
else:
self.command = pluginCommand
self.command = cmd
if pluginCommand[-3:] == ".py":
self.helpFileName = pluginCommand[:-3] + ".html"
if cmd[-3:] == ".py":
self.helpFileName = cmd[:-3] + ".html"
else:
self.helpFileName = pluginCommand + ".html"
self.arguments = QStringList()
self.helpFileName = cmd + ".html"
def reject(self):
if self.process.state() != QProcess.NotRunning:

View File

@ -20,34 +20,56 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget):
self.extentSelector.setCanvas(self.canvas)
self.outputFormat = Utils.fillRasterOutputFormat()
self.layers = []
self.maskLayers = []
self.setParamsStatus(
[
(self.inputLayerCombo, [SIGNAL("currentIndexChanged(int)"), SIGNAL("editTextChanged(const QString &)")] ),
(self.outputFileEdit, SIGNAL("textChanged(const QString &)")),
(self.noDataSpin, SIGNAL("valueChanged(int)"), self.noDataCheck),
( self.extentSelector, [SIGNAL("selectionStarted()"), SIGNAL("newExtentDefined()")] )
(self.noDataSpin, SIGNAL("valueChanged(int)"), self.noDataCheck, "1.7.0"),
(self.maskLayerCombo, [SIGNAL("currentIndexChanged(int)"), SIGNAL("editTextChanged(const QString &)")], self.maskModeRadio, "1.6.0"),
( self.extentSelector, [SIGNAL("selectionStarted()"), SIGNAL("newExtentDefined()")] ),
(self.modeStackedWidget, SIGNAL("currentIndexChanged(int)"))
]
)
self.connect(self.selectInputFileButton, SIGNAL("clicked()"), self.fillInputFileEdit)
self.connect(self.selectOutputFileButton, SIGNAL("clicked()"), self.fillOutputFileEdit)
self.connect(self.selectMaskFileButton, SIGNAL("clicked()"), self.fillMaskFileEdit)
self.connect(self.extentSelector, SIGNAL("newExtentDefined()"), self.checkRun)
self.connect(self.extentSelector, SIGNAL("selectionStarted()"), self.checkRun)
self.connect(self.extentModeRadio, SIGNAL("toggled(bool)"), self.switchClippingMode)
def show_(self):
self.extentSelector.start()
self.switchClippingMode()
BasePluginWidget.show_(self)
def onClosing(self):
self.extentSelector.stop()
BasePluginWidget.onClosing(self)
def switchClippingMode(self):
if self.extentModeRadio.isChecked():
index = 0
self.extentSelector.start()
else:
self.extentSelector.stop()
index = 1
self.modeStackedWidget.setCurrentIndex( index )
self.checkRun()
def checkRun(self):
self.base.enableRun( self.extentSelector.getExtent() != None )
if self.extentModeRadio.isChecked():
enabler = self.extentSelector.isCoordsValid()
else:
enabler = not self.getMaskFileName().isEmpty()
self.base.enableRun( enabler )
def onLayersChanged(self):
self.fillInputLayerCombo()
self.fillMaskLayerCombo()
def fillInputLayerCombo(self):
self.inputLayerCombo.clear()
@ -74,12 +96,35 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget):
self.outputFormat = Utils.fillRasterOutputFormat(lastUsedFilter, outputFile)
self.outputFileEdit.setText(outputFile)
def fillMaskLayerCombo(self):
self.maskLayerCombo.clear()
self.maskLayers = filter( lambda x: x.geometryType() == QGis.Polygon, Utils.LayerRegistry.instance().getVectorLayers()[0] )
self.maskLayerCombo.addItems( map( lambda x: x.name(), self.maskLayers ) )
self.checkRun()
def fillMaskFileEdit( self ):
lastUsedFilter = Utils.FileFilter.lastUsedVectorFilter()
maskFile = Utils.FileDialog.getOpenFileName(self, self.tr( "Select the mask file" ), Utils.FileFilter.allVectorsFilter(), lastUsedFilter )
if maskFile.isEmpty():
return
Utils.FileFilter.setLastUsedVectorFilter(lastUsedFilter)
self.maskLayerCombo.setCurrentIndex(-1)
self.maskLayerCombo.setEditText( maskFile )
self.checkRun()
def getArguments(self):
if not self.extentModeRadio.isChecked():
return self.getArgsModeMask()
return self.getArgsModeExtent()
def getArgsModeExtent(self):
self.base.setPluginCommand( "gdal_translate" )
arguments = QStringList()
if self.noDataCheck.isChecked():
arguments << "-a_nodata"
arguments << str(self.noDataSpin.value())
if self.extentSelector.isCoordsValid():
if self.extentModeRadio.isChecked() and self.extentSelector.isCoordsValid():
rect = self.extentSelector.getExtent()
if rect != None:
arguments << "-projwin"
@ -87,6 +132,8 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget):
arguments << str(rect.yMaximum())
arguments << str(rect.xMaximum())
arguments << str(rect.yMinimum())
if Utils.GdalConfig.version() >= "1.7.0":
arguments << "-q"
if not self.getOutputFileName().isEmpty():
arguments << "-of"
arguments << self.outputFormat
@ -94,6 +141,28 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget):
arguments << self.getOutputFileName()
return arguments
def getArgsModeMask(self):
self.base.setPluginCommand( "gdalwarp" )
arguments = QStringList()
if self.noDataCheck.isChecked():
arguments << "-dstnodata"
arguments << str(self.noDataSpin.value())
if self.maskModeRadio.isChecked():
mask = self.getMaskFileName()
if not mask.isEmpty():
arguments << "-q"
arguments << "-cutline"
arguments << mask
arguments << "-dstalpha"
outputFn = self.getOutputFileName()
if not outputFn.isEmpty():
arguments << "-of"
arguments << self.outputFormat
arguments << self.getInputFileName()
arguments << outputFn
return arguments
def getOutputFileName(self):
return self.outputFileEdit.text()
@ -102,6 +171,11 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget):
return self.layers[self.inputLayerCombo.currentIndex()].source()
return self.inputLayerCombo.currentText()
def getMaskFileName(self):
if self.maskLayerCombo.currentIndex() >= 0:
return self.maskLayers[self.maskLayerCombo.currentIndex()].source()
return self.maskLayerCombo.currentText()
def addLayerIntoCanvas(self, fileInfo):
self.iface.addRasterLayer(fileInfo.filePath())

View File

@ -110,29 +110,6 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget):
def addLayerIntoCanvas(self, fileInfo):
self.iface.addRasterLayer(fileInfo.filePath())
def getRectangle( self, file ):
processSRS = QProcess( self )
processSRS.start( "gdalinfo", QStringList() << file, QIODevice.ReadOnly )
arr = QByteArray()
if processSRS.waitForFinished():
arr = processSRS.readAllStandardOutput()
processSRS.close()
if arr.isEmpty():
return None
info = QString( arr ).split( "\n" )
ulCoord = info[ info.indexOf( QRegExp( "^Upper\sLeft.*" ) ) ].simplified()
lrCoord = info[ info.indexOf( QRegExp( "^Lower\sRight.*" ) ) ].simplified()
ulCoord = ulCoord[ulCoord.indexOf( "(" ) + 1 : ulCoord.indexOf( ")" ) - 1].split( "," )
lrCoord = lrCoord[lrCoord.indexOf( "(" ) + 1 : lrCoord.indexOf( ")" ) - 1].split( "," )
xUL = ulCoord[0].toDouble()[0]
yUL = ulCoord[1].toDouble()[0]
xLR = lrCoord[0].toDouble()[0]
yLR = lrCoord[1].toDouble()[0]
return QgsRectangle( xUL, yLR, xLR, yUL )
def getExtent( self ):
files = self.inputFilesEdit.text().split( "," )
@ -140,11 +117,12 @@ class GdalToolsDialog(QWidget, Ui_Widget, BasePluginWidget):
res = rect2 = None
for fileName in files:
if res == None:
res = self.getRectangle( fileName )
res = Utils.getRasterExtent( self, fileName )
continue
rect2 = self.getRectangle( fileName )
rect2 = Utils.getRasterExtent( self, fileName )
if rect2 == None:
continue
res = res.intersect( rect2 )
return res

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>338</width>
<height>172</height>
<height>227</height>
</rect>
</property>
<property name="sizePolicy">
@ -109,11 +109,96 @@
<item>
<widget class="QGroupBox" name="extentGroup">
<property name="title">
<string>Extent</string>
<string>Clipping mode</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="GdalToolsExtentSelector" name="extentSelector" native="true"/>
<widget class="QRadioButton" name="extentModeRadio">
<property name="text">
<string>Extent</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="maskModeRadio">
<property name="text">
<string>Mask layer</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QStackedWidget" name="modeStackedWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page">
<layout class="QGridLayout" name="gridLayout_3">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="GdalToolsExtentSelector" name="extentSelector" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<layout class="QGridLayout" name="gridLayout_4">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QComboBox" name="maskLayerCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="selectMaskFileButton">
<property name="text">
<string>Select...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Mask layer</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>