【QGIS】国土地理院ベクターのズーム制限解除 & 巨大点群からの傾斜区分図自動作成(岐阜県バージョン)
【QGIS】国土地理院ベクターのズーム制限解除 & 巨大点群からの傾斜区分図自動作成(岐阜県バージョン)
1. 国土地理院ベクタータイルの「拡大すると消える」問題を解決する
QGISで「国土地理院ベクター(最適化ベクトルタイル)」を表示した際、標準スタイルではズームレベル16.1以上に拡大すると建物や道路が消えてしまう仕様になっています。これでは詳細な図面作成ができません。
ベクタタイルレイヤはプロパティから一括でズームレベルを変更できませんが、Pythonコンソールを使えば一瞬で全項目の制限を解除できます。
【解決手順】
レイヤパネルで「国土地理院ベクター」レイヤを選択。
メニューの
[プラグイン]>[Pythonコンソール]を開く。下部の入力欄に以下の1行を貼り付けてEnter。
Python
layer = iface.activeLayer(); styles = layer.renderer().styles(); [s.setMaxZoomLevel(22) for s in styles]; layer.renderer().setStyles(styles); layer.triggerRepaint()
これでレベル22まで拡大しても地物が表示され続けます。
2. 巨大点群から傾斜区分図を一括作成する(岐阜県仕様)
数千万点のデータから傾斜区分図を作る際、QGISのGUI操作ではフリーズのリスクが高まります。ここでは、用途に応じて使い分けられる「超高速版」と「高精度フルバージョン」の2つのスクリプトを紹介します。
傾斜区分の定義(5段階)
値 1:0° - 2°(緑色)
値 2:2° - 15°(黄緑色)
値 3:15° - 30°(薄い黄色)
値 4:30° - 45°(山吹色)
値 5:45° - 90°(オレンジ色)
A. 【超高速版】とりあえず全体を素早く確認したい時
1000万点超えのデータでも数分で完了します。微地形は多少簡略化されますが、スピード重視の現場確認に最適です。
Python
import os
import numpy as np
import tkinter as tk
from tkinter import filedialog
try:
from osgeo import gdal, ogr, osr
except ImportError:
print("エラー: GDALライブラリが見つかりません。OSGeo4W Shellから実行してください。")
import sys
sys.exit()
def process_fast_slope():
root = tk.Tk()
root.withdraw()
root.attributes('-topmost', True)
input_path = filedialog.askopenfilename(title="処理するファイルを選択", filetypes=[("GeoPackage/Shapefile", "*.gpkg;*.shp")])
if not input_path: return
base_dir = os.path.dirname(input_path)
base_name = os.path.splitext(os.path.basename(input_path))[0]
output_name = base_name.replace("_clipped", "")
dem_tif = os.path.join(base_dir, f"{output_name}_dem.tif")
slope_tif = os.path.join(base_dir, f"{output_name}_slope.tif")
reclass_tif = os.path.join(base_dir, f"{output_name}_reclass.tif")
z_field = "Z"
res = 1.0
ds = ogr.Open(input_path)
layer = ds.GetLayer()
x_min, x_max, y_min, y_max = layer.GetExtent()
srs = layer.GetSpatialRef()
srs_wkt = srs.ExportToWkt() if srs else 'EPSG:6675'
print(f"超高速処理開始: {os.path.basename(input_path)}")
# 1. ラスタライズ
gdal.Rasterize(dem_tif, input_path, options=gdal.RasterizeOptions(
format='GTiff', outputBounds=[x_min, y_min, x_max, y_max],
xRes=res, yRes=res, attribute=z_field, noData=-9999, outputType=gdal.GDT_Float32, outputSRS=srs_wkt))
# 2. 隙間補間
ds_dem = gdal.Open(dem_tif, gdal.GA_Update)
gdal.FillNodata(targetBand=ds_dem.GetRasterBand(1), maskBand=None, maxSearchDist=20, smoothingIterations=0)
ds_dem = None
# 3. 傾斜計算
gdal.DEMProcessing(slope_tif, dem_tif, 'slope', options=gdal.DEMProcessingOptions(format='GTiff', computeEdges=True, slopeFormat='degree'))
# 4. 再分類
ds_slope = gdal.Open(slope_tif)
band = ds_slope.GetRasterBand(1)
arr = band.ReadAsArray()
nodata = band.GetNoDataValue()
reclass = np.full(arr.shape, -9999, dtype=np.int16)
v = (arr != nodata)
reclass[v & (arr >= 0) & (arr <= 2)] = 1
reclass[v & (arr > 2) & (arr <= 15)] = 2
reclass[v & (arr > 15) & (arr <= 30)] = 3
reclass[v & (arr > 30) & (arr <= 45)] = 4
reclass[v & (arr > 45)] = 5
driver = gdal.GetDriverByName('GTiff')
ds_out = driver.Create(reclass_tif, ds_slope.RasterXSize, ds_slope.RasterYSize, 1, gdal.GDT_Int16)
ds_out.SetGeoTransform(ds_slope.GetGeoTransform())
ds_out.SetProjection(ds_slope.GetProjection())
ds_out.GetRasterBand(1).WriteArray(reclass)
ds_out.GetRasterBand(1).SetNoDataValue(-9999)
ds_out = ds_slope = None
print(f"✅ 完了: {reclass_tif}")
if __name__ == "__main__":
process_fast_slope()
input("Enterキーを押して終了...")
B. 【高精度フルバージョン】公式図面・報告書作成用
全ての点を精密に結ぶ「線形補間」を行います。1000万点超えでは10時間以上かかる場合がありますが、微地形まで忠実に再現します。退勤前の実行を推奨します。
Python
import os
import numpy as np
import tkinter as tk
from tkinter import filedialog
try:
from osgeo import gdal, ogr, osr
except ImportError:
print("エラー: GDALライブラリが見つかりません。")
import sys
sys.exit()
def process_full_slope():
root = tk.Tk()
root.withdraw()
root.attributes('-topmost', True)
input_path = filedialog.askopenfilename(title="処理するファイルを選択", filetypes=[("GeoPackage/Shapefile", "*.gpkg;*.shp")])
if not input_path: return
base_dir = os.path.dirname(input_path)
base_name = os.path.splitext(os.path.basename(input_path))[0]
output_name = base_name.replace("_clipped", "")
dem_tif = os.path.join(base_dir, f"{output_name}_dem.tif")
slope_tif = os.path.join(base_dir, f"{output_name}_slope.tif")
reclass_tif = os.path.join(base_dir, f"{output_name}_reclass.tif")
z_field = "Z"
res = 1.0
ds = ogr.Open(input_path)
layer = ds.GetLayer()
x_min, x_max, y_min, y_max = layer.GetExtent()
width = int((x_max - x_min) / res)
height = int((y_max - y_min) / res)
srs = layer.GetSpatialRef()
srs_wkt = srs.ExportToWkt() if srs else 'EPSG:6675'
print(f"高精度版処理開始: {os.path.basename(input_path)}")
# 1. 線形補間(Grid)
gdal.Grid(dem_tif, input_path, options=gdal.GridOptions(
format='GTiff', outputBounds=[x_min, y_min, x_max, y_max],
width=width, height=height, algorithm='linear', zfield=z_field, outputSRS=srs_wkt))
# 2. 傾斜計算
gdal.DEMProcessing(slope_tif, dem_tif, 'slope', options=gdal.DEMProcessingOptions(format='GTiff', computeEdges=True, slopeFormat='degree'))
# 3. 再分類
ds_slope = gdal.Open(slope_tif)
band = ds_slope.GetRasterBand(1)
arr = band.ReadAsArray()
nodata = band.GetNoDataValue()
reclass = np.full(arr.shape, -9999, dtype=np.int16)
v = (arr != nodata)
reclass[v & (arr >= 0) & (arr <= 2)] = 1
reclass[v & (arr > 2) & (arr <= 15)] = 2
reclass[v & (arr > 15) & (arr <= 30)] = 3
reclass[v & (arr > 30) & (arr <= 45)] = 4
reclass[v & (arr > 45)] = 5
driver = gdal.GetDriverByName('GTiff')
ds_out = driver.Create(reclass_tif, ds_slope.RasterXSize, ds_slope.RasterYSize, 1, gdal.GDT_Int16)
ds_out.SetGeoTransform(ds_slope.GetGeoTransform())
ds_out.SetProjection(ds_slope.GetProjection())
ds_out.GetRasterBand(1).WriteArray(reclass)
ds_out.GetRasterBand(1).SetNoDataValue(-9999)
ds_out = ds_slope = None
print(f"✅ 完了: {reclass_tif}")
if __name__ == "__main__":
process_full_slope()
input("Enterキーを押して終了...")
おわりに
作成された _reclass.tif をQGISに読み込み、「単バンド疑似カラー」「正確」モードで5色を割り当てれば完成です。
建物の色を砂防基盤図に合わせる。
返信削除QColor(170, 5, 134)
from qgis.PyQt.QtGui import QColor
from qgis.core import Qgis
layer = iface.activeLayer()
styles = layer.renderer().styles()
pink = QColor(170, 5, 134)
for s in styles:
# ここを layerName() に修正しました
if s.layerName() == 'building':
sym = s.symbol()
# 線(LineString)の場合は線の色を変更
if sym.type() == Qgis.SymbolType.Line:
sym.setColor(pink)
# 面(Polygon)の場合は外枠(Stroke)の色を変更
elif sym.type() == Qgis.SymbolType.Fill:
sym.symbolLayer(0).setStrokeColor(pink)
layer.renderer().setStyles(styles)
layer.triggerRepaint()
ズームレベルを破壊(拡大すると、非表示になる)
返信削除layer = iface.activeLayer(); styles = layer.renderer().styles(); [s.setMaxZoomLevel(22) for s in styles]; layer.renderer().setStyles(styles); layer.triggerRepaint()