「森林計画図を地図ソフトで見たいけど、GISは難しそう…」
そんな声をよく聞きます。確かに、データの入手先を調べ、QGISの操作方法・設定を覚え、座標系や文字コードの問題を乗り越えるのは、初心者には高い壁です。
この記事では、AIアシスタントのClaudeCodeを使って必要なデータを入手する手順と、PyQGIS(QGISのPythonスクリプト機能)で地図をワンクリック自動セットアップする方法を紹介します。長野県・塩尻市を実例に、誰でも再現できるように丁寧に解説します。
完成する地図には以下のすべてが含まれます:
- 林班・小班・施業班の3階層(縮尺連動で自動切替)
- 樹種カラーレイヤー(森林簿CSV JOIN・スギ/ヒノキ/カラマツなど25樹種を色分け)
- 航空写真(高解像度オンライン・オフラインMBTilesの2種)
- 等高線(国土地理院5m DEMから自動生成・オフライン対応)
- CS立体図(地形の起伏を可視化・ローカル保存対応)
なぜ「自動化」が必要なのか
森林計画図のデータ(Shapefile形式)は、全国で公開されています。ただし実際に使うには、いくつかの作業が必要です。
- データのダウンロード先を探す
- QGISにレイヤーを追加し、表示順を整える
- 日本語が含まれるため文字コード(SHIFT-JIS)を適切に処理する
- 林班・小班・施業班ごとに色分けを設定する
- スケールに応じてラベルを切り替える
- 現地でも使えるようにオフライン対応の背景地図を準備する
- 航空写真から樹種・林層を確認できるようにする
これらを毎回手動でやると、慣れている人でも1〜2時間かかります。スクリプトで自動化すれば、次回からは実行するだけ。市町村が変わっても、数か所の設定を変えるだけで済みます。
STEP 1:g空間情報センターからデータを取得する
g空間情報センターとは
g空間情報センター(国土交通省) は、全国の地理情報(GISデータ)を無料で提供している政府公式サイトです。森林計画図のShapefileも、ここから都道府県・地域ごとにダウンロードできます。
ClaudeCodeを使った検索のコツ
データの探し方がわからないときは、Claudeに聞いてみましょう。たとえば次のように質問すると、必要な手順を整理してくれます。
「g空間情報センターで、長野県松本地域の森林計画図(Shapefile)をダウンロードする手順を教えてください」
Claudeはサイトの構造を理解しているため、
- サイトのどのカテゴリから探すか
- 検索キーワード(「森林計画図」「森林基本図」など)
- ダウンロード後のファイル構成
を一括で教えてくれます。自分でサイトを探し回る時間が大幅に短縮されます。

ダウンロードの手順(塩尻市の場合)
- g空間情報センターにアクセスし、「森林計画図」で検索
- 「長野県 松本地域森林計画区」のデータを選択
- 対象市町村のShapefileをダウンロード・解凍
- 以下のファイルが含まれていることを確認:
塩尻市_GIS/
├── SHICHOSON.shp # 市町村界
├── RINPAN_M.shp # 林班(大ゾーン)
├── SHOHAN_M.shp # 小班(中ゾーン)
└── SEGYOHAN_M.shp # 施業班(最詳細)
メモ: ファイル名や構成は地域・年度によって異なる場合があります。不明な点はClaudeに「このファイル構成で森林計画図を表示するにはどのレイヤーを使えばいいですか」と確認しながら進めると確実です。

STEP 2:QGISとPythonコンソールの準備
QGISをまだインストールしていない場合は、公式サイトから無料でダウンロードできます。
🔗 https://qgis.org/(QGIS 3.x 推奨)
インストール後、次の場所からPythonコンソールを開きます。
メニュー → プラグイン → Pythonコンソール
コンソール上部の「エディタを表示」ボタンを押すと、スクリプトを貼り付けられるエディタ画面が開きます。

STEP 3:PyQGISスクリプトの全体像
以下が、塩尻市の森林計画図を自動セットアップするスクリプトの主要部分です。
# =====================================================================
# 塩尻市 森林計画図 QGISプロジェクト自動セットアップスクリプト
# 使い方: QGISのScript Editorでこのファイルを開いて▶で実行
# =====================================================================
import os
from qgis.core import (
QgsProject, QgsVectorLayer, QgsRasterLayer,
QgsFillSymbol, QgsLineSymbol, QgsSingleSymbolRenderer,
QgsCategorizedSymbolRenderer, QgsRendererCategory,
QgsPalLayerSettings, QgsVectorLayerSimpleLabeling,
QgsTextFormat, QgsTextBufferSettings, QgsTextBackgroundSettings,
QgsField, QgsFeature,
)
from PyQt5.QtGui import QColor, QFont
from PyQt5.QtCore import QSizeF, QVariant
BASE = "/Users/yourname/Downloads/塩尻市_GIS" # ← ご自身のパスに変更
# QGIS バージョン互換シム
try:
from qgis.core import QgsUnitTypes
RENDER_POINTS = QgsUnitTypes.RenderPoints
except AttributeError:
from qgis.core import Qgis
RENDER_POINTS = Qgis.RenderUnit.Points
使い方はシンプルです:
BASE =にShapefileを置いたフォルダのパスを入力- QGISのScript Editorでファイルを開いて「▶ 実行」
初回実行時は DEM・航空写真・CS立体図・森林簿CSV を自動ダウンロードします(インターネット接続が必要)。2回目以降はローカルキャッシュを使うため、山中でもオフラインで使えます。
STEP 4:スクリプトのポイント解説
① 文字コードはCPGファイルにまかせる
森林計画図のShapefileにはSHIFT-JISを宣言する .cpg ファイルが付属しています。このファイルが揃っていれば、QGISは自動で文字コードを判別するため、|encoding=SHIFT_JIS の手動指定は不要です。むしろ指定することで逆に読み込み失敗するケースもあるため、このスクリプトでは省略しています。
付属ファイル(
.shp/.shx/.dbf/.prj/.cpg)が同じフォルダに揃っていることが前提です。
② 小班コードをひらがなに変換する
小班の区分コードは A, B, C…とアルファベットで格納されていますが、林業の現場では伝統的に「いろは順」が使われています。スクリプトはCASE WHEN式でQGIS側の変換を行います。
# 変換例: A→い, B→ろ, C→は ...
CASE WHEN "SHO"='A' THEN 'い' WHEN "SHO"='B' THEN 'ろ' ... ELSE "SHO" END
注意: QGISの式エンジンは
CASE "SHO" WHEN 'A' THEN ...のようなSQL短縮形には対応していません。必ずCASE WHEN "SHO"='A' THEN ...の形式で書く必要があります。
③ 縮尺に応じてレイヤーとラベルを自動切り替え
地図を広域で見ているときに細かい線やラベルが全部表示されると、地図が読めなくなります。このスクリプトでは、レイヤー全体の表示縮尺(線)とラベルだけの表示縮尺を別々に制御できるようにしています。
| 縮尺 | 表示されるもの |
|---|---|
| 1:100,000 以下 | 林班の線+番号(緑・太字18pt) |
| 1:50,000 以下 | +小班の線+ひらがな(青・白丸背景) |
| 1:10,000 以下 | +施業班の赤い細線+樹種カラー |
| 1:5,000 以下 | +施業番号ラベル(黒)+樹種名ラベル |
④ テキストバッファ(白い縁取り)で読みやすく
緑・青・黒と複数の色が重なる森林計画図では、ラベルが背景に溶け込みがちです。すべてのラベルに白い縁取り(テキストバッファ)を設定することで、どんな背景色の上でも文字が読みやすくなります。
buf = QgsTextBufferSettings()
buf.setEnabled(True)
buf.setSize(2.5) # 縁取りの太さ(ポイント)
buf.setColor(QColor("#ffffff"))
⑤ 小班ラベルに白丸背景
ひらがな1文字だけの小班ラベルは、林班番号や施業番号と重なると紛らわしくなります。楕円形の白背景を付けることで、どのラベルが小班のものかひと目でわかるようになります。
bg = QgsTextBackgroundSettings()
bg.setType(QgsTextBackgroundSettings.ShapeEllipse) # 楕円形
bg.setFillColor(QColor(255, 255, 255, 230)) # 白・半透明
bg.setStrokeColor(QColor("#003399")) # 青の枠線
⑥ 林班ラベルは太字・大きめで目立たせる
林班・小班・施業班の3レイヤーが重なるため、最上位区分である林班の番号が埋もれないよう、太字・18ptで表示します。小班(12pt)・施業班(10pt)と明確にサイズ差をつけることで、縮尺を変えても「今どのゾーンを見ているか」が直感的にわかります。
⑦ 背景レイヤーの構成
用途に応じて6種類の背景レイヤーをセットします。
| レイヤー | デフォルト | 用途 |
|---|---|---|
| 地理院タイル(淡色) | ON | オンライン時のベース地図 |
| CS立体図 XYZタイル | OFF | 山の起伏を立体的に確認 |
| CS立体図 ローカルTIFF | OFF | オフラインでCS立体図を表示 |
| 等高線(20m間隔) | ON | オフライン対応・山中でも地形が読める |
| 航空写真 高解像度(ort) | OFF | zoom 18・色調鮮明・林冠確認に最適 |
| 航空写真(オフラインMBTiles) | OFF | インターネット不要のキャッシュ |
CS立体図はデフォルトでは非表示になっており、レイヤーパネルのチェックボックスをONにするだけで即座に切り替えられます。山中などインターネットが使えない現場では、等高線と森林計画図の組み合わせで地形と区画を同時に確認できます。
等高線の生成について: 国土地理院の5mメッシュ標高タイル(dem5a)を自動ダウンロードしてGeoTIFFに合成し、GDALの等高線ツールで20m間隔の線を生成したあと
native:smoothgeometryでなめらかな曲線に整形します。初回実行時のみインターネット接続が必要で、生成後は塩尻市_等高線.gpkgとしてローカル保存されるためオフラインでも使えます。
⑧ レイヤーの重ね順
QGISはリスト上で下にあるレイヤーが地図上では下に描画されます。スクリプトでは「市町村界 → 林班 → 小班 → 施業班」の順に addMapLayer を呼ぶことで、詳細なレイヤーが上に重なる構成を自動的に作ります。
【上】施業班(赤枠・透明塗り)
小班(青枠・透明塗り)
林班(緑枠・透明塗り)
市町村界
─────────────────────── ← 塗りがここから始まる
樹種カラー(60%透過)← 森林簿JOINの色分け
等高線 / CS立体図 / 航空写真
【下】地理院タイル淡色
森林ポリゴンは透明塗りなので、下の樹種カラーが透けて見え、さらに背景の地形も見通せます。
⑨ 樹種カラーレイヤー(森林簿 CSV JOIN)

スクリプトはg空間情報センターの長野県 森林簿データも自動取得して、施業班ポリゴンを樹種別に色分けします。
- スギ(深緑)・ヒノキ(緑)・カラマツ(薄黄緑)・ブナ(淡緑)など25樹種に対応
- 60%透過表示で背景(地理院タイル・CS立体図・航空写真)が透けて見える
- 識別ツールでポリゴンをクリックすると樹種・林齢・林種をポップアップ表示
- 1:5,000以下に拡大すると樹種名ラベルも自動表示
# 森林簿 CSV + JOIN のコア処理(抜粋)
species_map = {}
for row in csv.DictReader(open(CSV_CACHE, encoding="utf-8")):
key = (row.get("施業キー") or "").strip()
if not key.startswith("2151"): # 塩尻市の施業キー前置詞
continue
rate = float(row.get("混交率") or 0)
if key not in species_map or rate > species_map[key]["混交率"]:
species_map[key] = {
"樹種": row["樹種"], "林齢": row["林齢"], "混交率": rate
}
# 施業班ジオメトリと JOIN して GeoPackage に永続保存
for feat in segyohan_layer.getFeatures():
info = species_map.get(feat["KEY_02"].strip())
new_feat.setAttributes([key, info["樹種"], info["林齢"]] if info else [key, "", ""])
ポイント: 1施業班に複数の樹種が記録されている場合は「混交率」最大(主要樹種)を自動選択します。結果は 塩尻市_樹種.gpkg に永続保存されるため、2回目以降はオフラインで即時読み込みできます。
⑩ 航空写真レイヤー(林冠観察用)
![航空写真2種を自動追加|seamlessphoto(暗い)からort(高解像度・色調鮮明)への改善比較]()
山の調査では林層(樹高・樹冠・疎密度)の目視確認が欠かせません。スクリプトは2種類の航空写真レイヤーを自動追加します。
| レイヤー | 解像度 | インターネット | 特徴 |
|---|---|---|---|
| 航空写真 高解像度(ort) | zoom 18 ≒ 0.6m/px | 必要 | 色調が正確・最新写真・鮮明 |
| 航空写真(オフラインMBTiles) | zoom 15 ≒ 5m/px | 不要 | 初回DL後は山中でも使用可 |
国土地理院の seamlessphoto は複数時期の写真を合成しているため色調が暗くなる場合があります。ort(オルソ空中写真)タイルは元画像の色調に近く、葉の色・樹冠の形がより鮮明に確認できます。
MBTilesはSQLite形式のオフラインタイルキャッシュです。初回実行時に自動ダウンロードされ、塩尻市_航空写真.mbtiles(約50〜100MB)として保存されます。
STEP 5:他の地域・市町村でそのまま使う

スクリプトのベースは塩尻市になっていますが、変更が必要な箇所は5か所だけです。
変更マップ
| # | 変更箇所 | 塩尻市の設定 | 変更の考え方 |
|---|---|---|---|
| 1 | SHPフォルダパス | "/.../塩尻市_GIS" | 対象市町村のSHPフォルダに変更 |
| 2 | DEM・航空写真の緯度経度範囲 | LAT_MIN=35.95 など | 対象市町村を囲む4辺に変更 |
| 3 | 森林簿ZIPのURL | 07matumoto.zip | 対象地域のZIPに変更 |
| 4 | 森林簿の施業キー前置詞 | "2151" | 対象市町村コードに変更 |
| 5 | プロジェクトタイトル | "塩尻市 森林計画図" | 対象市町村名に変更 |
変更①:SHPフォルダを指定する
BASE = "/Users/yourname/Downloads/松本市_GIS" # ← 変更
変更②:バウンディングボックスを調べる
Googleマップで対象市町村を表示し、四隅の緯度経度を読み取ります。右クリック「この場所について」で座標が確認できます。
# _generate_contours() と _download_aerial_mbtiles() 両関数内で変更
LAT_MIN, LAT_MAX = 36.10, 36.40 # 市町村の南端・北端(0.05度の余裕を推奨)
LON_MIN, LON_MAX = 137.80, 138.10 # 市町村の西端・東端
変更③:長野県 森林簿の地域ZIPを選ぶ
長野県の森林簿データは10地域に分かれています。対象市町村の地域ZIPを選んでURLを差し替えます。
| ZIP | 主な対象市町村 |
|---|---|
| 01佐久 | 佐久市など |
| 02上田 | 上田市など |
| 03諏訪 | 茅野市など |
| 04上伊那 | 伊那市など |
| 05南信州 | 飯田市など |
| 06木曽 | 木曽町など |
| 07松本 | 塩尻市・松本市・安曇野市・山形村・朝日村・生坂村・筑北村・麻績村 |
| 08北アルプス | 大町市など |
| 09長野 | 長野市など |
| 10北信 | 飯山市など |
各ZIPには複数市町村の個別CSVが入っています。スクリプトは全CSVを走査して施業キーの前置詞で自動的に対象市町村の行だけ抽出するため、ZIP内に他市町村のデータが混在していても問題ありません。
# _build_tree_species_layer() 内の ZIP_URL を変更
ZIP_URL = (
"https://www.geospatial.jp/ckan/dataset/"
"e58d5fb7-490a-4fec-999a-d6ae174b6e9e/resource/"
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/download/03suwa.zip"
)
変更④:施業キーの前置詞を調べる
QGISで SEGYOHAN_M.shp を開き、属性テーブルの KEY_02 列を確認します。
21510027B007- → 先頭4文字「2151」が塩尻市のコード
20290001A001- → 先頭4文字「2029」が松本市のコード
この先頭4文字を _build_tree_species_layer() 内のフィルターに設定します。
# 松本市の場合
if not key.startswith("2029"):
continue
変更⑤:プロジェクトタイトルを変える
project.setTitle("松本市 森林計画図(2025年度)")
完全チェックリスト
新しい市町村でセットアップする前に確認してください。
-
BASE =のパスを変更した -
_generate_contours()内のLAT_MIN/MAXLON_MIN/MAXを変更した -
_download_aerial_mbtiles()内のLAT_MIN/MAXLON_MIN/MAXを変更した -
_build_tree_species_layer()のZIP_URLを変更した -
_build_tree_species_layer()のstartswith("XXXX")を変更した -
project.setTitle()を変更した - 古いキャッシュ(
.gpkg/.mbtiles/.csv)が混在していないか確認した
キャッシュに注意: 別の市町村で試す際は、前の市町村のキャッシュが残っていないか確認してください。同じフォルダで実行すると上書きされ、別フォルダで実行すると別々に保存されます。
完成した地図の活用例

塩尻市のデータを実際に動かすと、次のような情報が地図上で確認できます。
- 塩尻市全域で259林班、1,089小班、27,387施業班が登録されている
- 地図を広域で見ると林班の番号だけが大きく表示され、ズームインするにつれて小班・施業班の詳細が現れる
- 1:10,000以下に拡大すると樹種カラーが出現 — スギ林(深緑)・カラマツ林(薄黄緑)・広葉樹(黄系)が塗り分けられる
- 航空写真をONにして樹種カラーと重ねると、色分けと実際の林冠を対比できる
- 識別ツールでクリックすると施業番号・樹種・林齢を即座に確認できる
これらはすべて紙の計画図ではできない、GISならではの操作です。
プラスα:QGISで林業業務をもっと効率化するアイデア
1. 施業班ごとの面積集計を瞬時に
「この林班のなかで、スギ・ヒノキの人工林はどのくらいあるか」といった集計が、QGISのフィールド計算機やGeoprocessingツールで数クリックで行えます。Excelへのエクスポートも簡単で、補助金申請書類の下地にも使えます。
2. CS立体図・等高線との重ね合わせ
このスクリプトで追加されるCS立体図は、地形の起伏を色と陰影で視覚化した地図です。急斜面・尾根・谷が一目でわかるため、作業道の計画や施業優先度の検討に役立ちます。インターネットが使えない山中でも、ローカル保存したTIFFや自動生成した等高線で対応できます。
3. 航空写真と樹種カラーで林相を把握
スクリプトが自動生成する樹種カラーレイヤーはあくまで計画上の樹種です。航空写真を重ねて実際の林冠と比較することで、計画と現況のズレを視覚的に確認できます。変更が必要な施業班を素早く特定する用途に使えます。
4. 作業道・路網の入力と管理
既存のルートを地図上でトレースして、作業道や路網のレイヤーを作成・保存できます。GPS端末で取得した実測データを取り込んで、計画上の路網と比較することも可能です。
5. 現地調査のデジタル化(QField連携)
スマートフォン用アプリ「QField」を使えば、QGISで作った地図をスマホに転送し、現地で直接入力・マーキングできます。紙の野帳の代わりに、施業班ごとの調査結果をその場で記録して、帰社後にQGISへ取り込む、という運用が実現します。樹種カラーが入った地図を持参すれば、現地での区画確認もよりスムーズになります。
6. 複数市町村を一括セットアップする
STEP 5 の変更箇所を関数化しておくと、複数市町村を一気に処理できます。

def setup_city(city_name, base_dir, lat_min, lat_max, lon_min, lon_max,
zip_url, key_prefix):
"""市町村ごとにパラメータを切り替えてプロジェクトを生成する"""
global BASE, LAT_MIN, LAT_MAX, LON_MIN, LON_MAX
BASE = base_dir
LAT_MIN, LAT_MAX = lat_min, lat_max
LON_MIN, LON_MAX = lon_min, lon_max
# 以降はメイン処理と同じ(load_layer, set_symbol ... project.write())
# 使用例
CITIES = [
{"name": "塩尻市", "base": "/.../塩尻市_GIS", "bbox": (35.95,36.25,137.75,138.05),
"zip": "...07matumoto.zip", "prefix": "2151"},
{"name": "松本市", "base": "/.../松本市_GIS", "bbox": (36.10,36.45,137.75,138.05),
"zip": "...07matumoto.zip", "prefix": "2029"},
]
for c in CITIES:
setup_city(c["name"], c["base"], *c["bbox"], c["zip"], c["prefix"])
print(f"✅ {c['name']} 完了")
まとめ
| 作業 | 手動の場合 | 自動化後 |
|---|---|---|
| データ探し(SHP・森林簿CSV) | 30分〜1時間 | Claudeに聞いて5分 |
| QGIS設定(レイヤー・色・ラベル) | 30〜60分 | スクリプト実行で1〜2分 |
| 樹種カラー作成(CSVからJOIN) | 数時間(手動は困難) | 自動ダウンロード・JOIN・保存 |
| 航空写真のオフライン化 | 困難(専用ツールが必要) | MBTilesとして自動生成 |
| 別市町村への展開 | また一から | 5か所の設定変更のみ |
最初のスクリプト作成に少し時間がかかりますが、一度作ってしまえば何度でも再利用できる資産になります。複数市町村を担当している方や、毎年データが更新される環境では特に効果が大きいはずです。
Claudeでデータの場所を調べ、PyQGISで地図を組み立てる—この組み合わせは、林業GISの入り口としておすすめです。ぜひ試してみてください。
参考リンク
– g空間情報センター — 国土交通省公式GISデータポータル(森林計画図・森林簿・CS立体図)
– QGIS公式サイト — 無料のオープンソースGIS
– QField — スマホ用フィールドGISアプリ
– 国土地理院 地理院タイル一覧 — 淡色・航空写真・標高タイル
– 国土地理院 標高タイル仕様 — DEMタイル(dem5a・dem)の仕様


コメント