QGISでTypographicMap
続きです
これで本当に最後の予定です。
せっかく2回やったのでまとめを行います。
QGISのSVG塗りつぶしパターンを属性から作ってみる
QGISのSVGマーカーを属性から作ってラインに置く
使用するデータ
基盤地図情報ダウンロードサービスから縮尺レベル2500の行政区画・軌道の中心線・道路縁を使用しました。
付属のツールでshapefileへの変換を行い、カラム名称を日本語からアルファベットに変換はしています。
行政区画についてはnameカラムに行政名が入るように、軌道の中心線・道路縁についてはsortカラムに種別が入るようにしています。
結果
スケールでフィルタしているので、ひいているときは行政区画だけ表示。
拡大していくと道路も表示。完全にラインに沿っての表示は出来ていない。ライン上にマーカーを置いているので、はみ出している文字が出てきます。改善したいですが、この方法だと無理ですね。
五稜郭。
書いたソース
QGIS2.0の、pythonコンソールから実行します。"エディタの表示"をしておいて、ソースを貼り付けて実行しています。
前提条件として、埋め込んでしまって、
- ラインは"sort"カラム、ポリゴンは"name"カラムの属性を描画
としています。
処理としては、
- レイヤーを順次アクセス
- ベクトルレイヤのうち、ラインとポリゴンのみが対象
- 属性値のリストを作っておく
- 属性値毎のSVGファイルを作成(temporaryファイルですが消さず)
- 図形種別にあわせたシンボル作成、色はランダム、ポリゴン塗りつぶしについては角度もランダム
- "ルールに基づいた"スタイルにフィルターと合わせてラインシンボルをセット
- 全ての属性値に対するルールの設定が終わったら、スタイルをrendererに入れてlayerに設定
- 再描画
といった流れです。
あいかわらず変なやり方なので、スタイルの設定の参考程度に。
# -*- coding: utf-8 -*- from PyQt4 import QtGui, QtCore import tempfile import random #描画サイズ lineSymbolSize = 3 polySymbolSize = 4 def makePolySymbol(attr, svg, size): #空のシンボルを作成 symbol = QgsFillSymbolV2() symbol.deleteSymbolLayer(0) #属性を入れたSVGを指定して、SVG塗りつぶしを作成 fillLayer = QgsSVGFillSymbolLayer(svg.name, len(attr)*size) subSymbol = fillLayer.subSymbol() subSymbol.deleteSymbolLayer(0) #シンボルに塗りつぶしを追加 symbol.appendSymbolLayer(fillLayer) #適当に回転させる symbol.setAngle(random.randint(0,90)) return symbol def makeLineSymbol(attr, svg, size): #SVG読み込み markerSymbolLayer = QgsSvgMarkerSymbolLayerV2 (svg.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) return symbol #レイヤーを順次アクセス layers = iface.legendInterface().layers() for layer in layers: if layer.type() != layer.VectorLayer: continue if layer.geometryType() != QGis.Line and layer.geometryType() != QGis.Polygon: continue #描画する属性フィールド key = "sort" if layer.geometryType() == QGis.Line else "name" #空の"ルールに基づいた"スタイル作成 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ファイルを作成 svgPattern = """<?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">""" svgPattern += '<svg width="%dpx" height="1px" ' % len(attr) svgPattern += 'xmlns="http://www.w3.org/2000/svg" version="1.1">' svgPattern += '<rect x="0" y="0" width="%d" height="1" fill="#FFFFFF" />' % len(attr) svgPattern += '<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)) svgPattern += '%s' % attr.encode('utf-8') svgPattern += '</text>' svgPattern += '</svg>' tempSvg = tempfile.NamedTemporaryFile(mode="w+t", delete=False) tempSvg.write(svgPattern) tempSvg.close() symbol = makeLineSymbol(attr, tempSvg, lineSymbolSize) if layer.geometryType() == QGis.Line else makePolySymbol(attr, tempSvg, polySymbolSize) #指定の属性カラムによるフィルタを設定して、ルールを作成、追加 #ラインとポリゴンで表示スケール変更 scaleMax = 2500 if layer.geometryType() == QGis.Line else 200000 ruleAdd = QgsRuleBasedRendererV2.Rule(symbol, label=attr, filterExp="\"%s\" = '%s'" % (key, attr), description=attr, scaleMaxDenom=scaleMax) rule.appendChild(ruleAdd) renderer = QgsRuleBasedRendererV2(rule) layer.setRendererV2(renderer) iface.mapCanvas().refresh() iface.legendInterface().refreshLayerSymbology(layer)