Mapコントロールの追加example [Chapter 2]

Mapコントロールの追加example

[Chapter 2]では[Chapter 1]で作成したプログラムにMap control eventやメニューを追加してみます。

Program開発環境は、Visual Basic.NET 2010です。
Visual Sutdioの使い方は、一通り問題なく操作でき、一度はGUIのprogramを作成したことがある中級者を対象にしています。 したがって、vb.netの操作に関しては、端折ります。

Map controlの登録

Map Controlの登録については、[Chapter 1]を見てください。

Program Coding

まずは、From designをして、Codingします。

Form Design

Form designはiconを使ってtoolbarにsettingします。
こんな感じ、
blog.godo-tys.jp_wp-content_gallery_mapwingis_ex02_image01.jpg
Form Design

AxMap1のプロパティの変更
CursorMode → cmNone
MapUnits → umDecimalDegrees (サンプルの神奈川県のshape fileがJGD2000世界測地系)
SendMouseDown → True
SendMouseMove → True
SendMouseUp → false

ここで、mouse eventを利用するには、必ずSendMouse~~をtrueにしてください。falseではeventを捕まえることができません。

その他は、[Chapter 1]から追加したcontrolはtoolstripstatusです。

iconは、Mapwindowのsvnからdwonloadします。
詳しくはHPを参照してください。

Coding

ToolStrip1

Add layerの追加
blog.godo-tys.jp_wp-content_gallery_mapwingis_ex02_image02.jpg
ToolStrip1

Add layerを以下のようにします。

    Private Sub AddLayer()
        Dim shpfile As MapWinGIS.Shapefile
        Dim openDlg As OpenFileDialog = New OpenFileDialog()
        Dim handle As Integer
        Dim ext As String = ""
 
        'initialize dialog
        openDlg.Filter = "Supported Formats|*.shp|Shapefile (*.shp)|*.shp"
        openDlg.CheckFileExists = True
 
        If (openDlg.ShowDialog(Me) = DialogResult.OK) Then
 
            'get the extension of the file
            ext = System.IO.Path.GetExtension(openDlg.FileName)
 
            If ext = ".shp" Then
 
                shpfile = New MapWinGIS.ShapefileClass()
 
                'open the shapefile
                Dim blmCheck As Boolean = shpfile.Open(openDlg.FileName)
 
                'add the shapefile to the map
                handle = AxMap1.AddLayer(shpfile, True)
 
                AxMap1.Redraw()
 
                rootNode.Nodes.Add(System.IO.Path.GetFileNameWithoutExtension(shpfile.Filename))
 
            End If
 
        End If
    End Sub

ここで、rootNode.Nodes.Addは親ノードに子ノードを追加するようにしています。

    Private rootNode As New TreeNode("Layer")

で宣言しています。

ToolStrip2

zoom表示の履歴や属性表示の機能を追加します。
blog.godo-tys.jp_wp-content_gallery_mapwingis_ex02_image03.jpg
ToolStrip1

ToolZoomPrevBtn

「表示範囲を前に戻す」機能の追加です。
ToolZoomPrevBtnのClick eventを以下のように追加します。

    Private Sub ToolZoomPrevBtn_Click(sender As System.Object, e As System.EventArgs) Handles ToolZoomPrevBtn.Click
        If ZoomLevel > 0 Then
            ZoomingLevels = True
            ZoomLevel -= 1
            AxMap1.Extents = ZoomExtents(ZoomLevel)
            ZoomingLevels = False
        End If
    End Sub

ZoomLevelで表示履歴を保存しておきます。
AxMap1.Extentsは、Map controlの表示範囲になります。

ToolZoomNextBtn

「表示範囲を次に進む」機能の追加です。
ToolZoomNextBtnのClick eventを以下のように追加します。

    Private Sub ToolZoomNextBtn_Click(sender As System.Object, e As System.EventArgs) Handles ToolZoomNextBtn.Click
        If ZoomLevel < ZoomExtents.Count - 1 Then
            ZoomingLevels = True
            ZoomLevel += 1
            AxMap1.Extents = ZoomExtents(ZoomLevel)
            ZoomingLevels = False
        End If
    End Sub

このToolZoomNextBtnとToolZoomPrevBtnには、AxMap1の拡大縮小移動したばあいのextentsを取得する必要があります。これは、ExtentsChanged eventで取得します。

ExtentsChanged event

Extentsが変化した時に発生するeventです。
これは、よく使いますので、覚えておいてください。

    Private Sub AxMap1_ExtentsChanged(sender As System.Object, e As System.EventArgs) Handles AxMap1.ExtentsChanged
        Dim ex As MapWinGIS.Extents = AxMap1.Extents
        Dim i As Integer
 
        If ZoomingLevels = False Then 'we're not in mid-zoomprev or zoomnext
            If Not ZoomLevel = ZoomExtents.Count - 1 Then 'we're not at the end of the zoom list to empty the array beyond this point
                For i = ZoomExtents.Count - 1 To ZoomLevel + 1 Step -1
                    ZoomExtents.RemoveAt(i)
                Next
            End If
            'now add the new extents to the end of the array
            ZoomExtents.Add(ex)
            ZoomLevel = ZoomExtents.Count - 1
            ZoomingLevels = False
        End If
 
        AxMap1.Refresh()
 
    End Sub
ToolIdentityBtn

「個別属性値の表示する」機能の追加です。
ToolIdentityBtnのClick eventを以下のように追加します。

    Private Sub ToolIdentityBtn_Click(sender As System.Object, e As System.EventArgs) Handles ToolIdentityBtn.Click
        AxMap1.CursorMode = MapWinGIS.tkCursorMode.cmSelection
        chkAction = "Identity"
    End Sub

chkActionでmouse click時の動作の変更をします。
ToolIdentityBtn_Clickだけでは、mouse cursorが変わるだけで、個別属性値表示はできません。
ここで、mouse down eventを使います。
今回は、mouseのright button clickで個別属性値表示ができるようにします。

    Private Sub AxMap1_MouseDownEvent(sender As System.Object, e As AxMapWinGIS._DMapEvents_MouseDownEvent) Handles AxMap1.MouseDownEvent
        Dim sf As MapWinGIS.Shapefile
        Dim ex As New MapWinGIS.Extents
        Dim xProjected As Double, yProjected As Double
        Dim result As Boolean
        Dim ShapeIDs As Object = Nothing
        Dim ShapeID As Integer
        Dim i As Integer
 
 
        If AxMap1.CursorMode <> MapWinGIS.tkCursorMode.cmSelection Then Exit Sub
 
        'get layer handle
        layerHandle = setLayerHandle()
        If layerHandle < 0 Then Exit Sub
 
        'mouse down event
        If e.button = 1 Then
            ' mouse left button click
 
 
        ElseIf e.button = 2 Then
            ' mouse right button click
 
            If AxMap1.NumLayers > 0 Then
 
                'get the shapefile object
                sf = AxMap1.get_GetObject(layerHandle)
 
                For i = 0 To sf.NumShapes - 1
                    sf.ShapeSelected(i) = False
                Next i
 
                'test to see if any shapes for this area lie withing the seleted bounds
                AxMap1.PixelToProj(e.x, e.y, xProjected, yProjected)
                ex.SetBounds(xProjected, yProjected, 0, xProjected, yProjected, 0)
                result = sf.SelectShapes(ex, 0.0, MapWinGIS.SelectMode.INTERSECTION, ShapeIDs)
 
                'if we found some selected shapes then mark as selected
                If result = True Then
                    For i = 0 To UBound(ShapeIDs)
                        ShapeID = ShapeIDs(i)
                        If sf.ShapeSelected(ShapeIDs(i)) = True Then
                            sf.ShapeSelected(ShapeIDs(i)) = False
                        Else
                            sf.ShapeSelected(ShapeIDs(i)) = True
                        End If
                        AxMap1.set_ShapeFillColor(layerHandle, ShapeIDs(i), System.Convert.ToUInt32(RGB(0, 255, 0)))     'Green
                        AxMap1.set_ShapeLineColor(layerHandle, ShapeIDs(i), System.Convert.ToUInt32(RGB(255, 0, 0)))    ' Color.Red
                    Next i
                End If
 
                AxMap1.Redraw()
 
                If chkAction = "Identity" Then
                    Identity(ShapeID, result)
                End If
 
            End If
        End If
    End Sub

MapWinGISを利用する場合、気をつけなければならない点は、

  1. Layer numbersは0から始まる。
  2. shape numbersは0から始まる。
  3. field numbersは0から始まる。

のように、0が基準になっていることです。
したがって、「For i = 0 To sf.NumShapes – 1」のように、feature数でloopさせる場合、 「-1」する必要があります。
今後、間違えないようにしてください。

上記のmouse down clickの中で重要な部分は

AxMap1.PixelToProj(e.x, e.y, xProjected, yProjected)
ex.SetBounds(xProjected, yProjected, 0, xProjected, yProjected, 0)
result = sf.SelectShapes(ex, 0.0, MapWinGIS.SelectMode.INTERSECTION, ShapeIDs)
If result = True Then
    For i = 0 To UBound(ShapeIDs)
        ShapeID = ShapeIDs(i)
        If sf.ShapeSelected(ShapeIDs(i)) = True Then
            sf.ShapeSelected(ShapeIDs(i)) = False
        Else
            sf.ShapeSelected(ShapeIDs(i)) = True
        End If
        AxMap1.set_ShapeFillColor(layerHandle, ShapeIDs(i), System.Convert.ToUInt32(RGB(0, 255, 0)))     'Green
        AxMap1.set_ShapeLineColor(layerHandle, ShapeIDs(i), System.Convert.ToUInt32(RGB(255, 0, 0)))    ' Color.Red
    Next i
End If
  1. AxMap1.PixelToProjでAxMap1上のpixcel座標から測地座標系に変換
  2. ex.SetBoundsでfeatureの検索範囲を設定
  3. sf.SelectShapes(ex, 0.0, MapWinGIS.SelectMode.INTERSECTION, ShapeIDs)でexの範囲内にfeatureの有無をチェックする。 検索の結果は、ShapeIDSのobjectに入っています。
  4. 範囲内にfeatureが存在した場合にShapeIDsからShapeIDを取得します。

この方法は、いろいろと使いますので、覚えてください。

MapWinGISのmethodやpropertyについては、MapWinGIS Class Documentを参照してください。

StatusStrip1

layerの選択時の名前、AxMap1上でのmouse move eventの機能の追加をします。
blog.godo-tys.jp_wp-content_gallery_mapwingis_ex02_image04.jpg
StatusStrip1

mouse move event

AxMap1上でmouseを移動した時に、緯度経度を表示させます。

    Private Sub AxMap1_MouseMoveEvent(sender As System.Object, e As AxMapWinGIS._DMapEvents_MouseMoveEvent) Handles AxMap1.MouseMoveEvent
        Dim sf As MapWinGIS.Shapefile
        Dim ex As New MapWinGIS.Extents
        Dim xProjected As Double, yProjected As Double
        Dim handle As Integer = 0
 
        If AxMap1.NumLayers > 0 Then
            'get the shapefile object
            sf = AxMap1.get_GetObject(handle)
            'test to see if any shapes for this area lie withing the seleted bounds
            AxMap1.PixelToProj(e.x, e.y, xProjected, yProjected)
            ex.SetBounds(xProjected, yProjected, 0, xProjected, yProjected, 0)
            ToolStripStatusLabelx.Text = Format(xProjected, "###.######")
            ToolStripStatusLabely.Text = Format(yProjected, "###.######")
        End If
    End Sub

mouse down click eventとよく似ていますので、理解はできるはずです。

Programの実行

ex02のprojectを保存後、実行してみましょう。

Add Layerをクリックするとファイル選択ダイアログが表示されます。
拡張子がshpだけを選択でいるようになっています。

blog.godo-tys.jp_wp-content_gallery_mapwingis_ex01_image04.jpg
ファイル選択ダイアログ

サンプルの神奈川県のshape fileを読み込んでみます。

blog.godo-tys.jp_wp-content_gallery_mapwingis_ex02_image06.jpg
神奈川県のshape fileを読み込んだ例

ex01よりもかっこよくなりましたね。
Treeview controlも、ex01より若干変更しています。

個別属性値を表示させます。
blog.godo-tys.jp_wp-content_gallery_mapwingis_ex02_image07.jpg
個別属性値を表示した例

ほかのshape fileを読み込んでも表示されるはずですが、注意点があります

  1. 測地系・座標系はJGD2000世界測地系の緯度経度にのみ対応している。*.prjファイルがないとおかしな表示になると思います。
  2. 先に読み込んだshape fileから順番にlayerを重ねていくので、下のlayerが隠れてしまう。

などの注意点があります。

今回のまとめ

  1. MapWinGISのmouse eventを使う。
  2. ShapeSelectを使ってfeatureを検索する。
  3. その他機能の追加

vb.netd2010だけでなく、C#でも、visual studio2008でも動作することができます。
簡単に自前のソフトウェアにちょっとしたGIS機能を付け加えるには良いと思います。
source code sampleです。活用してください。ダラダラとprogram codeを貼り付けてもよくわからないでので、サンプルコードを見ながら使い方を見る方が勉強になると思います。 ただし、あくまでの自分用のサンプルですので、バグなどがある可能性が高いので、原文のままの使用は避けてください。

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

Exercise

今回のProgramを少し発展させて以下の項目を付け加えてみてください。

  1. 読み込んだshape fileのprojectionを取得して、表示する。
  2. 個別属性値を別フォームに表示させる。

参考となる資料は、MapWinGIS documentationを活用すると良いでしょう。

Comments are closed.

Social Widgets powered by AB-WebLog.com.