plot facilities for spatial data in OpenGL or WebGL
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
R fix for #80 Nov 27, 2018
inst anglr() is defunct Mar 14, 2018
man cadastre and contour example Nov 7, 2018
tests tests and dep in line with silicate Nov 27, 2018
.travis.yml bump Feb 28, 2018 all the stuff Aug 19, 2016
DESCRIPTION tests and dep in line with silicate Nov 27, 2018
NAMESPACE updates Aug 31, 2018 cadastre and contour example Nov 7, 2018
README.Rmd bump and docs Oct 31, 2018 bump and docs Oct 31, 2018
_pkgdown.yml bump Feb 27, 2018
appveyor.yml bump appveyor Feb 27, 2018

Travis-CI Build Status Build Status AppVeyor Build Status CRAN_Status_Badge Coverage Status

NOTE: none of these 3D scenes can be viewed on github so a temporary copy of this readme with the figures rendered is here:

Topological forms for plotting spatial data

The ‘anglr’ package illustrates some generalizations of GIS-y tasks in R with a database-y approach.

The basic idea is to showcase topological forms of objects from a variety of sources:

  • silicate forms
  • simple features
  • Spatial features
  • rgl 3D objects
  • trip objects (and general animal tracking data types)
  • regular raster grids
  • igraph
  • Lidar
  • others - let me know!

To do this anglr works with forms defined by silicate and (after rgl) provides plot3d methods for each of the models SC, PATH, ARC and TRI. Here we add two more models DEL (for high-quality triangulation) and QUAD (for raster data).


The general approach is re-model your data using one of these models, optionally use copy_down to augment the model with a Z coordinate, and then plot3d it.

model <- sf::st_read("some/shapefile.shp")
araster <- raster::raster("some/gridraster.tif")
mesh <- copy_down(silicate::SC(model), araster)

The copy down process will copy feature attributes (a constant measure) or raster attributes (a continuous measure) in the appropriate way. After copy down the mesh will be unique in XYZ, whereas the usual starting point is uniqueness in XY.

These mesh or topological forms can be used to merge disparate data into a single form, or used to convert standard spatial objects to rgl ready forms.

An example of merging vector and raster can be seen with this.

## a global DEM
data("gebco1", package = "anglr")
## North Carolina, the sf boilerplate polygon layer
nc <- read_sf(system.file("shape/nc.shp", package="sf"))


p_mesh <- DEL(nc, max_area = 0.002)
## a relief map, composed of triangles grouped by polygon with ##  interpolated raster elevation 
p_mesh <- copy_down(p_mesh, z = gebco1)

## plot the scene

rgl.clear()  ## rerun the cycle from clear to widget in browser contexts 
bg3d("black"); material3d(specular = "black")
aspect3d(1, 1, .1)
rglwidget()  ## not needed if you have a local device

Here the z argument to copy_down is a raster, and so the z_ coordinate of the mesh is updated by extracting values from the raster. If z_ is alternately set to a column in the layer or a specific vector of values this is used as a constant offset for the z_ value, and the mesh is separated by feature.

We only use TRI here both to illustrate its availability, but also because we only need poor quality triangles for planar geometry.

## either form works
#c_mesh <- copy_down(TRI(nc), z = p_mesh$object$BIR74)
c_mesh <- copy_down(TRI(nc), z = "BIR74")
a <- plot3d(c_mesh) 
bg3d("black"); material3d(specular = "black")
aspect3d(1, 1, .2)
rglwidget()  ## not needed if you have a local device

In the silicate models, complex objects are decomposed to a set of related, linked tables. Object identity is maintained with attribute metadata and this is carried through to colour and other aesthetics.

Plot (3D) methods take those tables and generate the “indexed array” structures needed for ‘rgl’. (plot3d will return the rgl-model form). This gets us part of the way towards having the best of both worlds of GIS and 3D graphics.

Another example shows this approach applied to a 3D multipatch shapefile, with a few easy steps we can plot a wiremesh or roof/floor polygons from a civic building footprint.

Ongoing design

The core work for translating spatial classes is done by the unspecialized ‘silicate::PATH’ function and its underlying decomposition generics. Ongoing work in the silicate package will improve and support these types more fully.

Planar polygons and lines are described by the same 1D primitives, and this is easy to do. Harder is to generate 2D primitives and for that we rely on Jonathan Richard Shewchuk’s Triangle.

Triangulation in DEL is with RTriangle package using “constrained mostly-Delaunay Triangulation” from the Triangle library, and TRI in silicate uses ear-clipping via Mapbox’s earcut.hpp (this is analogous to but faster and more robust than rgl::triangulate). Independent work for mostly-Delaunay methods is in the laridae project.

With RTriangle we can set a max area for the triangles, so it can wrap around curves like globes and hills, and this can only be done by the addition of Steiner points. All of this takes us very far from the path-based types generally used by GIS-alikes.


Raster gridded data are decomposed to QUAD forms, essentially a 2D primitive with four corners rather than three. This works well in rgl and is super fast using the quadmesh package that can translate from the raster package.

Texture mapping is possible with rgl, but it needs a local coordinate system mapped to the index space of a PNG image. It’s easy enough but requires a bit of awkward preparation, not yet simplified.

Some different approaches:

Deprecated use of rangl here, but shows the general texture coordinate approach required:


We must use a version of R that is 3.3.2 or later, and anglr can only be installed from Github, and that at least requires the package devtools.

Also required are packages ‘rgl’ and ‘RTriangle’ and ‘sf’, so first make sure you can install and use these. On a fresh installation of R these package together require a lot of other contributed packages, and that can take some time.


With that out of the way, install from Github using devtools.


Feel free to contact me via the Issues if you have problems, or these notes don’t make sense.


On Linux you will need at least the following installed by an administrator, here tested on Ubuntu Xenial 16.04 (note the apt/sources.list is specific to version).

## key for apt-get update, see
echo 'deb xenial/' >> /etc/apt/sources.list
apt-key adv --keyserver --recv-keys E084DAB9

## up to date GDAL and PROJ.4 and GEOS
add-apt-repository ppa:ubuntugis/ubuntugis-unstable --yes

apt update 
apt upgrade --assume-yes

## Install 3rd parties
apt install libproj-dev libgdal-dev libgeos-dev  libssl-dev libgl1-mesa-dev libglu1-mesa-dev libudunits2-dev
## install R, if you need to
## apt install r-base r-base-dev 

Then in R

install.packages(c("dplyr", "proj4", "raster",  "rgl", "rlang", "RTriangle", "spbabel", "tibble", "viridis"))

Get involved!

Let me know if you have problems, or are interested in this work. See the issues tab to make suggestions or report bugs.


Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.