Трехцветный градиент цвета заполняет r
Как я могу заполнить трехцветный градиент (тепловая карта) на триплет (график треугольника), как это.
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)
![enter image description here]()
Цвет должен работать параллельно триплету.
Ответы
Ответ 1
Вот один из способов сделать это - это немного взломать, используя точки для построения градиента по частям:
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)
}
}
И вывод:
![enter image description here]()
Вы хотите использовать эти градиенты для представления данных? Если это так, можно изменить d.red
, d.green
и d.blue
, чтобы это сделать - я еще не тестировал ничего подобного. Надеюсь, что это несколько полезно, но подходящее решение, использующее colorRamp
, возможно, будет лучше.
РЕДАКТИРОВАТЬ. В соответствии с предложением baptiste вы можете хранить информацию в векторах и отображать все сразу. Это значительно быстрее (особенно при sm
, установленном на 500, например):
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)
Ответ 2
Здесь есть решение с растрированным фоновым изображением. Параметр sharpness
функции tricol
определяет, как быстро цвет исчезает до черного. Установка его в 1 дает вам цвета Эдварда и настройку на 2 дает вам цвета ниже.
# 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")
Что tricol()
представляет собой каждый угол i
с цветом (красный, зеленый, синий). Он определяет матрицу a
векторов от угла к точкам в pt
и вектору b
от угла к центру противоположного края. Затем он проецирует a
на b
и масштабируется, чтобы получить относительные расстояния = интенсивность цвета (и применяет небольшой взлом с sharpness
, чтобы немного настроить цвета). Когда дело доходит до таких проблем, как эта простая алгебра может работать с магией.
Вы получаете шум вокруг краев из-за сглаживания, но вы, вероятно, могли бы откорректировать его, или нарисовать несколько более широкие линии в треугольнике.
![Gradient triangle]()
Ответ 3
Вот реализация, обработанная для пакета phonR
... функция fillTriangle
не экспортируется, поэтому вам нужно использовать оператор :::
для доступа к ней. В примере показаны как основанные на pch, так и растровые подходы.
# 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)
![примеры графов заполнения градиентного треугольника]()