doGeometry.py

replace older with this one, but don't forget to backup older first - Dedy Fuadi, 2014-05-25 02:12 AM

Download (43.9 KB)

 
1
# -*- coding: utf-8 -*-
2
#-----------------------------------------------------------
3
#
4
# fTools
5
# Copyright (C) 2008-2011  Carson Farmer
6
# EMAIL: carson.farmer (at) gmail.com
7
# WEB  : http://www.ftools.ca/fTools.html
8
#
9
# A collection of data management and analysis tools for vector data
10
#
11
#-----------------------------------------------------------
12
#
13
# licensed under the terms of GNU GPL 2
14
#
15
# This program is free software; you can redistribute it and/or modify
16
# it under the terms of the GNU General Public License as published by
17
# the Free Software Foundation; either version 2 of the License, or
18
# (at your option) any later version.
19
#
20
# This program is distributed in the hope that it will be useful,
21
# but WITHOUT ANY WARRANTY; without even the implied warranty of
22
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
# GNU General Public License for more details.
24
#
25
# You should have received a copy of the GNU General Public License along
26
# with this program; if not, write to the Free Software Foundation, Inc.,
27
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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: # Singleparts to multipart
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: # Multipart to singleparts
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: # Extract nodes
118
      self.setWindowTitle( self.tr( "Extract nodes" ) )
119
      self.lineEdit.setVisible( False )
120
      self.label.setVisible( False )
121
    elif self.myFunction == 4: # Polygons to lines
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: # Export/Add geometry columns
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
      # populate calculation types
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: # Polygon centroids
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: # Delaunay triangulation
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: # Voronoi Polygons
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: #Lines to polygons
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: # Polygon from layer extent
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
#1:  Singleparts to multipart
205
#2:  Multipart to singleparts
206
#3:  Extract nodes
207
#4:  Polygons to lines
208
#5:  Export/Add geometry columns
209
#6:  Simplify geometries (disabled)
210
#7:  Polygon centroids
211
#8:  Delaunay triangulation
212
#9:  Polygon from layer extent
213
#10: Voronoi polygons
214
#11: Lines to polygons
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: # Singleparts to multipart
325
      success = self.single_to_multi()
326
    elif self.myFunction == 2: # Multipart to singleparts
327
      success = self.multi_to_single()
328
    elif self.myFunction == 3: # Extract nodes
329
      success = self.extract_nodes()
330
    elif self.myFunction == 4: # Polygons to lines
331
      success = self.polygons_to_lines()
332
    elif self.myFunction == 5: # Export/Add geometry columns
333
      success = self.export_geometry_info()
334
    # note that 6 used to be associated with simplify_geometry
335
    elif self.myFunction == 7: # Polygon centroids
336
      success = self.polygon_centroids()
337
    elif self.myFunction == 8: # Delaunay triangulation
338
      success = self.delaunay_triangulation()
339
    elif self.myFunction == 9: # Polygon from layer extent
340
      if self.byFeatures:
341
        success = self.feature_extent()
342
      else:
343
        success = self.layer_extent()
344
    elif self.myFunction == 10: # Voronoi Polygons
345
      success = self.voronoi_polygons()
346
    elif self.myFunction == 11: # Lines to polygons
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
    # calculate with:
528
    # 0 - layer CRS
529
    # 1 - project CRS
530
    # 2 - ellipsoidal
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:       # two vertices
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:                      # only one vertex
776
        if c.lines[ edge[ 0 ] ][ 1 ] == 0:      # vertical line
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:                       # only one vertex
787
        if c.lines[ edge[ 0 ] ][ 1 ] == 0:       # vertical line
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 )