2013-03-17 2 views
3

У меня есть несколько матриц, заполненных координатами x и y нескольких точек в 2D-пространстве, составляющих график. Матрицы выглядеть примерно такПовернуть график по углу

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

Возможный график выглядит так

enter image description here

То, что я хочу сделать, вращает график вокруг точки 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 
} 

Этот подход не потому, что это не является достаточно гибкой, чтобы всегда рассчитать необходимый угол с результатом того, что график вращается неправильным углом и/или в неправильном направлении.

Заранее спасибо за чтение и, надеюсь, некоторые из вас может принести некоторые свежие идеи для этого

Edit: Данные для воспроизведения этого можно найти здесь

X-Coordinates

Y-Coordinates

Не конечно, как предоставить данные, о которых вы просили, я с удовольствием предоставил бы его по-другому, если вы укажете, как вам понравится.

+0

Просьба представить данные. – Roland

+0

Сделайте небольшие примеры данных, которые демонстрируют проблему, и вставьте здесь результат 'dput'. –

+0

Я попытаюсь сократить его, когда найду время, в основном вы могли бы просто выбрать две случайные точки в 2D-пространстве для A и B, что должно быть достаточным для воспроизведения основной проблемы. – Rickyfox

ответ

7

Нравится?

#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)) 

enter image description here

Edit:

Я разрушу преобразование, чтобы сделать его легче понять. Однако это просто базовая линейная алгебра.

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") 

enter image description here

+0

, это выглядит хорошо, я попробую позже и посмотрю, правильно ли он работает – Rickyfox

+0

не хотите ли вы разработать следующую строку в своем коде? M2 <- t (rotm% *% (t (M) -c (M [1,1], M [1,2])) + c (M [1,1], M [1,2])) – Rickyfox

+0

Вы забыли свои лекции о линейной алгебре? Если вам нужны преобразования, подобные этому чаще, вы должны прочитать соответствующую математическую книгу. – Roland

3

Вместо кадра данных, он выглядит, как ваши данные лучше служили в качестве матрицы (через as.matrix).

Этот ответ очень похож на Roland's, но разбивает вещи на несколько шагов и имеет обработку специального корпуса, когда угол кратен 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]) 
Смежные вопросы