Introduction

The caricRture package is used to create maps (and possibly other graphics) that have the appearance of being hand drawn. The algorithms used to acheive this are derived from Wood et. al. (2012). Hand drawn maps are useful to convey the impression that the geographical data being shown is in some way imprecise, or vague. The degree of ‘roughness’ of the hand drawing is controllable, and it is possible to draw in a number of styles - for example to give the appearance of marker pens, or pencil sketches.

Setting up the package

At the moment, the package exists only on github. On an R session on a computer connected to the internet, enter:

install_github('chrisbrunsdon/caricRture')

to install the package. To load the package, just enter

library(caricRture)

First steps

The package is designed to work well with dplyr, in particular tyhe pipeline approach, and also to work with SpatialPolygons,SpatialPolygonsDataFrame classes of geographical objects as supplied by the sp package. A practice SpatialPolygonsDataFrame based on Irish NUTS3 regions is provided in the data set RA - the actual object is called RA.spdf:

data(RA)
RA.spdf %>% make_canvas %>% plot_it

Although the more conventional plot(RA.spdf) could have been used here, the %>% form is useful, as a general approach used by this package is to pipeline objects through various transformations, quite often culminating in the plot_it command to produce a final map. The make_canvas command sets up a blank map extent, and the plot_it function actually plots the map. make_canvas returns its input value - which can then be passed on to the next stage of the pipeline. Its main value is that it has a side effect - that of creating the ‘canvas’.

An example of a shape-based operation is the small_chop function chops away smaller polygons that are part of multipolygons in spatial objects. Typically these are small islands or enclaves. Dropping these sometimes simplifies the shape of polygons, which is useful for caricaturing and generalisation - see below:

RA.spdf %>% small_chop %>% make_canvas %>% plot_it

Notice that now the islands are no longer included in the map. The form of the command illustrates the pipeline - the SpatialPolygonsDataFrame called RA.spdf is first fed into small_chop and the output from this is fed into plot. Again, it is possible to use plot(small_chop(RA.spdf)) here, but this form is less legible. This distinction would be even greater if there were several functions comprising the ‘pipeline’.

Some More Basic Tools

The above example (small_chop) is a basic pipeline functuion to transform SpatialPolygons and SpatialPolygonsDataFrames - there are a number of these. Another is the generalise_it function - the effectively reduces the number of points used to make up the polygons in an object - although it doesn’t guarantee that the resultant polygons do not overlap.

RA.spdf %>% small_chop %>% generalise_it(10000) %>% make_canvas %>% plot_it

For those familiar, this is actually the Ramer-Douglas-Peuker Algorithm - although in this context the tolerance parameter is much higher than usually used - for example around 10km for mapsof Ireland. Note also that it is most effective in this context if any small islands are removed before it is applied. At this stage a possible ‘sketchy’ map can be created. To do this, another function sketch_it is used, that works like plot_it except it produces images with a hand-drawn appearance.

RA.spdf %>% small_chop %>% generalise_it(10000) %>% make_canvas %>% sketch_it(col='lightgrey')

The parameter rough in sketch_it allows the ‘roughness’ or sketchiness of the drawn lines to be controlled. The default value is 0.05 - below a less rough sketch is created:

RA.spdf %>% small_chop %>% generalise_it(10000) %>% make_canvas %>% 
  sketch_it(rough=0.01,col='violetred')

It is also possible to ‘tidy’ the overlaps using the function tidy_it - when a pair of polygons overlap, this algorithm curts away the overlapping part of the larger polygon:

RA.spdf %>% small_chop %>% generalise_it(10000) %>% tidy_it %>% make_canvas %>% plot_it

That was shown in non-sketchy form to make clear the geometrical process, but is a useful tool for sketching as well:

RA.spdf %>% small_chop %>% generalise_it(10000) %>% tidy_it %>% 
  make_canvas %>% sketch_it(rough=0.02,col='darkred')

Hole Filling

The tidy-it function deals with overlaps bewtween component polygons, but not gaps. One way of dealing with gaps is to use the dilate_it function. This essentially creates a buffer around each of the polygons. The idea here is to expand them to fill out any holes. It may be that in sketchy terms the holes are not an issue and this is really a matter of style. However since things are being represented in sketch form, I see no problem with this. Here, the effect is shown:

RA.spdf %>% small_chop %>% generalise_it(10000) %>% tidy_it %>% 
  dilate_it(3500) %>% make_canvas %>% plot_it

In true Laurel and Hardy style, of course this brings back lots of overlaps. So, tidy up again…

RA.spdf %>% small_chop %>% generalise_it(10000) %>% tidy_it %>% 
  dilate_it(3500) %>% tidy_it %>% make_canvas %>% plot_it

This can be made sketchy without much difficulty:

RA.spdf %>% small_chop %>% generalise_it(10000) %>% tidy_it %>% 
  dilate_it(3500) %>% tidy_it %>% make_canvas %>% sketch_it(col='maroon')

Stylistic Modifications - Dealing With Outer Boundaries

Oddly, although the holes are now filled in, the overlapping lines on coterminous regions look overly complex, compared to the border and coastal areas - the ‘outer boundaries’. There are a couple of work-arounds for this. Firstly, a function called outline_it finds the external outline of a set of polygons. By potting the external boundaries after the original map, at least the external boundaries also get over-written, so that the style is consistent. Like make_canvas, sketch_it is another command that passes the input argument through, drawing the sketchy map as a side effect. This can be exploited here, where the output (ie the object being sketched) is passed on to outline_it before being re-sketched.

RA.spdf %>% small_chop %>% generalise_it(10000) %>% tidy_it %>% 
  dilate_it(3500) %>% tidy_it %>% make_canvas %>% sketch_it(col='darkorange') %>%
  outline_it %>% sketch_it(col=NA)

The alternative is to use contract_it - this effectively buffers all of the polygons inwardly by a fixed amount. This then leaves a clear gap between each polygon. Sometimes this is useful - unlike the holes earlier these are evenly distributed, and really just constitute an alternative sketch style. Here is the result of using this approach:

RA.spdf %>% small_chop %>% generalise_it(10000) %>% tidy_it %>% 
  dilate_it(3500) %>% tidy_it %>% contract_it(3000) %>% 
  make_canvas %>% sketch_it(col='turquoise') 

Curvy Representations

As well as ‘hand-drawn’ effects, caricRture also offers curvy representations of boundaries. These are achieved using the curve_it function. This takes a ‘shape’ parameter. If this is zero, the transformed shapes are identical to those input, and if equal to one a much smoother curve results - the function makes use of the xspline function - the help page for this explains in greater detail. Values between zero and one result in intermediate degrees of smoothness. Here, it is used to provide a ‘curvy’ version of the Irish regions:

RA.spdf %>% small_chop %>% generalise_it(10000) %>% tidy_it %>% 
  dilate_it(3500) %>% tidy_it %>% curve_it(0.8) %>% make_canvas %>% plot_it

Because plot_it passes its input argument directly through, it is viable to re-use this. Here, it is used in tandem with sketch_it to provide a set of curvy outlines, with a sketched filling. Using a quite thick line (lwd=4) gives a ‘felt tipped pen’ style:

RA.spdf %>% small_chop %>% generalise_it(10000) %>% tidy_it %>% 
  dilate_it(3500) %>% tidy_it %>% curve_it(0.8) %>% make_canvas %>% plot_it(lwd=4) %>%
  sketch_it(col='darkgreen',border=NA)

Working with text

Fonts can be complex in R - and much of the time the temptation is to keep with R’s default font. However, this font does not have the appearance of being hand drawn, and so we will have to grasp the nettle and consider font management. The showtext library helps a lot here - and caricRture makes use of it. The function get_fonts fetches some fonts from Google fonts, and then the function hand_title adds a title to the graphic in a ‘hand drawn’ font.

At the momemt, showtext does not work well with RStudio. If you are using RStudio, the best work-around is to open a non-RStudio graphics window - that is one not using the RStudioGD graphics device. For example, on a Mac, enter quartz() or on windows try X11(). Then, things should work. Here is an example:

get_fonts()
data(RA)
RA.spdf %>% small_chop %>% generalise_it(11000) %>% tidy_it %>% make_canvas %>% 
  sketch_it(col='orange')
'NUTS3 Regions in Ireland' %>% hand_title(fontfam='rs',cex=1.3)

The parameter fontfam refers to the font family. At the moment, seven hand-written styled fonts are provided, all of which are available from Google fonts. The fonts are:

fontfam parameter Google font name Default
am Amatic SC Yes
dk Dekko No
gr Covered By Your Grace No
hl Handlee No
pm Permanent Marker No
ws Waiting for the Sunrise No
rs Rock Salt No

Samples of each are shown below:

A further text tool is the hand_text function. This works in the same way as the standard text function and allows annotation to be placed anywhere on the map. Here, the pm style is used on the curvy map:

RA.spdf %>% small_chop %>% generalise_it(10000) %>% tidy_it %>% 
  dilate_it(3500) %>% tidy_it %>% curve_it(0.8) %>% make_canvas %>% 
  sketch_it(col='lightgreen',border=NA) %>% plot_it(lwd=4)
RA.spdf %>% coordinates -> label_loc
RA.spdf$NUTS3NAME %>% hand_text(label_loc,fontfam='pm',cex=0.8,col='blue')
"NUTS3 Regions in Ireland" %>% hand_title(col.main='blue',fontfam='pm')