Smoking GRASS

Today on the Astrographer, we’re going to look at a workflow using only free tools that are available for the Apple Macintosh platform. Almost all of these tools are available for any unix-based platform and most are available for windows as well.

By the end of this tutorial, we will have created an initial set of basic raster heightfields successfully georeferenced, scaled and imported into GRASS GIS(GRASS). We will also have a vector dataset(shapefile) representing the shorelines as generated. Later on, this data will be used in gplates to create an approximate geological history of the world which will be useful in “realistically” editing the elevations.

Since we’re starting from the ground floor, we need to generate a heightfield image to represent the elevations of our planet’s surface. Our needs here aren’t too stringent since down the line we’ll be editing  the heck out of this thing.

There are many options for noise-based generators. I’ve had good results using the Flaming Pear LunarCell filter on Photoshop, Torben Mogensen’s “Planet” and the still useful planetGenesis.

LunarCell is actually pretty attractive and easy to use, but it isn’t free and its requires Photoshop, so it fails to meet the requirements of the project(I use Photoshop to prepare the images for this web page, but none of the work I describe in the tutorial will require it). Planet is also excellent for the purpose, and it is quite free both in the sense of speech and beer. I have, however, covered Planet in some detail in the past , so in the interests of variety I think its worthwhile to introduce planetGenesis. I should, in the interest of transparency, note that I, myself, have made some minor contributions to the planetGenesis open source project(implementing perlin simplex noise, the somewhat successful Modified Multifractal Noise node, and the Range function among other small things). I don’t have any pecuniary interest in the project, but it is a source of pride. Also if I can get an active programmer with more skill than me onto the project, planetGenesis may become more useful to me… One suggestion, rather than downloading pG-1.9 which is available directly, it would be better to grab the CVS version and compile it(Eclipse is a good tool for both purposes). The 1.9 version of planetGenesis is pretty old and there have been some improvements to the codebase, but the principal programmer hasn’t been active in awhile and nobody else can make new releases.

Here is a copy of the graph used to generate the working heightfield. Along the top of the graph are the four noise nodes that are really generating the heightfield.

The planetGenesis graph I am using. [Click on image for closer look]

The planetGenesis graph I am using.
[Click on image for closer look]

Everything else just controls how they go together. Left click on any node to see its parameters in the right-hand panel, double click to open a parameter dialogue if there isn’t a right-hand panel. To create a new node, right click on any blank space in the graph window and select a node type from the popup menu. To link two nodes, simply shift-drag from the red output dot of the source node to the hollow input dot of the target node. The hollow node at the bottom is the image output node required for the program to do anything. This is also where you set the size and type of output.

The simplest way to change the appearance of your heightfield to create a new world is to change the seed values of the four noise nodes. The leftmost noise node generates the mountain texture. The two noise nodes on the far right are multiplied together to generate the overall texture of the surface. The Range function nodes are used to create “soft” masks of various the features. The second noise from the left governs the placement of mountainous areas, constricted by the output of the two noises to the right. The Rough Scale nodes serve to control the relative contribution of various noises to the final heightfield. They are also used to constrain inputs to appropriate

An image of the generated heightfield. The original is much larger at 8k x 4k.

An image of the generated heightfield. The original is much larger at 8k x 4k.

ranges to avoid problems with some mathematical functions like square root. As the name implies Rough Scale is not guaranteed to constrict its output strictly to the range specified. Values are set by constraining a small subset(64×64 pixel) of the input noise. I invite readers to manipulate the parameters of all of the nodes in this graph to see what sort of effects they can get. For those who wish to create their own graphs from whole cloth, I direct the reader to the program’s documentation. It’s elderly and a bit sparse, but it will give you a good start. If any interest is shown, I may provide a more in depth overview of the program.

Now that we have a useful raster, lets import this into the GRASS GIS(GRASS) package.

First thing, we need to reference our raster to a geographic location. This is a global image and, to keep things simple, I’m going to use a geographic or lat-long coordinate system.

We’ll start by creating a world file. This is simply a plaintext file with the same name as the raster file and a special extension(*.pgw for PNG rasters, *.tfw for TIFF rasters or *.jpw for JPEG rasters). Since we’re referencing a file named genesis.png, the world file will be named genesis.pgw.

The format of a world file is fairly simple. The first line is the x-direction size, in world units, of a pixel on our image. In our case, the units are degrees. For a global lat-long image, this value is equal to 360° divided by the width of the image in pixels. The second and third lines describe the rotation of the raster relative to the coordinate system. We’ll leave both of these at zero, thankfully. The fourth line gives the size of a pixel in the y-direction. For this raster, with square pixels, we enter the negative of the first line. These first four lines describe the size(and rotation) of the area covered by the raster, while the next two lines set its position. The fifth line is the longitude of the center of the upper-left pixel. This value is determined by subtracting 180° from one half of the value in the top line. Similarly, the sixth line, which is the latitude of the center of the upper-left pixel, is derived by adding the value on the fourth line to 90°. I have a copy of some template world files here. “template_4k.pgw,” is intended for 4096×2048 global geographic maps, and, “template_8k.pgw,” is intended for 8192×4096 maps like genesis.png. I also have a text file explaining the format with more and maybe more clarity as well as another file which I will explain. The wikipedia article I mentioned earlier may or may not clarify matters, but it does link to a nice little online calculator which will make all of your calculations and return a box of text which you can just paste into your own world file. How cool is that? Now that we have a raster heightfield with a fully defined spatial reference, let’s go smoke some GRASS!

Start by opening GRASS GIS. This will bring up the Grass {version number: I’m using 6.4.3} Startup window. We’re going to create a new location. In the lower right hand corner of the window you will see, “Define new location with…,” and three options. We’ll click the middle button, “EPSG codes.” We’ll name our new location… I don’t know, I’ll call mine, “Astrographer,” I guess…, and we’ll browse around to find our genesis.png file. A bit of research shows that the EPSG code for WGS84 lat-long is 4326. We’ll enter that and click the “Define location” button. This method isn’t going to work well for defining alien planets accurately(unless of course there is already an EPSG code!). Just remember that all distances are proportional to the relative radius or diameter of the planet(radius_planet/radius_Earth or diameter_planet/diameter_Earth) and surface areas are proportional to the square of that( (size_planet/size_Earth)2 ). I’ll work later on figuring out how to set up a location with an arbitrary coordinate system, but for now, lets select the “PERMANENT” mapset in our new location and click “Enter GRASS.”

Now, in the main menu select >File>Import raster map>Multiple formats using GDAL. “Raster file to be imported” will be the one we just made(e.g. genesis.png). Under “Name for output raster map” I would select “InitialElevations.” The elevation range is going to be funky so we’ll probably want to alter that a bit. Plus there will be some manual editing down the line… Just not today!

Since things haven’t worked out all that well so far, I’m going to be cautious. Under the Options tab I will check “Override projection(use location’s projection)” and “Force Lat/Lon maps to fit into geographic coordinates(90N,S; 180E,W).” Oh well, setting up world and projection files will pay off when we start working on QGIS. Click Run.

Now you have a raster in. The region configuration will probably be screwed up, so select >Config>Region>Change region settings from the main menu. In the text entry field labelled, “Set region to match this raster map:” select the InitialElevations we just opened. This will avoid headaches later. Run the tool.

Now I’m going to use r.mapcalculator(>Raster>Map calculator) to create a map with a somewhat saner distribution than the current range of zero to 65,535. I’m going to try something a bit sophisticated here. I decided to set sea level near the 21000 point, the deepest point in the ocean at about -11000m and the highest point at about 8800m.  I do a bit of a trick here. Logical operators return 0 when false and 1 when true, so this formula should apply a multiplier of 0.44 to all values less than 25000 and 0.218 to all values greater than or equal to 25000. With InitialElevations as my “A” raster input and ReducedElevations as my output raster map, and this formula…


… it worked perfectly. Though I wasn’t entirely happy with the where that put my landmasses, the method was great. I’ll probably go back and rework that a bit, but for now, as a proof of concept, it’s good!

So now, prefatory to making a LandMass vector dataset, I’ll create a raster dataset with a value of zero for water and one for land. There’s probably a better way to do this kind of reclassification, but I’m going to use r.mapcalculator again. I’ll use the ReducedElevations raster as my “A” input and LandMass as my output. The formula, this time will be…

A >= 0.0

…and again it works perfectly. Now to create that vector.

On the main menu, select >File>Map type conversions>Raster to vector which opens up the tool. Select the LandMass vector as your input, LandMass_Vector as your output(I know! Imaginative, huh?) and a feature type of “area.” Make sure to check “Smooth corners of area features”(Didn’t do that the first time I ran it, and everything was stairstepped!). Run it.

And now we have generated a raster, loaded it into GRASS and created a vector dataset to delineate land from sea.

Although the work done in GRASS so far is pretty basic, getting information into

So this is what I ended up with.

So this is what I ended up with.

GRASS in the first place is half the battle. Having fought to create properly georeferenced data on imaginary worlds into GRASS for so long, it’s surprising how relatively easy everything else is proving. I’ve been looking up at the tantalizing grapes of this tool’s power for a long time unable to reach them. Now that I’ve reached this point, those grapes aren’t sour at all!

Good hunting!
The Astrographer

This entry was posted in Mapping, World Building and tagged , , , , , , , , , , . Bookmark the permalink.

2 Responses to Smoking GRASS

  1. Realmwright says:

    I like the layout of continents a lot! Gotta love random seed 🙂
    But does this software give you an option/tool to rotate the map projection? For instance,

    I think a very slight adjustment to combine the yellow and blue would better center the map with the long, green continent smack in the middle.

    • Astrographer says:

      Looking at Donjon, it appears to only be capable of rotating the map in the x-axis. This can be readily done in photoshop or gimp with the offset tool, or Wilbur with toroidal rotation.

      If I can figure out the projection settings for grass, this should be doable. Give me a few days, I’ll get on that!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s