rgeometry-surface

How to draw a squircle in R


This is the code for a rounded square, I wonder if it could get the one for a squircle, which is a very similar figure.

The Wikipedia states that:

Although constructing a rounded square may be conceptually and physically simpler, the squircle has the simpler equation and can be generalised much more easily.

{
  x<-c(1,1,0,0)
  y<-c(1,0,0,1)
  rad <- max(x)/7
  ver<-25

  yMod<-y
  yMod[which(yMod==max(yMod))]<-yMod[which(yMod==max(yMod))]-rad
  yMod[which(yMod==min(yMod))]<-yMod[which(yMod==min(yMod))]+rad

  topline_y<-rep(max(y),2)
  topBotline_x<-c(min(x)+rad, max(x)-rad)
  bottomline_y<-rep(min(y),2)

  pts<- seq(-pi/2, pi*1.5, length.out = ver*4)
  ptsl<-split(pts, sort(rep(1:4, each=length(pts)/4, len=length(pts))) )

  xy_1 <- cbind( (min(x)+rad) + rad * sin(ptsl[[1]]), (max(y)-rad) + rad * cos(ptsl[[1]]))
  xy_2 <- cbind( (max(x)-rad) + rad * sin(ptsl[[2]]), (max(y)-rad) + rad * cos(ptsl[[2]]))
  xy_3 <- cbind( (max(x)-rad) + rad * sin(ptsl[[3]]), (min(y)+rad) + rad * cos(ptsl[[3]]))
  xy_4 <- cbind( (min(x)+rad) + rad * sin(ptsl[[4]]), (min(y)+rad) + rad * cos(ptsl[[4]]))

  newLongx<-c(x[1:2]   ,xy_3[,1],topBotline_x,xy_4[,1], x[3:4],    xy_1[,1],topBotline_x,xy_2[,1])
  newLongy<-c(yMod[1:2],xy_3[,2],bottomline_y,xy_4[,2], yMod[3:4], xy_1[,2],topline_y   ,xy_2[,2])

  par(pty="s")
  plot.new()
  polygon(newLongx,newLongy, col="red")
}

enter image description here


Solution

  • Here is a base R squircle function.
    I believe the arguments are self descriptive.

    1. x0, y0 - center coordinates.
    2. radius - the squircle radius.
    3. n - number of points to be computed, the default 1000 should make the squircle smooth.
    4. ... - further arguments to be passed to lines. See help('par').

    Now for the function and simple tests.

    squircle <- function(x0 = 0, y0 = 0, radius, n = 1000, ...){
      r <- function(radius, theta){
        radius/(1 - sin(2*theta)^2/2)^(1/4)
      }
      angle <- seq(0, 2*pi, length.out = n)
      rvec <- r(radius, angle)
      x <- rvec*cos(angle) + x0
      y <- rvec*sin(angle) + y0
      lines(x, y, ...)
    }
    
    plot(-5:5, -5:5, type = "n")
    squircle(0, 0, 2, col = "red")
    squircle(1, 1, 2, col = "blue", lty = "dashed")
    

    enter image description here

    Fernandez-Guasti squircle.

    This is another type of squircle. The extra argument is s, giving the squareness of the squircle.

    # squircleFG: Manuel Fernandez-Guasti  (1992)
    squircleFG <- function(x0 = 0, y0 = 0, radius, s, n = 1000, ...){
      angle <- seq(0, 2*pi, length.out = n)
      cosa <- cos(angle)
      sina <- sin(angle)
      sin2a <- sin(2*angle)
      k <- sqrt(1 - sqrt(1 - s^2*sin2a^2))
      x <- k*radius*sign(cosa)/(sqrt(2)*s*abs(sina)) + x0
      y <- k*radius*sign(sina)/(sqrt(2)*s*abs(cosa)) + y0
      lines(x[-n], y[-n], ...)
    }
    
    
    plot(-5:5, -5:5, type = "n")
    squircleFG(0, 0, 2, s = 0.75, col = "red")
    squircleFG(1, 1, 2, s = 0.75, col = "blue", lty = "dashed")
    

    enter image description here