-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAxelRot.m
More file actions
180 lines (132 loc) · 3.52 KB
/
AxelRot.m
File metadata and controls
180 lines (132 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
function varargout=AxelRot(varargin)
%Generate roto-translation matrix for the rotation around an arbitrary line in 3D.
%The line need not pass through the origin. Optionally, also, apply this
%transformation to a list of 3D coordinates.
%
%SYNTAX 1:
%
% M=AxelRot(deg,u,x0)
%
%
%in:
%
% u, x0: 3D vectors specifying the line in parametric form x(t)=x0+t*u
% Default for x0 is [0,0,0] corresponding to pure rotation (no shift).
% If x0=[] is passed as input, this is also equivalent to passing
% x0=[0,0,0].
%
% deg: The counter-clockwise rotation about the line in degrees.
% Counter-clockwise is defined using the right hand rule in reference
% to the direction of u.
%
%
%out:
%
% M: A 4x4 affine transformation matrix representing
% the roto-translation. Namely, M will have the form
%
% M=[R,t;0 0 0 1]
%
% where R is a 3x3 rotation and t is a 3x1 translation vector.
%
%
%
%SYNTAX 2:
%
% [R,t]=AxelRot(deg,u,x0)
%
% Same as Syntax 1 except that R and t are returned as separate arguments.
%
%
%
%SYNTAX 3:
%
% This syntax requires 4 input arguments be specified,
%
% [XYZnew, R, t] = AxelRot(XYZold, deg, u, x0)
%
% where the columns of the 3xN matrix XYZold specify a set of N point
% coordinates in 3D space. The output XYZnew is the transformation of the
% columns of XYZold by the specified rototranslation about the axis. All
% other input/output arguments are as before.
%
% by Matt Jacobson
%
% Copyright, Xoran Technologies, Inc. 2011
if nargin>3
XYZold=varargin{1};
varargin(1)=[];
[R,t]=AxelRot(varargin{:});
XYZnew=bsxfun(@plus,R*XYZold,t);
varargout={XYZnew, R,t};
return;
end
[deg,u]=deal(varargin{1:2});
if nargin>2, x0=varargin{3}; end
R3x3 = nargin>2 && isequal(x0,'R');
if nargin<3 || R3x3 || isempty(x0),
x0=[0;0;0];
end
x0=x0(:); u=u(:)/norm(u);
AxisShift=x0-(x0.'*u).*u;
Mshift=mkaff(eye(3),-AxisShift);
Mroto=mkaff(R3d(deg,u));
M=inv(Mshift)*Mroto*Mshift;
varargout(1:2)={M,[]};
if R3x3 || nargout>1
varargout{1}=M(1:3,1:3);
end
if nargout>1,
varargout{2}=M(1:3,4);
end
function R=R3d(deg,u)
%R3D - 3D Rotation matrix counter-clockwise about an axis.
%
%R=R3d(deg,axis)
%
% deg: The counter-clockwise rotation about the axis in degrees.
% axis: A 3-vector specifying the axis direction. Must be non-zero
R=eye(3);
u=u(:)/norm(u);
x=deg; %abbreviation
for ii=1:3
v=R(:,ii);
R(:,ii)=v*cosd(x) + cross(u,v)*sind(x) + (u.'*v)*(1-cosd(x))*u;
%Rodrigues' formula
end
function M=mkaff(varargin)
% M=mkaff(R,t)
% M=mkaff(R)
% M=mkaff(t)
%
%Makes an affine transformation matrix, either in 2D or 3D.
%For 3D transformations, this has the form
%
% M=[R,t;[0 0 0 1]]
%
%where R is a square matrix and t is a translation vector (column or row)
%
%When multiplied with vectors [x;y;z;1] it gives [x';y';z;1] which accomplishes the
%the corresponding affine transformation
%
% [x';y';z']=R*[x;y;z]+t
%
if nargin==1
switch numel(varargin{1})
case {4,9} %Only rotation provided, 2D or 3D
R=varargin{1};
nn=size(R,1);
t=zeros(nn,1);
case {2,3}
t=varargin{1};
nn=length(t);
R=eye(nn);
end
else
[R,t]=deal(varargin{1:2});
nn=size(R,1);
end
t=t(:);
M=eye(nn+1);
M(1:end-1,1:end-1)=R;
M(1:end-1,end)=t(:);