2009-04-01 3 views
1

私はMicrosoft Virtual Earth 3Dで大気圏を移動しています。滑らかに降りることができますが、滑らかに上がる数学はわかりません。大気中を滑らか​​に移動する

私はこのように下降しています:

for(int curAlt = startAlt; curAlt < endAlt; curAlt--){ 
    //do something 
    curAlt -= curAlt/150 
} 

これは近い私が地球(低高度)を取得ジャンプの大きさを減少させることによって動作します。似たようなソリューションを必要とします。逆に、低高度でも小さなジャンプを維持します。

どうすればいいですか?それとも、私が受け入れられないことですし、別の方法(対数で言う)をしなければなりませんか?

答えて

4

さらに良い解決策は、Logistic functionのような機能を使用することです。現在の高度が明示的に精度releatedエラーのすべての種類を導入反復計算に頼る必要はありません計算されているので

Double minAlt = 0.0; 
Double maxAlt = 500000.0; 

Int32 numberSteps = 1000; 

Double boundary = +6.0; 

for (Int32 step = 0; step < numberSteps; step++) 
{ 
    Double t = -boundary + 2.0 * boundary * step/(numberSteps - 1); 
    Double correction = 1.0/(1.0 + Math.Exp(Math.Abs(boundary))); 
    Double value = 1.0/(1.0 + Math.Exp(-t)); 
    Double correctedValue = (value - correction)/(1.0 - 2.0 * correction); 
    Double curAlt = correctedValue * (maxAlt - minAlt) + minAlt; 
} 

関数の形状を調整する方法のサンプルコードを参照してください。


ここには、この機能を表示するコンソールアプリケーションのサンプルがあります。あなたは、その行動の感情を得るためにパラメータを少し再生することができます。

using System; 

namespace LogisticFunction 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Double minAlt = 5.0; 
      Double maxAlt = 95.0; 

      Int32 numberSteps = 60; 

      // Keep maxAlt and numberSteps small if you don't want a giant console window. 
      Console.SetWindowSize((Int32)maxAlt + 12, numberSteps + 1); 

      // Positive values produce ascending functions. 
      // Negative values produce descending functions. 
      // Values with smaller magnitude produce more linear functions. 
      // Values with larger magnitude produce more step like functions. 
      // Zero causes an error. 
      // Try for example +1.0, +6.0, +20.0 and -1.0, -6.0, -20.0 
      Double boundary = +6.0; 

      for (Int32 step = 0; step < numberSteps; step++) 
      { 
       Double t = -boundary + 2.0 * boundary * step/(numberSteps - 1); 
       Double correction = 1.0/(1.0 + Math.Exp(Math.Abs(boundary))); 
       Double value = 1.0/(1.0 + Math.Exp(-t)); 
       Double correctedValue = (value - correction)/(1.0 - 2.0 * correction); 
       Double curAlt = correctedValue * (maxAlt - minAlt) + minAlt; 

       Console.WriteLine(String.Format("{0, 10:N4} {1}", curAlt, new String('#', (Int32)Math.Round(curAlt)))); 
      } 

      Console.ReadLine(); 
     } 
    } 
} 
+0

私が探しているかもしれません!私はそれをテストしてみましょう – Malfist

+0

私はそれを間違った方法で実装しているかもしれないと思います。私は最初の反復の巨大なジャンプを取得しますが、それ以降は誰もがそれをすべきです。次のコード行があります。double curAlt = 1 /(1 + Math.Exp(-t))*(properties.endingAltitude) - properties.startingAltitude; – Malfist

+0

また、私はカーブの前半または後半だけを望んでいます、どうすればいいですか? – Malfist

0

スムーズに上がることで、何をしたいかによって決まります。高度をある最大値maxAltに制限し、地面と同じように滑らかにその値に近づけることができます。

curAlt += (maxAlt - curAlt)/150 

最大高度に制限がない場合は、正確に滑らかにしたいものをクリアする必要があります。

また、コードはいくつかの副作用によってのみ機能することにも注意してください。あなたは無限ループに近づいています。私はfolowingをお勧めします。

epsilon = 0.1; // A small value that fits your needs 

curAlt = startAlt; 

while (curAlt > endAlt + epsilon) 
{ 
    curAlt -= (curAlt - endAlt)/150; 
} 

curAltの反復 - =(curAlt - endAlt)/ 150は、ほとんどのエラーをroudingことにより、理論的には、実際にあるendAltに到達することはありません。あなたのコードは、反復ごとに1つの追加高さ単位を減算するためにのみ機能します。私はこれが設計上のものか、バグを防ぐエラーかどうかはわかりません。イプシロン・スレッショルドを追加すると、ループがより論理的に分割されます。

+0

最大値はユーザーによって指定されます。この場合、まったく同じではない500k – Malfist

+0

としましょう。テストケースを使用して、私の降下のために私は1338ステップを得るが、これで私は1557を得るが、それは十分に近いと思う。 – Malfist

+0

これは前述のように追加の引き算に関連するかもしれない。 –

1

ところで、あなたは本当に上昇時間を(フレームレートを意識して)依存させるべきです。ここでのすべての答えは、特定の間隔で呼び出されるコードに依存します。それはそうではありません。いくつかのプロセスが始まると、Virtual Earthは何らかの形でストレスを受けます.Virtual Earthを最小化するか、Virtual Earthのパフォーマンスに影響を及ぼすものが発生した場合、動きはスムーズになります。バーチャルアースに何も起こらなくても、あなたの3Dカードがストールすることがあります。潜在的には、潜在的にあなたはいつもジャンプを得るでしょう。特に

ユーザーはVSYNCがあなたには、いくつかの本当に嫌なことは、最大トリミングれますオフになっている場合:

  • を遅いマシンで昇天が(でも上のVSyncで)永遠にかかります。
  • 高速のマシンでは、それは非常に速くて気付かないかもしれません。あなたのクラスで

:あなたのループ/イベントに

private int lastTime; 

if(lastTime == 0) 
{ 
    lastTime = Environment.TickCount; 
    return; 
} 

int curTime = Environment.TickCount; // store this baby. 
int timeDiff = lastTime - curTime; 

if(timeDiff == 0) 
    return; 

curAlt += (maxAlt - curAlt) * timeDiff/(150000); // TickCount reports 
                // time in Ticks 
                // (1000 ticks per second) 

lastTime = curTime; 

あなたは空想を取得したい場合は、DX SDKからコードを差し込むことができます。 Environment.TickCountは15msの解像度を持っています(なぜなら、それは簡単にできるので、timeDiffが0であることを確認する理由です)。管理されたDX SDKサンプルフレームワークには、より優れた解像度を持つDxTimer(またはソート)というクラスがあります。

There is an article that uses the same API

+0

downvoteの理由はどうですか? –

0

あなたがcurAltを使用するので - 降順のために= curAlt/150、なぜ上昇のためcurAlt + = curAlt * 150を使用していませんか?

+0

curAltが増加するにつれて、彼は減速したいと同時にますます加速しています。 –

+0

彼の記述は「より低い高度で小さなジャンプを維持する」と言っているので、それは高い標高でステップサイズが大きくなることを意味すると理解しています。 –

+0

彼は実際には低高度で小さな歩みを維持しながら、高高度では小さな歩みを達成したいと考えています。 http://ja.wikipedia.org/wiki/Logistic_functionは、彼が何を望んでいるかを示しています。地面をスムーズにスタートさせ、加速し、最大上昇率に到達し、減速し、最高高度にスムーズに近づきます。 –

関連する問題