空間参照は、位置情報を扱う上でもっとも基本的で重要な要素のひとつですが、GIS をはじめるときに、最初にぶつかる大きな壁のひとつでもあるのではないでしょうか。
今回は、そんな空間参照について、アプリ開発の視点から解説します。
この記事では ArcGIS API for JavaScript を使用しますが、ほかの SDK でも空間参照に関する基本的な理解は同じです。
空間参照とは?
位置情報を表す際に使用される緯度経度や XY 座標は、座標の原点となる地点や距離などを定めた基準をもとに求められます。この基準を座標系と呼びます。
空間参照は、座標がどの座標系を使用するのかを定義します。
座標系には、さまざまな種類があり、同じ座標でも、参照する座標系が違えば、まったく異なる地点を示すことがあります。座標が示す正しい地点を得るためには、空間参照を定義し、座標と座標系を紐づけることが必要です。
ArcGIS では、WKID と呼ばれる一意の ID で空間参照を定義します。例えば、日本でよく使用される平面直角座標系(JGD 2011)のうち、関東周辺で用いられる第9系の WKID は「6677」です。
また、空間参照においてよく耳にする EPSG は、European Petroleum Survey Group (EPSG) という団体によって定義された空間参照のコード体系で、さまざまな GIS に導入されています。WKID も EPSG をもとに作成されています。
GIS アプリの空間参照
では、アプリでは空間参照はどのように扱われるのでしょうか?
データの空間参照
位置情報には、通常、位置を表す座標とともに、その座標がどの空間参照を使用して表されているのかも定義されています。
API/SDK で使用する各サービスにも、サービスに含まれる位置情報が使用する空間参照が定義されています。
サービスの空間参照は、サービス ディレクトリで確認することができます。
以下のリンクは、Esri が提供する道路地図ベースマップのサービス ディレクトリです。
SpatialReference パラメーターに、サービスに定義されている空間参照の WKID が表示されているのがわかります。
このサービスに定義されている WKID:102100 は WGS 1984 Web メルカトル(球体補正)というタイル サービスの配信に適した座標系を参照します。
サービスから作成したレイヤーの空間参照プロパティには、サービスが持つ空間参照が適用されます。
マップの空間参照
レイヤーに含まれる位置情報を投影するため、マップにも空間参照が定義されます。
マップの空間参照には、最初に読み込まれたレイヤーに定義されている空間参照が適用されます。
例えば、Esri が提供するベースマップを使用する場合、マップにはベースマップが使用する空間参照、WKID:102100が定義されます。
もし、ベースマップを使用せずに、サービスを読み込み、レイヤーとしてマップに追加するような場合は、マップの空間参照は読み込んだサービスに定義された空間参照になります。
さて、マップに空間参照が定義されるということは、マップと異なる空間参照を持つレイヤーはどうなるのでしょうか?
API/SDK は、マップに定義された空間参照と異なる空間参照を持つレイヤーを、動的に再投影します。
サンプル コードを見てみましょう。
マップは、Esri の提供する道路地図をベースマップとして使用しています。したがって、マップの空間参照にはベースマップの空間参照、すなわち WKID:102100 が適用されます。
続いて、マップ イメージ レイヤーを使用し、マップにアメリカのセンサス データを追加します。
このレイヤーの空間参照は、WKID:4269 で、NAD83 というアメリカで使用される座標系を参照しています。マップとは異なる空間参照を使用していますが、データは正しい位置に表示されます。
<SPAN class="keyword token">var</SPAN> map <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">Map</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">{</SPAN>
basemap<SPAN class="punctuation token">:</SPAN> <SPAN class="string token">"streets"</SPAN>
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">var</SPAN> view <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">MapView</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">{</SPAN>
container<SPAN class="punctuation token">:</SPAN> <SPAN class="string token">"viewDiv"</SPAN><SPAN class="punctuation token">,</SPAN>
map<SPAN class="punctuation token">:</SPAN> map
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">var</SPAN> layer <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">MapImageLayer</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">{</SPAN>
url<SPAN class="punctuation token">:</SPAN> <SPAN class="string token"><SPAN>"</SPAN><A class="jive-link-external-small" href="https://community.esri.com/external-link.jspa?url=https%3A%2F%2Fsampleserver6.arcgisonline.com%2Farcgis%2Frest%2Fservices%2FCensus%2FMapServer" target="_blank">https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer</A><SPAN>"</SPAN></SPAN>
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
map<SPAN class="punctuation token">.</SPAN><SPAN class="token function">add</SPAN><SPAN class="punctuation token">(</SPAN>layer<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>このように、API/SDK は、レイヤーを動的に再投影することで、マップとは異なる空間参照を持つレイヤーの表示を実現します。
ただし、動的な再投影は、アプリのパフォーマンスに影響します。可能ならば、アプリで使用するデータの座標系をあらかじめ統一し、使用する空間参照を一種類にすることが望まれます。
ジオメトリの空間参照
これまで紹介した通り、マップと、サービスから作成されたレイヤーには、それぞれの空間参照が定義されます。
では、クライアント側で作成したジオメトリをマップに描画する場合、空間参照はどのように使用されるのでしょうか?
平面直角座標系 第9系を使用して、x: -5995.3221、y: -35382.5003 という値で表される地点があります。この地点を先ほど作成したマップに描画してみましょう。
まず、上記の情報をもとに ポイントを作成します。
リファレンスを見ると、x プロパティに X 座標の値、y プロパティにY 座標の値が設定されているのがわかります。そして、spatialReference プロパティに空間参照が定義されています。
[空間参照とは?] でも触れましたが、平面直角座標系 第9系の WKID は「6677」です。spatialReference プロパティの wkid パラメーターに、座標が参照する空間参照を指定します。
各座標系の WKID は以下のリンクから確認できます。
Tips:座標系には、地点を、平面に投影して XY座標で表す投影座標系と、三次元の緯度経度で表す地理座標系があります。平面直角座標系は投影座標系に分類されます。詳しくは、座標系(GIS 基礎解説)をご参照ください。
<SPAN class="keyword token">var</SPAN> point <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">Point</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">{</SPAN>
x<SPAN class="punctuation token">:</SPAN> <SPAN class="operator token">-</SPAN><SPAN class="number token">5995.3221</SPAN><SPAN class="punctuation token">,</SPAN>
y<SPAN class="punctuation token">:</SPAN> <SPAN class="operator token">-</SPAN><SPAN class="number token">35382.5003</SPAN><SPAN class="punctuation token">,</SPAN>
spatialReference<SPAN class="punctuation token">:</SPAN> <SPAN class="punctuation token">{</SPAN>
wkid<SPAN class="punctuation token">:</SPAN> <SPAN class="number token">6677</SPAN>
<SPAN class="punctuation token">}</SPAN>
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>さて、作成したポイントからグラフィックを作りマップに表示してみましょう。
<SPAN class="keyword token">var</SPAN> graphic <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">Graphic</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">{</SPAN>
geometry<SPAN class="punctuation token">:</SPAN> point<SPAN class="punctuation token">,</SPAN>
symbol<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">SimpleMarkerSymbol</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">{</SPAN>
color<SPAN class="punctuation token">:</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="number token">226</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">119</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">40</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN>
outline<SPAN class="punctuation token">:</SPAN> <SPAN class="punctuation token">{</SPAN>
color<SPAN class="punctuation token">:</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="number token">255</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">255</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">255</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN>
width<SPAN class="punctuation token">:</SPAN> <SPAN class="number token">2</SPAN>
<SPAN class="punctuation token">}</SPAN>
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
view<SPAN class="punctuation token">.</SPAN>graphics<SPAN class="punctuation token">.</SPAN><SPAN class="token function">add</SPAN><SPAN class="punctuation token">(</SPAN>graphic<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>あれ?おかしいですね。グラフィックが表示されません。
ジオメトリの空間参照 – 空間参照の変換
実は、マップに追加されたグラフィックやグラフィックス レイヤーには、レイヤーのような動的な再投影は行われません。
そのため、マップの空間参照と異なる空間参照を持つグラフィックはマップに表示されません。
作成したポイントをマップに表示するために、ポイントの空間参照を変換してみましょう。
さまざまなジオメトリ処理を行う GeometryService は、ジオメトリを新しい空間参照へ変換して投影するメソッドを提供しています。
パラメーターに、変換するジオメトリと、空間参照を設定します。今回は、マップの空間参照を使用するので、view.spatialReference の値を使用しています。
そして、メソッドを実行し、出力結果からグラフィックを作成します。
出力されたジオメトリの空間参照は、マップに定義されている空間参照と同じなので、マップ上にグラフィックが表示されます。
<SPAN class="keyword token">var</SPAN> geometryService <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">GeometryService</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="string token">"GeometryService の URL"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">var</SPAN> params <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">ProjectParameters</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
params<SPAN class="punctuation token">.</SPAN>geometries <SPAN class="operator token">=</SPAN> <SPAN class="punctuation token">[</SPAN>point<SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
params<SPAN class="punctuation token">.</SPAN>outSpatialReference <SPAN class="operator token">=</SPAN> view<SPAN class="punctuation token">.</SPAN>spatialReference<SPAN class="punctuation token">;</SPAN>
geometryService<SPAN class="punctuation token">.</SPAN><SPAN class="token function">project</SPAN><SPAN class="punctuation token">(</SPAN>params<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="token function">then</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="keyword token">function</SPAN><SPAN class="punctuation token">(</SPAN>results<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">{</SPAN>
<SPAN class="keyword token">var</SPAN> point <SPAN class="operator token">=</SPAN> results<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">var</SPAN> graphic <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">Graphic</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">{</SPAN>
geometry<SPAN class="punctuation token">:</SPAN> point<SPAN class="punctuation token">,</SPAN>
symbol<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">SimpleMarkerSymbol</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">{</SPAN>
color<SPAN class="punctuation token">:</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="number token">226</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">119</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">40</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN>
outline<SPAN class="punctuation token">:</SPAN> <SPAN class="punctuation token">{</SPAN>
color<SPAN class="punctuation token">:</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="number token">255</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">255</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">255</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN>
width<SPAN class="punctuation token">:</SPAN> <SPAN class="number token">2</SPAN>
<SPAN class="punctuation token">}</SPAN>
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
view<SPAN class="punctuation token">.</SPAN>graphics<SPAN class="punctuation token">.</SPAN><SPAN class="token function">add</SPAN><SPAN class="punctuation token">(</SPAN>graphic<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>平面直角座標系 第9系を使用して、x: -5995.3221、y: -35382.5003 で表される地点がどこか、わかりましたか?
東京駅付近にポイントが表示されれば、成功です。
アプリ開発における空間参照の基本的なことを紹介しましたが、GIS の基礎となる座標や座標系、空間参照は、学習範囲も広く、ここで説明しきれないこともあります。ぜひ、関連リンクもご活用ください。
関連リンク