電子国土地図にGeoJSONを重ねてみる。[Chapter 1]
OpenLayersではKML,GML,GeoJSONなど様々なファイル形式を読み込んで描画することができます。
当初は、Shape file → kml と考えていたのですが、JSONの方が簡単でわかりやすいと考えて、Shape file → GeoJSONでいくことにしました。
準備
本来ならば、「Shape fileを読み込んで、GeoJSONに変換して」の部分から作成する予定でしたが、今回はGeoJSONを読み込んで描画させるテストとして、GeoJSONファイルは別途作成しました。
FWToolsのインストール
作成方法は、FEToolsからFwToolsをダウンロードしてインストールします。
これは、gdal/ogrのdllとexe群が含まれています。
GeoJSONファイルを作成する
今回は、ディスクトップ上のFWTools Shellを起動して、ogr2ogrコマンドを叩きます。
ogr2ogr -f "GeoJSON" -s_srs "EPSG:4326" -t_srs "EPSG:900913" kanagawk.json kanagawk.shp
たったこれだけでOKです。
gdal/ogrについては、http://www.gdal.org/や月の杜工房- gdal/ogr小技集が非常に参考になります。
vb.netのデザイン
今回も、特に準備するものは、ありません。
Visual Basic 2010を使います。(たぶんvb.net2008でも大丈夫でしょう。)
まずは、vb.netを起動して、適当なプロジェクト名で新規作成します。
使用するコントロールは、Toolstrip,StatusStrip,WebBrowserの3つです。 いつもながらかんたんですな。
デザインイメージ
サンプルコード
GeoJSONファイルを読み込んで電子国土地図にoverlayをするコードはこんな感じです。
''' <summary> ''' GeoJSONを読み込む ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub ToolStripButton3_Click(sender As System.Object, e As System.EventArgs) Handles ToolStripButton3.Click 'StreamReader の新しいインスタンスを生成する 'E:japansample_test.jsonは各人変更すること 'ogr2ogrでGeoJsonに変換してものを使用する。 'ogr2ogr -f "GeoJSON" -s_srs "EPSG:4326" -t_srs "EPSG:900913" kanagawk.json kanagawk.shp Dim openDlg As OpenFileDialog = New OpenFileDialog() 'initialize dialog openDlg.Filter = "GeoJSON Formats|*.json" openDlg.CheckFileExists = True If (openDlg.ShowDialog(Me) = DialogResult.OK) Then stResult = "" Dim cReader As New System.IO.StreamReader(openDlg.FileName, System.Text.Encoding.Default) 'E:W05-08_14_GMLKS-META-W05-08_14-g.xml '読み込みできる文字がなくなるまで繰り返す While (cReader.Peek() >= 0) ' ファイルを 1 行ずつ読み込む Dim stBuffer As String = cReader.ReadLine() ' 読み込んだものを追加で格納する stResult &= stBuffer & System.Environment.NewLine End While 'cReaderを閉じる cReader.Close() '表示する 'MessageBox.Show(stResult) WebBrowser1.ObjectForScripting = New ExtOpenLayersObj 'クラスのインスタンスを渡す '電子国土地図表示 Dim lat As String = ToolStripTextBox1.Text Dim lng As String = ToolStripTextBox2.Text WebBrowser1.DocumentText = OpenLayersGeoJson(Double.Parse(lat), Double.Parse(lng)) End If End Sub ''' <summary> ''' GeoJSONをOverlayする。 ''' </summary> ''' <param name="lat"></param> ''' <param name="lng"></param> ''' <returns></returns> ''' <remarks></remarks> Private Function OpenLayersGeoJson(ByRef lat As Double, ByRef lng As Double) As String Dim txtHtml As String = "" txtHtml = txtHtml & "<html>" & vbCrLf txtHtml = txtHtml & "<head>" & vbCrLf 'txtHtml = txtHtml & "<script type=""text/javascript"" src=""http://openlayers.org/api/OpenLayers.js"" charset=""UTF-8""></script>"& vbCrLf 'txtHtml = txtHtml & "<script type=""text/javascript"" src=""http://portal.cyberjapan.jp/sys/OpenLayers-2.11/OpenLayers.js"" charset=""UTF-8""></script>" & vbCrLf txtHtml = txtHtml & "<script type=""text/javascript"" src=""http://tys-yokohama.com/OpenLayers-2.11/OpenLayers.js"" charset=""UTF-8""></script>" & vbCrLf 'txtHtml = txtHtml & "<script type=""text/javascript"" src=""http://portal.cyberjapan.jp/sys/v4/webtis/webtis_v4.js"" charset=""UTF-8""></script>" & vbCrLf txtHtml = txtHtml & "<script type=""text/javascript"" src=""http://tys-yokohama.com/v4source/webtis_v4.js"" charset=""UTF-8""></script>" & vbCrLf 'txtHtml = txtHtml & "<link rel=""stylesheet"" href=""http://portal.cyberjapan.jp/sys/v4/css/webtis.css"" type=""text/css"">" & vbCrLf txtHtml = txtHtml & "<script type=""text/javascript"">" & vbCrLf txtHtml = txtHtml & "var map = null;" & vbCrLf txtHtml = txtHtml & "var markers = null;" & vbCrLf txtHtml = txtHtml & "var initCX = " & lng.ToString.Trim & ";" & vbCrLf txtHtml = txtHtml & "var initCY = " & lat.ToString.Trim & ";" & vbCrLf txtHtml = txtHtml & "var initZoomLv = 4;" & vbCrLf txtHtml = txtHtml & "var projection900913 = new OpenLayers.Projection(""EPSG:900913"");" & vbCrLf txtHtml = txtHtml & "var projection4326 = new OpenLayers.Projection(""EPSG:4326"");" & vbCrLf 'txtHtml = txtHtml & "var projection4612 = new OpenLayers.Projection(""EPSG:4612"");" & vbCrLf txtHtml = txtHtml & "function init(){" & vbCrLf txtHtml = txtHtml & " var maxExtent = new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508);" & vbCrLf txtHtml = txtHtml & " var restrictedExtent = maxExtent.clone();" & vbCrLf txtHtml = txtHtml & " var maxResolution = 156543.0339;" & vbCrLf txtHtml = txtHtml & " var options = {" & vbCrLf txtHtml = txtHtml & " controls: [" & vbCrLf txtHtml = txtHtml & " new OpenLayers.Control.Navigation({mouseWheelOptions: {interval: 100}})," & vbCrLf txtHtml = txtHtml & " new OpenLayers.Control.PanZoomBar()," & vbCrLf txtHtml = txtHtml & " new OpenLayers.Control.KeyboardDefaults()," & vbCrLf txtHtml = txtHtml & " new OpenLayers.Control.Attribution()," & vbCrLf txtHtml = txtHtml & " new OpenLayers.Control.OverviewMap()," & vbCrLf txtHtml = txtHtml & " new OpenLayers.Control.LayerSwitcher()" & vbCrLf txtHtml = txtHtml & " ]," & vbCrLf txtHtml = txtHtml & " projection: projection900913," & vbCrLf txtHtml = txtHtml & " displayProjection: projection4326," & vbCrLf txtHtml = txtHtml & " units: ""m""," & vbCrLf txtHtml = txtHtml & " maxResolution: maxResolution," & vbCrLf txtHtml = txtHtml & " maxExtent: maxExtent," & vbCrLf txtHtml = txtHtml & " restrictedExtent: restrictedExtent" & vbCrLf txtHtml = txtHtml & " };" & vbCrLf txtHtml = txtHtml & " map = new OpenLayers.Map('map', options);" & vbCrLf txtHtml = txtHtml & " map.addControl(new OpenLayers.Control.ScaleLine({maxWidth:200,bottomOutUnits: """" , bottomInUnits: """" ,geodesic:true}));" & vbCrLf txtHtml = txtHtml & " webtisMap = new webtis.Layer.BaseMap(""webtismap"");" & vbCrLf txtHtml = txtHtml & " map.addLayer(webtisMap);" & vbCrLf txtHtml = txtHtml & " map.setCenter(new OpenLayers.LonLat(initCX,initCY).transform(projection4326,projection900913), initZoomLv);" & vbCrLf txtHtml = txtHtml & " // Mapにクリックイベントを登録" & vbCrLf txtHtml = txtHtml & " map.events.register('click', map, onMouseClick);" & vbCrLf txtHtml = txtHtml & " map.events.register('mousemove', map, onMouseMove);" & vbCrLf txtHtml = txtHtml & " markers = new OpenLayers.Layer.Markers( ""Markers"" );" & vbCrLf txtHtml = txtHtml & " map.addLayer(markers);" & vbCrLf txtHtml = txtHtml & " // Styleの設定" & vbCrLf txtHtml = txtHtml & " var styleMap = new OpenLayers.StyleMap(OpenLayers.Util.applyDefaults(" & vbCrLf txtHtml = txtHtml & " {fillColor: ""green"", fillOpacity: 1, strokeColor: ""black""}," & vbCrLf txtHtml = txtHtml & " OpenLayers.Feature.Vector.style[""default""]" & vbCrLf txtHtml = txtHtml & " ));" & vbCrLf '=========================================== 'Geojson txtHtml = txtHtml & " var featurecollection = " & stResult & ";" & vbCrLf txtHtml = txtHtml & " var geojson_format = new OpenLayers.Format.GeoJSON();" & vbCrLf txtHtml = txtHtml & " var vector_layer = new OpenLayers.Layer.Vector(""神奈川県"",{styleMap: styleMap});" & vbCrLf txtHtml = txtHtml & " vector_layer.setOpacity(0.5);" & vbCrLf txtHtml = txtHtml & " map.addLayer(vector_layer);" & vbCrLf txtHtml = txtHtml & " vector_layer.addFeatures(geojson_format.read(featurecollection));" & vbCrLf '=========================================== txtHtml = txtHtml & "}" & vbCrLf txtHtml = txtHtml & "// mouseclickイベント" & vbCrLf txtHtml = txtHtml & "function onMouseClick(evt) {" & vbCrLf txtHtml = txtHtml & " // クリック地点の座標を取得" & vbCrLf txtHtml = txtHtml & " var lonlat = map.getLonLatFromViewPortPx(evt.xy);" & vbCrLf txtHtml = txtHtml & " // 地図座標に変換" & vbCrLf txtHtml = txtHtml & " lonlat.transform(projection900913, projection4326);" & vbCrLf 'txtHtml = txtHtml & " document.sample.boxLon.value = lonlat.lon;" & vbCrLf 'txtHtml = txtHtml & " document.sample.boxLat.value = lonlat.lat;" & vbCrLf '.NETのSubroutineを呼び出す。 txtHtml = txtHtml & " window.external.MouseClick(lonlat.lat, lonlat.lon);" & vbCrLf txtHtml = txtHtml & "}" & vbCrLf txtHtml = txtHtml & "// mousemoveイベント" & vbCrLf txtHtml = txtHtml & "function onMouseMove(evt) {" & vbCrLf txtHtml = txtHtml & " var lonlat = map.getLonLatFromViewPortPx(evt.xy);" & vbCrLf txtHtml = txtHtml & " // 地図座標に変換" & vbCrLf txtHtml = txtHtml & " lonlat.transform(projection900913, projection4326);" & vbCrLf '.NETのSubroutineを呼び出す。 txtHtml = txtHtml & " window.external.MouseMove(lonlat.lat, lonlat.lon);" & vbCrLf txtHtml = txtHtml & "}" & vbCrLf 'Markerの描画 txtHtml = txtHtml & "// mousemoveイベント" & vbCrLf txtHtml = txtHtml & "function moveToPoint(Lat, Lng, strTitle) {" & vbCrLf txtHtml = txtHtml & " var lonlat = new OpenLayers.LonLat(Lng,Lat).transform(projection4326,projection900913);" & vbCrLf txtHtml = txtHtml & " map.setCenter(lonlat);" & vbCrLf txtHtml = txtHtml & " // markerの描画" & vbCrLf txtHtml = txtHtml & " var marker = new OpenLayers.Marker(lonlat);" & vbCrLf txtHtml = txtHtml & " markers.addMarker(marker);" & vbCrLf txtHtml = txtHtml & "}" & vbCrLf txtHtml = txtHtml & "</script>" & vbCrLf txtHtml = txtHtml & "</head>" & vbCrLf txtHtml = txtHtml & "<body onload=""init();"">" & vbCrLf txtHtml = txtHtml & "<div id=""map"" name=""map"" style=""width: 100%; height:100%;""></div>" & vbCrLf 'txtHtml = txtHtml & "<form name=""sample"">" & vbCrLf 'txtHtml = txtHtml & "<div>チェックのためのhtml出力</div>" & vbCrLf 'txtHtml = txtHtml & "<div>" & vbCrLf 'txtHtml = txtHtml & "緯度:<input type=""text"" name=""boxLat"" />" & vbCrLf 'txtHtml = txtHtml & "経度:<input type=""text"" name=""boxLon"" />" & vbCrLf 'txtHtml = txtHtml & "</div>" & vbCrLf 'txtHtml = txtHtml & "</form>" & vbCrLf txtHtml = txtHtml & "</body>" & vbCrLf txtHtml = txtHtml & "</html>" & vbCrLf OpenLayersGeoJson = txtHtml End Function
プログラムの説明
注意点jacascriptを弊社のURLに設置して呼び出しています。 この部分は、本家を参照してください。 弊社Serverのdirectory構成で変更になる可能性があります。
プログラムとしては、簡単ですが、
-
GeoJSONファイルを読み込んで、stringに放り込みます。
-
Function OpenLayersGeoJsonでGeoJSONファイルを結合します。
簡単にGeoJSONのVector Layer作成部分は数行で書くことができます。
プログラムの実行
WebBrowserコントロールはvisual studio標準のものを使っています。GeoJSONデータ数が多くなると描画に非常に時間がかかります。
これは、WEBレンダリングエンジンの影響と思われます。
今後はGoogle ChromeとかSafariとかAndroidとかで使われているレンダリングエンジンでのWebkitや、Firefoxとかで使われているレンダリングエンジンのGeckoを使うことで処理速度は速める必要があります。
それでは、実行してみましょう。
プログラムを起動すると地図が表示されます。
「ポイント移動」ボタンをクリックした場合、toolstrip内のtextboxの緯度経度に移動して、マーカーが描画されます。 Googlemapのサンプルと同じようにタイトルを入力しても、tooltipsでマーカーにmouseoverすると表示されません。ここのところは、作成中です。
GeoJSON読み込みボタンをクリックしてGeoJSONファイルを選択した例
LayerSwticherでoverlayerを表示/非表示に変更した例
基本的は機能だけをチェックしてみましたが、いろいろと応用すれば、非常におもしろいソフトウェアができあがりますね。
次回は、Shape file → GeoJSONの実装を作成してみます。FwTools内にgdal_csharp.dllとogr_csharp.dllがあるので、これでできるのでは?と安易に考えていますが。。。
サンプルコードとGeoJSONサンプルをこちらにアップしておきます。使用する際は自己責任にて使って下さい。
参照したHP(先人に感謝します。
おまけ
GIS Data ConverterなんていうWEBサービスがありました。
最近のコメント