A new version of wk is fresh on CRAN! Version 0.5 introduces some new features to the framework, incorporates most of the functionality that was previously in the wkutils package, and fixes a number of bugs that popped up in the development of s2 and geos. To showcase some of the new features I’ll use the Vermont counties data set from the VT Open Geodata Portal.
Breaking down features and building them back up again
The biggest feature in the new release is the ability to break down features to simpler components (at the simplest, a bunch of coordinates) and build them back up again into geometry that you can pass elsewhere. Some of this functionality previously lived in wkutils but it turns out this is really important: pretty much all geometry in base R is done with big long
y vectors (e.g.,
xy.coords()). To make geometry that was previously locked away in WKB, WKT, or sf objects accessible, there needed to be a way out.
The first level of a geometry you might want to break down are collections: MULTIPOLYGON, MULTILINESTRING, MULTIPOINT, and GEOMETRYCOLLECTION. These types are useful when you have multiple things that represent one element in a vector, like multiple bits of land representing a county. In our case the features were saved as MULTIPOLYGON but there aren’t actually any features with more than one. To simplify it, we can use
wk_flatten() peels off one layer of collections, repeating rows where a feature has more than one element. This is a little like
sf::st_cast() but is defined in terms of what you have rather than what you want. For advanced users, the flattening functionality is also implemented as a wk “filter”, which means it can do most of what it does without allocating any extra memory and can stream input and output very efficiently.
I’m demonstrating all of this with sf because it’s the most common use-case, but it works with any data frame/tibble with exactly one column implementing the
wk_handle() generic (including an
st_sfc()!). In fact, pretty much anything you do with wk also “just works” with data frames.
The next level is vertices: one point feature for each vertex in the input.
Vertices are useful if you need to input something that requires points but you were handed a boundary or polygon layer (I use this kind of thing to set depth values at 0 along coastlines when calculating bathymetry, for example). This is good for GIS function stuff, but if you’re doing any custom geometry processing or just need coordinates for ggplot2 or some base R function, you’ll need straight up
y vectors. If so, the new
wk_coords() function is just for you!
And, of course, sometimes you get handed a bunch of coordinates but you really want an sf object. For this case there is
wk_collection(). For example, to reconstruct the original sf object starting with coordinates we could do:
There’s nothing new about dplyr’s ability to work with vectors in wk 0.5, but the new functions are well-suited to dplyr’s
summarise() as well as the newish auto-unpacking feature in
summarise(). For example, to keep all the attributes when calling
wk_coords() you can do:
The new coordinate functions make dplyr more accessible for doing raw coordinate processing if you’re into that kind of thing. If you’ll recall the short formula for the signed area of a polygon, you can check the winding direction of your polygons without leaving dplyr (the polygons here are wound correctly, hence the positive areas).
First-class coordinate transforms
Starting small, though, wk just provides the framework so that other packages can do cool stuff that I don’t need to maintain (maybe). I did put in enough transforms to make sure every thing was tested, which includes an affine transform and transforms that set/drop coordinate values (most usefully, Z and M).
The point of this all, though, is that extension packages can make their own transforms. There’s no C++ wrapper for this yet but the C is relatively minimal.
You do need a tiny bit of R infrastructure to make this work smoothly:
Then your transform is accessible for anything that needs it! Most algorithms will probably also need an implementation of
wk_trans_inverse() to return the inverse operation.
As a side effect of some of this, plotting now “just works” without the wkutils package for the built-in vector types. It isn’t particularly fast or glamourous, but it’s good enough for a basic “get this geometry on my screen”. Previously this was done using a confusing circular dependency on wkutils. It’s used for
wkt(), but also works for arbitrary data types with a
wk_handle() method via
So far wk development has focused on getting all the nuts and bolts in place so that extensions can do really awesome stuff with few dependencies. Now is that time! I’m hoping to get transforms working for PROJ so that s2 can do a better job creating valid spherical geometry from projected coordinates. Finally, I’m hoping to get some file readers working so that the lazy nature of the handler/filter system can really shine.