Batman plots, such as shown above, have been produced many times before. One earlier version which already used ggplot2 is given at https://guangchuangyu.github.io/2011/08/the-batman-equation/. This author used the so-called Batman Equations given at HardOCP to come up with a number of dataframes containing the data to be plotted. The data in the dataframes were used as input for the ggplot2-plotting routines.

An alternative approach using the mathematical functions of the Batman equation directly for the plot is shown on CoCalc. In this post, the same approach as on CoCalc is followed, but the mathematical functions from the Batman equation are defined as R-functions and the plots are drawn using ggplot2. More information about ggplot2 is available at http://ggplot2.org/book/.

Constructing The Batman Plot

According to the example given on CoCalc, we first define the functions that will later be used for constructing the plot.

sc <- function(x) sqrt(1-x^2)                                # semicircle
el <- function(x) 3*sc(abs(x)/7)                             # ellipse
nl <- function(x) (-1) * el(x)                               # negative of el 
sh <- function(x) 4.2 - .5*abs(x) -2.8*sc(.5*abs(x) -.5)     # shoulders
bf <- function(x) sc(abs(2 - abs(x)) - 1) - x^2/11 + .5*abs(x) -3      # bottom
cr  <- data.frame(x = c(0, .5, .8, 1), y = c(1.7, 1.7, 2.6, .9))   # cowl right
cl  <- data.frame(x = -cr$x, y = cr$y)                             # cowl left

So far, we have defined the pieces that eventually will be used to produce the whole plot. Next, we define a function that will accept a function and a range of values and will return a plotting object. The following plot-creator function takes into account that the whole Batman-plot is symmetric with respect to the \(y\)-coordinate axis.

plot_create <- function(fun, xmin, xmax){
  rp <- ggplot2::stat_function(fun = fun, xlim = c(xmin,xmax))
  lp <- ggplot2::stat_function(fun = fun, xlim = c(-xmax, -xmin))
  result_plot <- list(left_plot = lp, right_plot = rp)
  return(result_plot)
}

As the first step, we have to initialize our plot object.

require(ggplot2)
## Loading required package: ggplot2
### # initialize ggplot object
plot_result <- ggplot(data.frame(x = c(-7,7), y=c(-3,3)), aes(x,y))

Now we are ready to add the wings.

### # get object of plot parts
### # upper part of wing
upper_wing_plot <- plot_create(fun = el, xmin = 3, xmax = 7)
### # lower part of wing
lower_wing_plot <- plot_create(fun = nl, xmin = 4, xmax = 7)
plot_result <- plot_result + upper_wing_plot$left_plot + upper_wing_plot$right_plot +
  lower_wing_plot$left_plot + lower_wing_plot$right_plot
print(plot_result)

Next come the shoulders

### # shoulder
sh_plot <- plot_create(fun = sh, xmin = 1, xmax = 3)
plot_result <- plot_result + sh_plot$left_plot + sh_plot$right_plot
print(plot_result)

Next thing to add is the bottom part.

### # bottom
bt_plot <- plot_create(fun = bf, xmin = 0, xmax = 4)
plot_result <- plot_result + bt_plot$left_plot + bt_plot$right_plot
print(plot_result)

Finally, what remains to be done is the cowls for which we are usin ordinary lines.

plot_result <- plot_result + geom_path(data = cr)
plot_result <- plot_result + geom_path(data = cl)
print(plot_result)