Skip to content

Commit 74e76f9

Browse files
author
cfarmer
committedNov 15, 2010
commit missing files for new simplify implementation by alexbruy
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@14678 c8812cc2-4d05-0410-92ff-de0c093fc19c

File tree

2 files changed

+435
-0
lines changed

2 files changed

+435
-0
lines changed
 
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from PyQt4.QtCore import *
4+
from PyQt4.QtGui import *
5+
6+
from qgis.core import *
7+
from qgis.gui import *
8+
9+
import ftools_utils
10+
11+
from ui_frmSimplify import Ui_Dialog
12+
13+
class Dialog( QDialog, Ui_Dialog ):
14+
def __init__( self, iface ):
15+
QDialog.__init__( self )
16+
self.setupUi( self )
17+
self.iface = iface
18+
19+
self.simplifyThread = None
20+
21+
self.okButton = self.buttonBox.button( QDialogButtonBox.Ok )
22+
self.closeButton = self.buttonBox.button( QDialogButtonBox.Close )
23+
24+
QObject.connect( self.writeShapefileCheck, SIGNAL( "stateChanged( int )" ), self.updateGui )
25+
QObject.connect( self.btnSelectOutputFile, SIGNAL( "clicked()" ), self.selectOutputFile )
26+
27+
self.manageGui()
28+
29+
def manageGui( self ):
30+
layers = ftools_utils.getLayerNames( [ QGis.Polygon, QGis.Line ] )
31+
self.cmbInputLayer.addItems( layers )
32+
33+
def updateGui( self ):
34+
if self.writeShapefileCheck.isChecked():
35+
self.outputFileEdit.setEnabled( True )
36+
self.btnSelectOutputFile.setEnabled( True )
37+
self.addToCanvasCheck.setEnabled( True )
38+
else:
39+
self.outputFileEdit.setEnabled( False )
40+
self.btnSelectOutputFile.setEnabled( False )
41+
self.addToCanvasCheck.setEnabled( False )
42+
self.encoding = None
43+
44+
def selectOutputFile( self ):
45+
self.outputFileEdit.clear()
46+
(self.shapefileName, self.encoding) = ftools_utils.saveDialog(self)
47+
if self.shapefileName is None or self.encoding is None:
48+
return
49+
self.outputFileEdit.setText(QString(self.shapefileName))
50+
51+
def accept( self ):
52+
vLayer = ftools_utils.getVectorLayerByName( self.cmbInputLayer.currentText() )
53+
54+
QApplication.setOverrideCursor( Qt.WaitCursor )
55+
self.okButton.setEnabled( False )
56+
57+
if self.writeShapefileCheck.isChecked():
58+
outFileName = self.outputFileEdit.text()
59+
outFile = QFile( outFileName )
60+
if outFile.exists():
61+
if not QgsVectorFileWriter.deleteShapeFile( outFileName ):
62+
QmessageBox.warning( self, self.tr( "Delete error" ), self.tr( "Can't delete file %1" ).arg( outFileName ) )
63+
return
64+
self.simplifyThread = GeneralizationThread( vLayer, self.useSelectionCheck.isChecked(), self.toleranceSpin.value(), True, outFileName, self.encoding )
65+
else:
66+
self.simplifyThread = GeneralizationThread( vLayer, self.useSelectionCheck.isChecked(), self.toleranceSpin.value(), False, None, None )
67+
QObject.connect( self.simplifyThread, SIGNAL( "rangeCalculated( PyQt_PyObject )" ), self.setProgressRange )
68+
QObject.connect( self.simplifyThread, SIGNAL( "featureProcessed()" ), self.featureProcessed )
69+
QObject.connect( self.simplifyThread, SIGNAL( "generalizationFinished( PyQt_PyObject )" ), self.generalizationFinished )
70+
QObject.connect( self.simplifyThread, SIGNAL( "generalizationInterrupted()" ), self.generalizationInterrupted )
71+
72+
self.closeButton.setText( self.tr( "Cancel" ) )
73+
QObject.disconnect( self.buttonBox, SIGNAL( "rejected()" ), self.reject )
74+
QObject.connect( self.closeButton, SIGNAL( "clicked()" ), self.stopProcessing )
75+
76+
self.simplifyThread.start()
77+
78+
def setProgressRange( self, max ):
79+
self.progressBar.setRange( 0, max )
80+
81+
def featureProcessed( self ):
82+
self.progressBar.setValue( self.progressBar.value() + 1 )
83+
84+
def generalizationFinished( self, pointsCount ):
85+
self.stopProcessing()
86+
87+
QMessageBox.information( self,
88+
self.tr( "Simplify results" ),
89+
self.tr( "There were %1 vertices in original dataset which\nwere reduced to %2 vertices after simplification" )
90+
.arg( pointsCount[ 0 ] )
91+
.arg( pointsCount[ 1 ] ) )
92+
93+
self.restoreGui()
94+
if self.addToCanvasCheck.isEnabled() and self.addToCanvasCheck.isChecked():
95+
if not ftools_utils.addShapeToCanvas( unicode( self.shapefileName ) ):
96+
QMessageBox.warning( self, self.tr( "Merging" ),
97+
self.tr( "Error loading output shapefile:\n%1" )
98+
.arg( unicode( self.shapefileName ) ) )
99+
100+
self.iface.mapCanvas().refresh()
101+
#self.restoreGui()
102+
103+
def generalizationInterrupted( self ):
104+
self.restoreGui()
105+
106+
def stopProcessing( self ):
107+
if self.simplifyThread != None:
108+
self.simplifyThread.stop()
109+
self.simplifyThread = None
110+
111+
def restoreGui( self ):
112+
self.progressBar.setValue( 0 )
113+
QApplication.restoreOverrideCursor()
114+
QObject.connect( self.buttonBox, SIGNAL( "rejected()" ), self.reject )
115+
self.closeButton.setText( self.tr( "Close" ) )
116+
self.okButton.setEnabled( True )
117+
118+
def geomVertexCount( geometry ):
119+
geomType = geometry.type()
120+
if geomType == 1: # line
121+
points = geometry.asPolyline()
122+
return len( points )
123+
elif geomType == 2: # polygon
124+
polylines = geometry.asPolygon()
125+
points = []
126+
for l in polylines:
127+
points.extend( l )
128+
return len( points )
129+
else:
130+
return None
131+
132+
class GeneralizationThread( QThread ):
133+
def __init__( self, inputLayer, useSelection, tolerance, writeShape, shapePath, shapeEncoding ):
134+
QThread.__init__( self, QThread.currentThread() )
135+
self.inputLayer = inputLayer
136+
self.useSelection = useSelection
137+
self.tolerance = tolerance
138+
self.writeShape = writeShape
139+
self.outputFileName = shapePath
140+
self.outputEncoding = shapeEncoding
141+
142+
self.shapeFileWriter = None
143+
self.pointsBefore = 0
144+
self.pointsAfter = 0
145+
146+
self.mutex = QMutex()
147+
self.stopMe = 0
148+
149+
def run( self ):
150+
self.mutex.lock()
151+
self.stopMe = 0
152+
self.mutex.unlock()
153+
154+
interrupted = False
155+
156+
shapeFileWriter = None
157+
158+
if self.writeShape:
159+
vProvider = self.inputLayer.dataProvider()
160+
allAttrs = vProvider.attributeIndexes()
161+
vProvider.select( allAttrs )
162+
shapeFields = vProvider.fields()
163+
crs = vProvider.crs()
164+
wkbType = self.inputLayer.wkbType()
165+
if not crs.isValid():
166+
crs = None
167+
shapeFileWriter = QgsVectorFileWriter( self.outputFileName, self.outputEncoding, shapeFields, wkbType, crs )
168+
featureId = 0
169+
if self.useSelection:
170+
selection = self.inputLayer.selectedFeatures()
171+
self.emit( SIGNAL( "rangeCalculated( PyQt_PyObject )" ), len( selection ) )
172+
for f in selection:
173+
featGeometry = QgsGeometry( f.geometry() )
174+
attrMap = f.attributeMap()
175+
self.pointsBefore += geomVertexCount( featGeometry )
176+
newGeometry = featGeometry.simplify( self.tolerance )
177+
self.pointsAfter += geomVertexCount( newGeometry )
178+
feature = QgsFeature()
179+
feature.setGeometry( newGeometry )
180+
feature.setAttributeMap( attrMap )
181+
shapeFileWriter.addFeature( feature )
182+
featureId += 1
183+
self.emit( SIGNAL( "featureProcessed()" ) )
184+
185+
self.mutex.lock()
186+
s = self.stopMe
187+
self.mutex.unlock()
188+
if s == 1:
189+
interrupted = True
190+
break
191+
else:
192+
self.emit( SIGNAL( "rangeCalculated( PyQt_PyObject )" ), vProvider.featureCount() )
193+
f = QgsFeature()
194+
while vProvider.nextFeature( f ):
195+
featGeometry = QgsGeometry( f.geometry() )
196+
attrMap = f.attributeMap()
197+
self.pointsBefore += geomVertexCount( featGeometry )
198+
newGeometry = featGeometry.simplify( self.tolerance )
199+
self.pointsAfter += geomVertexCount( newGeometry )
200+
feature = QgsFeature()
201+
feature.setGeometry( newGeometry )
202+
feature.setAttributeMap( attrMap )
203+
shapeFileWriter.addFeature( feature )
204+
featureId += 1
205+
self.emit( SIGNAL( "featureProcessed()" ) )
206+
207+
self.mutex.lock()
208+
s = self.stopMe
209+
self.mutex.unlock()
210+
if s == 1:
211+
interrupted = True
212+
break
213+
else: # modify existing shapefile
214+
if not self.inputLayer.isEditable():
215+
self.inputLayer.startEditing()
216+
self.inputLayer.beginEditCommand( QString( "Simplify line(s)" ) )
217+
if self.useSelection:
218+
selection = self.inputLayer.selectedFeatures()
219+
self.emit( SIGNAL( "rangeCalculated( PyQt_PyObject )" ), len( selection ) )
220+
for f in selection:
221+
featureId = f.id()
222+
featGeometry = QgsGeometry( f.geometry() )
223+
self.pointsBefore += geomVertexCount( featGeometry )
224+
newGeometry = featGeometry.simplify( self.tolerance )
225+
self.pointsAfter += geomVertexCount( newGeometry )
226+
self.inputLayer.changeGeometry( featureId, newGeometry )
227+
self.emit( SIGNAL( "featureProcessed()" ) )
228+
229+
self.mutex.lock()
230+
s = self.stopMe
231+
self.mutex.unlock()
232+
if s == 1:
233+
interrupted = True
234+
break
235+
else:
236+
vProvider = self.inputLayer.dataProvider()
237+
self.emit( SIGNAL( "rangeCalculated( PyQt_PyObject )" ), vProvider.featureCount() )
238+
f = QgsFeature()
239+
while vProvider.nextFeature( f ):
240+
featureId = f.id()
241+
featGeometry = QgsGeometry( f.geometry() )
242+
self.pointsBefore += geomVertexCount( featGeometry )
243+
newGeometry = featGeometry.simplify( self.tolerance )
244+
self.pointsAfter += geomVertexCount( newGeometry )
245+
self.inputLayer.changeGeometry( featureId, newGeometry )
246+
self.emit( SIGNAL( "featureProcessed()" ) )
247+
248+
self.mutex.lock()
249+
s = self.stopMe
250+
self.mutex.unlock()
251+
if s == 1:
252+
interrupted = True
253+
break
254+
255+
# cleanup
256+
if self.inputLayer.isEditable():
257+
self.inputLayer.endEditCommand()
258+
259+
if shapeFileWriter != None:
260+
del shapeFileWriter
261+
262+
if not interrupted:
263+
self.emit( SIGNAL( "generalizationFinished( PyQt_PyObject )" ), ( self.pointsBefore, self.pointsAfter ) )
264+
else:
265+
self.emit( SIGNAL( "generalizationInterrupted()" ) )
266+
267+
def stop( self ):
268+
self.mutex.lock()
269+
self.stopMe = 1
270+
self.mutex.unlock()
271+
272+
QThread.wait( self )
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>Dialog</class>
4+
<widget class="QDialog" name="Dialog">
5+
<property name="windowModality">
6+
<enum>Qt::WindowModal</enum>
7+
</property>
8+
<property name="geometry">
9+
<rect>
10+
<x>0</x>
11+
<y>0</y>
12+
<width>400</width>
13+
<height>269</height>
14+
</rect>
15+
</property>
16+
<property name="windowTitle">
17+
<string>Simplify geometries</string>
18+
</property>
19+
<layout class="QVBoxLayout" name="verticalLayout">
20+
<item>
21+
<widget class="QLabel" name="label">
22+
<property name="text">
23+
<string>Input line or polygon layer</string>
24+
</property>
25+
</widget>
26+
</item>
27+
<item>
28+
<widget class="QComboBox" name="cmbInputLayer">
29+
<property name="sizePolicy">
30+
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
31+
<horstretch>0</horstretch>
32+
<verstretch>0</verstretch>
33+
</sizepolicy>
34+
</property>
35+
</widget>
36+
</item>
37+
<item>
38+
<widget class="QCheckBox" name="useSelectionCheck">
39+
<property name="text">
40+
<string>Use only selected features</string>
41+
</property>
42+
</widget>
43+
</item>
44+
<item>
45+
<layout class="QHBoxLayout" name="horizontalLayout_3">
46+
<item>
47+
<widget class="QLabel" name="label_2">
48+
<property name="text">
49+
<string>Simplify tolerance</string>
50+
</property>
51+
</widget>
52+
</item>
53+
<item>
54+
<widget class="QDoubleSpinBox" name="toleranceSpin">
55+
<property name="decimals">
56+
<number>4</number>
57+
</property>
58+
<property name="minimum">
59+
<double>0.000000000000000</double>
60+
</property>
61+
<property name="maximum">
62+
<double>10000000.000000000000000</double>
63+
</property>
64+
<property name="value">
65+
<double>0.000100000000000</double>
66+
</property>
67+
</widget>
68+
</item>
69+
</layout>
70+
</item>
71+
<item>
72+
<layout class="QHBoxLayout" name="horizontalLayout_2">
73+
<item>
74+
<widget class="QCheckBox" name="writeShapefileCheck">
75+
<property name="text">
76+
<string>Save to new file</string>
77+
</property>
78+
</widget>
79+
</item>
80+
<item>
81+
<widget class="QLineEdit" name="outputFileEdit">
82+
<property name="enabled">
83+
<bool>false</bool>
84+
</property>
85+
</widget>
86+
</item>
87+
<item>
88+
<widget class="QPushButton" name="btnSelectOutputFile">
89+
<property name="enabled">
90+
<bool>false</bool>
91+
</property>
92+
<property name="text">
93+
<string>Browse</string>
94+
</property>
95+
</widget>
96+
</item>
97+
</layout>
98+
</item>
99+
<item>
100+
<widget class="QCheckBox" name="addToCanvasCheck">
101+
<property name="enabled">
102+
<bool>false</bool>
103+
</property>
104+
<property name="text">
105+
<string>Add result to canvas</string>
106+
</property>
107+
</widget>
108+
</item>
109+
<item>
110+
<widget class="QProgressBar" name="progressBar">
111+
<property name="value">
112+
<number>0</number>
113+
</property>
114+
</widget>
115+
</item>
116+
<item>
117+
<widget class="QDialogButtonBox" name="buttonBox">
118+
<property name="orientation">
119+
<enum>Qt::Horizontal</enum>
120+
</property>
121+
<property name="standardButtons">
122+
<set>QDialogButtonBox::Close|QDialogButtonBox::Ok</set>
123+
</property>
124+
</widget>
125+
</item>
126+
</layout>
127+
</widget>
128+
<resources/>
129+
<connections>
130+
<connection>
131+
<sender>buttonBox</sender>
132+
<signal>accepted()</signal>
133+
<receiver>Dialog</receiver>
134+
<slot>accept()</slot>
135+
<hints>
136+
<hint type="sourcelabel">
137+
<x>248</x>
138+
<y>254</y>
139+
</hint>
140+
<hint type="destinationlabel">
141+
<x>157</x>
142+
<y>274</y>
143+
</hint>
144+
</hints>
145+
</connection>
146+
<connection>
147+
<sender>buttonBox</sender>
148+
<signal>rejected()</signal>
149+
<receiver>Dialog</receiver>
150+
<slot>reject()</slot>
151+
<hints>
152+
<hint type="sourcelabel">
153+
<x>316</x>
154+
<y>260</y>
155+
</hint>
156+
<hint type="destinationlabel">
157+
<x>286</x>
158+
<y>274</y>
159+
</hint>
160+
</hints>
161+
</connection>
162+
</connections>
163+
</ui>

0 commit comments

Comments
 (0)
Please sign in to comment.