我的情节有两条来自原点的光线。我想以逆时针方向遮蔽从光线 1 到光线 2 的区域。我在想我可能不得不使用 geom_polygon。我希望能够为 任何两条任意光线 执行此操作,但我似乎无法弄清楚。
*我想坚持使用笛卡尔坐标。
这是我的意思的一个例子:
d <- data.frame()
base <- ggplot(d) + xlim(-5, 5) + ylim(-5, 5) + geom_blank()
ray1 <- geom_segment(aes(x=0,y=0,xend=5,yend=4))
ray2 <- geom_segment(aes(x=0,y=0,xend=0,yend=5))
shading <- geom_polygon(data=data.frame(x=c(0,5,5,0), y=c(0,4,5,5)),
aes(x,y), fill="blue", alpha=0.2)
base + ray1 + ray2 + shading
在这个例子中,我能够通过检查获得多边形的顶点,但我将生成几对随机光线,我不想每次都手动完成这个过程。
有什么建议吗?
最佳答案
我认为这会更简单;但我已经找到了这个丑陋的解决方案。这是一个辅助函数,用于计算沿 base
中定义的限制的所有交点
findslice<-function(seg1, seg2, base=NULL, lim=getlims(base)) {
getlims<-function(x) {
list(y=x$scales$get_scales("y")$limits,
x=x$scales$get_scales("x")$limits)
}
gethit<-function(seg, lim) {
with(seg$mapping, {
x<-eval(x); y<-eval(y);
xend<-eval(xend); yend<-eval(yend);
dx<-(xend-x); dy<-(yend-y)
bx<-ifelse(dx>0,max(lim$x), min(lim$x))
by<-ifelse(dy>0,max(lim$y), min(lim$y))
sx<-ifelse(dx>0,1, 3)
sy<-ifelse(dy>0,2, 4)
if(identical(dx,0)) {
return(list(x=x,y=by, side=sy))
}
if (identical(dy,0)) {
return(list(x=bx,y=y, side=sx))
}
nx<-bx
ny<-(y+dy)*(nx-x)/dx
side<-sx
if (abs(ny)>abs(by)) {
ny<-by
nx<-(x+dx)*(ny-y)/dy
side<-sy
}
return(list(x=nx, y=ny, side=side))
})
}
p1<-gethit(seg1, lim)
p2<-gethit(seg2, lim)
side<-p1$side
corners<-data.frame(x=lim$x[c(2,1,1,2)], y=lim$y[c(2,2,1,1)])
r<-data.frame(x=c(seg1$mapping$x, p1$x), y=c(seg1$mapping$y, p1$y))
while(side != p2$side) {
r<-rbind(r, corners[side, ])
side <- (side %% 4) +1
}
r<-rbind(r, data.frame(x=p2$x, y=p2$y))
r
}
这将创建多边形绘图所需的 data.frame。例如
base <- ggplot(d) + xlim(-5, 5) + ylim(-5, 5) + geom_blank()
ray1 <- geom_segment(aes(x=0,y=0,xend=5,yend=4))
ray2 <- geom_segment(aes(x=0,y=0,xend=0,yend=5))
shading <- geom_polygon(data=findslice(ray1, ray2, base),
aes(x,y), fill="blue", alpha=0.2)
base + ray1 + ray2 + shading + ggtitle("Take 1")
这个想法是它会超出限制,然后开始环绕边缘。所以另一个例子是
ray1 <- geom_segment(aes(x=0,y=0,xend=5,yend=4))
ray2 <- geom_segment(aes(x=0,y=0,xend=0,yend=5))
shading <- geom_polygon(data=findslice(ray1, ray2, base),
aes(x,y), fill="blue", alpha=0.2)
base + ray1 + ray2 + shading + ggtitle("Take 2")
关于r - ggplot2 : filling the area between two rays,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24591878/