Mengaplikasikan renderer lulusan di PyQGIS? [Tutup]

8

Hanya mencoba menjalankan kode berikut yang sudah diberikan dalam buku masak pyqgis untuk membuat simbologi warna berskala (seperti misalnya dengan 2 kelas)

Saya mendefinisikan sumber info untuk shapefile tetapi ketika saya menjalankan mengeksekusi kode dalam plugin-pengujian saya, itu hanya menambahkan lapisan tanpa mengklasifikasikan. Hanya menambahkan seperti biasa, semua polyline tampak sama.

Ada solusi atau kode / metode kerja?

tautan ke kode di buku masak http://www.qgis.org/pyqgis-cookbook/vector.html#graduated-symbol-renderer

from qgis.core import  (QgsVectorLayer, QgsMapLayerRegistry, QgsGraduatedSymbolRendererV2, QgsSymbolV2,QgsRendererRangeV2)

myVectorLayer = QgsVectorLayer('C:/my_test_shape_file.shp', 'test_shp_file', 'ogr')

myTargetField = 'target_field'
myRangeList = []
myOpacity = 1

# Make our first symbol and range...
myMin = 0.0
myMax = 50.0
myLabel = 'Group 1'
myColour = QtGui.QColor('#ffee00')
mySymbol1 = QgsSymbolV2.defaultSymbol(myVectorLayer.geometryType())
mySymbol1.setColor(myColour)
mySymbol1.setAlpha(myOpacity)
myRange1 = QgsRendererRangeV2(myMin, myMax, mySymbol1, myLabel)
myRangeList.append(myRange1)

#now make another symbol and range...
myMin = 50.1
myMax = 100
myLabel = 'Group 2'
myColour = QtGui.QColor('#00eeff')
mySymbol2 = QgsSymbolV2.defaultSymbol(myVectorLayer.geometryType())
mySymbol2.setColor(myColour)
mySymbol2.setAlpha(myOpacity)
myRange2 = QgsRendererRangeV2( myMin, myMax, mySymbol2, myLabel)
myRangeList.append(myRange2)

myRenderer = QgsGraduatedSymbolRendererV2('', myRangeList)
myRenderer.setMode(QgsGraduatedSymbolRendererV2.EqualInterval)
myRenderer.setClassAttribute(myTargetField)
myVectorLayer.setRendererV2(myRenderer)
QgsMapLayerRegistry.instance().addMapLayer(myVectorLayer) 

@ Kode Kelly bekerja dengan sempurna.

Namun saya perhatikan bahwa kedua kodenya (yang saya ketik di pesan pertama dan milik Anda di pesan ke-2) JANGAN bekerja di QGIS v1.7.3 tetapi BEKERJA di QGIS v1.8.0. Saya pikir ini adalah bug (?) Yang sudah teratasi di v1.8.0

Dan satu pertanyaan lagi;

Apakah Anda memiliki kode sampel untuk (alami istirahat, Jenks) klasifikasi "numeric_attribute_field" berdasarkan jumlah kelas yang diberikan (yaitu tidak ada kelas akan menjadi variabel dalam kode, katakan "n", dan saya akan meneruskannya dari plugin GUI yaitu n = spinBox.value ())

cempro
sumber
1
Baca bantuan tentang cara memformat kode untuk situs ini. Saya telah memperbaikinya untuk Anda saat ini.
Nathan W

Jawaban:

20

Saya menemukan bahwa dengan layer point saya menggunakan garis berikut kembali None

mySymbol1 = QgsSymbolV2.defaultSymbol(myVectorLayer.geometryType())

Namun ini bisa diperbaiki dengan menggantinya dengan panggilan ke validatedDefaultSymbolmetode dari kode di bawah ini. Premis dasarnya adalah menelepon QgsSymbolV2.defaultSymbol()dan kemudian memvalidasi dan jika perlu melakukan koreksi.


Perubahan untuk memastikan kompatibilitas dengan QGIS 1.8 dan master saat ini (27/01/13); meluas ke serangkaian contoh dengan ruang lingkup yang lebih luas. *

Cuplikan di bawah ini diformat untuk ditempelkan ke konsol python dan untuk diterapkan ke Natural Earth Data 1: 10m Tempat Penduduk tersedia dari sini . Perhatikan bahwa cuplikan selanjutnya memiliki dependensi pada definisi dan impor dari yang pertama.

1) Ini adalah contoh penerapan kategori khusus tetapi kode sulit ke lapisan tertentu.

from PyQt4.QtGui import *

def validatedDefaultSymbol( geometryType ):
    symbol = QgsSymbolV2.defaultSymbol( geometryType )
    if symbol is None:
        if geometryType == QGis.Point:
            symbol = QgsMarkerSymbolV2()
        elif geometryType == QGis.Line:
            symbol =  QgsLineSymbolV2 ()
        elif geometryType == QGis.Polygon:
            symbol = QgsFillSymbolV2 ()
    return symbol

def makeSymbologyForRange( layer, min , max, title, color):
    symbol = validatedDefaultSymbol( layer.geometryType() )
    symbol.setColor( color )
    range = QgsRendererRangeV2( min, max, symbol, title )
    return range

def applySymbologyFixedDivisions( layer, field ):
    rangeList = []
    rangeList.append( makeSymbologyForRange( layer, -99, 999999.9, '<1 Million', QColor("Green") ) )
    rangeList.append( makeSymbologyForRange( layer, 1000000, 10000000, '1-10 Million',  QColor("Purple") ) )
    rangeList.append( makeSymbologyForRange( layer, 10000000.1, 100000000, '>10 Million', QColor("Orange") ) )
    renderer = QgsGraduatedSymbolRendererV2( field, rangeList )
    renderer.setMode( QgsGraduatedSymbolRendererV2.Custom )
    layer.setRendererV2( renderer )

targetField = 'POP_OTHER'
layer = QgsVectorLayer( 'C:/data/ne_10m_populated_places.shp', 'Fixed Divisions', 'ogr' )
if layer.isValid():
    applySymbologyFixedDivisions( layer, targetField )
    QgsMapLayerRegistry.instance().addMapLayers( [layer] )

2) Contoh ini berlaku, pada gilirannya, masing-masing mode standar yang didukung oleh QgsGraduatedSymbolRendererV2. Nilai kelas akan diperlakukan sebagai petunjuk daripada aturan seperti yang disyaratkan oleh setiap mode tertentu. Garis setSizeScaleField dapat dibatalkan komentar jika diinginkan, namun nilai kolom LABELRANK terlalu besar untuk terlihat bagus di tingkat zoom standar.

def applyGraduatedSymbologyStandardMode( layer, field, classes, mode):
    symbol = validatedDefaultSymbol( layer.geometryType() )
    colorRamp = QgsVectorGradientColorRampV2.create({'color1':'255,0,0,255', 'color2':'0,0,255,255','stops':'0.25;255,255,0,255:0.50;0,255,0,255:0.75;0,255,255,255'})
    renderer = QgsGraduatedSymbolRendererV2.createRenderer( layer, field, classes, mode, symbol, colorRamp )
    #renderer.setSizeScaleField("LABELRANK")
    layer.setRendererV2( renderer )

modes = { QgsGraduatedSymbolRendererV2.EqualInterval : "Equal Interval",
          QgsGraduatedSymbolRendererV2.Quantile      : "Quantile",
          QgsGraduatedSymbolRendererV2.Jenks         : "Natural Breaks (Jenks)",
          QgsGraduatedSymbolRendererV2.StdDev        : "Standard Deviation",
          QgsGraduatedSymbolRendererV2.Pretty        : "Pretty Breaks"
        }

targetField = 'POP_OTHER'
classes = 6
for mode in modes.keys():
    layer = QgsVectorLayer('C:/data/ne_10m_populated_places.shp', modes[mode] , 'ogr')
    if layer.isValid():
        applyGraduatedSymbologyStandardMode( layer, targetField, classes, mode)
        QgsMapLayerRegistry.instance().addMapLayers( [layer] ) 

3) Contoh ini menunjukkan penerapan divisi kustom dinamis. Dalam hal ini fitur diurutkan berdasarkan nilai, kemudian dibagi menjadi beberapa kelompok sehingga jumlah nilai dalam setiap kategori sama. yaitu membagi populasi dunia menjadi pertiga yang hidup di tempat-tempat populasi terkecil / sedang / terbesar.

def getSortedFloatsFromAttributeTable( layer, fieldName ):
    provider = layer.dataProvider()
    fieldIndex = provider.fieldNameIndex(fieldName)
    provider.select( [fieldIndex] )
    values = []
    feature = QgsFeature()
    while provider.nextFeature( feature ):
        values.append( feature.attributeMap()[fieldIndex].toFloat()[0] )
    values.sort()
    return values

def arbitaryColor( amount, max ):
    color = QColor()
    color.setHsv( 240 * amount / float( max - 1 ), 255, 255 )
    return color

def makeGraduatedRendererFromDivisionsList( layer, fieldName, divisions ):
    classes = len( divisions ) - 1
    rangeList = []
    for i in range( classes ):
        label = str( divisions[i] ) + " < X < " + str( divisions[i+1] )
        rangeList.append( makeSymbologyForRange( layer, divisions[i] , divisions[i+1], label, arbitaryColor( i, classes ) ) )
    renderer = QgsGraduatedSymbolRendererV2( fieldName, rangeList )
    renderer.setMode( QgsGraduatedSymbolRendererV2.Custom )
    return renderer

def applySymbologyEqualTotalValue( layer, classes, fieldName):
    values = getSortedFloatsFromAttributeTable( layer, fieldName )
    total = sum( values )
    step = total / float( classes )
    nextStep = step
    divisions = [ values[0] ]
    runningTotal = 0
    for value in values:
        runningTotal += value
        if runningTotal >= nextStep:
            divisions.append( value )
            nextStep += step
    if divisions[-1] != values[-1]:
        divisions.append(values[-1])
    renderer = makeGraduatedRendererFromDivisionsList( layer, fieldName, divisions )
    layer.setRendererV2( renderer )

targetField = 'POP_OTHER'
classes = 3
layer = QgsVectorLayer( 'C:/data/ne_10m_populated_places.shp', 'Equal Total Value', 'ogr')
if layer.isValid():
    applySymbologyEqualTotalValue(layer, classes, targetField)
    QgsMapLayerRegistry.instance().addMapLayers( [layer] ) 
Kelly Thomas
sumber
Saya ingin mengatakan beberapa hal. Pertama, jika Anda mencoba membuat kembali jawaban di atas dari @Kelly, pastikan untuk memilih file "unduh tempat yang dihuni" dari tautan Kelly. Jika Anda ingin melihat versi terbaru dari kode ini untuk PyQGIS 3 / QGIS 3.x, lihat utas ini: gis.stackexchange.com/questions/303990/… Saya menggunakan shapefile yang berbeda, perlu diingat. Tetapi kodenya sangat mirip dan Anda harus bisa mengikutinya. Beberapa metode dan hal telah berubah untuk QGIS 3.
Erich Purpur