library(dplyr)
## Warning: package 'dplyr' was built under R version 4.1.3
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

Example

x=c(rep(0,500),seq(0,1,length.out=1000), rep(1,500))
y=c(seq(-1,1,length.out=500),rep(0,1000), seq(-1,1,length.out=500))
z=rbind(x,y)
plot(y~x, xlim=c(-3,3), ylim=c(-3,3))

Initials

x=c(rep(0,500),seq(0,0.5,length.out=250),seq(0.5,1,length.out=250), rep(1,500), rep(2,500), seq(1.5,2.5,length.out=500),seq(1.5,2,length.out=500))
y=c(seq(-1,1,length.out=500),seq(1,0,length.out=250),seq(0,1,length.out=250), seq(-1,1,length.out=500), seq(0,1,length.out=500), rep(1,500),cos(seq(pi/1.8,(3*pi)/2,length.out=500)))
z=rbind(x,y)
plot(y~x, xlim=c(-3,3), ylim=c(-3,3))

Identity Matrix

identity <- diag(2)
leftMultiply  <- function(x,y){
   x %*% y
}

Shear

for (i in seq(0,1,length.out=40)) {
  identity[2,1]<-i
  z1<-apply(z,2,function(x) leftMultiply(x,identity))
  plot(z1[2,]~z1[1,], xlim=c(-3,3), ylim=c(-3,3))
}

Scale

identity<- diag(2)
for (i in seq(0,1,length.out=40)) {
  identity[2,2]<-i
  identity[1,1]<-i
  z1<-apply(z,2,function(x) leftMultiply(x,identity))
  plot(z1[2,]~z1[1,], xlim=c(-3,3), ylim=c(-3,3))
}

Rotate

#2pi is a full circle rotation
for (i in seq(0,2*pi,length.out=40)) {
  identity<-matrix(c(cos(i),-sin(i),sin(i),cos(i)),nrow=2,ncol=2)
  z1<-apply(z,2,function(x) leftMultiply(x,identity))
  plot(z1[2,]~z1[1,], xlim=c(-3,3), ylim=c(-3,3))
}

Projection

z.threeD<-rbind(z,rep(0, ncol(z)))
for (i in seq(0,pi/2,length.out=40)) {
  identity<- matrix(c(1,0,0,0,cos(i),-sin(i),0,sin(i),cos(i)),nrow=3,ncol=3)
  z1<-apply(z.threeD,2,function(x) leftMultiply(x,identity))
  plot(z1[2,]~z1[1,], xlim=c(-3,3), ylim=c(-3,3))
}

References

Matrix Transformation Sources for Shear, Rotate, Scale:

Matrix Transformation around the axes: