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します。
こんな感じ、
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を以下のようにします。
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
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を利用する場合、気をつけなければならない点は、
-
Layer numbersは0から始まる。
-
shape numbersは0から始まる。
-
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
-
AxMap1.PixelToProjでAxMap1上のpixcel座標から測地座標系に変換
-
ex.SetBoundsでfeatureの検索範囲を設定
-
sf.SelectShapes(ex, 0.0, MapWinGIS.SelectMode.INTERSECTION, ShapeIDs)でexの範囲内にfeatureの有無をチェックする。 検索の結果は、ShapeIDSのobjectに入っています。
-
範囲内にfeatureが存在した場合にShapeIDsからShapeIDを取得します。
この方法は、いろいろと使いますので、覚えてください。
MapWinGISのmethodやpropertyについては、MapWinGIS Class Documentを参照してください。
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だけを選択でいるようになっています。
サンプルの神奈川県のshape fileを読み込んでみます。
ex01よりもかっこよくなりましたね。
Treeview controlも、ex01より若干変更しています。
ほかのshape fileを読み込んでも表示されるはずですが、注意点があります
-
測地系・座標系はJGD2000世界測地系の緯度経度にのみ対応している。*.prjファイルがないとおかしな表示になると思います。
-
先に読み込んだshape fileから順番にlayerを重ねていくので、下のlayerが隠れてしまう。
などの注意点があります。
今回のまとめ
-
MapWinGISのmouse eventを使う。
-
ShapeSelectを使ってfeatureを検索する。
-
その他機能の追加
vb.netd2010だけでなく、C#でも、visual studio2008でも動作することができます。
簡単に自前のソフトウェアにちょっとしたGIS機能を付け加えるには良いと思います。
source code sampleです。活用してください。ダラダラとprogram codeを貼り付けてもよくわからないでので、サンプルコードを見ながら使い方を見る方が勉強になると思います。 ただし、あくまでの自分用のサンプルですので、バグなどがある可能性が高いので、原文のままの使用は避けてください。
サンプルコードを使って、お使いのPCの不具合が生じても一切責任は持てませんので、あくまでも自己責任にて使用してください。
Exercise
今回のProgramを少し発展させて以下の項目を付け加えてみてください。
-
読み込んだshape fileのprojectionを取得して、表示する。
-
個別属性値を別フォームに表示させる。
参考となる資料は、MapWinGIS documentationを活用すると良いでしょう。
最近のコメント