プログラムな日常>C#>
地図投影法
(Atlas projections : C#)

今回久々の C# になります。 お手元で実行されるには、このページの最後にあるソースコードを VisualStudio(無料)でコンパイルして頂き、得られた *.exe を、同じディレクトリに、画像の 元データ を置いて実行する必要があります。 そういうことをしなくても、結果の概略はこのページでご覧になれます。 なお、手数の少ない javascript 版も試み、そちらもできたのですが、実行速度に難があったので今回は公開しません。C# のパフォーマンスは凄いと改めて思います。 画像の元データについては、前回と引き続き、 地図投影法学習のための地図画像素材集 のものを使わせて頂きました。

ひとつのデータをもとに、色々に変型して提示するというのが今回の趣旨です。 変換は逆にもできるので、元データの形式は何でも良いわけです。 最初は、(円形の)正距方位図法を利用して始めましたが、(長方形の)等距円筒図法にシフトして画質を上げました。 全てはそれを変型してお見せしているわけですが、まずは、正射方位図法です。 視点の高さ(緯度)と経度(東経の角度)とはテキストボックスで自由に指定できます。 これは以下の全てのフォームにつき、同じです。

ランベルト等積方位図法です。

正距方位図法になります。

サンソン図法もこのように高い位置から見れます。しかし、これはさすがにふざけているので、ソフトではデフォで緯度ゼロに戻されます(再設定はできます)。

高い緯度から見たモルワイデ図法です。

メルカトル図法も、高緯度から見ると、とてもダイナミックになります。 緯度(この場合は図の縦方向)の変換方法は、逆変換も含めて、前回 ご説明したところです。

正積円筒図法です。緯度ゼロから見ています。

正距円筒図法であり、元データに近いです。

地図の投影方法ではないのですが、球の中心の光源から平面に写したらどうなるかをやってみました。 これは普通の写真に近いです。 地球の中心にカメラを置いて撮影した感じです。 それだと裏返しになるのでは?というご意見もありそうですね。 むしろ、普通の写真が透明なフィルムを裏から見ているので、この場合は、表から見て正しくなります。 小型フィルムカメラ換算の焦点距離(mm)を指定できます。 メニューにない距離も、テキストボックスに直接書き込む(85mm なら "h85")ことで設定できます。 ここに示したのは 17mm とかなり広角のものになります(Landscape)。

縦長(Portrait)もできます。ここに示したのは、焦点距離 17mm です。

これらの投影においては、「投影」という言葉とは逆に、むしろ、画面の個々の位置に相当する地球上の位置はどこかという考え方で変換します。 光というより、視線を導く感じです。 そういう逆変換は、ここまでのものについてはスラスラとできていたのですが、ここに至って、地球を内側からではなく、宇宙から見てみたいという希望が生じました。 その場合、視野の中心からの変位角を、画面上の半径にどう変換するかという問題が生じます。

地球の中心からの角度を A、視点からの角度を B とします。 フィルム平面への投影だから、tan B が大事なのですが、それはともかく、この変換自体は次のようにできます。 地球からの視点の高さを地球半径で割った値を h とすると、

   tan B = (sin A) / (1 + h - cos A)

このようにして、A → B の変換はできますが、その逆変換をするというときに、困ってしまいました。 何らかの式があるのかも知れませんが、私はそれを知りません。 どっちみちビットマップの問題なので、プログラム的に解決することにしました。 代表点をいくつか置いて一次関数で結べばかなり正確な値は得られるし、その代表点の逆計算には Newton-Raphson 法が効果的なのは、十分承知しているが面倒くさい。 1,000 要素の配列でやってしまいました。 A の側からは、4万分割で計算して、一番近いものを配列に当てはめました。 目的に対して必要十分な手段で済ませるということも、プログラミングでは大事です、と言ったりして。 いずれスマートな式などを見つけたら、その時点でサブルーチン(手続き)を置き換えれば良いことです。 最後に示すプログラムでは 265 行から 298 行までの内容になり、カメラの焦点距離に合わせて、配列を先に作ってしまっています。

使い方ですが、例えばメニューの「O15,2000」(最初の文字は大文字のオー)は、焦点距離 15mm 、フィルムの縦横がどちらも 36mm (小型カメラの長辺と同じ)のカメラで、地球上 2000km の高さから地球にまっすぐに光軸を向けて撮っていることです。 その画像を見るにあたっても、写真を十分拡大し、写真幅の半分位の距離から見るのが正しい見方です。 「O6,400」(焦点距離 6mm)とかだと、もっと近くから見ないといけません。

こうして、宇宙から見た画像が作れましたが、実はこれは制限されたものです。 と言うのは、カメラの方向は地球の中心に向けられているからです。 ですので、たとえこの一部を切り出して拡大したとしても、ユニバーサル映画のイントロにあるような視角の画像にはなりません。 あれをするには、カメラの軸を地平線に近い方に向けなければいけません。 そのためにはもうひと手間が必要です。 平面から平面への、「あおり」の変換であり、これが次回の課題になってくるかと思います。

 C# のソースコードですが、コンパイルしたものは、画像の 元データ と組合せて使ってください。