Thursday, September 29, 2016

Shapely land masses

The initial continent shape shown in yesterday's post was simply a circle.  This evening I enhanced code to generate a very irregular polygons that make a decent stand-in for an island or continent.  The irregularity is formed by creating a basic polygon, then applying several iterations of two-dimensional midpoint displacement to the line segments.  The two shapes in the images below started as four-sided convex polygons.

An island or continent.

Another island or continent


The code for the midpoint displacement is fairly simple, and is shown below.  The images were originally generated at a resolution of 1024 x 512.  Six iterations of midpoint displacement were applied, with an initial maxDisplacement value of 70; by the sixth iteration this would have been reduced to a maxDisplacement of only 2 pixels.

/// <summary>
/// Performs midpoint displacement upon each line segment that
/// makes up the polyon.  When multiple iterations are requested,
/// maxDisplacement is halved at each iteration.
/// </summary>
/// <param name="iterations">number of iterations of midpoint displacement to apply</param>
/// <param name="maxDisplacement">number of pixels a midpoint may be displaced by</param>
/// <param name="rand">optional pseudo-random number generator (PRNG) instance to use;
/// supplying an instance of a PRNG can be used as part of a strategy to
/// allow deterministic results based upon the seed used</param>

public void MidpointDisplace(int iterations,
    int maxDisplacement = 10, Random rand = null)
{
    if (rand == null) rand = new Random();
    for (int i = 0; i < iterations; i++)
    {
        int numPoints = Vertices.Count;
        int k = numPoints - 1;
        int j = 0;
        while (j < Vertices.Count)
        {
            Point p1 = Vertices[j];
            Point p2 = Vertices[k];
            int mx = (p1.X + p2.X) / 2;
            int my = (p1.Y + p2.Y) / 2;
            mx += rand.Next(0, 2 * maxDisplacement) - maxDisplacement;
            my += rand.Next(0, 2 * maxDisplacement) - maxDisplacement;
            Vertices.Insert(j, new Point { X = mx, Y = my });
            k = j + 1;                  
            j += 2;
        }
        maxDisplacement /= 2;
        if (maxDisplacement < 1) break;
    }
}


I still have more work to do to implement the "step 3" from yesterday's post.  As it is, the easternmost and westernmost continents are shifted, but any others are left where they are.  They should also move, either colliding with the other plates or moving into clear space.  That should then be sufficient to use as input for an Experilous-style planet generator to generate a more desirable set of initial land masses.

The red continent reminds me of the southern portion of South America.


No comments:

Post a Comment