マインクラフトで再現する中世城郭#3

(2)XMLデータを配列化し5mメッシュを1mメッシュに補間

ダウンロードした標高データはXMLデータのため、XMLパーサーを使い配列化します。具体的には以下のPythonプログラムを使用します(ここを参照しました)。プログラムと同じディレクトリーに(1)でダウンロードしたZIPファイルを展開しておきます。展開すると以下のように「FG-GML-XXXX-XX-DEM5A」ディレクトリーが作成されます。

<ディレクトリ状態>

d--------- 1 root root 4096 Feb 10 2023 FG-GML-5339-31-DEM5A
-rwxr-xr-x 1 root root 795 Feb 10 2023 npy5x5.py
-rwxr-xr-x 1 root root 3214 Feb 10 2023 xml2npy.py

<プログラムの内容>

実行プログラム(Python)は以下の通りです。

xml2npy.py

# coding: utf-8

import xml.etree.ElementTree as ET
import numpy as np
import sys
import os

GEO_DIR = "FG-GML-{0:04d}-{1:02d}-DEM5A"
GEO_XML_20161001 = "FG-GML-{0:04d}-{1:02d}-{2:02d}-DEM5A-20161001.xml"
GEO_XML_20170202 = "FG-GML-{0:04d}-{1:02d}-{2:02d}-DEM5A-20170202.xml"

NPY_DIR = "./"
NPY_2ND_FILE = "npydata-{0:04d}-{1:02d}.npy"
NPY_3RD_FILE = "npydata-{0:04d}-{1:02d}-{2:02d}.npy"

WATER_LEVEL = -1.0
SEA_LEVEL = -5.0

def xml2array(mesh1, mesh2, mesh3):
    dir = GEO_DIR.format(mesh1, mesh2)
    fname = GEO_XML_20161001.format(mesh1, mesh2, mesh3)
    if os.path.isfile(dir+"/"+fname) == False:
        fname = GEO_XML_20170202.format(mesh1, mesh2, mesh3)
    if os.path.isfile(dir+"/"+fname) == False:
        raise FileNotFoundError(dir+"/"+fname)

    tree = ET.parse(dir+"/"+fname)
    root = tree.getroot()

    tl = root.find('./{http://fgd.gsi.go.jp/spec/2008/FGD_GMLSchema}DEM/{http://fgd.gsi.go.jp/spec/2008/FGD_GMLSchema}coverage/{http://www.opengis.net/gml/3.2}rangeSet/{http://www.opengis.net/gml/3.2}DataBlock/{http://www.opengis.net/gml/3.2}tupleList')
    if tl is None:
        raise Exception("{http://www.opengis.net/gml/3.2}tupleList is not found")

    sp = root.find('./{http://fgd.gsi.go.jp/spec/2008/FGD_GMLSchema}DEM/{http://fgd.gsi.go.jp/spec/2008/FGD_GMLSchema}coverage/{http://www.opengis.net/gml/3.2}coverageFunction/{http://www.opengis.net/gml/3.2}GridFunction/{http://www.opengis.net/gml/3.2}startPoint')
    if sp is None:
        raise Exception("{http://www.opengis.net/gml/3.2}startPoint is not found")

    (spx, spy) = sp.text.split()

    lines = tl.text.split()
    array = np.zeros(33750)
    array.fill(WATER_LEVEL)
    i = int(spx) + int(spy) * 225
    for l in lines:
        (t, h) = l.split(",")
        hval = float(h)
        if hval == -9999:
            array[i] = WATER_LEVEL
        else:
            array[i] = hval
        i += 1

    return array.reshape((150, 225))

# ここからスタート

if len(sys.argv) < 3:
    print("xml2npy.py mesh1 mesh2 [mesh3]")
    exit(-1)

print("sys.argv=", sys.argv)

mesh1 = int(sys.argv[1])
mesh2 = int(sys.argv[2])

mesh3 = -1

if len(sys.argv) > 3:
    mesh3 = int(sys.argv[3])

print("mesh1=", mesh1)
print("mesh2=", mesh2)
print("mesh3=", mesh3)

if mesh3 == -1:
    yarray = None
    for y in range(10):
        xarray = None
        for x in range(10):
            try:
                m3 = y * 10 + x
                tarray = xml2array(mesh1, mesh2, m3)
            except Excetion as err:
                tarray = np.zeros((150, 225))
                tarray.fill(SEA_LEVEL)
            finally:
                if xarray is None:
                    xarray = tarray
                else:
                    xarray = np.concatenate((xarray, tarray), axis=1)
        if yarray is None:
            yarray = xarray
        else:
            yarray = np.concatenate((xarray, yarray), axis=0)
    np.save(NPY_DIR+"/"+NPY_2ND_FILE.format(mesh1, mesh2), yarray)
else:
    yarray = xml2array(mesh1, mesh2, mesh3)
    np.save(NPY_DIR+"/"+NPY_3RD_FILE.format(mesh1, mesh2, mesh3), yarray)

print(yarray.shape)

npy5x5.py

# coding: utf-8

import numpy as np
from scipy.ndimage import filters
import re
import sys

NPY_DIR = "./"
NPY_FILE = "npy_5x5{0}.npy"

# ここからスタート

if len(sys.argv) < 2:
    print("plotnpy.py npyfilename")
    exit(-1)

m = re.search('npy(data|_5x5)((\-[0-9]+)+)\.npy', sys.argv[1])
if m is None:
    print("Bad npy filename.")
    exit(-1)

if m.group(1) == '_5x5':
    print("This is 5x5 file.")
    exit(-1)

array = np.load(NPY_DIR+"/"+sys.argv[1])
print(array.shape)
print(array)
array5 = np.repeat(array, 5, axis=0)
print(array5.shape)
print(array5)
array5x5 = np.repeat(array5, 5, axis=1)
print(array5x5.shape)
print(array5x5)
aa_array = filters.gaussian_filter(array5x5, 2)

np.save(NPY_DIR+"/"+NPY_FILE.format(m.group(2)), aa_array)

<プログラムの実行>

①XMLを配列に変換します。変換対象のデータは標高データのファイル後半の数字を使います。

 例)対象:FG-GML-5339-31-DEM5A

   ・5339-31のマップ(以下)で赤枠部分の場合、指定方法は「5339 31 72」となります。

   ・コマンドの実行は「python3 xlm2npy.py 5339 31 72」。

   ・実行により「npydata-5339-31-72.npy」というファイルができます。

②5mメッシュを1mメッシュに補間します。

 例)上の例を使うと、

   ・コマンドの実行は「python3 npy5x5.py npydata-5339-31-72.npy」。

   ・実行により「npy_5x5-5339-31-72.npy」というファイルができます。(このファイルを次使います)。

フォロー

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です