Skip to content
Permalink
Browse files
add cutline option to clipper to fix #3066
git-svn-id: http://svn.osgeo.org/qgis/trunk@15712 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
brushtyler committed Apr 15, 2011
1 parent aeb7519 commit adbcbcbb7660aadc358f1bee535594993704dfd9
@@ -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 @@ def removeAllLayers(self):
LayerRegistry.layers = []
self.emit( SIGNAL( "layersChanged" ) )

@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

def getRasterLayers(self):
layers = []
names = []
layers = filter( self.isRaster, LayerRegistry.layers )
names = map( lambda x: x.name(), layers )
return ( layers, names )

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)
@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
@@ -37,6 +37,7 @@ def __init__(self, parent, iface, pluginBase, pluginName, pluginCommand):
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 @@ def __init__(self, parent, iface, pluginBase, pluginName, pluginCommand):
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:
@@ -20,34 +20,56 @@ def __init__(self, iface):

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,26 +96,73 @@ def fillOutputFileEdit(self):
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"
arguments << str(rect.xMinimum())
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
arguments << self.getInputFileName()
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 @@ def getInputFileName(self):
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())

@@ -110,41 +110,19 @@ def getOutputFileName(self):
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( "," )

i = 0
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

0 comments on commit adbcbcb

Please sign in to comment.