#r #ggplot2 #random
#r #ggplot2 #Случайный
Вопрос:
Ребята,
Я пытаюсь воспроизвести известную компьютерную художественную работу «Компьютерная композиция с линиями» А. Майкла Нолла на языке R, используя ggplot.
Вот оригинал: https://collections.vam.ac.uk/item/O1193787/computer-composition-with-lines-photograph-noll-a-michael/
Я дошел до того, что могу создать круг из случайных черных или белых пикселей, но мне трудно создавать шаблоны, подобные тем, которые использует Noll.
Я могу легко создать матрицу из единиц и нулей, а затем вырезать части, которые выходят за пределы круга. Но шаблон (я пробовал равномерный, бета, обычный …) определенно слишком похож на белый шум, в то время как в случайности оригинальной работы есть структура.
library(tidyverse)
# this generates the matrix
genData <- function(N) {
# a N*N matrix of ones and zero according to a rounded beta draw
df <- tibble(x = rep(seq(1,N), N),
y = rep(seq(1,N), each = N),
z = round(rbeta(N*N, 2, 1)))
# centering on zero and cutting away all points outside of a circle
df %>%
mutate(x = x-(N/2 1), y = y-(N/2 1)) %>%
filter(x^2 y^2 < (N/2)^2)
}
#this plots the data
plotData <- function(df, color = "black"){
df %>%
ggplot(aes(x,y, fill = as.factor(z)))
geom_tile()
scale_fill_manual(values = c(color, "white"))
coord_equal()
theme_void()
theme(legend.position = "none")
}
#executing
genData(100) %>%
plotData()
Что приводит к:
Я полагаю, вопрос сводится к тому, какой случайный процесс я могу использовать здесь? Я не нашел ни одной зацепки в Интернете.
Ответ №1:
Я думаю, это немного приблизит вас. Я также сократил код, используя geom_segment
, который позволяет извлекать длины из распределения Пуассона.
Она включает в себя некоторую логику, чтобы сделать строки в верхней части короче.
Если вы попробуете это с разными случайными начальными значениями, вы, вероятно, найдете то, что вам понравится:
draw_picture <- function(seed = 1, density = 1, length = 2,
col = "black", bg = "gray90")
{
set.seed(seed)
x <- sample(100, 600 * density, TRUE) - 50
y <- sample(100, 600 * density, TRUE) - 50
ss <- which(sqrt(x^2 y^2) < 50)
x <- x[ss]
y <- y[ss]
orient <- sample(2, length(x), TRUE)
lambda <- abs(ifelse(y > 0, length - 2/3 * length * abs(atan(y/x)), length))
lens <- rpois(length(x), lambda) 1
end_x <- (orient %% 2) * lens x
end_y <- (orient - 1) * lens y
df <- data.frame(x, y, end_x, end_y)
ggplot(df, aes(x, y))
geom_segment(aes(xend = end_x, yend = end_y), color = col, size = 2)
coord_equal()
theme_void()
theme(panel.background = element_rect(fill = bg, color = NA))
}
Итак, вы можете сделать:
draw_picture(8)
Или настройте ее с помощью параметров:
draw_picture(2020, density = 0.9, length = 5, col = "#567AFF", bg = "#2345A0")
Комментарии:
1. Блестяще. Спасибо, это определенно становится ближе. Я не думал об использовании geom_segment, я думал о какой-то игре с правилами жизни для точек, чтобы сегменты «появлялись». Я полагаю, что оставшееся (трудное, насколько я вижу) — это иметь точечные артефакты вверху, а более сегментные — внизу. Случайный процесс должен каким-то образом зависеть от позиции, но я не понял, как. Спасибо!
2. @PaoloCrosetto это тоже возможно, хотя я не был уверен, было ли это просто случайным. Я посмотрю еще раз, когда вернусь к своему компьютеру.
3. не могли бы вы просто создать
length
функциюx
иy
? например, расстояние от75,75
4. @PaoloCrosetto смотрите мое обновление. Это еще немного ближе.