Calculate angle between vectors
이전 댓글 표시
Dear MatLab comunity,
I have a vectorial problem. I am writing again the question because it wasn't clearly explained, so I'll try to be as precise as possible.
I have a molecular dynamics trajectory of a molecule with 1000 frames.
For this molecule I calculated the three major axis of inertia (see picture)

The three major axes of inertia intersect at the center of mass of coordinates:
COM = [3.9721615314483643 -8.11227798461914 -0.34564414620399475]
and each one has coordinates, respectively:
X_ax = [0.43753358721733093 0.719929575920105 -0.5387632250785828]
Y_ax = [0.5724487900733948 0.2390475869178772 0.7843204736709595]
Z_ax = [0.6934455633163452 -0.6515809297561646 -0.3075314462184906]
Now, I have chosen three protons in the molecule: H1p, H5p and H3.
Of these I extracted the xyz coordinates in each frame and stored them (see file attached, the first column is the frame number):
L_H1p = load('H1p.dat');
L_H5p = load('H5p.dat');
L_H3 = load('H3.dat');
H1p = [L_H1p(:,2), L_H1p(:,3), L_H1p(:,4)];
H5p = [L_H5p(:,2), L_H5p(:,3), L_H5p(:,4)];
H3 = [L_H3(:,2), L_H3(:,3), L_H3(:,4)];
so having an array of coordinates for each atom.
Now, I want to define the vectors that goes from H1p to H5p and the vector that goes from H1p to H3 and I did it as following:
H5pH1p = [(H5p(:,1)-H1p(:,1)), (H5p(:,2)-H1p(:,2)), (H5p(:,3)-H1p(:,3))];
H3H1p = [(H3(:,1)-H1p(:,1)), (H3(:,2)-H1p(:,2)), (H3(:,3)-H1p(:,3))];
Now I have the array of 1000 vectors for H5pH1p and 1000 vectors for H3H1p.
I want to study how these vectors move with reference to the axis of inertia.
Let's say that I want to calculate the angle between the array of vectors H5pH1p and the Z component of the inertia axes.
I am not sure how to approach to this and hopefully I stated clearly the problem.
Best,
Alex
댓글 수: 2
As mentioned in another thread already: You can simplify
H5pH1p = [(H5p(:,1)-H1p(:,1)), (H5p(:,2)-H1p(:,2)), (H5p(:,3)-H1p(:,3))];
to
H5pH1p = H5p - H1p;
or:
H1p = [L_H1p(:,2), L_H1p(:,3), L_H1p(:,4)];
to
H1p = L_H1p(:,2:4);
This reduces the cance of typos and is much faster.
The actual question is: "I want to calculate the angle between the array of vectors H5pH1p and the Z component of the inertia axes" . Then all you need to know to create an answer is the dimension of the vectors. So "X = rand(1000, 3), Z = rand(1, 3)" is sufficient and much shorter than your question.
Alessandro Ruda
2022년 3월 6일
답변 (2개)
The actual numerically stable formula is: atan2(norm(cross(X, Z)), dot(X, Z));
Unfortunately Matlab's cross and dot do not work with implicit expanding yet.
X = rand(1000, 3);
Z = rand(1, 3);
A = atan2(vecnorm(myCross(X, Z), 2, 2), X * Z.');
function Z = myCross(X, Y)
% INPUT: X, Y: [M x 3] or [1 x 3] arrays.
% OUTPUT: Z: Cross product.
Z = [ X(:,2) .* Y(:,3) - X(:,3) .* Y(:,2), ...
X(:,3) .* Y(:,1) - X(:,1) .* Y(:,3), ...
X(:,1) .* Y(:,2) - X(:,2) .* Y(:,1)];
end
댓글 수: 5
Alessandro Ruda
2022년 3월 6일
편집: Alessandro Ruda
2022년 3월 6일
Jan
2022년 3월 6일
The actual algorithm is:
Angle = atan2(norm(cross(X, Z)), dot(X, Z))
For the implementation in Matlab we have to consider, that norm() calculates the matrix norm, when the argument is a matrix. Therefore vecnorm is the wanted function, which calculates the norm over vectors along the specified direction.
Many Matlab function are working with "implicit expanding". This means, that if the operands are [M x N] and [1 x N], the vector is expanded to the same size automatically. This works e.g. for +, -, .*, ./ and so on, but not for the functions cross() and dot().
"Then you define the cross product function where I guess X is H5pH1p and Y is the Z_axis [1, 3] vector." - almost. It is very useful to implement a function not only for a specific input, but generally. If you call e.g. sin(x), it does not matter, if the argument is called "x", "y", "hurliturli_Kafonz" or if it is constand like 19. Using the names "H5pH1p" and "Z_ax" as inputs is not useful, because "X" and "Y" are short, clear and general.
The function is defined with its inputs and outputs by the line
function Z = myCross(X, Y)
Now the names of the variables in the caller do not matter in any way, because the function sees their values only. The "Z" in the caller has no relation to the "Z" used inside the function. Both are variables and each function has its own set of variables completely independent from other functions.
You can use the function "myCross()" exactly how I have posted it. There is no need to rename the variables.
"First I am not sure if I have to use the vector Z = Z_ax - COM instead of Z_ax directly." - I do not know this either. It depends on what you want to calculate.
"Is it not that the vectors of the first matrix have to be translated to the same origin of the the Z_ax vector for the angle to be calculated and the cross product to be obtained" - as said before, a vector is a set of e.g. 3 elements. You can interprete it as coordinates of a point in 3D or a direction. If you want to calculate angles between vectors, there is no need to move them around in space, if the vectors are directions. If they are coordinates, and "angle" between them is not defined mathematically. So it really depends on the mathematical nature of the problem, but I did not understand yet what you want to calculate.
"Is this the array of angles between each vector in the array H5pH1p and the Z axis" - exactly.
Alessandro Ruda
2022년 3월 6일
편집: Alessandro Ruda
2022년 3월 6일
Alessandro Ruda
2022년 3월 6일
편집: Alessandro Ruda
2022년 3월 6일
Alessandro Ruda
2022년 3월 6일
편집: Alessandro Ruda
2022년 3월 6일
카테고리
도움말 센터 및 File Exchange에서 Semantic Segmentation에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!