VB.NETでgdal/ogrを使ってみる。 [Chapter 1]

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版のGDALInfoOGRInfoを作成してみました。

とりあえず、プログラムを見てみましょう。

準備

gdal/ogrの最新版?をインストール
これは、FWToolsを使ってもよいのですが、調べて新しいbinaryが存在することがわかったので、こちらからダウンロードしてセットアップしました。
動作確認したのは、release-1600-gdal-1-9-1-mapserver-6-0-3のgdal-19-1600-core.msiを使いました。

そして、こちらの方法を参考にしてgdal/ogrが使えるようにしました。

参照の追加は、gdal-19-1600-core.msiをセットアップしたフォルダーのgdal_csharp.dllとogr_csharp.dllを参照するようにしてください。

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のデザイン

visual studio 2010を使っていますので、2005や2008ではそれにあわせたGDALのcore.msiでセットアップしてください。

blog.godo-tys.jp_wp-content_gallery_gdal_image01.jpg
デザイン画面

サンプルコード

http://trac.osgeo.org/gdal/wiki/GdalOgrInCsharpのC#のサンプルソースを使います。

まずは、ファイル選択ボタンをClick event内に処理を書きます。
大まかな流れは、

  1. Form load 時に、SetupGDALOGR でAllRegister()します。
  2. file open dialogから対応するVector formatを読み込みます。
  3. Vector formatのすべてのデータをTextboxに書き出します。 
  4. 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

プログラムの実行

それでは、実行してみましょう。

blog.godo-tys.jp_wp-content_gallery_gdal_image02.jpg
kanagawk.shpを呼び出した例

blog.godo-tys.jp_wp-content_gallery_gdal_image03.jpg
kanagawk.jsonを呼び出した例

ちゃんと読み込んでいるようですね。 Vectorデータの情報が表示されていますので、
これを改良していけば、vb版ogr2ogrが作れて、Vector format transformが可能となりますね。 そうすると、OpenLayersで電子国土地図と重ねることができるわけです。

まだまだ、長いなぁ。。。

サンプルコードをこちらにアップしておきます。使用する際は自己責任にて使って下さい。

今回お世話にになってHPです。 先人に感謝します。

おまけ

gdal Utilitiesogr Utilitiesのコマンド版exeの説明がまとめてあります。市販のGISにも使われているのですが、open sourceとはすごいですね。 感謝します。
コマンド版をパラメータ渡した方が早くない??? 

なんとOsGeo日本支部で基盤地図対応GDAL/OGRが公開されているではありませんか。 こちらに差し替えた方が後々便利かな?

gdalinfoのvbサンプルもこちらにアップしておきます。使用する際は自己責任にて使って下さい。

Comments are closed.

Social Widgets powered by AB-WebLog.com.