Daily Archives: 11/23/2012

MapWinGISでContour Generation

MapWinGISでContour Generation

自前のプログラムで標高データからコンター図を作成する必要があったので、作ってみました。
ArcGISではラスター解析はoptionで別売りだし、QGISとかでもできるのですが、自前のプログラムには組み込めないんですよね。 ましてやvb.netでは。

今回のsampleは、必要最低限の機能しか持っていないので、MapWinGISのtutorialに付け加えれば、操作性も向上できると思います。
元になるprogramは、Mapコントロールの追加example [Chapter 2]にコンター作成機能を付け加えてました。

コンター作成のプログラムは、MapWindowのPluginを参考にしました。svnでソースを取得することができますので、ぜひ参考にすると良いと思います。詳しくは、MapWindow Source Code Repositoryを見てください。

Program Coding

今回は、Mapコントロールの追加example [Chapter 2]に若干付け加えます。

Form design

Main Form

Main Form designはiconを使ってtoolbarにsettingします。
こんな感じ、

blog.godo-tys.jp_wp-content_gallery_contour_image01.jpg
toolbar

Contour Generation Option Form

Main Formから呼び出すContour Generation Option Form designはこんな感じ、

blog.godo-tys.jp_wp-content_gallery_contour_image02.jpg
Contour Generation option Form

Coding

それでは、Contour Generation Option Formからcodingを始めていきます。
参照の追加で、MapWinUtility.dllを追加を忘れないように。

Contour Generation

コンターを作成するのに、必要な情報は、

  1. 入力raster
  2. 出力shape file
  3. コンター間隔
  4. No Data Value

が必要になります。

まずは、dllをimportsしておきます。

Imports System
 
Imports AxMapWinGIS
Imports MapWinGIS
Imports MapWinUtility

次に 変数の宣言

 
    Public t_legend As New LegendControl.Legend
    Public t_handle As Integer
    Public gridFile As String
 
    Private inputGridFile As String = ""
    Private chb3D As Boolean = False

publicな部分は、Main Formから呼び出す時に使います。

コンターは、bool Utils.GenerateContourを参考に作成します。

bool Utils.GenerateContour	(	string 	pszSrcFilename,
string 	pszDstFilename,
double 	dfInterval,
double 	dfNoData,
bool 	Is3D,
object 	dblFLArray,
ICallback 	cBack
)
This program generates a vector contour file from the input raster elevation model (DEM).

See the description of approriate routine in GDAL Tools.

Parameters:
bstrSrcFilename	The name of the source file.
bstrDstFilename	The name of the output file.
bstrOptions	Options of the routine.
cBack	The callback object.
Returns:
True on success and false otherwise.

コンター作成のメインは、

            'Contour Generate
            Dim u As New MapWinGIS.Utils
 
            If rdCI.Checked Then
                boolRes = u.GenerateContour(actualInput,
                                            txtOutputSF.Text,
                                            Double.Parse(txtInterval.Text),
                                            Double.Parse(txtNoData.Text),
                                            chb3D,
                                            0.0)
            Else
                boolRes = u.GenerateContour(actualInput,
                                            txtOutputSF.Text,
                                            0.0,
                                            Double.Parse(txtNoData.Text),
                                            chb3D,
                                            dblArray)
            End If

rdCIはコンター間隔を一定値、もしくは固定値で行うかのチェック値です。そのrdCIによってGenerateContourの引数を変えています。

Generate button event内の実装は

    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        Dim dblArray() As Double = Nothing
        Dim boolRes As Boolean
 
        Try
            Try
                If System.IO.File.Exists(txtOutputSF.Text) Then
                    If (MapWinUtility.Logger.Msg(txtOutputSF.Text.ToString & " already exists. Do you want to replace it?",
                                                 MsgBoxStyle.OkCancel, "Save As") = Microsoft.VisualBasic.MsgBoxResult.Ok) Then
                        Kill(txtOutputSF.Text)
                        Kill(Mid(txtOutputSF.Text, 1, Len(txtOutputSF.Text) - 4) & ".shx")
                        Kill(Mid(txtOutputSF.Text, 1, Len(txtOutputSF.Text) - 4) & ".dbf")
                    Else
                        Me.Cursor = Windows.Forms.Cursors.Default
                        Me.Close()
                        Exit Sub
                    End If
                End If
            Catch ex As Exception
                MapWinUtility.Logger.Msg(ex.Message.ToString)
                Me.Cursor = Windows.Forms.Cursors.Default
                Me.Close()
                Exit Sub
            End Try
 
            Dim actualInput As String = inputGridFile
 
            'Rob Cairns 4-Mar-06: There is a problem with this function somewhere
            'It shifts the contour half a pixel up and to the right
            'The latest gdal build recognises .asc format so I have made a temporary
            'fix by circumventing this conversion for AAIGrid formats
            If inputGridFile.ToLower().EndsWith("arc") Or
               inputGridFile.ToLower().EndsWith("bgd") Then
 
                'If it's not a GDAL-compatible format, must interchange the filename
                actualInput = System.IO.Path.GetDirectoryName(inputGridFile) & "" & _
                              System.IO.Path.GetFileNameWithoutExtension(inputGridFile) & _
                              ".tif"
 
                Try
                    Dim formatChange As New MapWinGIS.Grid
                    formatChange.Open(inputGridFile,
                                      MapWinGIS.GridDataType.UnknownDataType,
                                      True,
                                      MapWinGIS.GridFileType.UseExtension)
                    formatChange.Save(actualInput,
                                      MapWinGIS.GridFileType.GeoTiff)
                    formatChange.Close()
                Catch ex As Exception
                    If Not System.IO.File.Exists(actualInput) Then
                        MapWinUtility.Logger.Msg("Aborting: An error occurred while translating the grid. The error follows." & vbCrLf & vbCrLf & ex.ToString)
                        Exit Sub
                    End If
                End Try
            End If
 
            'Contour Generate
            Dim u As New MapWinGIS.Utils
 
            If rdCI.Checked Then
                boolRes = u.GenerateContour(actualInput,
                                            txtOutputSF.Text,
                                            Double.Parse(txtInterval.Text),
                                            Double.Parse(txtNoData.Text),
                                            chb3D,
                                            0.0)
            Else
                boolRes = u.GenerateContour(actualInput,
                                            txtOutputSF.Text,
                                            0.0,
                                            Double.Parse(txtNoData.Text),
                                            chb3D,
                                            dblArray)
            End If
 
            'Clean up
            If Not actualInput = inputGridFile Then
                Try
                    Kill(actualInput)
                Catch
                End Try
            End If
 
            Me.Close()
        Catch ex As Exception
        End Try
 
    End Sub

.asc.bgd形式のgridの場合は、tifに一度変換しないとだめなようです。

後は、他のcontrol類のevent実装して、Contour Generation Option Formを作成します。
その他は省略。。。

次に、Contour Generation Option Formを呼び出すためのMain Formのcodeingを行います。

Main Formのcodeing

blog.godo-tys.jp_wp-content_gallery_contour_image07.jpg
Add rasterとcontour button

Raster Layersでgridデータを呼び出します。button click event発生時のcodingは、

    Private Sub AddRasterLayer()
        Dim grid As New MapWinGIS.Grid
        Dim gridScheme As MapWinGIS.GridColorScheme
        Dim image As MapWinGIS.Image
        Dim utils As MapWinGIS.Utils
        Dim openDlg As OpenFileDialog = New OpenFileDialog()
        Dim handle As Integer
        Dim ext As String
 
        'initialize dialog
        openDlg.Filter = grid.CdlgFilter '"Supported Formats|*.bgd;*.asc;*.img;*.tif|Binary Grids (*.bgd)|*.bgd|ASCII Grids (*.asc)|*.asc|Image Grids (*.img)|*.img|TIFF Raster (*.tif)|*.tif"
        openDlg.CheckFileExists = True
 
        If (openDlg.ShowDialog(Me) = DialogResult.OK) Then
 
            'get the extension of the file
            ext = System.IO.Path.GetExtension(openDlg.FileName)
 
            utils = New MapWinGIS.UtilsClass()
            gridScheme = New MapWinGIS.GridColorScheme()
            grid = New MapWinGIS.GridClass()
 
            'open the grid
            grid.Open(openDlg.FileName, MapWinGIS.GridDataType.UnknownDataType, True, MapWinGIS.GridFileType.UseExtension)
 
 
            'create a coloring scheme for the image
            gridScheme.UsePredefined(System.Convert.ToDouble(grid.Minimum), System.Convert.ToDouble(grid.Maximum), MapWinGIS.PredefinedColorScheme.SummerMountains)
 
            image = New MapWinGIS.Image()
 
            'convert the grid to a image
            image = utils.GridToImage(grid, gridScheme)
 
            'add the image to the legend and map
            handle = Legend1.Layers.Add(image, True)
 
            'grid filname set
            gridFilename(handle) = openDlg.FileName
 
            If (Legend1.Layers.IsValidHandle(handle)) Then
 
                'set the layer name
                'Legend1.Map.set_LayerName(handle, System.IO.Path.GetFileNameWithoutExtension(grid.Filename))
                Legend1.Map.LayerName(handle) = System.IO.Path.GetFileNameWithoutExtension(grid.Filename)
 
                'set's the legend layer type, this displays a default icon in the legend (line shapefile, point shapefile,polygon shapefile,grid,image)
                Legend1.Layers.ItemByHandle(handle).Type = MapWindow.Interfaces.eLayerType.Grid
 
                'set coloring scheme
                AxMap1.SetImageLayerColorScheme(Legend1.SelectedLayer, gridScheme)
                Legend1.Layers.ItemByHandle(Legend1.SelectedLayer).Refresh()
            End If
 
            'close the grid
            grid.Close()
 
        End If
 
    End Sub

でrasterファイルだけを呼び出しています。Map上はimagefileとして変換しなければ表示できないので、image = utils.GridToImage(grid, gridScheme)でimageに変換しています。
その際に、gridファイル名がNullになってしまうため、gridFilenam()にファイル名を入れておきます。

次に、Contour button click event発生時のcodingは、

    Private Sub ToolStripButton2_Click(sender As System.Object, e As System.EventArgs) Handles ToolStripButton2.Click
        If AxMap1.NumLayers > 0 Then
 
            Dim frmGenerateContour As New ContourGenerate()
 
            frmGenerateContour.t_legend = Legend1
            frmGenerateContour.t_handle = layerHandle
            frmGenerateContour.GridFile = gridFilename(layerHandle)
            frmGenerateContour.Show(Me)
 
        End If
    End Sub

で、MapWInGISのtutorialで別Formの呼び出しでのcodingと同じ形式です。

Programの実行

では、ToolContourを保存して実行してみましょう。

legendで選択したRaster Layerのコンターを作成します。 layerを選択して、contour buttonをクリックします。

今回は、神奈川県のサンプルrasterを読み込んで表示させます。
blog.godo-tys.jp_wp-content_gallery_contour_image03.jpg
神奈川県のサンプルraster file表示

Contour buttonをクリックして、Contour Generation Option Formを表示させます。
blog.godo-tys.jp_wp-content_gallery_contour_image04.jpg
Contour Generation Option Form表示画面

Generate buttonをclickしてコンター図作成した結果です。
blog.godo-tys.jp_wp-content_gallery_contour_image05.jpg
コンター図作成表示図

追加したcontourのshape fileだけを表示する。
blog.godo-tys.jp_wp-content_gallery_contour_image06.jpg
contourのshape file選択表示

今回のまとめ

  1. MapWinUtilityを使ってcontour作成のcodeing実装を行いました。
  2. 別Formを作成して、contour Generation Oprion表示を行いました。

vb.net2010だけでなく、C#でも、visual studio2008でも動作することができます。
簡単に自前のソフトウェアにちょっとしたGIS機能を付け加えるには良いと思います。
Contour Generate sampleのsource codeを公開しますので、活用してください。
ただし、あくまでの自分用のサンプルですので、バグなどがある可能性が高いので、原文のままの使用は避けてください。

サンプルコードおよびサンプルデータを使って、お使いのPCの不具合が生じても一切責任は持てませんので、あくまでも自己責任にて使用してください。

1 / 11

Social Widgets powered by AB-WebLog.com.