VB.NETでgdal/ogrを使ってみる。 [Chapter 1]
電子国土地図にGeoJSONを重ねてみる。 [Chapter 1]で作成したGeoJSONファイルを作るためにogr2ogrというコマンドを使いました。いろいろと調べていると、gdal/ogrのC#のdllがあるんですね。 ここを参照してください。おまけにC#のサンプルもあるので、ちょちょいと変換すれば、VBでも簡単にできるのでは? と考えた次第でして。
gdal_csharp.dllとogr_csharp.dllをFWToolsをインストールしたフォルダーから参照設定すれば、オブジェクトブラウザーから見えますね。
なんと簡単。 ではサンプルをVBに変換してGO Debug。
しかし、エラーで動かず。 なんかOSGeo.OGR.Ogr.RegisterAll()でエラーでだめ。
2日ほど、このOSGeo.OGR.Ogr.RegisterAll()にはまってしまいましたが、なんとか解決しました。
これで、Gdalでラスター解析とogrでVectorデータの変換や編集できるじゃないの。
ということで、まずは第一歩です。
vb.net版のGDALInfoとOGRInfoを作成してみました。
とりあえず、プログラムを見てみましょう。
準備
gdal/ogrの最新版?をインストール
これは、FWToolsを使ってもよいのですが、調べて新しいbinaryが存在することがわかったので、こちらからダウンロードしてセットアップしました。
動作確認したのは、release-1600-gdal-1-9-1-mapserver-6-0-3のgdal-19-1600-core.msiを使いました。
そして、こちらの方法を参考にしてgdal/ogrが使えるようにしました。
vb.netのコードは
Private Function SetupGDALOGR() As Boolean SetupGDALOGR = False Dim strNewPath As String = Environment.GetEnvironmentVariable("PATH") 'gdalPathとtmpPathは、開発PCの環境にあわせて変更してください。 'GDALは下記のURLより最新版を取得して、default complete install 'http://www.gisinternals.com/sdk/Download.aspx?file=release-1600-gdal-1-9-1-mapserver-6-0-3gdal-19-1600-core.msi Dim gdalPath As String = "C:Program Files" 'GDAL_EXTRACT_FOLDER_PATH_GOES_HERE & "GDAL-1.8.0" Dim tmpPath As String = "c:\tmp" Dim GDAL_CACHEMAX As String = "100000" Dim info As New FileInfo(gdalPath) If (info.Attributes And FileAttributes.Directory) > 0 Then Dim oldPath As [String] = Environment.GetEnvironmentVariable("PATH") Dim PATH2 As [String] = gdalPath & "\GDAL;" & _ gdalPath & "\GDALpython;" & _ gdalPath & "\GDALpythonosgeo;" & _ gdalPath & "\GDALplugins;" & _ gdalPath & "\GDALcsharp;" If Not strNewPath.Contains(PATH2) Then strNewPath = PATH2 & ";" & strNewPath Environment.SetEnvironmentVariable("PATH", strNewPath) End If Dim GDAL_DATA As [String] = gdalPath & "\GDALgdal-data" Environment.SetEnvironmentVariable("\GDAL_DATA", GDAL_DATA) OSGeo.GDAL.Gdal.SetConfigOption("\GDAL_DATA", GDAL_DATA) Dim GDAL_DRIVER_PATH As [String] = gdalPath & "\GDALgdalplugins" Environment.SetEnvironmentVariable("GDAL_DRIVER_PATH", GDAL_DRIVER_PATH) OSGeo.GDAL.Gdal.SetConfigOption("GDAL_DRIVER_PATH", GDAL_DRIVER_PATH) Dim PYTHONPATH As [String] = gdalPath & "\GDALpythonosgeo" Environment.SetEnvironmentVariable("PYTHONPATH", PYTHONPATH) OSGeo.GDAL.Gdal.SetConfigOption("PYTHONPATH", PYTHONPATH) Dim PROJ_LIB As [String] = gdalPath & "\GDALproj" Environment.SetEnvironmentVariable("PROJ_LIB", PROJ_LIB) OSGeo.GDAL.Gdal.SetConfigOption("PROJ_LIB", PROJ_LIB) OSGeo.GDAL.Gdal.SetConfigOption("GDAL_CACHEMAX", GDAL_CACHEMAX) OSGeo.GDAL.Gdal.SetConfigOption("CPL_TMPDIR", tmpPath) 'This line throws an exception if the the wrong version of GDal was found in the path somewhere ' OR the path didn't point to GDal correctly. ' -------------------------------------------------------------------- ' Register format(s). ' -------------------------------------------------------------------- OSGeo.OGR.Ogr.RegisterAll() OSGeo.GDAL.Gdal.AllRegister() SetupGDALOGR = True End If End Function
注意点はプログラムのコメントをみてください。
vb.netのデザイン
サンプルコード
http://trac.osgeo.org/gdal/wiki/GdalOgrInCsharpのC#のサンプルソースを使います。
まずは、ファイル選択ボタンをClick event内に処理を書きます。
大まかな流れは、
-
Form load 時に、SetupGDALOGR でAllRegister()します。
-
file open dialogから対応するVector formatを読み込みます。
-
Vector formatのすべてのデータをTextboxに書き出します。
-
imports OSGeo.OGR などを忘れずに。
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load If Not SetupGDALOGR() Then System.Environment.[Exit](-1) End If End Sub Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click Dim openDlg As OpenFileDialog = New OpenFileDialog() 'initialize dialog 'openDlg.Filter = "Shapefile Format|*.shp" '対応するRaster format形式 'http://www.gdal.org/ogr/ogr_formats.html openDlg.Filter = "Supported Vector Formats|*.shp;*.json;*gml;*.kml;*.tab;*.mif;*.mid|" & _ "Shapefile (*.shp)|*.shp|" & _ "GeoJSON (*.json)|*.json|" & _ "GML File (*.gml)|*.gml|" & _ "KML File (*.kml)|*.kml|" & _ "MapInfo File (*.tab;*.mif;*.mid)|*.tab;*.mif;*.mid" openDlg.CheckFileExists = True If (openDlg.ShowDialog(Me) = DialogResult.OK) Then Try TextBox1.Text = "" ' -------------------------------------------------------------------- ' Open data source. ' -------------------------------------------------------------------- Me.Text = "OGRInfo(VB版)" & " ファイル名 : " & Path.GetFileName(openDlg.FileName) infoTextLineOut("Vector Filename: " & openDlg.FileName) Dim ds As DataSource = Ogr.Open(openDlg.FileName, 0) If ds Is Nothing Then MsgBox("Can't open " & openDlg.FileName, MsgBoxStyle.Exclamation, "file open error") System.Environment.[Exit](-1) End If ' -------------------------------------------------------------------- ' Get driver ' -------------------------------------------------------------------- Dim drv As OSGeo.OGR.Driver = ds.GetDriver() If drv Is Nothing Then MsgBox("Can't get driver." & openDlg.FileName, MsgBoxStyle.Exclamation, "driver error") System.Environment.[Exit](-1) End If ' TODO: drv.name is still unsafe with lazy initialization (Bug 1339) infoTextLineOut("Using driver " & drv.name) ' -------------------------------------------------------------------- ' Iterating through the layers ' -------------------------------------------------------------------- For iLayer As Integer = 0 To ds.GetLayerCount() - 1 Dim layer As Layer = ds.GetLayerByIndex(iLayer) If layer Is Nothing Then MsgBox("FAILURE: Couldn't fetch advertised layer " & iLayer, MsgBoxStyle.Exclamation, "layer error") System.Environment.[Exit](-1) End If ReportLayer(layer) Next Catch ex As System.Exception MsgBox(ex.Message, MsgBoxStyle.Exclamation, "Application error") Exit Sub End Try End If End Sub Public Sub ReportLayer(layer As Layer) Dim def As FeatureDefn = layer.GetLayerDefn() infoTextLineOut("Layer name: " & def.GetName()) infoTextLineOut("Feature Count: " & layer.GetFeatureCount(1)) Dim ext As New Envelope() layer.GetExtent(ext, 1) Dim minx As Double = Convert.ToDouble(ext.MinX) Dim miny As Double = Convert.ToDouble(ext.MinY) Dim maxx As Double = Convert.ToDouble(ext.MaxX) Dim maxy As Double = Convert.ToDouble(ext.MaxY) infoTextLineOut("Extent: " & minx & "," & miny & "," & maxx & "," & maxy) ' -------------------------------------------------------------------- ' Reading the spatial reference ' -------------------------------------------------------------------- Dim sr As SpatialReference = layer.GetSpatialRef() Dim srs_wkt As String = "" If sr IsNot Nothing Then sr.ExportToPrettyWkt(srs_wkt, 1) Else srs_wkt = "(unknown)" End If infoTextLineOut("Layer SRS WKT: " & srs_wkt) ' -------------------------------------------------------------------- ' Reading the fields ' -------------------------------------------------------------------- infoTextLineOut("Field definition:" & vbNewLine) For iAttr As Integer = 0 To def.GetFieldCount() - 1 Dim fdef As FieldDefn = def.GetFieldDefn(iAttr) infoTextLineOut(fdef.GetNameRef() & ": " & fdef.GetFieldTypeName(fdef.GetFieldType()) & _ " (" & fdef.GetWidth() & "." & fdef.GetPrecision() & ")") Next ' -------------------------------------------------------------------- ' Reading the shapes ' -------------------------------------------------------------------- infoTextLineOut("") Dim feat As Feature = Nothing While (InlineAssignHelper(feat, layer.GetNextFeature())) IsNot Nothing ReportFeature(feat, def) feat.Dispose() End While End Sub Public Sub ReportFeature(feat As Feature, def As FeatureDefn) infoTextLineOut("Feature(" & def.GetName() & "): " & feat.GetFID()) For iField As Integer = 0 To feat.GetFieldCount() - 1 Dim fdef As FieldDefn = def.GetFieldDefn(iField) infoTextLineOut(fdef.GetNameRef() & " (" & fdef.GetFieldTypeName(fdef.GetFieldType()) & ") = ") If feat.IsFieldSet(iField) Then If fdef.GetFieldType() = FieldType.OFTStringList Then Dim sList As String() = feat.GetFieldAsStringList(iField) For Each s As String In sList infoTextOut("""" & s & """ ") Next infoTextLineOut("") ElseIf fdef.GetFieldType() = FieldType.OFTIntegerList Then Dim count As Integer Dim iList As Integer() = feat.GetFieldAsIntegerList(iField, count) For i As Integer = 0 To count - 1 infoTextOut(iList(i) & " ") Next infoTextLineOut("") ElseIf fdef.GetFieldType() = FieldType.OFTRealList Then Dim count As Integer Dim iList As Double() = feat.GetFieldAsDoubleList(iField, count) For i As Integer = 0 To count - 1 infoTextOut(iList(i).ToString() & " ") Next infoTextLineOut("") Else infoTextLineOut(feat.GetFieldAsString(iField)) End If Else infoTextLineOut("(null)") End If Next If feat.GetStyleString() IsNot Nothing Then infoTextLineOut(" Style = " & feat.GetStyleString()) End If Dim geom As Geometry = feat.GetGeometryRef() If geom IsNot Nothing Then infoTextLineOut(" " & geom.GetGeometryName() & "(" & geom.GetGeometryType() & ")") Dim sub_geom As Geometry For i As Integer = 0 To geom.GetGeometryCount() - 1 sub_geom = geom.GetGeometryRef(i) If sub_geom IsNot Nothing Then infoTextLineOut(" subgeom" & i & ": " & sub_geom.GetGeometryName() & "(" & sub_geom.GetGeometryType() & ")") End If Next Dim env As New Envelope() geom.GetEnvelope(env) Dim minx As Double = Convert.ToDouble(env.MinX) Dim miny As Double = Convert.ToDouble(env.MinY) Dim maxx As Double = Convert.ToDouble(env.MaxX) Dim maxy As Double = Convert.ToDouble(env.MaxY) infoTextLineOut("Extent: " & minx & "," & miny & "," & maxx & "," & maxy) Dim geom_wkt As String = "" geom.ExportToWkt(geom_wkt) infoTextLineOut(" " & geom_wkt) End If infoTextLineOut("") End Sub Private Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T target = value Return value End Function Private Sub infoTextLineOut(ByRef strInfo As String) TextBox1.AppendText(strInfo & vbNewLine) Application.DoEvents() End Sub Private Sub infoTextOut(ByRef strInfo As String) TextBox1.AppendText(strInfo) Application.DoEvents() End Sub
プログラムの実行
それでは、実行してみましょう。
ちゃんと読み込んでいるようですね。 Vectorデータの情報が表示されていますので、
これを改良していけば、vb版ogr2ogrが作れて、Vector format transformが可能となりますね。 そうすると、OpenLayersで電子国土地図と重ねることができるわけです。
まだまだ、長いなぁ。。。
サンプルコードをこちらにアップしておきます。使用する際は自己責任にて使って下さい。
今回お世話にになってHPです。 先人に感謝します。
おまけ
gdal Utilitiesとogr Utilitiesのコマンド版exeの説明がまとめてあります。市販のGISにも使われているのですが、open sourceとはすごいですね。 感謝します。
コマンド版をパラメータ渡した方が早くない???
なんとOsGeo日本支部で基盤地図対応GDAL/OGRが公開されているではありませんか。 こちらに差し替えた方が後々便利かな?
gdalinfoのvbサンプルもこちらにアップしておきます。使用する際は自己責任にて使って下さい。
最近のコメント