<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  
  <channel>
    <title>Michael Corey, data journalist</title>
    <description>Michael Corey is a data journalist who likes maps, science and history.
</description>
    <link>http://www.mikejcorey.com/</link>
    <atom:link href="http://www.mikejcorey.com/rss.xml" rel="self" type="application/rss+xml" />
    <pubDate>Tue, 18 Oct 2016 02:47:36 +0000</pubDate>
    <lastBuildDate>Tue, 18 Oct 2016 02:47:36 +0000</lastBuildDate>
    
    <item>
      <title>Tutorial part 2: Create beautiful hillshade maps from digital elevation models with GDAL and Mapnik</title>
      <description><![CDATA[ <p><a href="/tutorials/2011/02/05/Tutorial-part-1-Create-beautiful-hillshade-maps-from-digital-elevation-models-with-GDAL-and-Mapnik.html">In part 1 of our GDAL and Mapnik hillshade map tutorial</a>, we used GDAL to convert tiled USGS digital elevation models to a merged GeoTIFF. When also reprojected the map to Mercator and used a California border shapefile to cut out just the state of California.</p>

<p>In this installment, we’ll use the result as a Mapnik layer, and check out some different options for using raster data in your Mapnik maps.</p>

<p>Before we dive in, a note about versions. In this tutorial I’m using Mapnik2, which is now in beta release. I’m doing this both because Mapnik2 adds some exciting new capabilities, and so this tutorial is worth anything for more than a few weeks. Even though Mapnik2 is still beta, I’ve been running it for several weeks now and so far haven’t run into any serious difficulties, so especially if you’re on Mac OS X, I’d recommend giving version 2 a shot.</p>

<p>Even if you do run into problems, <a href="http://www.mail-archive.com/mapnik-users@lists.berlios.de/info.html">the Mapnik listserv is very active</a>, and the developers themselves are very quick to respond with help and to fix bugs. If only every open-source project was so well-maintained!</p>

<p>If you’re not running version 2, a lot of this will still work, though you might need to tweak syntax a little bit. I’ll note anything you just can’t do in Mapnik before version 2.</p>

<p><strong>Data mis en place</strong></p>

<p>Here’s the data we’ll use for this part of the tutorial:</p>

<ul>
	<li><a href="media.mikejcorey.com/download/ca-mercator.tar.gz">A California border shapefile in Mercator projection (SRID 3395)</a></li>
	<li><a href="media.mikejcorey.com/download/california_county_shortline.tar.gz">A California county/shorelines shapefile (SRID 4326)</a></li>
	<li><a href="media.mikejcorey.com/download/california_water.tar.gz">A California water shapefile (SRID 4269)</a></li>
	<li><a href="media.mikejcorey.com/download/ca-dem-combined-merc-cutout.tif.gz">The final GeoTIFF cutout from part 1</a> (This is an 88 MB file, so don't download if you don't have to!)</li>
</ul>

<p>Now on to the fun!</p>

<p>First, let’s do a basic Mapnik map with our GeoTIFF layer. For many Mapnik maps, <a href="https://github.com/mapnik/Cascadenik/wiki/Cascadenik">Cascadenik makes styling much simpler for anyone familiar with CSS syntax</a>, but currently (February 2011) Cascadenik doesn’t support raster layers. So we’ll start with this XML:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt">&lt;Map</span> <span class="na">srs=</span><span class="s">"+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;Style</span> <span class="na">name=</span><span class="s">"hillshade style"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Rule</span> <span class="na">name=</span><span class="s">"rule 1"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;RasterSymbolizer</span> <span class="na">opacity=</span><span class="s">"1"</span> <span class="na">scaling=</span><span class="s">"bilinear"</span> <span class="na">mode=</span><span class="s">"normal"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/Rule&gt;</span>
  <span class="nt">&lt;/Style&gt;</span>
  <span class="nt">&lt;Layer</span> <span class="na">name=</span><span class="s">"hillshade"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;StyleName&gt;</span>hillshade style<span class="nt">&lt;/StyleName&gt;</span>
    <span class="nt">&lt;Datasource&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"type"</span><span class="nt">&gt;</span>gdal<span class="nt">&lt;/Parameter&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"file"</span><span class="nt">&gt;</span>/Users/yourname/Documents/gdaltutorial/ca-dem-combined-merc-cutout.tif<span class="nt">&lt;/Parameter&gt;</span>
    <span class="nt">&lt;/Datasource&gt;</span>
  <span class="nt">&lt;/Layer&gt;</span>
<span class="nt">&lt;/Map&gt;</span></code></pre></figure>

<p>Let’s break this down in stages. First, the overall <strong>&lt;Map&gt;</strong> wrapper:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt">&lt;Map</span> <span class="na">srs=</span><span class="s">"+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"</span><span class="nt">&gt;</span>
<span class="nt">&lt;/Map&gt;</span></code></pre></figure>

<p>This is where we set the projection of the overall map. Don’t worry, you don’t need to understand what all of it means (although it’s fun to find out!). As you no doubt noticed, this is the same srs data we used to reproject our GeoTIFF in part 1.</p>

<p>One of the great features of Mapnik is that even if the data for separate layers are in different projections, in most cases Mapnik can simply reproject that data on the fly. You can’t reproject raster data within Mapnik, however, so you’ll always want to be sure that you get your GeoTIFF into the projection you want your final map to use before you get to Mapnik (as we did in part 1).</p>

<p>Now let’s drop down a bit to the layer data:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml">  <span class="nt">&lt;Layer</span> <span class="na">name=</span><span class="s">"hillshade"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;StyleName&gt;</span>hillshade style<span class="nt">&lt;/StyleName&gt;</span>
    <span class="nt">&lt;Datasource&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"type"</span><span class="nt">&gt;</span>gdal<span class="nt">&lt;/Parameter&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"file"</span><span class="nt">&gt;</span>/Users/yourname/Documents/gdaltutorial/ca-dem-combined-merc-cutout.tif<span class="nt">&lt;/Parameter&gt;</span>
    <span class="nt">&lt;/Datasource&gt;</span>
  <span class="nt">&lt;/Layer&gt;</span></code></pre></figure>

<p>This is where we tell Mapnik what type of data we’re using for this layer. Inside the <strong>&lt;Datasource&gt;&lt;/Datasource&gt;</strong> tags, we specify the data type (<strong>gdal</strong>), and point to the location of our GeoTIFF file. It’s good practice to use the absolute path to your files so if you move your Mapnik files you won’t break the script.</p>

<p>The remaining line inside our <strong>&lt;Layer&gt;&lt;/Layer&gt;</strong> tags is the <strong>&lt;StyleName&gt;&lt;/StyleName&gt;</strong>. This tells Mapnik which style definition to use for this layer. So let’s take a look at that style definition.</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml">  <span class="nt">&lt;Style</span> <span class="na">name=</span><span class="s">"hillshade style"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Rule</span> <span class="na">name=</span><span class="s">"rule 1"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;RasterSymbolizer</span> <span class="na">opacity=</span><span class="s">"1"</span> <span class="na">scaling=</span><span class="s">"bilinear"</span> <span class="na">mode=</span><span class="s">"normal"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/Rule&gt;</span>
  <span class="nt">&lt;/Style&gt;</span></code></pre></figure>

<p>There’s a lot you can do with raster data, especially in Mapnik2. This style definiton is pretty basic, though. We’re saying that we want the GeoTIFF to be rendered at 100% opacity. Scaling controls how Mapnik renders the image when scaling it down from its original size, and the mode controls how the raster layer is blended with layers below it. Since there’s nothing currently behind the layer, mode is somewhat moot at the moment. &lt;a href=”http://trac.mapnik.org/wiki/RasterSymbolizer#Usage”&lt;/a&gt;Feel free to play with different values for both scaling and mode.&lt;/a&gt;</p>

<p>That’s about it. Just make sure your style name matches the <strong>&lt;StyleName&gt;&lt;/StyleName&gt;</strong> tag in your layer.</p>

<p>That’s it for our first, pretty basic GeoTIFF Mapnik map. Save this file as <strong>ca-map.xml</strong>.</p>

<p>Now we’ll use Python to compile this XML into an image. I highly recommend that once you get the basics down, you simplify your life and download <a href="https://github.com/mapnik/Cascadenik/wiki/Cascadenik">Cascadenik</a> and <a href="http://code.google.com/p/mapnik-utils/wiki/Nik2Img">nik2img</a> to do a little of this coding for you, but at this point you’ve installed enough for one tutorial. So we’ll stick to a basic Python script. Even if you’ve never used Python before, now’s the time to start. Trust me, if you have any programming experience this will make sense.</p>

<p>Open a new text file, and save the following code as <strong>ca-stuff-compile.py</strong> into the same directory as your XML document:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c">#!/usr/bin/env python</span>
import mapnik2
mapfile <span class="o">=</span> <span class="s1">'ca-stuff.xml'</span>
map_output <span class="o">=</span> <span class="s1">'ca-map.png'</span>
m <span class="o">=</span> mapnik2.Map<span class="o">(</span>1200, 800<span class="o">)</span>
mapnik2.load_map<span class="o">(</span>m, mapfile<span class="o">)</span>
bbox <span class="o">=</span> mapnik2.Box2d<span class="o">(</span>mapnik2.Coord<span class="o">(</span>-14000000, 3700000<span class="o">)</span>, mapnik2.Coord<span class="o">(</span>-12500000, 5200000<span class="o">))</span>
m.zoom_to_box<span class="o">(</span>bbox<span class="o">)</span>
mapnik2.render_to_file<span class="o">(</span>m, map_output<span class="o">)</span></code></pre></figure>

<p>Right off the bat, if you’re not using Mapnik2 for this, you’ll need to change everthing that says <strong>mapnik2</strong> to simply <strong>mapnik</strong>.</p>

<p>Next we assign some variables. We specify our XML file for Mapnik to chew on, and tell Mapnik what filename to use for the final image.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">mapfile <span class="o">=</span> <span class="s1">'ca-stuff.xml'</span>
map_output <span class="o">=</span> <span class="s1">'ca-map.png'</span></code></pre></figure>

<p>Next we instantiate a new mapnik map, and pass our XML to Mapnik’s load_map() function. We also specify the pixel dimensions we want to give our final map, 800 pixels wide by 600 pixels deep.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">m <span class="o">=</span> mapnik2.Map<span class="o">(</span>800, 600<span class="o">)</span>
mapnik2.load_map<span class="o">(</span>m, mapfile<span class="o">)</span></code></pre></figure>

<p>Now we tell Mapnik what bounding box we want the map to use. We’ll use this to control how much space will show up around our map content, but you could also specify only a section of the map or any other arbitrary bounding box. But how do we know what to use?</p>

<p>Remember back in part 1 when we used <strong>ogrinfo</strong> to get the bounding box of our California shapefile that we used to cut out the GeoTIFF? Here’s what that returned:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Extent: <span class="o">(</span>-13849389.898804, 3810165.061203<span class="o">)</span> - <span class="o">(</span>-12704836.275367, 5133847.169980<span class="o">)</span></code></pre></figure>

<p>So if you want to clip your map at California’s exact boundaries, you can use that extent exactly. But generally we want our maps to have a little padding, so we’ll round up and down a bit:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">bbox <span class="o">=</span> mapnik2.Box2d<span class="o">(</span>mapnik2.Coord<span class="o">(</span>-14000000, 3700000<span class="o">)</span>, mapnik2.Coord<span class="o">(</span>-12500000, 5200000<span class="o">))</span>
m.zoom_to_box<span class="o">(</span>bbox<span class="o">)</span></code></pre></figure>

<p>Note that, mercifully, Mapnik uses the same format for its bounding box as <strong>ogrinfo</strong>. The points represent the lower left and upper right corners of our image.</p>

<p>Finally, the script renders the map to our file:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">mapnik2.render_to_file<span class="o">(</span>m, map_output<span class="o">)</span></code></pre></figure>

<p>If you haven’t already save this file into the same directory as your XML document as <strong>ca-stuff-compile.py</strong>.</p>

<p>Now, in a terminal window, change into this directory, and let’s build that map:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span>python ca-stuff-compile.py</code></pre></figure>

<p>If you don’t get any error messages, check your directory. You should see a new file called ca-map.png, and hopefully your hillshade map is in the middle.</p>

<p><img src="http://media.mikejcorey.com/blog/2011/02/ca-mapnik-1.jpg" alt="" title="ca-mapnik-1" width="610" height="406" class="aligncenter size-full wp-image-400" /></p>

<p>Neato! Well, sort of - it’s pretty boring, right? Not much different from our original GeoTIFF. Let’s change that now by adding more styles and more map layers to our XML. We’ll add a lot at once here, but not so much conceptually:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt">&lt;Map</span> <span class="na">background-color=</span><span class="s">"rgb(51,122,207)"</span> <span class="na">srs=</span><span class="s">"+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;Style</span> <span class="na">name=</span><span class="s">"hillshade style"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Rule</span> <span class="na">name=</span><span class="s">"rule 1"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;RasterSymbolizer</span> <span class="na">opacity=</span><span class="s">"0.8"</span> <span class="na">scaling=</span><span class="s">"bilinear"</span> <span class="na">mode=</span><span class="s">"multiply"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/Rule&gt;</span>
  <span class="nt">&lt;/Style&gt;</span>
  <span class="nt">&lt;Style</span> <span class="na">name=</span><span class="s">"polygon style"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Rule</span> <span class="na">name=</span><span class="s">"rule 1"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;PolygonSymbolizer</span> <span class="na">fill=</span><span class="s">"rgb(255,204,102)"</span> <span class="na">fill-opacity=</span><span class="s">"1"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/Rule&gt;</span>
  <span class="nt">&lt;/Style&gt;</span>
  <span class="nt">&lt;Style</span> <span class="na">name=</span><span class="s">"county style"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Rule</span> <span class="na">name=</span><span class="s">"rule 1"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;LineSymbolizer</span> <span class="na">stroke=</span><span class="s">"#CCCCCC"</span> <span class="na">stroke-width=</span><span class="s">"0.4"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/Rule&gt;</span>
  <span class="nt">&lt;/Style&gt;</span>
  <span class="nt">&lt;Style</span> <span class="na">name=</span><span class="s">"water style"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Rule</span> <span class="na">name=</span><span class="s">"rule 1"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;PolygonSymbolizer</span> <span class="na">fill=</span><span class="s">"rgb(51,122,207)"</span> <span class="na">fill-opacity=</span><span class="s">"1"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/Rule&gt;</span>
  <span class="nt">&lt;/Style&gt;</span>
  <span class="nt">&lt;Layer</span> <span class="na">name=</span><span class="s">"stateborder"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;StyleName&gt;</span>polygon style<span class="nt">&lt;/StyleName&gt;</span>
    <span class="nt">&lt;Datasource&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"file"</span><span class="nt">&gt;</span>/Users/youruser/Documents/gdaltutorial/ca-mercator/ca-mercator.shp<span class="nt">&lt;/Parameter&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"type"</span><span class="nt">&gt;</span>shape<span class="nt">&lt;/Parameter&gt;</span>
    <span class="nt">&lt;/Datasource&gt;</span>
  <span class="nt">&lt;/Layer&gt;</span>
  <span class="nt">&lt;Layer</span> <span class="na">name=</span><span class="s">"hillshade"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;StyleName&gt;</span>hillshade style<span class="nt">&lt;/StyleName&gt;</span>
    <span class="nt">&lt;Datasource&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"type"</span><span class="nt">&gt;</span>gdal<span class="nt">&lt;/Parameter&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"file"</span><span class="nt">&gt;</span>/Users/youruser/Documents/gdaltutorial/ca-dem-combined-merc-cutout.tif<span class="nt">&lt;/Parameter&gt;</span>
    <span class="nt">&lt;/Datasource&gt;</span>
  <span class="nt">&lt;/Layer&gt;</span>
  <span class="nt">&lt;Layer</span> <span class="na">name=</span><span class="s">"water"</span> <span class="na">srs=</span><span class="s">"+proj=longlat +ellps=WGS84 +no_defs"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;StyleName&gt;</span>water style<span class="nt">&lt;/StyleName&gt;</span>
    <span class="nt">&lt;Datasource&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"file"</span><span class="nt">&gt;</span>/Users/youruser/Documents/gdaltutorial/california_water/california_water.shp<span class="nt">&lt;/Parameter&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"type"</span><span class="nt">&gt;</span>shape<span class="nt">&lt;/Parameter&gt;</span>
    <span class="nt">&lt;/Datasource&gt;</span>
  <span class="nt">&lt;/Layer&gt;</span>
  <span class="nt">&lt;Layer</span> <span class="na">name=</span><span class="s">"counties"</span> <span class="na">srs=</span><span class="s">"+proj=longlat +ellps=GRS80 +datum=NAD83 +no_defs"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;StyleName&gt;</span>county style<span class="nt">&lt;/StyleName&gt;</span>
    <span class="nt">&lt;Datasource&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"file"</span><span class="nt">&gt;</span>/Users/youruser/Documents/gdaltutorial/california_county_shoreline/california_county_shoreline.shp<span class="nt">&lt;/Parameter&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"type"</span><span class="nt">&gt;</span>shape<span class="nt">&lt;/Parameter&gt;</span>
    <span class="nt">&lt;/Datasource&gt;</span>
  <span class="nt">&lt;/Layer&gt;</span>
<span class="nt">&lt;/Map&gt;</span></code></pre></figure>

<p>We’ve added 3 shapefile layers: one in Mercator projection that you may recognize as the state border shapefile we used to cutout the GeoTIFF in part 1:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml">  <span class="nt">&lt;Layer</span> <span class="na">name=</span><span class="s">"stateborder"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;StyleName&gt;</span>polygon style<span class="nt">&lt;/StyleName&gt;</span>
    <span class="nt">&lt;Datasource&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"file"</span><span class="nt">&gt;</span>/Users/youruser/Documents/gdaltutorial/ca-mercator/ca-mercator.shp<span class="nt">&lt;/Parameter&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"type"</span><span class="nt">&gt;</span>shape<span class="nt">&lt;/Parameter&gt;</span>
    <span class="nt">&lt;/Datasource&gt;</span>
  <span class="nt">&lt;/Layer&gt;</span></code></pre></figure>

<p>You’ll also notice that we’ve put this layer before the GeoTIFF in our XML. This is because we want the state border to be behind the GeoTIFF in the rendered image.</p>

<p>We’ve specified that this layer uses <strong>&lt;StyleName&gt;polygon style&lt;/StyleName&gt;</strong>, so let’s take a look at the <strong>polygon style</strong> style, defined above the layers:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml">  <span class="nt">&lt;Style</span> <span class="na">name=</span><span class="s">"polygon style"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Rule</span> <span class="na">name=</span><span class="s">"rule 1"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;PolygonSymbolizer</span> <span class="na">fill=</span><span class="s">"rgb(255,204,102)"</span> <span class="na">fill-opacity=</span><span class="s">"1"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/Rule&gt;</span>
  <span class="nt">&lt;/Style&gt;</span></code></pre></figure>

<p>This one’s pretty simple. We set a fill color for features in this layer using standard Web RGB syntax and Mapnik’s <a href="http://trac.mapnik.org/wiki/PolygonSymbolizer"><strong>PolygonSymbolizer</strong></a>, and specify that we want 100% opacity for this layer.</p>

<p>Next let’s turn to the style for the GeoTIFF, which we’ve now changed so it will blend with our state border background layer:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml">  <span class="nt">&lt;Style</span> <span class="na">name=</span><span class="s">"hillshade style"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Rule</span> <span class="na">name=</span><span class="s">"rule 1"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;RasterSymbolizer</span> <span class="na">opacity=</span><span class="s">"0.8"</span> <span class="na">scaling=</span><span class="s">"bilinear"</span> <span class="na">mode=</span><span class="s">"multiply"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/Rule&gt;</span>
  <span class="nt">&lt;/Style&gt;</span></code></pre></figure>

<p>We’ve changed the opacity of the GeoTIFF layer to 80%, to keep the level of gray down, and we’ve changed the blend mode to <strong>multiply</strong>. This tells Mapnik how to blend the GeoTIFF with the underlying layers. There are <a href="http://trac.mapnik.org/wiki/RasterSymbolizer#Usage">several other modes you can experiment with</a>, but in most cases you’ll probably want multiply.</p>

<p>Now we’ll add a water layer so we can see some of California’s major lakes, and then county borders. Here’s another great thing about Mapnik: You can use many types of data as layers: shapefiles, PostGIS tables and many other ogr types.</p>

<p>Here’s the top 2 layers:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml">  <span class="nt">&lt;Layer</span> <span class="na">name=</span><span class="s">"water"</span> <span class="na">srs=</span><span class="s">"+proj=longlat +ellps=WGS84 +no_defs"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;StyleName&gt;</span>water style<span class="nt">&lt;/StyleName&gt;</span>
    <span class="nt">&lt;Datasource&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"file"</span><span class="nt">&gt;</span>/Users/youruser/Documents/gdaltutorial/california_water/california_water.shp<span class="nt">&lt;/Parameter&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"type"</span><span class="nt">&gt;</span>shape<span class="nt">&lt;/Parameter&gt;</span>
    <span class="nt">&lt;/Datasource&gt;</span>
  <span class="nt">&lt;/Layer&gt;</span>
  <span class="nt">&lt;Layer</span> <span class="na">name=</span><span class="s">"counties"</span> <span class="na">srs=</span><span class="s">"+proj=longlat +ellps=GRS80 +datum=NAD83 +no_defs"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;StyleName&gt;</span>county style<span class="nt">&lt;/StyleName&gt;</span>
    <span class="nt">&lt;Datasource&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"file"</span><span class="nt">&gt;</span>/Users/youruser/Documents/gdaltutorial/california_county_shoreline/california_county_shoreline.shp<span class="nt">&lt;/Parameter&gt;</span>
      <span class="nt">&lt;Parameter</span> <span class="na">name=</span><span class="s">"type"</span><span class="nt">&gt;</span>shape<span class="nt">&lt;/Parameter&gt;</span>
    <span class="nt">&lt;/Datasource&gt;</span>
  <span class="nt">&lt;/Layer&gt;</span></code></pre></figure>

<p>The main thing to notice about these layers is that we’ve specified an additional parameter in the <strong>&lt;Layer&gt;&lt;/Layer&gt;</strong> tag: <strong>srs</strong>. We’re doing this because each of these layers is in a different spatial reference system than our main map. The water layer is in SRID 4326, or standard latitude/longitude pairs. The county layer is in SRID 4269, otherwise known as NAD83. As long as you specify the correct srs, Mapnik will do any reprojection needed on the fly (though not on raster layers, remember), so there’s no need to reproject everything into the same projection on your own.</p>

<p>All that’s left is the style definitions for those two layers:</p>

<figure class="highlight"><pre><code class="language-xml" data-lang="xml">  <span class="nt">&lt;Style</span> <span class="na">name=</span><span class="s">"county style"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Rule</span> <span class="na">name=</span><span class="s">"rule 1"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;LineSymbolizer</span> <span class="na">stroke=</span><span class="s">"#CCCCCC"</span> <span class="na">stroke-width=</span><span class="s">"0.4"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/Rule&gt;</span>
  <span class="nt">&lt;/Style&gt;</span>
  <span class="nt">&lt;Style</span> <span class="na">name=</span><span class="s">"water style"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;Rule</span> <span class="na">name=</span><span class="s">"rule 1"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;PolygonSymbolizer</span> <span class="na">fill=</span><span class="s">"rgb(51,122,207)"</span> <span class="na">fill-opacity=</span><span class="s">"1"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/Rule&gt;</span>
  <span class="nt">&lt;/Style&gt;</span></code></pre></figure>

<p>Nothing too fancy here. The county style is using a <a href="http://trac.mapnik.org/wiki/LineSymbolizer"><strong>LineSymbolizer</strong></a> instead of the PolygonSymbolizer we saw earlier. Look - we can use hexadecimal color codes too! And we set the stroke width to 0.4 pixels. The water style colors the water blue – not much more to say than that.</p>

<p>OK, time to render this map. In your Terminal:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span>python ca-stuff-compile.py</code></pre></figure>

<p>If you did everything right, you should have a simple but pretty nice multi-layer Mapnik map.</p>

<p><a href="http://media.mikejcorey.com/blog/2011/02/ca-mapnik-2.jpg"><img src="http://media.mikejcorey.com/blog/2011/02/ca-mapnik-2.jpg" alt="" title="ca-mapnik-2" width="610" height="407" class="aligncenter size-full wp-image-402" /></a></p>

<p>Since we used a fairly high-resolution GeoTIFF, you should be able to change the image dimensions in ca-stuff-compile.py to make the image quite large for print, HD video, or a poster for your bedroom. But even I don’t do that with my maps!</p>

<p>Unless you want to <a href="http://www.axismaps.com/typographic.php">send me this one</a>.</p>
 
<br />
<hr />
<p>You’ve just read <strong>"<a href="http://www.mikejcorey.com/tutorials/2011/02/25/Tutorial-part-2-Create-beautiful-hillshade-maps-from-digital-elevation-models-with-GDAL-and-Mapnik.html">Tutorial part 2: Create beautiful hillshade maps from digital elevation models with GDAL and Mapnik</a>"</strong> on <strong>"<a href="http://www.mikejcorey.com/">Michael Corey, data journalist</a>"</strong>.</p>
 ]]></description>
      <pubDate>Fri, 25 Feb 2011 17:15:11 +0000</pubDate>
      <link>http://www.mikejcorey.com/tutorials/2011/02/25/Tutorial-part-2-Create-beautiful-hillshade-maps-from-digital-elevation-models-with-GDAL-and-Mapnik.html</link>
      <guid isPermaLink="true">http://www.mikejcorey.com/tutorials/2011/02/25/Tutorial-part-2-Create-beautiful-hillshade-maps-from-digital-elevation-models-with-GDAL-and-Mapnik.html</guid>
      
      <category>tutorials</category>
      
    </item>
    
    <item>
      <title>Tutorial part 1: Create beautiful hillshade maps from digital elevation models with GDAL and Mapnik</title>
      <description><![CDATA[ <p>Mapnik is your best friend if you want to create map tiles for a slippy map or just want an open-source way to output high-quality printed maps for a wide variety of uses.</p>

<p>Though for your first project I might recommend a somewhat lower-priority project, <a href="http://media.mikejcorey.com/blog/2011/02/SaveTheDate3-5x5.jpg">I like to think I’m the only person to ever use Mapnik to make wedding invitations</a>.</p>

<p>(If I’m wrong, I’d love to see more examples!)</p>

<p>One of Mapnik’s greatest strengths is its ability to combine multiple types of data into a single map: shapefiles, PostGIS data and raster data are all easy to combine.</p>

<p>When I began working with GIS data I started with exclusively vector data, because vector data are so easily scaled to any size and don’t take up much storage space. Vector layers are also easy to color and style, and are great at keeping your thematic maps clean and easy to read.</p>

<p>But sooner or later you’ll want to add some texture to your maps, and it’s time to add elevation models with raster data.</p>

<p>Luckily, there’s lots of raster data available to get started. The <a href="http://edc2.usgs.gov/geodata/index.php">USGS publishes digital elevation models (.DEM) of most of the United States</a> (everywhere except Alaska, I believe). This is definitely high-enough resolution for adding texture to a state-level visualization.</p>

<p>Less luckily, the digital elevation models are sliced up into small pieces. This can be nice because it cuts down on file sizes, but if you want a statewide elevation map, you’ll have to put many pieces together.</p>

<p>A statewide elevation model of California, for example, requires <a href="http://www.brenorbrophy.com/California-DEM.htm">merging 70 .dem files at the 2 arc-second resolution</a>.</p>

<p><a href="http://www.brenorbrophy.com/California-DEM.htm"><img class="aligncenter size-full wp-image-374" title="ca-components" src="http://media.mikejcorey.com/blog/2011/02/ca-components.jpg" alt="" width="610" height="610" /></a></p>

<p>However, never fear! GDAL is here to help.</p>

<p><a href="http://www.gdal.org/">GDAL is a powerful, open-source library of translation scripts</a> for raster geographic data.</p>

<p>So with GDAL, a shapefile of California’s border and a set of digital elevation models and Mapnik, it’s straightforward to make a seamless high-resolution .PNG map of California with nice elevation hillshades.</p>

<p>This tutorial isn’t for people without any GIS or programming experience, but if you have a little of both you’ll be fine. This tutorial is for Mac OS X Snow Leopard users, but will probably work for Linux users with a few OS-related tweaks.</p>

<p>Using GDAL requires knowledge of basic GIS concepts and basic command-line programming. I’ve had good luck installing the <a href="http://www.kyngchaos.com/software/frameworks">GDAL Complete package from kyngchaos.com</a>. Scroll down to the “GDAL 1.8 Complete” .dmg installer.</p>

<p>To get started with raster data, you mostly just need to know what a TIF image is.</p>

<p>To do any Mapnik work, you should feel comfortable with:</p>
<ul>
	<li> GIS concepts like map projections</li>
	<li> Shapefiles and/or PostGIS</li>
	<li> XML</li>
	<li> Basic command-line programming</li>
</ul>
<p>The Mapnik website has detailed <a href="http://trac.mapnik.org/wiki/MacInstallation">installation guides</a> and  <a href="http://trac.mapnik.org/wiki/MapnikTutorials">tutorials on how to use it</a>. There’s an excellent <a href="http://mojodna.net/2009/12/05/the-os-x-spatial-stack.html">OS X-specific guide to installing Mapnik and dependencies (including GDAL and many other useful spacial libraries) here</a>. There’s many ways to do it and I won’t get into that here. Just make sure you have Mapnik running with GDAL support.</p>

<p>The tutorial is divided into two parts. Part 1, this post, will focus on merging, converting, projecting and clipping the digital elevation models so they can be used with Mapnik. We’ll handle the Mapnik process in part 2.</p>
<h2>Data mis en place</h2>
<p>Here’s the data we’ll use for this tutorial:<a href="http://media.mikejcorey.com/download/ca-mercator.tar.gz"></a></p>
<ul>
	<li><a href="http://media.mikejcorey.com/download/ca-mercator.tar.gz">A California border shapefile in Mercator projection (SRID 3395)</a></li>
	<li> <a href="http://media.mikejcorey.com/download/raw-ca-dems.tar.gz">A g-zipped archive of all the digital elevation models you'll need for California</a></li>
</ul>
<h2>Fun with GDAL</h2>
<p>Download and upzip the shapefile and the .dem folder. Then open a terminal window and navigate to wherever you downloaded the shapefile and dem folders.</p>

<p>Then, in the terminal:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span><span class="nb">cd </span>raw-ca-dems</code></pre></figure>

<p>First we’ll merge the digital elevation model tiles into a single .dem file using <strong>gdal_merge</strong>. We need to specify that we want any areas without data to be white by specifying <strong>-init “255”</strong>. Then we specify our desired output filename with <strong>-o (filename)</strong> and then list the files we want to merge together. Like so:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span>gdal_merge.py -init <span class="s2">"255"</span> -o ca-dem-combined.dem alturas-e.dem alturas-w.dem bakersfield-e.dem bakersfield-w.dem chico-e.dem chico-w.dem crescent_city-e.dem death_valley-e.dem death_valley-w.dem el_centro-e.dem el_centro-w.dem eureka-e.dem fresno-e.dem fresno-w.dem goldfield-w.dem kingman-e.dem kingman-w.dem klamath_falls-w.dem las_vegas-w.dem long_beach-e.dem long_beach-w.dem los_angeles-e.dem los_angeles-w.dem lovelock-w.dem mariposa-e.dem mariposa-w.dem medford-e.dem medford-w.dem monterey-e.dem monterey-w.dem needles-e.dem needles-w.dem noyo_canyon-e.dem redding-e.dem redding-w.dem reno-e.dem reno-w.dem sacramento-e.dem sacramento-w.dem salton_sea-e.dem salton_sea-w.dem san_bernardino-e.dem san_bernardino-w.dem san_clemente_island-e.dem san_diego-e.dem san_diego-w.dem san_francisco-e.dem san_francisco-w.dem san_jose-e.dem san_jose-w.dem san_luis_obispo-e.dem san_luis_obispo-w.dem santa_ana-e.dem santa_ana-w.dem santa_cruz-e.dem santa_maria-e.dem santa_rosa_island-e.dem santa_rosa-e.dem santa_rosa-w.dem susanville-e.dem susanville-w.dem trona-e.dem trona-w.dem ukiah-e.dem ukiah-w.dem vya-w.dem walker_lake-e.dem walker_lake-w.dem weed-e.dem weed-w.dem</code></pre></figure>

<p>As long as you don’t get any errors, you should now have a new file in your folder called ca-dem-combined.dem. If you have GIS software like Quantum GIS you should be able to add this as a raster layer. If you do open it up, you shouldn’t see any seams between the former tiles – that’s what we want for a good-looking Mapnik layer.</p>

<p>But for this to work in Mapnik, we need a GeoTIFF. To convert the merged .dem to a GeoTIFF, we’ll use <a href="http://www.gdal.org/gdaldem.html"><strong>gdaldem</strong></a>. The gdaldem command has several modes; we’ll use hillshade to create a shaded relief map, the most common way to visualize texture. We also need to specify the ratio of vertical units to horizontal. Since right now the .dem is in WGS84 projection (standard latitude/longitude), we’ll use degrees, so <strong>-s 111120</strong>. Then we specify the input file and the output file. Here’s the full command:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span>gdaldem hillshade -s 111120 ca-dem-combined.dem ca-dem-combined.tif</code></pre></figure>

<p>Even if you don’t have a GIS viewer, you should be able to open the .tif file in any image browser like Preview or Photoshop. (Be careful you don’t resave the file, though – most image editors will remove necessary geometric data from the file if you re-save it.) You’ll see a few thin black lines around the outside edge of the old tile data, but don’t worry – we’ll cut this out later.</p>

<p><img class="aligncenter size-full wp-image-378" title="ca-combined" src="http://media.mikejcorey.com/blog/2011/02/ca-combined.jpg" alt="" width="620" height="620" /></p>

<p>So now we have a combined .tif, but most of the time we want to display our finished project in Mercator projection – most non-GIS types will think non-Mercator maps look a bit strange. We need to reproject our .tif to Mercator with <a href="http://www.gdal.org/gdalwarp.html"><strong>gdalwarp</strong></a>. We’ll use the <strong>-t_srs</strong> option to set the target projection, and use the projection specification for the version of Mercator that’s also used by Google Maps and OpenLayers.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span>gdalwarp -t_srs <span class="s1">'+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs'</span> ca-dem-combined.tif ca-dem-combined-merc.tif</code></pre></figure>

<p>If you open up the resulting file, you should see that the projection has changed.</p>

<p><img class="aligncenter size-full wp-image-379" title="ca-merc" src="http://media.mikejcorey.com/blog/2011/02/ca-merc.jpg" alt="" width="620" height="781" /></p>

<p>Now we have our final hillshade data, but we want to only show California – not all the extra stuff outside the border. We’ll use our California border shapefile as a mask to cut out just the hillshade data inside the boundary. This is a three-step process.</p>

<p>First, we determine the bounding box, or extent, of our clipping mask – the California border shapefile in this case. We use <strong>ogrinfo</strong> for this, which comes along with GDAL Complete.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span>ogrinfo -al ../ca-mercator/ca-mercator.shp</code></pre></figure>

<p>This will return a lot of details about the shapefile. But if you scroll back to the top of the output you’ll see:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Extent: <span class="o">(</span>-13849389.898804, 3810165.061203<span class="o">)</span> - <span class="o">(</span>-12704836.275367, 5133847.169980<span class="o">)</span></code></pre></figure>

<p>These represent the longitude and latitude points (in Mercator projection) of the southwest and northeast corners of our shapefile data.</p>

<p>Next, we trim our merged Mercator .tif to those exact boundaries with <a href="http://www.gdal.org/gdal_translate.html"><strong>gdal_translate</strong></a>.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span>gdal_translate -projwin -13849389.898804 5133847.169980 -12704836.275367 3810165.061203 ca-dem-combined-merc.tif ca-dem-combined-merc-box.tif</code></pre></figure>

<p><strong>Warning:</strong> Notice that in the above command we reversed the order of the two y-axis values (5133847.169980 and 3810165.061203) from how they appeared in our ogrinfo query. This is because gdal_translate’s <strong>-projwin</strong> option is looking for the upper left and lower right coordinates – exactly the opposite of the extent we got from ogrinfo. Annoying, but that’s just the way it is.</p>

<p>Finally, we’ll use the shapefile’s polygon boundaries as a clipping mask on the merged, projected and trimmed .tif, which is now trimmed to show the same area as the shapefile. We’ll use <a><strong>gdalwarp</strong></a> for this, using some different options than before. The <strong>-co COMPRESS=DEFLATE</strong> option is a generic “creation option” that can have many values. We specify <strong>-dstalpha</strong> to create a “nodata” band in our resulting .tif, so we are left with a transparent background. And finally we use <strong>-cutline</strong> to specify a file to use as the clipping mask. As before we then specify our input file and desired output filename.</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="gp">$ </span>gdalwarp -co <span class="nv">COMPRESS</span><span class="o">=</span>DEFLATE -dstalpha -cutline ../ca-mercator/ca-mercator.shp ca-dem-combined-merc-box.tif ca-dem-combined-merc-cutout.tif</code></pre></figure>

<p>And there’s our textured California border. If you open <strong>ca-dem-combined-merc-cutout.tif</strong> in an image viewer, you should see a beautifully clipped grayscale image.</p>

<p><img class="aligncenter size-full wp-image-380" title="ca-cutout" src="http://media.mikejcorey.com/blog/2011/02/ca-cutout.jpg" alt="" width="620" height="717" /></p>

<p><a href="/tutorials/2011/02/25/Tutorial-part-2-Create-beautiful-hillshade-maps-from-digital-elevation-models-with-GDAL-and-Mapnik.html">In the second half of our tutorial, we’ll use this cutout .tif as a layer in Mapnik</a>. We’re more than halfway there!</p>
 
<br />
<hr />
<p>You’ve just read <strong>"<a href="http://www.mikejcorey.com/tutorials/2011/02/05/Tutorial-part-1-Create-beautiful-hillshade-maps-from-digital-elevation-models-with-GDAL-and-Mapnik.html">Tutorial part 1: Create beautiful hillshade maps from digital elevation models with GDAL and Mapnik</a>"</strong> on <strong>"<a href="http://www.mikejcorey.com/">Michael Corey, data journalist</a>"</strong>.</p>
 ]]></description>
      <pubDate>Sat, 05 Feb 2011 17:15:11 +0000</pubDate>
      <link>http://www.mikejcorey.com/tutorials/2011/02/05/Tutorial-part-1-Create-beautiful-hillshade-maps-from-digital-elevation-models-with-GDAL-and-Mapnik.html</link>
      <guid isPermaLink="true">http://www.mikejcorey.com/tutorials/2011/02/05/Tutorial-part-1-Create-beautiful-hillshade-maps-from-digital-elevation-models-with-GDAL-and-Mapnik.html</guid>
      
      <category>tutorials</category>
      
    </item>
    
  </channel>
</rss>
