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.
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)
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’.
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')
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')
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')
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)
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')