Search code examples
c#math.net-3.5virtual-earth

Smooth movement to ascend through the atmosphere


I'm moving through the atmosphere with Microsoft Virtual Earth 3D and I can descend smoothly, but I don't know the math to ascend smoothly.

I'm descending like this:

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

This works by decreasing the size of the jump the closer I get to the earth (lower altitude). I need a solution that would do similar, just in reverse, while still keeping the smaller jumps at the lower altitude.

How can I do this? Or is what I am doing unacceptable and should be done differently (say with logarithms)?


Solution

  • An even better solution might be to use a function like the Logistic function.

    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;
    }
    

    Because the current altitude is explicitly calculated you do not have to rely on a iterative calculation introducing all sorts of precision releated errors.

    See the sample code for how to tune the function shape.


    Here is a sample console application that displays the function. You can play a bit with the parameters to get a feeling for the behavior.

    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();
            }
        }
    }