電子国土V4でプログラミングしてみた
この背景地図等データは、国土地理院の電子国土Webシステムから提供されたものである
7月下旬にテスト公開された電子国土V4システムに関する情報が、国土地理院から少しずつ開示されつつあるが、まだ一般のユーザがOpenLayersを用いて電子国土V4システムのWebアプリケーションを開発するにはあまりにも情報が少なすぎるのが現状だろう.
国土地理院の簡単なサンプルプログラムのソースコードを見れば、地図を単純に表示するだけであればそれ程苦労することはないだろうが、独自のレイヤーを追加したり、KMLなどの重ね合わせデータを表示させようとすると大変厄介なことになる.
国土地理院側では従来の電子国土システムとの互換性をある程度確保したAPIを用意する意向のようだが、現時点では詳細は不明である.『電子国土Webシステムの開発や運用の予定について』を見る限り、
・今年の秋に電子国土WebシステムVer.4が正式公開?される予定(新しいAPIが開示される?)
・来年(H25年)秋までは従来の電子国土Webシステム(V1〜3)はそのまま利用可能である
但し、従来の電子国土Webシステム(V1〜3)の背景地図が新方式の256ピクセルの正方タイルに
切り替わるが、電子国土Webシステム(V1〜3)のAPIを用いているWebアプリはそのまま利用可能
→ 旧方式の背景地図タイルに直接アクセスするGISアプリケーションは利用できなくなる
という事のようだ.
とりあえず現状では、先に公開された 『電子国土WebシステムVer.4(オープンソース版)ソースコード』 の内容を紐解いて自分でプログラミングしてみるしか無さそうだ.
この秋に公開される時点でどの程度電子国土V4のWebAPIが整備されるのか不明だが、恐らく現状から大幅に機能アップすることは無いだろう.電子国土V4を使いこなすには、やはりOpenLayersに習熟しなければならないようだ.
電子国土WebシステムVer.4(オープンソース版)ソースコード
上記国土地理院のWEBサイトから電子国土WebシステムVer.4のJavascriptソースコード “webtis_v4.js” をダウンロードしてざっと中身を覗いてみた.”webtis_v4.js”全体で5,365行もあるので、まだ詳細は把握できていないが、電子国土WebシステムVer.4仕様の背景地図にアクセスするための基本的なクラスライブラリと重ね合わせデータを扱うためのレイヤーのクラスライブラリがメインのようだ.
国土地理院が独自に実装したクラスライブラリはクラス名の先頭に “webtis” という名前が付いているが、基本的にはOpenLayersのクラスライブラリを継承した物なので、OpenLayersの知識があれば問題無いだろう.
まだ開発途上らしく、これまでの電子国土Webシステムが提供していたAPIの機能はまだほんの一部しか実装されていないようだ.とりあえず現時点で実装されている機能を試してみることにした.
・ “webtis.Layer.JSGIXMLLayer” クラス(#2701行目あたり)
従来のAPI “openJSGIXML()” を実装したLayerクラスと思われるが、実際にJSGIXMLデータを指定して表示
させようとしてみたが、背景地図上に重ね合わせる事はできなかった.
JSGIXMLデータを読み込んで、JSON形式のデータに変換されているところまでは確認できたが、
このレイヤー上のオブジェクトが背景地図の上に表示されない原因は不明.
webtis.Layer.JSGIXMLLayerの使い方としては、つぎのような形になるだろう.
#1 name : レイヤー名
#2 url : JSGIXMLデータのURL
#3 options : オプションパラメータ
・ KMLデータの重ね合わせ(OpenLayersの標準機能)
電子国土V4では、重ね合わせデータの形式としてこれまでのJSGIXML形式のみから Google MapsやGoogle Earth等で一般的に使われている KML形式のデータにも対応するようになるという.今後もJSGIXML形式のデータをサポートし続けるのかどうかは不明だが、とりあえずV4のAPIには”webtis.Layer.JSGIXMLLayer” クラスが実装されているようなので、当面はJSGIXML形式のデータを重ね合わせることができそうだ.
KML形式のデータについてはOpenLayersの標準機能でサポートされているので、電子国土V4のAPIでKML形式のレイヤークラスが用意されるかどうかは分からないが、敢えて電子国土V4のAPIを用意しなくても問題無さそうだ.
現在テスト公開中の 『電子国土ポータルV4』では、KML形式のデータを地図上に重ね合わせる事ができる.但しKMLデータの互換製に関しては限定されているようで、今のところ電子国土ポータルV4で作成したKMLデータ以外は上手く表示できないようだ.
試しに電子国土ポータルV4で作成したKMLデータをGoogle Earthで読み込んでみたが、それなりに表示されているようだ.国土地理院でしか使われないような独自のタグが含まれていないと使えないようなKMLでは意味が無いので、変な拡張は止めて欲しい.
国土地理院側としては従来のJSGIXML形式のデータを今後サポートする事を止めてしまうようだ.世間一般ではKMLデータ形式がデファクトスタンダード化しているので、KML形式に移行するのは自然な流れだろう.
『電子国土ポータルV4』サイトではJSGIXML形式のデータが読み込み可能であることを明示してはいないようだが、JSGIXML形式のデータを読み込ませてみたところきちんと表示されていた.KML形式で書き出せば JSGIXML → KML への簡易データコンバータとして使えそうだ.
『電子国土ポータルV4』の作図機能でJSGIXMLデータを読み込んでみた
現時点では電子国土V4側には KMLデータをレイヤーに読み込ませるクラスが無いので、KMLデータを表示するにはOpenLayersのクラスを用いる必要がある.尚、OpenLayersのKMLレイヤークラスでは、Google Earth等で作成した一般的なKMLファイルを問題無く取り扱うことができる.
HTMLサンプル
CJ4 Map Test
// define map projection
var prjSphereMercator = new OpenLayers.Projection("EPSG:900913");
var prjLatLon = new OpenLayers.Projection("EPSG:4326");
function init() {
var map = new OpenLayers.Map( 'map_cj4' );
// map area restriction
var maxExtentArea = new OpenLayers.Bounds();
maxExtentArea.extend(new OpenLayers.LonLat(110.0, 15.0).transform(prjLatLon, prjSphereMercator));
maxExtentArea.extend(new OpenLayers.LonLat(165.0, 55.0).transform(prjLatLon, prjSphereMercator));
var restrictedExtent = maxExtentArea.clone();
var dataSet = {
5:{dataId:"JAIS"},
6:{dataId:"JAIS"},
7:{dataId:"JAIS"},
8:{dataId:"JAIS"},
9:{dataId:"BAFD1000K"},
10:{dataId:"BAFD1000K"},
11:{dataId:"BAFD1000K"},
12:{dataId:"BAFD200K"},
13:{dataId:"BAFD200K"},
14:{dataId:"BAFD200K"},
15:{dataId:"DJBMM"},
16:{dataId:"DJBMM"},
17:{dataId:"DJBMM"},
18:{dataId:"FGD"}
};
// Ortho Maps
var orthoDataSet = {
15:{dataId:"DJBMO"},
16:{dataId:"DJBMO"},
17:{dataId:"DJBMO"},
18:{dataId:"FGD"}
};
var cj4BaseMap = new webtis.Layer.BaseMap( "CJ4 Base Map",
{
dataSet:dataSet,
units: "m",
projection: prjSphereMercator,
displayProjection: prjLatLon,
maxExtent: maxExtentArea,
restrictedExtent: restrictedExtent
} );
var cj4OrthoMap = new webtis.Layer.BaseMap( "CJ4 Ortho Image",
{
dataSet:orthoDataSet,
units: "m",
projection: prjSphereMercator,
displayProjection: prjLatLon,
maxExtent: maxExtentArea,
restrictedExtent: restrictedExtent
} );
// Google Maps
var googlemap = new OpenLayers.Layer.Google(
"Google ROADMAP", // the default
{numZoomLevels: 20}
);
var cj4JSGILayer = new webtis.Layer.JSGIXMLLayer(
"CJ4 JSGIXML Layer",
"https://y2tech.net/maps/xml/JSGITEST.xml",
{});
var kmlLayer = new OpenLayers.Layer.Vector( "KML Layer", {
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP({
url: "https://y2tech.net/CJMapTest/Apr07Markers.kml",
format: new OpenLayers.Format.KML({
extractStyles: true,
extractAttributes: true,
maxDepth: 2
})
})
});
map.addLayers( [ cj4BaseMap, cj4OrthoMap, googlemap ] );
//var mapCenterLatLng = new OpenLayers.LonLat(139.65, 35.44);
var mapCenterLatLng = new OpenLayers.LonLat( 134.344417, 34.050613 );
var mapCenter = mapCenterLatLng.transform( prjLatLon, map.getProjectionObject() );
map.setCenter( mapCenter, 10 );
// Add overlay features (draw a random zigzagged line)
var vectorLayer = new OpenLayers.Layer.Vector("Random Zigzagged Line");
var style_red = {
strokeColor: "#66DD33",
strokeOpacity: 0.5,
strokeWidth: 3,
pointRadius: 6,
pointerEvents: "visiblePainted"
};
var point = new OpenLayers.Geometry.Point( mapCenter.lon, mapCenter.lat );
var pointList = [];
var newPoint = point;
for( var i=0; i<20; ++i) {
var sx = Math.random(1) > 0.5 ? 1 : -1;
var sy = Math.random(1) > 0.5 ? 1 : -1;
newPoint = new OpenLayers.Geometry.Point( newPoint.x + Math.random(1) * 200 * sx,
newPoint.y + Math.random(1) * 200 * sy );
pointList.push( newPoint );
}
var lineFeature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.LineString( pointList ), null, style_red );
vectorLayer.addFeatures([ lineFeature ] );
map.addLayers( [cj4JSGILayer, kmlLayer, vectorLayer ] );
//map.addLayers( [cj4JSGILayer ] );
map.addControl( new OpenLayers.Control.LayerSwitcher() );
// crosshairs cursor
var crosshairsCursorPosition = 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: crosshairsCursorPosition
});
map.addControl( crosshairsCursorCtrl );
// logo
var logoPosition = new OpenLayers.Pixel( map.getCurrentSize().w - 20,
map.getCurrentSize().h - 40 );
var logoIconCtrl = new OpenLayers.Control.Crosshairs({
imgUrl: "./icon01.gif",
size: new OpenLayers.Size(32, 32),
position: logoPosition
});
map.addControl( logoIconCtrl );
// mouse position
map.addControl( new OpenLayers.Control.MousePosition(
{ 'div': OpenLayers.Util.getElement('mouse_position'),
prefix: 'Mouse Position : ',
suffix: ' [Lon, Lat]',
displayProjection: prjLatLon,
emptyString: 'Mouse Position : ',
numDigits: 6
} ));
map.addControl( new OpenLayers.Control.MousePosition(
{ 'div': OpenLayers.Util.getElement('mouse_position_m'),
prefix: ' ( ',
suffix: ' [m] )',
emptyString: '',
numDigits: 0
} ));
// draw a map scale bar
map.addControl( new OpenLayers.Control.ScaleLine(
{
maxWidth:150,
bottomOutUnits: "",
bottomInUnits: "",
geodesic:true
} ));
// show map center location
show_map_center( map );
// event handler
map.events.register( 'moveend', map, function() { show_map_center(map); } );
}
function show_map_center( map ) {
var center = map.getCenter();
var centerLatLon = center.transform(prjSphereMercator, prjLatLon);
var lat = Math.round(centerLatLon.lat * 1000000) / 1000000;
var lon = Math.round(centerLatLon.lon * 1000000) / 1000000;
var zoomLevel = map.getZoom() + 5;
var htmlText= "Map Center: " + lon + ", " + lat + " Zoom Level: "+ zoomLevel;
document.getElementById('map_info').firstChild.nodeValue = htmlText;
}
#map_cj4 {
width: 640px;
height: 480px;
border: solid 1px #999;
}
#map_info_area {
width: 640px;
height: 40px;
font-size: small;
border: solid 1px #999;
}
#map_scale {
float: right;
height: 40px;
}
#mouse_position {
float: left;
height: 20px;
}
#mouse_position_m {
margin-left: 0.5em;
float: left;
height: 20px;
}
#map_zoom {
float: left;
height: 20px;
}
#map_info {
display: block;
height: 18px;
}
div.olControlAttribution {
font-size: x-smaller;
right: 3px;
bottom: 0.2em;
position: absolute;
display: block;
}
Map Center: