# -*- 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() ) # checkFieldNameLength( QgsFieldMap ) # 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 ) shortName = field.name().left( 8 ) if check.startsWith("_"): ( val, test ) = check.right( 1 ).toInt() if test: if val < 2: val = 2 else: val = val + 1 field.setName( shortName.left( len( shortName )-1 ) + unicode( val ) ) else: field.setName( shortName + "_2" ) else: field.setName( shortName + "_2" ) return field # Return list of field names with more than 10 characters length def checkFieldNameLength( fieldList ): longNames = QStringList() for num, field in fieldList.iteritems(): if field.name().size() > 10: longNames << unicode( field.name() ) return longNames # 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, filtering="Shapefiles (*.shp)"): settings = QSettings() dirName = settings.value( "/UI/lastShapefileDir" ).toString() encode = settings.value( "/UI/encoding" ).toString() fileDialog = QgsEncodingFileDialog( parent, "Save output shapefile", dirName, QString(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() ) ) # Generate a save file dialog with a dropdown box for choosing encoding style def openDialog( parent, filtering="Shapefiles (*.shp)"): settings = QSettings() dirName = settings.value( "/UI/lastShapefileDir" ).toString() encode = settings.value( "/UI/encoding" ).toString() fileDialog = QgsEncodingFileDialog( parent, "Save output shapefile", dirName, QString(filtering), encode ) fileDialog.setFileMode( QFileDialog.AnyFile ) fileDialog.setAcceptMode( QFileDialog.AcceptOpen ) 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() ) ) # Generate a select directory dialog with a dropdown box for choosing encoding style def dirDialog( parent ): settings = QSettings() dirName = settings.value( "/UI/lastShapefileDir" ).toString() encode = settings.value( "/UI/encoding" ).toString() fileDialog = QgsEncodingFileDialog( parent, "Save output shapefile", dirName, encode ) fileDialog.setFileMode( QFileDialog.DirectoryOnly ) fileDialog.setAcceptMode( QFileDialog.AcceptSave ) fileDialog.setConfirmOverwrite( False ) if not fileDialog.exec_() == QDialog.Accepted: return None, None folders = fileDialog.selectedFiles() settings.setValue("/UI/lastShapefileDir", QVariant( QFileInfo( unicode( folders.first() ) ) ) ) return ( unicode( folders.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