Chapter 9

Reference and Physical Maps

A reference map focuses on the geographic location of features. In these maps, cities are named and major transport routes are identified. In addition, natural features such as rivers and mountains are named, and elevation is shown using a simple color shading.

A physical map shows the physical landscape features of a place. Mountains and elevation changes are usually shown with different colors and shades to show relief, using green to show lower elevations and browns for high elevations.

This chapter details how to create a reference map of a northern region of Spain using data from OpenStreetMap and a physical map of Brazil with data from different sources.

9.1 Physical Maps

Brazil1, the world’s fifth largest country, is one of the seventeen megadiverse countries2, home to diverse wildlife, natural environments, and extensive natural resources in a variety of protected habitats. Throughout this section we will create a physical map of this exceptional country using data from several data services.

library(raster)
library(rasterVis)
library(maptools)
library(rgeos)
library(latticeExtra)
library(colorspace)

## Longitude-Latitude projection
proj <- CRS(’+proj=longlat+ellps=WGS84’)

9.1.1 Retrieving Data

Four types of information are needed: administrative boundaries, terrain elevation, rivers and lakes, and sea depth.

  1. The administrative boundaries are available from GADM3. The readShapePoly function reads data from the downloaded shapefile and creates a SpatialPolygonsDataFrame object.

    old <- setwd(tempdir())
    
    
    download.file(’http://www.gadm.org/data/shp/BRA_adm.zip’,
               ’BRA_adm.zip’)
    unzip(’BRA_adm.zip’)
    brazilAdm <- readShapePoly(’BRA_adm1.shp’, proj4string=proj)
    Encoding(levels(brazilAdm$NAME_1)) <- ’latin1’
  2. The terrain elevation or digital elevation model (DEM) is available from DIVA-GIS4. The raster function reads the file and creates a RasterLayer object.

    download.file(’http://www.diva-gis.org/data/alt/BRA_alt.zip’,
               ’BRA_alt.zip’)
    unzip(’BRA_alt.zip’)
    brazilDEM <- raster(’BRA_alt’)
  3. The water lines (rivers and lakes) are available from Natural Earth Data5. The readShapeLines function reads data from the downloaded shapefile and creates a SpatialLinesDataFrame object.

    ## World Water lines (Natural Earth)
    download.file(’http://www.naturalearthdata.com/http//www.
        naturalearthdata.com/download/10m/physical/ne_10m_rivers_lake_
        centerlines.zip’,
               ’neRivers.zip’)
    unzip(’neRivers.zip’)
    worldlRiv <- readShapeLines(’ne_10m_rivers_lake_centerlines’,
        proj4string = proj)
  4. Finally, the sea depth is also available from Natural Earth Data5. The raster covers the whole world so it must be cropped by the extent of the DEM raster.

    download.file(’http://www.naturalearthdata.com/http//www.
        naturalearthdata.com/download/10m/raster/OB_LR.zip’,
               ’neSea.zip’)
    unzip(’neSea.zip’)
    worldSea <- raster(’OB_LR.tif’)
    brazilSea <- crop(worldSea, brazilDEM)
    setwd(old)

9.1.2 Intersection of Shapefiles and Elevation Model

The rivers and lakes database from Natural Earth Data comprises all the world extent, but we only need the rivers of Brazil. The function gIntersection of the package rgeos determines the intersection between two geometries. Because these geometries must be defined with classes of the sp package, the extent of brazilDEM must be first converted to SpatialPolygons. The intersection is a new SpatialLines object, brazilRiv.

## only those features labeled as “River” are needed
worlRiv<- worlRiv[worlRiv$featurecla==’River’,]

## Define the extent of Brazil as a SpatialPolygons
extBrazil <- as(extent(brazilDEM), ’SpatialPolygons’)
proj4string(extBrazil) <- proj

## and intersect it with worldRiv to extract brazilian rivers
## from the world database
brazilRiv <- gIntersection(worldRiv, extBrazil, byid=TRUE)
## and especially the famous Amazonas River
amazonas <- worldRiv[worldRiv$name==’Amazonas’,]

9.1.3 Labels

Each region of Brazil will be labeled with the name of its corresponding polygon. The locations of the labels are defined by the centroid of each polygon, easily computed with the coordinates method. In addition, a larger label with the name of the country will be placed in the average centroid.

## Locations of labels of each polygon
centroids <- coordinates(brazilAdm)
## Location of the “Brazil” label (average of the set of polygons
    centroids)
xyBrazil <- apply(centroids, 2, mean)

Some region names are too long to be displayed in one line. Thus, a previous step is to split the string if it comprises more than two words.

admNames <- strsplit(as.character(brazilAdm$NAME_1), ’’)

admNames <- sapply(admNames,
             FUN=function(s){
               sep=if (length(s)>2) ’
’ else ’
               paste(s, collapse=sep)
               })

9.1.4 Overlaying Layers of Information

Therefore, the physical map (Figure 9.2) is composed of four layers:

  1. The sea depth raster displayed with the levelplot method of the rasterVis package. The palette is defined with brewer.pal (Figure 9.1).

    blueTheme <- rasterTheme(region=brewer.pal(n=9, ’Blues’))
    
    
    seaPlot <- levelplot(brazilSea, par.settings=blueTheme,
                    maxpixels=1e6, panel=panel.levelplot.raster,
                    margin=FALSE, colorkey=FALSE)
  2. The altitude raster layer uses a terrain colors palette, as the one produced by the terrain_hcl function from the colorspace package (Ihaka et al. 2011) (Figure 9.1).

    terrainTheme <- rasterTheme(region=terrain_hcl(15))
    
    
    altPlot <- levelplot(brazilDEM, par.settings=terrainTheme,
                     maxpixels=1e6, panel=panel.levelplot.raster,
                     margin=FALSE, colorkey=FALSE)
  3. The rivers represented by the SpatialLinesDataFrame object. The Amazonas River is labeled with sp.lineLabel and printed with a thicker line. The label is created with the label method, a wrapper function to extract the ID slots from the SpatialLines and create a suitable character object with the correct names values.

    amazonasLab <- label(amazonas, ’Amazonas’)
  4. The administrative boundaries represented by the SpatialPolygonsDataFrame object with their labels printed with the panel.pointLabel function. This function uses optimization routines to find good locations for point labels without overlaps.

    seaPlot + altPlot + layer({
      ## Rivers
      sp.lines(brazilRiv, col=’darkblue’, lwd=0.2)
      ## Amazonas
      sp.lineLabel(amazonas, amazonasLab,
                lwd=1, col=’darkblue’, col.line=’darkblue’,
                 cex=0.5, fontfamily=’Palatino’)
      ## Administrative boundaries
      sp.polygons(brazilAdm, col=’black’, lwd=0.2)
      ## Centroids of administrative boundaries ...
      panel.points(centroids, col=’black’)
      ## ... with their labels
      panel.pointLabel(centroids, labels=admNames,
                   cex=0.7, fontfamily=’Palatino’, lineheight=.8)
      ## Country name
      panel.text(xyBrazil[1], xyBrazil[2], labels=’BRAZIL’,
               cex=1.5, fontfamily = ’Palatino’, fontface=2)
    })

Figure 9.1

Figure showing sea depth and altitude rasters of brazil.

Sea depth and altitude rasters of Brazil.

Figure 9.2

Figure showing physical map of brazil. main administrative regions and the amazonas river are labeled.

Physical map of Brazil. Main administrative regions and the Amazonas River are labeled.

9.2 imageOpenStreetMap with Hill Shade Layers

Although I was born in Madrid, Galicia (north of Spain) is a very special region for me. More precisely, the Cedeira and Valdoviño regions offer a wonderful combination of wild sea, secluded beaches, and forests. I will show you a map of these marvelous places.

9.2.1 Retrieving Data from OpenStreetMap

The first step is to acquire information from the OpenStreetMap project. There are several packages to extract data from this service but, while most of them only provide already rendered raster images, the osmar package6 (Eugster and Schlesinger 2010) enables the use of the raw data with classes from the packages sp and igraph.

The get_osm function retrieves a region defined by corner_bbox using the OSM API.

library(’osmar’)

api <- osmsource_api()
ymax <- 43.7031
ymin <- 43.6181
xmax <- -8.0224
xmin <- -8.0808
box <- corner_bbox(xmin, ymin, xmax, ymax)
cedeira <- get_osm(box, source=api, full=TRUE)

The cedeira object includes three main components: nodes, ways and relations. These components can be accessed with the functions find, subset, way, node, relation, and tags. Thus, the different kinds of roads can be obtained using way and tags with the appropiate tag.

summary(cedeira$nodes)
idxHighways <- find(cedeira, way(tags(k==’highway’)))
highways <- subset(cedeira, way_ids=idxHighways)
idxStreets <- find(highways, way(tags(v==’residential’)))
idxPrimary <- find(highways, way(tags(v==’primary’)))
idxSecondary <- find(highways, way(tags(v==’secondary’)))
idxTertiary <- find(highways, way(tags(v==’tertiary’)))
idxOther <- find(highways,
              way(tags(v==’unclassified’ |
                     v==’footway’ |
                     v==’steps’)))

The result of find is the index of each element. The correspondent spatial object is extracted with find_down and subset, and can be converted to a class defined by the sp package with as_sp. The following spFromOSM function encodes the procedure, and extracts the SpatialLines object that represent each type of road.

spFromOSM <- function(source, index, type=’lines’){
  idx <- find_down(source, index)
  obj <- subset(source, ids=idx)
  objSP <- as_sp(obj, type)
  }

streets <- spFromOSM(cedeira, way(idxStreets))
primary <- spFromOSM(cedeira, way(idxPrimary))
secondary <- spFromOSM(cedeira, way(idxSecondary))
tertiary <- spFromOSM(cedeira, way(idxTertiary))
other <- spFromOSM(cedeira, way(idxOther))

A similar procedure can be applied to construct a SpatialPoints object with the collection of places with name:

idxPlaces <- find(cedeira, node(tags(k==’name’)))
places <- spFromOSM(cedeira, node(idxPlaces), ’points’)

nms <- subset(cedeira$nodes$tags, subset=(k==’name’), select=c(’id’,
     ’v’))
ord <- match(idxPlaces, nms$id)
nms <- nms[ord,]
places$name <- nms$v[ord]

## Cedeira town will be printed differently
idxCedeira <- which(nms$v==’Cedeira’) ##Main town
cedeiraCoords <- coordinates(places[idxCedeira,])
places <- places[-idxCedeira,]

9.2.2 Hill Shading

The second step is to produce layers to display the topography. A suitable method is shaded relief or hill shading. This technique simulates the cast shadow thrown from a light source upon a raised relief map. The hill shade layer can be computed from the slope and aspect layers derived from a Digital Elevation Model (DEM). This layer will underlay the DEM raster, which will be printed using semitransparency.

The DEM for this region is available at the Geonetwork-SECAD service from the Universidad de Extremadura and can be read with raster:

library(raster)
## Galicia DEM
## http://ide.unex.es/geonetwork/srv/es/main.search?any=MDE_Galicia
## http://ide.unex.es:8180/geonetwork/srv/es/resources.get?id=21&
    fname=dem_gal.7z&access=private

old <- tempdir()
download.file(’http://ide.unex.es:8180/geonetwork/srv/es/resources.
    get?id=21&fname=dem_gal.7z&access=private’, ’dem_gal.7z’)
unzip(’dem_gal.7z’)
demGalicia <- raster(’dem_gal.asc’)
setwd(old)

The slope and aspect layers are computed with the terrain function, and the hill shade layer is derived with these layers for a fixed sun position. Previously, the useful region of the DEM raster was extracted with the crop function:

cedeiraSP <- as_sp(cedeira, ’points’)
projCedeira <- projection(cedeiraSP)
##extCedeira <- bbox(cedeiraSP)
## or summary(cedeira$nodes)$bbox
extCedeira <- extent(-8.15, -7.95, 43.6, 43.75)
demCedeira <- crop(demGalicia, extCedeira)
projection(demCedeira) <- projCedeira
demCedeira[demCedeira <= 0] <- NA

slope <- terrain(demCedeira, ’slope’)
aspect <- terrain(demCedeira, ’aspect’)
hsCedeira <- hillShade(slope=slope, aspect=aspect,
                  angle=20, direction=30)

9.2.3 Overlaying Layers of Information

And finally, the third step is to display the different layers of information in correct order (Figure 9.3):

  • The hill shade layer is created with the levelplot method for Raster objects defined in the rasterVis package. The GrTheme is modified to display the sea region with blue color.
  • The DEM raster is printed with terrain colors and semitransparency over the hill shade layer.
  • The roads are displayed with an auxiliary function (sp.road) that produces a colored line over a thicker black line.
  • The places are represented with sp.points and labeled with the sp.pointLabel method, a modification of the pointLabel function for base graphics, both defined in the maptools package. These functions use optimization routines to find good locations for point labels without overlaps.

Figure 9.3

Figure showing main roads near cedeira, galicia. local topography is displayed with the hill shading technique. some places are highlighted.

Main roads near Cedeira, Galicia. Local topography is displayed with the hill shading technique. Some places are highlighted.

library(maptools)
library(latticeExtra)
library(colorspace)
library(rasterVis)

##Auxiliary function to display the roads. A thicker black line in
##the background and a thinner one with an appropiate color.
sp.road <- function(line, lwd=5, blwd=7,
                col=’indianred1’, bcol=’black’){
  sp.lines(line, lwd=blwd, col=bcol)
  sp.lines(line, lwd=lwd, col=col)
}

## The background color of the panel is set to blue to represent the
     sea
hsTheme <- modifyList(GrTheme(), list(panel.background=list(col=’
    skyblue3’)))
## DEM with terrain colors and semitransparency
terrainTheme <- modifyList(rasterTheme(region=terrain_hcl(n=15)),
                          list(regions=list(alpha=0.6)))
## Hill shade and DEM overlaid
levelplot(hsCedeira, maxpixels=ncell(hsCedeira),
        par.settings=hsTheme, margin=FALSE, colorkey=FALSE) +
  levelplot(demCedeira, maxpixels=ncell(demCedeira),
          par.settings=terrainTheme) +
  ## Roads and places
  layer({
    ## Street and roads
    sp.road(streets, lwd=1, blwd=2, col=’white’)
    sp.road(other, lwd=2, blwd=3, col=’white’)
    sp.road(tertiary, lwd=3, blwd=4, col=’palegreen’)
    sp.road(secondary, lwd=4, blwd=6, col=’midnightblue’)
    sp.road(primary, col=’indianred1’)
    ## Places except Cedeira town
    sp.points(places, pch=19, col=’black’, cex=0.4, alpha=0.8)
    sp.pointLabel(places, labels=places$name,
                  fontfamily = ’Palatino’,
                  cex=0.6, col=’black’)
    ## Cedeira town
    panel.points(cedeiraCoords, pch=18, col=’black’, cex=1)
    panel.text(cedeiraCoords, labels=’Cedeira’, pos=2, offset=1)
    })

1 http://en.wikipedia.org/wiki/Brazil

2 http://en.wikipedia.org/wiki/Megadiverse_countries

3 http://gadm.org/

4 http://www.diva-gis.org/Data

5 http://www.naturalearthdata.com/

6 Its webpage http://osmar.r-forge.r-project.org/ proposes two interesting demos.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.39.59