We will use R to produce surface plots, heat maps and contour projections of 2D surfaces. We will be utilizing R’s ability to make these visualizations to create digital art that resembles Native American vector patterns.
We will further test the capabilities of R by demonstrating visualizations through recursive methods. The images that we will be trying to implement using recursive means are fractals.
\[ \]
What exactly are surface plots, heat maps, contour projections of 2D surfaces. What are fractals?
Heat maps are graphs where a matrix’s individual values are denoted by colors. It is a 2D representation that uses colors to help explain relationships of data that would be easier to decipher than looking at a spreadsheet equivalent. We will implement several functions to show these images.
Fractals are geometric figures that are self-similar across all of its scalar levels. That is to say that a smaller part of a fractal at different scales usually resembles the whole fractal. We will implement the Sierpinksi Carpet Fractal in R.
Our first goal is to make digital art using surface plots, heat maps and contour projections of two-dimensional surfaces. To do this we must make a given function \(z\). We first assign the independent variables \(x\) and \(y\) with their corresponding vectors of possible values that we choose. We then make a \(z\) function dependent on \(x\) and \(y\). This function will be what we formulate our plots from.
Our second goal is to show how to make fractals without using the built-in R functions. To do this we will demonstrate how to make a well-known fractal, The Sierpinksi Carpet. To make the Sierpinski Carpet we will construct a matrix: \[\boxed{f(A) = \begin{pmatrix} A_{1,1} & A_{1,2} & A_{1,3} \\ A_{2,1} & 0 & A_{2,3} \\ A_{3,1} & A_{3,2} & A_{3,3} \end{pmatrix}}\] After making this matrix, the idea will be to make a \(for-loop\) that can manipulate this matrix in such a way that when the recursive property is in-effect, each element \(A\) is treated just as the initial matrix \(f(A)\) has been treated.
Here we initialize the surface \(z\) to show the 12 points we will sample from.
library("plot3D") #required library for plots
x <- c(1,2,3,4) #vector of x-values
y <- c(-1,0,1) #vector of y-values
z <- 2*x + 5*y #given function
M <- mesh(x,y) #creates a rectangular full 2D or 3D grid
zz <- 2*M$x + 5*M$y #using Mesh in tandem with our independent variables to get our 12 points
M$x
## [,1] [,2] [,3]
## [1,] 1 1 1
## [2,] 2 2 2
## [3,] 3 3 3
## [4,] 4 4 4
M$y
## [,1] [,2] [,3]
## [1,] -1 0 1
## [2,] -1 0 1
## [3,] -1 0 1
## [4,] -1 0 1
zz
## [,1] [,2] [,3]
## [1,] -3 2 7
## [2,] -1 4 9
## [3,] 1 6 11
## [4,] 3 8 13
plot(M$x,M$y, xlim=c(0.5,4.5), ylim=c(-1.5,1.5), col = "blue", pch = 16, xlab="x-values", ylab="y-values") #plotting our points
This is the plot of the actual surface we generate from the given vectors of \(x\) and \(y\).
persp3D( M$x, M$y, zz, colvar=zz, colkey = FALSE, shade = 0.1, box = FALSE, theta = 60) #plotting the surface
This is the corresonding heat map of the matrix \(zz\). As we can see colors are assigned to each number from the matrix to produce this heat map. Colors that are close to each other are indicative of close numbers.
zz
## [,1] [,2] [,3]
## [1,] -3 2 7
## [2,] -1 4 9
## [3,] 1 6 11
## [4,] 3 8 13
image(zz, axes=FALSE)
Now that we made a heat map in 2D we are going to up the ante and the dimension by one. We will be using the function \(z = cos(x^{2}+y^{2})*e^{\frac{-1}{\pi})\sqrt{x^{2}+y^{2}}}\) as our given function. Repeating the same steps as above we would generate another plot this time 3-dimensional as our initial function does not generate a simple plane in the \(xyz\) coordinate system. \[ \] To get a better descriptive look at the graphical interpretation of this function we must set the independent variables to all the variables within its domain. Since we are dealing with trig functions the domain is \(-2\pi \ to \ 2*\pi\). This time we will consider the function of two variables z= f(x,y), which defines a surface in 3D: \[z=cos(x^2+y^2)e^{\frac{-1}{\pi}\sqrt{x^2+y^2}}\]
x <- seq(-2*pi,2*pi,length.out = 300) #vector of x-values
y <- seq(-2*pi,2*pi,length.out = 300) #vector of y-values
M <- mesh(x,y) #creates a rectangular full 2D or 3D grid
z <- cos(x^2 + y^2)*exp((-1/pi)*sqrt(x^2 + y^2)) #our given function
zz <- cos(M$x^2 + M$y^2)*exp((-1/pi)*sqrt(M$x^2 + M$y^2)) #using Mesh in tandem with our independent variables
persp3D( M$x, M$y, zz, colvar=zz, colkey = FALSE, shade = 0.5, box = FALSE, theta = 60) #plotting the surface
We will now use our proven methods our gerenating heat maps and contour plots to generate digital art. Our new function is \[z=cos(x^2+y^2)e^{\frac{-1}{\pi^2}\sqrt{x^2+y^2}}\]. We will sample 27 points from the interval \((-4\pi, 4\pi)\).
x <- seq(-4*pi,4*pi,length.out = 27) #vector of x-values
y <- seq(-4*pi,4*pi,length.out = 27) #vector of y-values
M <- mesh(x,y)
z <- cos(x^2 + y^2)*exp((-1/pi)*sqrt(x^2 + y^2)) #our given function
zz <- cos(M$x^2 + M$y^2)*exp((-1/pi)*sqrt(M$x^2 + M$y^2)) #using Mesh in tandem with our independent variables
persp3D( M$x, M$y, zz, colvar=zz, colkey = FALSE, shade = 0.5, box = FALSE, theta = 60) #plotting the surface
We now show the aerial view of the function now added with contour plots to finish our digital art masterpiece.
image2D(zz, axes=FALSE)
contour2D(zz,add=TRUE,colkey=FALSE,drawlabels=FALSE,axes=FALSE,frame=TRUE)
We repeat the same steps as before this time using \(image()\) to plot the heat map. We also use \(contour()\) to superimpose the contour plot of \(z\). Our new function is \[z=tan(x^2+y^2)e^{\frac{-1}{\pi^2}\sqrt{x^2+y^2}}\]. We will sample 27 points from the interval \((-7\pi, 7\pi)\).
x <- seq(-7*pi,7*pi,length.out = 27)
y <- seq(-7*pi,7*pi,length.out = 27)
M <- mesh(x,y)
z <- tan(x^2 + y^2)*exp((-1/pi^2)*sqrt(x^2 + y^2))
zz <- tan(M$x^2 + M$y^2)*exp((-1/pi^2)*sqrt(M$x^2 + M$y^2))
persp3D( M$x, M$y, zz, colvar=zz, colkey = FALSE, shade = 0.5, box = FALSE, theta = 60)
image(zz,axes=FALSE)
contour(zz,add=TRUE,colkey=FALSE,drawlabels=FALSE,axes=FALSE,frame=TRUE)
To make the Sierpinksi Carpet we must first generate a matrix f(A).\[\boxed{f(A) = \begin{pmatrix} A & A & A \\ A & 0 & A \\ A & A & A \end{pmatrix}}\] An effective way to do this is with binding. R has built-in functions to bind elements by row and by column. We take advantage of this by using a couple of binds in quick-succesion. First we bind 3 copies of the element \(A\) by column to form a row of 3 elements of A. That will be our top row of our desired matrix. The middle element in the second row will eventually be our “hole” that we see through each of the iterations. To get the second row with a zero in the middle we do the same bind except that we multiply the middle element by 0. It must be multiplied and not just inputted as zero because if the element is a matrix, the act of multipliying by zero will count as multiplying by the zero matrix.
\[ \] We will first generate the matrix above which is the same as a Level 1 Sierpinski Carpet.
IterateCarpet <- function(A){
B <- cbind(A,A,A) #Binds three elements names A into a row of A.
C <- cbind(A,0*A,A) #Binds three elements names A into a row of A with the middle element multiplied by 0 to indicate the hole in the level 1 carpet.
D <- rbind(B,C,B) #Binds three rows together to form a 3x3 Matrix
return(D)
}
S <- matrix(1,1,1);
S <- IterateCarpet(S);
image(S,col=c(0, 12), axes=FALSE, asp=1)
Now that we have the Level 1 Carpet we must add a \(for-loop\) that will allow us to add the recursion that will show the self-similar property that fractals are known for.
IterateCarpet <- function(A){
B <- cbind(A,A,A)
C <- cbind(A,0*A,A)
D <- rbind(B,C,B)
return(D)
}
S <- matrix(1,1,1);
for(i in 1:2)
S <- IterateCarpet(S);
image(S,col=c(0, 12), axes=FALSE, asp=1)
Level 6 Sierpinski Carpet : As you can see we manipulate recursion by changing the number of iteration in the \(for-loop\).
IterateCarpet <- function(A){
B <- cbind(A,A,A)
C <- cbind(A,0*A,A)
D <- rbind(B,C,B)
return(D)
}
S <- matrix(1,1,1);
for(i in 1:6)
S <- IterateCarpet(S);
image(S,col=c(0, 12), axes=FALSE, asp=1)
Now that we know our function is reliable in finding fractals we get creative by manipulating the initial matrix \(f(A)\) solely to get various fractals.
IterateStar <- function(A){
B <- cbind(A, A*0, A)
C <- cbind(A*0, A, A*0)
D <- cbind(A, A*0, A)
E <- rbind(B,C,D)
return(E)
}
t <- matrix(1,1,1);
for(i in 1:6) t <- IterateStar(t);
image(t,col=c(0, 12), axes=FALSE, asp=1)
IterateModified <- function(A){
B <- cbind(A*0 , A*0, A)
C <- cbind(A*0 , A, A)
D <- cbind(A , A, A)
E <- rbind(B,C,D)
return(E)
}
t <- matrix(1,1,1);
for(i in 1:6) t <- IterateModified(t);
image(t,col=c(0, 12), axes=FALSE, asp=1)
We want to look into other kinds of fractals. Fractals can be created by simulating different kinds of dynamical systems.
wallpaper<-function(n=4E4,x0=1,y0=1,a=1,b=4,c=60){
x<-c(x0,rep(NA,n-1))
y<-c(y0,rep(NA,n-1))
cor<-rep(0,n)
for (i in 2:n){
x[i] = y[i-1] - sign(x[i-1])*sqrt(abs( b*x[i-1] - c) )
y[i] = a - x[i-1]
cor[i]<-round(sqrt((x[i]-x[i-1])^2+(y[i]-y[i-1])^2),0)
}
n.c<-length(unique(cor))
cores<-heat.colors(n.c)
plot(x,y,pch=".",col=cores[cor])
}
wallpaper()
Here we use Euler’s Method to simulate chaotic dynamical systems.
library("rgl")
LiSys <- function(n, a=5, b=16, c=1, x0=5, y0=4, z0=10){
x<-c(x0,rep(NA,n-1))
y<-c(y0,rep(NA,n-1))
z<-c(z0,rep(NA,n-1))
h<-0.01
for (i in 2:n){
x[i] = x[i-1] + h*(a*(y[i-1]-x[i-1]))
y[i] = y[i-1] + h*(x[i-1]*z[i-1] - y[i-1])
z[i] = z[i-1] + h*(b - x[i-1]*y[i-1] - c*z[i-1])
}
require(rgl)
rgl.clear()
rgl.points(x,y,z, color=heat.colors(n), size=2)
}
LiSys(20000)
ThoSys <- function(n, b=0.209, x0=0.5, y0=0.4, z0=0.8){
x<-c(x0,rep(NA,n-1))
y<-c(y0,rep(NA,n-1))
z<-c(z0,rep(NA,n-1))
h<-0.01
for (i in 2:n){
x[i] = x[i-1] + h*(sin(y[i-1]) - b*x[i-1])
y[i] = y[i-1] + h*(sin(z[i-1]) - b*y[i-1])
z[i] = z[i-1] + h*(sin(x[i-1]) - b*z[i-1])
}
require(rgl)
rgl.clear()
rgl.points(x,y,z, color=heat.colors(n), size=2)
}
ThoSys(20000)
The Fractal Dragon has many names, The Dragon Curve, The Heighway Dragon or even The Jurassic Park Fractal. It is very difficult to code but the concept is very easy to understand.
Dragon<-function(Iters){
Rotation<-matrix(c(0,-1,1,0),ncol=2,byrow=T) #Rotation multiplication matrix
Iteration<-list() #Set up list for segment matrices for 1st
Iteration[[1]] <- matrix(rep(0,16), ncol = 4)
Iteration[[1]][1,]<-c(0,0,1,0)
Iteration[[1]][2,]<-c(1,0,1,-1)
Moveposition<-rep(0,Iters) #Which point should be shifted to origin
Moveposition[1]<-4
if(Iters > 1)
{ #where to move to get to origin
for(l in 2:Iters)
{#####################################only if >1, because 1 set before for loop
Moveposition[l]<-(Moveposition[l-1]*2)-2#############sets vector of all positions in matrix where last point is
}
}
Move<-list() ########################################vector to add to all points to shift start at origin
for (i in 1:Iters)
{
half<-dim(Iteration[[i]])[1]/2
half<-1:half
for(j in half)
{########################################Rotate all points 90 degrees clockwise
Iteration[[i]][j+length(half),]<-c(Iteration[[i]][j,1:2]%*%Rotation,Iteration[[i]][j,3:4]%*%Rotation)
}
Move[[i]]<-matrix(rep(0,4),ncol=4)
Move[[i]][1,1:2]<-Move[[i]][1,3:4]<-(Iteration[[i]][Moveposition[i],c(3,4)]*-1)
Iteration[[i+1]]<-matrix(rep(0,2*dim(Iteration[[i]])[1]*4),ncol=4)##########move the dragon, set next Iteration's matrix
for(k in 1:dim(Iteration[[i]])[1])
{#########################################move dragon by shifting all previous iterations point
Iteration[[i+1]][k,]<-Iteration[[i]][k,]+Move[[i]]###so the start is at the origin
}
xlimits<-c(min(Iteration[[i]][,3])-2,max(Iteration[[i]][,3]+2))#Plot
ylimits<-c(min(Iteration[[i]][,4])-2,max(Iteration[[i]][,4]+2))
plot(0,0,type='n',axes=FALSE,xlab="",ylab="",xlim=xlimits,ylim=ylimits)
s<-dim(Iteration[[i]])[1]
s<-1:s
segments(Iteration[[i]][s,1], Iteration[[i]][s,2], Iteration[[i]][s,3], x0 = Iteration[[i]][s,4], col= 'red')
}
}#########################################################################
R is mainly known for its value in statistics and its number crunching abilities. However it is not well known that R is a software that you can use to make digital art. We used mathematics to show heat maps and fractals, both with ubiquitous application in the world. We have proved that R is a viable way to show amazing artistic creations.