2

I am using QGIS + pyQGIS + Python. Layer geometry is line. Each line has a magnitude and a direction (from 1st node to 2nd node).

What exactly I want to perform is "graduated width marker symbology overlaid on the graduated width line symbology"

Example:

line thickness 5mm. and 5mm. width marker symbol overlaid on it. ===(5mm)===

line thickness 3mm. and 3mm. width marker symbol overlaid on it. -----(3mm)-----

For the time being, I can perform the following; either "(i) lines with graduated thickness" or "(ii) single line symbology overlaid with single marker symbol (no graduated thickness)".

Can I perform it at the same time? Graduated width markers on graduated thickness lines.

Below code does all same appearing markers overlaid on all same appearing lines:

#Use the currently selected layer
layer = qgis.utils.iface.mapCanvas().currentLayer()
registry = QgsSymbolLayerV2Registry.instance()
lineMeta = registry.symbolLayerMetadata("SimpleLine")
markerMeta = registry.symbolLayerMetadata("MarkerLine")

symbol = QgsSymbolV2.defaultSymbol(layer.geometryType())

#Line layer
lineLayer = lineMeta.createSymbolLayer({'width': '0.26', 'color': '255,0,0', 'offset': '0', 'penstyle': 'solid', 'use_custom_dash': '0', 'joinstyle': 'bevel', 'capstyle': 'square'})

#Marker layer
markerLayer = markerMeta.createSymbolLayer({'width': '0.26', 'color': '255,0,0', 'rotate': '1', 'placement': 'centralpoint', 'offset': '0'})
subSymbol = markerLayer.subSymbol()

#Replace the default layer with our own SimpleMarker
subSymbol.deleteSymbolLayer(0)
triangle = registry.symbolLayerMetadata("SimpleMarker").createSymbolLayer({'name': 'filled_arrowhead', 'color': '255,0,0', 'color_border': '0,0,0', 'offset': '0,0', 'size': '3', 'angle': '0'})
subSymbol.appendSymbolLayer(triangle)

#Replace the default layer with our two custom layers
symbol.deleteSymbolLayer(0)
symbol.appendSymbolLayer(lineLayer)
symbol.appendSymbolLayer(markerLayer)

#Replace the renderer of the current layer
renderer = QgsSingleSymbolRendererV2(symbol)
layer.setRendererV2(renderer)    

QgsMapLayerRegistry.instance().addMapLayer( layer )

Below code performs only graduated width lines (equal interval) BUT NO MARKERS OVERLAID

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, label ,colour, alpha, width):
    symbol = validatedDefaultSymbol(layer.geometryType())
    symbol.setColor(colour)
    symbol.setAlpha(alpha)
    symbol.setWidth(width)
    range = QgsRendererRangeV2(min, max, symbol, label)
    return range                    

vlayer = QgsVectorLayer(str(SaveShpName), str(SaveShpName), 'ogr')
myTargetField = 'magnitude'

#For Equal Interval Classes
if dlg.ui.comboBoxSelectSymbology.currentText() == "Equal Interval":
    GradSymNoOfClasses = dlg.ui.spinBoxClasses.value() 
    GradSymInterval = round(((int(GradSymMax) - int(GradSymMin)) / float(GradSymNoOfClasses)),0)
    myRangeList = []
    for i in range(GradSymNoOfClasses):
        if i == 0:
            classlabel = str(GradSymMin)+" - "+str(int(GradSymMin)+GradSymInterval)
            myRangeList.append(makeSymbologyForRange( vlayer, int(GradSymMin), int(GradSymMin)+GradSymInterval, classlabel , QColor(0, 255-(255*i/GradSymNoOfClasses), 255*i/GradSymNoOfClasses), 1, 0.25 ))
        elif i == (GradSymNoOfClasses - 1):
            classlabel = str(int(GradSymMin)+(GradSymInterval*i)+0.001)+" - "+str(GradSymMax)
            myRangeList.append(makeSymbologyForRange( vlayer, (GradSymInterval*i)+0.001, int(GradSymMax), classlabel , QColor(0, 255-(255*i/GradSymNoOfClasses), 255*i/GradSymNoOfClasses), 1, i/1.25 ))
        else:
            classlabel = str(int(GradSymMin)+(GradSymInterval*i)+0.001)+" - "+str(int(GradSymMin)+GradSymInterval*(i+1))
            myRangeList.append(makeSymbologyForRange( vlayer, int(GradSymMin)+(GradSymInterval*i)+0.001, int(GradSymMin)+GradSymInterval*(i+1), classlabel , QColor(0, 255-(255*i/GradSymNoOfClasses), 255*i/GradSymNoOfClasses), 1, i/1.25 ))

    myRenderer = QgsGraduatedSymbolRendererV2( myTargetField, myRangeList )
    vlayer.setRendererV2( myRenderer )

    QgsMapLayerRegistry.instance().addMapLayer( vlayer ) 

1 Answer 1

3

After working one full day on both codes; at last I was able to modify the code to create graduated symbology overlayed with proportional direction arrows.

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, label ,colour, alpha, width):
    symbol = validatedDefaultSymbol(layer.geometryType())


    #Line layer
    lineLayer = lineMeta.createSymbolLayer({'width': '1', 'color': '255,0,0', 'offset': '0', 'penstyle': 'solid', 'use_custom_dash': '0', 'joinstyle': 'bevel', 'capstyle': 'square'})
    #Marker layer
    markerLayer = markerMeta.createSymbolLayer({'width': '0.26', 'color': '255,0,0', 'rotate': '1', 'placement': 'centralpoint', 'offset': '0'})
    subSymbol = markerLayer.subSymbol()
    #Replace the default layer with our own SimpleMarker
    subSymbol.deleteSymbolLayer(0)
    triangle = registry.symbolLayerMetadata("SimpleMarker").createSymbolLayer({'name': 'filled_arrowhead', 'color': '255,0,0', 'color_border': '255,255,255', 'offset': '0,0', 'size': '3', 'outline_width': '0.5', 'angle': '0'})
    subSymbol.appendSymbolLayer(triangle)
    #Replace the default layer with our two custom layers
    symbol.deleteSymbolLayer(0)
    symbol.appendSymbolLayer(lineLayer)
    symbol.appendSymbolLayer(markerLayer)


    symbol.setColor(colour)
    symbol.setAlpha(alpha)
    symbol.setWidth(width)
    range = QgsRendererRangeV2(min, max, symbol, label)
    return range                    

vlayer = QgsVectorLayer(str(SaveShpName), str(SaveShpName), 'ogr')
myTargetField = 'magnitude'
#Equal Interval
if dlg.ui.comboBoxSelectSymbology.currentText() == "Equal Interval":
    GradSymNoOfClasses = dlg.ui.spinBoxClasses.value() 
    GradSymInterval = round(((int(GradSymMax) - int(GradSymMin)) / float(GradSymNoOfClasses)),0)
    myRangeList = []
    for i in range(GradSymNoOfClasses):
        if i == 0:
            classlabel = str(GradSymMin)+" - "+str(int(GradSymMin)+GradSymInterval)
            myRangeList.append(makeSymbologyForRange( vlayer, int(GradSymMin), int(GradSymMin)+GradSymInterval, classlabel , QColor(0, 255-(255*i/GradSymNoOfClasses), 255*i/GradSymNoOfClasses), 1, 1 ))
        elif i == (GradSymNoOfClasses - 1):
            classlabel = str(int(GradSymMin)+(GradSymInterval*i)+0.001)+" - "+str(GradSymMax)
            myRangeList.append(makeSymbologyForRange( vlayer, (GradSymInterval*i)+0.001, int(GradSymMax), classlabel , QColor(0, 255-(255*i/GradSymNoOfClasses), 255*i/GradSymNoOfClasses), 1, i*3 ))
        else:
            classlabel = str(int(GradSymMin)+(GradSymInterval*i)+0.001)+" - "+str(int(GradSymMin)+GradSymInterval*(i+1))
            myRangeList.append(makeSymbologyForRange( vlayer, int(GradSymMin)+(GradSymInterval*i)+0.001, int(GradSymMin)+GradSymInterval*(i+1), classlabel , QColor(0, 255-(255*i/GradSymNoOfClasses), 255*i/GradSymNoOfClasses), 1, i*3 ))

    myRenderer = QgsGraduatedSymbolRendererV2( myTargetField, myRangeList )
    vlayer.setRendererV2( myRenderer )
    QgsMapLayerRegistry.instance().addMapLayer( vlayer )                     

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.