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サンプルもこちらにアップしておきます。使用する際は自己責任にて使って下さい。




最近のコメント