Skip to content

Commit d3b4786

Browse files
author
brushtyler
committed
add cutline option to clipper to fix #3066
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@15712 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 63a2222 commit d3b4786

File tree

5 files changed

+224
-62
lines changed

5 files changed

+224
-62
lines changed

python/plugins/GdalTools/tools/GdalTools_utils.py

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
# -*- coding: utf-8 -*-
22

33
# Utility functions
4-
# -------------------------------------------------
5-
# getLastUsedDir()
6-
# setLastUsedDir( QString *file_or_dir path )
7-
# -------------------------------------------------
84

95
from PyQt4.QtCore import *
106
from PyQt4.QtGui import *
@@ -137,27 +133,31 @@ def removeAllLayers(self):
137133
LayerRegistry.layers = []
138134
self.emit( SIGNAL( "layersChanged" ) )
139135

136+
@classmethod
137+
def isRaster(self, layer):
138+
# only gdal raster layers
139+
if layer.type() != layer.RasterLayer:
140+
return False
141+
if layer.usesProvider() and layer.providerKey() != 'gdal':
142+
return False
143+
return True
144+
140145
def getRasterLayers(self):
141-
layers = []
142-
names = []
146+
layers = filter( self.isRaster, LayerRegistry.layers )
147+
names = map( lambda x: x.name(), layers )
148+
return ( layers, names )
143149

144-
for layer in LayerRegistry.layers:
145-
# only gdal raster layers
146-
if layer.type() == layer.RasterLayer:
147-
if layer.usesProvider() and layer.providerKey() != 'gdal':
148-
continue
149-
layers.append(layer)
150-
names.append(layer.name())
151-
return (layers, names)
150+
@classmethod
151+
def isVector(self, layer):
152+
if layer.type() != layer.VectorLayer:
153+
return False
154+
return True
152155

153156
def getVectorLayers(self):
154-
layers = []
155-
names = []
156-
for layer in LayerRegistry.layers:
157-
if layer.type() == layer.VectorLayer:
158-
layers.append(layer)
159-
names.append(layer.name())
160-
return (layers, names)
157+
layers = filter( self.isVector, LayerRegistry.layers )
158+
names = map( lambda x: x.name(), layers )
159+
return ( layers, names )
160+
161161

162162
def getRasterFiles(path, recursive=False):
163163
rasters = QStringList()
@@ -271,6 +271,30 @@ def getRasterSRS( parent, fileName ):
271271
srs = info[ 0 ] + ":" + info[ 1 ]
272272
return srs
273273

274+
def getRasterExtent(parent, fileName):
275+
processSRS = QProcess( parent )
276+
processSRS.start( "gdalinfo", QStringList() << fileName, QIODevice.ReadOnly )
277+
arr = QByteArray()
278+
if processSRS.waitForFinished():
279+
arr = processSRS.readAllStandardOutput()
280+
processSRS.close()
281+
282+
if arr.isEmpty():
283+
return
284+
285+
info = QString( arr ).split( "\n" )
286+
ulCoord = info[ info.indexOf( QRegExp( "^Upper\sLeft.*" ) ) ].simplified()
287+
lrCoord = info[ info.indexOf( QRegExp( "^Lower\sRight.*" ) ) ].simplified()
288+
ulCoord = ulCoord[ulCoord.indexOf( "(" ) + 1 : ulCoord.indexOf( ")" ) - 1].split( "," )
289+
lrCoord = lrCoord[lrCoord.indexOf( "(" ) + 1 : lrCoord.indexOf( ")" ) - 1].split( "," )
290+
xUL = ulCoord[0].toDouble()[0]
291+
yUL = ulCoord[1].toDouble()[0]
292+
xLR = lrCoord[0].toDouble()[0]
293+
yLR = lrCoord[1].toDouble()[0]
294+
295+
return QgsRectangle( xUL, yLR, xLR, yUL )
296+
297+
274298
# This class is used to replace the QFileDialog class.
275299
# Its static methods are used in place of the respective QFileDialog ones to:
276300
# 1. set the last used directory

python/plugins/GdalTools/tools/dialogBase.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def __init__(self, parent, iface, pluginBase, pluginName, pluginCommand):
3737
self.connect(self.process, SIGNAL("finished(int, QProcess::ExitStatus)"), self.processFinished)
3838

3939
self.setupUi(self)
40+
self.arguments = QStringList()
4041

4142
self.connect(self.buttonBox, SIGNAL("rejected()"), self.reject)
4243
self.connect(self.buttonBox, SIGNAL("accepted()"), self.accept)
@@ -51,19 +52,19 @@ def __init__(self, parent, iface, pluginBase, pluginName, pluginCommand):
5152
self.plugin.setFocus()
5253

5354
self.setWindowTitle(pluginName)
55+
self.setPluginCommand(pluginCommand)
5456

57+
def setPluginCommand(self, cmd):
5558
# on Windows replace the .py with .bat extension
56-
if platform.system() == "Windows" and pluginCommand[-3:] == ".py":
57-
self.command = pluginCommand[:-3] + ".bat"
59+
if platform.system() == "Windows" and cmd[-3:] == ".py":
60+
self.command = cmd[:-3] + ".bat"
5861
else:
59-
self.command = pluginCommand
62+
self.command = cmd
6063

61-
if pluginCommand[-3:] == ".py":
62-
self.helpFileName = pluginCommand[:-3] + ".html"
64+
if cmd[-3:] == ".py":
65+
self.helpFileName = cmd[:-3] + ".html"
6366
else:
64-
self.helpFileName = pluginCommand + ".html"
65-
66-
self.arguments = QStringList()
67+
self.helpFileName = cmd + ".html"
6768

6869
def reject(self):
6970
if self.process.state() != QProcess.NotRunning:

python/plugins/GdalTools/tools/doClipper.py

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,56 @@ def __init__(self, iface):
2020

2121
self.extentSelector.setCanvas(self.canvas)
2222
self.outputFormat = Utils.fillRasterOutputFormat()
23+
self.layers = []
24+
self.maskLayers = []
2325

2426
self.setParamsStatus(
2527
[
2628
(self.inputLayerCombo, [SIGNAL("currentIndexChanged(int)"), SIGNAL("editTextChanged(const QString &)")] ),
2729
(self.outputFileEdit, SIGNAL("textChanged(const QString &)")),
28-
(self.noDataSpin, SIGNAL("valueChanged(int)"), self.noDataCheck),
29-
( self.extentSelector, [SIGNAL("selectionStarted()"), SIGNAL("newExtentDefined()")] )
30+
(self.noDataSpin, SIGNAL("valueChanged(int)"), self.noDataCheck, "1.7.0"),
31+
(self.maskLayerCombo, [SIGNAL("currentIndexChanged(int)"), SIGNAL("editTextChanged(const QString &)")], self.maskModeRadio, "1.6.0"),
32+
( self.extentSelector, [SIGNAL("selectionStarted()"), SIGNAL("newExtentDefined()")] ),
33+
(self.modeStackedWidget, SIGNAL("currentIndexChanged(int)"))
3034
]
3135
)
3236

3337
self.connect(self.selectInputFileButton, SIGNAL("clicked()"), self.fillInputFileEdit)
3438
self.connect(self.selectOutputFileButton, SIGNAL("clicked()"), self.fillOutputFileEdit)
39+
self.connect(self.selectMaskFileButton, SIGNAL("clicked()"), self.fillMaskFileEdit)
3540
self.connect(self.extentSelector, SIGNAL("newExtentDefined()"), self.checkRun)
3641
self.connect(self.extentSelector, SIGNAL("selectionStarted()"), self.checkRun)
3742

43+
self.connect(self.extentModeRadio, SIGNAL("toggled(bool)"), self.switchClippingMode)
44+
3845
def show_(self):
39-
self.extentSelector.start()
46+
self.switchClippingMode()
4047
BasePluginWidget.show_(self)
4148

4249
def onClosing(self):
4350
self.extentSelector.stop()
4451
BasePluginWidget.onClosing(self)
4552

53+
def switchClippingMode(self):
54+
if self.extentModeRadio.isChecked():
55+
index = 0
56+
self.extentSelector.start()
57+
else:
58+
self.extentSelector.stop()
59+
index = 1
60+
self.modeStackedWidget.setCurrentIndex( index )
61+
self.checkRun()
62+
4663
def checkRun(self):
47-
self.base.enableRun( self.extentSelector.getExtent() != None )
64+
if self.extentModeRadio.isChecked():
65+
enabler = self.extentSelector.isCoordsValid()
66+
else:
67+
enabler = not self.getMaskFileName().isEmpty()
68+
self.base.enableRun( enabler )
4869

4970
def onLayersChanged(self):
5071
self.fillInputLayerCombo()
72+
self.fillMaskLayerCombo()
5173

5274
def fillInputLayerCombo(self):
5375
self.inputLayerCombo.clear()
@@ -74,26 +96,73 @@ def fillOutputFileEdit(self):
7496
self.outputFormat = Utils.fillRasterOutputFormat(lastUsedFilter, outputFile)
7597
self.outputFileEdit.setText(outputFile)
7698

99+
def fillMaskLayerCombo(self):
100+
self.maskLayerCombo.clear()
101+
self.maskLayers = filter( lambda x: x.geometryType() == QGis.Polygon, Utils.LayerRegistry.instance().getVectorLayers()[0] )
102+
self.maskLayerCombo.addItems( map( lambda x: x.name(), self.maskLayers ) )
103+
self.checkRun()
104+
105+
def fillMaskFileEdit( self ):
106+
lastUsedFilter = Utils.FileFilter.lastUsedVectorFilter()
107+
maskFile = Utils.FileDialog.getOpenFileName(self, self.tr( "Select the mask file" ), Utils.FileFilter.allVectorsFilter(), lastUsedFilter )
108+
if maskFile.isEmpty():
109+
return
110+
Utils.FileFilter.setLastUsedVectorFilter(lastUsedFilter)
111+
112+
self.maskLayerCombo.setCurrentIndex(-1)
113+
self.maskLayerCombo.setEditText( maskFile )
114+
self.checkRun()
115+
77116
def getArguments(self):
117+
if not self.extentModeRadio.isChecked():
118+
return self.getArgsModeMask()
119+
return self.getArgsModeExtent()
120+
121+
def getArgsModeExtent(self):
122+
self.base.setPluginCommand( "gdal_translate" )
78123
arguments = QStringList()
79124
if self.noDataCheck.isChecked():
80125
arguments << "-a_nodata"
81126
arguments << str(self.noDataSpin.value())
82-
if self.extentSelector.isCoordsValid():
127+
if self.extentModeRadio.isChecked() and self.extentSelector.isCoordsValid():
83128
rect = self.extentSelector.getExtent()
84129
if rect != None:
85130
arguments << "-projwin"
86131
arguments << str(rect.xMinimum())
87132
arguments << str(rect.yMaximum())
88133
arguments << str(rect.xMaximum())
89134
arguments << str(rect.yMinimum())
135+
if Utils.GdalConfig.version() >= "1.7.0":
136+
arguments << "-q"
90137
if not self.getOutputFileName().isEmpty():
91138
arguments << "-of"
92139
arguments << self.outputFormat
93140
arguments << self.getInputFileName()
94141
arguments << self.getOutputFileName()
95142
return arguments
96143

144+
def getArgsModeMask(self):
145+
self.base.setPluginCommand( "gdalwarp" )
146+
arguments = QStringList()
147+
if self.noDataCheck.isChecked():
148+
arguments << "-dstnodata"
149+
arguments << str(self.noDataSpin.value())
150+
if self.maskModeRadio.isChecked():
151+
mask = self.getMaskFileName()
152+
if not mask.isEmpty():
153+
arguments << "-q"
154+
arguments << "-cutline"
155+
arguments << mask
156+
arguments << "-dstalpha"
157+
158+
outputFn = self.getOutputFileName()
159+
if not outputFn.isEmpty():
160+
arguments << "-of"
161+
arguments << self.outputFormat
162+
arguments << self.getInputFileName()
163+
arguments << outputFn
164+
return arguments
165+
97166
def getOutputFileName(self):
98167
return self.outputFileEdit.text()
99168

@@ -102,6 +171,11 @@ def getInputFileName(self):
102171
return self.layers[self.inputLayerCombo.currentIndex()].source()
103172
return self.inputLayerCombo.currentText()
104173

174+
def getMaskFileName(self):
175+
if self.maskLayerCombo.currentIndex() >= 0:
176+
return self.maskLayers[self.maskLayerCombo.currentIndex()].source()
177+
return self.maskLayerCombo.currentText()
178+
105179
def addLayerIntoCanvas(self, fileInfo):
106180
self.iface.addRasterLayer(fileInfo.filePath())
107181

python/plugins/GdalTools/tools/doMerge.py

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -110,41 +110,19 @@ def getOutputFileName(self):
110110
def addLayerIntoCanvas(self, fileInfo):
111111
self.iface.addRasterLayer(fileInfo.filePath())
112112

113-
def getRectangle( self, file ):
114-
processSRS = QProcess( self )
115-
processSRS.start( "gdalinfo", QStringList() << file, QIODevice.ReadOnly )
116-
arr = QByteArray()
117-
if processSRS.waitForFinished():
118-
arr = processSRS.readAllStandardOutput()
119-
processSRS.close()
120-
121-
if arr.isEmpty():
122-
return None
123-
124-
info = QString( arr ).split( "\n" )
125-
ulCoord = info[ info.indexOf( QRegExp( "^Upper\sLeft.*" ) ) ].simplified()
126-
lrCoord = info[ info.indexOf( QRegExp( "^Lower\sRight.*" ) ) ].simplified()
127-
ulCoord = ulCoord[ulCoord.indexOf( "(" ) + 1 : ulCoord.indexOf( ")" ) - 1].split( "," )
128-
lrCoord = lrCoord[lrCoord.indexOf( "(" ) + 1 : lrCoord.indexOf( ")" ) - 1].split( "," )
129-
xUL = ulCoord[0].toDouble()[0]
130-
yUL = ulCoord[1].toDouble()[0]
131-
xLR = lrCoord[0].toDouble()[0]
132-
yLR = lrCoord[1].toDouble()[0]
133-
134-
return QgsRectangle( xUL, yLR, xLR, yUL )
135-
136113
def getExtent( self ):
137114
files = self.inputFilesEdit.text().split( "," )
138115

139116
i = 0
140117
res = rect2 = None
141118
for fileName in files:
142119
if res == None:
143-
res = self.getRectangle( fileName )
120+
res = Utils.getRasterExtent( self, fileName )
144121
continue
145-
rect2 = self.getRectangle( fileName )
122+
rect2 = Utils.getRasterExtent( self, fileName )
146123
if rect2 == None:
147124
continue
148125
res = res.intersect( rect2 )
149126

150127
return res
128+

0 commit comments

Comments
 (0)