コード例 #1
0
ファイル: OrbitHelper.cs プロジェクト: ap0r/SpaceSim
        /// <summary>
        /// Traces a massive body orbit by re-centering the world around the parent.
        /// </summary>
        public static OrbitTrace TraceMassiveBody(MassiveBodyBase body)
        {
            IMassiveBody parent = body.GravitationalParent;

            DVector2 initialPosition = body.Position - parent.Position;

            var proxyParent    = new MassiveBodyProxy(DVector2.Zero, DVector2.Zero, parent);
            var proxySatellite = new MassiveBodyProxy(initialPosition, body.Velocity - parent.Velocity, body);

            double orbitalTerminationRadius;
            double altitude = body.GetRelativeAltitude();

            double orbitalDt = GetOrbitalDt(initialPosition, proxySatellite.Velocity, out orbitalTerminationRadius);

            var trace = new OrbitTrace(body.Position, altitude);

            for (int i = 0; i < 300; i++)
            {
                proxySatellite.ResetAccelerations();

                proxySatellite.ResolveGravitation(proxyParent);

                proxySatellite.Update(orbitalDt);

                altitude = proxyParent.GetRelativeHeight(proxySatellite.Position);

                // Check expensive termination conditions after half of the iterations
                if (i > 150)
                {
                    DVector2 offsetVector = proxySatellite.Position - initialPosition;

                    double distanceFromStart = offsetVector.Length();

                    // Terminate and add the end point
                    if (distanceFromStart < orbitalTerminationRadius)
                    {
                        trace.AddPoint(proxySatellite.Position + parent.Position, altitude);
                        break;
                    }
                }

                trace.AddPoint(proxySatellite.Position + parent.Position, altitude);
            }

            return(trace);
        }
コード例 #2
0
        /// <summary>
        /// Traces a massive body orbit by re-centering the world around the parent.
        /// </summary>
        public static void TraceMassiveBody(MassiveBodyBase body, OrbitTrace trace)
        {
            IMassiveBody parent = body.GravitationalParent;

            DVector2 initialPosition = body.Position - parent.Position;

            var proxyParent    = new MassiveBodyProxy(DVector2.Zero, DVector2.Zero, parent);
            var proxySatellite = new MassiveBodyProxy(initialPosition, body.Velocity - parent.Velocity, body);

            double orbitalDt = GetOrbitalDt(initialPosition.Length(), parent.Mass, proxySatellite.Velocity.Length());

            trace.Reset(body.Position);

            // Assumes that the parent is (0,0) which will be true in this case
            double previousAngle            = proxySatellite.Position.Angle();
            double totalAngularDisplacement = 0;

            // Max of 1000 steps, in practice it's 150-200
            for (int i = 0; i < 1000; i++)
            {
                proxySatellite.ResetAccelerations();

                proxySatellite.ResolveGravitation(proxyParent);

                proxySatellite.Update(orbitalDt);

                double currentAngle = proxySatellite.Position.Angle();

                totalAngularDisplacement += DeltaAngle(currentAngle, previousAngle);

                // Made a full orbit
                if (totalAngularDisplacement > AngularCutoff)
                {
                    break;
                }

                previousAngle = currentAngle;

                double altitude = proxyParent.GetRelativeHeight(proxySatellite.Position);

                trace.AddPoint(proxySatellite.Position + parent.Position, altitude);
            }
        }
コード例 #3
0
        private void PredictTargetThrottle(SpaceCraftBase spaceCraft)
        {
            double optimalThrust       = _currentThrust;
            double optimalLandingSpeed = double.PositiveInfinity;

            for (int i = -1; i <= 1; i++)
            {
                double thrust = _currentThrust;

                thrust += i;

                if (thrust < 40 || thrust > 100)
                {
                    continue;
                }

                IMassiveBody parent = spaceCraft.GravitationalParent;

                DVector2 initialPosition = spaceCraft.Position - parent.Position;

                var proxyParent    = new MassiveBodyProxy(DVector2.Zero, DVector2.Zero, parent);
                var proxySatellite = new SpaceCraftProxy(initialPosition, spaceCraft.Velocity - parent.Velocity, spaceCraft);

                foreach (int id in _engineIds)
                {
                    proxySatellite.Engines[id].Startup();
                    proxySatellite.Engines[id].AdjustThrottle(thrust);
                }

                proxySatellite.SetGravitationalParent(proxyParent);

                // Simulate until the rocket runs out of fuel or touches down
                for (int step = 0; step < 1000; step++)
                {
                    proxySatellite.ResetAccelerations();
                    proxySatellite.ResolveGravitation(proxyParent);
                    proxySatellite.ResolveAtmopsherics(proxyParent);

                    if (proxySatellite.PropellantMass <= 0)
                    {
                        break;
                    }

                    if (proxySatellite.OnGround)
                    {
                        double landingSpeed = proxySatellite.RelativeVelocity.Length();

                        if (landingSpeed < optimalLandingSpeed)
                        {
                            optimalLandingSpeed = landingSpeed;
                            optimalThrust       = thrust;
                        }

                        break;
                    }

                    proxySatellite.Update(0.05);
                }
            }

            // Set the target engines to the optimal computed thrust
            if (_engineIds != null)
            {
                // Startup the required landing engines
                foreach (int id in _engineIds)
                {
                    IEngine engine = spaceCraft.Engines[id];

                    engine.AdjustThrottle(optimalThrust);
                }

                _currentThrust = optimalThrust;
            }
        }
コード例 #4
0
        /// <summary>
        /// Traces a space craft orbit by re-centering the world around the parent.
        /// </summary>
        public static void TraceSpaceCraft(SpaceCraftBase satellite, OrbitTrace trace)
        {
            IMassiveBody parent = satellite.GravitationalParent;

            DVector2 initialPosition = satellite.Position - parent.Position;

            var shipOffset = new DVector2(Math.Cos(satellite.Pitch) * (satellite.TotalWidth - satellite.Width),
                                          Math.Sin(satellite.Pitch) * (satellite.TotalHeight - satellite.Height)) * 0.5;

            initialPosition -= shipOffset;

            var proxyParent    = new MassiveBodyProxy(DVector2.Zero, DVector2.Zero, parent);
            var proxySatellite = new SpaceCraftProxy(initialPosition, satellite.Velocity - parent.Velocity, satellite);

            proxySatellite.SetGravitationalParent(proxyParent);

            int stepCount;

            double targetDt;
            double proximityDt;
            double orbitalDt = 0;

            bool isOrbiting;

            double altitude          = proxyParent.GetRelativeHeight(proxySatellite.Position);
            double proximityAltitude = proxyParent.SurfaceRadius * 0.15;

            if (altitude < proximityAltitude)
            {
                stepCount = 1100;

                isOrbiting = false;

                proximityDt = GetProximityDt(altitude, proximityAltitude);

                targetDt = proximityDt;
            }
            else
            {
                stepCount = 600;

                isOrbiting = true;

                orbitalDt = GetOrbitalDt(initialPosition.Length(), parent.Mass, proxySatellite.Velocity.Length());

                targetDt = orbitalDt;
            }

            // Assumes that the parent is (0,0) which will be true in this case
            double previousAngle            = proxySatellite.Position.Angle();
            double totalAngularDisplacement = 0;

            trace.Reset(satellite.Position - shipOffset);

            // Update steps based on orbit vs atmosphere
            for (int step = 0; step < stepCount; step++)
            {
                proxySatellite.ResetAccelerations();

                proxySatellite.ResolveGravitation(proxyParent);
                proxySatellite.ResolveAtmopsherics(proxyParent);

                proxySatellite.Update(targetDt);

                double currentAngle = proxySatellite.Position.Angle();

                totalAngularDisplacement += DeltaAngle(currentAngle, previousAngle);

                // Made a full orbit
                if (totalAngularDisplacement > AngularCutoff)
                {
                    break;
                }

                previousAngle = currentAngle;

                altitude = proxyParent.GetRelativeHeight(proxySatellite.Position);

                double velocity = proxySatellite.GetRelativeVelocity().Length();

                double offsetFactor = 0.0;

                //if (altitude < proxyParent.AtmosphereHeight*2)
                if (altitude < proxyParent.AtmosphereHeight * 4)
                {
                    if (velocity < 3000)
                    {
                        offsetFactor = 1.0;
                    }
                    else if (velocity < 4000)
                    {
                        offsetFactor = 1.0 - velocity / 3000.0;
                    }
                }

                // Check if reference frame shifting needs to occur in atmosphere
                if (offsetFactor > 0.0001)
                {
                    DVector2 difference = proxyParent.Position - proxySatellite.Position;
                    difference.Normalize();

                    var surfaceNormal = new DVector2(-difference.Y, difference.X);

                    double altitudeFromCenter = altitude + proxyParent.SurfaceRadius;

                    // Distance of circumference at this altitude ( c= r * 2pi )
                    double pathCirumference = Constants.TwoPi * altitudeFromCenter;

                    double rotationalSpeed = pathCirumference / parent.RotationPeriod;

                    DVector2 atmopshereVelocity = surfaceNormal * rotationalSpeed;

                    proxySatellite.ApplyFrameOffset(atmopshereVelocity * offsetFactor * targetDt);
                }

                // Return early if the trace goes into a planet
                if (altitude <= 0)
                {
                    trace.AddPoint(proxySatellite.Position + parent.Position, altitude);
                    break;
                }

                // Determine the correct change overs from orbital to surface proximity
                if (isOrbiting)
                {
                    if (altitude < proximityAltitude)
                    {
                        proximityDt = GetProximityDt(altitude, proximityAltitude);

                        targetDt = MathHelper.Lerp(targetDt, proximityDt, 0.75);

                        isOrbiting = false;

                        stepCount = 1000;
                    }
                    else
                    {
                        targetDt = MathHelper.Lerp(targetDt, orbitalDt, 0.1);
                    }
                }
                else
                {
                    if (altitude > proximityAltitude)
                    {
                        orbitalDt = GetOrbitalDt(proxySatellite.Position.Length(), parent.Mass, proxySatellite.Velocity.Length());

                        targetDt = MathHelper.Lerp(targetDt, orbitalDt, 0.1);

                        isOrbiting = true;

                        stepCount = 600;
                    }
                    else
                    {
                        proximityDt = GetProximityDt(altitude, proximityAltitude);

                        targetDt = MathHelper.Lerp(targetDt, proximityDt, 0.75);
                    }
                }

                trace.AddPoint(proxySatellite.Position + parent.Position, altitude);
            }
        }
コード例 #5
0
ファイル: OrbitHelper.cs プロジェクト: AyaanaPS/SpaceSim
        /// <summary>
        /// Traces a space craft orbit by re-centering the world around the parent.
        /// </summary>
        public static void TraceSpaceCraft(SpaceCraftBase satellite, OrbitTrace trace)
        {
            IMassiveBody parent = satellite.GravitationalParent;

            DVector2 initialPosition = satellite.Position - parent.Position;

            var shipOffset = new DVector2(Math.Cos(satellite.Pitch) * (satellite.TotalWidth - satellite.Width),
                                          Math.Sin(satellite.Pitch) * (satellite.TotalHeight - satellite.Height)) * 0.5;

            initialPosition -= shipOffset;

            var proxyParent    = new MassiveBodyProxy(DVector2.Zero, DVector2.Zero, parent);
            var proxySatellite = new SpaceCraftProxy(initialPosition, satellite.Velocity - parent.Velocity, satellite);

            proxySatellite.SetGravitationalParent(proxyParent);

            int stepCount;

            double targetDt;
            double proximityDt;
            double orbitalDt = 0;

            bool   isOrbiting;
            double orbitalTerminationRadius = 0;

            double altitude          = proxyParent.GetRelativeHeight(proxySatellite.Position);
            double proximityAltitude = proxyParent.SurfaceRadius * 0.15;

            if (altitude < proximityAltitude)
            {
                stepCount = 1100;

                isOrbiting = false;

                proximityDt = GetProximityDt(altitude, proximityAltitude);

                targetDt = proximityDt;
            }
            else
            {
                stepCount = 600;

                isOrbiting = true;

                orbitalDt = GetOrbitalDt(initialPosition, proxySatellite.Velocity, out orbitalTerminationRadius);

                targetDt = orbitalDt;
            }

            trace.Reset(satellite.Position - shipOffset);

            // Simulate 300 orbital steps, more for proximity
            for (int step = 0; step < stepCount; step++)
            {
                proxySatellite.ResetAccelerations();

                proxySatellite.ResolveGravitation(proxyParent);
                proxySatellite.ResolveAtmopsherics(proxyParent);

                proxySatellite.Update(targetDt);

                altitude = proxyParent.GetRelativeHeight(proxySatellite.Position);

                double velocity = proxySatellite.GetRelativeVelocity().Length();

                double offsetFactor = 0.0;

                if (altitude < proxyParent.AtmosphereHeight * 2)
                {
                    if (velocity < 3000)
                    {
                        offsetFactor = 1.0;
                    }
                    else if (velocity < 4000)
                    {
                        offsetFactor = 1.0 - velocity / 3000.0;
                    }
                }

                // Check if reference frame shifting needs to occur in atmosphere
                if (offsetFactor > 0.0001)
                {
                    DVector2 difference = proxyParent.Position - proxySatellite.Position;
                    difference.Normalize();

                    var surfaceNormal = new DVector2(-difference.Y, difference.X);

                    double altitudeFromCenter = altitude + proxyParent.SurfaceRadius;

                    // Distance of circumference at this altitude ( c= 2r * pi )
                    double pathCirumference = 2 * Math.PI * altitudeFromCenter;

                    double rotationalSpeed = pathCirumference / parent.RotationPeriod;

                    DVector2 atmopshereVelocity = surfaceNormal * rotationalSpeed;

                    proxySatellite.ApplyFrameOffset(atmopshereVelocity * offsetFactor * targetDt);

                    // Return early if the trace goes into a planet
                    if (altitude <= 0)
                    {
                        trace.AddPoint(proxySatellite.Position + parent.Position, altitude);
                        break;
                    }
                }

                // Determine the correct change overs from orbital to surface proximity
                if (isOrbiting)
                {
                    if (altitude < proximityAltitude)
                    {
                        proximityDt = GetProximityDt(altitude, proximityAltitude);

                        targetDt = MathHelper.Lerp(targetDt, proximityDt, 0.75);

                        isOrbiting = false;

                        stepCount = 1000;
                    }
                    else
                    {
                        targetDt = MathHelper.Lerp(targetDt, orbitalDt, 0.1);
                    }
                }
                else
                {
                    if (altitude > proximityAltitude)
                    {
                        orbitalDt = GetOrbitalDt(proxySatellite.Position, proxySatellite.Velocity, out orbitalTerminationRadius);

                        targetDt = MathHelper.Lerp(targetDt, orbitalDt, 0.1);

                        isOrbiting = true;

                        stepCount = 600;
                    }
                    else
                    {
                        proximityDt = GetProximityDt(altitude, proximityAltitude);

                        targetDt = MathHelper.Lerp(targetDt, proximityDt, 0.75);
                    }
                }

                // Check expensive termination conditions after half of the iterations
                if (isOrbiting && step > 100)
                {
                    DVector2 offsetVector = proxySatellite.Position - initialPosition;

                    double distanceFromStart = offsetVector.Length();

                    // Terminate and add the end point
                    if (distanceFromStart < orbitalTerminationRadius)
                    {
                        trace.AddPoint(proxySatellite.Position + parent.Position, altitude);
                        break;
                    }
                }

                trace.AddPoint(proxySatellite.Position + parent.Position, altitude);
            }
        }