QGISのSVG塗りつぶしパターンを属性から作ってみる
FOSS4G 2013 Tokyoお疲れ様でした
10/31-11/2行われていたFOSS4G 2013 Tokyoに参加していました。運営のみなさま疲れさまでした。引き続き11/6-7のFOSS4G 2013 Osaka頑張ってください。Ust中継見てようと思います。
今回参加しての収穫の1つが、下記の本を紹介してもらったことでした。

- 作者: Sandra Rendgen,Paolo Ciuccarelli,Richard Saul Wurman,Simon Rogers,Julius Wiedemann
- 出版社/メーカー: Taschen America Llc
- 発売日: 2012/05/27
- メディア: ハードカバー
- クリック: 2回
- この商品を含むブログ (1件) を見る
面を属性で埋める
"Information Graphics"の中で紹介されていた、文字列で作った地図が気になっています。例えば行政区域のポリゴンがあったとしてその名称で、"あさひかわあさひかわあさひかわ"のようなパターンで埋めます。うまく伝えられなくてごめんなさい。
QGISで旨いこと出来ないかなと思い、少しだけやってみました。
制約が多いので、あくまで実験的のものです。他にいい方法あるよという方、ご指摘お待ちしております。
使用するデータ
natural earthのデータを使用します。
1:50m Cultural Vectorsの"Admin 0 – Countries"になります。

結果
先に結果。ポリゴンの属性に入っている国名からSVGファイルを作成して、スタイルに指定しています。本当はもう少し1文字ずつサイズとか変えながらやれると格好いいと思うのですが、そこまでやれないので単純なパターンで。当然"Information Graphics"で紹介されている地図はもっともっと格好いいです。


書いたソース
QGIS2.0の、pythonコンソールから実行します。"エディタの表示"をしておいて、ソースを貼り付けて実行しています。
前提条件として、
- "sovereignt"カラムの値を描画することにしています。他のカラムの場合utf8以外のコードが入っているとエラーが出たため、そうしています。
- レイヤーは選択済み
としています。
処理としては、
- 属性値のリストを作っておく
- 属性値毎のSVGファイルを作成(temporaryファイルですが消さず)
- symbolにSVG塗りつぶしを入れる
- "ルールに基づいた"スタイルにフィルターと合わせてsymbolをセット
- 全ての属性値に対するルールの設定が終わったら、スタイルをrendererに入れてlayerに設定
- 再描画
といった流れです。
# -*- coding: utf-8 -*-
from PyQt4 import QtGui, QtCore
import tempfile
#レイヤーが選択されていることが前提
layer = iface.activeLayer()
#描画する属性フィールド
key = "sovereignt"
#空の"ルールに基づいた"スタイル作成
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="%.1fpx" height="1px" ' % (len(attr)*0.5)
fillPattern += 'xmlns="http://www.w3.org/2000/svg" version="1.1">'
fillPattern += '<text x="0" y="1" font-family="serif" font-size="1" fill="blue" >'
fillPattern += '%s' % attr
fillPattern += '</text></svg>'
tempSvg = tempfile.NamedTemporaryFile(mode="w+t", delete=False)
tempSvg.write(fillPattern)
tempSvg.close()
#空のシンボルを作成
symbol = QgsSymbolV2.defaultSymbol(QGis.Polygon)
symbol.deleteSymbolLayer(0)
#属性を入れたSVGを指定して、SVG塗りつぶしを作成
fillLayer = QgsSVGFillSymbolLayer(tempSvg.name, len(attr)*2)
#シンボルに塗りつぶしを追加
symbol.appendSymbolLayer(fillLayer)
#指定の属性カラムによるフィルタを設定して、ルールを作成、追加
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)