示例#1
0
        /// <summary>
        /// Generates a random orbit in as similar a manner to stock as possible.
        /// </summary>
        /// <returns>The orbit of a randomly selected member of the population.</returns>
        ///
        /// <exception cref="InvalidOperationException">Thrown if cannot produce stockalike
        /// orbits. The program will be in a consistent state in the event of an exception.</exception>
        public Orbit drawOrbit()
        {
            CelestialBody kerbin = FlightGlobals.Bodies.Find(body => body.isHomeWorld);
            CelestialBody dres   = FlightGlobals.Bodies.Find(body => body.name.Equals("Dres"));

            if (dres != null && reachedBody(dres) && UnityEngine.Random.Range(0, 4) == 0)
            {
                // Drestroids
                double a     = RandomDist.drawLogUniform(0.55, 0.65) * dres.sphereOfInfluence;
                double e     = RandomDist.drawRayleigh(0.005);
                double i     = RandomDist.drawRayleigh(0.005); // lAn takes care of negative inclinations
                double lAn   = RandomDist.drawAngle();
                double aPe   = RandomDist.drawAngle();
                double mEp   = Math.PI / 180.0 * RandomDist.drawAngle();
                double epoch = Planetarium.GetUniversalTime();

                Debug.Log("[CustomAsteroids]: "
                          + Localizer.Format("#autoLOC_CustomAsteroids_LogOrbit",
                                             a, e, i, aPe, lAn, mEp, epoch));
                return(new Orbit(i, e, a, lAn, aPe, mEp, epoch, dres));
            }
            if (kerbin != null)
            {
                // Kerbin interceptors
                double delay = RandomDist.drawUniform(12.5, 55.0);
                Debug.Log("[CustomAsteroids]: "
                          + Localizer.Format("#autoLOC_CustomAsteroids_LogDefault", delay));
                return(Orbit.CreateRandomOrbitFlyBy(kerbin, delay));
            }
            throw new InvalidOperationException(
                      Localizer.Format("#autoLOC_CustomAsteroids_ErrorDefaultNoKerbin"));
        }
示例#2
0
        /// <summary>
        /// Creates a hyperbolic orbit around the given celestial body.
        /// </summary>
        /// <returns>The newly created orbit, with state vectors anchored to its periapsis.</returns>
        /// <param name="body">The celestial body at the focus of the orbit.</param>
        /// <param name="periapsis">The periapsis (from the body center), in meters. Must not be
        /// negative.</param>
        /// <param name="vInf">The excess speed associated with the orbit, in meters per second.
        /// Must be positive.</param>
        /// <param name="utPeri">The absolute time of periapsis passage.</param>
        ///
        /// <exception cref="ArgumentException">Thrown if either <c>periapsis</c> or <c>vInf</c>
        /// are out of bounds.</exception>
        static Orbit createHyperbolicOrbit (CelestialBody body, double periapsis, double vInf,
                                            double utPeri)
        {
            if (vInf <= 0.0) {
                throw new ArgumentException (
                    Localizer.Format ("#autoLOC_CustomAsteroids_ErrorHyperBadVInf", vInf),
                    nameof (vInf));
            }
            if (periapsis < 0.0) {
                throw new ArgumentException (
                    Localizer.Format ("#autoLOC_CustomAsteroids_ErrorHyperBadPeri", periapsis),
                    nameof (periapsis));
            }

            double a = -body.gravParameter / (vInf * vInf);
            double e = 1.0 - periapsis / a;

            // Random orientation, to be consistent with CreateRandomOrbitFlyBy
            double i = RandomDist.drawIsotropic ();
            double lAn = RandomDist.drawAngle ();
            double aPe = RandomDist.drawAngle ();

            Debug.Log ($"[CustomAsteroids]: "
                       + Localizer.Format ("#autoLOC_CustomAsteroids_LogHyperOrbit", body.bodyName,
                                           a, e, i, aPe, lAn));

            return new Orbit (i, e, a, lAn, aPe, 0.0, utPeri, body);
        }
 /// <summary>
 /// Randomly selects an asteroid class. The selection is weighted by the proportions passed
 /// to the method.
 /// </summary>
 ///
 /// <param name="typeRatios">The proportions in which to select the types.</param>
 /// <returns>The selected asteroid class. Shall not be null.</returns>
 ///
 /// <exception cref="InvalidOperationException">Thrown if there are no types from
 /// which to choose, or if all proportions are zero, or if any proportion is
 /// negative.</exception>
 internal static string drawAsteroidType <Dummy> (Proportions <Dummy> typeRatios)
 {
     try {
         return(RandomDist.weightedSample(typeRatios.asPairList()));
     } catch (ArgumentException e) {
         throw new InvalidOperationException(
                   Localizer.Format("#autoLOC_CustomAsteroids_ErrorNoClass2"), e);
     }
 }
示例#4
0
        public Tuple <double, double> drawTrackingTime()
        {
            Tuple <float, float> trackTimes = AsteroidManager.getOptions().getUntrackedTimes();
            double lifetime = RandomDist.drawUniform(trackTimes.Item1, trackTimes.Item2)
                              * SECONDS_PER_EARTH_DAY;
            double maxLifetime = trackTimes.Item2 * SECONDS_PER_EARTH_DAY;

            return(Tuple.Create(lifetime, maxLifetime));
        }
示例#5
0
 /// <summary>
 /// Randomly selects an asteroid set. The selection is weighted by the spawn rate of
 /// each population; a set with a rate of 2.0 is twice as likely to be chosen as one
 /// with a rate of 1.0.
 /// </summary>
 /// <returns>A reference to the selected asteroid set. Shall not be null.</returns>
 ///
 /// <exception cref="InvalidOperationException">Thrown if there are no sets from
 /// which to choose, or if all spawn rates are zero, or if any rate is negative</exception>
 internal AsteroidSet drawAsteroidSet()
 {
     try {
         var bins = new List <Pair <AsteroidSet, double> > ();
         foreach (AsteroidSet x in asteroidPops)
         {
             bins.Add(new Pair <AsteroidSet, double> (x, x.getSpawnRate()));
         }
         return(RandomDist.weightedSample(bins));
     } catch (ArgumentException e) {
         throw new InvalidOperationException(
                   Localizer.Format("#autoLOC_CustomAsteroids_ErrorNoGroup"), e);
     }
 }
        /// <summary>
        /// Returns the time until the next asteroid should be detected. Does not throw exceptions.
        /// </summary>
        /// <returns>The number of seconds before an asteroid detection, or infinity if asteroids
        /// should not spawn.</returns>
        private static double asteroidWaitTime()
        {
            double rate = AsteroidManager.spawnRate();  // asteroids per day

            if (rate > 0.0)
            {
                // Waiting time in a Poisson process follows an exponential distribution
                rate /= SECONDS_PER_EARTH_DAY;          // asteroids per second
                return(RandomDist.drawExponential(1.0 / rate));
            }
            else
            {
                return(double.PositiveInfinity);
            }
        }
        protected override void checkSpawn()
        {
            double ut = Planetarium.GetUniversalTime();

            try {
                // Cap at one asteroid per tick; this is unlikely to reduce the rate even at 100,000×
                if (areAsteroidsTrackable() && RandomDist.drawUniform(0, 1) < asteroidChance(ut - lastCheck))
                {
                    Debug.Log("[FixedRateSpawner]: "
                              + Localizer.Format("#autoLOC_CustomAsteroids_LogSpawnInterval",
                                                 ut));
                    spawnAsteroid();
                }
            } finally {
                lastCheck = ut;
            }
        }
 public UntrackedObjectClass drawAsteroidSize()
 {
     if (sizeRatios != null)
     {
         string sizeName = RandomDist.weightedSample(sizeRatios.asPairList());
         if (Enum.TryParse(sizeName, true, out UntrackedObjectClass size))
         {
             return(size);
         }
         else
         {
             Util.errorToPlayerLoc("#autoLOC_CustomAsteroids_ErrorNoSize", sizeName, name);
             Debug.LogError($"[CustomAsteroids]: Invalid asteroid size {sizeName} in group {name}.");
             return(UntrackedObjectClass.C);
         }
     }
     else
     {
         // Stock asteroids appear to be hardcoded to be from size A to E, even though there are more classes now
         return((UntrackedObjectClass)(int)
                (stockSizeCurve.Evaluate((float)RandomDist.drawUniform(0, 1)) * 5));
     }
 }
示例#9
0
        /// <summary>
        /// Generates a random number consistent with the distribution. The program state shall be
        /// unchanged in the event of an exception.
        /// </summary>
        /// <returns>The desired random variate. The distribution depends on this object's internal
        /// data.</returns>
        ///
        /// <exception cref="ArgumentException">Thrown if the parameters are inappropriate
        /// for the distribution.</exception>
        /// <exception cref="InvalidOperationException">Thrown if the distribution is
        /// invalid.</exception>
        internal double draw()
        {
            switch (dist)
            {
            case Distribution.Uniform:
                return(RandomDist.drawUniform(min, max));

            case Distribution.LogUniform:
                return(RandomDist.drawLogUniform(min, max));

            case Distribution.Gaussian:
            case Distribution.Normal:
                return(RandomDist.drawNormal(avg, stdDev));

            case Distribution.LogNormal:
                if (avg <= 0.0)
                {
                    throw new ArgumentException(
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorLogNormMean", avg));
                }
                if (stdDev <= 0.0)
                {
                    throw new ArgumentException(
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorLogNormStd", stdDev));
                }
                double quad  = Math.Sqrt(avg * avg + stdDev * stdDev);
                double mu    = Math.Log(avg * avg / quad);
                double sigma = Math.Sqrt(2 * Math.Log(quad / avg));
                return(RandomDist.drawLognormal(mu, sigma));

            case Distribution.Rayleigh:
                return(RandomDist.drawRayleigh(avg * Math.Sqrt(2.0 / Math.PI)));

            case Distribution.Exponential:
                return(RandomDist.drawExponential(avg));

            case Distribution.Gamma:
                if (avg <= 0.0)
                {
                    throw new ArgumentException(
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorGammaMean", avg));
                }
                if (stdDev <= 0.0)
                {
                    throw new ArgumentException(
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorGammaStd", stdDev));
                }
                double k = (avg / stdDev);
                k = k * k;
                double theta = stdDev * stdDev / avg;
                return(RandomDist.drawGamma(k, theta));

            case Distribution.Beta:
                if (avg <= min || avg >= max)
                {
                    throw new ArgumentException(
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorBetaMean", min, avg, max));
                }
                if (stdDev <= 0.0)
                {
                    throw new ArgumentException(
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorBetaStd", stdDev));
                }
                double scaledMean   = (avg - min) / (max - min);
                double scaledStdDev = stdDev / (max - min);
                double scaledVar    = scaledStdDev * scaledStdDev;
                double factor       = (scaledMean - scaledMean * scaledMean - scaledVar) / scaledVar;
                double alpha        = scaledMean * factor;
                double beta         = (1.0 - scaledMean) * factor;
                return(min + (max - min) * RandomDist.drawBeta(alpha, beta));

            case Distribution.Isotropic:
                return(RandomDist.drawIsotropic());

            default:
                throw new InvalidOperationException(
                          Localizer.Format("#autoLOC_CustomAsteroids_ErrorBadDistribution", dist));
            }
        }
示例#10
0
 public UntrackedObjectClass drawAsteroidSize()
 {
     // Asteroids appear to be hardcoded to be from size A to E, even though there are more classes now
     return((UntrackedObjectClass)(int)
            (stockSizeCurve.Evaluate((float)RandomDist.drawUniform(0.0, 1.0)) * 5));
 }