QGIS/python/plugins/fTools/tools/ftools_utils.py
cfarmer 24ba0309ff Large commit with several related bug fixes:
1) All fTools functions should now add all layers to dropdowns (including non-visible layers), 
2) All fTools functions should now be non-modal
3) Several fTools functions have been spead up slightly
4) Where possible, internal (cpp) functions have be used to replace older Python functions
5) Defining projections now also considers .qpj files
Fixes bugs #2502 and #2506, and possibly others?


git-svn-id: http://svn.osgeo.org/qgis/trunk@13037 c8812cc2-4d05-0410-92ff-de0c093fc19c
2010-03-10 01:11:11 +00:00

297 lines
11 KiB
Python
Executable File

# -*- coding: utf-8 -*-
# Utility functions
# -------------------------------------------------
#
# combineVectorAttributes( QgsAttributeMap, QgsAttributeMap )
# convertFieldNameType( QgsField.name() )
# combineVectorFields( QgsVectorLayer, QgsVectorLayer )
# checkCRSCompatibility( QgsCoordinateReferenceSystem, QgsCoordinateReferenceSystem )
# writeVectorLayerToShape(QgsVectorLayer, QString *file path, QString *encoding style )
# getVectorTypeAsString( QgsVectorLayer )
# measurePerimeter( QgsGeometry )
# extractPoints( QgsGeometry )
# testForUniqueness( QList *QgsField, QList *QgsField )
# createUniqueFieldName( QgsField.name() )
# getLayerNames( QGis.vectorType() )
# getFieldNames( QgsVectorLayer )
# getVectorLayerByName( QgsVectorLayer.name() )
# getFieldList( QgsVectorLayer )
# createIndex( QgsVectorDataProvider )
# addShapeToCanvas( QString *file path )
# getUniqueValues( QgsVectorDataProvider, int *field id )
# saveDialog( QWidget *parent )
# getFieldType( QgsVectorLayer, QgsField.name() )
# getUniqueValuesCount( QgsVectorLayer, int fieldIndex, bool useSelection ):
#
# -------------------------------------------------
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
# From two input attribute maps, create single attribute map
def combineVectorAttributes( atMapA, atMapB ):
attribA = atMapA.values()
lengthA = len(attribA)
attribB = atMapB.values()
lengthB = len(attribB)
attribA.extend( attribB )
return dict( zip( range( 0, lengthB + lengthA ), attribA ) )
# For use with memory provider/layer, converts full field type to simple string
def convertFieldNameType( inName ):
if inName == "Integer":
return "int"
elif inName == "Real":
return "double"
else:
return "string"
# From two input field maps, create single field map
def combineVectorFields( layerA, layerB ):
fieldsA = layerA.dataProvider().fields().values()
fieldsB = layerB.dataProvider().fields().values()
fieldsB = testForUniqueness( fieldsA, fieldsB )
seq = range( 0, len( fieldsA ) + len( fieldsB ) )
fieldsA.extend( fieldsB )
fieldsA = dict( zip ( seq, fieldsA ) )
return fieldsA
# Check if two input CRSs are identical
def checkCRSCompatibility( crsA, crsB ):
if crsA == crsB:
return True
else:
return False
# Convenience function to write vector layer to shapefile
def writeVectorLayerToShape( vlayer, outputPath, encoding ):
mCodec = QTextCodec.codecForName( QString(encoding).toLocal8Bit().data() )
if not mCodec:
return False
#Here we should check that the output path is valid
QgsVectorFileWriter.writeAsShapefile( vlayer, outputPath, encoding, vlayer.dataProvider().crs(), False )
return True
# For use with memory provider/layer, converts QGis vector type definition to simple string
def getVectorTypeAsString( vlayer ):
if vlayer.geometryType() == QGis.Polygon:
return "Polygon"
elif vlayer.geometryType() == QGis.Line:
return "LineString"
elif vlayer.geometryType() == QGis.Point:
return "Point"
else:
return False
# Compute area and perimeter of input polygon geometry
def getAreaAndPerimeter( geom ):
measure = QgsDistanceArea()
area = measure.measure( geom )
perim = measurePerimeter( geom, measure )
return ( area, perim )
# Compute perimeter of input polygon geometry
def measurePerimeter( geom ):
measure = QgsDistanceArea()
value = 0.00
polygon = geom.asPolygon()
for line in polygon:
value += measure.measureLine( line )
return value
# Generate list of QgsPoints from input geometry ( can be point, line, or polygon )
def extractPoints( geom ):
multi_geom = QgsGeometry()
temp_geom = []
if geom.type() == 0: # it's a point
if geom.isMultipart():
temp_geom = geom.asMultiPoint()
else:
temp_geom.append(geom.asPoint())
if geom.type() == 1: # it's a line
if geom.isMultipart():
multi_geom = geom.asMultiPolyline() #multi_geog is a multiline
for i in multi_geom: #i is a line
temp_geom.extend( i )
else:
temp_geom = geom.asPolyline()
elif geom.type() == 2: # it's a polygon
if geom.isMultipart():
multi_geom = geom.asMultiPolygon() #multi_geom is a multipolygon
for i in multi_geom: #i is a polygon
for j in i: #j is a line
temp_geom.extend( j )
else:
multi_geom = geom.asPolygon() #multi_geom is a polygon
for i in multi_geom: #i is a line
temp_geom.extend( i )
return temp_geom
# Check if two input field maps are unique, and resolve name issues if they aren't
def testForUniqueness( fieldList1, fieldList2 ):
changed = True
while changed:
changed = False
for i in fieldList1:
for j in fieldList2:
if j.name() == i.name():
j = createUniqueFieldName( j )
changed = True
return fieldList2
# Create a unique field name based on input field name
def createUniqueFieldName( field ):
check = field.name().right( 2 )
if check.startsWith("_"):
( val, test ) = check.right( 1 ).toInt()
if test:
if val < 2:
val = 2
else:
val = val + 1
field.setName( field.name().left( len( field.name() )-1 ) + unicode( val ) )
else:
field.setName( field.name() + "_2" )
else:
field.setName( field.name() + "_2" )
return field
# Return list of names of all layers in QgsMapLayerRegistry
def getLayerNames( vTypes ):
layermap = QgsMapLayerRegistry.instance().mapLayers()
layerlist = []
if vTypes == "all":
for name, layer in layermap.iteritems():
layerlist.append( unicode( layer.name() ) )
else:
for name, layer in layermap.iteritems():
if layer.type() == QgsMapLayer.VectorLayer:
if layer.geometryType() in vTypes:
layerlist.append( unicode( layer.name() ) )
elif layer.type() == QgsMapLayer.RasterLayer:
if "Raster" in vTypes:
layerlist.append( unicode( layer.name() ) )
return layerlist
# Return list of names of all fields from input QgsVectorLayer
def getFieldNames( vlayer ):
fieldmap = getFieldList( vlayer )
fieldlist = []
for name, field in fieldmap.iteritems():
if not field.name() in fieldlist:
fieldlist.append( unicode( field.name() ) )
return fieldlist
# Return QgsVectorLayer from a layer name ( as string )
def getVectorLayerByName( myName ):
layermap = QgsMapLayerRegistry.instance().mapLayers()
for name, layer in layermap.iteritems():
if layer.type() == QgsMapLayer.VectorLayer and layer.name() == myName:
if layer.isValid():
return layer
else:
return None
# Return QgsMapLayer from a layer name ( as string )
def getMapLayerByName( myName ):
layermap = QgsMapLayerRegistry.instance().mapLayers()
for name, layer in layermap.iteritems():
if layer.name() == myName:
if layer.isValid():
return layer
else:
return None
# Return the field list of a vector layer
def getFieldList( vlayer ):
vprovider = vlayer.dataProvider()
feat = QgsFeature()
allAttrs = vprovider.attributeIndexes()
vprovider.select( allAttrs )
myFields = vprovider.fields()
return myFields
# Convinience function to create a spatial index for input QgsVectorDataProvider
def createIndex( provider ):
feat = QgsFeature()
index = QgsSpatialIndex()
provider.rewind()
while provider.nextFeature( feat ):
index.insertFeature( feat )
return index
# Convinience function to add a vector layer to canvas based on input shapefile path ( as string )
def addShapeToCanvas( shapefile_path ):
file_info = QFileInfo( shapefile_path )
if file_info.exists():
layer_name = file_info.completeBaseName()
else:
return False
vlayer_new = QgsVectorLayer( shapefile_path, layer_name, "ogr" )
print layer_name
if vlayer_new.isValid():
QgsMapLayerRegistry.instance().addMapLayer( vlayer_new )
return True
else:
return False
# Return all unique values in field based on field index
def getUniqueValues( provider, index ):
allAttrs = provider.attributeIndexes()
provider.select( allAttrs )
f = QgsFeature()
values = []
check = []
while provider.nextFeature( f ):
if not f.attributeMap()[ index ].toString() in check:
values.append( f.attributeMap()[ index ] )
check.append( f.attributeMap()[ index ].toString() )
return values
# Generate a save file dialog with a dropdown box for choosing encoding style
def saveDialog( parent ):
settings = QSettings()
dirName = settings.value( "/UI/lastShapefileDir" ).toString()
filtering = QString( "Shapefiles (*.shp)" )
encode = settings.value( "/UI/encoding" ).toString()
fileDialog = QgsEncodingFileDialog( parent, "Save output shapefile", dirName, filtering, encode )
fileDialog.setDefaultSuffix( QString( "shp" ) )
fileDialog.setFileMode( QFileDialog.AnyFile )
fileDialog.setAcceptMode( QFileDialog.AcceptSave )
fileDialog.setConfirmOverwrite( True )
if not fileDialog.exec_() == QDialog.Accepted:
return None, None
files = fileDialog.selectedFiles()
settings.setValue("/UI/lastShapefileDir", QVariant( QFileInfo( unicode( files.first() ) ).absolutePath() ) )
return ( unicode( files.first() ), unicode( fileDialog.encoding() ) )
# Return field type from it's name
def getFieldType(vlayer, fieldName):
fields = vlayer.dataProvider().fields()
for name, field in fields.iteritems():
if field.name() == fieldName:
return field.typeName()
# return the number of unique values in field
def getUniqueValuesCount( vlayer, fieldIndex, useSelection ):
vprovider = vlayer.dataProvider()
allAttrs = vprovider.attributeIndexes()
vprovider.select( allAttrs )
count = 0
values = []
if useSelection:
selection = vlayer.selectedFeatures()
for f in selection:
if f.attributeMap()[ fieldIndex ].toString() not in values:
values.append( f.attributeMap()[ fieldIndex ].toString() )
count += 1
else:
feat = QgsFeature()
while vprovider.nextFeature( feat ):
if feat.attributeMap()[ fieldIndex ].toString() not in values:
values.append( feat.attributeMap()[ fieldIndex ].toString() )
count += 1
return count