====== visualR ====== ### Nota: após a finalização do código, o código foi reformatado utilizando a função "reformat code" do RStudio. ### Por conta disso, algumas linhas não estão comentadas, mas cada código usado está devidamente comentado. ## Cria a função visualR. visualR <- # Estabelece os parâmetros iniciais para a função. function(text = NULL, # vetor opcional com texto que será inserido no diagrama. Por padrão é NULL. color = "multi", # Estabelece a cor do diagrama. Por padrão é "multi" line = 2, # Estabelece o tipo de linha do diagrama. Por padrão é 2 (seta começo->fim) words = FALSE, # Opcional, estabelece a quantidade de palavras que o usuário irá escrever. arrows = FALSE, # Opcional, estabelece a quantidade de setas/linhas que o usuário irá desenhar. rectangle = TRUE, # Estabelece se um retângulo será desenhado ou não ao redor das palavras. font = "sans", # Estabelece o tipo de fonte do diagrama arrow.col = NULL){ #Opcional, estabelece uma cor única para a seta/linha ## Verificação das condições # Vê se as condições para a função foram satisfeitas if (is.null(text) == FALSE) { # Se texto não é nulo if (is.character(text) == FALSE) { #Caso o vetor text não seja character t.format <- class(text) #Grava a classe atual de text text <- as.character(text) #Converte text em character cat(paste( #Informa ao usuário a conversão de text em character (informando o tipo anterior) c( "TEXT convertido de", t.format, "para classe character. \n", "Resultado da conversão: \n", text, "\n" ), sep = " " )) } if (length(text) < 2) { #Verifica se o comprimento de text é menor que 2, e caso sim, para a função. stop("TEXT deve ser um vetor de tamanho maior ou igual a 2. \n") #Para e retorna mensagem de erro } if (max(nchar(text)) > 10) { #Verifica se alguma palavra do vetor text tem mais de 10 caracteres stop( "Número de caracteres excedido em TEXT. O número máximo de caracteres por palavra é 10. \n" #Para e retorna mensagem de erro. ) } if (is.numeric(words)) { #Verifica se WORDS foi definido pelo usuário na presença do vetor text cat( #Apenas comunica ao usuário que WORDS será ignorado nesse caso "WORDS não é um argumento quando TEXT está presente. Número de valores em TEXT será usado. \n" ) } } if (is.numeric(words) == FALSE & is.null(text)) { #Verifica se words e text estão ausentes. #Nesse caso o usuário terá um limite de 200 palavras e poderé parar quando quiser. cat(#Apenas comunica ao usuário esse fato. "WORDS e TEXT não especificados. \n O usuário terá um limite de 200 palavras, podendo parar quando quiser. \n" ) } if (is.numeric(words) & is.null(text)) { #Verifica se words está presente e text ausente. if (words < 2) { # Se sim, verifica se words é um número maior ou igual a 2 stop("WORDS deve ser um valor maior que 2 \n") # Caso words <2, para a função } if (words != as.integer(words)) { # Verifica se words é um número inteiro stop("WORDS deve ser um número inteiro \n") # Caso não seja, para a função } } if (is.numeric(arrows)) { # Verifica se arrows está presente if (arrows <= 0) { # Se sim, verifica se arrows é um número maior que 0 stop("ARROWS deve ser um valor maior que 0 \n") # Caso arrows <0, para a função } if (arrows != as.integer(arrows)) { # Verifica se arrows é um número inteiro stop("ARROWS deve ser um número inteiro \n") # Caso não seja, para a função } } ## Criação do espaço gráfico # Estabelece as configurações para o espaço gráfico par( mar = c(1, 1, 1, 1), # Estabelece margens mínimas family = font # Estabelece a família de fontes do diagrama a partir do objeto font ) # Plota o gráfico vazio, para criar o espaço onde o diagrama será desenhado plot( 0, # x0,y0 50, # x1,y1 ann = FALSE, # Remove anotações type = "n", # Tipo de gráfico "vazio" bty = "n", # Remove o quadrado em volta do gráfico plt = c(0, 1, 0, 1), # Coordenadas da região de plotagem como fração da região de figura atual. xaxt = "n", # Remove o eixo X yaxt = "n" # Remove o eixo Y ) ## Estabelece a quantidade de palavras para os diferentes casos (cria o objeto qt com essa quantidade) if (words) { #Caso words tenha sido estabelecido define qt como a quantidade de palavras que o usuário escolheu. qt <- words } if (is.character(text)) {#caso o vetor text esteja presente, usa o comprimento e text como quantidade de cliques (cada palavra será um clique) qt <- length(text) } if (is.character(text) == FALSE & isFALSE(words)) {# Caso nem words nem text tenham sido estabelecidos, dá um limite de 200 palavras para o usuário. qt <- 200 } ## Criação de cores aleatórias # Para a criação de cores aleatórias, a quantidade de palavras é usada como parâmetro definindo quantas cores serão criadas. # Assim, caso arrows tenha sido estabelecido e seja maior que a quantidade de palavras será necessário gerar cores para as setas adicionais. if (arrows > qt) {# caso arrows seja maior que qt qt.col <- arrows # Cria o objeto qt.col com o valor de arrows } else { #Se arrows não é maior que qt qt.col <- qt #Cria o objeto qt.col com o mesmo valor de qt } if (color == "multi") { #Cria as cores para a opção "multi" (cores aleatórias) random.c <- TRUE #Cria o objeto random.c com o valor TRUE (será usado para identificar o uso de multi-cores) colors <- #Cria o objeto colors data.frame( #Um dataframe com três colunas (r,g,b), cada uma com uma repetição de NAs pelo valor de qt.col r = rep(NA, qt.col), g = rep(NA, qt.col), b = rep(NA, qt.col) ) for (i in 1:qt.col) { #Cria um ciclo de 1 a qt.col random <- seq(from = 0.3, #Cria o objeto random com uma sequência de 0.3 (para evitar cores claras) a 1 to = 1, length.out = qt.col) #O comprimento dessa sequência será o valor de qt.col colors[i, 1] <- sample(random, 1) #Pega um valor aleatório do objeto random e coloca na linha i da coluna 1 de colors colors[i, 2] <- sample(random, 1) #Pega um valor aleatório do objeto random e coloca na linha i da coluna 2 de colors colors[i, 3] <- sample(random, 1) #Pega um valor aleatório do objeto random e coloca na linha i da coluna 3 de colors } } if (color == "grayscale") { #Cria as cores para a opção "grayscale" (cores aleatórias) random.c <- TRUE #Cria o objeto random.c com o valor TRUE (será usado para identificar o uso de multi-cores) colors <- #Cria o objeto colors data.frame( #Um dataframe com três colunas (r,g,b), cada uma com uma repetição de NAs pelo valor de qt.col r = rep(NA, qt.col), g = rep(NA, qt.col), b = rep(NA, qt.col) ) for (i in 1:qt.col) { #Cria um ciclo de 1 a qt.col random <- seq(from = 0.1, #Cria o objeto random com uma sequência de 0.1 a 0.7 (para evitar cores muito escuras) to = 0.7, length.out = qt.col) #O comprimento dessa sequência será o valor de qt.col samp <- sample(random, 1) #Cria o objeto samp com um valor aleatório de random colors[i, 1] <- samp #Coloca o valor de samp na linha i da coluna 1 de colors colors[i, 2] <- samp #Coloca o valor de samp na linha i da coluna 1 de colors colors[i, 3] <- samp #Coloca o valor de samp na linha i da coluna 1 de colors } } if (color != "multi" & color != "grayscale") { #Caso color não seja do tipo "multi" ou "grey.scale", será uma cor fixa estabelecida pelo usuário random.c <- FALSE #cria o objeto random.c com o valor FALSE colors <- #Cria o objeto colors com o valor do objeto color color } if (is.null(arrow.col) == FALSE) { # Verifica se foi estabelecida uma cor única para as setas/linhas arrow.c <- TRUE #Se sim, cria o objeto arrow.c com o valor TRUE (será usado como marcador) } else{ arrow.c <- FALSE #Se não, cria o objeto arrow.c com o valor FALSE } ## Inicia a inserção dos objetos no diagrama for (i in 1:qt) { # Cria um ciclo de 1 a qt (quantidade de palavras) cat("Clique onde você deseja o texto \n") # Imprime a mensagem para o usuário point <- locator(1) # Cria o objeto point com o valor de locator (1 clique) if (random.c) { # Caso random.c seja TRUE col <- rgb(colors$r[i], colors$g[i], colors$b[i], 1) # Cor do retângulo/linha será rgb pegando a posição i de cada coluna. Alpha 1. } else { # Caso random.c não seja TRUE col <- colors # Cor do retângulo/linha será o valor de colors (fixo) } if (is.null(text) == FALSE) { # Caso o vetor text esteja presente text.w <- strwidth(text[i]) # Grava no objeto text.w o comprimento da palavra na posição i do vetor text text.h <- strheight(text[i]) # Grava no objeto text.h a altura da palavra na posição i do vetor text } if (is.numeric(words) & is.null(text)) { # Se words foi estabelecido e text não está presente text.r <- readline("Escreva seu texto (max 10 caracteres) \t") # Cria o objeto text.r com o texto inserido pelo usuário if (nchar(text.r) > 10) { # Verifica se o texto inserido pelo usuário tem mais de 10 caracteres text.r <- # Caso tenha mais de 10 caracteres, dá uma nova chance do usuário escrever o texto. readline("Número de caracteres excedido. Escreva um novo texto (max 10 caracteres) \t") if (nchar(text.r) > 10) { # Caso tenha mais de 10 caracteres novamente stop("Número de caracteres excedido") # Para a função e imprime a mensagem } } text.w <- strwidth(text.r) # Grava no objeto text.w o comprimento da palavra de text.r text.h <- strheight(text.r) # Grava no objeto text.h a altura da palavra de text.r } if (is.numeric(words) == FALSE & is.null(text)) { #Se words e text estão ausentes text.r <- # Cria o objeto text.r com o texto inserido pelo autor #Dá a opção do usuário escrever para finalizar a etapa de digitação de texto readline("Escreva seu texto (max 10 caracteres) ou para finalizar as palavras \n") if (nchar(text.r) > 10) { # Verifica se o texto inserido pelo usuário tem mais de 10 caracteres text <- # Caso tenha mais de 10 caracteres, dá uma nova chance do usuário escrever o texto. readline("Número de carcteres excedido. Escreva um novo texto (max 10 caracteres) \n") if (nchar(text.r) > 10) { # Caso tenha mais de 10 caracteres novamente stop("Número de caracteres excedido") # Para a função e imprime a mensagem } } text.w <- strwidth(text.r) # Grava no objeto text.w o comprimento da palavra de text.r text.h <- strheight(text.r) # Grava no objeto text.h a altura da palavra de text.r if (text.r == "") { # Se o usuário digitou ## Desenho das setas, caso o usuário tenha digitado for (i in 1:qt) { # Inicia um ciclo de 1 a qt if (random.c) { # Caso random.c seja TRUE col <- rgb(colors$r[i], colors$g[i], colors$b[i], 1) # Cor do retângulo/linha será rgb pegando a posição i de cada coluna. Alpha 1. } else { # Caso random.c não seja TRUE col <- colors # Cor do retângulo/linha será o valor de colors (fixo) } if (arrow.c) { #Se arrow.c for TRUE col <- arrow.col #Substitui o valor de col pelo valor de arrow.col (inserido pelo usuário) } cat("Clique no ponto de início e término da seta/linha \n") # Imprime a mensagem para o usuário desenhar a linha ## Setas if (line <= 3) { # Se a linha for do tipo 1 a 3 point <- locator(2) # Cria o objeto point com os valores de locator (dois cliques) arrows( # Cria uma seta point$x[1], #Posição x1 da seta, com o valor da posição 1 de x de point point$y[1], #Posição y1 da seta, com o valor da posição 1 de y de point point$x[2], #Posição x2 da seta, com o valor da posição 2 de x de point point$y[2], #Posição y2 da seta, com o valor da posição 2 de y de point length = 0.1, # Define o comprimento das linhas da ponta da seta angle = 30, # Define o ângulo da seta code = line, # Define o tipo de seta (1,2 ou 3 - ver help de arrows para mais informações) col = col, # Define a cor da seta com o valor de col lwd = 2 # Define a espessura da linha da seta ) } ## Linha com pontos na ponta if (line == 4) { # Se a linha for do tipo 4 point <- locator(2) # Cria o objeto point com os valores de locator (dois cliques) segments(point$x[1], # Posição x1 da seta, com o valor da posição 1 de x de point point$y[1], # Posição y1 da seta, com o valor da posição 1 de y de point point$x[2], # Posição x2 da seta, com o valor da posição 2 de x de point point$y[2], # Posição y2 da seta, com o valor da posição 2 de y de point col = col, # Define a cor da linha com o valor de col lwd = 2) # Define a espessura da linha points(point$x[1], # Cria um ponto na posição 1 de x de point point$y[1], # e posição 1 de y de point pch = 19, # do tipo 19 col = col) # e cor com o valor de col points(point$x[2], # Faz o mesmo usando o valor da posição 2 de x de point point$y[2], # e posição 2 de y de point pch = 19, col = col) } ## Linha simples if (line == 5) { # Se a linha for do tipo 5 point <- locator(2) # Cria o objeto point com os valores de locator (dois cliques) segments(point$x[1], # Posição x1 da seta, com o valor da posição 1 de x de point point$y[1], # Posição y1 da seta, com o valor da posição 1 de y de point point$x[2], # Posição x2 da seta, com o valor da posição 2 de x de point point$y[2], # Posição y2 da seta, com o valor da posição 2 de y de point col = col, # Define a cor da linha com o valor de col lwd = 2) # Define a espessura da linha } finish <- # Cria o objeto finish com o texto escrito pelo usuário readline( "Deseja desenhar mais uma linha? \n Pressione enter para continuar ou digite N para parar \n" ) if (finish == "N") { # Se o valor de finish for N return("Usuário terminou o diagrama.") # Finaliza o diagrama e imprime a mensagem } } } } if (rectangle) { # Caso rectangle seja TRUE x0 <- point$x - text.w # Cria o objeto x0 com o valor de x em point, menos o valor de text.w x1 <- point$x + text.w # Cria o objeto x1 com o valor de x em point, mais o valor de text.w y0 <- point$y - text.h # Cria o objeto y0 com o valor de y em point, menos o valor de text.h y1 <- point$y + text.h # Cria o objeto y1 com o valor de y em point, menos o valor de text.h rect(x0, # Cria um retângulo com os valores de x0,x1,y0,y1 e cor com o valor de col y0, x1, y1, col = col) } if (is.null(text) == FALSE) { # Se text está presente text(point$x, point$y, labels = text[i]) # Insere o texto na posição x e y de point, com o texto da posição i do vetor text } else { # Se text está ausente text(point$x, point$y, labels = text.r) # Insere o texto na posição x e y de point, com o texto do objeto text.r (inserido pelo usuário) } } ## Desenho das setas/linhas if (is.numeric(arrows)) { # Se arrows está presente qt <- arrows # Substitui o valor de qt pelo valor de arrows } for (i in 1:qt) { # Cria um ciclo de 1 a qt if (random.c) { # Caso random.c seja TRUE col <- rgb(colors$r[i], colors$g[i], colors$b[i], 1) # Cor do retângulo/linha será rgb pegando a posição i de cada coluna. Alpha 1. } else { # Caso random.c não seja TRUE col <- colors # Cor do retângulo/linha será o valor de colors (fixo) } if (arrow.c) { #Se arrow.c é TRUE col <- arrow.col #Substitui o valor de col pelo valor de arrow.col (inserido pelo usuário) } cat("Clique no início e término da seta/linha \n") # Imprime mensagem para o usuário desenhar a seta/linha ## Setas if (line <= 3) { # Se a linha for do tipo 1 a 3 point <- locator(2) # Cria o objeto point com os valores de locator (dois cliques) arrows( # Cria uma seta point$x[1], #Posição x1 da seta, com o valor da posição 1 de x de point point$y[1], #Posição y1 da seta, com o valor da posição 1 de y de point point$x[2], #Posição x2 da seta, com o valor da posição 2 de x de point point$y[2], #Posição y2 da seta, com o valor da posição 2 de y de point length = 0.1, # Define o comprimento das linhas da ponta da seta angle = 30, # Define o ângulo da seta code = line, # Define o tipo de seta (1,2 ou 3 - ver help de arrows para mais informações) col = col, # Define a cor da seta com o valor de col lwd = 2 # Define a espessura da linha da seta ) } ## Linha com pontos na ponta if (line == 4) { # Se a linha for do tipo 4 point <- locator(2) # Cria o objeto point com os valores de locator (dois cliques) segments(point$x[1], # Posição x1 da seta, com o valor da posição 1 de x de point point$y[1], # Posição y1 da seta, com o valor da posição 1 de y de point point$x[2], # Posição x2 da seta, com o valor da posição 2 de x de point point$y[2], # Posição y2 da seta, com o valor da posição 2 de y de point col = col, # Define a cor da linha com o valor de col lwd = 2) # Define a espessura da linha points(point$x[1], # Cria um ponto na posição 1 de x de point point$y[1], # e posição 1 de y de point pch = 19, # do tipo 19 col = col) # e cor com o valor de col points(point$x[2], # Faz o mesmo usando o valor da posição 2 de x de point point$y[2], # e posição 2 de y de point pch = 19, col = col) } ## Linha simples if (line == 5) { # Se a linha for do tipo 5 point <- locator(2) # Cria o objeto point com os valores de locator (dois cliques) segments(point$x[1], # Posição x1 da seta, com o valor da posição 1 de x de point point$y[1], # Posição y1 da seta, com o valor da posição 1 de y de point point$x[2], # Posição x2 da seta, com o valor da posição 2 de x de point point$y[2], # Posição y2 da seta, com o valor da posição 2 de y de point col = col, # Define a cor da linha com o valor de col lwd = 2) # Define a espessura da linha } } return("Usuário terminou o diagrama.") # Retorna a mensagem para o usuário informando a finalização do diagrama }