Matrix 创建复合旋转矩阵时出错
我第一次把这个问题贴在Math.Stackexchange上,但是那里的人建议这是解决这个问题的正确地方 我试图沿着多个轴旋转球体上的一组点,以获得特定的方向。我用Fortran编写了同样的代码,如果我将点旋转到任意一个方向,转换似乎工作得很好。但一旦我指定了不止一个旋转轴,解决方案就会出错。大多数点,也许除了极端的点,都超出了球体的体积 我的代码(与问题相关)如下:Matrix 创建复合旋转矩阵时出错,matrix,fortran,fortran90,rotatetransform,Matrix,Fortran,Fortran90,Rotatetransform,我第一次把这个问题贴在Math.Stackexchange上,但是那里的人建议这是解决这个问题的正确地方 我试图沿着多个轴旋转球体上的一组点,以获得特定的方向。我用Fortran编写了同样的代码,如果我将点旋转到任意一个方向,转换似乎工作得很好。但一旦我指定了不止一个旋转轴,解决方案就会出错。大多数点,也许除了极端的点,都超出了球体的体积 我的代码(与问题相关)如下: DO iSlice = 1, nSlices IF(iSlice<10) THEN WRITE(string1
DO iSlice = 1, nSlices
IF(iSlice<10) THEN
WRITE(string1,'("slice",i1.1,".dat")'), iSlice
ELSE
WRITE(string1,'("slice",i2.2,".dat")'), iSlice
END IF
!PRINT*,string1
OPEN (1, file = string1)
DO j = 1,4
READ(1,*) z(j),y(j),t(j)
END DO
READ(1,*) temp
x(1:4) = -1.*temp
CLOSE (1)
!Transform the nodal positions as desired
CALL init_Trans
CALL form_translate(-1.*CG)
IF (iRotz) THEN
ang = (the3*pi/180.0)*(nSlices-iSlice)/(nSlices-1)
r_axis = '-rz'
PRINT*,'angz = ',ang*180./pi
CALL form_rotate(r_axis,ang)
END IF
IF (iRoty) THEN
ang = (the2*pi/180.0)*(nSlices-iSlice)/(nSlices-1)
r_axis = '-ry'
PRINT*,'angy = ',ang*180./pi
CALL form_rotate(r_axis,ang)
END IF
IF (iRotx) THEN
ang = (the1*pi/180.0)*(nSlices-iSlice)/(nSlices-1)
r_axis = '-rx'
PRINT*,'angx = ',ang*180./pi
CALL form_rotate(r_axis,ang)
END IF
CALL form_translate(CG)
CALL transform
WRITE(fout,'(A,I2)')'SLICE: ',iSlice
DO i = 1, 4
WRITE(fout,71) xnew(i), ynew(i), znew(i), t(i)
END DO
WRITE(fout,*)''
DO i = 1, 4
WRITE(fout_tec,'(3(D25.17,1X))') xnew(i), ynew(i), znew(i)
END DO
END DO
SUBROUTINE init_Trans
USE global_param, ONLY: Trans
IMPLICIT NONE
INTEGER :: i,j
! This subroutine initializes the final Transformation matrix as a 4x4 identity matrix
!--------------------------------------------------------------------------------------!
Trans (:,:) = 0
DO i = 1, 4
Trans(i,i) = 1
END DO
END SUBROUTINE init_Trans
! -------------------------------------------------------------------------------------------- !
SUBROUTINE form_translate (D_MOVE)
USE global_param, ONLY: Trans
IMPLICIT NONE
INTERFACE
SUBROUTINE mat_prod(M1, M2, M3)
REAL, DIMENSION(:,:), INTENT(IN) :: M1, M2
REAL, DIMENSION(:,:), INTENT(OUT) :: M3
END SUBROUTINE
END INTERFACE
REAL, DIMENSION(3), INTENT(IN) :: D_MOVE
REAL, DIMENSION(4,4) :: T, Temp
INTEGER :: i, j
! Initialize Translation Matrix
!-------------------------------!
! WRITE(*,*)'FORMULATING TRANSLATION MATRIX...'
DO i = 1, 3
DO j = 1, 3
IF (i .eq. j) THEN
T(i,j) = 1.0;
ELSE
T(i,j) = 0.0;
END IF
END DO
T(i,4) = D_MOVE(i)
END DO
T(4,4) = 1.0;
CALL mat_prod(T,Trans,Temp)
Trans = Temp
END SUBROUTINE form_translate
! -------------------------------------------------------------------------------------------- !
SUBROUTINE form_rotate(r_axis, theta)
USE global_param, ONLY: Trans
IMPLICIT NONE
INTERFACE
SUBROUTINE mat_prod(M1, M2, M3)
REAL, DIMENSION(:,:), INTENT(IN) :: M1, M2
REAL, DIMENSION(:,:), INTENT(OUT) :: M3
END SUBROUTINE
END INTERFACE
REAL, INTENT(IN) :: theta
REAL, DIMENSION(4,4) :: R, Temp
CHARACTER(LEN = 3), INTENT(IN) :: r_axis
INTEGER :: i,j
SELECT CASE (r_axis)
CASE('-rx')
! WRITE(*,*)'FORMULATING X-ROTATION MATRIX...'
! Initialize x-Rotation matrix
!----------------------------!
DO i = 2,3
DO j = 2, 3
IF (i .eq. j) THEN
R(i,j) = cos(theta)
ELSE
R(i,j) = ((-1)**(i-1))*sin(theta)
END IF
END DO
END DO
DO i = 1, 4, 3
DO j = 1, 4, 3
IF (i .eq. j) R(i,j) = 1.0
END DO
END DO
CASE('-ry')
! WRITE(*,*)'FORMULATING Y-ROTATION MATRIX...'
! Initialize y-Rotation matrix
!----------------------------!
DO i = 1,3,2
R(i,i) = cos(theta)
IF (mod(i+1,4) .eq. 0) THEN
R(i,4-i) = -sin(theta)
ELSE
R(i,4-i) = sin(theta)
END IF
END DO
DO i = 2, 4, 2
R(i,i) = 1.0
END DO
CASE('-rz')
! WRITE(*,*)'FORMULATING Z-ROTATION MATRIX...'
! Initialize z-Rotation matrix
!----------------------------!
DO i = 1,2
DO j = 1, 2
IF (i .eq. j) THEN
R(i,j) = cos(theta)
ELSE
R(i,j) = ((-1)**i)*sin(theta)
END IF
END DO
END DO
DO i = 3, 4
DO j = 3, 4
IF (i .eq. j) R(i,j) = 1.0
END DO
END DO
END SELECT
CALL mat_prod(R,Trans,Temp)
Trans = Temp
DO i = 1, 4
PRINT*,Trans(i,:)
END DO
END SUBROUTINE form_rotate
! -------------------------------------------------------------------------------------------- !
SUBROUTINE transform
! Transform coordinates of each point using p_new = Tran*p
!----------------------------------------------------------!
USE global_param
IMPLICIT NONE
INTERFACE
SUBROUTINE mat_prod(M1, M2, M3)
REAL, DIMENSION(:,:), INTENT(IN) :: M1, M2
REAL, DIMENSION(:,:), INTENT(OUT) :: M3
END SUBROUTINE
END INTERFACE
REAL, DIMENSION(4,1) :: p, p_new
INTEGER :: i,j
p(4,1) = 1.0
DO i = 1, n_nodes
p(1,1) = x(i); p(2,1) = y(i); p(3,1) = z(i)
CALL mat_prod(Trans, p, p_new)
xnew(i) = p_new(1,1); ynew(i) = p_new(2,1); znew(i) = p_new(3,1)
END DO
END SUBROUTINE transform
我已经尝试创建一个复合旋转矩阵,以便可以同时处理沿两个轴产生的旋转。我想这就是我出错的地方,因为代码对于围绕单个轴旋转点很有效。有人能帮我解决这个问题吗
非常感谢 什么是
mat_prod
?您是否可以使用自己的卷替换matmul
?查看轴角度公式如果问题仍然存在,您可以尝试。在使用4x4变换矩阵时,您可能会发现更多有用信息。我可能会建议你先处理3x3表单,如果你真的被卡住了,以后再添加平移。@Stefan,如果你要进行大量的旋转连接,四元数是有用的,但在单个连接中这应该不是问题。