knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
library(rgl)
setupKnitr(autoprint = TRUE)

Welcome to the rbff R package. rbff is an R wrapper around the boundary-first-flattening (BFF) software developed by Rowan Sawhney based on a method by Rowan Sawhney and Keenan Crane. It is designed to take a 3d object defined as a mesh and 'flatten' it into a 2d mesh (or map to a sphere), whilst minimizing angle and area distortion. This can be used for all sorts of interesting applications like texture mapping, painting on 3d surfaces, and generating representations of 3d objects suitable for machine learning algorithms (e.g. those that have been developed for 2d (or spherical) applications, here is just one example I like). To demonstrate how the package works we will use some 3d meashes included with the package. let's start by loading up a 3d human face, and start flattening it!

library(rbff)
library(rgl)
library(rnaturalearth)
library(sf)
library(dplyr)
library(rmapshaper)

data(face)

## what does it look like? Use the rgl package to view
shade3d(face, col = "#A15C33")

The first thing we can try is flatten the face automatically, using the bff_flatten() function. This function tries to flatten the mesh without too much guidance from the user, but minimizing area distortion. Using the default arguments, let's see what it produces.

face_flat <- bff_flatten(face)

bff_vis_metrics(face_flat, "mesh")
rglwidget() 

So that is cool, but what can we do with it. Well, one simple thing is to use the flattened mesh to project a 2d image onto the original 3d mesh. We can place an image produced by R onto the 2d mesh using the bff_place_image() function which creates an interactive window that allows the user to slide and rotate the 2d mesh over the image. The image can be anything produced by an R expression, or else a png file can be specified. Here is the result of placing an image of the R logo on our face mesh:


Let's try another model:

data(bunny)
bunny_flat <- bff_flatten(bunny, n_cones = 16)
bff_vis_metrics(bunny_flat, "area distortion")

We used 16 'cones' to reduce distortion in flattening the bunny. Cones are cuts through the mesh that are made before flattening. Where the cones are placed is determined automatically by an algorithm designed to minimize distortion.

Flattening to a Particular Shape

Instead of having the boundary of the flattened mesh be chosen automatically to minimize distortion, we can specify a particular boundary shape that we want the mesh to be flattened onto. This shape can be specified as a two-column matrix with coordinates that form a polygon, or it can be specified as an sf object storing a polygon (or anything that can be coerced to it). An sf object is a format designed for geographic shapes, so may have projection information. This information is ignored by rbff, which assumed planar geometry. But sf is a convenient format because the sf package has many functions for manipulating geometry efficiently. Let's get the coastline of Australia, and try flattening our 3d face onto it!

oz <- ne_states("Australia", returnclass = "sf")
## just mainland (sorry Tassie)
oz <- oz %>%
  filter(name %in% c("Western Australia", "Northern Territory",
                     "South Australia", "Queensland", "New South Wales",
                     "Victoria", "Australian Capital Territory"))
oz <- st_union(oz)
## remove small islands
oz <- st_cast(oz, "POLYGON") %>% 
  st_as_sf() %>%
  mutate(area = st_area(x)) %>%
  top_n(1)

plot(oz$x)

## simplify it a bit
oz <- ms_simplify(oz$x) %>%
  st_as_sf()

plot(oz)
oz_face <- bff_flatten_to_shape(face, oz)
bff_vis_metrics(oz_face, "mesh")


rdinnager/rbff documentation built on Jan. 21, 2022, 2:08 p.m.