Exemple #1
0
        static public void ApplyNoiseToSphere(SurfaceMap sphereLayer, Vector3Int center)
        {
            foreach (int contourPoint in sphereLayer.contour3D)
            {
                Vector3Int contourStartPoint = new Vector3Int(contourPoint % sphereLayer.resolution,
                                                              (contourPoint / sphereLayer.resolution) % sphereLayer.resolution,
                                                              contourPoint / sphereLayer.resolution2);
                Vector3 direction = contourStartPoint - center;
                direction = direction.normalized;

                Vector3    contourEndPointF = (contourStartPoint + direction * NoiseSettings.noiseMethod(contourStartPoint, NoiseSettings.frequency) * NoiseSettings.gain);
                Vector3Int contourEndPoint  = new Vector3Int(Mathf.RoundToInt(contourEndPointF.x),
                                                             Mathf.RoundToInt(contourEndPointF.y),
                                                             Mathf.RoundToInt(contourEndPointF.z));

                Cylinder(sphereLayer, contourStartPoint, contourEndPoint, 1,
                         sphereLayer.ReadMaterial(contourStartPoint.x, contourStartPoint.y, contourStartPoint.z));
            }
            Vector3Int point = new Vector3Int(sphereLayer.contour3D[0] % sphereLayer.resolution,
                                              (sphereLayer.contour3D[0] / sphereLayer.resolution) % sphereLayer.resolution,
                                              sphereLayer.contour3D[0] / sphereLayer.resolution2);

            Sphere(sphereLayer, center,
                   (int)((point - center).magnitude),
                   (int)((point - center).magnitude + 1),
                   /*sphereLayer.ReadMaterial(point.x, point.y, point.z)*/ 1,
                   false);
        }
Exemple #2
0
        /// <summary>
        /// <para>Draw a cylinder between p1 & p2</para>
        /// <para>Mode: 0 - overlay, 1 - add, 2 - inverse</para>
        /// </summary>
        static public void Cylinder(SurfaceMap surfaceMap, Vector3Int p1, Vector3Int p2, int radius, int material)
        {
            if (p1.x < 0 || p1.x >= surfaceMap.resolution || p1.y < 0 || p1.y >= surfaceMap.resolution || p1.z < 0 || p1.z >= surfaceMap.resolution)
            {
                throw new Exception("p1OutOfBounds");
            }
            if (p2.x < 0 || p2.x >= surfaceMap.resolution || p2.y < 0 || p2.y >= surfaceMap.resolution || p2.z < 0 || p2.z >= surfaceMap.resolution)
            {
                throw new Exception("p2OutOfBounds");
            }

            float      distance = Vector3Int.Distance(p1, p2);
            Quaternion rotation = Quaternion.FromToRotation(new Vector3Int(1, 0, 0), p2 - p1);

            for (int x = 0; x < distance; x++)
            {
                for (int z = -radius; z <= radius; z++)
                {
                    for (int y = -radius; y <= radius; y++)
                    {
                        if (Mathf.Pow(y, 2) + Mathf.Pow(z, 2) <= radius * radius)
                        {
                            //dodać mody
                            Vector3Int pointOnCylinder = Vector3Int.RoundToInt(rotation * new Vector3(x, y, z));
                            surfaceMap.SetMaterial(p1.x + pointOnCylinder.x, p1.y + pointOnCylinder.y, p1.z + pointOnCylinder.z, material);
                            surfaceMap.SetMaterial(p1.x + pointOnCylinder.x + 1, p1.y + pointOnCylinder.y + 1, p1.z + pointOnCylinder.z + 1, material);
                        }
                    }
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// <para>Draw a sphere from center to radius</para>
        /// </summary>
        static public void Sphere(SurfaceMap surfaceMap, Vector3Int center, int radius, int material, bool contour)
        {
            if (center.x < 0 || center.y < 0 || center.z < 0)
            {
                throw new Exception("PointBelowZero");
            }
            if (center.x >= surfaceMap.resolution || center.y >= surfaceMap.resolution || center.z >= surfaceMap.resolution)
            {
                throw new Exception("PointAboweResolution");
            }

            int radius2 = radius * radius;

            for (int z = center.z - radius; z <= center.z + radius && z < surfaceMap.resolution; z++)
            {
                if (z < 0)
                {
                    z = 0;
                }
                for (int y = center.y - radius; y <= center.y + radius && y < surfaceMap.resolution; y++)
                {
                    if (y < 0)
                    {
                        y = 0;
                    }
                    for (int x = center.x - radius; x <= center.x + radius && x < surfaceMap.resolution; x++)
                    {
                        if (x < 0)
                        {
                            x = 0;
                        }
                        int pointOnSphere = (int)(Mathf.Pow(x - center.x, 2) + Mathf.Pow(y - center.y, 2) + Mathf.Pow(z - center.z, 2));
                        if (pointOnSphere <= radius2)
                        {
                            surfaceMap.SetBiome(x, y, z, 1);
                            surfaceMap.SetMaterial(x, y, z, material);

                            if (contour && (
                                    (int)(Mathf.Pow(x - center.x + 1, 2) + Mathf.Pow(y - center.y, 2) + Mathf.Pow(z - center.z, 2)) > radius2 ||
                                    (int)(Mathf.Pow(x - center.x, 2) + Mathf.Pow(y - center.y + 1, 2) + Mathf.Pow(z - center.z, 2)) > radius2 ||
                                    (int)(Mathf.Pow(x - center.x, 2) + Mathf.Pow(y - center.y, 2) + Mathf.Pow(z - center.z + 1, 2)) > radius2 ||
                                    (int)(Mathf.Pow(x - center.x - 1, 2) + Mathf.Pow(y - center.y, 2) + Mathf.Pow(z - center.z, 2)) > radius2 ||
                                    (int)(Mathf.Pow(x - center.x, 2) + Mathf.Pow(y - center.y - 1, 2) + Mathf.Pow(z - center.z, 2)) > radius2 ||
                                    (int)(Mathf.Pow(x - center.x, 2) + Mathf.Pow(y - center.y, 2) + Mathf.Pow(z - center.z - 1, 2)) > radius2 ||
                                    x == 0 || x == surfaceMap.resolution - 1 ||
                                    y == 0 || y == surfaceMap.resolution - 1 ||
                                    z == 0 || y == surfaceMap.resolution - 1)
                                )
                            {
                                surfaceMap.SetContour(x, y, z);
                            }
                        }
                        //else surfaceMap.SetMaterial(x, y, z, 0);
                    }
                }
            }
        }
Exemple #4
0
 /// <summary>
 /// Calculates the approximate area of a point on a map projection with the given
 /// characteristics, by transforming the point and its nearest neighbors to latitude and
 /// longitude, calculating the midpoints between them, and calculating the area of the
 /// region enclosed within those midpoints.
 /// </summary>
 /// <param name="region">The mapped region.</param>
 /// <param name="planet">The mapped planet.</param>
 /// <param name="x">The x coordinate of a point on a map projection, with zero as the
 /// westernmost point.</param>
 /// <param name="y">The y coordinate of a point on a map projection, with zero as the
 /// northernmost point.</param>
 /// <param name="resolution">The vertical resolution of the projection.</param>
 /// <param name="options">
 /// The map projection options used to generate the map used.
 /// </param>
 /// <returns>The area of the given point, in m².</returns>
 public static HugeNumber GetAreaOfLocalPoint(
     this SurfaceRegion region,
     Planetoid planet,
     int x, int y,
     int resolution,
     MapProjectionOptions options) => SurfaceMap.GetAreaOfPointFromRadiusSquared(
     planet.RadiusSquared,
     x, y,
     (int)Math.Floor(resolution * options.AspectRatio),
     resolution,
     region.GetProjection(planet, options.EqualArea));
            public static DunesDescription CreateFromPlacement(Point origin, int width, int height)
            {
                Rectangle area = new Rectangle(origin.X - width / 2, origin.Y - height / 2, width, height);

                return(new DunesDescription
                {
                    Area = area,
                    IsValid = true,
                    Surface = SurfaceMap.FromArea(area.Left - 20, area.Width + 40),
                    WindDirection = ((WorldGen.genRand.Next(2) != 0) ? WindDirection.Right : WindDirection.Left)
                });
            }
Exemple #6
0
        /// <summary>
        /// <para>Draw a straight line between p1 & p2</para>
        /// <para>Mode: 0 - overlay, 1 - add, 2 - inverse</para>
        /// </summary>
        static public void Line(SurfaceMap surfaceMap, Vector3Int p1, Vector3Int p2, int width, int material, bool contour, int mode)
        {
            if (p1.x < 0 || p1.x >= surfaceMap.resolution || p1.y < 0 || p1.y >= surfaceMap.resolution || p1.z < 0 || p1.z >= surfaceMap.resolution)
            {
                throw new Exception("p1OutOfBounds");
            }
            if (p2.x < 0 || p2.x >= surfaceMap.resolution || p2.y < 0 || p2.y >= surfaceMap.resolution || p2.z < 0 || p2.z >= surfaceMap.resolution)
            {
                throw new Exception("p2OutOfBounds");
            }
            if (mode < 0 || mode > 2)
            {
                throw new Exception("InvalidMode");
            }

            if (Vector3Int.Distance(Vector3Int.zero, p1) > Vector3Int.Distance(Vector3Int.zero, p2))
            {
                Vector3Int tmp = p2;
                p2 = p1;
                p1 = tmp;
            }

            Vector3Int direction = p2 - p1;
            int        x, y, z;

            for (float t = 0.0f; t <= 1.0f; t = t + (1.0f / (2 * Vector3.Distance(p1, p2))))
            {
                int offset    = 0;
                int widthCopy = width;
                while (widthCopy > 0)
                {
                    if (width % 2 == 1)
                    {
                        x = p1.x + offset + (int)(direction.x * t);
                        y = p1.y + offset + (int)(direction.y * t);
                        z = p1.z + offset + (int)(direction.z * t);
                    }
                    else
                    {
                        x = p1.x - offset + (int)(direction.x * t);
                        y = p1.y - offset + (int)(direction.y * t);
                        z = p1.z - offset + (int)(direction.z * t);
                    }
                    offset++;
                    widthCopy--;
                    surfaceMap.SetMaterial(x, y, z, material);
                    if (contour)
                    {
                        surfaceMap.SetContour(x, y, z);
                    }
                }
            }
        }
Exemple #7
0
 public static DunesBiome.DunesDescription CreateFromPlacement(
     Point origin,
     int width,
     int height)
 {
     Microsoft.Xna.Framework.Rectangle rectangle = new Microsoft.Xna.Framework.Rectangle(origin.X - width / 2, origin.Y - height / 2, width, height);
     return(new DunesBiome.DunesDescription()
     {
         Area = rectangle,
         IsValid = true,
         Surface = SurfaceMap.FromArea(rectangle.Left - 20, rectangle.Width + 40),
         WindDirection = WorldGen.genRand.Next(2) == 0 ? DunesBiome.WindDirection.Left : DunesBiome.WindDirection.Right
     });
 }
Exemple #8
0
 /// <summary>
 /// Determines whether the given proportion of the year falls within the range indicated for
 /// a <paramref name="position"/> in a <paramref name="region"/>.
 /// </summary>
 /// <param name="region">The mapped region.</param>
 /// <param name="planet">The mapped planet.</param>
 /// <param name="position">A position relative to the center of <paramref
 /// name="region"/>.</param>
 /// <param name="ranges">A set of ranges.</param>
 /// <param name="proportionOfYear">
 /// The proportion of the year, starting and ending with midwinter, at which the calculation
 /// is to be performed.
 /// </param>
 /// <param name="equalArea">
 /// If <see langword="true"/> the projection will be a cylindrical equal-area projection.
 /// Otherwise, an equirectangular projection will be used.
 /// </param>
 /// <returns><see langword="true"/> if the given proportion of the year falls within the
 /// range indicated for a <paramref name="position"/> in a <paramref name="region"/>;
 /// otherwise <see langword="false"/>.</returns>
 public static bool GetAnnualRangeIsPositiveAtTimeAndLocalPosition(
     this SurfaceRegion region,
     Planetoid planet,
     Vector3 position,
     FloatRange[,] ranges,
     float proportionOfYear,
     bool equalArea = false)
 {
     var(x, y) = region.GetProjectionFromLocalPosition(
         planet,
         position,
         ranges.GetLength(0),
         ranges.GetLength(1),
         equalArea);
     return(SurfaceMap.GetAnnualRangeIsPositiveAtTime(ranges[x, y], proportionOfYear));
 }
Exemple #9
0
    /// <summary>
    /// <para>Merge layer top with bottom</para>
    /// <para>Mode: 0 - overlay, 1 - add, 2 - inverse</para>
    /// </summary>
    public static void MergeMaterialLayers(SurfaceMap bottom, SurfaceMap top, int mode)
    {
        if (mode < 0 || mode > 2)
        {
            throw new Exception("InvalidMode");
        }

        for (int i = 0; i < Mathf.Pow(bottom.resolution, 3); i++)
        {
            switch (mode)
            {
            case 0:
                bottom.map3D[i] = (byte)((bottom.map3D[i] & 0xF0) | (top.map3D[i] & 0x0F));
                break;

            case 1:
                if ((bottom.map3D[i] & 0x0F) == 0)
                {
                    bottom.map3D[i] = (byte)((bottom.map3D[i] & 0xF0) | (top.map3D[i] & 0x0F));
                }
                break;

            case 2:
                if ((bottom.map3D[i] & 0x0F) != 0)
                {
                    bottom.map3D[i] = (byte)(bottom.map3D[i] & 0xF0);
                }
                else
                {
                    bottom.map3D[i] = (byte)((bottom.map3D[i] & 0xF0) | (top.map3D[i] & 0x0F));
                }
                break;
            }
        }

        bottom.contour3D.Clear();
        for (int i = 0; i < top.contour3D.Count; i++)
        {
            bottom.contour3D.Add(top.contour3D[i]);
        }
    }
Exemple #10
0
    private void Awake()
    {
        resolution = chunkGridResolution * chunksMultiplier * isoMultiplier;
        Vector3Int center = new Vector3Int(resolution / 2,
                                           resolution / 2,
                                           resolution / 2);

        surfaceMap = new SurfaceMap(resolution);
        SurfaceMap layer1 = new SurfaceMap(resolution);

        DrawSurface.Sphere(layer1, center, radius, 3, true);
        DrawSurface.NoiseSettings.lacunarity  = 1;
        DrawSurface.NoiseSettings.persistance = 0;
        DrawSurface.NoiseSettings.octaves     = 1;
        DrawSurface.NoiseSettings.frequency   = 3;
        DrawSurface.NoiseSettings.gain        = 5;
        DrawSurface.ApplyNoiseToSphere(layer1, center);
        SurfaceMap.MergeMaterialLayers(surfaceMap, layer1, 1);

        //SurfaceMap.MergeMaterialLayers(surfaceMap, layer1, 0);
        //DrawSurface.Cylinder(surfaceMap, new Vector3Int(7, 7, 7), new Vector3Int(13, 13, 10), 6, 2, 0);

        /*//DrawSurface.Line(layer1, new Vector3Int(1, 0, 0), new Vector3Int(1, 5, 0), 2, 1, false, 0);
         *
         * DrawSurface.NoiseSettings.lacunarity = 1;
         * DrawSurface.NoiseSettings.persistance = 0;
         * DrawSurface.NoiseSettings.octaves = 1;
         * DrawSurface.NoiseSettings.frequency = 1;
         * DrawSurface.NoiseSettings.gain = 20;
         * DrawSurface.ApplyNoiseToSphere(layer1, center);
         * SurfaceMap.MergeMaterialLayers(surfaceMap, layer1, 1);*/
        voxelMap.size            = size;
        voxelMap.chunkResolution = chunksMultiplier;
        voxelMap.voxelResolution = chunkGridResolution;
        voxelMapObject           = Instantiate <VoxelMap>(voxelMap, position, rotation);
        Refresh();
    }
    /// <summary>
    /// Initializes a new instance of <see cref="WeatherMaps"/>.
    /// </summary>
    /// <param name="planet">The planet being mapped.</param>
    /// <param name="elevationMap">An elevation map.</param>
    /// <param name="winterTemperatureMap">A winter temperature map.</param>
    /// <param name="summerTemperatureMap">A summer temperature map.</param>
    /// <param name="precipitationMap">A precipitation map.</param>
    /// <param name="resolution">The intended vertical resolution of the maps.</param>
    /// <param name="options">
    /// The map projection options to use. All the map images must have been generated using
    /// these same options, or thew results will not be accurate.
    /// </param>
    public WeatherMaps(
        Planetoid planet,
        Image <L16> elevationMap,
        Image <L16> winterTemperatureMap,
        Image <L16> summerTemperatureMap,
        Image <L16> precipitationMap,
        int resolution,
        MapProjectionOptions?options = null)
    {
        var projection = options ?? MapProjectionOptions.Default;

        XLength = (int)Math.Floor(projection.AspectRatio * resolution);
        YLength = resolution;

        BiomeMap   = new BiomeType[XLength][];
        ClimateMap = new ClimateType[XLength][];
        var humidityMap = new HumidityType[XLength][];

        SeaIceRangeMap = new FloatRange[XLength][];

        for (var x = 0; x < XLength; x++)
        {
            BiomeMap[x]       = new BiomeType[YLength];
            ClimateMap[x]     = new ClimateType[YLength];
            humidityMap[x]    = new HumidityType[YLength];
            SeaIceRangeMap[x] = new FloatRange[YLength];
        }

        var scale          = SurfaceMap.GetScale(resolution, projection.Range);
        var stretch        = scale / projection.ScaleFactor;
        var elevationScale = SurfaceMap.GetScale(elevationMap.Height, projection.Range);
        var winterScale    = winterTemperatureMap.Height == elevationMap.Height
            ? elevationScale
            : SurfaceMap.GetScale(winterTemperatureMap.Height, projection.Range);
        var summerScale = summerTemperatureMap.Height == elevationMap.Height
            ? elevationScale
            : SurfaceMap.GetScale(summerTemperatureMap.Height, projection.Range);
        var precipitationScale = precipitationMap.Height == elevationMap.Height
            ? elevationScale
            : SurfaceMap.GetScale(precipitationMap.Height, projection.Range);

        var totalElevation    = 0.0;
        var minTemperature    = 5000.0f;
        var maxTemperature    = 0.0f;
        var totalTemperature  = 0.0f;
        var totalPrecipiation = 0.0;
        var xToEX             = new Dictionary <int, int>();
        var xToWX             = new Dictionary <int, int>();
        var xToSX             = new Dictionary <int, int>();
        var xToPX             = new Dictionary <int, int>();

        for (var y = 0; y < YLength; y++)
        {
            var latitude = projection.EqualArea
                ? SurfaceMap.GetLatitudeOfCylindricalEqualAreaProjection(y, resolution, scale, projection)
                : SurfaceMap.GetLatitudeOfEquirectangularProjection(y, resolution, scale, projection);

            var elevationY = projection.EqualArea
                ? SurfaceMap.GetCylindricalEqualAreaYFromLatWithScale(latitude, elevationMap.Height, elevationScale, projection)
                : SurfaceMap.GetEquirectangularYFromLatWithScale(latitude, elevationMap.Height, elevationScale, projection);
            var elevationSpan = elevationMap.GetPixelRowSpan(elevationY);

            int winterY;
            if (winterTemperatureMap.Height == elevationMap.Height)
            {
                winterY = elevationY;
            }
            else if (projection.EqualArea)
            {
                winterY = SurfaceMap.GetCylindricalEqualAreaYFromLatWithScale(latitude, winterTemperatureMap.Height, winterScale, projection);
            }
            else
            {
                winterY = SurfaceMap.GetEquirectangularYFromLatWithScale(latitude, winterTemperatureMap.Height, winterScale, projection);
            }

            var winterSpan = winterTemperatureMap.GetPixelRowSpan(winterY);

            int summerY;
            if (summerTemperatureMap.Height == elevationMap.Height)
            {
                summerY = elevationY;
            }
            else if (projection.EqualArea)
            {
                summerY = SurfaceMap.GetCylindricalEqualAreaYFromLatWithScale(latitude, summerTemperatureMap.Height, summerScale, projection);
            }
            else
            {
                summerY = SurfaceMap.GetEquirectangularYFromLatWithScale(latitude, summerTemperatureMap.Height, summerScale, projection);
            }

            var summerSpan = summerTemperatureMap.GetPixelRowSpan(summerY);

            int precipitationY;
            if (precipitationMap.Height == elevationMap.Height)
            {
                precipitationY = elevationY;
            }
            else if (projection.EqualArea)
            {
                precipitationY = SurfaceMap.GetCylindricalEqualAreaYFromLatWithScale(latitude, precipitationMap.Height, precipitationScale, projection);
            }
            else
            {
                precipitationY = SurfaceMap.GetEquirectangularYFromLatWithScale(latitude, precipitationMap.Height, precipitationScale, projection);
            }

            var precipitationSpan = precipitationMap.GetPixelRowSpan(precipitationY);

            for (var x = 0; x < XLength; x++)
            {
                if (!xToEX.TryGetValue(x, out var elevationX))
                {
                    var longitude = projection.EqualArea
                        ? SurfaceMap.GetLongitudeOfCylindricalEqualAreaProjection(x, XLength, scale, projection)
                        : SurfaceMap.GetLongitudeOfEquirectangularProjection(x, XLength, stretch, projection);

                    elevationX = projection.EqualArea
                        ? SurfaceMap.GetCylindricalEqualAreaXFromLonWithScale(longitude, elevationMap.Width, elevationScale, projection)
                        : SurfaceMap.GetEquirectangularXFromLonWithScale(longitude, elevationMap.Width, elevationScale, projection);
                    int wX;
                    if (winterTemperatureMap.Width == elevationMap.Width)
                    {
                        wX = elevationX;
                    }
                    else if (projection.EqualArea)
                    {
                        wX = SurfaceMap.GetCylindricalEqualAreaXFromLonWithScale(longitude, winterTemperatureMap.Width, winterScale, projection);
                    }
                    else
                    {
                        wX = SurfaceMap.GetEquirectangularXFromLonWithScale(longitude, winterTemperatureMap.Width, winterScale, projection);
                    }

                    int sX;
                    if (summerTemperatureMap.Width == elevationMap.Width)
                    {
                        sX = elevationX;
                    }
                    else if (projection.EqualArea)
                    {
                        sX = SurfaceMap.GetCylindricalEqualAreaXFromLonWithScale(longitude, summerTemperatureMap.Width, summerScale, projection);
                    }
                    else
                    {
                        sX = SurfaceMap.GetEquirectangularXFromLonWithScale(longitude, summerTemperatureMap.Width, summerScale, projection);
                    }

                    int pX;
                    if (precipitationMap.Width == elevationMap.Width)
                    {
                        pX = elevationX;
                    }
                    else if (projection.EqualArea)
                    {
                        pX = SurfaceMap.GetCylindricalEqualAreaXFromLonWithScale(longitude, precipitationMap.Width, precipitationScale, projection);
                    }
                    else
                    {
                        pX = SurfaceMap.GetEquirectangularXFromLonWithScale(longitude, precipitationMap.Width, precipitationScale, projection);
                    }

                    xToEX.Add(x, elevationX);
                    xToWX.Add(x, wX);
                    xToSX.Add(x, sX);
                    xToPX.Add(x, pX);
                }
                var winterX        = xToWX[x];
                var summerX        = xToSX[x];
                var precipitationX = xToPX[x];

                var normalizedElevation = elevationSpan[elevationX].GetValueFromPixel_PosNeg() - planet.NormalizedSeaLevel;
                totalElevation += normalizedElevation;

                var winterTemperature = (float)(winterSpan[winterX].GetValueFromPixel_Pos() * SurfaceMapImage.TemperatureScaleFactor);
                var summerTemperature = (float)(summerSpan[summerX].GetValueFromPixel_Pos() * SurfaceMapImage.TemperatureScaleFactor);
                minTemperature    = Math.Min(minTemperature, Math.Min(winterTemperature, summerTemperature));
                maxTemperature    = Math.Max(maxTemperature, Math.Max(winterTemperature, summerTemperature));
                totalTemperature += (minTemperature + maxTemperature) / 2;

                var precipValue   = precipitationSpan[precipitationX].GetValueFromPixel_Pos();
                var precipitation = precipValue * planet.Atmosphere.MaxPrecipitation;
                totalPrecipiation += precipValue;

                ClimateMap[x][y] = Universe.Climate.Climate.GetClimateType(new FloatRange(
                                                                               Math.Min(winterTemperature, summerTemperature),
                                                                               Math.Max(winterTemperature, summerTemperature)));
                humidityMap[x][y] = Universe.Climate.Climate.GetHumidityType(precipitation);
                BiomeMap[x][y]    = Universe.Climate.Climate.GetBiomeType(ClimateMap[x][y], humidityMap[x][y], normalizedElevation);

                if (normalizedElevation > 0 ||
                    (summerTemperature >= Substances.All.Seawater.MeltingPoint &&
                     winterTemperature >= Substances.All.Seawater.MeltingPoint))
                {
                    continue;
                }

                if (summerTemperature < Substances.All.Seawater.MeltingPoint &&
                    winterTemperature < Substances.All.Seawater.MeltingPoint)
                {
                    SeaIceRangeMap[x][y] = FloatRange.ZeroToOne;
                    continue;
                }

                var freezeProportion = ((summerTemperature >= winterTemperature
                    ? winterTemperature.InverseLerp(summerTemperature, (float)(Substances.All.Seawater.MeltingPoint ?? 0))
                    : summerTemperature.InverseLerp(winterTemperature, (float)(Substances.All.Seawater.MeltingPoint ?? 0))) * 0.8f) - 0.1f;
                if (freezeProportion <= 0 ||
                    float.IsNaN(freezeProportion))
                {
                    continue;
                }

                var freezeStart   = 1 - (freezeProportion / 4);
                var iceMeltFinish = freezeProportion * 3 / 4;
                if (latitude < 0)
                {
                    freezeStart += 0.5f;
                    if (freezeStart > 1)
                    {
                        freezeStart--;
                    }

                    iceMeltFinish += 0.5f;
                    if (iceMeltFinish > 1)
                    {
                        iceMeltFinish--;
                    }
                }
                SeaIceRangeMap[x][y] = new FloatRange(freezeStart, iceMeltFinish);
            }
        }

        Climate = Universe.Climate.Climate.GetClimateType(new FloatRange(minTemperature, totalTemperature / (XLength * YLength), maxTemperature));
        var humidity = Universe.Climate.Climate.GetHumidityType(totalPrecipiation / (XLength * YLength) * planet.Atmosphere.MaxPrecipitation);

        Biome = Universe.Climate.Climate.GetBiomeType(Climate, humidity, totalElevation / (XLength * YLength) * planet.MaxElevation);
    }
 /// <summary>
 /// Determines whether the given <paramref name="moment"/> falls within the range indicated.
 /// </summary>
 /// <param name="planet">The mapped planet.</param>
 /// <param name="range">The range being interpolated.</param>
 /// <param name="moment">The time at which the determination is to be performed.</param>
 /// <returns><see langword="true"/> if the range indicates a positive result for the given
 /// <paramref name="moment"/>; otherwise <see langword="false"/>.</returns>
 public static bool GetAnnualRangeIsPositiveAtTime(
     this Planetoid planet,
     FloatRange range,
     Instant moment) => SurfaceMap.GetAnnualRangeIsPositiveAtTime(range, (float)planet.GetProportionOfYearAtTime(moment));