示例#1
0
        public override Orbit drawOrbit ()
        {
            CelestialBody body = AsteroidManager.getPlanetByName (targetBody);

            Debug.Log ("[CustomAsteroids]: "
                       + Localizer.Format ("#autoLOC_CustomAsteroids_LogOrbitDraw", getName ()));

            double deltaV = wrappedDraw (vSoi, getName (), "vSoi");
            double deltaT = wrappedDraw (warnTime, getName (), "warnTime");

            if (deltaV <= 0.0) {
                throw new InvalidOperationException (
                    Localizer.Format ("#autoLOC_CustomAsteroids_ErrorFlybyBadVInf",
                                      getName (), deltaV));
            }
            // Negative deltaT is allowed

            double peri;
            switch (approach.getParam ()) {
            case ApproachRange.Type.ImpactParameter:
                double b = wrappedDraw (approach, getName (), "approach");
                if (b < 0.0) {
                    throw new InvalidOperationException (
                        Localizer.Format ("#autoLOC_CustomAsteroids_ErrorFlybyBadB", getName (), b));
                }
                double a = -body.gravParameter / (deltaV * deltaV);
                double x = b / a;
                peri = a * (1.0 - Math.Sqrt (x * x + 1.0));
                break;
            case ApproachRange.Type.Periapsis:
                peri = wrappedDraw (approach, getName (), "approach");
                if (peri < 0.0) {
                    throw new InvalidOperationException (
                        Localizer.Format ("#autoLOC_CustomAsteroids_ErrorFlybyBadPeri",
                                          getName (), peri));
                }
                break;
            default:
                throw new InvalidOperationException (
                    Localizer.Format ("#autoLOC_CustomAsteroids_ErrorFlybyBadApproach",
                                      getName (), approach.getParam ()));
            }
#if DEBUG
            Debug.Log ($"[CustomAsteroids]: "
                       + Localizer.Format ("#autoLOC_CustomAsteroids_LogFlyby",
                                          peri, targetBody, deltaT / (6.0 * 3600.0), deltaV)
                      );
#endif

            Orbit newOrbit = createHyperbolicOrbit (body, peri, deltaV,
                                                    Planetarium.GetUniversalTime () + deltaT);
            // Sun has sphereOfInfluence = +Infinity, so condition will always fail for Sun-centric
            // orbit. No special treatment needed for the case where the orbit lies entirely outside
            // the SoI
            while (needsSoITransition (newOrbit)) {
                newOrbit = patchToParent (newOrbit);
            }
            newOrbit.UpdateFromUT (Planetarium.GetUniversalTime ());
            return newOrbit;
        }
示例#2
0
        /// <summary>
        /// Returns the desired property of a known celestial body.
        /// </summary>
        ///
        /// <param name="planet">The exact, case-sensitive name of the celestial body. Assumes all
        /// loaded celestial bodies have unique names.</param>
        /// <param name="property">The short name of the property to recover. Must be one
        /// of ("rad", "soi", "sma", "per", "apo", "ecc", "inc", "ape", "lan", "mna0", "mnl0",
        /// "prot", "psun", "porb", "vesc", "vorb", "vmin", or "vmax").
        /// The only properties supported for Sun are "rad", "soi", "prot", and "vesc".</param>
        /// <returns>The value of <c>property</c> appropriate for <c>planet</c>. Distances are given
        /// in meters, angles are given in degrees.</returns>
        ///
        /// <exception cref="ArgumentException">Thrown if no planet named <c>name</c> exists, or if
        /// <c>property</c> does not have one of the allowed values. The program state shapp remain
        /// unchanged in the event of an exception.</exception>
        protected static double getPlanetProperty(string planet, string property)
        {
            CelestialBody body = AsteroidManager.getPlanetByName(planet);

            switch (property.ToLower())
            {
            case "rad":
                return(body.Radius);

            case "soi":
                return(body.sphereOfInfluence);

            case "prot":
                return(body.rotates ? body.rotationPeriod : double.PositiveInfinity);

            case "psol":
                if (body.solarRotationPeriod)
                {
                    return(body.solarDayLength);
                }
                else
                {
                    throw new ArgumentException(
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorPlanetNoDay", planet),
                              nameof(property));
                }

            case "vesc":
                return(Math.Sqrt(2 * body.gravParameter / body.Radius));

            default:
                if (body.GetOrbitDriver() == null)
                {
                    throw new ArgumentException(
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorPlanetNoOrbit", planet),
                              nameof(planet));
                }
                Orbit orbit = body.GetOrbit();

                switch (property.ToLower())
                {
                case "sma":
                    return(orbit.semiMajorAxis);

                case "per":
                    return(orbit.PeR);

                case "apo":
                    return(orbit.ApR);

                case "ecc":
                    return(orbit.eccentricity);

                case "inc":
                    return(orbit.inclination);

                case "ape":
                    return(orbit.argumentOfPeriapsis);

                case "lpe":
                    // Ignore inclination: http://en.wikipedia.org/wiki/Longitude_of_periapsis
                    return(orbit.LAN + orbit.argumentOfPeriapsis);

                case "lan":
                    return(orbit.LAN);

                case "mna0":
                    return(meanAnomalyAtUT(orbit, 0.0) * 180.0 / Math.PI);

                case "mnl0":
                    return(anomalyToLong(meanAnomalyAtUT(orbit, 0.0) * 180.0 / Math.PI,
                                         orbit.inclination, orbit.argumentOfPeriapsis, orbit.LAN));

                case "porb":
                    return(orbit.period);

                case "vorb":
                    // Need circumference of an ellipse; closed form does not exist
                    double sum        = orbit.semiMajorAxis + orbit.semiMinorAxis;
                    double diff       = orbit.semiMajorAxis - orbit.semiMinorAxis;
                    double h          = diff * diff / (sum * sum);
                    double correction = 1.0;
                    for (int n = 1; n < 10; n++)
                    {
                        double coeff = Util.DoubleFactorial(2 * n - 1)
                                       / (Math.Pow(2, n) * Util.Factorial(n))
                                       / (2 * n - 1);
                        correction += coeff * coeff * Math.Pow(h, n);
                    }
                    return(Math.PI * sum * correction / orbit.period);

                case "vmin":
                    return(orbit.getOrbitalSpeedAtDistance(orbit.ApR));

                case "vmax":
                    return(orbit.getOrbitalSpeedAtDistance(orbit.PeR));

                default:
                    throw new ArgumentException(
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorPlanetBadProperty", property),
                              nameof(property));
                }
            }
        }
示例#3
0
        public override Orbit drawOrbit()
        {
            // Would like to only calculate this once, but I don't know for sure that this object
            // will be initialized after FlightGlobals
            CelestialBody orbitee = AsteroidManager.getPlanetByName(centralBody);

            Debug.Log($"[CustomAsteroids]: "
                      + Localizer.Format("#autoLOC_CustomAsteroids_LogOrbitDraw", getName()));

            // Properties with only one reasonable parametrization
            double e = wrappedDraw(eccentricity, getName(), "eccentricity");

            if (e < 0.0)
            {
                throw new InvalidOperationException(
                          Localizer.Format("#autoLOC_CustomAsteroids_ErrorOrbitBadEcc", getName(), e));
            }
            // Sign of inclination is redundant with 180-degree shift in longitude of ascending node
            // So it's ok to just have positive inclinations
            double i   = wrappedDraw(inclination, getName(), "inclination");
            double lAn = wrappedDraw(ascNode, getName(), "ascNode");

            // Position of periapsis
            double aPe;
            double peri = wrappedDraw(periapsis, getName(), "periapsis");

            switch (periapsis.getParam())
            {
            case PeriRange.Type.Argument:
                aPe = peri;
                break;

            case PeriRange.Type.Longitude:
                aPe = peri - lAn;
                break;

            default:
                throw new InvalidOperationException(
                          Localizer.Format("#autoLOC_CustomAsteroids_ErrorOrbitBadPeri", getName(),
                                           periapsis.getParam()));
            }

            // Semimajor axis
            double a;
            double size = wrappedDraw(orbitSize, getName(), "orbitSize");

            switch (orbitSize.getParam())
            {
            case SizeRange.Type.SemimajorAxis:
                a = size;
                break;

            case SizeRange.Type.Periapsis:
                a = size / (1.0 - e);
                break;

            case SizeRange.Type.Apoapsis:
                if (e > 1.0)
                {
                    throw new InvalidOperationException(
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorOrbitHyperbolicApo",
                                               getName(), e));
                }
                a = size / (1.0 + e);
                break;

            default:
                throw new InvalidOperationException(
                          Localizer.Format("#autoLOC_CustomAsteroids_ErrorOrbitBadSize",
                                           getName(), orbitSize.getParam()));
            }

            // Mean anomaly at given epoch
            double mEp, epoch;
            double phase = wrappedDraw(orbitPhase, getName(), "orbitPhase");

            switch (orbitPhase.getParam())
            {
            case PhaseRange.PhaseType.MeanAnomaly:
                // Mean anomaly is the ONLY orbital angle that needs to be given in radians
                mEp = Math.PI / 180.0 * phase;
                break;

            case PhaseRange.PhaseType.MeanLongitude:
                mEp = Math.PI / 180.0 * longToAnomaly(phase, i, aPe, lAn);
                break;

            default:
                throw new InvalidOperationException(
                          Localizer.Format("#autoLOC_CustomAsteroids_ErrorOrbitBadPhase",
                                           getName(), orbitPhase.getParam()));
            }
            switch (orbitPhase.getEpoch())
            {
            case PhaseRange.EpochType.GameStart:
                epoch = 0.0;
                break;

            case PhaseRange.EpochType.Now:
                epoch = Planetarium.GetUniversalTime();
                break;

            default:
                throw new InvalidOperationException(
                          Localizer.Format("#autoLOC_CustomAsteroids_ErrorOrbitBadEpoch",
                                           getName(), orbitPhase.getEpoch()));
            }

            // Fix accidentally hyperbolic orbits
            if (a * (1.0 - e) < 0.0)
            {
                a = -a;
            }

            Debug.Log($"[CustomAsteroids]: "
                      + Localizer.Format("#autoLOC_CustomAsteroids_LogOrbit",
                                         a, e, i, aPe, lAn, mEp, epoch));

            // Does Orbit(...) throw exceptions?
            Orbit newOrbit = new Orbit(i, e, a, lAn, aPe, mEp, epoch, orbitee);

            frameTransform(newOrbit);
            newOrbit.UpdateFromUT(Planetarium.GetUniversalTime());

            return(newOrbit);
        }