【问题标题】:Rotate graph by angle按角度旋转图形
【发布时间】:2013-03-17 16:54:52
【问题描述】:

我有多个矩阵,其中填充了组成图形的 2D 空间中多个点的 x 和 y 坐标。矩阵看起来像这样

x1 x2 x3 x4 ...
y1 y2 y3 y4 ...

可能的图表看起来像这样

我想要做的是围绕点 A 旋转图形,使点 A 和 B 之间的线平行于 X 轴。

我的想法是将线 AB 视为直角三角形的假设,计算 α(点 A 处的角度)并使用旋转矩阵通过它旋转该图的矩阵。

到目前为止我所做的如下

#df is the subset of my data that describes the graph we're handling right now,
#df has 2 or more rows

beginx=df[1,]$xcord          #get the x coordinate of point A
beginy=df[1,]$ycord          #get the y coordinate of point A
endx=df[nrow(df)-1,]$xcord   #get the x coordinate of point B
endy=df[nrow(df)-1,]$ycord   #get the y coordinate of point B
xnow=df$xcord
ynow=df$ycord
xdif=abs(beginx-endx)
ydif=abs(beginy-endy)




 if((xdif != 0) & (ydif!=0)){
     direct=sqrt(abs((xdif^2)-(ydif^2))) #calculate the length of the hypothenuse
     sinang=abs(beginy-endy)/direct      
     angle=1/sin(sinang)
     if(beginy>endy){
     angle=angle
 }else{
     angle=360-angle
 }
rotmat=rot(angle)    # use the function rot(angle) to get the rotation matrix for
                         # the calculated angle
A = matrix(c(xnow,ynow),nrow=2,byrow = TRUE)  # matrix containing the graph coords
admat=rotmat%*%A                          #multiply the matrix with the rotation matrix
}

这种方法失败了,因为它不够灵活,无法始终计算所需的角度,结果是图形旋转了错误的角度和/或方向错误。

提前感谢您的阅读,希望你们中的一些人可以对此提出一些新的想法

编辑:可在此处找到重现此内容的数据

X-Coordinates

Y-Coordinates

不确定如何提供您要求的数据,如果您指定您喜欢的方式,我很乐意以其他方式提供它

【问题讨论】:

  • 制作更小的示例数据来演示问题,并将dput的结果粘贴到此处。
  • 有时间我会尽量减少,基本上你也可以在2D空间中为A和B随机选择两个点,这应该足以重现基本问题。跨度>
  • 这是绕 A 点旋转,还是绕原点旋转?
  • 补充说,旋转应该围绕起点A点
  • 你应该在假设计算中使用“+”而不是“-”

标签: r graph matrix rotation


【解决方案1】:

像这样?

#read in X and Y as vectors
M <- cbind(X,Y)
#plot data
plot(M[,1],M[,2],xlim=c(0,1200),ylim=c(0,1200))
#calculate rotation angle
alpha <- -atan((M[1,2]-tail(M,1)[,2])/(M[1,1]-tail(M,1)[,1]))
#rotation matrix
rotm <- matrix(c(cos(alpha),sin(alpha),-sin(alpha),cos(alpha)),ncol=2)
#shift, rotate, shift back
M2 <- t(rotm %*% (
  t(M)-c(M[1,1],M[1,2])
  )+c(M[1,1],M[1,2]))
#plot
plot(M2[,1],M2[,2],xlim=c(0,1200),ylim=c(0,1200))

编辑:

我将分解转换以使其更易于理解。但是,这只是基本的线性代数。

plot(M,xlim=c(-300,1200),ylim=c(-300,1200))
#shift points, so that turning point is (0,0)
M2.1 <- t(t(M)-c(M[1,1],M[1,2]))
points(M2.1,col="blue")
#rotate
M2.2 <- t(rotm %*% (t(M2.1)))
points(M2.2,col="green")
#shift back
M2.3 <- t(t(M2.2)+c(M[1,1],M[1,2]))
points(M2.3,col="red")

【讨论】:

  • 这个看起来不错,我稍后试试看是否正常
  • 您是否愿意在您的代码中详细说明以下行? M2
  • 你忘了你的线性代数讲座了吗?如果您需要更频繁地进行此类转换,则应该阅读适当的数学书。
  • 感谢您的解释
【解决方案2】:

看起来您的数据最好用作矩阵而不是数据框(通过as.matrix)。

这个答案与 Roland 的答案非常相似,但将事情分解为更多步骤,并且当角度是 pi/2 的倍数时有一些特殊情况处理。

#sample data
set.seed(1) #for consistency of random-generated data
d <- matrix(c(sort(runif(50)),sort(runif(50))),ncol=2)

#rotation about point A
rotA <- function(d) {
d.offset <- apply(d,2,function(z) z - z[1]) #offset data
  endpoint <- d.offset[nrow(d.offset),] #gets difference
  rot <- function(angle) matrix(
    c(cos(angle),-sin(angle),sin(angle),cos(angle)),nrow=2) #CCW rotation matrix
  if(endpoint[2] == 0) {
    return(d) #if y-diff is 0, then no action required
  } else if (endpoint[1] == 0) { 
    rad <- pi/2 #if x-diff is 0, then rotate by a right angle
  } else {rad <- atan(endpoint[2]/endpoint[1])}
  d.offset.rotate <- d.offset %*% rot(-rad) #rotation
  d.rotate <- sapply(1:2,function(z) d.offset.rotate[,z] + d[1,z]) #undo offset
  d.rotate
}

#results and plotting to check visually
d.rotate <- rotA(d)
plot(d.rotate)
abline(h=d[1,2])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-24
    • 1970-01-01
    • 2020-04-24
    • 1970-01-01
    • 1970-01-01
    • 2017-09-09
    • 2021-07-19
    相关资源
    最近更新 更多