# Random rotation at a given angle?

I need to generate a random rotation matrix for a given angle $$a$$. In other words, a random $$n\times n$$ matrix $$A$$ such that for any unit-length vector $$v$$ the following is true.

$$v'Av\le\cos a$$

The recipe below visualizes 10000 random rotations with "small" angles, can anyone see how to make it work with specific angle $$a$$? For $$a=\pi/2$$ and $$n=3$$, these rotations correspond to points along the equator in the visualization below

(* generate random rotation matrix corresponding to a "small" rotation *)

randomRotation2[n_] :=
Module[{},
z = IdentityMatrix[n] +
0.1 RandomVariate[NormalDistribution[0, 1], {n, n}];
{q, r} = QRDecomposition[z];
d = Diagonal[r];
ph = d/Abs[d];
q*ph];

n = 3;
points = Table[randomRotation2[n].{0, 0, 1}, {10^4}];
Graphics3D[{{Gray, PointSize[Small], Point[points]}, {Red, Thick,
Arrow[{{0, 0, 0}, {0, 0, 1}}]}}, Axes -> True]


• Can't you use RotationMatrix[a,{u,v}] with random vectors u,v? From the documentation of RotationMatrix: gives the matrix that rotates by $a$ radians in the plane spanned by $u$ and $v$. Oct 30 '20 at 10:28
• "a random n×n matrix A such that for any unit-length vector v the following is true: ..." That is only true in 2D. $v^\top A v = 1$ if $v$ is a unit vector along the rotation axis (try {1, 0, 0}.RotationMatrix[alpha, {1, 0, 0}].{1, 0, 0} for instance). Oct 30 '20 at 11:01
• you are right, it needed to be <= insteda of ==, fixed Oct 30 '20 at 18:21

Edit

For the band region.

bandReg =
RegionIntersection[HalfSpace[{0, 0, -1}, {0, 0, 0.8}],
HalfSpace[{0, 0, 1}, {0, 0, 0.9}], Sphere[]];
RotationMatrix[{RandomPoint[bandReg], {0, 0, 1}}]
Graphics3D[{Point[RandomPoint[bandReg, 2000]], Opacity[0.1], Ball[]}]


Update

n = 8;
normal = SparseArray[i_ /; i == n -> -1, {n}] // Normal
pt = SparseArray[i_ /; i == n -> 0.8, {n}] // Normal
center = center = ConstantArray[0, n];
a = HalfSpace[normal, pt] // Region;
b = Sphere[center, 1] // Region;
reg = RegionIntersection[a, b]
RotationMatrix[{RandomPoint[reg], normal}]


Original

Maybe this?

Or do you want to get angle instead of vector or point?

The answer need to be updated later.

a = HalfSpace[{0, 0, -1}, {0, 0, 0.8}] // Region;
b = Sphere[] // Region;
reg = RegionIntersection[a, b]
RotationMatrix[{RandomPoint[reg], {0, 0, 1}}]
Graphics3D[{Point[RandomPoint[reg, 2000]], Opacity[0.1], Ball[]}]


• thanks, that's a useful trick....any idea how to exclude rotations close to origin? I tried RegionIntersection[a, b, RegionDifference[FullRegion[3], HalfSpace[{0, 0, -1}, {0, 0, 0.9}]]] but RandomPoint fails to evaluate for that region Oct 30 '20 at 18:31
• @YaroslavBulatov I have edited the answer. Oct 31 '20 at 0:06

Assuming OP requires rotation matrices for $$n\ge 3$$ and adapting the algorithm given in https://stackoverflow.com/a/50342248/6644522 for Mathematica the following function genM generates a $$n\times n$$ rotation matrix given an axis of rotation v in form of an $$(n-1)$$-subspace (a $$n\times(n-1)$$ matrix) and an angle theta.

ArcTan2[y_,x_]/;x\[Element]Reals&&y\[Element]Reals:=Which[x>0||y!=0,2ArcTan[y/(Sqrt[x^2+y^2]+x)],x<0&&y==0,\[Pi],x==0&&y==0,Indeterminate]

genM[v_List,theta_]:=Module[{n,u,M,c,r,t,R},
n=Length[v[[All,1]]];
u=v;
M=IdentityMatrix[n];
For[c=1,c<=n-2,c++,
For[r=n,r>=c+1,r--,
t=ArcTan2[u[[r,c]],u[[r-1,c]]]//N;
R=IdentityMatrix[n];
R[[r-1;;r,r-1;;r]]={{Cos[t],-Sin[t]},{Sin[t],Cos[t]}}\[Transpose];
u=R.u;
M=R.M;
];
];
R=IdentityMatrix[n];
R[[n-1;;n,n-1;;n]]={{Cos[theta],-Sin[theta]},{Sin[theta],Cos[theta]}};
LeastSquares[M,R.M]
]


where I implemented ÀrcTan2 based on https://en.wikipedia.org/wiki/Atan2. Running

genM[{{1}, {2}, {3}}, \[Pi]/4] // N // MatrixForm
genM[{{1, 0}, {0, 1}, {1, 0}, {0, 1}}, \[Pi]/4] // N // MatrixForm


gives results consistent with https://stackoverflow.com/a/50342248/6644522:

and the three dimensional rotation matrix is equivalent to RotationMatrix[\[Pi]/4, {1, 2, 3}] within floating point precision. The math behind this (I have not looked into it) can supposedly be found in http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.8662.

I am not 100% sure that this implementation in Mathematica is correct: I had to add a Transpose, adapt some spans and I do not know if the implementation of ArcTan2 I have chosen is consistent with atan2 in MATLAB. I ran some test on against RotationMatrix with random angles and axes and in $$n=3$$ the code seems to work but for $$n>3$$ I only checked against the on example given for the MATLAB code.