@@ -39,11 +39,13 @@ class Dialog(QDialog, Ui_Dialog):
39
39
def __init__ (self , iface ):
40
40
QDialog .__init__ (self , iface .mainWindow ())
41
41
self .iface = iface
42
- # Set up the user interface from Designer.
43
42
self .setupUi (self )
44
- QObject . connect ( self . toolOut , SIGNAL ( "clicked()" ), self . outFile )
43
+
45
44
self .setWindowTitle (self .tr ("Count Points in Polygon" ))
46
- self .buttonOk = self .buttonBox_2 .button ( QDialogButtonBox .Ok )
45
+ self .btnOk = self .buttonBox .button ( QDialogButtonBox .Ok )
46
+ self .btnClose = self .buttonBox .button ( QDialogButtonBox .Close )
47
+
48
+ QObject .connect (self .toolOut , SIGNAL ("clicked()" ), self .outFile )
47
49
self .progressBar .setValue (0 )
48
50
self .populateLayers ()
49
51
@@ -56,93 +58,193 @@ def populateLayers( self ):
56
58
layers = ftools_utils .getLayerNames ([QGis .Point ])
57
59
self .inPoint .addItems (layers )
58
60
61
+ def outFile (self ):
62
+ self .outShape .clear ()
63
+ (self .shapefileName , self .encoding ) = ftools_utils .saveDialog (self )
64
+ if self .shapefileName is None or self .encoding is None :
65
+ return
66
+ self .outShape .setText (QString (self .shapefileName ))
67
+
59
68
def accept (self ):
60
- self .buttonOk .setEnabled ( False )
61
69
if self .inPolygon .currentText () == "" :
62
- QMessageBox .information (self , self .tr ("Count Points In Polygon" ), self .tr ("Please specify input polygon vector layer" ))
63
- elif self .outShape .text () == "" :
64
- QMessageBox .information (self , self .tr ("Count Points In Polygon" ), self .tr ("Please specify output shapefile" ))
70
+ QMessageBox .information (self , self .tr ("Count Points In Polygon" ),
71
+ self .tr ("Please specify input polygon vector layer" ))
65
72
elif self .inPoint .currentText () == "" :
66
- QMessageBox .information (self , self .tr ("Count Points In Polygon" ), self .tr ("Please specify input point vector layer" ))
73
+ QMessageBox .information (self , self .tr ("Count Points In Polygon" ),
74
+ self .tr ("Please specify input point vector layer" ))
67
75
elif self .lnField .text () == "" :
68
- QMessageBox .information (self , self .tr ("Count Points In Polygon" ), self .tr ("Please specify output count field" ))
76
+ QMessageBox .information (self , self .tr ("Count Points In Polygon" ),
77
+ self .tr ("Please specify output count field" ))
78
+ elif self .outShape .text () == "" :
79
+ QMessageBox .information (self , self .tr ("Count Points In Polygon" ),
80
+ self .tr ("Please specify output shapefile" ))
69
81
else :
70
- inPoly = self .inPolygon .currentText ()
71
- inPts = self .inPoint .currentText ()
72
- inField = self .lnField .text ()
73
- outPath = self .outShape .text ()
74
- if outPath .contains ("\\ " ):
75
- outName = outPath .right ((outPath .length () - outPath .lastIndexOf ("\\ " )) - 1 )
76
- else :
77
- outName = outPath .right ((outPath .length () - outPath .lastIndexOf ("/" )) - 1 )
78
- if outName .endsWith (".shp" ):
79
- outName = outName .left (outName .length () - 4 )
80
- self .compute (inPoly , inPts , inField , outPath , self .progressBar )
81
- self .outShape .clear ()
82
- addToTOC = QMessageBox .question (self , self .tr ("Count Points in Polygon" ), self .tr ("Created output shapefile:\n %1\n \n Would you like to add the new layer to the TOC?" ).arg (unicode (outPath )), QMessageBox .Yes , QMessageBox .No , QMessageBox .NoButton )
83
- if addToTOC == QMessageBox .Yes :
84
- self .vlayer = QgsVectorLayer (outPath , unicode (outName ), "ogr" )
85
- QgsMapLayerRegistry .instance ().addMapLayer (self .vlayer )
86
- self .populateLayers ()
82
+ inPoly = ftools_utils .getVectorLayerByName (self .inPolygon .currentText ())
83
+ inPnts = ftools_utils .getVectorLayerByName (self .inPoint .currentText ())
84
+
85
+ polyProvider = inPoly .dataProvider ()
86
+ pointProvider = inPnts .dataProvider ()
87
+ if polyProvider .crs () <> pointProvider .crs ():
88
+ QMessageBox .warning (self , self .tr ("CRS warning!" ),
89
+ self .tr ("Warning: Input layers have non-matching CRS.\n This may cause unexpected results." ))
90
+
91
+ self .btnOk .setEnabled (False )
92
+
93
+ self .workThread = PointsInPolygonThread (inPoly , inPnts , self .lnField .text (), self .outShape .text (), self .encoding )
94
+
95
+ QObject .connect (self .workThread , SIGNAL ("rangeChanged(int)" ), self .setProgressRange )
96
+ QObject .connect (self .workThread , SIGNAL ("updateProgress()" ), self .updateProgress )
97
+ QObject .connect (self .workThread , SIGNAL ("processingFinished()" ), self .processFinished )
98
+ QObject .connect (self .workThread , SIGNAL ("processingInterrupted()" ), self .processInterrupted )
99
+
100
+ self .btnClose .setText (self .tr ("Cancel" ))
101
+ QObject .disconnect (self .buttonBox , SIGNAL ("rejected()" ), self .reject )
102
+ QObject .connect (self .btnClose , SIGNAL ("clicked()" ), self .stopProcessing )
103
+
104
+ self .workThread .start ()
105
+
106
+ def setProgressRange (self , maxValue ):
107
+ self .progressBar .setRange (0 , maxValue )
87
108
self .progressBar .setValue (0 )
88
- self .buttonOk .setEnabled ( True )
89
109
90
- def outFile (self ):
110
+ def updateProgress (self ):
111
+ self .progressBar .setValue (self .progressBar .value () + 1 )
112
+
113
+ def processFinished (self ):
114
+ self .stopProcessing ()
115
+
116
+ addToTOC = QMessageBox .question (self , self .tr ("Count Points in Polygon" ),
117
+ self .tr ("Created output shapefile:\n %1\n \n Would you like to add the new layer to the TOC?" ).arg (self .outShape .text ()),
118
+ QMessageBox .Yes , QMessageBox .No , QMessageBox .NoButton )
119
+ if addToTOC == QMessageBox .Yes :
120
+ fileInfo = QFileInfo ( self .outShape .text () )
121
+ layerName = fileInfo .completeBaseName ()
122
+ layer = QgsVectorLayer (self .outShape .text (), layerName , "ogr" )
123
+ QgsMapLayerRegistry .instance ().addMapLayer (layer )
124
+ self .populateLayers ()
125
+
126
+ self .restoreGui ()
127
+
128
+ def processInterrupted (self ):
129
+ self .restoreGui ()
130
+
131
+ def stopProcessing (self ):
132
+ if self .workThread != None :
133
+ self .workThread .stop ()
134
+ self .workThread = None
135
+
136
+ def restoreGui (self ):
137
+ self .progressBar .setRange (0 , 1 )
138
+ self .progressBar .setValue (0 )
91
139
self .outShape .clear ()
92
- ( self .shapefileName , self .encoding ) = ftools_utils .saveDialog ( self )
93
- if self .shapefileName is None or self .encoding is None :
94
- return
95
- self .outShape .setText ( QString ( self .shapefileName ) )
96
-
97
- def compute (self , inPoly , inPts , inField , outPath , progressBar ):
98
- polyLayer = ftools_utils .getVectorLayerByName (inPoly )
99
- pointLayer = ftools_utils .getVectorLayerByName (inPts )
100
- polyProvider = polyLayer .dataProvider ()
101
- pointProvider = pointLayer .dataProvider ()
102
- if polyProvider .crs () <> pointProvider .crs ():
103
- QMessageBox .warning (self , self .tr ("CRS warning!" ), self .tr ("Warning: Input layers have non-matching CRS.\n This may cause unexpected results." ))
140
+
141
+ QObject .disconnect (self .btnClose , SIGNAL ("clicked()" ), self .stopProcessing )
142
+ QObject .connect (self .buttonBox , SIGNAL ("rejected()" ), self .reject )
143
+ self .btnClose .setText (self .tr ("Close" ))
144
+ self .btnOk .setEnabled (True )
145
+
146
+ class PointsInPolygonThread (QThread ):
147
+ def __init__ ( self , inPoly , inPoints , fieldName , outPath , encoding ):
148
+ QThread .__init__ ( self , QThread .currentThread () )
149
+ self .mutex = QMutex ()
150
+ self .stopMe = 0
151
+ self .interrupted = False
152
+
153
+ self .layerPoly = inPoly
154
+ self .layerPoints = inPoints
155
+ self .fieldName = fieldName
156
+ self .outPath = outPath
157
+ self .encoding = encoding
158
+
159
+ def run (self ):
160
+ self .mutex .lock ()
161
+ self .stopMe = 0
162
+ self .mutex .unlock ()
163
+
164
+ interrupted = False
165
+
166
+ polyProvider = self .layerPoly .dataProvider ()
167
+ pointProvider = self .layerPoints .dataProvider ()
168
+
104
169
allAttrs = polyProvider .attributeIndexes ()
105
170
polyProvider .select (allAttrs )
106
- allAttrs = pointProvider .attributeIndexes ()
107
- pointProvider .select (allAttrs )
108
- fieldList = ftools_utils .getFieldList (polyLayer )
109
- index = polyProvider .fieldNameIndex (unicode (inField ))
171
+
172
+ fieldList = ftools_utils .getFieldList (self .layerPoly )
173
+ index = polyProvider .fieldNameIndex (unicode (self .fieldName ))
110
174
if index == - 1 :
111
175
index = polyProvider .fieldCount ()
112
- field = QgsField (unicode (inField ), QVariant .Double , "real" , 24 , 15 , self .tr ("point count field" ))
176
+ field = QgsField (unicode (self . fieldName ), QVariant .Double , "real" , 24 , 15 , self .tr ("point count field" ))
113
177
fieldList [index ] = field
178
+
114
179
sRs = polyProvider .crs ()
115
- check = QFile (self .shapefileName )
116
- if check .exists ():
117
- if not QgsVectorFileWriter .deleteShapeFile (self .shapefileName ):
180
+ if QFile (self .outPath ).exists ():
181
+ if not QgsVectorFileWriter .deleteShapeFile (self .outPath ):
118
182
return
119
- writer = QgsVectorFileWriter (self .shapefileName , self .encoding , fieldList , polyProvider .geometryType (), sRs )
120
- inFeat = QgsFeature ()
121
- inFeatB = QgsFeature ()
183
+
184
+ writer = QgsVectorFileWriter (self .outPath , self .encoding , fieldList ,
185
+ polyProvider .geometryType (), sRs )
186
+
187
+ spatialIndex = ftools_utils .createIndex ( pointProvider )
188
+ pointProvider .rewind ()
189
+ pointProvider .select ()
190
+
191
+ self .emit (SIGNAL ("rangeChanged(int)" ), polyProvider .featureCount () )
192
+
193
+ polyFeat = QgsFeature ()
194
+ pntFeat = QgsFeature ()
122
195
outFeat = QgsFeature ()
123
196
inGeom = QgsGeometry ()
124
- start = 15.00
125
- add = 85.00 / polyProvider .featureCount ()
126
- spatialIndex = ftools_utils .createIndex ( pointProvider )
127
- while polyProvider .nextFeature (inFeat ):
128
- inGeom = inFeat .geometry ()
129
- atMap = inFeat .attributeMap ()
197
+ while polyProvider .nextFeature (polyFeat ):
198
+ inGeom = polyFeat .geometry ()
199
+ atMap = polyFeat .attributeMap ()
130
200
outFeat .setAttributeMap (atMap )
131
201
outFeat .setGeometry (inGeom )
132
- pointList = []
202
+
133
203
count = 0
204
+ pointList = []
205
+ hasIntersection = True
134
206
pointList = spatialIndex .intersects (inGeom .boundingBox ())
135
- if len (pointList ) > 0 : check = 0
136
- else : check = 1
137
- if check == 0 :
138
- for i in pointList :
139
- pointProvider .featureAtId ( int ( i ), inFeatB , True , allAttrs )
140
- tmpGeom = QgsGeometry ( inFeatB .geometry () )
141
- if inGeom .intersects ( tmpGeom ):
142
- count = count + 1
143
- outFeat .setAttributeMap (atMap )
207
+ if len (pointList ) > 0 :
208
+ hasIntersection = True
209
+ else :
210
+ hasIntersection = False
211
+
212
+ if hasIntersection :
213
+ for p in pointList :
214
+ pointProvider .featureAtId (p , pntFeat , True )
215
+ tmpGeom = QgsGeometry (pntFeat .geometry ())
216
+ if inGeom .intersects (tmpGeom ):
217
+ count += 1
218
+
219
+ self .mutex .lock ()
220
+ s = self .stopMe
221
+ self .mutex .unlock ()
222
+ if s == 1 :
223
+ interrupted = True
224
+ break
225
+
144
226
outFeat .addAttribute (index , QVariant (count ))
145
227
writer .addFeature (outFeat )
146
- start = start + 1
147
- progressBar .setValue (start )
228
+
229
+ self .emit ( SIGNAL ( "updateProgress()" ) )
230
+
231
+ self .mutex .lock ()
232
+ s = self .stopMe
233
+ self .mutex .unlock ()
234
+ if s == 1 :
235
+ interrupted = True
236
+ break
237
+
148
238
del writer
239
+
240
+ if not interrupted :
241
+ self .emit ( SIGNAL ( "processingFinished()" ) )
242
+ else :
243
+ self .emit ( SIGNAL ( "processingInterrupted()" ) )
244
+
245
+ def stop (self ):
246
+ self .mutex .lock ()
247
+ self .stopMe = 1
248
+ self .mutex .unlock ()
249
+
250
+ QThread .wait ( self )
0 commit comments