ここのことはなかったことにするかもしれない

仕事がらみの記事を主として扱いますが、あくまで個人ブログです。2013年以前の記事は https://yellow-73.hatenablog.com/ にあります。

KMLのLookAtでタイル有効範囲全体を見せるためのカメラ位置標高計算方法

はじめに

Google Earthでタイル画像を表示するためにはKMLを作りますが、ズームレベル0 からKMLを作ると、赤道上アフリカ沖にカメラが行ってしまいました。

こまったので、LookAt要素を活用して、タイル有効範囲の中心にカメラを持っていきますが、緯度、経度、標高の3つを指定する必要があり、標高の計算が難しかったので、メモしておきます。

方針

焦点距離 a[mm] で4隅が収まる標高hを求めます。
ちょっと変えると、「4隅について、焦点距離a[mm]で収まる標高hを求め、最大値を取る」となります。

なお、焦点距離は50mmにしました。どうもGoogle Earthは視野角(焦点距離とは違う)は30度(焦点距離では30mm近辺)のようで、ぎりぎりまでカメラ標高を落とすようにはなってないのですが、逆にその方が良いかんじになったので、やはり50mmとします。

以下は、各隅について計算します。

カメラの緯度経度位置を得る

画像範囲の中心点をカメラの緯度経度位置とします。

以降は、緯度経度を(φc,λc)とします。


緯度経度からxyzを得る

半径Rの球面上の 緯度lat, 経度 lng の点を、x,y,z であらわすと、次の通りとなります。

xn = R*cos(φn)*cos(λn)
yn = R*cos(φn)*sin(λn)
zn = R*sin(φn) 

回転行列と逆行列

まず、こちらは使いませんが、X=(R,0,0)から 緯度φc, 経度λc 上の点に回転させる行列を考えます。

φcの行列 Ap は次の通りです。

cp 0 -sp
0 1 0
sp 0 cp
Y軸について逆回転させています。 λcの行列 Al は次の通りです。
cl -sl 0
sl cl 0
0 0 1
Z軸について回転させています。 この2つの行列は次の通り合成します。
X' = Al * Ap * X
この逆行列を使えば、緯度φc, 経度λc 上の点が(R,0,0)に回転します。 まず、Alの逆行列 invAl は次の通り。
cl sl 0
-sl cl 0
0 0 1
invAp は次の通り。
cp 0 sp
0 1 0
-sp 0 cp
よって、逆行列は次の通りとなります。
invAp * invAl
   |  cp   0  sp |   |  cl  sl   0 |
 = |   0   1   0 | * | -sl  cl   0 |
   | -sp   0  cp |   |   0   0   1 |
(x,y,z)を逆行列で回転させた後の座標(xr,yr,zr)は次の通りです。
xr = x*cp*cl + y*cp*sl + z*sp
yr = -x*sl + y*cl
zr = -x*sp*cl - y*sp*sl * z*cp
f:id:boiledorange73:20180719192719j:plain f:id:boiledorange73:20180719192830j:plain

指定画角となる標高を求める

逆行列回転後のカメラ位置は、球面半径 R として、標高 h とすると
(R+h, 0, 0)
となります。これから原点方向に向いています。 焦点距離 a[mm] から 画角α[rad]のタンジェント ta を求めるのは次の通りです。 35はフィルムサイズが35mmであるから、です。
ta = (35/2)/a = 17.5/a
yrについて画角 a で端っこに写るようになる標高 h1 は次の方程式となります。
yr/(R+h1-xr) = ta
h1 = yr/ta - R + xr
f:id:boiledorange73:20180719192855j:plain zrについても見てみます。
h2 = zr/ta - R + xr
最大値を採用します。
h = max(h1, h2)