Random fun with repetitive elements in R trying to get something nice out of geometrical patterns.

Disco ball

plot(0,0,xlim=c(0,100), ylim = c(0,100), col = "white", bty = "n", xaxt = "n", yaxt = "n", ylab = NA, xlab = NA, cex = 0)
dfx = as.data.frame(matrix(rep(1:100, 100), nrow = 100))
for(i in seq(1,100,2)) points(y = dfx[i,], x = dfx[,i], cex = runif(100, 0.1, 1.3), col = colorRampPalette(c("gray", "orange", "purple"))(100)[i], pch = 16)

Waves 1

plot(0,0,xlim=c(0,100), ylim = c(0,100), col = "white", bty = "n", xaxt = "n", yaxt = "n", ylab = NA, xlab = NA)
for(i in seq(1,100,2)) for(j in seq(1,100,2)) points(y = i, x = j+cos(i), cex = i/100, pch = 16)

Fur 1

plot(0,0,xlim=c(0,100), ylim = c(0,100), col = "white", bty = "n", xaxt = "n", yaxt = "n", ylab = NA, xlab = NA, cex = 0)
for(i in seq(1,100,3)) for(j in seq(1,100,2)) segments(y0 = i, x0 = j+cos(runif(1,-1,1)), y1 = i+2+runif(1,0,2), x1 = j+sin(runif(1,0,1))+(2*cos(runif(1,-1,1)))+runif(1,0,2), lwd = cos(j)*sin(i), col = colorRampPalette(c("gray", "orange", "purple"))(100)[i])

Fur 2

(speed optimized)

dfy1 <-  matrix(1:10000, nrow = 100)
dfx1 <- matrix(1:10000, nrow = 100)
dfx0 <- matrix(1:10000, nrow = 100)
for(i in 1:100)

{
    dfx0[i,] = i + cos(runif(100, -1, 1))
    dfy1[i,] = i + cos(runif(100, 0, 2))
    dfx1[i,] = i-2*cos(runif(100, -1, 1) + runif(100, 0, 2))

}

dfy1 <- as.data.frame(dfy1, stringsAsFactors = F)
dfx1 <- as.data.frame(dfx1, stringsAsFactors = F)
dfx0 <- as.data.frame(dfx0, stringsAsFactors = F)

plot(0,0,xlim=c(0,100), ylim = c(0,100), col = "white", bty = "n", xaxt = "n", yaxt = "n", ylab = NA, xlab = NA, cex = 0)
for(i in seq(1,100,1)) segments(y0 = i, x0 = dfx0[,i], y1 = i+2, x1 = dfx1[,i], lwd = runif(100,0,1), col = colorRampPalette(c("gray", "orange", "purple"))(100)[i])

Waves 2

pal = colorRampPalette(c("white", "deepskyblue", "cadetblue"))(100)
plot(0,0,xlim=c(0,100), ylim = c(0,100), col = "white", bty = "n", xaxt = "n", yaxt = "n", ylab = NA, xlab = NA)
for(i in seq(1,100,3)) for(j in seq(1,100,1)) points(y = i+sin(j), x = j+cos(i), cex = j/100, pch = 16, col = pal[i])

Waves 3

pal = colorRampPalette(c("lightgoldenrodyellow", "azure", "deepskyblue", "cadetblue"))(100)
v = 1:100
df = as.data.frame(matrix(v,nrow=100,ncol=100,byrow=TRUE))
dfy = sin(df)
dfy2 = apply(dfy, 2, function(x) x+seq(1,100,1))
par(bg = "black")
plot(0,0,xlim=c(0,100), ylim = c(0,100), col = "white", bty = "n", xaxt = "n", yaxt = "n", ylab = NA, xlab = NA, cex = 0)
for(i in seq(1,100,1))  lines(smooth.spline(y = dfy2[i,], x = dfy2[,i], spar = i/200), lwd = i/100+0.5, col = pal[i])

Space invaders

This simple algorithm plots random points, calculates the Euclidean distance between them and clusters them by cutting the tree at an arbitrary height. Within each cluster, points are ordered by distance. Segments are then drawn within each clustered set of ordered points with random width.

xs = runif(200, 1, 100)
ys = runif(200, 1, 100)
tmp <- dist(cbind(xs,ys))
hc = hclust(tmp)
cutt =  cutree(hc, h = 41)
dat = as.data.frame(cbind(xs, ys, cutt))


plot(dat$xs, dat$ys, pch = 16, cex = 0.4,  bty = "n", xaxt = "n", yaxt = "n", xlab = NA, ylab = NA)
for(i in unique(dat$cutt)){
nr = length(which(dat$cutt == i))
dat.tmp = dat[which(dat$cutt == i),]
dist.tmp = dist(dat.tmp)
order.dist = order(dist.tmp)
#for (j in 1:length(order.dist))
#dist.tmp[order.dist[j]]
for(j in 1:nr) segments(dat$xs[which(dat$cutt == i)][j], dat$ys[which(dat$cutt == i)][j], dat$xs[which(dat$cutt == i)][j+1], dat$ys[which(dat$cutt == i)][j+1], lwd = runif(1,0.1,1.5))
}

Space invaders 2

Same as in Space invaders, but polygons are drawn rather than segments

plot(dat$xs, dat$ys, pch = 16, cex = 0.4,  bty = "n", xaxt = "n", yaxt = "n", xlab = NA, ylab = NA)
for(i in unique(dat$cutt)){
nr = length(which(dat$cutt == i))
dat.tmp = dat[which(dat$cutt == i),]
dist.tmp = dist(dat.tmp)
order.dist = order(dist.tmp)
#for (j in 1:length(order.dist))
#dist.tmp[order.dist[j]]
for(j in 1:nr) polygon(dat.tmp$xs, dat.tmp$ys, lwd = runif(1,0.1,1.5))
}

Space invaders 3

Same as above, but clustered points are joined by the vertices of their Delauney triangulation, making for a nicer set of shapes. The outermost vertices are actually the convex hull for that point cluster.

xs = runif(200, 1, 100)
ys = runif(200, 1, 100)
tmp <- dist(cbind(xs,ys))
hc = hclust(tmp)
cutt =  cutree(hc, h = 41)
dat = as.data.frame(cbind(xs, ys, cutt))


library(deldir)

plot(dat$xs, dat$ys, pch = 16,  bty = "n", xaxt = "n", yaxt = "n", xlab = NA, ylab = NA, cex = 0)
for(i in unique(dat$cutt)){
nr = length(which(dat$cutt == i))
dat.tmp = dat[which(dat$cutt == i),]
dist.tmp = dist(dat.tmp)
order.dist = order(dist.tmp)
#for (j in 1:length(order.dist))
#dist.tmp[order.dist[j]]

vtess <- deldir(dat.tmp$xs, dat.tmp$y)
    
    plot(vtess, wlines="triang", wpoints="dummy", number=FALSE, add=TRUE, lty=1, col = colorRampPalette(c("gray", "orange", "purple"))(length(unique(dat$cutt)))[i])
    points(dat.tmp$xs, dat.tmp$ys, pch = 16, cex = runif(nr, 0.1, 1), col = colorRampPalette(c("gray", "orange", "purple"))(length(unique(dat$cutt)))[i])

}

Spirals

rotate = function(a,b,i)
{ 
    ar = a*cos(i) - b*sin(i)
    br = a*sin(i) + b*cos(i)

return(c(ar, br))
}

plot(0,0, pch = 16,  bty = "n", xaxt = "n", yaxt = "n", xlab = NA, ylab = NA, cex = 0, ylim = c(0,200), xlim = c(0,400))
    for(j in seq(1,300, by = 2)){

    for(i in seq(0,20,by=0.2)){ 

    rx = rotate(a = c(0,1,1,0), b = c(0,0,1,1), i*(j/5))
    polygon(x = rx[1:4]+(i*15), y = rx[5:8]+j, col = colorRampPalette(c("gray", "red"))(400)[j], border = NA)
        }
    }

    plot(0,0, pch = 16,  bty = "n", xaxt = "n", yaxt = "n", xlab = NA, ylab = NA, cex = 0, ylim = c(-300,300), xlim = c(-300,300))
    for(j in 1:100){
    xp = runif(100, 0, 50)
    yp = runif(100, 0, 50)
    for(i in seq(0,100,by=runif(1,0,2))){
    rx = rotate(a = xp+(i*5), b = yp-(i*5), i)
    points(x = rx[1:(length(rx)/2)]+runif(length(rx), 0, 10), y = rx[((length(rx)/2)+1):length(rx)]-runif(length(rx), 0, 10), cex = 0.1, col = rgb(0,0,0,runif(100,0,1)), pch = 16)
    }
}