relleno - tipos de degradado
gradiente de color de tres vías de relleno en r (3)
Aquí hay una forma de hacerlo: es un poco de pirateo, usando puntos para trazar el degradado pieza por pieza:
plot(NA,NA,xlim=c(0,1),ylim=c(0,1),asp=1,bty="n",axes=F,xlab="",ylab="")
segments(0,0,0.5,sqrt(3)/2)
segments(0.5,sqrt(3)/2,1,0)
segments(1,0,0,0)
# sm - how smooth the plot is. Higher values will plot very slowly
sm <- 500
for (y in 1:(sm*sqrt(3)/2)/sm){
for (x in (y*sm/sqrt(3)):(sm-y*sm/sqrt(3))/sm){
## distance from base line:
d.red = y
## distance from line y = sqrt(3) * x:
d.green = abs(sqrt(3) * x - y) / sqrt(3 + 1)
## distance from line y = - sqrt(3) * x + sqrt(3):
d.blue = abs(- sqrt(3) * x - y + sqrt(3)) / sqrt(3 + 1)
points(x, y, col=rgb(1-d.red,1 - d.green,1 - d.blue), pch=19)
}
}
Y la salida:
¿Querías usar estos gradientes para representar datos? Si es así, puede ser posible alterar d.red
, d.green
y d.blue
para hacerlo, aunque todavía no he probado nada de eso. Espero que esto sea de alguna ayuda, pero una solución adecuada con colorRamp
, por ejemplo, probablemente sea mejor.
EDITAR : De acuerdo con la sugerencia de Baptiste, esta es la forma en que almacenaría la información en vectores y los trazaría todos a la vez. Es considerablemente más rápido (especialmente con sm
establecido en 500, por ejemplo):
plot(NA,NA,xlim=c(0,1),ylim=c(0,1),asp=1,bty="n",axes=F,xlab="",ylab="")
sm <- 500
x <- do.call(c, sapply(1:(sm*sqrt(3)/2)/sm,
function(i) (i*sm/sqrt(3)):(sm-i*sm/sqrt(3))/sm))
y <- do.call(c, sapply(1:(sm*sqrt(3)/2)/sm,
function(i) rep(i, length((i*sm/sqrt(3)):(sm-i*sm/sqrt(3))))))
d.red = y
d.green = abs(sqrt(3) * x - y) / sqrt(3 + 1)
d.blue = abs(- sqrt(3) * x - y + sqrt(3)) / sqrt(3 + 1)
points(x, y, col=rgb(1-d.red,1 - d.green,1 - d.blue), pch=19)
¿Cómo puedo rellenar gradiente de color de tres vías (mapa de calor) a un triplot (gráfico de triángulo), como este.
plot(NA,NA,xlim=c(0,1),ylim=c(0,sqrt(3)/2),asp=1,bty="n",axes=F,xlab="",ylab="")
segments(0,0,0.5,sqrt(3)/2)
segments(0.5,sqrt(3)/2,1,0)
segments(1,0,0,0)
El color debe correr en paralelo a triplot.
Aquí hay una implementación que phonR
para el paquete phonR
... la función fillTriangle
no se exporta, por lo que debe usar el operador :::
para acceder a ella. El ejemplo muestra los enfoques basados en pch y en raster.
# set up color scale
colmap <- plotrix::color.scale(x=0:100, cs1=c(0, 180), cs2=100, cs3=c(25, 100),
alpha=1, color.spec=''hcl'')
# specify triangle vertices and corner colors
vertices <- matrix(c(1, 4, 2, 1, 3, 4, length(colmap), 1, 30), nrow=3,
dimnames=list(NULL, c("x", "y", "z")))
# edit next line to change density / resolution
xseq <- yseq <- seq(0, 5, 0.01)
grid <- expand.grid(x=xseq, y=yseq)
grid$z <- NA
grid.indices <- splancs::inpip(grid, vertices[,1:2], bound=FALSE)
grid$z[grid.indices] <- with(grid[grid.indices,],
phonR:::fillTriangle(x, y, vertices))
# plot it
par(mfrow=c(1,2))
# using pch
with(grid, plot(x, y, col=colmap[round(z)], pch=16))
# overplot original triangle
segments(vertices[,1], vertices[,2], vertices[c(2,3,1),1],
vertices[c(2,3,1),2])
points(vertices[,1:2], pch=21, bg=colmap[vertices[,3]], cex=2)
# using raster
image(xseq, yseq, matrix(grid$z, nrow=length(xseq)), col=colmap)
# overplot original triangle
segments(vertices[,1], vertices[,2], vertices[c(2,3,1),1],
vertices[c(2,3,1),2])
points(vertices[,1:2], pch=21, bg=colmap[vertices[,3]], cex=2)
Aquí hay una solución con una imagen de fondo rasterizada. El parámetro de sharpness
de la función tricol
controla la rapidez con que los colores se desvanecen en negro. Establecerlo en 1 le da los colores de Edward y establecerlo en 2 le da los colores a continuación.
# Coordinates of the triangle
tri <- rbind(sin(0:2*2/3*pi), cos(0:2*2/3*pi))
# Function for calculating the color of a set of points `pt`
# in relation to the triangle
tricol <- function(pt, sharpness=2){
require(splancs)
RGB <- sapply(1:3, function(i){
a <- sweep(pt, 2, tri[,i])
b <- apply(tri[,-i], 1, mean) - tri[,i]
sharpness*((a %*% b) / sum(b^2))-sharpness+1
})
RGB[-inpip(pt,t(tri)),] <- 1 # Color points outside the triangle white
do.call(rgb, unname(as.data.frame(pmin(pmax(RGB, 0), 1))))
}
# Plot
res <- 1000 # Resolution
xi <- seq(-1, 1, length=res) # Axis points
yi <- seq(-.8, 1.2, length=res)
x <- xi[1] + cumsum(diff(xi)) # Midpoints between axis points
y <- yi[1] + cumsum(diff(yi))
xy <- matrix(1:(length(x)*length(y)), length(x))
image(xi, yi, xy, col=tricol(as.matrix(expand.grid(x,y))), useRaster=TRUE)
lines(tri[1,c(1:3,1)], tri[2,c(1:3,1)], type="l")
Lo que hace tricol()
es representar cada esquina i
con un color (rojo, verde, azul). Define una matriz de vectores desde la esquina hasta los puntos en pt
y un vector b
desde la esquina hasta el centro del borde opuesto. Luego proyecta a
sobre b
y escalas para obtener las distancias relativas = intensidad del color (y aplica un pequeño corte con sharpness
para ajustar los colores un poco). Cuando se trata de problemas como este sencillo, el álgebra puede hacer magia.
Se produce un poco de ruido alrededor de los bordes debido al aliasing, pero probablemente podría modificarlo o dibujar líneas ligeramente más anchas en el triángulo.