日別アーカイブ: 2007年12月27日

地球上の座標

地球の上、どこにいるのか緯度と経度でわかります。
例えば GoogleEarth の座標も緯度、経度。

自分が好きな方向に 1m 進んだ場合の位置はを求めるには
緯度方向はほぼ一定
 1度 = 約111km
 1分 = 約1852m
 1秒 = 約30.9m
 1m = 0.000009度
float では足りないので倍精度が必要。
(double の演算ライブラリを全く用意していなかったことにふと気が付く)

経度の変化量は場所によって異なるのと、直進が経度方向に一致しないので、
簡単ではなさそうです。

慣れているベクトルに変換してみます。
角度は度分秒で時間と同じ。度 + 分/60 + 秒/3600
完全な球とみなして極方向を Y、赤道面を X-Z とすると

const double	dtr= _PI / 180.0;
double	rlat= latitude * dtr;
double	rlon= longitude * dtr;
Position.y= sin( rlat );
double	xlength= cos( rlat );
Position.x= xlength * sin( rlon );
Position.z= xlength * cos( rlon );

これで位置が求まるので、接ベクトルを求めれば移動できそうです。
極で矛盾するけど取りあえず

const static double	vup[3]= { 0.0, 1.0, 0.0, };
Cross( tvx, vup, Position );
Normalize( tvx );
Cross( tvy, Position, tvx );

自分の向きの表現は GoogleEarth では方位角度で、0 が北 180 が南と
なるようです。よって

double razimuth= azimuth * dtr;
double rxa= sin( razimuth ) * speed;
double rya= cos( razimuth ) * speed;
Position+= tvx * rxa + tvy * rya;

Position は正規化されているので、speed は 1/地球の半径 倍する
必要あり。
移動したら緯度経度に戻します。

Normalize( Position );
double	rlon= atan2( Position.x, Position.z );
double	xlength= sqrt( Position.x*Position.x + Position.z*Position.z );
double	rlat= atan2( Position.y, xlength );
latitude= rlat * rtd;
longitude= rlon * rtd;

最初に変換してベクトルのまま保持しておいた方がよさそうです。

参考ページ
Wikipedia 緯度
Google Earth COM API を C++ で使う
Google Earth COM API Documentation