基盤地図情報 数値標高を読み込んでみる(修正版)
2012/3/5の記事の修正版です
Pythonで強引に基盤地図情報 数値標高をQGISに取り込むぞというのを前に書いたのですが、中途半端な対応で開けないファイルがありました。開けないのは悲しいので、その辺だけ修正しておきます。
もう一回言っときますが、コマンドラインでやれよというような内容です。
処理手順
手順は同じ。
ここで紹介したScript Runnerプラグインを使用して、
- JPGIS形式そのままでは読めませんので、GDALで読めるフォーマットのうち簡単なものに変換(ESRI ASCII Raster formatにしました)
- 変換したものをGDALを使用して開く
- ついでなので、GDALで等高線のshapefileを作成して、それも開く
としました。
中間ファイルとして
が開いたファイルと同じディレクトリに作成されちゃいます。
実行イメージ
前回と同じなので割愛
ソースです
dem20120330.py
Script Runnerプラグインのインストールもお忘れなく。
ソースの中身はこんな感じです。
# -*- coding: utf-8 -*- import os, sys from PyQt4.QtCore import * from PyQt4.QtGui import * from qgis.core import * from qgis.gui import * class demHandler(): def __init__(self, filename): self.row = 0 self.col = 0 self.west = 0 self.east = 0 self.north = 0 self.south = 0 self.alti = [] self._readFile(filename) def _readFile(self, filename): file = open(filename, 'r') for line in file: if line.lstrip().startswith('<jps:westBoundLongitude>'): self.west = float(self._getValue(line)) self.east = float(self._getValue(file.next())) self.south = float(self._getValue(file.next())) self.north = float(self._getValue(file.next())) break for line in file: if line.lstrip().startswith('<jps:high>'): val = (self._getValue(file.next())).split(' ') self.col = int(val[0])+1 self.row = int(val[1])+1 break for line in file: if line.lstrip().startswith('</jps:sequencingRule>'): break if line.lstrip().startswith('<alti>'): self.alti.append(self._getValue(line)) for i in range(5): file.next() for line in file: if line.lstrip().startswith('<jps:coordValues>'): val = self._getValue(line).split(' ') x = int(val[0]) y = int(val[1]) break file.close() for i in range(y*self.col+x): self.alti.insert(0, '-9999.') for i in range((self.col*self.row)-len(self.alti)): self.alti.append('-9999.') def _getValue(self, line): return ((line.split('>'))[1].split('<'))[0] def getAlti(self): return self.alti.pop(0) def getAltiRow(self, row): return self.alti[row*self.col:(row+1)*self.col] class ascWriter(): def __init__(self, dem): self.dem = dem def write(self, filename): #ESRI ASCII Raster file = open(filename, 'w') outbuff = [] outbuff.append(' '.join(('ncols','%s\n' % self.dem.col))) outbuff.append(' '.join(('nrows','%s\n' % self.dem.row))) outbuff.append(' '.join(('xllcorner','%s\n' % self.dem.west))) outbuff.append(' '.join(('yllcorner','%s\n' % self.dem.south))) outbuff.append(' '.join(('cellsize','%.10f\n' % ((self.dem.east-self.dem.west)/self.dem.col)))) outbuff.append(' '.join(('NODATA_value','-9999.\n'))) for x in range(self.dem.row): outbuff.append(''.join((' '.join(self.dem.getAltiRow(x)), '\n'))) file.writelines(outbuff) file.close() #prj fileInfo = QFileInfo(filename) prjfile = r'%s/%s.prj' % (fileInfo.path(), fileInfo.baseName()) file = open(prjfile, 'w') outbuff = [r'GEOGCS["GCS_JGD_2000",DATUM["D_JGD_2000",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]'] file.writelines(outbuff) file.close() def run_script(iface): demfile = QFileDialog.getOpenFileName(iface.mainWindow(), ur'基盤地図情報 数値標高(JPGIS形式)', '', 'XML files (*.xml)') dem = demHandler(demfile) fileInfo = QFileInfo(demfile) ascfile = r'%s/%s.asc' % (fileInfo.path(), fileInfo.baseName()) asc = ascWriter(dem) asc.write(ascfile) #contour shapefile shpfile = r'%s/%s.shp' % (fileInfo.path(), fileInfo.baseName()) process = QProcess() process.start(r'gdal_contour -i 10.0 %s %s' % (ascfile, shpfile), QIODevice.ReadOnly) process.waitForFinished() demLayer = iface.addRasterLayer(ascfile,ascfile) demLayer.setDrawingStyle(QgsRasterLayer.SingleBandPseudoColor) demLayer.setColorShadingAlgorithm(QgsRasterLayer.PseudoColorShader) contLayer = iface.addVectorLayer(shpfile,shpfile,'ogr') iface.mapCanvas().refresh()
改良するなら
- QFileDialog.getOpenFileName→QFileDialog.getOpenFileNamesに変更して複数ファイル指定にする
- 中でgdalのコマンドたたいているので、他のコマンドに変えちゃう
とかすると色々出来るはず。
やると本業に差し支えそうなので止めときます。大量のデータ処理は業者さんにお願いしましょう。