この記事は機械翻訳されたものです。

快適な動作

Windows Phone での球座標を探る (機械翻訳)

Charles Petzold

コード サンプルのダウンロード

Charles Petzoldモーション センサー Windows Phone 7.1 で知り合いになった以来、私はまさに私がそれを行うに望んで知られている:私は約 5 年前に書いたいくつか c# 位置天文学コードを復活させ、それをモーション センサーのロジックと Windows Phone プログラムにワイヤーします。 このようなプログラム私電話夜空に惑星とそこにある星座を表示する場所をポイントすることでしょう。

そのプログラム — ばかげて、名前 AstroPhone — この列の次の分割払いで来ています。 一方、いくつかの概念、数学的でプログラムの基礎が必要です。

以前のコラムでを議論してきたように、モーション センサー コンパス、加速度計、ジャイロスコープと GPS からの入力を統合し、(他のものの間で) 空間における携帯電話の方向を記述する 3D 回転行列を計算します。 携帯電話の座標系を基準として 3D ベクトルをこの行列を適用すると便利です。 このトランス フォームされたベクトルを概念的な天球上の場所を指します。 この球上の場所の高度で構成される水平方向の座標です — 角度の上または下、ビューアーの地平線 — とコンパスの方向は基本的に、方位角。

水平方向の座標は、地球の表面上の位置を識別するおなじみの地理座標に似ています。 上または下のビューアーの地平線高度は緯度の上または下の地球の赤道に似ています。 コンパス方向の地平線の視聴者の周りを示す方位が地球の赤道付近の経度に似ています。 あなたが見るように、球座標のすべてのタイプは基本的に most 重要な下から上の半球を分ける飛行機で異なる同じです。

球の平坦化

先月のコラムで (msdn.microsoft.com/magazine/jj553520)、水平方向の座標を使用して空間における携帯電話の方向を変更することによって大規模な写真やその他の画像をスキャンする方法を示した。 ただし、そのプログラム「ビット単球座標の真の自然を無視して浮気」。 それは、緯度の円は、天球の上下に向かってますます小さくなる、その結果、方位角度はますます圧縮になるという事実を認めることを拒否しました。

夜空の模擬表示を提供するプログラムは、単にこれらのショートカットを取ることができません。 それは、アルゴリズム天球の領域は、携帯電話の薄型にマップする方法を見つける必要があります。 もちろん、偏平球グリーンマップメイカーによって何世紀にも遭遇問題となっています。 歪みなしに、行うことができないが、目的はこれらの歪みを最小限に抑えることです。

図 1 球内装の高度および方位が行毎 15 ° を示しています。 球の内側の中心の視点から、赤いドット表示またはあなたの電話を指しているポイントを表します。 この特定のポイントの標高は、25 ° です。 方位角がカウントを開始し、どのような方向によって異なります。

A Point (in Red) on a Celestial Sphere
図 1 点 (赤) は天球上

携帯電話の画面の中央にマップされますポイントのため、「センター ビュー」このポイントと呼びましょう。 何行の球体で、画面の端に対応ですか?

携帯電話の画面の端が、高度および方位の行に対応すると仮定する魅力的です。 しかしはのみ地平線近くの場所で合理的です。 ビューの中心が地平線から遠いを取得し、全体が崩壊を打破するための概念を開始ストレート アップまたはダウンの棒は、表示しています。

代わりに、直交ビュー センターでの「グレート サークル」に示すように建設しよう図 2

Orthogonal Great Circles Crossing the View Center
図 2 ビューの中心を渡る直交大円

大円球面幾何学で重要な概念です。 グレート サークルは球として同じ中心と半径を共有 3 D 空間における二次元円です。 2 点間の最短距離を表すために、大円の球体では平面上の直線に似ています。 線の方位 (経度) は大円です。 行の高度 (緯度) ではありません。 彼らは代わりに小さな「円」、2 つの球を分割円を除いてです — 地平線 (または赤道)。

グレート赤丸で図 2 を介して 2 つの極を通過し、単に、方位線です。 青のグレート サークル地平線で方位角 90 ° のビューの中心方位から交差しています。

そのセンターの表示の四角形は、携帯電話の画面にマップされます。 概念的には、この四角形は、大円のグリッドを使用できます。 2 つ以上、最初の 1 つと同じポイントで地平線を越える大円ブルーを建設しよう。 2 つ以上赤も 2 つの点が最初のものを共有大円を建設しよう。 このコマンドを実行すると、結果の HTML ファイルは図 3 のようになります。 赤の大円の共有ポイント ビュー センターだ (または方位角プラス 180 °) として同じ方位角が 90 °、高度のオフセットします。

Additional Great Circles to Create a Rectangular Area
図 3 追加大円長方形の領域を作成するには

これら追加の大円、携帯電話の肖像画モード画面約 19 ° のアークとアークの 32 ° の高さの幅に対応する四角形の端を定義します。 携帯電話の画面が約 2 インチ ワイドと 3.33 インチ高いであることを仮定した場合、携帯電話の画面は、あなたの顔から約 6 インチ開催されますこれらの弧度は該当します。 弧度あたり 25 ピクセルもこれらの数字をほのめかすので、携帯電話の画面は、高さ 800 ピクセル、幅 480 ピクセルです。

この投影方式のアルゴリズムで実装する場合、逆方向に動作する必要があります。2 つの点で 3 つの青い大円を軸として共有とによって 3 つの赤い大円を別の軸として共有 2 つの点を考えます。 一緒にベクトル表示の中心にこれらが正規直交座標系を形成します。

ベクトル代数ができます他の座標表示の中心からの角度オフセットを派生 HorizontalCoordinateProjection クラスで示すように図 4。 クラスには、ビューの中心を設定するには、1 つのメソッドとその他のオブジェクトをビューの中心と相対的な水平方向の座標の角度オフセットを取得する別の方法があります。

図 4 HorizontalCoordinateProjection クラス

public class HorizontalCoordinateProjection
{
  Vector3 viewCenterVector, horzAxis, vertAxis;
  public void SetViewCenter(HorizontalCoordinate viewCenterCoord)
  {
    viewCenterVector = viewCenterCoord.ToVector();
    HorizontalCoordinate vertAxisCoord =
      new HorizontalCoordinate(viewCenterCoord.Azimuth + 90, 0);
    vertAxis = vertAxisCoord.ToVector();
    horzAxis = Vector3.Cross(viewCenterVector, vertAxis);
  }
  public void GetAngleOffsets(HorizontalCoordinate objectCoord,
       out double horzAngle, out double vertAngle)
  {
    Vector3 objectVector = objectCoord.ToVector();
    Vector3 horzObjectCross = Vector3.Cross(objectVector, -horzAxis);
    Vector3 vertObjectCross = Vector3.Cross(objectVector, vertAxis);
    horzObjectCross.Normalize();
    vertObjectCross.Normalize();
    double x = Vector3.Dot(horzObjectCross, vertAxis);
    double y = Vector3.Dot(horzObjectCross, viewCenterVector);
    horzAngle = -180 * Math.Atan2(y, x) / Math.PI;
    x = Vector3.Dot(vertObjectCross, horzAxis);
    y = Vector3.Dot(vertObjectCross, viewCenterVector);
    vertAngle = -180 * Math.Atan2(y, x) / Math.PI;
  }
}

携帯電話の画面にそのオブジェクトを配置する場所を決定するには、GetAngleOffsets メソッドから取得角度を弧度あたりのピクセル数を選択定数乗算する必要があります。 以前この定数の携帯電話は、あなたの顔から 6 インチ開催ですより広範なビューを提供するためには低いもので移動する必要があるときに 25 等しい必要があります.

内側から球を表示

ViewHorizontalCoordinates プログラムがその PIXELS_PER_DEGREE の定数を設定します、内側からの水平方向の座標を表示する 15 を示すように探して図 5。 特定のビューは携帯電話を少し東の南、ビットが地平線の上ポイントしたときに発生します。

The ViewHorizontalCoordinates Program
図 5 ViewHorizontalCoordinates プログラム

モーション センサーによって発射される CurrentValueChanged イベントごとに、イベント ハンドラーはどの地球、携帯電話からの相対かを示す、回転行列を取得を開始します。 それは、HorizontalCoordinate の値に変換し、以前に作成した HorizontalCoordinateProjection オブジェクトのビューの中心を設定します。

Microsoft.Xna.Framework.Matrix matrix =
  args.SensorReading.Attitude.RotationMatrix;
HorizontalCoordinate viewCenter =
  HorizontalCoordinate.FromMotionMatrix(matrix);
coordinateProjection.SetViewCenter(viewCenter);
rotate.Angle = -viewCenter.Tilt;

回転オブジェクトは、全体のキャンバスに適用 RotateTransform です。 ハンドラーは、高度および方位値を 15 ° ずつを含むいくつかのループを実装します。 CurrentValueChanged イベントの発生を初めてイベント ハンドラーは必要な行と TextBlock 要素を作成し、それらをキャンバスに追加します。 2 番目の後続の時間を通して、ハンドラーは、単にキャンバスで既に既存の線と TextBlock 要素にアクセスし、新しいポイントを設定します。

HorizontalCoordinate の各値は、画面座標に変換する必要があります。 CalculateScreenPoint のメソッドの仕事は図 6、HorizontalCoordinateProjection で、GetAngleOffsets メソッドを呼び出し、PIXELS_PER_DEGREE 定数によって角度を乗算します。

図 6 水平座標から画面のポイントを計算します。

Point CalculateScreenPoint(HorizontalCoordinate horizontalCoordinate)
{
  double horzAngle, vertAngle;
  coordinateProjection.GetAngleOffsets(horizontalCoordinate,
                                       out horzAngle, out vertAngle);
  // Use NaN to indicate points clearly out of range of the screen
  float x = float.NaN;
  float y = float.NaN;
  if (horzAngle > -90 && horzAngle < 90 && 
     vertAngle > -90 && vertAngle < 90)
  {
    x = (float)(width / 2 + PIXELS_PER_DEGREE * horzAngle);
    y = (float)(height / 2 + PIXELS_PER_DEGREE * vertAngle);
  }
  return new Point(x, y);
}

GetAngleOffsets メソッドは常に 180 °、-180 ° の範囲で角度を返します。 時々 これらの制限の行にまたがるし、このラップアラウンドの問題を作成します。 たとえば、行 (理論で)-175 ° から 175 ° に拡張可能性があります。 その行の長さ、のみ 10 ° はずですが、計算された長さ 380 ℃ になる ! NaN (「非数」) を含む CalculateScreenPoint のロジックは、この問題によって、すべて点の-90 ° 未満の角度オフセットにフラグを設定またはが画面の範囲外です 90 ° より大きいを修正します。

方位に関係なく表示されるように高度の角度を示すテキスト ラベルと思ったし、どのように高または低に関係なく表示されるようにコンパスのポイントを示すものをポイント、携帯電話。 標高ラベル スクリーンのポイントをビューの中心方位からの計算と表示され、ビューのセンター高度なまっすぐ上下に電話をポイントすると彼らはすべてのクラスター一緒にしないように少し調整から計算画面ポイントとコンパスのラベルが表示されます。 この小さなトリックは、おそらく少し中心から回転スクリーン、内部ラベルを保つことができます。

XNA に切り替える

次の月の列と組み合わせてのプログラムと AstroPhone で働いていたように、いくつかのパフォーマンスの問題に気づくだした。 ViewHorizontalCoordinates プログラムは約 10 フレーム/秒、私の開発の電話でのみ管理できます、問題は、私のコードではなく、Silverlight のレイアウト システムよりと思われます。

いくつかの不本意残りのプログラム、Windows Phone の XNA framework ではなく、Silverlight を目標とするということにしました。 これは ViewHorizontalCoordinates に似ていますが、XNA ではなく、Silverlight 向けに書かれたは、ViewThreeCoordinates プロジェクトのためのケースです。

ライブラリのプレビュー

ViewThreeCoordinates プロジェクトはまた、いくつかの本格的な天文学プログラムを使用する戦略を明らかにします。 それはの Petzold.Astronomy と呼ばれる大きいライブラリの一部を使用します。 このライブラリの作成では、私のプライマリ参照の古典的な本「天文アルゴリズム」によってジャン ・ Meeus (1998 Willmann ベル) の第 2 版をされています。

位置天文学では、多数の三角法が必要です。 Petzold.Astronomy ライブラリでは、角度という名前の構造体を実装することによって混乱し、度数とラジアンの間の変換を回避しようと思います。 学位または静的 FromDegree または FromRadian メソッドを使用してラジアンから角度の値を作成して度またはラジアンを取得することができますが、角度はまた必要の三角関数のプロパティとして実装されるため多くの場合は必要ありません。

たとえば、myAngle という名前に角度の値がある場合は、その角度の余弦を取得できるようになります。

double x = myAngle.Cosine;

正弦、余弦、正接の角度の「プロパティ」として考える場合は、これは完璧な意味をが。 しかし、コサイン プロパティの実装方法に注意してください。

public double Cosine
{
  get { return Math.Cos(radians); }
  set { radians = Math.Acos(value); }
}

Set アクセサーは、このようなステートメントを使用して数値の逆余弦を既存の角度の値を設定することができます意味逆余弦関数です。

myAngle.Cosine = x;

このプロセスが非常に動作しなかった唯一の場所は、不可欠の Atan2 メソッドを実装するのだった。 角度の値を作成する静的メソッドをやった:

public static Angle ArcTangent(double y, double x)
{
  return Angle.FromRadians(Math.Atan2(y, x));
}

赤道座標

ViewThreeCoordinates プログラムは緑、プラスの他の 2 つの座標システムの位置天文学に非常に有用な水平座標を表示します。赤道座標に赤青と黄道の座標。 図 7北と 25 ° の高度を指しているとの電話では典型的な表示を示しています。 (はい、私は、画面が乱雑です、しかし、座標の 1 つまたは 2 つのセットを表示する画面をタップすることができます知って。)

The ViewThreeCoordinates Display図 7 ViewThreeCoordinates 表示

地球が自転し、太陽の周りを回転するように、地球の赤道のはかなり同じ平面に滞在します。 地球の赤道の平面は、赤道座標と関連付けられている基礎の平面です。 赤道座標で構成の赤緯 — 赤道上に正と負の下 — そして、赤道の周りを行く右アセンション。 右アセンションは通常各時間 15 ° に相当、度ではなく、時間で指定します。

もちろん、地理座標 (経度と緯度) 赤道座標が宇宙の残りの部分を基準に固定されていますがもが地球の赤道、地理座標と地球回転基づいています、したがって、地球が自転として有効にするように見えます。 星の位置が赤道座標で指定された、彼らは多くの時間の経過を変更しないでください。

ViewThreeCoordinates は水平座標に変換することによって、赤道座標のグリッドを表示します。 この変換は、観察者の地理的位置 (緯度と経度) と現在の時刻に依存し、HorizontalCoordinate 構造で実装されます。

しかし、右アセンションの方位への非常に大まかな変換が可能です。春分の日の深夜のローカル時刻で (3 月 20 日またはその辺)、右アセンションです北 0 時間 (0 ° の方位角)。 明るい星アルクトゥルス右アセンション約 14 時間にその日その時、210 ℃ (または 150 ° 東) それを見るために西をスイングする必要があります。 または、ちょうど 2 時間まで 2 を待つことができます。 アルクトゥルス南支払いいただきます。

その右アセンション ローカル時間の真夜中からの時間数からを減算することによって星のローカル時間角度を計算できます。 度に 15 を乗じて変換、3 月 21 日とその測定の北から東向きへ星の方位からの日数を追加します。

夜空赤道北極までに携帯電話を保持 ViewThreeCoordinates を実行すると (非常に上部の表示図 7) 北斗の非常に約 90 ° の赤緯をおり、それゆえ地球の軸ベクトルが一致している北極星の位置と対応します。 どのようにその極北の方位線を交差する注意してください。

黄道の座標

太陽系のすべての惑星の軌道はほぼ同一の平面上にです。 この飛行機が黄道と呼ばれる、ViewThreeCoordinates によっては赤色の黄道座標 (天体座標とも呼ばれます) の基礎であります。 黄道座標、黄道経度と緯度黄道ので構成されています。

黄道座標は大抵太陽、惑星と月の位置を計算するときに使用されます。 太陽や惑星にほぼ同一の平面上にあるため、これらのオブジェクトの黄道緯度通常ゼロに近いです。 黄道自体は ViewThreeCoordinates で赤い太線で表示されます。 あなたを保持する場合は、携帯電話、日または夜の空、太陽や惑星にその行を一致させてください。

赤道座標と黄道座標相対黄道約 23 ° の傾きを地球の結果のみが異なります。 0 時間右アセンションと 0 ° の赤緯のする赤道の座標は赤道座標 0 ° 経度と緯度 0 ° のと同じです、2 つのシステムが 180 ℃ でも一致します。

春分の日に太陽が黄道経度 0 ° を持っています。 その経度 1 日あたり約 1 ° が、今年のコース上に増加します。 したがって、黄道経度度の太陽の日 3 月 21 日からの日数にほぼ等しいです。

黄道経度は、多くの場合、開始 0 °-30 ° の牡羊座、おうし座 30 ° 60 °、60 °-90 ° などを通じて 330 ° 360 ° のうお座のジェミニ星座に付いています。 私も ViewThreeCoordinates でこれを行っています。 これら、十二支の兆候は、約これら黄道経度黄道緯度 0 の周辺である星座です。 したがって、太陽「牡羊座」です (意味) を超えて太陽は牡羊座 3 月 21 日最初の月の間。

理論は十分です。 この列の次の外観では、グリッド線の球面座標系の太陽、月、惑星、星や星座を置き換えられます。

Charles Petzold 長年の寄稿、MSDN Magazine にあり、Windows 8 の彼の古典的な本"Windows プログラミング"(マイクロソフト プレス、1998年) が現在更新中です。 彼の Web サイト charlespetzold.com

この記事のレビュー、次技術専門家のおかげで:Donn Morse