As suggested by Realmwright, I’ve decided to rework my last map a little bit. He pointed out that the landmasses would all fit nicely on the map if they were just shifted a little so that the continent that got split in two on either edge of the map could be contiguous. I had noticed this actually. I also observed that this would also avoid issues with the vectorization routine treating that continent as two separate features. However I wasn’t aware of a free or open source way of doing it. Photoshop can readily recenter the map in full 16-bit glory(just select Filter>Other>Offset… from the main window, make sure to click “Wrap Around” for undefined areas and keep vertical offset to zero while adjusting horizontal offset), but not everybody has it, and acquiring it is not cheap(That said, I’d certainly be appreciative of anyone who bought a copy through my Amazon link… Yes we likes the pennies what trickles in!). This can definitely be done using G.Projector or Flex Projector, about which I will surely post later, but I found the process is quick and simple enough to do in Image Magick, so that’s what I’ll demonstrate here.
A quick word of warning, I have changed things up a bit here. I found the previous map’s landforms just a bit too thin and spidery, so I adjusted some of the settings in the planetGenesis graph just a bit and I’m using a somewhat different sea level. I rerendered the map, using the name input.png for the result. I’m doing this in bash shell on unix. It might look a bit different in dos.
I start by rotating the map to recenter the landmasses.
convert input.png -depth 16 -roll -2260 0 work/ground_floor/heightfield.png
The input file is “input.png”, “-depth 16” insures that IM is actually working in 16-bit(not necessarily necessarily, but just to be safe), “-roll -2260 0” tells IM to offset the image(rolling it) by 2260 pixels(~27.6% of image width, or ~99°) to the left, “work/ground_floor/heightfield.png” is the path to the output file. I’ve learned that workspace organization pays off later when you got large numbers of files to keep track of.
The next stage will show me approximately what my land masses look like now.
convert work/ground_floor/heightfield.png -depth 16 -threshold 23130 -depth 8 work/ground_floor/landmask.png
Here, we use the output from the last operation as the input. “-threshold 23130” means that pixels where the 16-bit value is equal to or greater than 23130 are set to one and all pixels where the value is less than 23130 are set to zero. Since the landmask is only going to have two values, zero and one, there ain’t much point in having more than 256 possible values, so “-depth 8” returns the threshold image to 8-bit, saving hard drive space when the image gets written to disk. The name of the output file is “landmask.png,” and it’s in the same “work/ground_floor” directory as the previous image.
We can get a prj file from the spatial reference site here, just right click on “.prj file” and download file to your your ground floor directory with the “heightmask.png” file and rename to “heightfield.prj.” Duplicate the prj file and rename the copy as “landmask.prj.” Create pgw files for the two images in your favorite text editor and paste in the results from the worldfile calculator.
Now you’re ready to try using Quantum GIS(QGIS) to load data into GRASS. Unfortunately, the current stable version(1.8.0) is, at the moment, incapable of properly talking to the current version of GRASS(which is the one I have. I’m using the 2.1 nightly build from Dakota Cartography. Hopefully, this will get better soon, but I enjoy being an early adopter anyway. In QGIS click the “Add Raster Layer” button. Navigate to the directory with your heightfield file and load it in. Just for reference purposes, I’m going to load in the landmask file too.
Now that we have our data in QGIS let’s create a new Location in GRASS using QGIS. Select Plugins>GRASS>New mapset. The window that opens, should default to your GRASS database location. If not browse to find it. When you’re ready, click “Next >”.
Click “Create new location” and give it a name. Next.
Click “Projection” and search for “EPSG:4326”. Select that. Next.
Use the default GRASS region: N 90, E 180, S -90, W -180. Next.
Enter mapset name. Since this is a brand new mapset, I’d go with “PERMANENT” in allcaps. Next. Finish.
Now we need to import our data to GRASS. First select, “Open GRASS tools”, and the “Modules Tree” tab. Under “File Management” select >Import into GRASS>Import raster into GRASS>Import raster into GRASS from QGIS view>r.in.gdal.qgis – Import loaded raster…, select the layer you want to import, in this case heightfield, I’m not sure what the Password field is about. Set a name for the map in GRASS, I use something like init_elevations to distinguish the 16-bit png with a range of 0 to 65,535 from later real elevation maps with somewhat sane altitude ranges. Usually I’ll check the “Override projection(use location’s projection)” button, just in case. Run.
Repeat the procedure to load landmask into GRASS as ref_continents.
Now, we want to make something with a saner elevation range. I’ll use the GRASS r.mapcalculator tool, though through the QGIS front end this time. You’ll find it in the Modules Tree under >Raster>Spatial analysis>Map algebra>r.mapcalculator. You’ll find the module looks and works pretty much exactly the way it does in GRASS.
Because, the raster is slightly different and I’ve chosen a different sea level, the formula will be a bit different. I’m also using a different overall range for a couple of reasons.
First, the undersea bathymetry is unrealistic and lacks the kind of narrow trenches that a real sea bottom has. This means that when I set the lowest depth to match the Marianas trench, I get wide expanses of way-too-deep ocean. Instead, I’m going to set the deepest generated depth to about -7000 meters. Second, I want to leave room for manual editing. I figure I’ll place the greatest depths and ultimate heights myself. This supports the reduction of both bathymetric depth and topographic elevation. I’ll put the greatest elevation at about 6000 meters. I say, “about,” because, when I calculate the multipliers to create the new elevation map, I’ll round them off pretty broadly. I really don’t need a hugely precise set of elevations here.
As before, I set raster A as init_elevations. The formula, this time, will be:
(A<23130)*0.303*(A-23130) + (A>=23130)*0.142*(A-23130)
with the resulting range of elevations being -7008.39m to 6021.51m. I can live with that, I think. Run the module. If it gives you an error message telling you that it can not read the region or some such nastiness, be patient. Keep clicking OK and it will eventually run the module just fine. This may be one of the vagaries of using a daily build. I can’t wait till they come up with a stable version of QGIS that will talk to my version of GRASS, but it will work just fine.
Now, let’s make the land raster. Use the mapcalculator again, with basic_elevations as our A input raster,
A>= 0.00 as our formula, and land as our output raster. Run.
Once we get through the, “can’t read region, blah-dee-blah,” nonsense, load up the land raster. Looks awesome! To me anyway. Perfect match for the landmask I made in ImageMagick, anyway.
Our last step, for now. Let’s create the continents vector. In the Grass Tools module tree, open >File management>Map type conversion>Convert a raster to vector within GRASS>r.to.vect.area – convert raster to vector areas… Select land as your input raster, and give your output vector a name, I chose “continents“. Run.
Add the GRASS vector layer and have a look.
Hmm. The lines are good, but everything’s pink! Double click on land in the Layers panel. Select Style on the left. On the pull-down menu where it says “Single Symbol”, select “Categorized”. Set “Column” to “value” and click the Classify button near the bottom. Under Symbol there are little color squares, double click to change the color. For value 0, I chose the saved symbol “water”, and for the value 1, I chose “land”. For the third color swatch, I usually pick some grotesquely bright and ugly color to highlight problems. Also next to the values, you will see Label text fields. I replace “0” with “Water” and “1” with “Land”. Usually I replace that last one with “err.” Once I’m sure there are no glaring problems, I’ll delete the entry for “err”. It’s good to check, but pretty uncool when you get to a production map.
So today we’ve looked at the very useful roll and threshold functions in Image Magick, and the use of Quantum GIS as a sometimes more friendly front-end for GRASS GIS. Hopefully, this will prove useful in your mapping of places both real and fantastic. I hope, too, that you enjoyed this introduction as much as I enjoyed making it.