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)
つづくかな?
さすがに限界なので、この辺で終了かな?
以上