原始数据范例:
1.05776628 1.60088055 1.98083628
1.60295099 2.11222298 2.74647487
1.09353710 0.54675196 2.16092866
0.03952735 1.92957383 1.98791557
1.49504967 1.81497343 1.02802603
代码如下:
Module RotCoordMod ! 做成一个模块,可以直接插入到已有程序中
Implicit None
Integer , parameter :: DP = Selected_Real_Kind( p = 9 )
contains
Subroutine RotCoord( coord , coord1 , coord2 , coord3 )
!矩阵,要转换到原点的点、到Y正向的点、到XY平面的点
Real(kind=DP) :: coord(:,:)
Integer :: coord1,coord2,coord3
real(kind=DP) :: A(1,3),B(1,3),C(1,3),ab(1,3),ac(1,3),U(3,3),Ustar(3,3)
real(kind=DP) :: Lab(1,1),M(3,3),I(3,3)
A(1,:)=coord(:,coord1) ! 要转换到原点的点的坐标读入A
coord(1,:)=coord(1,:)-A(1,1)
coord(2,:)=coord(2,:)-A(1,2)
coord(3,:)=coord(3,:)-A(1,3) ! 这三步实现了整体坐标的平移,平移到了原点
A(1,:)=coord(:,coord1)
B(1,:)=coord(:,coord2)
C(1,:)=coord(:,coord3) ! 重新将要转换到原点的点、到Y正向的点、到XY平面的点的坐标读入A B C
ab=B-A !求A指向B的向量ab,其实此时就是B的坐标了。用ab表示,只是为了方便阅读
Lab=sqrt(matmul(ab,transpose(ab))) !利用矩阵乘积求ab的模Lab
ab(1,:)=[ab(1,1)/2, ((ab(1,2)+Lab(1,1))/2), ab(1,3)/2] !得到ab与Y轴正向的角平分线向量ab
Lab=sqrt(matmul(ab,transpose(ab))) !求新的ab的模
ab=ab/Lab(1,1) !将新的ab转换成单位长度的向量ab
U=matmul(transpose(ab),ab) !得到ab的方阵U
I=reshape((/1.0_DP ,0.0_DP ,0.0_DP ,0.0_DP ,1.0_DP ,0.0_DP ,0.0_DP ,0.0_DP ,1.0_DP/),(/3,3/)) !单位矩阵I
M=2*U- I
A=matmul(A,transpose(M))
B=matmul(B,transpose(M))
C=matmul(C,transpose(M)) ! ABC此时已经整体旋转至,AB平行于Y轴。这次旋转是180度的旋转
coord=transpose(matmul(transpose(coord),transpose(M))) ! 整体坐标已旋转至平行于Y轴
!接下来继续旋转ABC坐标,使C绕Y轴转至XY平面
ac=C-A ! 求A指向C的向量ac,其实此时就是c的坐标
ab(1,:)=[ 0.0_DP,1.0_DP,0.0_DP ] ! 直接构造Y轴方向的单位向量ab,之后,类似于上一次的旋转过程。
U=matmul(transpose(ab),ab) !得到ab的方阵U
Ustar=reshape((/0.0_DP,ab(1,3),-ab(1,2),-ab(1,3),0.0_DP,ab(1,1),ab(1,2),-ab(1,1),0.0_DP/),(/3,3/)) !U的共轭矩阵
M=U+ (I-U)*ac(1,1)/sqrt(ac(1,1)*ac(1,1)+ac(1,3)*ac(1,3))+ Ustar*ac(1,3)/sqrt(ac(1,1)*ac(1,1)+ac(1,3)*ac(1,3))
coord=transpose(matmul(transpose(coord),transpose(M))) ! 整体坐标已旋转完成
End Subroutine RotCoord
End Module RotCoordMod
Program www_fcode_cn
use RotCoordMod
Implicit None
integer :: i , j , k , io , coordmax = 0
Real(kind=DP) , allocatable :: coord(:,:) ! 声明可变二维数组coord
character(80) :: c
open(10,file='old-coordinate.txt',status="old")
Do ! 利用do循环确定坐标个数
read ( 10 ,'(A)',iostat=io) c
if (io < 0) exit
if (len_trim(c) == 0) cycle
coordmax = coordmax + 1
End Do
Rewind(10) ! 回到文件的开头
allocate( coord(3,coordmax) ) ! 配置可变二维数组coord
read( 10 , * ) coord(:,:) ! 将数据读入二维数组coord
write(*, * ) "Input the Coordinate sequence, such as 2 1 3"
read(*,*) i , j , k
call RotCoord( coord , i , j , k )
write( * , "(3f15.9)" ) coord(:,:) ! 屏幕显示变换结果
End Program www_fcode_cn
!我的方法笨了些,需要平移-->旋转-->再旋转。其实,这应该就是个正交变换,变换一次就够了,肯定有更便捷的已有的代码块。