QGISのSVGマーカーを属性から作ってラインに置く
FOSS4G Advent Calendar 2013
2011、2012に続いて、今年もFOSS4G Advent Calendar行います。ご参加お待ちしております。
FOSS4G Advent Calendar 2013
つづきです
QGISのSVG塗りつぶしパターンを属性から作ってみるの続きです。
そもそもそんなやり方するな、というものなのでスタイルの設定の参考程度に。
前回はポリゴンをSVGパターンで塗りつぶしたので、今回はラインにSVGマーカーを設定してラインを属性文字で描画します。文字を線に沿わせるというより、ライン上に一定間隔のポイントを配置して、SVGマーカーを置いていくことになります。
QGISの画面で言うと、"レイヤプロパティ"を表示して"スタイル"を選択"マーカーライン"を"SVGマーカー"に設定します。
使用するデータ
基盤地図情報ダウンロードサービスから縮尺レベル2500の道路縁を使用しました。
付属のツールでshapefileへの変換を行い、カラム名称を日本語からアルファベットに変換はしています。
結果
ラインの属性に入っている種別からSVGファイルを作成して、スタイルに指定しています。
スケールの設定が良くない…
拡大すると。文字が線に沿うわけではないので、当然厳しいですね。
ラインとSVGマーカーが置かれているポイントも一緒に表示するとこんな感じ。
書いたソース
QGIS2.0の、pythonコンソールから実行します。"エディタの表示"をしておいて、ソースを貼り付けて実行しています。
前提条件として、埋め込んでしまって、
- "sort"カラムの値を描画することにしています。
- レイヤーは選択済み
としています。
処理としては、
- 属性値のリストを作っておく
- 属性値毎のSVGファイルを作成(temporaryファイルですが消さず)
- マーカーラインを作成しておいて、SVGシンボルを入れる
- ラインシンボルを作成しておいて、マーカーラインを入れる
- "ルールに基づいた"スタイルにフィルターと合わせてラインシンボルをセット
- 全ての属性値に対するルールの設定が終わったら、スタイルをrendererに入れてlayerに設定
- 再描画
といった流れです。
# -*- coding: utf-8 -*- from PyQt4 import QtGui, QtCore import tempfile import random #レイヤーが選択されていることが前提 layer = iface.activeLayer() #描画する属性フィールド key = "sort" #描画サイズ size = 3 #空の"ルールに基づいた"スタイル作成 rule = QgsRuleBasedRendererV2.Rule(None) #指定の属性フィールドの値リストを作成 attrList = [] features = layer.getFeatures() for feature in features: if feature[key] not in attrList: attrList.append(feature[key]) for attr in attrList: #指定の属性を入れたSVGファイルを作成 fillPattern = """<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">""" fillPattern += '<svg width="%dpx" height="1px" ' % len(attr) fillPattern += 'xmlns="http://www.w3.org/2000/svg" version="1.1">' fillPattern += '<text x="0" y="1" font-family="MS-Mincho" font-size="1" fill="rgb(%i,%i,%i)" >' % (random.randint(0,255), random.randint(0,255), random.randint(0,255)) fillPattern += '%s' % attr.encode('utf-8') fillPattern += '</text></svg>' tempSvg = tempfile.NamedTemporaryFile(mode="w+t", delete=False) tempSvg.write(fillPattern) tempSvg.close() #SVG読み込み markerSymbolLayer = QgsSvgMarkerSymbolLayerV2 (tempSvg.name, len(attr)*size) #マーカーライン作成、SVGシンボルセット markerLine = QgsMarkerLineSymbolLayerV2() svgSymbol = markerLine.subSymbol() svgSymbol.deleteSymbolLayer(0) svgSymbol.appendSymbolLayer(markerSymbolLayer) markerLine.setInterval(len(attr)*size) symbol = QgsLineSymbolV2() symbol.deleteSymbolLayer(0) symbol.appendSymbolLayer(markerLine) #指定の属性カラムによるフィルタを設定して、ルールを作成、追加 ruleAdd = QgsRuleBasedRendererV2.Rule(symbol, label=attr, filterExp="\"%s\" = '%s'" % (key, attr), description=attr) rule.appendChild(ruleAdd) renderer = QgsRuleBasedRendererV2(rule) layer.setRendererV2(renderer) iface.mapCanvas().refresh() iface.legendInterface().refreshLayerSymbology(layer)
つづくかな?
さすがに限界なので、この辺で終了かな?
以上