Suppress redraw when calling polygon in R

2019-02-24 01:26发布

问题:

I would like to draw 60,000+ non-overlapping triangles (part of an unstructured triangular mesh) on a single plot in R. Currently, it takes 15-20 minutes per plot, which makes it impossible to use this for making animations. For example,

n <- 100 #Except replace this with 60,000
x <- matrix(runif(3*n), n)
y <- matrix(runif(3*n), n)
cols <- heat.colors(n)[order(x[,1])]
poly <- function(i) {polygon(x[i,], y[i,], col=cols[i])}
plot(0, xlim=c(min(x),max(x)), ylim=c(min(y),max(y)))
sapply(1:n, poly)

Is it possible to suppress polygon() from redrawing after every polygon? I'm guessing that is the most time consuming step, and it's not mentioned in the man page. Alternative suggestions for how to achieve this would be appreciated. Thank you.

回答1:

You can pass several polygons to polygon. All you have to do is separate then with NA. here's a code:

cuts <- function(x)
{
    n <- length(x) %/% 3

    map <- rep(c(TRUE,TRUE,TRUE,FALSE), n)

    result <- rep(NA, n*4)

    result[map] <- x

    result
}


set.seed(1234)

n <- 10000
x <- matrix(runif(3*n), n)
y <- matrix(runif(3*n), n)
cols <- heat.colors(n)[order(x[,1])]
plot(0, xlim=c(min(x),max(x)), ylim=c(min(y),max(y)))
polygon(x=cuts(t(x)), y=cuts(t(y)), col=cols)

Works fast. I've tested controlling the seed and comparing with the plot generated by your code.



回答2:

here a vectorized solution using grid.polygon of the grid package. I use the lattice just to draw the scene( xyplot(0~0) ~ plot(0)).

library(lattice)
library(grid)
xyplot(0~0, xlim=c(min(x),max(x)), ylim=c(min(y),max(y)),
       panel=function(...)
       {
         grid.polygon(x  = as.vector(t(x)),
                      y  = as.vector(t(y)),
                      id = rep(1:n,each=3),
                      gp=gpar(fill=cols),
                      def='native')         
       })

This takes less than 30 seconds in my modest PC to generate the 60000 polygons.



标签: r graphics