Esempio n. 1
0
    /// <summary>
    /// Generates a new set of precipitation and snowfall map images.
    /// </summary>
    /// <param name="planet">The planet being mapped.</param>
    /// <param name="winterTemperatures">A winter temperature map.</param>
    /// <param name="summerTemperatues">A summer temperature map.</param>
    /// <param name="resolution">The vertical resolution.</param>
    /// <param name="steps">
    /// The number of maps to generate internally (representing evenly spaced "seasons" during a year,
    /// starting and ending at the winter solstice in the northern hemisphere).
    /// </param>
    /// <param name="temperatureProjection">
    /// <para>
    /// The map projection of the temperature maps. They must be the same.
    /// </para>
    /// <para>
    /// If left <see langword="null"/> an equirectangular projection of the full globe is
    /// assumed.
    /// </para>
    /// </param>
    /// <param name="projection">
    /// <para>
    /// The map projection options used.
    /// </para>
    /// <para>
    /// If left <see langword="null"/> an equirectangular projection of the full globe is
    /// produced.
    /// </para>
    /// </param>
    /// <returns>
    /// A set of precipitation and snowfall map images. Pixel luminosity indicates
    /// precipitation in mm/hr, relative to the <see cref="Atmosphere.MaxPrecipitation"/> of
    /// this planet's <see cref="Atmosphere"/>.
    /// </returns>
    public static (Image <L16>[] precipitationMaps, Image <L16>[] snowfallMaps) GetPrecipitationAndSnowfallMaps(
        this Planetoid planet,
        Image <L16> winterTemperatures,
        Image <L16> summerTemperatues,
        int resolution,
        int steps,
        MapProjectionOptions?temperatureProjection = null,
        MapProjectionOptions?projection            = null)
    {
        var options           = projection ?? MapProjectionOptions.Default;
        var precipitationMaps = new Image <L16> [steps];
        var snowMaps          = new Image <L16> [steps];

        if (planet.Atmosphere.MaxPrecipitation.IsNearlyZero())
        {
            var xResolution = (int)Math.Floor(resolution * options.AspectRatio);
            for (var i = 0; i < steps; i++)
            {
                precipitationMaps[i] = new Image <L16>(xResolution, resolution);
                snowMaps[i]          = new Image <L16>(xResolution, resolution);
            }
            return(precipitationMaps, snowMaps);
        }

        var noise1 = new FastNoise(planet.Seed4, 1.0, FastNoise.NoiseType.Simplex);
        var noise2 = new FastNoise(planet.Seed5, 3.0, FastNoise.NoiseType.SimplexFractal, octaves: 3);

        var proportionOfYear           = 1f / steps;
        var proportionOfYearAtMidpoint = 0f;
        var trueAnomaly          = planet.WinterSolsticeTrueAnomaly;
        var trueAnomalyPerSeason = DoubleConstants.TwoPi / steps;

        for (var i = 0; i < steps; i++)
        {
            var solarDeclination = planet.GetSolarDeclination(trueAnomaly);
            (precipitationMaps[i], snowMaps[i]) = SurfaceMapImage.GenerateMapImages(
                new[] { winterTemperatures, summerTemperatues },
                (lat, lon, temperature) =>
            {
                var precipitation = planet.GetPrecipitationNoise(
                    noise1,
                    noise2,
                    planet.LatitudeAndLongitudeToDoubleVector(lat, lon),
                    lat,
                    Planetoid.GetSeasonalLatitudeFromDeclination(lat, solarDeclination),
                    temperature * SurfaceMapImage.TemperatureScaleFactor,
                    out var snow);
                return(
                    precipitation / planet.Atmosphere.MaxPrecipitation,
                    snow / planet.Atmosphere.MaxSnowfall);
            },