1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
11
|
|
12
|
|
13
|
|
14
|
|
15
|
|
16
|
|
17
|
|
18
|
|
19
|
|
20
|
|
21
|
|
22
|
|
23
|
|
24
|
|
25
|
|
26
|
|
27
|
|
28
|
|
29
|
|
30
|
|
31
|
from PyQt4.QtCore import *
|
32
|
from PyQt4.QtGui import *
|
33
|
from qgis.core import *
|
34
|
from ui_frmGeometry import Ui_Dialog
|
35
|
import ftools_utils
|
36
|
import math
|
37
|
from itertools import izip
|
38
|
import voronoi
|
39
|
from sets import Set
|
40
|
|
41
|
class GeometryDialog( QDialog, Ui_Dialog ):
|
42
|
def __init__( self, iface, function ):
|
43
|
QDialog.__init__( self, iface.mainWindow() )
|
44
|
self.iface = iface
|
45
|
self.setupUi( self )
|
46
|
self.myFunction = function
|
47
|
self.buttonOk = self.buttonBox_2.button( QDialogButtonBox.Ok )
|
48
|
QObject.connect( self.toolOut, SIGNAL( "clicked()" ), self.outFile )
|
49
|
if self.myFunction == 1:
|
50
|
QObject.connect( self.inShape, SIGNAL( "currentIndexChanged( QString )" ), self.update )
|
51
|
elif self.myFunction == 5:
|
52
|
QObject.connect( self.chkWriteShapefile, SIGNAL( "stateChanged( int )" ), self.updateGui )
|
53
|
self.updateGui()
|
54
|
self.manageGui()
|
55
|
self.success = False
|
56
|
self.cancel_close = self.buttonBox_2.button( QDialogButtonBox.Close )
|
57
|
self.progressBar.setValue( 0 )
|
58
|
|
59
|
def update( self ):
|
60
|
self.cmbField.clear()
|
61
|
inputLayer = unicode( self.inShape.currentText() )
|
62
|
if inputLayer != "":
|
63
|
changedLayer = ftools_utils.getVectorLayerByName( inputLayer )
|
64
|
changedField = ftools_utils.getFieldList( changedLayer )
|
65
|
for f in changedField:
|
66
|
self.cmbField.addItem( unicode( f.name() ) )
|
67
|
self.cmbField.addItem( "--- " + self.tr( "Merge all" ) + " ---" )
|
68
|
|
69
|
def accept( self ):
|
70
|
if self.inShape.currentText() == "":
|
71
|
QMessageBox.information( self, self.tr( "Geometry" ),
|
72
|
self.tr( "Please specify input vector layer" ) )
|
73
|
elif self.outShape.text() == "" and self.myFunction != 5:
|
74
|
QMessageBox.information( self, self.tr( "Geometry" ),
|
75
|
self.tr( "Please specify output shapefile" ) )
|
76
|
elif self.lineEdit.isVisible() and self.lineEdit.value() < 0.00:
|
77
|
QMessageBox.information( self, self.tr( "Geometry" ),
|
78
|
self.tr( "Please specify valid tolerance value" ) )
|
79
|
elif self.cmbField.isVisible() and self.cmbField.currentText() == "":
|
80
|
QMessageBox.information( self, self.tr( "Geometry" ),
|
81
|
self.tr( "Please specify valid UID field" ) )
|
82
|
else:
|
83
|
self.outShape.clear()
|
84
|
self.geometry( self.inShape.currentText(), self.lineEdit.value(),
|
85
|
self.cmbField.currentText() )
|
86
|
|
87
|
def outFile( self ):
|
88
|
self.outShape.clear()
|
89
|
(self.shapefileName, self.encoding) = ftools_utils.saveDialog( self )
|
90
|
if self.shapefileName is None or self.encoding is None:
|
91
|
return
|
92
|
self.outShape.setText( self.shapefileName )
|
93
|
|
94
|
def manageGui( self ):
|
95
|
self.lblField.setVisible( False )
|
96
|
self.cmbField.setVisible( False )
|
97
|
|
98
|
self.lblCalcType.setVisible( False )
|
99
|
self.cmbCalcType.setVisible( False )
|
100
|
|
101
|
self.chkUseSelection.setVisible( False )
|
102
|
self.chkByFeatures.setVisible( False )
|
103
|
|
104
|
self.chkWriteShapefile.setVisible( False )
|
105
|
if self.myFunction == 1:
|
106
|
self.setWindowTitle( self.tr( "Singleparts to multipart" ) )
|
107
|
self.lineEdit.setVisible( False )
|
108
|
self.label.setVisible( False )
|
109
|
self.lblOutputShapefile.setText( self.tr( "Output shapefile" ) )
|
110
|
self.cmbField.setVisible( True )
|
111
|
self.lblField.setVisible( True )
|
112
|
elif self.myFunction == 2:
|
113
|
self.setWindowTitle( self.tr( "Multipart to singleparts" ) )
|
114
|
self.lineEdit.setVisible( False )
|
115
|
self.label.setVisible( False )
|
116
|
self.lblOutputShapefile.setText( self.tr( "Output shapefile" ) )
|
117
|
elif self.myFunction == 3:
|
118
|
self.setWindowTitle( self.tr( "Extract nodes" ) )
|
119
|
self.lineEdit.setVisible( False )
|
120
|
self.label.setVisible( False )
|
121
|
elif self.myFunction == 4:
|
122
|
self.setWindowTitle( self.tr( "Polygons to lines" ) )
|
123
|
self.lblOutputShapefile.setText( self.tr( "Output shapefile" ) )
|
124
|
self.label_3.setText( self.tr( "Input polygon vector layer" ) )
|
125
|
self.label.setVisible( False )
|
126
|
self.lineEdit.setVisible( False )
|
127
|
elif self.myFunction == 5:
|
128
|
self.setWindowTitle( self.tr( "Export/Add geometry columns" ) )
|
129
|
self.lblOutputShapefile.setText( self.tr( "Output shapefile" ) )
|
130
|
self.label_3.setText( self.tr( "Input vector layer" ) )
|
131
|
self.label.setVisible( False )
|
132
|
self.lineEdit.setVisible( False )
|
133
|
|
134
|
self.lblCalcType.setVisible( True )
|
135
|
self.cmbCalcType.setVisible( True )
|
136
|
self.cmbCalcType.addItem( self.tr( "Layer CRS" ) )
|
137
|
self.cmbCalcType.addItem( self.tr( "Project CRS" ) )
|
138
|
self.cmbCalcType.addItem( self.tr( "Ellipsoid" ) )
|
139
|
|
140
|
self.chkWriteShapefile.setVisible( True )
|
141
|
self.chkWriteShapefile.setChecked( False )
|
142
|
self.lblOutputShapefile.setVisible( False )
|
143
|
elif self.myFunction == 7:
|
144
|
self.setWindowTitle( self.tr( "Polygon centroids" ) )
|
145
|
self.lblOutputShapefile.setText( self.tr( "Output point shapefile" ) )
|
146
|
self.label_3.setText( self.tr( "Input polygon vector layer" ) )
|
147
|
self.label.setVisible( False )
|
148
|
self.lineEdit.setVisible( False )
|
149
|
else:
|
150
|
if self.myFunction == 8:
|
151
|
self.setWindowTitle( self.tr( "Delaunay triangulation" ) )
|
152
|
self.label_3.setText( self.tr( "Input point vector layer" ) )
|
153
|
self.label.setVisible( False )
|
154
|
self.lineEdit.setVisible( False )
|
155
|
elif self.myFunction == 10:
|
156
|
self.setWindowTitle( self.tr( "Voronoi polygon" ) )
|
157
|
self.label_3.setText( self.tr( "Input point vector layer" ) )
|
158
|
self.label.setText( self.tr( "Buffer region" ) )
|
159
|
self.lineEdit.setSuffix( " %" )
|
160
|
self.lineEdit.setRange( 0, 100 )
|
161
|
self.lineEdit.setSingleStep( 5 )
|
162
|
self.lineEdit.setValue( 0 )
|
163
|
elif self.myFunction == 11:
|
164
|
self.setWindowTitle( self.tr( "Lines to polygons" ) )
|
165
|
self.lblOutputShapefile.setText( self.tr( "Output shapefile" ) )
|
166
|
self.label_3.setText( self.tr( "Input line vector layer" ) )
|
167
|
self.label.setVisible( False )
|
168
|
self.lineEdit.setVisible( False )
|
169
|
else:
|
170
|
self.setWindowTitle( self.tr( "Polygon from layer extent" ) )
|
171
|
self.label_3.setText( self.tr( "Input layer" ) )
|
172
|
self.label.setVisible( False )
|
173
|
self.lineEdit.setVisible( False )
|
174
|
self.chkByFeatures.setVisible( True )
|
175
|
self.chkUseSelection.setVisible( True )
|
176
|
self.lblOutputShapefile.setText( self.tr( "Output polygon shapefile" ) )
|
177
|
self.resize( 381, 100 )
|
178
|
self.populateLayers()
|
179
|
|
180
|
def updateGui( self ):
|
181
|
if self.chkWriteShapefile.isChecked():
|
182
|
self.lineEdit.setEnabled( True )
|
183
|
self.toolOut.setEnabled( True )
|
184
|
else:
|
185
|
self.lineEdit.setEnabled( False )
|
186
|
self.toolOut.setEnabled( False )
|
187
|
|
188
|
def populateLayers( self ):
|
189
|
self.inShape.clear()
|
190
|
if self.myFunction == 3 or self.myFunction == 6:
|
191
|
myList = ftools_utils.getLayerNames( [ QGis.Polygon, QGis.Line ] )
|
192
|
elif self.myFunction == 4 or self.myFunction == 7:
|
193
|
myList = ftools_utils.getLayerNames( [ QGis.Polygon ] )
|
194
|
elif self.myFunction == 8 or self.myFunction == 10:
|
195
|
myList = ftools_utils.getLayerNames( [ QGis.Point ] )
|
196
|
elif self.myFunction == 9:
|
197
|
myList = ftools_utils.getLayerNames( "all" )
|
198
|
elif self.myFunction == 11:
|
199
|
myList = ftools_utils.getLayerNames( [ QGis.Line ] )
|
200
|
else:
|
201
|
myList = ftools_utils.getLayerNames( [ QGis.Point, QGis.Line, QGis.Polygon ] )
|
202
|
self.inShape.addItems( myList )
|
203
|
|
204
|
|
205
|
|
206
|
|
207
|
|
208
|
|
209
|
|
210
|
|
211
|
|
212
|
|
213
|
|
214
|
|
215
|
|
216
|
def geometry( self, myLayer, myParam, myField ):
|
217
|
if self.myFunction == 9:
|
218
|
vlayer = ftools_utils.getMapLayerByName( myLayer )
|
219
|
else:
|
220
|
vlayer = ftools_utils.getVectorLayerByName( myLayer )
|
221
|
error = False
|
222
|
|
223
|
if ( self.myFunction == 5 and self.chkWriteShapefile.isChecked() ) or self.myFunction != 5:
|
224
|
check = QFile( self.shapefileName )
|
225
|
if check.exists():
|
226
|
if not QgsVectorFileWriter.deleteShapeFile( self.shapefileName ):
|
227
|
QMessageBox.warning( self, self.tr( "Geometry"),
|
228
|
self.tr( "Unable to delete existing shapefile." ) )
|
229
|
return
|
230
|
|
231
|
if self.myFunction == 5 and not self.chkWriteShapefile.isChecked():
|
232
|
self.shapefileName = None
|
233
|
self.encoding = None
|
234
|
|
235
|
res = QMessageBox.warning( self, self.tr( "Geometry"),
|
236
|
self.tr( "Currently QGIS doesn't allow simultaneous access from \
|
237
|
different threads to the same datasource. Make sure your layer's \
|
238
|
attribute tables are closed. Continue?"),
|
239
|
QMessageBox.Yes | QMessageBox.No )
|
240
|
if res == QMessageBox.No:
|
241
|
return
|
242
|
|
243
|
self.buttonOk.setEnabled( False )
|
244
|
self.testThread = geometryThread( self.iface.mainWindow(), self, self.myFunction,
|
245
|
vlayer, myParam, myField, self.shapefileName, self.encoding,
|
246
|
self.cmbCalcType.currentIndex(), self.chkWriteShapefile.isChecked(),
|
247
|
self.chkByFeatures.isChecked(), self.chkUseSelection.isChecked() )
|
248
|
QObject.connect( self.testThread, SIGNAL( "runFinished( PyQt_PyObject )" ), self.runFinishedFromThread )
|
249
|
QObject.connect( self.testThread, SIGNAL( "runStatus( PyQt_PyObject )" ), self.runStatusFromThread )
|
250
|
QObject.connect( self.testThread, SIGNAL( "runRange( PyQt_PyObject )" ), self.runRangeFromThread )
|
251
|
self.cancel_close.setText( self.tr( "Cancel" ) )
|
252
|
QObject.connect( self.cancel_close, SIGNAL( "clicked()" ), self.cancelThread )
|
253
|
self.testThread.start()
|
254
|
|
255
|
def cancelThread( self ):
|
256
|
self.testThread.stop()
|
257
|
self.buttonOk.setEnabled( True )
|
258
|
|
259
|
def runFinishedFromThread( self, success ):
|
260
|
self.testThread.stop()
|
261
|
self.buttonOk.setEnabled( True )
|
262
|
extra = ""
|
263
|
if success == "math_error":
|
264
|
QMessageBox.warning( self, self.tr( "Geometry" ),
|
265
|
self.tr( "Error processing specified tolerance!\nPlease choose larger tolerance..." ) )
|
266
|
if not QgsVectorFileWriter.deleteShapeFile( self.shapefileName ):
|
267
|
QMessageBox.warning( self, self.tr( "Geometry" ),
|
268
|
self.tr( "Unable to delete incomplete shapefile." ) )
|
269
|
elif success == "attr_error":
|
270
|
QMessageBox.warning( self, self.tr( "Geometry" ),
|
271
|
self.tr( "At least two features must have same attribute value!\nPlease choose another field..." ) )
|
272
|
if not QgsVectorFileWriter.deleteShapeFile( self.shapefileName ):
|
273
|
QMessageBox.warning( self, self.tr( "Geometry" ),
|
274
|
self.tr( "Unable to delete incomplete shapefile." ) )
|
275
|
else:
|
276
|
if success == "valid_error":
|
277
|
extra = self.tr( "One or more features in the output layer may have invalid "
|
278
|
+ "geometry, please check using the check validity tool\n" )
|
279
|
success = True
|
280
|
self.cancel_close.setText( "Close" )
|
281
|
QObject.disconnect( self.cancel_close, SIGNAL( "clicked()" ), self.cancelThread )
|
282
|
if success:
|
283
|
if ( self.myFunction == 5 and self.chkWriteShapefile.isChecked() ) or self.myFunction != 5:
|
284
|
addToTOC = QMessageBox.question( self, self.tr("Geometry"),
|
285
|
self.tr( "Created output shapefile:\n{0}\n{1}\n\nWould you like to add the new layer to the TOC?" ).format( self.shapefileName, extra ),
|
286
|
QMessageBox.Yes, QMessageBox.No, QMessageBox.NoButton )
|
287
|
if addToTOC == QMessageBox.Yes:
|
288
|
if not ftools_utils.addShapeToCanvas( unicode( self.shapefileName ) ):
|
289
|
QMessageBox.warning( self, self.tr( "Geometry"),
|
290
|
self.tr( "Error loading output shapefile:\n{0}" ).format( self.shapefileName ) )
|
291
|
self.populateLayers()
|
292
|
else:
|
293
|
QMessageBox.information( self, self.tr( "Geometry" ),
|
294
|
self.tr( "Layer '{0}' updated" ).format( self.inShape.currentText() ) )
|
295
|
else:
|
296
|
QMessageBox.warning( self, self.tr( "Geometry" ), self.tr( "Error writing output shapefile." ) )
|
297
|
|
298
|
def runStatusFromThread( self, status ):
|
299
|
self.progressBar.setValue( status )
|
300
|
|
301
|
def runRangeFromThread( self, range_vals ):
|
302
|
self.progressBar.setRange( range_vals[ 0 ], range_vals[ 1 ] )
|
303
|
|
304
|
class geometryThread( QThread ):
|
305
|
def __init__( self, parentThread, parentObject, function, vlayer, myParam,
|
306
|
myField, myName, myEncoding, myCalcType, myNewShape, myByFeatures,
|
307
|
myUseSelection ):
|
308
|
QThread.__init__( self, parentThread )
|
309
|
self.parent = parentObject
|
310
|
self.running = False
|
311
|
self.myFunction = function
|
312
|
self.vlayer = vlayer
|
313
|
self.myParam = myParam
|
314
|
self.myField = myField
|
315
|
self.myName = myName
|
316
|
self.myEncoding = myEncoding
|
317
|
self.myCalcType = myCalcType
|
318
|
self.writeShape = myNewShape
|
319
|
self.byFeatures = myByFeatures
|
320
|
self.useSelection = myUseSelection
|
321
|
|
322
|
def run( self ):
|
323
|
self.running = True
|
324
|
if self.myFunction == 1:
|
325
|
success = self.single_to_multi()
|
326
|
elif self.myFunction == 2:
|
327
|
success = self.multi_to_single()
|
328
|
elif self.myFunction == 3:
|
329
|
success = self.extract_nodes()
|
330
|
elif self.myFunction == 4:
|
331
|
success = self.polygons_to_lines()
|
332
|
elif self.myFunction == 5:
|
333
|
success = self.export_geometry_info()
|
334
|
|
335
|
elif self.myFunction == 7:
|
336
|
success = self.polygon_centroids()
|
337
|
elif self.myFunction == 8:
|
338
|
success = self.delaunay_triangulation()
|
339
|
elif self.myFunction == 9:
|
340
|
if self.byFeatures:
|
341
|
success = self.feature_extent()
|
342
|
else:
|
343
|
success = self.layer_extent()
|
344
|
elif self.myFunction == 10:
|
345
|
success = self.voronoi_polygons()
|
346
|
elif self.myFunction == 11:
|
347
|
success = self.lines_to_polygons()
|
348
|
self.emit( SIGNAL( "runFinished( PyQt_PyObject )" ), success )
|
349
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
|
350
|
|
351
|
def stop( self ):
|
352
|
self.running = False
|
353
|
|
354
|
def single_to_multi( self ):
|
355
|
vprovider = self.vlayer.dataProvider()
|
356
|
allValid = True
|
357
|
geomType = self.singleToMultiGeom( vprovider.geometryType() )
|
358
|
writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(),
|
359
|
geomType, vprovider.crs() )
|
360
|
inFeat = QgsFeature()
|
361
|
outFeat = QgsFeature()
|
362
|
inGeom = QgsGeometry()
|
363
|
outGeom = QgsGeometry()
|
364
|
index = vprovider.fieldNameIndex( self.myField )
|
365
|
if not index == -1:
|
366
|
unique = ftools_utils.getUniqueValues( vprovider, int( index ) )
|
367
|
else:
|
368
|
unique = [ "" ]
|
369
|
nFeat = vprovider.featureCount() * len( unique )
|
370
|
nElement = 0
|
371
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
|
372
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) )
|
373
|
merge_all = self.myField == "--- " + self.tr( "Merge all" ) + " ---"
|
374
|
if not len( unique ) == self.vlayer.featureCount() or merge_all:
|
375
|
for i in unique:
|
376
|
multi_feature= []
|
377
|
first = True
|
378
|
fit = vprovider.getFeatures()
|
379
|
while fit.nextFeature( inFeat ):
|
380
|
atMap = inFeat.attributes()
|
381
|
if not merge_all:
|
382
|
idVar = atMap[ index ]
|
383
|
else:
|
384
|
idVar = ""
|
385
|
if idVar.strip() == i.strip() or merge_all:
|
386
|
if first:
|
387
|
atts = atMap
|
388
|
first = False
|
389
|
inGeom = QgsGeometry( inFeat.geometry() )
|
390
|
vType = inGeom.type()
|
391
|
feature_list = self.extractAsMulti( inGeom )
|
392
|
multi_feature.extend( feature_list )
|
393
|
nElement += 1
|
394
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
|
395
|
if not first:
|
396
|
outFeat.setAttributes( atts )
|
397
|
outGeom = QgsGeometry( self.convertGeometry( multi_feature, vType ) )
|
398
|
if not outGeom.isGeosValid():
|
399
|
allValid = "valid_error"
|
400
|
outFeat.setGeometry( outGeom )
|
401
|
writer.addFeature( outFeat )
|
402
|
del writer
|
403
|
else:
|
404
|
return "attr_error"
|
405
|
return allValid
|
406
|
|
407
|
def multi_to_single( self ):
|
408
|
vprovider = self.vlayer.dataProvider()
|
409
|
geomType = self.multiToSingleGeom( vprovider.geometryType() )
|
410
|
writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(),
|
411
|
geomType, vprovider.crs() )
|
412
|
inFeat = QgsFeature()
|
413
|
outFeat = QgsFeature()
|
414
|
inGeom = QgsGeometry()
|
415
|
outGeom = QgsGeometry()
|
416
|
nFeat = vprovider.featureCount()
|
417
|
nElement = 0
|
418
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
|
419
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) )
|
420
|
fit = vprovider.getFeatures()
|
421
|
while fit.nextFeature( inFeat ):
|
422
|
nElement += 1
|
423
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
|
424
|
inGeom = inFeat.geometry()
|
425
|
atMap = inFeat.attributes()
|
426
|
featList = self.extractAsSingle( inGeom )
|
427
|
outFeat.setAttributes( atMap )
|
428
|
for i in featList:
|
429
|
outFeat.setGeometry( i )
|
430
|
writer.addFeature( outFeat )
|
431
|
del writer
|
432
|
return True
|
433
|
|
434
|
def extract_nodes( self ):
|
435
|
vprovider = self.vlayer.dataProvider()
|
436
|
writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(),
|
437
|
QGis.WKBPoint, vprovider.crs() )
|
438
|
inFeat = QgsFeature()
|
439
|
outFeat = QgsFeature()
|
440
|
inGeom = QgsGeometry()
|
441
|
outGeom = QgsGeometry()
|
442
|
nFeat = vprovider.featureCount()
|
443
|
nElement = 0
|
444
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
|
445
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) )
|
446
|
fit = vprovider.getFeatures()
|
447
|
while fit.nextFeature( inFeat ):
|
448
|
nElement += 1
|
449
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
|
450
|
inGeom = inFeat.geometry()
|
451
|
atMap = inFeat.attributes()
|
452
|
pointList = ftools_utils.extractPoints( inGeom )
|
453
|
outFeat.setAttributes( atMap )
|
454
|
for i in pointList:
|
455
|
outFeat.setGeometry( outGeom.fromPoint( i ) )
|
456
|
writer.addFeature( outFeat )
|
457
|
del writer
|
458
|
return True
|
459
|
|
460
|
def polygons_to_lines( self ):
|
461
|
vprovider = self.vlayer.dataProvider()
|
462
|
writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(),
|
463
|
QGis.WKBLineString, vprovider.crs() )
|
464
|
inFeat = QgsFeature()
|
465
|
outFeat = QgsFeature()
|
466
|
inGeom = QgsGeometry()
|
467
|
outGeom = QgsGeometry()
|
468
|
nFeat = vprovider.featureCount()
|
469
|
nElement = 0
|
470
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0)
|
471
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) )
|
472
|
|
473
|
fit = vprovider.getFeatures()
|
474
|
while fit.nextFeature( inFeat ):
|
475
|
multi = False
|
476
|
nElement += 1
|
477
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
|
478
|
inGeom = inFeat.geometry()
|
479
|
if inGeom.isMultipart():
|
480
|
multi = True
|
481
|
atMap = inFeat.attributes()
|
482
|
lineList = self.extractAsLine( inGeom )
|
483
|
outFeat.setAttributes( atMap )
|
484
|
for h in lineList:
|
485
|
outFeat.setGeometry( outGeom.fromPolyline( h ) )
|
486
|
writer.addFeature( outFeat )
|
487
|
del writer
|
488
|
return True
|
489
|
|
490
|
def lines_to_polygons( self ):
|
491
|
vprovider = self.vlayer.dataProvider()
|
492
|
writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(),
|
493
|
QGis.WKBPolygon, vprovider.crs() )
|
494
|
inFeat = QgsFeature()
|
495
|
outFeat = QgsFeature()
|
496
|
inGeom = QgsGeometry()
|
497
|
nFeat = vprovider.featureCount()
|
498
|
nElement = 0
|
499
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0)
|
500
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) )
|
501
|
|
502
|
fit = vprovider.getFeatures()
|
503
|
while fit.nextFeature( inFeat ):
|
504
|
outGeomList = []
|
505
|
multi = False
|
506
|
nElement += 1
|
507
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
|
508
|
if inFeat.geometry().isMultipart():
|
509
|
outGeomList = inFeat.geometry().asMultiPolyline()
|
510
|
multi = True
|
511
|
else:
|
512
|
outGeomList.append( inFeat.geometry().asPolyline() )
|
513
|
polyGeom = self.remove_bad_lines( outGeomList )
|
514
|
if len( polyGeom ) <> 0:
|
515
|
outFeat.setGeometry( QgsGeometry.fromPolygon( polyGeom ) )
|
516
|
atMap = inFeat.attributes()
|
517
|
outFeat.setAttributes( atMap )
|
518
|
writer.addFeature( outFeat )
|
519
|
del writer
|
520
|
return True
|
521
|
|
522
|
def export_geometry_info( self ):
|
523
|
ellips = None
|
524
|
crs = None
|
525
|
coordTransform = None
|
526
|
|
527
|
|
528
|
|
529
|
|
530
|
|
531
|
if self.myCalcType == 2:
|
532
|
settings = QSettings()
|
533
|
ellips = settings.value( "/qgis/measure/ellipsoid", "WGS84" )
|
534
|
crs = self.vlayer.crs().srsid()
|
535
|
elif self.myCalcType == 1:
|
536
|
mapCRS = self.parent.iface.mapCanvas().mapRenderer().destinationCrs()
|
537
|
layCRS = self.vlayer.crs()
|
538
|
coordTransform = QgsCoordinateTransform( layCRS, mapCRS )
|
539
|
|
540
|
inFeat = QgsFeature()
|
541
|
outFeat = QgsFeature()
|
542
|
inGeom = QgsGeometry()
|
543
|
nElement = 0
|
544
|
|
545
|
vprovider = self.vlayer.dataProvider()
|
546
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0)
|
547
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, vprovider.featureCount() ) )
|
548
|
|
549
|
( fields, index1, index2 ) = self.checkMeasurementFields( self.vlayer, not self.writeShape )
|
550
|
|
551
|
if self.writeShape:
|
552
|
writer = QgsVectorFileWriter( self.myName, self.myEncoding, fields,
|
553
|
vprovider.geometryType(), vprovider.crs() )
|
554
|
|
555
|
fit = vprovider.getFeatures()
|
556
|
while fit.nextFeature(inFeat):
|
557
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
|
558
|
nElement += 1
|
559
|
inGeom = inFeat.geometry()
|
560
|
|
561
|
if self.myCalcType == 1:
|
562
|
inGeom.transform( coordTransform )
|
563
|
|
564
|
( attr1, attr2 ) = self.simpleMeasure( inGeom, self.myCalcType, ellips, crs )
|
565
|
|
566
|
if self.writeShape:
|
567
|
outFeat.setGeometry( inGeom )
|
568
|
atMap = inFeat.attributes()
|
569
|
maxIndex = index1 if index1>index2 else index2
|
570
|
if maxIndex>=len(atMap):
|
571
|
atMap += [ "" ] * ( index2+1 - len(atMap) )
|
572
|
atMap[ index1 ] = attr1
|
573
|
if index1!=index2:
|
574
|
atMap[ index2 ] = attr2
|
575
|
outFeat.setAttributes( atMap )
|
576
|
writer.addFeature( outFeat )
|
577
|
else:
|
578
|
changeMap = {}
|
579
|
changeMap[ inFeat.id() ] = {}
|
580
|
changeMap[ inFeat.id() ][ index1 ] = attr1
|
581
|
if index1!=index2:
|
582
|
changeMap[ inFeat.id() ][ index2 ] = attr2
|
583
|
vprovider.changeAttributeValues( changeMap )
|
584
|
self.vlayer.updateFields()
|
585
|
|
586
|
if self.writeShape:
|
587
|
del writer
|
588
|
|
589
|
return True
|
590
|
|
591
|
def polygon_centroids( self ):
|
592
|
vprovider = self.vlayer.dataProvider()
|
593
|
writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(),
|
594
|
QGis.WKBPoint, vprovider.crs() )
|
595
|
inFeat = QgsFeature()
|
596
|
outFeat = QgsFeature()
|
597
|
nFeat = vprovider.featureCount()
|
598
|
nElement = 0
|
599
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
|
600
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) )
|
601
|
fit = vprovider.getFeatures()
|
602
|
while fit.nextFeature( inFeat ):
|
603
|
nElement += 1
|
604
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
|
605
|
inGeom = inFeat.geometry()
|
606
|
atMap = inFeat.attributes()
|
607
|
outGeom = inGeom.centroid()
|
608
|
if outGeom is None:
|
609
|
return "math_error"
|
610
|
outFeat.setAttributes( atMap )
|
611
|
outFeat.setGeometry( QgsGeometry( outGeom ) )
|
612
|
writer.addFeature( outFeat )
|
613
|
del writer
|
614
|
return True
|
615
|
|
616
|
def delaunay_triangulation( self ):
|
617
|
import voronoi
|
618
|
from sets import Set
|
619
|
vprovider = self.vlayer.dataProvider()
|
620
|
|
621
|
fields = QgsFields()
|
622
|
fields.append( QgsField( "POINTA", QVariant.Double ) )
|
623
|
fields.append( QgsField( "POINTB", QVariant.Double ) )
|
624
|
fields.append( QgsField( "POINTC", QVariant.Double ) )
|
625
|
|
626
|
writer = QgsVectorFileWriter( self.myName, self.myEncoding, fields,
|
627
|
QGis.WKBPolygon, vprovider.crs() )
|
628
|
inFeat = QgsFeature()
|
629
|
c = voronoi.Context()
|
630
|
pts = []
|
631
|
ptDict = {}
|
632
|
ptNdx = -1
|
633
|
fit = vprovider.getFeatures()
|
634
|
while fit.nextFeature( inFeat ):
|
635
|
geom = QgsGeometry( inFeat.geometry() )
|
636
|
point = geom.asPoint()
|
637
|
x = point.x()
|
638
|
y = point.y()
|
639
|
pts.append( ( x, y ) )
|
640
|
ptNdx +=1
|
641
|
ptDict[ptNdx] = inFeat.id()
|
642
|
if len(pts) < 3:
|
643
|
return False
|
644
|
uniqueSet = Set( item for item in pts )
|
645
|
ids = [ pts.index( item ) for item in uniqueSet ]
|
646
|
sl = voronoi.SiteList( [ voronoi.Site( *i ) for i in uniqueSet ] )
|
647
|
c.triangulate = True
|
648
|
voronoi.voronoi( sl, c )
|
649
|
triangles = c.triangles
|
650
|
feat = QgsFeature()
|
651
|
nFeat = len( triangles )
|
652
|
nElement = 0
|
653
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
|
654
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) )
|
655
|
for triangle in triangles:
|
656
|
indicies = list( triangle )
|
657
|
indicies.append( indicies[ 0 ] )
|
658
|
polygon = []
|
659
|
attrs = []
|
660
|
step = 0
|
661
|
for index in indicies:
|
662
|
vprovider.getFeatures( QgsFeatureRequest().setFilterFid( ptDict[ ids[ index ] ] ) ).nextFeature( inFeat )
|
663
|
geom = QgsGeometry( inFeat.geometry() )
|
664
|
point = QgsPoint( geom.asPoint() )
|
665
|
polygon.append( point )
|
666
|
if step <= 3:
|
667
|
attrs.append(ids[ index ] )
|
668
|
step += 1
|
669
|
feat.setAttributes(attrs)
|
670
|
geometry = QgsGeometry().fromPolygon( [ polygon ] )
|
671
|
feat.setGeometry( geometry )
|
672
|
writer.addFeature( feat )
|
673
|
nElement += 1
|
674
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
|
675
|
del writer
|
676
|
return True
|
677
|
|
678
|
def voronoi_polygons( self ):
|
679
|
vprovider = self.vlayer.dataProvider()
|
680
|
writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(),
|
681
|
QGis.WKBPolygon, vprovider.crs() )
|
682
|
inFeat = QgsFeature()
|
683
|
outFeat = QgsFeature()
|
684
|
extent = self.vlayer.extent()
|
685
|
extraX = extent.height() * ( self.myParam / 100.00 )
|
686
|
extraY = extent.width() * ( self.myParam / 100.00 )
|
687
|
height = extent.height()
|
688
|
width = extent.width()
|
689
|
c = voronoi.Context()
|
690
|
pts = []
|
691
|
ptDict = {}
|
692
|
ptNdx = -1
|
693
|
fit = vprovider.getFeatures()
|
694
|
while fit.nextFeature( inFeat ):
|
695
|
geom = QgsGeometry( inFeat.geometry() )
|
696
|
point = geom.asPoint()
|
697
|
x = point.x() - extent.xMinimum()
|
698
|
y = point.y() - extent.yMinimum()
|
699
|
pts.append( ( x, y ) )
|
700
|
ptNdx +=1
|
701
|
ptDict[ ptNdx ] = inFeat.id()
|
702
|
self.vlayer = None
|
703
|
if len( pts ) < 3:
|
704
|
return False
|
705
|
uniqueSet = Set( item for item in pts )
|
706
|
ids = [ pts.index( item ) for item in uniqueSet ]
|
707
|
sl = voronoi.SiteList( [ voronoi.Site( i[ 0 ], i[ 1 ], sitenum = j ) for j, i in enumerate( uniqueSet ) ] )
|
708
|
voronoi.voronoi( sl, c )
|
709
|
inFeat = QgsFeature()
|
710
|
nFeat = len( c.polygons )
|
711
|
nElement = 0
|
712
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
|
713
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) )
|
714
|
for site, edges in c.polygons.iteritems():
|
715
|
vprovider.getFeatures( QgsFeatureRequest().setFilterFid( ptDict[ ids[ site ] ] ) ).nextFeature( inFeat )
|
716
|
lines = self.clip_voronoi( edges, c, width, height, extent, extraX, extraY )
|
717
|
geom = QgsGeometry.fromMultiPoint( lines )
|
718
|
geom = QgsGeometry( geom.convexHull() )
|
719
|
outFeat.setGeometry( geom )
|
720
|
outFeat.setAttributes( inFeat.attributes() )
|
721
|
writer.addFeature( outFeat )
|
722
|
nElement += 1
|
723
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
|
724
|
del writer
|
725
|
return True
|
726
|
|
727
|
def clip_voronoi( self, edges, c, width, height, extent, exX, exY ):
|
728
|
""" Clip voronoi function based on code written for Inkscape
|
729
|
Copyright (C) 2010 Alvin Penner, [email protected]
|
730
|
"""
|
731
|
def clip_line( x1, y1, x2, y2, w, h, x, y ):
|
732
|
if x1 < 0 - x and x2 < 0 - x:
|
733
|
return [ 0, 0, 0, 0 ]
|
734
|
if x1 > w + x and x2 > w + x:
|
735
|
return [ 0, 0, 0, 0 ]
|
736
|
if x1 < 0 - x:
|
737
|
y1 = ( y1 * x2 - y2 * x1 ) / ( x2 - x1 )
|
738
|
x1 = 0 - x
|
739
|
if x2 < 0 - x:
|
740
|
y2 = ( y1 * x2 - y2 * x1 ) / ( x2 - x1 )
|
741
|
x2 = 0 - x
|
742
|
if x1 > w + x:
|
743
|
y1 = y1 + ( w + x - x1 ) * ( y2 - y1 ) / ( x2 - x1 )
|
744
|
x1 = w + x
|
745
|
if x2 > w + x:
|
746
|
y2 = y1 + ( w + x - x1 ) *( y2 - y1 ) / ( x2 - x1 )
|
747
|
x2 = w + x
|
748
|
if y1 < 0 - y and y2 < 0 - y:
|
749
|
return [ 0, 0, 0, 0 ]
|
750
|
if y1 > h + y and y2 > h + y:
|
751
|
return [ 0, 0, 0, 0 ]
|
752
|
if x1 == x2 and y1 == y2:
|
753
|
return [ 0, 0, 0, 0 ]
|
754
|
if y1 < 0 - y:
|
755
|
x1 = ( x1 * y2 - x2 * y1 ) / ( y2 - y1 )
|
756
|
y1 = 0 - y
|
757
|
if y2 < 0 - y:
|
758
|
x2 = ( x1 * y2 - x2 * y1 ) / ( y2 - y1 )
|
759
|
y2 = 0 - y
|
760
|
if y1 > h + y:
|
761
|
x1 = x1 + ( h + y - y1 ) * ( x2 - x1 ) / ( y2 - y1 )
|
762
|
y1 = h + y
|
763
|
if y2 > h + y:
|
764
|
x2 = x1 + ( h + y - y1) * ( x2 - x1 ) / ( y2 - y1 )
|
765
|
y2 = h + y
|
766
|
return [ x1, y1, x2, y2 ]
|
767
|
lines = []
|
768
|
hasXMin = False
|
769
|
hasYMin = False
|
770
|
hasXMax = False
|
771
|
hasYMax = False
|
772
|
for edge in edges:
|
773
|
if edge[ 1 ] >= 0 and edge[ 2 ] >= 0:
|
774
|
[ x1, y1, x2, y2 ] = clip_line( c.vertices[ edge[ 1 ] ][ 0 ], c.vertices[ edge[ 1 ] ][ 1 ], c.vertices[ edge[ 2 ] ][ 0 ], c.vertices[ edge[ 2 ] ][ 1 ], width, height, exX, exY )
|
775
|
elif edge[ 1 ] >= 0:
|
776
|
if c.lines[ edge[ 0 ] ][ 1 ] == 0:
|
777
|
xtemp = c.lines[ edge[ 0 ] ][ 2 ] / c.lines[ edge[ 0 ] ][ 0 ]
|
778
|
if c.vertices[ edge[ 1 ] ][ 1 ] > ( height + exY ) / 2:
|
779
|
ytemp = height + exY
|
780
|
else:
|
781
|
ytemp = 0 - exX
|
782
|
else:
|
783
|
xtemp = width + exX
|
784
|
ytemp = ( c.lines[ edge[ 0 ] ][ 2 ] - ( width + exX ) * c.lines[ edge[ 0 ] ][ 0 ] ) / c.lines[ edge[ 0 ] ][ 1 ]
|
785
|
[ x1, y1, x2, y2 ] = clip_line( c.vertices[ edge[ 1 ] ][ 0 ], c.vertices[ edge[ 1 ] ][ 1 ], xtemp, ytemp, width, height, exX, exY )
|
786
|
elif edge[ 2 ] >= 0:
|
787
|
if c.lines[ edge[ 0 ] ][ 1 ] == 0:
|
788
|
xtemp = c.lines[ edge[ 0 ] ][ 2 ] / c.lines[ edge[ 0 ] ][ 0 ]
|
789
|
if c.vertices[ edge[ 2 ] ][ 1 ] > ( height + exY ) / 2:
|
790
|
ytemp = height + exY
|
791
|
else:
|
792
|
ytemp = 0.0 - exY
|
793
|
else:
|
794
|
xtemp = 0.0 - exX
|
795
|
ytemp = c.lines[ edge[ 0 ] ][ 2 ] / c.lines[ edge[ 0 ] ][ 1 ]
|
796
|
[ x1, y1, x2, y2 ] = clip_line( xtemp, ytemp, c.vertices[ edge[ 2 ] ][ 0 ], c.vertices[ edge[ 2 ] ][ 1 ], width, height, exX, exY )
|
797
|
if x1 or x2 or y1 or y2:
|
798
|
lines.append( QgsPoint( x1 + extent.xMinimum(), y1 + extent.yMinimum() ) )
|
799
|
lines.append( QgsPoint( x2 + extent.xMinimum(), y2 + extent.yMinimum() ) )
|
800
|
if 0 - exX in ( x1, x2 ):
|
801
|
hasXMin = True
|
802
|
if 0 - exY in ( y1, y2 ):
|
803
|
hasYMin = True
|
804
|
if height + exY in ( y1, y2 ):
|
805
|
hasYMax = True
|
806
|
if width + exX in ( x1, x2 ):
|
807
|
hasXMax = True
|
808
|
if hasXMin:
|
809
|
if hasYMax:
|
810
|
lines.append( QgsPoint( extent.xMinimum() - exX, height + extent.yMinimum() + exY ) )
|
811
|
if hasYMin:
|
812
|
lines.append( QgsPoint( extent.xMinimum() - exX, extent.yMinimum() - exY ) )
|
813
|
if hasXMax:
|
814
|
if hasYMax:
|
815
|
lines.append( QgsPoint( width + extent.xMinimum() + exX, height + extent.yMinimum() + exY ) )
|
816
|
if hasYMin:
|
817
|
lines.append( QgsPoint( width + extent.xMinimum() + exX, extent.yMinimum() - exY ) )
|
818
|
return lines
|
819
|
|
820
|
def layer_extent( self ):
|
821
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
|
822
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, 0 ) )
|
823
|
|
824
|
fields = QgsFields()
|
825
|
fields.append( QgsField( "MINX", QVariant.Double ) )
|
826
|
fields.append( QgsField( "MINY", QVariant.Double ) )
|
827
|
fields.append( QgsField( "MAXX", QVariant.Double ) )
|
828
|
fields.append( QgsField( "MAXY", QVariant.Double ) )
|
829
|
fields.append( QgsField( "CNTX", QVariant.Double ) )
|
830
|
fields.append( QgsField( "CNTY", QVariant.Double ) )
|
831
|
fields.append( QgsField( "AREA", QVariant.Double ) )
|
832
|
fields.append( QgsField( "PERIM", QVariant.Double ) )
|
833
|
fields.append( QgsField( "HEIGHT", QVariant.Double ) )
|
834
|
fields.append( QgsField( "WIDTH", QVariant.Double ) )
|
835
|
|
836
|
writer = QgsVectorFileWriter( self.myName, self.myEncoding, fields,
|
837
|
QGis.WKBPolygon, self.vlayer.crs() )
|
838
|
rect = self.vlayer.extent()
|
839
|
minx = rect.xMinimum()
|
840
|
miny = rect.yMinimum()
|
841
|
maxx = rect.xMaximum()
|
842
|
maxy = rect.yMaximum()
|
843
|
height = rect.height()
|
844
|
width = rect.width()
|
845
|
cntx = minx + ( width / 2.0 )
|
846
|
cnty = miny + ( height / 2.0 )
|
847
|
area = width * height
|
848
|
perim = ( 2 * width ) + (2 * height )
|
849
|
rect = [ QgsPoint( minx, miny ),
|
850
|
QgsPoint( minx, maxy ),
|
851
|
QgsPoint( maxx, maxy ),
|
852
|
QgsPoint( maxx, miny ),
|
853
|
QgsPoint( minx, miny ) ]
|
854
|
geometry = QgsGeometry().fromPolygon( [ rect ] )
|
855
|
feat = QgsFeature()
|
856
|
feat.setGeometry( geometry )
|
857
|
feat.setAttributes( [ minx,
|
858
|
miny,
|
859
|
maxx,
|
860
|
maxy,
|
861
|
cntx,
|
862
|
cnty,
|
863
|
area,
|
864
|
perim,
|
865
|
height,
|
866
|
width ] )
|
867
|
writer.addFeature( feat )
|
868
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, 100 ) )
|
869
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
|
870
|
del writer
|
871
|
|
872
|
return True
|
873
|
|
874
|
def feature_extent( self ):
|
875
|
vprovider = self.vlayer.dataProvider()
|
876
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 )
|
877
|
|
878
|
fields = QgsFields()
|
879
|
fields.append( QgsField( "MINX", QVariant.Double ) )
|
880
|
fields.append( QgsField( "MINY", QVariant.Double ) )
|
881
|
fields.append( QgsField( "MAXX", QVariant.Double ) )
|
882
|
fields.append( QgsField( "MAXY", QVariant.Double ) )
|
883
|
fields.append( QgsField( "CNTX", QVariant.Double ) )
|
884
|
fields.append( QgsField( "CNTY", QVariant.Double ) )
|
885
|
fields.append( QgsField( "AREA", QVariant.Double ) )
|
886
|
fields.append( QgsField( "PERIM", QVariant.Double ) )
|
887
|
fields.append( QgsField( "HEIGHT", QVariant.Double ) )
|
888
|
fields.append( QgsField( "WIDTH", QVariant.Double ) )
|
889
|
|
890
|
writer = QgsVectorFileWriter( self.myName, self.myEncoding, fields,
|
891
|
QGis.WKBPolygon, self.vlayer.crs() )
|
892
|
inFeat = QgsFeature()
|
893
|
outFeat = QgsFeature()
|
894
|
nElement = 0
|
895
|
|
896
|
if self.useSelection:
|
897
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), (0, self.vlayer.selectedFeatureCount() ) )
|
898
|
for inFeat in self.vlayer.selectedFeatures():
|
899
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
|
900
|
nElement += 1
|
901
|
|
902
|
rect = inFeat.geometry().boundingBox()
|
903
|
minx = rect.xMinimum()
|
904
|
miny = rect.yMinimum()
|
905
|
maxx = rect.xMaximum()
|
906
|
maxy = rect.yMaximum()
|
907
|
height = rect.height()
|
908
|
width = rect.width()
|
909
|
cntx = minx + ( width / 2.0 )
|
910
|
cnty = miny + ( height / 2.0 )
|
911
|
area = width * height
|
912
|
perim = ( 2 * width ) + ( 2 * height )
|
913
|
rect = [ QgsPoint( minx, miny ),
|
914
|
QgsPoint( minx, maxy ),
|
915
|
QgsPoint( maxx, maxy ),
|
916
|
QgsPoint( maxx, miny ),
|
917
|
QgsPoint( minx, miny ) ]
|
918
|
geometry = QgsGeometry().fromPolygon( [ rect ] )
|
919
|
|
920
|
outFeat.setGeometry( geometry )
|
921
|
outFeat.setAttributes( [ minx,
|
922
|
miny,
|
923
|
maxx,
|
924
|
maxy,
|
925
|
cntx,
|
926
|
cnty,
|
927
|
area,
|
928
|
perim,
|
929
|
height,
|
930
|
width ] )
|
931
|
writer.addFeature( outFeat )
|
932
|
else:
|
933
|
self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, vprovider.featureCount() ) )
|
934
|
fit = vprovider.getFeatures()
|
935
|
while fit.nextFeature( inFeat ):
|
936
|
self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement )
|
937
|
nElement += 1
|
938
|
|
939
|
rect = inFeat.geometry().boundingBox()
|
940
|
minx = rect.xMinimum()
|
941
|
miny = rect.yMinimum()
|
942
|
maxx = rect.xMaximum()
|
943
|
maxy = rect.yMaximum()
|
944
|
height = rect.height()
|
945
|
width = rect.width()
|
946
|
cntx = minx + ( width / 2.0 )
|
947
|
cnty = miny + ( height / 2.0 )
|
948
|
area = width * height
|
949
|
perim = ( 2 * width ) + ( 2 * height )
|
950
|
rect = [ QgsPoint( minx, miny ),
|
951
|
QgsPoint( minx, maxy ),
|
952
|
QgsPoint( maxx, maxy ),
|
953
|
QgsPoint( maxx, miny ),
|
954
|
QgsPoint( minx, miny ) ]
|
955
|
geometry = QgsGeometry().fromPolygon( [ rect ] )
|
956
|
|
957
|
outFeat.setGeometry( geometry )
|
958
|
outFeat.setAttributes( [ minx,
|
959
|
miny,
|
960
|
maxx,
|
961
|
maxy,
|
962
|
cntx,
|
963
|
cnty,
|
964
|
area,
|
965
|
perim,
|
966
|
height,
|
967
|
width ] )
|
968
|
writer.addFeature( outFeat )
|
969
|
|
970
|
del writer
|
971
|
return True
|
972
|
|
973
|
def simpleMeasure( self, inGeom, calcType, ellips, crs ):
|
974
|
if inGeom.wkbType() in ( QGis.WKBPoint, QGis.WKBPoint25D ):
|
975
|
pt = inGeom.asPoint()
|
976
|
attr1 = pt.x()
|
977
|
attr2 = pt.y()
|
978
|
elif inGeom.wkbType() in ( QGis.WKBMultiPoint, QGis.WKBMultiPoint25D ):
|
979
|
pt = inGeom.asMultiPoint()
|
980
|
attr1 = pt[ 0 ].x()
|
981
|
attr2 = pt[ 0 ].y()
|
982
|
else:
|
983
|
measure = QgsDistanceArea()
|
984
|
|
985
|
if calcType == 2:
|
986
|
measure.setSourceCrs( crs )
|
987
|
measure.setEllipsoid( ellips )
|
988
|
measure.setEllipsoidalMode( True )
|
989
|
|
990
|
attr1 = measure.measure( inGeom )
|
991
|
if inGeom.type() == QGis.Polygon:
|
992
|
attr2 = self.perimMeasure( inGeom, measure )
|
993
|
else:
|
994
|
attr2 = attr1
|
995
|
return ( attr1, attr2 )
|
996
|
|
997
|
def perimMeasure( self, inGeom, measure ):
|
998
|
value = 0.00
|
999
|
if inGeom.isMultipart():
|
1000
|
poly = inGeom.asMultiPolygon()
|
1001
|
for k in poly:
|
1002
|
for j in k:
|
1003
|
value = value + measure.measureLine( j )
|
1004
|
else:
|
1005
|
poly = inGeom.asPolygon()
|
1006
|
for k in poly:
|
1007
|
value = value + measure.measureLine( k )
|
1008
|
return value
|
1009
|
|
1010
|
def doubleFieldIndex( self, name, desc, fieldList ):
|
1011
|
i = 0
|
1012
|
for f in fieldList:
|
1013
|
if name == f.name().upper():
|
1014
|
return (i, fieldList )
|
1015
|
i += 1
|
1016
|
|
1017
|
fieldList.append( QgsField( name, QVariant.Double, "double precision", 21, 6, desc ) )
|
1018
|
return ( len(fieldList)-1, fieldList )
|
1019
|
|
1020
|
def checkMeasurementFields( self, vlayer, add ):
|
1021
|
vprovider = vlayer.dataProvider()
|
1022
|
geomType = vlayer.geometryType()
|
1023
|
fieldList = vprovider.fields()
|
1024
|
|
1025
|
idx = len(fieldList)
|
1026
|
|
1027
|
if geomType == QGis.Polygon:
|
1028
|
(index1, fieldList) = self.doubleFieldIndex( "AREA", self.tr( "Polygon area" ), fieldList )
|
1029
|
(index2, fieldList) = self.doubleFieldIndex( "PERIMETER", self.tr( "Polygon perimeter" ), fieldList )
|
1030
|
elif geomType == QGis.Line:
|
1031
|
(index1, fieldList) = self.doubleFieldIndex( "LENGTH", self.tr( "Line length" ), fieldList )
|
1032
|
index2 = index1
|
1033
|
else:
|
1034
|
(index1, fieldList) = self.doubleFieldIndex( "XCOORD", self.tr( "Point x ordinate" ), fieldList )
|
1035
|
(index2, fieldList) = self.doubleFieldIndex( "YCOORD", self.tr( "Point y ordinate" ), fieldList )
|
1036
|
|
1037
|
if add and idx<len(fieldList):
|
1038
|
newFields = []
|
1039
|
for i in range(idx,len(fieldList)):
|
1040
|
newFields.append(fieldList[i])
|
1041
|
vprovider.addAttributes( newFields )
|
1042
|
|
1043
|
return ( fieldList, index1, index2 )
|
1044
|
|
1045
|
def extractAsLine( self, geom ):
|
1046
|
multi_geom = QgsGeometry()
|
1047
|
temp_geom = []
|
1048
|
if geom.type() == 2:
|
1049
|
if geom.isMultipart():
|
1050
|
multi_geom = geom.asMultiPolygon()
|
1051
|
for i in multi_geom:
|
1052
|
temp_geom.extend( i )
|
1053
|
else:
|
1054
|
multi_geom = geom.asPolygon()
|
1055
|
temp_geom = multi_geom
|
1056
|
return temp_geom
|
1057
|
else:
|
1058
|
return []
|
1059
|
|
1060
|
def remove_bad_lines( self, lines ):
|
1061
|
temp_geom = []
|
1062
|
if len( lines ) == 1:
|
1063
|
if len( lines[ 0 ] ) > 2:
|
1064
|
temp_geom = lines
|
1065
|
else:
|
1066
|
temp_geom = []
|
1067
|
else:
|
1068
|
temp_geom = [ elem for elem in lines if len( elem ) > 2 ]
|
1069
|
return temp_geom
|
1070
|
|
1071
|
def singleToMultiGeom( self, wkbType ):
|
1072
|
try:
|
1073
|
if wkbType in ( QGis.WKBPoint, QGis.WKBMultiPoint,
|
1074
|
QGis.WKBPoint25D, QGis.WKBMultiPoint25D ):
|
1075
|
return QGis.WKBMultiPoint
|
1076
|
elif wkbType in ( QGis.WKBLineString, QGis.WKBMultiLineString,
|
1077
|
QGis.WKBMultiLineString25D, QGis.WKBLineString25D ):
|
1078
|
return QGis.WKBMultiLineString
|
1079
|
elif wkbType in ( QGis.WKBPolygon, QGis.WKBMultiPolygon,
|
1080
|
QGis.WKBMultiPolygon25D, QGis.WKBPolygon25D ):
|
1081
|
return QGis.WKBMultiPolygon
|
1082
|
else:
|
1083
|
return QGis.WKBUnknown
|
1084
|
except Exception, err:
|
1085
|
print str( err )
|
1086
|
|
1087
|
def multiToSingleGeom( self, wkbType ):
|
1088
|
try:
|
1089
|
if wkbType in ( QGis.WKBPoint, QGis.WKBMultiPoint,
|
1090
|
QGis.WKBPoint25D, QGis.WKBMultiPoint25D ):
|
1091
|
return QGis.WKBPoint
|
1092
|
elif wkbType in ( QGis.WKBLineString, QGis.WKBMultiLineString,
|
1093
|
QGis.WKBMultiLineString25D, QGis.WKBLineString25D ):
|
1094
|
return QGis.WKBLineString
|
1095
|
elif wkbType in ( QGis.WKBPolygon, QGis.WKBMultiPolygon,
|
1096
|
QGis.WKBMultiPolygon25D, QGis.WKBPolygon25D ):
|
1097
|
return QGis.WKBPolygon
|
1098
|
else:
|
1099
|
return QGis.WKBUnknown
|
1100
|
except Exception, err:
|
1101
|
print str( err )
|
1102
|
|
1103
|
def extractAsSingle( self, geom ):
|
1104
|
multi_geom = QgsGeometry()
|
1105
|
temp_geom = []
|
1106
|
if geom.type() == 0:
|
1107
|
if geom.isMultipart():
|
1108
|
multi_geom = geom.asMultiPoint()
|
1109
|
for i in multi_geom:
|
1110
|
temp_geom.append( QgsGeometry().fromPoint ( i ) )
|
1111
|
else:
|
1112
|
temp_geom.append( geom )
|
1113
|
elif geom.type() == 1:
|
1114
|
if geom.isMultipart():
|
1115
|
multi_geom = geom.asMultiPolyline()
|
1116
|
for i in multi_geom:
|
1117
|
temp_geom.append( QgsGeometry().fromPolyline( i ) )
|
1118
|
else:
|
1119
|
temp_geom.append( geom )
|
1120
|
elif geom.type() == 2:
|
1121
|
if geom.isMultipart():
|
1122
|
multi_geom = geom.asMultiPolygon()
|
1123
|
for i in multi_geom:
|
1124
|
temp_geom.append( QgsGeometry().fromPolygon( i ) )
|
1125
|
else:
|
1126
|
temp_geom.append( geom )
|
1127
|
return temp_geom
|
1128
|
|
1129
|
def extractAsMulti( self, geom ):
|
1130
|
temp_geom = []
|
1131
|
if geom.type() == 0:
|
1132
|
if geom.isMultipart():
|
1133
|
return geom.asMultiPoint()
|
1134
|
else:
|
1135
|
return [ geom.asPoint() ]
|
1136
|
elif geom.type() == 1:
|
1137
|
if geom.isMultipart():
|
1138
|
return geom.asMultiPolyline()
|
1139
|
else:
|
1140
|
return [ geom.asPolyline() ]
|
1141
|
else:
|
1142
|
if geom.isMultipart():
|
1143
|
return geom.asMultiPolygon()
|
1144
|
else:
|
1145
|
return [ geom.asPolygon() ]
|
1146
|
|
1147
|
def convertGeometry( self, geom_list, vType ):
|
1148
|
if vType == 0:
|
1149
|
return QgsGeometry().fromMultiPoint( geom_list )
|
1150
|
elif vType == 1:
|
1151
|
return QgsGeometry().fromMultiPolyline( geom_list )
|
1152
|
else:
|
1153
|
return QgsGeometry().fromMultiPolygon( geom_list )
|