0

I want to rotate a point around an origin that could be different from [0,0,0] (but axis don't change direction). Knowing the math, I did my try in MATLAB and everything works as expected.

P = [10 2 33];
O = [1 10 5];
O1 = [0 0 0];

B = zeros(3,100);
for i=1:100
c = cos(i/10);
s = sin(i/10);
Rz = [c -s 0; s c 0; 0 0 1];
A = P - O;
B(:,i) = Rz*A' + O';
end

plot3(B(1,:),B(2,:),B(3,:),'ob');
hold on
plot3(O(1),O(2),O(3),'or');
hold on
plot3(O1(1),O1(2),O1(3),'og');

Next I wanted to insert this thing into a bigger python script, so I wrote this code taking inspiration from this solution. The points that I want to rotate have their coordinates in self.line, the origin is inside self.tvec2, and both of them are continuously updated from the rest of the code

import numpy as np
#many other lines of code    
theta = np.radians(1)
c, s = np.cos(theta), np.sin(theta)
Rz = np.matrix([[c, -s, 0], [s, c, 0], [0, 0, 1]])
self.line_T = self.line[:] - [self.tvec2[0], self.tvec2[1], 0]
print [self.tvec2[0], self.tvec2[1], 0]
for ii in range(self.line_T.shape[0]):
        self.line[ii,:] = np.dot(Rz,self.line_T[ii,:]) + [self.tvec2[0], self.tvec2[1], 0]

The code works, but now it seems that self.line is always rotates around [0,0,0], no matters what the value of self.tvec2 is (I use print to check it out).

What is the problem? Where is my mistake? I am not an expert of numpy and python, but

np.dot(Rz,self.line_T[ii,:])

works, instead of this line with transposition

Rz*(self.line_T[ii,:].T)

and the result should be the same.

NB note that the third value of every coordinates, along Z axes, shouldn't be influenced by rotation around Z axes.

marcoresk
  • 1,837
  • 2
  • 17
  • 29
  • One problem might be that `self.line_T[ii, :]` looks like a 1-d array to me, a concept wich IIRC doesn't really exist in matlab. The transpose of a 1-d array is a nop. If you need something like a column or row vector these are 2-d (nx1 and 1xn respectively) and not the same thing as a 1-d vector in numpy – Paul Panzer Nov 22 '17 at 17:58
  • Also, but I may be opinionated here, there is no good reason for using the `matrix` class which can behave quite counterintuitively at times. Use plain 2-d `arrays` instead, they are much more consistent. If you need matrix multiplication: python/numpy has now for some time supported the `@` infix operator for that, so matlab * <-> numpy @ - matlab .* <-> numpy * – Paul Panzer Nov 22 '17 at 18:04
  • @PaulPanzer thank you for these information. May I ask you some lines of code that I can test? I will try the @ operator, but how can I adjust the self.line_T array? – marcoresk Nov 22 '17 at 20:26

1 Answers1

1

Here is a working version of your code. Notable changes:

  • replace matrix with array
  • use @ operator

The points to rotate are the rows of self.line.

import numpy as np

class Test:
    def __init__(self, tvec2, line):
        self.line = np.asanyarray(line)
        self.tvec2 = np.asanyarray(tvec2)
    def rot(self, theta):
        c, s = np.cos(theta), np.sin(theta)
        Rz = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
        offset = np.array([self.tvec2[0], self.tvec2[1], 0])
        shifted = self.line - offset
        self.line = shifted @ Rz.T + offset

test = Test([-1,-2], [[1,2,3],[3,4,5]])
for i in range(8):
    test.rot(np.pi/8)
    print(test.line)
Paul Panzer
  • 51,835
  • 3
  • 54
  • 99
  • Thank you for the answer, but your code gives me an error: the @ operator gives `SyntaxError: invalid syntax`. Your code was copied-and-pasted as it is, I didn't change nothing. – marcoresk Nov 23 '17 at 09:03
  • Then your python version is too old. In that case, it's back to `np.dot` `np.dot(shifted, Rz.T)`. Could you please try that? – Paul Panzer Nov 23 '17 at 10:30
  • Thank you. It worked also using `np.dot(Rz,shifted)` – marcoresk Nov 28 '17 at 09:42