26 Nov 2017
Trees, Streets and Streams
I decided to make map prints inspired by the All Streets, All Rivers and All Trees projects for holiday gifts this year. Since all the datasets for these maps are free, and there is a wealth of open source cartographic software, I threw together customized maps at a fraction of the cost of the All Streets prints. I did the mapping on Black Friday and Small Business Saturday 2017, instead of spending the day elbowing my way through big box stores. #OptOpenSource
I used the QGIS packages and GUI for mapping. The streets data is from OpenStreetMap (OSM), the stream data is from the National Hydrology Database (NHD), and the tree cover data is from the National Land Cover Survery (2011) (NLCS). Thanks to the open source community and government funding of science, all of these resources are free!
Below are some details about how to use QGIS to map these datasets.
The OSM dataset is so commonly used that there is built-in QGIS functionality for getting an OSM subset of interest. First, find the lattitude/longitude bounding box of the area you want here. Then open Vector > OSM > Download Data, select manual mode, and enter in the bounding coordinates¹. Next do Vector > OSM > Import and select the previously downloaded file, which results in a .db file. This will save a database file onto disk. As OSM is meant to be an open replacement to Google Maps, the database contains information not only on roads, but on bike paths, businesses, geography and even such tiny details as the local line voltage and frequency! To make an all streets map most of this information must be filtered out. Use Vector > OSM > Export and select the .db file. This brings up the important dialog for sifting through all those database fields. Select the “highway” attribute, meaning highway in the broadest sense encompassing freeways, roads, and paths for cars, cyclists and pedestrians (and even equestrians!). Click OK to create a vector layer of all highways in the downloaded region.
If the streets map looks too dense, some streets can be filtered out. Right
click > Filter on the cropped OSM layer. In the input box type construct
a SQL query like
"highway" != 'track' and ... where ‘track’ is one
of the highway varieties listed here.
This can also be good for getting rid of pesky stray lines through lakes.
The next step is to cut out everything not in whatever state is being mapped. I chose to use the built-in Spatial Query plugin for geographically cropping vector layers. This uses a boundary defined in one layer to crop out features in a second vector layer. To get a layer with the boundary of a state, start by grabbing this US State map from Census.gov. Right click the layer, select filter, and enter a SQL query like “NAME” = ‘State Name’ (note the double and single quotes that are part of SQL syntax). After clicking OK, save the new layer to disk using it’s context menu. To do the spatial filter go to Vector > Spatial Query and follow the instructions. This plugin just selects all features inside the state’s boundary. To get it into a new vector layer right click the existing layer, click Save As, and only save the selected features. This saves the new cropped OSM layer to disk and opens it in the workspace.
The process for mapping the NHD data on streams is quite similar. Use the NHD website to download streams data for whatever region you are interested in (several granularities are available). Once you have downloaded the data open the flowline shapefile and load it as lines, not polygons, to save on rendering time. Since this is just another vector layer, it can be geographically cropped in the exact same way as the OSM data.
Finally, grab the NLCS 2011 dataset. This dataset is 60+ GB. I couldn’t find a way to download any subregions. Since this data is a raster, not a vector, it is just a big 2D array of pixels packaged alongside some geographical metadata. Each pixel corresponds to about 30m x 30m of land. Cropping rasters is a bit trickier than it was for the vectors. Before starting the crop, a modification of the census state map vector layer is required. Duplicate the layer you have and save the new layer to disk. In the general section of the properties menu for the new layer, change the coordinate reference system (CRS, map projection) to EPSG:5070 Conus / Albers. This is the CRS used by the NLCS dataset. If the two CRSs don’t match, the cropping process will fail!
Now it’s cropping time. The tool to use is Clipper, found at Raster > Extraction > Clipper, which is just a thin wrapper around a command from the GDAL package. In the dialog select on output file (out.tif), select mask layer choosing the state layer from the census map, and copy the command from the text display at the bottom of the dialog. Open a terminal and paste the command. On OSX I had to change MSGN to GTiff, which I deduced from an error message. I found it helpful to delete the -q (quiet) option as well. The command should look something like:
$ gdalwarp -q -cutline /Users/.../wi-epsg5070.shp -tr 30.0 30.0 -of GTiff /Users/.../nlcd2011_usfs_conus_canopy_cartographic.img /Users/.../out.tif
and it will take several minutes to run.
Now that you have beautifully cropped streets, steams and trees layers, mess with the style options to change color schemes and line thicknesses.
The final step is to export each of the cropped layers one by one. The QGIS print composer tool (file menu) was as disappointment to me, but it did eventually get the job done. Before using the composer, make sure you have selected a CRS that doesn’t distort your state, and the same CRS for the streets, streams and trees layers. With only one cropped layer selected, open the (buggy) composer and use the insert map tool to put your map onto a page sized to your liking. The move item and move content tools can (sort of) be used to optimally position the map on the page. Then export as a high DPI image! I used a haphazard combination of GIMP and PowerPoint ( ¯_(ツ)_/¯ ) to complete the final layout. Maybe I will learn about using open source design and layout tools next December!
¹If your region is too large this plugin won’t work. Instead go here.