I need some suggestion of how to plot 2D figures and fill them effectively in R
. I need to visualize some mathematical \"oddities\", for example the Sierpiński
geom_raster()
will be the fastest for square tiles of equal shape.
probably you want geom_polygon()
- here is Sierpinski:
remember to use coord_fixed(ratio=1)
or the shape proportions will scale to the shape of your viewer:
EDIT - sorry realised looking at it I hadn't give you Sierpinski (not sure what I was thinking) fixed
require(ggplot2)
require(reshape2)
t.h<-sin(2*pi/6) # eq triangle unit height
sierpinski<-function(iter=3){
n<-2^iter
points<-ldply((n-1):0,function(x){
data.frame(
y=rep(n-x-1,x)*t.h/n,
x=seq((from=(0.5/n)+(n-x)*(0.5/n)),by=1/n,length.out=x)
)
})
points$id<-1:nrow(points)
rbind(
points,
points+matrix(c((t.h/n),(-0.5/n),0),nrow(points),ncol=3,byrow=T),
points+matrix(c((t.h/n),(0.5/n),0),nrow(points),3,byrow=T)
)
}
axiom<-data.frame(x=c(0,0.5,1),y=c(0,t.h,0))
iterations<-6
ggplot() + theme_bw() + coord_fixed(ratio=1) +
geom_polygon(data=axiom,aes(x,y), fill="orange") +
lapply(1:iterations,function(x){
geom_polygon(data=sierpinski(x),aes(x,y,group=id), fill="white")
})
Also, something you should be aware of with these very precise recursive & series models. Sometimes ggplot will not provide an image looking precisely as you expect. e.g. see below for a cantor dust diagram:
With ggplot (using raster) you can see that even with a high-res output, the 'legs' don't look consistent, whereas you know mathematically that they are. If you download the image and zoom, you'll see the inconsistencies at the bottom.
In the code below, I have shown how you can generate your own precise image by creating a raw png file on the fly. Don't be afraid of doing this if you need precision! The output of the raw image generation is below:
Good luck!
# CANTOR
# NUMBER OF ROWS
n<-9
# MATRIX
m<-matrix(sapply(n:1,function(x){
str.zero<-rep(0,3^(x-1))
str.one<-rep(1,3^(x-1))
rep(c(str.one,str.zero),length.out=3^(n-1))
}),nrow=n,byrow=T)
# CLEANUP
m.cantor<-apply(m,2,cumprod)
# ggplot
ggplot(melt(m.cantor)) + theme_bw() +
geom_raster(aes(x=Var2,y=-Var1,alpha=value),color="white")
# MAKE IMAGE FROM RAW DATA
# LIBRARIES REQUIRED
require(png)
# AT THE MOMENT WE HAVE A SHORT, WIDE MATRIX
dim(m.cantor)
# [1] 9 6561
# so let's scale it up say * 700 to make an approx square image (9 x 700 = 6300 ~ 6561)
# basically we're running through each row and replicating x 700
# then putting the pixels in a matrix with the new height (n=9 * 700)
new.m<-matrix(sapply(1:n,function(x)rep(m.cantor[x,],700)),nrow=n*700,byrow=T)
dim(new.m) # check the size
#[1] 6300 6561 * OK!
# then let's put it in raw image format
# png expects an array of 4 matrices, R,G,B and alpha
img.raw<-array(c((1-new.m), # R,G,B pixels oinverted so 1=shading
(1-new.m), # no G
(1-new.m), # no B
new.m^0 #note I'm putting this to ^0 to make all alphas 1
),
dim=c(dim(new.m),4))
writePNG(img.raw,"cantor.png")