Finding the angle and distance over a ggplot/grid in R

自作多情 提交于 2019-12-11 06:56:50

问题


I have made a ggplot using some A and B numeric values. (If possible can you give me the solution for grid too?) Such as:

A   B
2   3
3   7
4   8
5   9
6   2
7   1

Now from the points, lets say A1 and A2 as shown in diagram, I want to measure the angle and the distance covered from each point.

I know how to calculate the distance (via euclidean distance formula) from one point and for angle it can be calculated as cross and dot product of the vectors. But I am facing the problem to code this and to represent it. Can you help?


回答1:


Okay, here is a first pass - doing it in grid. This could be done in ggplot2 too I imagine, but I want to learn grid for now since ggplot2 and lattice are based on it. This plot has some issues, for example the angle of the annotation text really has to be calculated in device coordinates, not native coordinates, so it only looks right if your grid squares are really square. I might fix that later, but I don't have time now. Also I would think I could specify the defaults so that each primitive doesn't have that default.units parameter. This should get you started though.

library(grid)

grid.newpage()
df <- data.frame(a=c(2,3,4,5,6,7),b=c(3,7,8,9,2,1))

vp <- viewport(x=0.5,y=0.5,width=0.999,height=0.999,xscale=c(0,1),yscale=c(0,1))
pushViewport(vp)

# a rectangle (with dashed lines) on the border of the viewport:
grid.rect(gp=gpar(lty="dashed",col="steelblue"))

vp <- viewport(x=0.5,y=0.5,width=0.9,height=0.9,xscale=c(0,8),yscale=c(0,10),
               default.units="native")
pushViewport(vp)

#draw the background grid
grid.polyline(x=rep(0:8,each=2),y=rep(c(0,10),9),id=rep(1:9,each=2),
              gp=gpar(lty="solid",col="gray"),default.units="native")
grid.polyline(x=rep(c(0,8),11),y=rep(0:10,each=2),id=rep(1:11,each=2),
              gp=gpar(lty="solid",col="gray"),default.units="native")

# add the lables
grid.text(as.character(0:8),x=0:8,y=rep(-0.2,9),
          gp=gpar(col="gray",fontsize=12),default.units="native")
grid.text(as.character(0:10),y=0:10,x=rep(-0.2,11),
          gp=gpar(col="gray",fontsize=12),default.units="native")

grid.lines(x=df$a,y=df$b,gp=gpar(col="steelblue"),default.units="native")
grid.points(x=df$a,y=df$b,gp=gpar(col="steelblue"),default.units="native")


for (i in 1:(nrow(df)-1)){
   x0 <- df$a[i]
   y0 <- df$b[i]
   x1 <- df$a[i+1]
   y1 <- df$b[i+1]
   dx <- x1-x0
   dy <- y1-y0
   dist <- sqrt( dx^2 + dy^2 )
   ang <- (180/3.14159)*atan2(dy,dx)
   txt <- sprintf("D: %.1f  Ang:%.1f",dist,ang)
   xt <- (x0+x1)/2
   yt <- (y0+y1)/2 + 0.2*abs(dy/dx)
   grid.text(txt,x=xt,y=yt,rot=ang,
             gp=gpar(col="steelblue",fontsize=9),default.units="native")
}




回答2:


It sounds easier to calculate those angles and distances outside the plot,

library(dplyr)
d <- data.frame(x=c(2,3,4,5,6,7),
                y=c(3,7,8,9,2,1))

d2 <- with(d, data.frame(dx=diff(x), dy=diff(y)))
d2 <- mutate(d2, distance = sqrt(dx^2 + dy^2), 
             angle = atan2(dy, dx))

ann <- mutate(cbind(d[-nrow(d),], d2), 
              x=x+dx/2, y=y+dy/2, 
              label = sprintf("%.2f\n %2.f degrees", 
                              distance, angle*180/pi))

library(ggplot2)
ggplot(d, aes(x,y)) + geom_line() +
  geom_text(data = ann, vjust = 0,
            aes(x, y, label=label, angle=angle*180/pi)) +
  coord_equal()



来源:https://stackoverflow.com/questions/31424222/finding-the-angle-and-distance-over-a-ggplot-grid-in-r

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!