0

I am looking to make a colored triangle for my plot with a customized color gradient starting from each vertex of the triangle. Example:

ideal triangle

Below is my code so far. The colors are correct but I am unable to have each of the preferred color start from the vertex. The triangle currently looks like that:

wrong triangle

My current code:

## make a triangle of cell coordinates
cells.x<-cells.y<-vector()
k<-1
asp<-abs(diff(par()$usr[4:3])/diff(par()$usr[2:1]))*par()$pin[2]/par()$pin[1]
for(i in 1:50){
  for(j in i:(100-i+1)){
    cells.x[k]<-0.1+(j-1)*0.1/100
    cells.y[k]<-(-1)+(i-1)*2*0.1*asp/100
    k<-k+1
  }
}

# Define the three colors for the gradient
color1 <- "#1e88e5"
color2 <- "#d81b60"
color3 <- "#ffc107"

# Create a color gradient function between the three colors
color_gradient <- colorRampPalette(c(color1, color2, color3))

# Calculate the number of points
num_points <- length(cells.x)

# Generate the gradient colors based on the number of points
gradient_colors <- color_gradient(num_points)

## draw points
dx<-diff(range(cells.x))
dy<-diff(range(cells.y))
red.x<-max(cells.x)
red.y<-min(cells.y)
red<-1-sqrt((((cells.x-red.x)/dx)^2+((cells.y-red.y)/dy)^2)/2)
green.x<-min(cells.x)
green.y<-min(cells.y)
green<-1-sqrt((((cells.x-green.x)/dx)^2+((cells.y-green.y)/dy)^2)/2)
blue.x<-min(cells.x)
blue.y<-max(cells.y)
blue<-1-sqrt((((cells.x-blue.x)/dx)^2+((cells.y-blue.y)/dy)^2)/2)
points(cells.x,cells.y,col=gradient_colors, pch=15,cex=0.5)

1 Answers1

1

Here is a solution using barycentric coordinates:

# triangle vertices
A <- c(0, 0)
B <- c(1, 0)
C <- c (0.5, 1)

# rgb colors
clrA <- c(1, 0, 0)
clrB <- c(0, 1, 0)
clrC <- c(0, 0, 1)
clrs <- rbind(clrA, clrB, clrC)


library(geometry)

trgl <- rbind(A, B, C)
cart2bary(trgl, rbind(c(1,1)))


M <- matrix(NA_character_, nrow = 512, ncol = 512)
x <- y <- seq(0, 1, length.out = 512L)
for(i in 1L:512L) {
  for(j in 1L:512L) {
    coords <- cart2bary(trgl, rbind(c(x[i], y[j])))[1L, ]
    if(all(coords >= 0)) {
      r <- crossprod(coords, clrs[1, ])
      g <- crossprod(coords, clrs[2, ])
      b <- crossprod(coords, clrs[3, ])
      M[i, j] <- rgb(r, g, b)
    }
  }
}

M[is.na(M)] <- "white"

par(mar = c(0, 0, 0, 0))
plot(
  NULL, asp = 1, xlim = c(0, 1), ylim = c(0, 1), 
  xlab = NA, ylab = NA, axes = FALSE, xaxs = "i", yaxs = "i"
)
rasterImage(M, 0, 0, 1, 1)

enter image description here

Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
  • Thanks for this, its works, but would also like to have the vertices with the following colours: "#1e88e5", "#d81b60", "#ffc107". And cannot seem to figure out how the colour scheme works... – Lilnet Cloud Jun 06 '23 at 23:57
  • @LilnetCloud A red B green C blue with my code, but that does not correspond to the triangle because it is rotated, there's an option to rotate it in `rasterImage`, to put it in the right orientation. – Stéphane Laurent Jun 07 '23 at 02:46