Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 581
Ferroao Avatar asked Mar 03 '23 16:03

Ferroao


2 Answers

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

like image 152
Rui Barradas Avatar answered Mar 19 '23 22:03

Rui Barradas


Is the reason to do this yourself, and see if your code can be simplified?

If this is not the case, one possibility is to use the function grid.roundrect from the grid package.

One example adopted from their help page ?grid::grid.roundrect is to simply use

grid.roundrect(width=.5, height=.5, name="rr", gp = gpar(fill = "red"))
like image 38
Oliver Avatar answered Mar 19 '23 22:03

Oliver