2016-04-01 14 views
1

この問題の背景を説明するために、オブジェクトの 'Orbit'が許容範囲内にあるかどうかを知る必要があるゲームを作成します。別の軌道。これを表示するために、私は目標軌道を使って与えられた半径(公差)でトーラス形状をプロットします。そして今、私はその楕円がそのトーラス内にあるかどうかを確認する必要があります。3D空間内での3D点とOrientated Ellipse間の距離の計算(C++)

私は数学/スタック交換の方程式に迷っているので、より具体的な解決策を求めています。明確にするため、TorusとOrbit(赤い線)を使ったゲームのイメージを示します。確かに、その赤い軌道がそのトーラスの形の中にあるかどうかを確認したいと思います。私は私が行う必要があると信じて何

enter image description here

は、プロット(行うのは簡単に十分な)それらの軌道の1の世界空間の4つのポイントです。私はその点と他の軌道の楕円との間の最短距離を計算する必要があります。これは難しい部分です。ある点から楕円までの最短距離を求めるいくつかの例がありますが、すべてが2Dであり、追跡が非常に困難です。

この距離が4点すべての許容誤差より小さい場合、目標トーラスの内側にある軌道に等しいと考えます。

簡素化のために、これらの軌道のすべての原点は、常にワールド原点(0、0、0)にあり、私の座標系はZ-Upです。各軌道には、それを定義する一連のパラメータ(軌道要素)があります。ここ

+3

2次元の点から楕円までの距離を見つける方法を知っていれば、3Dで簡単です。楕円の平面に点を投影し、その平面内の投影された点からの距離を求めます。楕円のターゲットポイントから、元のポイントまで測定しやすい直線を作成できます。乾杯! –

+0

楕円は楕円か円ですか?トーラスは円形か楕円形ですか?彼らは同じセンターを持っていますか? [通常は、楕円軌道は惑星の中心に集中していません] –

+0

こんにちは@YvesDaoust - 両方のオブジェクトは実際には円ではなく楕円であり、同じ起点を共有します。 –

答えて

0

私は新しい解決策があるかもしれないと思う。

  1. 現在の軌道(楕円)の4つの点をプロットします。
  2. これらの点をターゲット軌道(トーラス)の平面に投影します。
  3. ターゲットの軌道傾斜を平面の法線として使用して、ターゲット軌道上の各(正規化された)点と、円周の引数 の間の角度を計算します。
  4. この角度を平均異常として使用し、同等の偏心異常を計算します。
  5. これらの偏心的な異常を使用して、ターゲット軌道上の4つの点をプロットします。これは、他の軌道に最も近い点です。
  6. これらのポイント間の距離を確認してください。

ここでの難しさは、角度を計算し、それを他の軌道上の異常に変換することに由来します。これは再帰関数よりも正確で速いはずです。私はこれを試したときに更新されます。

編集:

// The Four Locations we will use for the checks 
TArray<FVector> CurrentOrbit_CheckPositions; 
TArray<FVector> TargetOrbit_ProjectedPositions; 
CurrentOrbit_CheckPositions.SetNum(4); 
TargetOrbit_ProjectedPositions.SetNum(4); 

// We first work out the plane of the target orbit. 
const FVector Target_LANVector = FVector::ForwardVector.RotateAngleAxis(TargetOrbit.LongitudeAscendingNode, FVector::UpVector); // Vector pointing to Longitude of Ascending Node 
const FVector Target_INCVector = FVector::UpVector.RotateAngleAxis(TargetOrbit.Inclination, Target_LANVector);     // Vector pointing up the inclination axis (orbit normal) 
const FVector Target_AOPVector = Target_LANVector.RotateAngleAxis(TargetOrbit.ArgumentOfPeriapsis, Target_INCVector);   // Vector pointing towards the periapse (closest approach) 

// Geometric plane of the orbit, using the inclination vector as the normal. 
const FPlane ProjectionPlane = FPlane(Target_INCVector, 0.f); // Plane of the orbit. We only need the 'normal', and the plane origin is the Earths core (periapse focal point) 

// Plot four points on the current orbit, using an equally-divided eccentric anomaly. 
const float ECCAngle = PI/2.f; 
for (int32 i = 0; i < 4; i++) 
{ 
    // Plot the point, then project it onto the plane 
    CurrentOrbit_CheckPositions[i] = PosFromEccAnomaly(i * ECCAngle, CurrentOrbit); 
    CurrentOrbit_CheckPositions[i] = FVector::PointPlaneProject(CurrentOrbit_CheckPositions[i], ProjectionPlane); 

    // TODO: Distance from the plane is the 'Depth'. If the Depth is > Acceptance Radius, we are outside the torus and can early-out here 

    // Normalize the point to find it's direction in world-space (origin in our case is always 0,0,0) 
    const FVector PositionDirectionWS = CurrentOrbit_CheckPositions[i].GetSafeNormal(); 

    // Using the Inclination as the comparison plane - find the angle between the direction of this vector, and the Argument of Periapse vector of the Target orbit 
    // TODO: we can probably compute this angle once, using the Periapse vectors from each orbit, and just multiply it by the Index 'I' 
    float Angle = FMath::Acos(FVector::DotProduct(PositionDirectionWS, Target_AOPVector)); 

    // Compute the 'Sign' of the Angle (-180.f - 180.f), using the Cross Product 
    const FVector Cross = FVector::CrossProduct(PositionDirectionWS, Target_AOPVector); 
    if (FVector::DotProduct(Cross, Target_INCVector) > 0) 
    { 
     Angle = -Angle; 
    } 

    // Using the angle directly will give us the position at th eccentric anomaly. We want to take advantage of the Mean Anomaly, and use it as the ecc anomaly 
    // We can use this to plot a point on the target orbit, as if it was the eccentric anomaly. 
    Angle = Angle - TargetOrbit.Eccentricity * FMathD::Sin(Angle); 
    TargetOrbit_ProjectedPositions[i] = PosFromEccAnomaly(Angle, TargetOrbit);} 

コメントがこの動作の仕組みを説明してくれることを願っています。最後に数ヶ月の頭を悩ませて解決しました。皆さんありがとう!

1

単純なアプローチ:

  1. N点のセットに各軌道のサンプル。

    第1の軌道からの点をAとし、第2の軌道からの点をBとします。

    const int N=36; 
    float A[N][3],B[N][3]; 
    
  2. 2つの最も近い点

    を見つけるようd=|A[i]-B[i]|は最小です。 dがあなたのマージン/しきい値以下であれば、軌道はお互いに近すぎます。精度

  3. スピードあなたは#のためにいくつかの高度な方法を使用していない場合は、2その計算は少し怖いですO(N^2)になります。 Nが大きいほど結果の精度は向上しますが、計算にはさらに時間がかかります。両方を解決する方法があります。例えば:

    1. 小さなN

    2. を有する第一のサンプルのみ(高いN付き)問題のこれらの点の近くに最も近い点は再び両方の軌道をサンプリング

      を発見しました。

      enter image description here

    3. あなたは再帰的に楕円が互いに

に近すぎる場合は、精度

  • テストd希望するまで、#2をループすることにより、精度を高めることができます

  • +0

    ありがとう、これは良い提案です。だから、私にとって重要なのはスピードです。一度に整列させる必要があるものがいくつかあり、各フレーム(毎秒30〜60回)をチェックする必要があります。 もう一度上記のプロジェクションを試してみましょう(プロジェクトを1つずつ投影し、次にターゲット上の4点で最短距離を作ろうとします) –

    +0

    私はそれを試しましたが、残念ながらそれは遅すぎます。特に15 + orbits程度のフレームと比べると、比較するポイントの量は、レールから外れ始める。モバイルゲームの場合、それはあまりにも多くあります。 これはどこにも例がないことは私にはわかりません。確かに、3D空間内の点と楕円との間の最短距離を計算する数学的方法が存在しなければならない。 –

    関連する問題