Sunset Tokyo


Date/Time: 2014:08:23 05:08:11
Camera: Panasonic
Model: DMC-LX2
Exporsure Time: 1/200
FNumber: 4.9
Aperture Value: 4.6
Focal Length: 25.2

Close

y2blog » OpenLayersで電子国土マップを表示してみる

1

15

2012

OpenLayersで電子国土マップを表示してみる

OpenLayersを用いて電子国土基本図を表示してみる


電子国土システムV3の地図表示部分の基本フレームワークとして、OpenLayers 2.10 が使用されていますが、電子国土基本図の背景地図の形式が『地球を真球とみなした擬似円筒図法』という緯度により縦方向の解像度が異なるという特殊な方式のため、標準的な正方メルカトルタイリングを用いたGISシステムとはとても相性が悪いと言わざる負えないでしょう.


OpenLayersのソースコードを紐解きながら、電子国土基本図の背景地図をOpenLayers上に取り込むプログラムを一から作ってみましたが、あまりの面倒くささに途中で放り投げたくなってしまいました.背景地図の緯度(縦)方向の解像度が緯度によって変化するため、固定サイズ(ピクセル数)の地図フレームに表示できる緯度・経度の範囲が一定にならないという困った問題がつきまといます.


例えば日本列島の北端の宗谷岬付近の緯度は約45度で、背景地図の縦方向のピクセル数は約428ピクセルとなっている.一方、南端の波照間島付近の緯度は約24度で、縦方向のピクセル数は328ピクセルである.640 x 480 ピクセルの地図フレームに、60秒(1分)サイズの背景地図を配置する場合、経度(横)方向の表示可能範囲(度数)は、640 / 300 * 60/3600 = 0.035555 と一定ですが、緯度(縦)方向は、

宗谷岬付近:  480 / 428 * 60/3600 = 0.0186915 [度]  解像度 0.00004367 [度/ピクセル] 

波照間島付近: 480 / 328 * 60/3600 = 0.0243902 [度]  解像度 0.00007436 [度/ピクセル]


となってしまいます.同じ種類の地図でありながら、北と南では緯度方向の解像度[度/ピクセル]が大きく異なってしまいます.
ピクセルベース(ラスターイメージ)の地図では、画素数と座標系の関係がリニアー(線形)でなければとても面倒な事になります.OpenLayersも基本的に画素数と座標系の関係がリニアーであることを前提にフレームワークが作成されていますので、ノンリニアーな処理を行おうとするととても煩雑な処理を自分で組み込まなければならなくなります.


OpenLayersには Layer という基本的なクラスがあり、そのサブクラスとしてGridというクラスが用意されています.このクラスはタイリングされた地図を扱う際の基本となるクラスで、WMSサーバで配信されている地図データを扱うサブクラス WMSクラスもこのGridクラスをベースにしています.


OpenLayers での Layer クラスの継承関係は次の様になっています.


Layer → HTTPRequest → Grid → WMS
当初はこれらのサブクラスの内、Gridクラスだけを自前のメソッドでオーバライドする程度で、電子国土基本図の背景地図を取り込めるだろうと思っていましたが、緯度(縦)方向の解像度が可変の場合に対応できるようにするのは思った以上に困難でした.既存のクラスのオーバライドよりも一からクラスの設計をやり直した方がすんなり実装できるかもしれません.


電子国土V3のOpenLayers廻りのコードを見ていても相当面倒で複雑な処理を行っています.とりあえず今回は自前で一からコードを書いている暇がなかったので、電子国土V3システムのOpenLayers廻りのコードをベースに、電子国土のAPIを使わずにOpenLayersレベルで電子国土基本図の背景地図を表示してみました.


電子国土基本図 をOpenLayersの背景地図として取り込んだ例


国土地理院への承認申請が必要なため実物をここで表示することができません.
Mt. Fuji Kengamine
「この背景地図等データは、国土地理院の電子国土Webシステムから提供されたものです」

[sourcecode language=”Javascript”] <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Cyber Japan Map Test [ OpenLayers: Layer.Grid ]</title> <script src="./OpenLayers-2.10/OpenLayers.js"></script> <script src="./CJMap.js"></script> <script src="./CJGrid.js"></script> <script src="./CJCrosshairs.js"></script> <script type="text/javascript"> window.onload = init; var layer; var name = ‘CJ 25K Map Base Layer’; function init() { var map = new CJMap(‘cjmap’); // Kengamine, Mt Fuji var mapCenterLonLat = new OpenLayers.LonLat( 138.7273611, 35.36064 ); baseMapLayer = new CJGrid( name ); map.addLayer( baseMapLayer ); map.setCenter( mapCenterLonLat, 10 ); var mapCenterPosition = new OpenLayers.Pixel( map.getCurrentSize().w / 2, map.getCurrentSize().h / 2 ); var crosshairsCursorCtrl = new OpenLayers.Control.Crosshairs({ imgUrl: "./crosshairs.png", size: new OpenLayers.Size(32, 32), position: mapCenterPosition }); map.addControl( crosshairsCursorCtrl ); //var scaleCtrl = new OpenLayers.Control.Scale; //map.addControl( scaleCtrl ); }; </script> <style> #cjmap { width: 800px; height:600px; border: 1px solid #888; } </style> </head> <body style="margin: 0;"> <div id="cjmap"></div> </body> </html> [/sourcecode]
CJMapクラスは OpenLayersの基本クラス “Map” の派生クラスで、ベースとなるコードは “sys/v3/webtis/Map.js” です.


CJGridクラスはOpenLayersの基本クラス “Grid” の派生クラスで、ベースとなるコードは “sys/v3/webtis/Layer/BaseMap.js” です.
CrossHairsCursor のソースコードは “sys/v3/webtis/Control/Crosshairs.js” です.

上記のサンプルではこの3つのソースコードをに少し手を加えたものを使って表示しています.単純に背景地図だけをベースレイヤーに表示するのであれば、上記のサンプルのように少ないコードで表示可能です.


後は、重ね合わせのレイヤーや各種コントロールを付け加えることでカスタマイズしていけば良いでしょう.

【修正内容】
・ ”sys/v3/webtis/Map.js” のクラス名を適当な名前に変更する.


Line #1: webtis.Map = OpenLayers.Class(OpenLayers.Map, {

                 ↓

       CJMap = OpenLayers.Class(OpenLayers.Map, {

 Line #105: CLASS_NAME: “webtis.Map”

                 ↓

       CLASS_NAME: “CJMap”


・ ”sys/v3/webtis/Layer/BaseMap.js” のクラス名および 関数”webtis.Layer.DynamicResolution” の名前を変更する.

 Line #1: webtis.Layer.DynamicResolution = function (dirx, diry, map, baseLayer) {

                 ↓

        dynamicResolution = function (dirx, diry, map, baseLayer) {    

Line #693, #701: resolution = new webtis.Layer.DynamicResolution(

                 ↓

            resolution = new dynamicResolution(      

 Line #29: webtis.Layer.BaseMap = OpenLayers.Class(OpenLayers.Layer.Grid, {

                 ↓

  CJLayerGrid = OpenLayers.Class(OpenLayers.Layer.Grid, {

 Line #1129 CLASS_NAME: “webtis.Layer.BaseMap”

                 ↓

  CLASS_NAME: “CJLayerGrid”


おまけ:iPhoneのUIWebView上でOpenLayersを使ってみた


電子国土の背景地図にOpenLayersのフレームワークを通じてアクセスできたところで、iPhoneのUIWebView上で上記のWebアプリケーションを動かしてみました.詳しい手順やソースコードについては『iPhoneでGPSナビ』の記事の中で説明する予定ですが、とりあえずiPhone上で動かすとこんな感じになりますということで... OpenLayersをUIWebView上で使用すると何故か地図のスクロールができません.OpenLayersのコントロールはマウスクリックに反応するので、UIWebView側からマウスクリックイベントはOpenLayers側には渡っているようです.OpenLayers側で何か特別な設定が必要なのか、あるいはUIWebViw側で特別な処理が必要なのか今のところ解決方法は不明です.

XCode Settings
HTMLファイルとJavascript関係のリソースをXcodeのプロジェクトに組み込む
Initial Startup Screen
アプリを起動すると初期位置が表示される
Move to Current Location
GPSから取得した現在位置にマップが移動する