MGM.05 3D Matrices
TUTORIALS

Needs["LinearAlgebra`MatrixManipulation`"];
Needs["Graphics`Colors`"];
Off[General::"spell"];
Off[General::"spell1"];
Off[ParametricPlot3D::"ppcom"];
Off[ParametricPlot::"ppcom"];
Off[Plot::"plnr"];
SetOptions[Limit, Analytic -> True];
$Pre = Chop;

CMView = {2.7, 1.6, 1.2};

Vector Drawer

\(\(\( (*\ \(\(:\)\(Date : \ \ Copyright\ 2001\)\), \ 
      Math\ Everywhere, \ \(\(Inc\)\(.\)\)\ 
*) \)\(
\)\( (*
Original\ Conception\ to\ create\ a\ vector\ drawer\ is\ due\ to\ Bill\ Davis . 
Current\ code\ is\ by\ Bruce\ \(\(Carpenter\)\(.\)\)
*) \)\(
\)\( (*\ \ \(\(\(:\)\(Drawbacks : \ \ Since\ the\ vectors\ are\ drawn\ out\ of\)\)\ 

      \ \ \ \ \ context\), \ 
      the\ shapes\ of\ the\ arrowheads\ are\ only\ 
\ \ \ \ \ correct\ with\ AspectRatio\ set\ to\ \(\(Automatic\)\(.\)\)
*) \)\)\)

BeginPackage["Vector3D`","Graphics`Colors`"];

Axes3D::usage = "Axes3D[a, b] creates a Graphics3D object of cartesian axes with x, y, and z running from -a/3 to a, and with axes labels b units beyond the tips of the axes.  Axes3D[a] is Axes3D[a, a/8].";

Perpend::usage = "Perpend[a] returns a unit vector which is perpendicular to the vector a.";

Arrow::usage = "Arrow[a] produces a 2 or 3 dimensional vector from the origin to a. Arrow[a, Tail -> tail] gives a vector from tail to a.";
	
Vector::usage = "Vector[a, b] gives a 2D or 3D vector from a to b.";

ArrowHead::usage = "ArrowHead[a, vec] produces an arrowhead with its tip placed at the point a, pointing in the direction of the vector vec.";

Tail::usage = "Tail -> point puts the tail of the vector at point.";

Norm::usage = "Norm[vec] returns the Euclidean length of vec.";

Normalize::usage = "Normalize[vec] returns a unit vector in the direction of vec, provided vec is nonzero.";

Aperture::usage = "Aperture is the ratio of the radius of the base to the length of the head of a vector.";

TipSize::usage = "TipSize specifies an absolute size for the inner tip length of the head of a vector.";

TipRatio::usage = "TipRatio is the ratio of the inner length of the arrowhead to the length of the shaft of a vector.";

HeadRatio::usage = "HeadRatio is the ratio of the outer length of the arrowhead to the length of the shaft of a vector.";

HeadSize::usage = "HeadSize specifies an absolute size for the head of a vector.";

ScaleFactor::usage = "ScaleFactor specifies the amount to scale a vector in length and may be either a number or a pure function.";

ZeroVectorPointSize::usage = "ZeroVectorPointSize is the size of the point used to represent a zero vector.";

Options[Vector] = Options[Arrow] = Options[ArrowHead] =
{HeadRatio -> 0.18, TipRatio -> 0.14, Aperture -> 0.3, ScaleFactor -> 1, HeadType -> Polygon, ShaftQ -> True, EdgesQ -> True, VectorColor -> RGBColor[0,0,1], ShaftWidth -> 0.005, ZeroVectorPointSize -> 0.01};
		
Begin["`Private`"];

SetOptions[ParametricPlot,AspectRatio -> Automatic];
SetOptions[Plot,AspectRatio -> Automatic];
SetOptions[Graphics,AspectRatio -> Automatic];

Axes3D[u_,v_] := 
      Graphics3D[{
            {Blue,Line[{{-u/3,0,0},{u,0,0}}]},
                    Text["x",{u + v,0,0}],
            {Blue,Line[{{0,-u/3,0},{0,u,0}}]},
                    Text["y",{0, u + v,0}],
            {Blue,Line[{{0,0,-u/3},{0,0,u}}]},
                    Text["z",{0,0,u + v}]}]; 
Axes3D[u_] := Axes3D[u,u/8];
				
Norm[a_?VectorQ] := N[Sqrt[a.a]];

Normalize[a_?VectorQ] := If[a.a == 0, a, a/Norm[a]];

Perpend[a_?VectorQ] := Normalize[{a[[2]],-a[[1]]}]/;Length[a]==2;

Perpend[a_?VectorQ]:=
    Normalize[If[a[[1]]==0,{1,0,0},{a[[2]],-a[[1]],0}]]/;
      Length[a]==3;
      
Base3D = Table[{Cos[2 k Pi/8.], Sin[2 k Pi/8.]},{k,0,8}]; 

Vector[from_?VectorQ, to_?VectorQ, opts___] := Module[
   {sq, sw, ht, hs, hr, tr, ap, sf, vc, zvps, diff = to - from, tip},
   {sq, sw, ht, hs, hr, ts, tr, ap, sf, vc, zvps} = {ShaftQ, ShaftWidth, HeadType, HeadSize, HeadRatio, TipSize, TipRatio, Aperture, ScaleFactor, VectorColor, ZeroVectorPointSize} /. {opts} /. Options[Vector];
   If[from==to, Return[Graphics[{PointSize[zvps],vc,Point[from]}]]];
   diff = If[NumberQ[N[sf]], sf diff, sf[diff]];
   tip = from + diff;
   If[NumberQ[hs], hr = hs/Norm[diff]; tr = 0.75 hr];
   If[NumberQ[ts], tr = ts/Norm[diff]];
   Graphics[{If[sq,{vc,Thickness[sw],Line[{from,tip - tr diff}]},{}],
      With[{trans = ap hr Norm[diff] Perpend[diff]},
      {vc, Thickness[sw], ht[{tip,
                   (tip - hr diff + trans),
                   (tip - tr diff),
                   (tip - hr diff - trans),tip}]}]}]
] /; Length[from]==Length[to]==2

Vector[from_?VectorQ, to_?VectorQ, opts___] := Module[
   {sq, eq, sw, hs, hr, tr,ap, sf, vc, zvps, diff = to - from, tip},
   {sq, eq, sw, hs, hr, ap, sf, vc, zvps} = {ShaftQ, EdgesQ, ShaftWidth, HeadSize, HeadRatio, Aperture, ScaleFactor, VectorColor, ZeroVectorPointSize} /. {opts} /. Options[Vector];
   If[from==to, Return[Graphics3D[{PointSize[zvps],vc,Point[from]}]]];
   diff = If[NumberQ[N[sf]], sf diff, sf[diff]];
   tip = from + diff;
   If[NumberQ[hs], hr = hs/Norm[diff]];
   tr = hr/2;
   Graphics3D[{If[sq,{vc,Thickness[sw],Line[{from,tip-tr diff}]},{}], If[eq, {}, EdgeForm[]], {SurfaceColor[vc],
      With[{temp = Perpend[diff]},
      Polygon[Append[#,tip]]& /@ Partition[(tip - hr diff + #)&/@((ap hr Norm[diff] Base3D) . {temp,Normalize[Cross[temp,diff]]}),2,1]]}}]
] /; Length[from]==Length[to]==3


Arrow[a_, Tail->b_, opts___] := Vector[b,a+b,opts]

Arrow[a_, opts___] := Vector[Table[0,{Length[a]}],a,opts]

ArrowHead[a_, b_, opts___] := Vector[a-b,a,ShaftQ->False,opts];

End[];

EndPackage[];
Null

Graphics`Colors`GosiaGreen = 
        RGBColor[0,  0.392187,  0];

ThreeAxes[u,v]

ThreeAxes[u_, v_] := 
        Graphics3D[{{Blue, Line[{{-u, 0, 0}, {u, 0, 0}}]}, 
            Text["x", {u + v, 0, 0}], {Blue, 
              Line[{{0, -u, 0}, {0, u, 0}}]}, 
            Text["y", {0, u + v, 0}], {Blue, 
              Line[{{0, 0, 0}, {0, 0, u}}]}, 
            Text["z", {0, 0, u + v}]}];
ThreeAxes[u_] := ThreeAxes[u, (u/8)];
ThreeAxes::"usage" = "ThreeAxes[a,b] makes a standard cartesian \
axis graphics object with x, y, and z running from -a to a, and with axis \
labels b units beyond the tips of the axes.  ThreeAxes[a] is \
ThreeAxes[a,a/8].";

T.1) Making 3D perpendicular projections onto planes.
 Making 3D positive definite matrices (frame stretchers). 
 Making 3D reflection matrices (plane flippers) 
 Making matrices for bouncing light rays off surfaces in 3D

T.1.a) Making a  perpendicular projection onto a plane

Any two non-parallel vectors determine a plane through {0,0,0}.
Here's a sample:

Clear[planevector];
planevector[1] = {0.95, 1.71, -1.19};
\(\(planevector[2] = {0.24, 1.83, 1.06};\)
\)
ranger = 4;
b = 3;
\(\(planeplot = 
        Graphics3D[
          Polygon[{\(-b\)\ planevector[1] - 
                b\ planevector[2], \(-b\)\ planevector[1] + 
                b\ planevector[2], b\ planevector[1] + b\ planevector[2], 
              b\ planevector[1] - b\ planevector[2]}]];\)
\)
Show[planeplot, ThreeAxes[2], 
        PlotRange -> {{-ranger, ranger}, {-ranger, 
              ranger}, {-ranger, ranger}}, Axes -> True, 
        Boxed -> False, ViewPoint -> CMView];

The question here is to come up with a matrix P so that when you hit a point {x,y,z} with your matrix P, you get the point on the plane that is closest to {x,y,z}.
Illustrate the action of your matrix with decisive plots.

This is a job for a custom perpendicular frame. Here's one:

normal=planevector[1]\[Cross]planevector[2];

unitnormal = (normal/(Sqrt[normal . normal]));

perpframe[3] = unitnormal;

perpframe[1] = 
          planevector[1]/(Sqrt[planevector[1] . planevector[1]]);

perpframe[2] = perpframe[3]\[Cross]perpframe[1];

scalefactor = 0.7 b;
frameplot = 
          Table[Arrow[scalefactor perpframe[k], Tail -> {0, 0, 0}, 
              VectorColor -> Indigo], {k, 1, 3}];

newplaneplot = 
        Show[frameplot, planeplot, 
          PlotRange -> {{-ranger, ranger}, {-ranger, 
                ranger}, {-ranger, ranger}}, Axes -> True, 
          ViewPoint -> CMView, Boxed -> False, 
          AxesLabel -> {"x", "y", "z"}];

The job is to come up with a matrix P so that when you hit a point {x, y, z} with your matrix P, you get the point on the plane that is closest to {x, y, z}.
Notice that if {x, y, z} is on the plane, then {x, y, z}
is the point on the plane closest to 
       {x, y, z} + any multiple of perpframe[3].

In other words, if {x, y, z} is on the plane, then 
           P . ({x, y, z} +  any multiple of perpframe[3]) = {x, y, 
          z}. 
 This tells you that 
           P.prepframe[3]={0, 0, 0}
Also if {x, y, z} is on the plane, then {x, y, z} is the point on the plane closest to {x, y, z}.  
And because perpframe[1] and perpframe[2] are on the plane, you now know that
          P . perpframe[1] = perpframe[1]
and
           P . perpframe[2] = perpframe[2].
This tells all. 
The matrix P you want is:

Clear[alignerframe, hangerframe, 
        k];
{alignerframe[1], alignerframe[2], 
          alignerframe[3]} = {perpframe[1], perpframe[2], 
          perpframe[3]};
\(\(aligner = {alignerframe[1], alignerframe[2], 
            alignerframe[3]};\)\(
\)\)
{xstretch, ystretch, zstretch}={1,1,0};
\(\(stretcher = 
          DiagonalMatrix[{xstretch, ystretch, zstretch}];\)\(
\)\)
{hangerframe[1], hangerframe[2], 
          hangerframe[3]} = {perpframe[1], perpframe[2], 
          perpframe[3]};
\(\(hanger = 
          Transpose[{hangerframe[1], hangerframe[2], 
              hangerframe[3]}];\)\(
\)\)
P=hanger.stretcher.aligner;
MatrixForm[
      P]

Check it:

P . perpframe[1] == perpframe[1]
P . perpframe[2] == perpframe[2]
P . perpframe[3]

Watch this matrix do its work in this action movie:

a = 3;
Clear[k, pointcolor];
points = 
        Table[{Random[Real, {-a, a}], Random[Real, {-a, a}], 
            Random[Real, {-a, a}]}, {k, 1, 40}];
\(\(pointcolor[k_] = 
        RGBColor[0.5\ \((Sin[\(2\ π\ k\)\/Length[points]] + 1)\), 
          0.5\ \((Cos[\(2\ π\ k\)\/Length[points]] + 1)\), 
          0.3];\)
\)
pointplot = 
        Table[Graphics3D[{PointSize[0.04], pointcolor[k], 
              Point[points[[k]]]}], {k, 
            1, Length[points]}];
\(\(hitpointplot = 
        Table[Graphics3D[{PointSize[0.04], pointcolor[k], 
              Point[P . 
                  points[[k]]]}], {k, 1, 
            Length[points]}];\)
\)
\(\(actionarrows = 
        Table[Arrow[
            P . points[[k]] - 
              points[[k]], 
            Tail -> points[[k]], 
            VectorColor -> pointcolor[k]], {k, 1, 
            Length[points]}];\)
\)
\(\(before = 
        Show[pointplot, newplaneplot, Axes -> True, 
          AxesLabel -> {"x", "y", "z"}, 
          PlotRange -> {{\(-ranger\), ranger}, {\(-ranger\), 
                ranger}, {\(-ranger\), ranger}}, ViewPoint -> CMView, 
          Boxed -> False, 
          PlotLabel -> "Before the hit"];\)
\)
\(\(action = 
        Show[before, actionarrows, 
          PlotRange -> {{\(-ranger\), ranger}, {\(-ranger\), 
                ranger}, {\(-ranger\), ranger}}, ViewPoint -> CMView, 
          PlotLabel -> "Action Arrows"];\)
\)
after = 
        Show[hitpointplot, newplaneplot, Axes -> True, 
          Axes -> True, AxesLabel -> {"x", "y", "y"}, 
          Boxed -> False, 
          PlotRange -> {{-ranger, ranger}, {-ranger, 
                ranger}, {-ranger, ranger}}, ViewPoint -> CMView, 
          PlotLabel -> "After the hit"];

See the same thing from the view point of 6 perpframe[1].

Show[before, ViewPoint -> 6 perpframe[1]];
Show[action, ViewPoint -> 6 perpframe[1]];
Show[after, ViewPoint -> 6 perpframe[1]];

You can see why some folks call this matrix by the name "perpendicular projection".

T.1.b) Making a 3D positive definite matrix (frame stretcher)

Here's a 3D perpendicular frame:

\(\({r, s, t} = N[{0.1\ π, π\/6, 0.2\ π}];\)
\)
Clear[perpframe];
\(\({perpframe[1], perpframe[2], 
          perpframe[3]} = {{Cos[r]\ Cos[t] - Cos[s]\ Sin[r]\ Sin[t], 
            Cos[s]\ Cos[t]\ Sin[r] + Cos[r]\ Sin[t], 
            Sin[r]\ Sin[s]}, {\(-Cos[t]\)\ Sin[r] - Cos[r]\ Cos[s]\ Sin[t], 
            Cos[r]\ Cos[s]\ Cos[t] - Sin[r]\ Sin[t], 
            Cos[r]\ Sin[s]}, {Sin[s]\ Sin[t], \(-Cos[t]\)\ Sin[s], 
            Cos[s]}};\)
\)
ranger = 1;
Show[
        Table[Arrow[perpframe[k], Tail -> {0, 0, 0}, 
            VectorColor -> Indigo], {k, 1, 3}], 
        Graphics3D[Text["perpframe[1]", 0.6 perpframe[1]]], 
        Graphics3D[Text["perpframe[2]", 0.6 perpframe[2]]], 
        Graphics3D[Text["perpframe[3]", 0.6 perpframe[3]]], 
        ThreeAxes[1], ViewPoint -> CMView, 
        PlotRange -> {{-ranger, ranger}, {-ranger, 
              ranger}, {-ranger, ranger}}, 
        Boxed -> False];

Make a 3D positive definite ( a frame stretcher) matrix A whose hits stretch 
  vectors in the direction of perpframe[1] by a factor of 2.5,
  vectors in the direction of perpframe[2] by a factor of 4.1, and
  vectors in the direction of perpframe[3] by a factor of 3.2.
Illustrate with plots.

You want a matrix A with 
       A . perpframe[1]=2.5 perpframe[1]
        A . perpframe[2]=4.1 perpframe[2]
        A . perpframe[3]=3.2 perpframe[3].
To make A, you go with the given perpendicular frame for both your aligner frame  and your hanger frame and use the indicated numbers for your stretches.
Here you go:

Clear[alignerframe, hangerframe, 
        k];
{alignerframe[1], alignerframe[2], 
          alignerframe[3]} = {perpframe[1], perpframe[2], 
          perpframe[3]};
\(\(aligner = {alignerframe[1], alignerframe[2], 
            alignerframe[3]};\)\(
\)\)
{xstretch, ystretch, zstretch}={2.5, 4.1, 3.2};
\(\(stretcher = 
          DiagonalMatrix[{xstretch, ystretch, zstretch}];\)\(
\)\)
{hangerframe[1], hangerframe[2], 
          hangerframe[3]} = {perpframe[1], perpframe[2], 
          perpframe[3]};
\(\(hanger = 
          Transpose[{hangerframe[1], hangerframe[2], 
              hangerframe[3]}];\)\(
\)\)
A=hanger.stretcher.aligner;
MatrixForm[A]

Check:

A . perpframe[1] == xstretch perpframe[1]
A . perpframe[2] == ystretch perpframe[2]
A . perpframe[3] == zstretch perpframe[3]

To illustrate, hit the unit sphere with A and see the resulting football:

Clear[x, y, s, t, pointcolor];
\(\({x[s_, t_], y[s_, t_], z[s_, t_]} = {Sin[s]\ Cos[t], Sin[s]\ Sin[t], 
          Cos[s]};\)
\)
{slow, shigh} = {0, π};
\(\({tlow, thigh} = {0, 2\ π};\)
\)
ranger = Max[{xstretch, ystretch, zstretch, 1.2}];
pointcolor[s_, t_] = 
        RGBColor[0.5 (x[s, t] + 1), 0.5 (y[s, t] + 1), 
          0.5 (z[s, t] + 1)];
sjump = ((shigh - slow)/12);
\(\(tjump = \(thigh - tlow\)\/12;\)
\)
Clear[hitplotter, hitpointplotter, matrix3D];
\(\(hitplotter[matrix3D_] := 
        ParametricPlot3D[
          matrix3D . {x[s, t], y[s, t], z[s, t]}, {s, slow, shigh}, {t, tlow, 
            thigh}, PlotRange -> {{\(-ranger\), ranger}, {\(-ranger\), 
                ranger}, {\(-ranger\), ranger}}, Axes -> True, 
          AxesLabel -> {"x", "y", "z"}, Boxed -> False, 
          ViewPoint -> CMView, 
          DisplayFunction -> Identity];\)
\)
\(\(hitpointplotter[matrix3D_] := 
        Show[{Table[
              Graphics3D[{pointcolor[s, t], PointSize[0.025], 
                  Point[matrix3D . {x[s, t], y[s, t], z[s, t]}]}], {s, slow, 
                shigh - sjump, sjump}, {t, tlow, thigh - tjump, tjump}], 
            Table[Arrow[matrix3D . alignerframe[k], Tail -> {0, 0, 0}, 
                VectorColor -> Red], {k, 1, 3}], 
            Table[Arrow[\(-matrix3D . alignerframe[k]\), 
                Tail -> {0, 0, 0}, VectorColor -> Red], {k, 1, 
                3}]}, PlotRange -> {{\(-ranger\), ranger}, {\(-ranger\), 
                ranger}, {\(-ranger\), ranger}}, Axes -> True, 
          AxesLabel -> {"x", "y", "z"}, Boxed -> False, 
          ViewPoint -> CMView, 
          DisplayFunction -> Identity];\)
\)
\(\(hitframeplotter[
          matrix3D_] := {Table[
            Arrow[matrix3D . alignerframe[k], Tail -> {0, 0, 0}, 
              VectorColor -> Indigo], {k, 1, 3}], 
          Table[Arrow[\(-matrix3D . alignerframe[k]\), 
              Tail -> {0, 0, 0}, VectorColor -> Indigo], {k, 1, 
              3}]};\)
\)
pointsbefore = 
        Show[hitpointplotter[IdentityMatrix[3]], 
          hitframeplotter[IdentityMatrix[3]], 
          PlotLabel -> "Before the hit", 
          DisplayFunction -> $DisplayFunction];

pointsafter = 
        Show[hitpointplotter[A], hitframeplotter[A], 
          PlotLabel -> "After the hit", 
          DisplayFunction -> $DisplayFunction];

See the same thing from the view points of each of the given perpendicular frame vectors:

Show[pointsbefore, ViewPoint -> 10 perpframe[1]];
Show[pointsafter, ViewPoint -> 10 perpframe[1]];

Show[pointsbefore, ViewPoint -> 10 perpframe[2]];
Show[pointsafter, ViewPoint -> 10 perpframe[2]];

Show[pointsbefore, ViewPoint -> 10 perpframe[3]];
Show[pointsafter, ViewPoint -> 10 perpframe[3]];

About as sensual as math gets.

T.1.c) Making a 3D reflection matrix ( plane flipper)

Here is a single vector in 3D:

\(\(normal = {0.2, 0.4, 1.3};\)
\)
\(\(ranger = 
        Max[{normal[[1]], 
            normal[[2]], 
            normal[[3]]}];\)
\)
Show[
        Arrow[normal, Tail -> {0, 0, 0}, 
          VectorColor -> GosiaGreen], Axes3D[ranger], 
        PlotRange -> {{-ranger, ranger}, {-ranger, 
              ranger}, {-ranger, ranger}}, Axes -> True, 
        ViewPoint -> CMView, 
        AxesLabel -> {"x", "y", "z"}, 
        Boxed -> False];

Make this vector into a unit vector and plot:

unitnormal=(normal/(Sqrt[normal . normal]));

ranger = 1;
Show[
        Arrow[unitnormal, Tail -> {0, 0, 0}, 
          VectorColor -> GosiaGreen], Axes3D[1], 
        PlotRange -> {{-ranger, ranger}, {-ranger, 
              ranger}, {-ranger, ranger}}, Axes -> True, 
        ViewPoint -> CMView, 
        AxesLabel -> {"x", "y", "z"}, 
        Boxed -> False];

Envision this unit vector as a unit normal for a plane passing through {0,0,0}.
 Call
            perpframe[3] = unitnormal 
You can use cross products to come up with 
           perpframe[1] and perpframe[2] 
to frame this plane. 
Here's how it goes:

perpframe[3]=unitnormal;

throwawayvector = {Random[Real, {-1, 1}], 
            Random[Real, {-1, 1}], Random[Real, {-1, 1}]};

planevector=throwawayvector\[Cross]perpframe[3];

perpframe[1] = (planevector/Norm)[planevector];

perpframe[2] = perpframe[3]\[Cross]perpframe[1];

frameplot = 
        Table[Arrow[perpframe[k], Tail -> {0, 0, 0}, 
            VectorColor -> Indigo], {k, 1, 3}];
framelabels = {Graphics3D[
              Text["perpframe[1]", 0.6 perpframe[1]]], 
            Graphics3D[Text["perpframe[2]", 0.6 perpframe[2]]], 
            Graphics3D[Text["perpframe[3]", 0.6 perpframe[3]]]};

customframe =  
        Show[frameplot, framelabels, ThreeAxes[1], 
          PlotRange -> {{-ranger, ranger}, {-ranger, 
                ranger}, {-ranger, ranger}}, Axes -> True, 
          ViewPoint -> CMView, Boxed -> False, 
          AxesLabel -> {"x", "y", "z"}];

Throw in a plot of the plane framed by perpframe[1] and perpframe[2]:

{slow, shigh} = {-1, 1};
{tlow, thigh} = {-1, 1};
ranger  =  1.4;
Clear[planeplotter, s, t];
planeplotter[s_, t_] = s perpframe[1] + t perpframe[2];
\(\(planeplot = 
        ParametricPlot3D[
          planeplotter[s, t], {s, slow, shigh}, {t, tlow, thigh}, 
          PlotRange -> All, PlotPoints -> {2, 2}, 
          DisplayFunction -> Identity];\)
\)
planeframe = Show[customframe, planeplot];

Rerun both cells several times. You will probably get different perpframe[1] and perpframe[2] vectors each time, but you will always get the same plane because you get the same normal vector (perpframe[3]) each time.
Here's a new plane through {0,0,0} and a perpendicular frame set so that perpframe[1] and perpframe[2] frame the plane:

normal = {0.2, -0.3, 1.1};
perpframe[3] = (normal/Norm)[normal];
throwawayvector = {Random[Real, {-1, 1}], 
          Random[Real, {-1, 1}], Random[Real, {-1, 1}]};
planevector = throwawayvector\[Cross]perpframe[3];
perpframe[1] = (planevector/Norm)[planevector];
\(\(perpframe[2] = perpframe[3]\[Cross]perpframe[1];\)
\)
\(\(frameplot = 
        Table[Arrow[perpframe[k], Tail -> {0, 0, 0}, 
            VectorColor -> Indigo], {k, 1, 3}];\)
\)
{slow, shigh} = {-2, 3};
\(\({tlow, thigh} = {\(-2\), 3};\)
\)
Clear[planeplotter, s, t];
planeplotter[s_, t_] = s perpframe[1] + t perpframe[2];
\(\(planeplot = 
        ParametricPlot3D[
          planeplotter[s, t], {s, slow, shigh}, {t, tlow, thigh}, 
          PlotRange -> All, PlotPoints -> {2, 2}, 
          DisplayFunction -> Identity];\)
\)
planeandframe = 
        Show[planeplot, frameplot, PlotRange -> All, 
          BoxRatios -> Automatic, Axes -> True, 
          AxesLabel -> {"x", "y", "z"}, Boxed -> False, 
          ViewPoint -> CMView, 
          DisplayFunction -> $DisplayFunction];

Throw in a 3D surface:

Clear[x, y, z, s, t, pointcolor];
\(\({x[s_, t_], y[s_, t_], 
          z[s_, t_]} = {1, \(-1\), 1.5} + {1.5\ Sin[s]\ Cos[2  t], 
            Sin[s]\ Sin[t], 0.4\ Cos[2  s]};\)
\)
{slow, shigh} = {0, π};
\(\({tlow, thigh} = {0, \ π};\)
\)
sjump = ((shigh - slow)/5);
\(\(tjump = \(thigh - tlow\)\/5;\)
\)
ranger = 2.8;
Clear[hitplotter, matrix];
hitplotter[matrix3D_] := 
        ParametricPlot3D[
          matrix3D . {x[s, t], y[s, t], z[s, t]}, {s, slow, shigh}, {t, tlow, 
            thigh}, PlotRange -> {{-ranger, ranger}, {-ranger, 
                ranger}, {-ranger, ranger}}, BoxRatios -> Automatic, 
          Axes -> True, AxesLabel -> {"x", "y", "z"}, 
          Boxed -> False, ViewPoint -> CMView, 
          DisplayFunction -> Identity];
before = 
        Show[hitplotter[IdentityMatrix[3]], planeandframe, Axes3D[ranger], 
          PlotLabel -> "Before", 
          DisplayFunction -> $DisplayFunction];

Use a 3D matrix hit to flip this surface underneath the plane.

Remember that perpframe[3] is perpendicular to the plane and perpframe[1] and perpframe[2] frame the plane.
To make a matrix whose hits flip about the plane,
-> align with {perpframe[1], perpframe[2], perpframe[3]}
-> go with stretch factors all equal to 1 
-> hang on the reversed frame {perpframe[1], perpframe[2], -perpframe[3]}:

\({alignerframe[1], alignerframe[2], 
            alignerframe[
              3]}\  = \ \ 
		\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ {perpframe[1], perpframe[2], 
            perpframe[3]};\)

{xstretch, ystretch, zstretch}  =  {1, 1, 1};

{hangerframe[1], hangerframe[2], hangerframe[3]} =  
		                                          {perpframe[1],perpframe[2],-perpframe[3]};

aligner  =  {alignerframe[1], alignerframe[2], 
            alignerframe[3]};
stretcher  =  
          DiagonalMatrix[{xstretch, ystretch, zstretch}];
\(\(hanger\  = \ 
          Transpose[{hangerframe[1], hangerframe[2], 
              hangerframe[3]}];\)\(
\)\(		\)\)
A = hanger.stretcher.aligner;
MatrixForm[A]

Hits with this matrix preserve everything in the plane framed by perpframe[1] and perpframe[2]:

Clear[s, t];
Expand[A . (s perpframe[1]  +  t perpframe[2])]

s perpframe[1]  +  t perpframe[2]

Hits with this matrix reverse the direction of anything in the direction of perpframe[3]:

A . (s perpframe[3])

-s perpframe[3]

See a hit with this matrix do the flip:

Show[before];
after = 
        Show[hitplotter[A], planeandframe, Axes3D[ranger], 
          PlotLabel -> "After the hit", 
          DisplayFunction -> $DisplayFunction];

See both from the viewpoint of perpframe[2]:

Show[before, ViewPoint -> 6 perpframe[2]];
Show[after, ViewPoint -> 6 perpframe[2]];

Just a little groovy.

T.1.d.i) Making a matrix for bouncing a light ray off a 3D surface

Here are a surface in 3D and a point above the surface all plotted in true scale:

Clear[x, y, z, r, s, t];
\(\({x[s_, t_], y[s_, t_], 
          z[s_, t_]} = {\(-1\), \(-1\), 0} + {Sin[s]\ Cos[t], 
            2\ Sin[s]\ Sin[t], Cos[s]};\)
\)
\(\({{slow, shigh}, {tlow, thigh}} = {{0.2, 1.0}, {0.2, 
            1.5}};\)
\)
point = {0, -0.5, 3};
Clear[surfaceplotter];
\(\(surfaceplotter[s_, t_] = {x[s, t], y[s, t], z[s, t]};\)
\)
surfaceplot = 
        ParametricPlot3D[
          Evaluate[surfaceplotter[s, t]], {s, slow, shigh}, {t, tlow, thigh}, 
          Boxed -> False, BoxRatios -> Automatic, 
          ViewPoint -> CMView, 
          AxesLabel -> {"x", "y", "z"}, 
          DisplayFunction -> Identity];
\(\(pointplot = 
        Graphics3D[{CadmiumOrange, PointSize[0.05], 
            Point[point]}];\)
\)
Show[surfaceplot, pointplot, Boxed -> False, 
        BoxRatios -> Automatic, ViewPoint -> CMView, 
        PlotRange -> All, AxesLabel -> {"x", "y", "z"}, 
        DisplayFunction -> $DisplayFunction];

A light ray emanates from the point and hits the surface:

Clear[ray];
\(\(ray[s_, t_] = surfaceplotter[s, t] - point;\)
\)
sjump = ((shigh - slow)/2);
\(\(tjump = \(thigh - tlow\)\/2;\)
\)
\(\(rayplots = 
        Table[Arrow[ray[s, t], Tail -> point, 
            VectorColor -> MarsYellow, HeadSize -> 0.15], {s, 
            slow + sjump, shigh - sjump, sjump}, {t, tlow + tjump, 
            thigh - tjump, tjump}];\)
\)
setup = 
        Show[surfaceplot, pointplot, rayplots, Boxed -> False, 
          BoxRatios -> Automatic, ViewPoint -> CMView, 
          PlotRange -> All, 
          AxesLabel -> {"x", "y", "z"}, 
          DisplayFunction -> $DisplayFunction];

Your job is to plot the reflected light ray. 
 Do it.

At a point  {x[s, t], y[s, t], z[s, t]} on the surface, the vectors
       tan1[s, t] = {D[x[s, t], s], D[y[s, t], s], D[z[s, t], s]};
and
         tan2[s, t] = {D[x[s, t], t], D[y[s, t], t], D[z[s, t], t]} 
are tangent to the surface.
At each point 
       {x[s, t], y[s, t], z[s, t]}
on the surface, use these two tangential vectors to make a 3D perpendicular frame including two tangential vectors and one normal vector and plot:

Clear[tan1, 
        tan2];
tan1[s_, 
          t_] = {(∂_s) x[s, t], (∂_s) y[s, 
              t], (∂_s) z[s, t]};
tan2[s_, 
            t_] = {(∂_t) x[s, t], (∂_t) y[s, 
                t], (∂_t) z[s, t]};

Clear[alignerframe, s, t, cross];
alignerframe[1,s_,t_]:=tan1[s, t]/(Sqrt[tan1[s, t] . tan1[s, t]]);
cross[s_, t_] := tan1[s, t]\[Cross]tan2[s, t];
alignerframe[3,s_,t_]:=cross[s, t]/(Sqrt[cross[s, t] . cross[s, t]]);
alignerframe[2,s_,t_]:=alignerframe[1,s,t]\[Cross]alignerframe[3,s,t];

frameplots = 
          Table[Arrow[alignerframe[k, s, t], 
              Tail -> {x[s, t], y[s, t], z[s, t]}, 
              VectorColor -> Magenta], {s, slow + sjump, shigh - sjump, 
              sjump}, {t, tlow + tjump, thigh - tjump, tjump}, {k, 1, 3}];

step1 = 
        Show[setup, rayplots, frameplots, 
          DisplayFunction -> $DisplayFunction];

Now reverse the light vector:

\(\(reversedrayplots = 
        Table[Arrow[\(-ray[s, t]\), Tail -> {x[s, t], y[s, t], z[s, t]}, 
            VectorColor -> MarsYellow], {s, slow + sjump, shigh - sjump, 
            sjump}, {t, tlow + tjump, thigh - tjump, tjump}];\)
\)
step2 = 
        Show[surfaceplot, pointplot, reversedrayplots, frameplots, 
          Boxed -> False, BoxRatios -> Automatic, 
          ViewPoint -> CMView, PlotRange -> All, 
          AxesLabel -> {"x", "y", "z"}, 
          DisplayFunction -> $DisplayFunction];

These are not the reflected rays. To get the reflected rays, just use these choices of aligner, stretcher and hanger and plot:

Clear[aligner, hanger, hangerframe, reflectormatrix];
aligner[s_, t_]  =  {alignerframe[1, s, t], 
            alignerframe[2, s, t], alignerframe[3, s, t]};

{xstretch, ystretch, zstretch}  =  {1, 1, 1};
stretcher  =  
          DiagonalMatrix[{xstretch, ystretch, zstretch}];

{hangerframe[1, s_, t_], hangerframe[2, s_, t_], 
            hangerframe[3, s_, t_]} =
 {-alignerframe[1, s, t],-alignerframe[2, s, t],alignerframe[3, s, t]};
 
hanger[s_, t_]  = 
          Transpose[ {hangerframe[1, s, t], hangerframe[2, s, t], 
              hangerframe[3, s, t]}];

reflectormatrix[s_, t_]  =  
          hanger[s, t] . (stretcher . aligner[s, t]);

reflectedrayplots = 
Table[Arrow[reflectormatrix[s, t].(-ray[s, t]),Tail -> {x[s, t], y[s, t], z[s, t]},VectorColor -> CadmiumOrange],
{s, slow + sjump , shigh - sjump, sjump},
                   {t, tlow +  tjump, thigh - tjump, 
                tjump}]; 

\(step3\  = \ \ Show[surfaceplot, pointplot, 
          reversedrayplots, frameplots, reversedrayplots, reflectedrayplots, 
          frameplots, 
          PlotRange -> 
            All, 
\ \ \ \ \ \ \ \ \ \ \ \ DisplayFunction -> $DisplayFunction];\)

Clean it up with a plot showing both the incoming rays and the reflected rays:

finalproduct = 
        Show[setup, rayplots, reflectedrayplots, 
          DisplayFunction -> $DisplayFunction];

Done.

T.1.d.ii) Making  matrices for bouncing lots of light rays off a 3D surface

Here's the same setup as in part i), but this time there are many light rays hitting the surface:

Clear[ray];
\(\(ray[s_, t_] = surfaceplotter[s, t] - point;\)
\)
sjump = ((shigh - slow)/2);
\(\(tjump = \(thigh - tlow\)\/2;\)
\)
\(\(rayplots = 
        Table[Arrow[ray[s, t], Tail -> point, 
            VectorColor -> CadmiumOrange, HeadSize -> 0.1], {s, 
            slow, shigh, sjump}, {t, tlow, thigh, tjump}];\)
\)
setup = 
        Show[surfaceplot, pointplot, rayplots, Boxed -> False, 
          BoxRatios -> Automatic, ViewPoint -> CMView, 
          PlotRange -> All, 
          AxesLabel -> {"x", "y", "z"}, 
          DisplayFunction -> $DisplayFunction];

Your job is to plot the reflected light rays. 
Do it.

At a point  {x[s, t], y[s, t], z[s, t]} on the surface, the vectors
       tan1[s, t] = {D[x[s, t], s], D[y[s, t], s], D[z[s, t], s]};
and
         tan2[s, t] = {D[x[s, t], t], D[y[s, t], t], D[z[s, t], t]} 
are tangent to the surface.
At each point 
       {x[s, t], y[s, t], z[s, t]}
on the surface, use these two tangential vectors to make a 3D perpendicular frame including two tangential vectors and one normal vector and plot:

Clear[tan1, 
        tan2];
tan1[s_, 
          t_] = {(∂_s) x[s, t], (∂_s) y[s, 
              t], (∂_s) z[s, t]};
tan2[s_, 
            t_] = {(∂_t) x[s, t], (∂_t) y[s, 
                t], (∂_t) z[s, t]};

Clear[alignerframe, s, t, cross];
alignerframe[1,s_,t_]:=tan1[s, t]/(Sqrt[tan1[s, t] . tan1[s, t]]);
cross[s_, t_] := tan1[s, t]\[Cross]tan2[s, t];
alignerframe[3,s_,t_]:=cross[s, t]/(Sqrt[cross[s, t] . cross[s, t]]);
alignerframe[2,s_,t_]:=alignerframe[1,s,t]\[Cross]alignerframe[3,s,t];

frameplots = 
          Table[Arrow[alignerframe[k, s, t], 
              Tail -> {x[s, t], y[s, t], z[s, t]}, 
              VectorColor -> Magenta], {s, slow, shigh, sjump}, {t, tlow, 
              thigh, tjump}, {k, 1, 3}];

step1 = 
        Show[setup, rayplots, frameplots, 
          DisplayFunction -> $DisplayFunction];

Now reverse the light vectors:

\(\(reversedrayplots = 
        Table[Arrow[\(-ray[s, t]\), Tail -> {x[s, t], y[s, t], z[s, t]}, 
            VectorColor -> MarsYellow], {s, slow, shigh, sjump}, {t, 
            tlow, thigh, tjump}];\)
\)
step2 = 
        Show[surfaceplot, pointplot, reversedrayplots, frameplots, 
          Boxed -> False, BoxRatios -> Automatic, 
          ViewPoint -> CMView, PlotRange -> All, 
          AxesLabel -> {"x", "y", "z"}, 
          DisplayFunction -> $DisplayFunction];

These are not the reflected rays. To get the reflected rays, just use these choices of aligner, stretcher and hanger and plot:

Clear[aligner, hanger, hangerframe, reflectormatrix];
aligner[s_, t_]  =  {alignerframe[1, s, t], 
            alignerframe[2, s, t], alignerframe[3, s, t]};

{xstretch, ystretch, zstretch}  =  {1, 1, 1};
stretcher  =  
          DiagonalMatrix[{xstretch, ystretch, zstretch}];

{hangerframe[1, s_, t_], hangerframe[2, s_, t_], 
            hangerframe[3, s_, t_]} =
 {-alignerframe[1, s, t],-alignerframe[2, s, t],alignerframe[3, s, t]};
 
hanger[s_, t_]  =  
          Transpose[ {hangerframe[1, s, t], hangerframe[2, s, t], 
              hangerframe[3, s, t]}];

reflectormatrix[s_, t_]  =  
          hanger[s, t] . stretcher . aligner[s, t];

\(reflectedrayplots\  = \ 

          Table[Arrow[reflectormatrix[s, t] . \((\(-ray[s, t]\))\), 
              Tail -> {x[s, t], y[s, t], z[s, t]}, 
              VectorColor -> CadmiumOrange], 
{s, slow\ , shigh, 
              sjump}, 
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ {t, tlow, 
              thigh, tjump}];\) 

\(step3\  = \ \ Show[surfaceplot, pointplot, 
          reversedrayplots, frameplots, reversedrayplots, reflectedrayplots, 
          frameplots, 
          PlotRange -> 
            All, 
\ \ \ \ \ \ \ \ \ \ \ \ DisplayFunction -> $DisplayFunction];\)

Clean it up with a plot showing both the incoming rays and the reflected rays:

finalproduct = 
        Show[setup, rayplots, reflectedrayplots, 
          DisplayFunction -> $DisplayFunction];

Done.

T.2) 3D rotations: Rotating about lines in 3D

T.2.a.i) Making matrices whose hits rotate about the z-axis

Here's a double pyramid:

ranger = 3.5;
Clear[x, y, z, s, t];
\(\({x[s_, t_], y[s_, t_], 
          z[s_, t_]} = {\(-1\), \(-1\), 2} + {Sin[s]\ Cos[t], Sin[s]\ Sin[t], 
            Cos[s]\^3};\)
\)
{slow, shigh} = {0, π};
\(\({tlow, thigh} = {0, 2\ π};\)
\)
ranger = 3.5;
Clear[hitplotter, matrix];
\(\(hitplotter[matrix3D_] := 
        ParametricPlot3D[
          matrix3D . {x[s, t], y[s, t], z[s, t]}, {s, slow, shigh}, {t, tlow, 
            thigh}, PlotPoints -> {5, 5}, 
          PlotRange -> {{\(-ranger\), ranger}, {\(-ranger\), 
                ranger}, {\(-1\), ranger}}, BoxRatios -> Automatic, 
          Axes -> True, AxesLabel -> {"x", "y", "z"}, 
          Boxed -> False, ViewPoint -> CMView, 
          DisplayFunction -> Identity];\)
\)
surfacebefore = 
        Show[hitplotter[IdentityMatrix[3]], Axes3D[ranger], 
          PlotLabel -> "Before", 
          DisplayFunction -> $DisplayFunction];

Use hits with a 3D rotation matrix to rotate this surface about the z-axis.

In 2D, to rotate by s counterclockwise radians, you hit with:

Clear[rotater2D, s];
rotater2D[s_]=Transpose[{{Cos[s], Sin[s]},{Cos[s + (π/2)], Sin[s + (π/2)]}}];

MatrixForm[rotater2D[s]]

You can carry this over a 3D matrix whose hits rotate about the z-axis this way:

Clear[zrotater3D, s];
zrotater3D[s_]=Transpose[{{Cos[s],Sin[s],0},{Cos[s + (π/2)],Sin[s + (π/2)],0},{0,0,1}}];

MatrixForm[
      zrotater3D[s]]

To see why this works, look at:

rotater2D[s].{x, y}

And look at:

zrotater3D[s] . {x, y, z}

A hit with rotater3D[s] rotates the x's and y's just the way a hit with rotater2D[s] does and rotater3D[s] does not disturb the z's at all.
Watch hits with rotater3D[s] whirl the double pyramid around the z - axis:

jump = ((2 π)/6);
Table[Show[hitplotter[zrotater3D[s]],Axes3D[ranger],PlotLabel -> N[s],DisplayFunction -> $DisplayFunction],{s, (jump/2), 2 π - (jump/2), jump}]

See the same thing from a view point way out the positive z axis.

jump = ((2 π)/6);
Table[Show[hitplotter[zrotater3D[s]],Axes3D[0.8 ranger],PlotLabel -> N[s],ViewPoint -> 12 {0, 0, 1},DisplayFunction -> $DisplayFunction],{s, (jump/2), 2 π - (jump/2), jump}]

Just as it was made to do.

T.2.a.ii)  Making matrices whose hits rotate about the x-axis

Here's another double pyramid :

ranger = 4;
Clear[x, y, z, s, t];
\(\({x[s_, t_], y[s_, t_], 
          z[s_, t_]} = {1, \(-1\), 2} + {Sin[s]\ Cos[t], Sin[s]\ Sin[t], 
            Cos[s]\^3};\)
\)
{slow, shigh} = {0, π};
\(\({tlow, thigh} = {0, 2\ π};\)
\)
ranger = 3.5;
Clear[hitplotter, matrix];
\(\(hitplotter[matrix3D_] := 
        ParametricPlot3D[
          matrix3D . {x[s, t], y[s, t], z[s, t]}, {s, slow, shigh}, {t, tlow, 
            thigh}, PlotPoints -> {5, 5}, 
          PlotRange -> {{\(-ranger\), ranger}, {\(-ranger\), 
                ranger}, {\(-ranger\), ranger}}, BoxRatios -> Automatic, 
          Axes -> True, AxesLabel -> {"x", "y", "z"}, 
          Boxed -> False, ViewPoint -> CMView, 
          DisplayFunction -> Identity];\)
\)
surfacebefore = 
        Show[hitplotter[IdentityMatrix[3]], Axes3D[ranger], 
          PlotLabel -> "Before", 
          DisplayFunction -> $DisplayFunction];

Use hits with a 3D rotation matrix to rotate this surface about the plotted x-axis.

In 2D, to rotate by s counterclockwise radians, you hit with:

Clear[rotater2D, s];
rotater2D[s_]=Transpose[{{Cos[s], Sin[s]},{Cos[s + (π/2)], Sin[s + (π/2)]}}];

MatrixForm[rotater2D[s]]

You can carry this over a 3D matrix whose hits rotate about the x-axis this way:

Clear[xrotater3D, s];
xrotater3D[s_]=Transpose[{{1,0,0},{0,Cos[s],Sin[s]},{0,Cos[s + (π/2)],Sin[s + (π/2)]}}];

MatrixForm[
      xrotater3D[s]]

To see why this works, look at:

rotater2D[s] . {y, z}

And look at:

xrotater3D[s] . {x, y, z}

A hit with xrotater3D[s] rotates the y's and z's just the way a hit with rotater2D[s] does and xrotater3D[s] does not disturb the x's at all.
Watch hits with xrotater3D[s] whirl the double pyramid around the x - axis:

jump = ((2 π)/6);
Table[
      Show[hitplotter[xrotater3D[s]], Axes3D[ranger], PlotLabel -> N[s], 
        DisplayFunction -> $DisplayFunction], {s, (jump/2), 
        2 π - (jump/2), jump}]

See the same thing from a view point way out the positive x axis.

jump = ((2 π)/6);
Table[
      Show[hitplotter[xrotater3D[s]], Axes3D[0.8 ranger], 
        PlotLabel -> N[s], ViewPoint -> 12 {1, 0, 0}, 
        DisplayFunction -> $DisplayFunction], {s, (jump/2), 
        2 π - (jump/2), jump}]

Just as it was made to do.

Whirlaway.

T.3.a.iii) Rotating about 3D lines through {0,0,0}

Here's the same setup as in part i) shown with a line through {0,0,0}:

linedirectionvector = {0.1, 1.1, 2.6};
\(\(newline = 
        Graphics3D[{ForestGreen, 
            Line[{\(-linedirectionvector\), 
                2  linedirectionvector}]}];\)
\)
Show[hitplotter[IdentityMatrix[3]], newline, PlotRange -> All, 
        PlotLabel -> "Before", 
        DisplayFunction -> $DisplayFunction];

Use matrix hits to rotate this surface about the plotted line.

Make a custom perpendicular frame, taking care that perpframe[3] is a unit vector pointing in the direction of the plotted line:

perpframe[3] = 
          (linedirectionvector/Norm)[linedirectionvector];

throwawayvector = {Random[Real, {-1, 1}], 
            Random[Real, {-1, 1}], Random[Real, {-1, 1}]};

planevector=throwawayvector\[Cross]perpframe[3];
perpframe[1] = (planevector/Norm)[planevector];
perpframe[2] = perpframe[3]\[Cross]perpframe[1];

frameplot = 
          Table[Arrow[perpframe[k], Tail -> {0, 0, 0}, 
              VectorColor -> Indigo], {k, 1, 3}];

Show[hitplotter[IdentityMatrix[3]], frameplot, newline, 
        PlotLabel -> "Before", 
        DisplayFunction -> $DisplayFunction];

Activate:

Clear[zrotater3D, s];
\(\(zrotater3D[s_] = 
        Transpose[{{Cos[s], Sin[s], 0}, {Cos[s + π\/2], 
              Sin[s + π\/2], 0}, {0, 0, 1}}];\)
\)
MatrixForm[zrotater3D[s]]

Use the custom frame for the aligner frame and for the hanger frame:

Clear[alignerframe, 
        hangerframe];
{alignerframe[1], alignerframe[2], 
          alignerframe[3]} = {perpframe[1], perpframe[2], 
          perpframe[3]};
aligner = {alignerframe[1], alignerframe[2], 
              alignerframe[3]};

MatrixForm[
      aligner]

{hangerframe[1], hangerframe[2], 
          hangerframe[3]} = {perpframe[1], perpframe[2], 
          perpframe[3]};
hanger = 
            Transpose[{hangerframe[1], hangerframe[2], hangerframe[3]}];

MatrixForm[
      hanger]

The matrix you want is:

Clear[linerotator];
linerotater[s_]=Expand[hanger.zrotater3D[s].aligner]

Ugly, but effective.
Watch this ugly rotation matrix do its work:

jump = (π/4);
Table[
      Show[hitplotter[linerotater[s]], frameplot, newline, 
        PlotLabel -> N[s], 
        DisplayFunction -> $DisplayFunction], {s, 0, 2 π - (jump/2), 
        jump}]

See it from the viewpoint of perpframe[3]:

Table[
      Show[hitplotter[linerotater[s]], frameplot, newline, 
        PlotLabel -> N[s], ViewPoint -> 6 perpframe[3], 
        DisplayFunction -> $DisplayFunction], {s, 0, 2 π - (jump/2), 
        jump}]

Getting dizzy.

The hit with aligner replots the surface with  
       the positive x - axis playing the former role of perpframe[1],
       the positive y - axis playing the former role of perpframe[2], 
 and  the positive z - axis playing the former role of perpframe[3].
 
Then the hit with zrotater3D[s] rotates about the z-axis. 
 
And the hit with hanger replots the rotated surface with
        perpframe[1] playing the former role of the positive x-axis 
        perpframe[2] playing the former role of the positive y-axis   
        perpframe[3] playing the former role of the positive z-axis.

The final result is nothing more or less than a rotation about perpframe[3]

T.3) Euler angles and the 3D right hand frame maker.
Right and left hand perpendicular frames in 3D.

T.3.a.i)  Euler angles r, s and t  and the 3D right hand frame maker

Here's that nasty formula that produces beautiful 3D right hand perpendicular frames.

Clear[perpframe, r, s, t];
{perpframe[1], perpframe[2], perpframe[3]} ={{Cos[r] Cos[t] - Cos[s] Sin[r] Sin[t], 
              Cos[s] Cos[t] Sin[r] + Cos[r] Sin[t], Sin[r] Sin[s]},{-Cos[t] Sin[r] - Cos[r] Cos[s] Sin[t], 
              Cos[r] Cos[s] Cos[t] - Sin[r] Sin[t], Cos[r] Sin[s]},{Sin[s] Sin[t], -Cos[t] Sin[s], Cos[s]}}

See one:

r = (π/4);
s = (π/8);
t = (π/3);
Clear[perpframe];
{perpframe[1], perpframe[2], 
          perpframe[3]} = {{Cos[r] Cos[t] - Cos[s] Sin[r] Sin[t], 
            Cos[s] Cos[t] Sin[r] + Cos[r] Sin[t], 
            Sin[r] Sin[s]}, {-Cos[t] Sin[r] - Cos[r] Cos[s] Sin[t], 
            Cos[r] Cos[s] Cos[t] - Sin[r] Sin[t], 
            Cos[r] Sin[s]}, {Sin[s] Sin[t], -Cos[t] Sin[s], 
            Cos[s]}};
ranger = 1.0;
frameplot = 
        Show[Table[
            Arrow[perpframe[k], Tail -> {0, 0, 0}, 
              VectorColor -> Indigo], {k, 1, 3}], 
          Graphics3D[Text["perpframe[1]", 0.4 perpframe[1]]], 
          Graphics3D[Text["perpframe[2]", 0.7 perpframe[2]]], 
          Graphics3D[Text["perpframe[3]", 0.7 perpframe[3]]], 
          Axes3D[2, 0.1], 
          PlotRange -> {{-ranger, ranger}, {-ranger, 
                ranger}, {-ranger, ranger}}, Boxed -> False, 
          Axes -> True, ViewPoint -> CMView, 
          AxesLabel -> {"x", "y", "z"}];

See some more:

r  =   Random[Real, {-(π/2), (π/2)}];
s  =   Random[Real, {-(π/2), (π/2)}];
t  =  
        Random[Real, {-(π/2), (π/2)}];
{perpframe[1], perpframe[2], 
          perpframe[3]}  =  {{Cos[r] Cos[t] - Cos[s] Sin[r] Sin[t], 
            Cos[s] Cos[t] Sin[r] + Cos[r] Sin[t], 
            Sin[r] Sin[s]}, {-Cos[t] Sin[r] - Cos[r] Cos[s] Sin[t], 
            Cos[r] Cos[s] Cos[t] - Sin[r] Sin[t], 
            Cos[r] Sin[s]}, {Sin[s] Sin[t], -Cos[t] Sin[s], 
            Cos[s]}};
ranger  =  1;
\(\(frameplot\  = \ 
        Show[Table[
\ \ \ \ \ Arrow[perpframe[k], Tail -> {0, 0, 0}, 
              VectorColor -> Indigo], {k, 1, 3}], \ 
\ \ \ \ \ Graphics3D[
            Text["perpframe[1]", 
              0.4\ perpframe[1]]], 
\ \ \ \ \ Graphics3D[
            Text["perpframe[2]", 
              0.7\ perpframe[2]]], 
\ \ \ \ \ Graphics3D[
            Text["perpframe[3]", 0.7\ perpframe[3]]], 
\ \ \ \ \ Axes3D[
            1, 0.1], 
\ \ \ \ \ PlotRange -> {{\(-ranger\), 
                ranger}, {\(-ranger\), ranger}, {\(-ranger\), 
                ranger}}, 
\ \ \ \ \ Boxed -> False, 
\ \ \ \ \ Axes -> 
            True, ViewPoint -> CMView, 
          AxesLabel -> {"x", "y", "z"}];\)\)

Explain what the parameters r, s and t mean.

This is one situation in which the explanation is easier than the formula.
Dial up the matrix zrot[r] whose hits rotate everything r radians about the z-axis:

Clear[zrot, r];
zrot[r_]=Transpose[{{Cos[r],Sin[r],0},{Cos[r + (π/2)],Sin[r + (π/2)],0},{0,0,1}}];
MatrixForm[zrot[r]]

Dial up the matrix xrot[s] whose hits rotate everything s radians about the x-axis:

Clear[xrot, s];
xrot[s_]=Transpose[{{1,0,0},{0,Cos[s],Sin[s]},{0,Cos[s + (π/2)],Sin[s + (π/2)]}}];
MatrixForm[xrot[s]]

Now start with the usual x-y-z axes perpendicular frame
          {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}} 
and hit it with zrot[r], thereby rotating r radians about the z- axis.
This gives a new perpendicular frame:

{zrot[r].{1, 0, 0},
	zrot[r].{0, 1, 0},
	zrot[r].{0, 0, 1}}

Hit this perpendicular frame with  xrot[s], thereby rotating s radians about the x- axis.
This gives a new perpendicular frame:

{xrot[s].zrot[r].{1, 0, 0},
	xrot[s].zrot[r].{0, 1, 0},
	xrot[s].zrot[r].{0, 0, 1}}

Finally hit this perpendicular frame with  zrot[t], thereby rotating t radians about the z- axis (again).
This is the perpendicular frame corresponding to the Euler angles r, s and t:

{zrot[t].xrot[s].zrot[r].{1, 0, 0},
	zrot[t].xrot[s].zrot[r].{0, 1, 0},
	zrot[t].xrot[s].zrot[r].{0, 0, 1}}

This is the same as the formula
{perpframe[1], perpframe[2], perpframe[3]} =
{{Cos[r] Cos[t] - Cos[s] Sin[r] Sin[t], 
          Cos[s] Cos[t] Sin[r] + Cos[r] Sin[t], Sin[r] Sin[s]},
 {-Cos[t] Sin[r] - Cos[r] Cos[s] Sin[t], 
          Cos[r] Cos[s] Cos[t] - Sin[r] Sin[t], Cos[r] Sin[s]},
 {Sin[s] Sin[t], -Cos[t] Sin[s], Cos[s]}}.
Now you know where this formula comes from.

And you know that the Euler angles r, s and t specify:
         An initial rotation by r radians about the z-axis, 
         followed by a rotation by s radians about the x-axis 
and then 
          followed by a rotation by t radians about the z-axis.

See it happen in stages:

Start with r, s and t zeroed out:

r  =   0;
s  =   0;
t  =  0;
{perpframe[1], perpframe[2], 
          perpframe[3]}  =  {{Cos[r] Cos[t] - Cos[s] Sin[r] Sin[t], 
            Cos[s] Cos[t] Sin[r] + Cos[r] Sin[t], 
            Sin[r] Sin[s]}, {-Cos[t] Sin[r] - Cos[r] Cos[s] Sin[t], 
            Cos[r] Cos[s] Cos[t] - Sin[r] Sin[t], 
            Cos[r] Sin[s]}, {Sin[s] Sin[t], -Cos[t] Sin[s], 
            Cos[s]}};
ranger  =  
        1;
frameplot = Show[\(Table[
\ \ \ \ \ Arrow[perpframe[k], Tail -> {0, 0, 0}, 
                VectorColor -> Indigo], {k, 1, 3}]\), 
     Graphics3D[
              Text["perpframe[1]", 0.4 perpframe[1]]],
     Graphics3D[
              Text["perpframe[2]", 0.7 perpframe[2]]],
     Graphics3D[
              Text["perpframe[3]", 0.7 perpframe[3]]],
     Axes3D[1, 0.1],
     PlotRange -> {{-ranger, ranger}, {-ranger, 
                  ranger}, {-ranger, ranger}},
     Boxed -> False,PlotLabel->"\!\(\*
StyleBox[\"Before\",\nFontColor->RGBColor[0, 0, 1]]\)",
     ViewPoint -> CMView,AxesLabel -> {"x", "y", "z"}];

First rotate this frame r radians about the z- axis:

r  =  (π/4);
s  =   0;
t  =  0;
{perpframe[1], perpframe[2], 
          perpframe[3]}  =  {{Cos[r] Cos[t] - Cos[s] Sin[r] Sin[t], 
            Cos[s] Cos[t] Sin[r] + Cos[r] Sin[t], 
            Sin[r] Sin[s]}, {-Cos[t] Sin[r] - Cos[r] Cos[s] Sin[t], 
            Cos[r] Cos[s] Cos[t] - Sin[r] Sin[t], 
            Cos[r] Sin[s]}, {Sin[s] Sin[t], -Cos[t] Sin[s], 
            Cos[s]}};
ranger  =  
        1;
frameplot = Show[\(Table[
\ \ \ \ \ Arrow[perpframe[k], Tail -> {0, 0, 0}, 
                VectorColor -> Indigo], {k, 1, 3}]\), 
     Graphics3D[
              Text["perpframe[1]", 0.4 perpframe[1]]],
     Graphics3D[
              Text["perpframe[2]", 0.7 perpframe[2]]],
     Graphics3D[
              Text["perpframe[3]", 0.7 perpframe[3]]],
     Axes3D[1, 0.1],
     PlotRange -> {{-ranger, ranger}, {-ranger, 
                  ranger}, {-ranger, ranger}},
     Boxed -> False,PlotLabel->"\!\(\*
StyleBox[\"Rotate\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"r\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"radians\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"about\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"z\",\nFontColor->RGBColor[1, 0, 0]]\)\!\(\*
StyleBox[\"-\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"axis\",\nFontColor->RGBColor[0, 0, 1]]\)",
    ViewPoint -> CMView,AxesLabel -> {"x", "y", "z"}];

Second rotate the frame above by s radians about the x-axis

r  = (π/4);
s = (π/6);
t  =  0;
{perpframe[1], perpframe[2], 
          perpframe[3]}  =  {{Cos[r] Cos[t] - Cos[s] Sin[r] Sin[t], 
            Cos[s] Cos[t] Sin[r] + Cos[r] Sin[t], 
            Sin[r] Sin[s]}, {-Cos[t] Sin[r] - Cos[r] Cos[s] Sin[t], 
            Cos[r] Cos[s] Cos[t] - Sin[r] Sin[t], 
            Cos[r] Sin[s]}, {Sin[s] Sin[t], -Cos[t] Sin[s], 
            Cos[s]}};
ranger  =  
        1;
frameplot = Show[\(Table[
\ \ \ \ \ Arrow[perpframe[k], Tail -> {0, 0, 0}, 
                VectorColor -> Indigo], {k, 1, 3}]\), 
     Graphics3D[
              Text["perpframe[1]", 0.4 perpframe[1]]],
     Graphics3D[
              Text["perpframe[2]", 0.7 perpframe[2]]],
     Graphics3D[
              Text["perpframe[3]", 0.7 perpframe[3]]],
     Axes3D[1, 0.1],
     PlotRange -> {{-ranger, ranger}, {-ranger, 
                  ranger}, {-ranger, ranger}},
     Boxed -> False,PlotLabel->"\!\(\*
StyleBox[\"Then\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"rotate\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\(\(\\\\\)
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\)\!\(\*
StyleBox[\"s\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"radians\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"about\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"x\",\nFontColor->RGBColor[1, 0, 0]]\)\!\(\*
StyleBox[\"-\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"axis\",\nFontColor->RGBColor[0, 0, 1]]\)",
    ViewPoint -> CMView,AxesLabel -> {"x", "y", "z"}];

Finally rotate the frame above by t radians about the z-axis

r  = (π/4);
s = (π/6);
t  = -(π/4);
{perpframe[1], perpframe[2], 
          perpframe[3]}  =  {{Cos[r] Cos[t] - Cos[s] Sin[r] Sin[t], 
            Cos[s] Cos[t] Sin[r] + Cos[r] Sin[t], 
            Sin[r] Sin[s]}, {-Cos[t] Sin[r] - Cos[r] Cos[s] Sin[t], 
            Cos[r] Cos[s] Cos[t] - Sin[r] Sin[t], 
            Cos[r] Sin[s]}, {Sin[s] Sin[t], -Cos[t] Sin[s], 
            Cos[s]}};
ranger  =  
        1;
frameplot = Show[\(Table[
\ \ \ \ \ Arrow[perpframe[k], Tail -> {0, 0, 0}, 
                VectorColor -> Indigo], {k, 1, 3}]\), 
     Graphics3D[
              Text["perpframe[1]", 0.4 perpframe[1]]],
     Graphics3D[
              Text["perpframe[2]", 0.7 perpframe[2]]],
     Graphics3D[
              Text["perpframe[3]", 0.7 perpframe[3]]],
     Axes3D[1, 0.1],
     PlotRange -> {{-ranger, ranger}, {-ranger, 
                  ranger}, {-ranger, ranger}},
     Boxed -> False,PlotLabel->"\!\(\*
StyleBox[\"Finally\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"rotate\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\(\(\\\\\)
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\)\!\(\*
StyleBox[\"t\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"radians\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"about\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\" \",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"z\",\nFontColor->RGBColor[1, 0, 0]]\)\!\(\*
StyleBox[\"-\",\nFontColor->RGBColor[0, 0, 1]]\)\!\(\*
StyleBox[\"axis\",\nFontColor->RGBColor[0, 0, 1]]\)",
     ViewPoint -> CMView,AxesLabel -> {"x", "y", "z"}];

Grab all four plots and animate. Then go back and change the specifications of r, s and t rerun.

T.3.a.ii) The 3D frame maker produces right hand perpendicular frames

A right hand 3D perpendicular frame is any frame that has the same orientation as
the x-y-z coordinate frame  {{1,0.0},{0,1,0},{0,0,1}}:

{1, 0, 0} . Cross[{0, 1, 0}, {0, 0, 1}]

So a 3D perpendicular frame  
          {perpframe[1],  perpframe[2] , perpframe[3]} 
 is a right hand frame if
          perpframe[1]. ( perpframe[2] × perpframe[3]) = 1.
          
And a hand 3D perpendicular frame  
          {perpframe[1],  perpframe[2] , perpframe[3]} 
 is a left hand frame if
          perpframe[1]. ( perpframe[2] × perpframe[3]) = -1.
      
Explain why the 3D perpendicular frame produced by:

Clear[perpframe, r, s, t];
{perpframe[1], perpframe[2], perpframe[3]} ={{Cos[r] Cos[t] - Cos[s] Sin[r] Sin[t], 
              Cos[s] Cos[t] Sin[r] + Cos[r] Sin[t], Sin[r] Sin[s]},{-Cos[t] Sin[r] - Cos[r] Cos[s] Sin[t], 
              Cos[r] Cos[s] Cos[t] - Sin[r] Sin[t], Cos[r] Sin[s]},{Sin[s] Sin[t], -Cos[t] Sin[s], Cos[s]}}

is a right hand frame.

From the last part  
      {perpframe[1],perpframe[2],perpframe[3]} 
comes from successive rotations of 
         {{1,0.0},{0,1,0},{0,0,1}}; 
so it has the same relative orientation as  
         {{1,0.0},{0,1,0},{0,0,1}}.
So the fact that  
         perpframe[1]. ( perpframe[2] × perpframe[3])  = 1
is guaranteed:

Simplify[perpframe[1].Cross[perpframe[2],perpframe[3]]]

T.3.a.iii) Left hand perpendicular frames in 3D

Look at this:

Clear[perpframe, r, s, t];
{perpframe[1], perpframe[2], perpframe[3]} ={{Cos[r] Cos[t] - Cos[s] Sin[r] Sin[t], 
              Cos[s] Cos[t] Sin[r] + Cos[r] Sin[t], Sin[r] Sin[s]},{-Cos[t] Sin[r] - Cos[r] Cos[s] Sin[t], 
              Cos[r] Cos[s] Cos[t] - Sin[r] Sin[t], Cos[r] Sin[s]},{Sin[s] Sin[t], -Cos[t] Sin[s], Cos[s]}}

Make a new perpendicular frame by interchanging perpframe[1] and perpframe[2] and see whether the new frame is a right hand frame:

Clear[
        newperpframe];
newperpframe[1]  =  
        perpframe[2];
newperpframe[2]  =  
        perpframe[1];
newperpframe[3]  =  
        perpframe[3];
Simplify[newperpframe[1].Cross[newperpframe[2],newperpframe[3]]]

You make the call: 
Is 
        {newperpframe[1],newperpframe[2],{newperpframe[3]} 
a left or a right hand frame in 3D?

Look at  newperpframe[1]. ( newperpframe[2] × newperpframe[3])  again:

Simplify[newperpframe[1].Cross[newperpframe[2],newperpframe[3]]]

This signals loudly and clearly that   {newperpframe[1],newperpframe[2],{newperpframe[3]} is a left hand perpendicular frame.

T.4)  Det[A .B]   = Det[A] Det[B]
If A is a 3D diagonal matrix, then Det[A] = product of diagonal entries
Why Det[(A^(-1))]  =  (1/Det) [A]
 If A is a 3D hanger or aligner based on a right hand frame, then Det[A]  =  1.
 If A is a 3D hanger or aligner based on a left hand frame, then Det[A]  = —1.
 Why Det[(A^t)] = Det[A]

T.4.a.)   Det[A.B] = Det[A] Det[B]

Here are two random 3D matrices A and B

A=(({{Random[Real, {-4, 4}], Random[
                  Real, {-4, 4}], Random[Real, {-4, 4}]}, {Random[Real, {-4, 4}], Random[
                  Real, {-4, 4}], Random[Real, {-4, 4}]}, {Random[Real, {-4, 4}], Random[
                  Real, {-4, 4}], Random[Real, {-4, 4}]}}));
B=(({{Random[Real, {-4, 4}], Random[
                  Real, {-4, 4}], Random[Real, {-4, 4}]}, {Random[Real, {-4, 4}], Random[
                  Real, {-4, 4}], Random[Real, {-4, 4}]}, {Random[Real, {-4, 4}], Random[
                  Real, {-4, 4}], Random[Real, {-4, 4}]}}));
MatrixForm[
      A]
MatrixForm[B]

Here are calculations of Det[A.B] and Det[A] Det[B]:

Det[A . B]
Det[A] Det[B]

All clued in matrix folks know that when you go with two 3D matrices A and B, then you can be sure that
        Det[A.B] = Det[A].Det[B].                         
Explain this.

This is a job for pure bean-counting. Doing it by hand would be a big project. But turning the supreme bean-counter - namely the computer loose on this one makes the explanation into a snap.
Enter a cleared matrix 3D A:

Clear[a, b, c, d, e, f, g, h, i, j]
A = (({{a, b, c}, {d, f, g}, {h, i, j}}));
MatrixForm[A]

Apply the formula Det[A] =  col[1].(col[2] × col[3]) to calculate Det[A]

Det[A]

Enter another cleared matrix B:

Clear[r, s, t, u, v, w, x, y, z]
B = (({{r, s, t}, {u, v, w}, {x, y, z}}));
MatrixForm[B]

Apply the formula Det[B] =  col[1].(col[2] × col[3]) to calculate Det[B]

Det[B]

Calculate A.B:

MatrixForm[A.B]

Apply the formula Det[A.B] = col[1].(col[2]×col[3]) to calculate Det[A.B]

productdet = Expand[Det[A.B]]

Now calculate Det[A] times Det[B]

Expand[Det[A] Det[B]]

Both give you the same thing:

Expand[Det[A.B]] == Expand[Det[A] Det[B]]

And because A and B could stand for any choices of 3D matrices A and B, you see conclusively that
              Det[A.B] = Det[A] Det[B]
is a sure bet for any 3D matrices A and B.

T.4.b) If A is 3D diagonal matrix , then Det[A] = product of diagonal entries

Here's a random 3D diagonal matrix

Clear[
        diagonalentry];
diagonalentry[1]  =  
        Random[Real, {-2, 2}];
diagonalentry[
          2]  =  Random[
          Real, {-2, 2}];
diagonalentry[
          3]  =  Random[Real, {-2, 2}];
diagonalmatrix=(({{diagonalentry[1], 0, 0}, {0, diagonalentry[2], 0}, {0, 0, diagonalentry[3]}}));
MatrixForm[
      diagonalmatrix]

Det[diagonalmatrix] is:

Det[diagonalmatrix]

Compare:

diagonalentry[1] diagonalentry[2] diagonalentry[3]

Explain why the same thing happens for any and all 3D diagonal matrices.

The easiest way to see this is to use the formula

Det[A] =  col[1].(col[2] × col[3])

from the Basics.
Applying this formula to

Det[diagonalmatrix ]  = Det[ (({{diagonalentry[1], 0, 0}, {0, diagonalentry[2], 0}, {0, 0, diagonalentry[3]}}))]

gives

Clear[col, diagonalentry];
col[1]  =  {diagonalentry[1], 0, 0};
col[2]  =  {0, diagonalentry[2], 0};
col[3]  =  {0, 0, diagonalentry[3]};
col[1] . Cross[col[2], col[3]]

There you go.

T.4.c)  Why   Det[(A^(-1))] =  (1/Det) [A]

Look at these calculations of Det[(A^(-1))] and (1/Det)[A] for a random matrix A:

A = (({{Random[Real, {-3, 3}], Random[
                      Real, {-3, 3}]}, {Random[Real, {-3, 3}], Random[
                      Real, {-3, 3}]}}));
Det[Inverse[A]]

(1/(Det[A]))

Apparently,   Det[(A^(-1))] = (1/Det) [A].

Explain why this is guaranteed for any and all invertible 2D matrices A.

Identity =  (A^(-1)). A
So
        1  = Det[Identity] = Det[(A^(-1))] Det[A].
And so
        (1/Det) [A] = Det[(A^(-1))] .
That's all there is to it.

T.4.d.i) The determinant of a 3D hanger or aligner based on a right hand perpendicular frame is equal to +1

Explain this:
   The determinant of a hanger or aligner based on a right hand perpendicular frame is equal to 1.

Go with a right hand 3D perpendicular frame {perpframe[1],perpframe[2],perpframe[3]} so that  
              perpframe[1]. ( perpframe[2] × perpframe[3]) = 1. 
              
The hanger matrix based on this right hand perpendicular frame is
           hanger  =    (({{perpframe[1], perpframe[2], perpframe[3]}, {↓, ↓, ↓}})).

So Det[hanger] = column[1]. ( column[2] × column[3]) = perpframe[1]. ( perpframe[2] × perpframe[3]) = 1.

The aligner matrix based on this right hand frame is
        aligner =(({{perpframe[1], →}, {perpframe[2], →}, {perpframe[3], →}})).
Remembering that hanger and aligner are mutually inverse, you get
           Identity = hanger.aligner.
 So
           1 = Det[Identity] = Det[hanger] Det[aligner].
And because Det[ hanger] = 1, you get
            1  = 1 Det[aligner].
This tells you that Det[aligner] = 1.

T.4.d.ii) The determinant of a 3D hanger or aligner based on a left hand perpendicular frame is equal to  -1

Explain this:
   The determinant of a hanger or aligner based on a left hand perpendicular frame is equal to -1.

Go with a left hand 3D perpendicular frame {perpframe[1],perpframe[2],perpframe[3]} so that  
              perpframe[1]. ( perpframe[2] × perpframe[3]) = -1. 
              
The hanger matrix based on this right hand perpendicular frame is
           hanger  =    (({{perpframe[1], perpframe[2], perpframe[3]}, {↓, ↓, ↓}})).

So Det[hanger] = column[1]. ( column[2] × column[3]) = perpframe[1]. ( perpframe[2] × perpframe[3]) =  -1.

The aligner matrix based on this right hand frame is
        aligner =(({{perpframe[1], →}, {perpframe[2], →}, {perpframe[3], →}})).
Remembering that hanger and aligner are mutually inverse, you get
           Identity = hanger.aligner.
 So
           1 = Det[Identity] = Det[hanger] Det[aligner].
And because Det[ hanger] = -1, you get
            1  = -1 Det[aligner].
This tells you that Det[aligner] = -1.

T.3.e)   Why Det[(A^t)] = Det[A]

Look at these calculations of Det[A] and Det[(A^t)] for random 3D matrices A:

A =(({{Random[Real, {-5, 5}], Random[
                  Real, {-5, 5}], Random[Real, {-5, 5}]}, {Random[Real, {-5, 5}], Random[
                  Real, {-5, 5}], Random[Real, {-5, 5}]}, {Random[Real, {-5, 5}], Random[
                  Real, {-5, 5}], Random[Real, {-5, 5}]}})) ;
Det[
      A]
Det[Transpose[A]]

This is strong evidence that when you go with any 3D matrix A , then both A and (A^t) have the same determinant. 
Explain why this is guaranteed.

Go with any 3D matrix 
        A = hanger.stretcher.aligner.
This gives
        (A^t) = (aligner^t).stretcher.(hanger^t).
So 
         Det[A] = Det[hanger] Det[stretcher] Det[aligner] 
and
        Det[(A^t)] = Det[(aligner^t)] Det[stretcher] Det[(hanger^t)].
   
But  Det[(aligner^t)] = Det[aligner] and Det[hanger] = Det[(hanger^t)]

The upshot: Det[A] and  Det[(A^t)] are both the product of the same three numbers. 
This makes them equal.

T.5) Hits with 3D matrices with positive determinants preserve orientation. 
 Hits with 3D matrices with negative determinants reverse orientation

T.3.a.i) Saying that A is a 3D matrix with a positive determinant 
is the same as  saying that hits with A preserve orientation in the sense that 
           vector[1].(vector[2] × vector[3]) and (A.vector[1]).((A.vector[2]) × (A.vector[3]) 
have the same sign

Here is a 3D matrix A with a positive determinant

A = (({{-1.2, -0.7, -1.7}, {-1.8, -1.1, -0.3}, {-1.4, 0.6, -1.4}}));
Det[A]

Here are three vectors in 3D:

Clear[vector];
vector[1]  = {0, -1.7, 1.2};
vector[
          2]  =  {1.3, -0.1, -1.8};
vector[3]  =  {1.6, 0.2, -0.2};
\(\(Show[
        Table[
\ \ \ \ \ Arrow[vector[k], Tail -> {0, 0, 0}, 
            VectorColor -> Indigo], {k, 1, 3}], \ 
\ \ \ \ \ Graphics3D[
          Text["vector[1]", 0.4\ vector[1]]], 
\ \ \ \ \ Graphics3D[
          Text["vector[2]", 0.7\ vector[2]]], 
\ \ \ \ \ Graphics3D[
          Text["vector[3]", 0.7\ vector[3]]], 
\ \ \ \ \ Axes3D[1, 
          0.1], 
\ \ \ \ \ PlotRange -> All, 
\ \ \ \ \ Boxed -> 
          False, 
\ \ \ \ \ Axes -> True, ViewPoint -> CMView, 
        AxesLabel -> {"x", "y", "z"}];\)\)

Check the orientation of {vector[1],vector[2],vector[3]} by calculating
          vector[1]. (vector[2]×vector[3]):

vector[1] . Cross[vector[2], vector[3]]

{vector[1],vector[2],vector[3]} are positively oriented.

Now check the orientation of {A.vector[1],A.vector[2],A.vector[3]} by calculating
          (A.vector[1]). ((A.vector[2])×(A.vector[3]))::

(A.vector[1]).Cross[A.vector[2],A.vector[3]]

{A.vector[1],A.vector[2],A.vector[3]} are also positively oriented. 
See them:

Show[Table[
     Arrow[A.vector[k],Tail -> {0, 0, 0},VectorColor -> Indigo],{k, 1, 3}], 
     Graphics3D[
            Text["A.vector[1]", 0.4 A . vector[1]]],
     Graphics3D[
            Text["A,vector[2]", 0.7 A . vector[2]]],
     Graphics3D[
            Text["A.vector[3]", 0.7 A .  vector[3]]],
     Axes3D[1, 0.1],
     PlotRange -> All,
     Boxed -> False,
     Axes -> True,ViewPoint -> CMView,AxesLabel -> {"x", "y", "z"}];

Explain this: 
Saying that A is a 3D matrix with a positive determinant  is the same as saying that hits with A preserve orientation in the sense that 
           vector[1].(vector[2] × vector[3]) and (A.vector[1]).((A.vector[2]) × (A.vector[3]) 
have the same sign (positive or negative) no matter what choices you make of vector[1],vector[2] and vector[3].

Make a new matrix  
             B = (({{vector[1], vector[2], vector[3]}, {↓, ↓, ↓}})).

The product A.B  =  (({{A.vector[1], A.vector[2], A.vector[3]}, {↓, ↓, ↓}})).

On one hand,
      Det[A.B] =  col[1].(col[2] × col[3]) =  A.vector[1].(A.vector[2] × A.vector[3]).
      
On the other hand,
     Det[A.B] = Det[A] Det[B] = Det[A] (vector[1].(vector[2] × vector[3])).
     
So
 A.vector[1].(A.vector[2] × A.vector[3]) = Det[A] (vector[1].(vector[2] × vector[3])) .
 
So saying that hits with A preserve orientation in the sense that 
   vector[1].(vector[2] × vector[3]) and (A.vector[1]).((A.vector[2]) × (A.vector[3])  have the same sign 
is the same as saying that  
          Det[A] > 0.

T.3.a.ii) Saying that A is a 3D matrix with a negative determinant 
is the same as  saying that hits with A reverse orientation in the sense that 
           vector[1].(vector[2] × vector[3]) and (A.vector[1]).((A.vector[2]) × (A.vector[3]) 
have the opposite signs

Explain this: 
Saying that A is a 3D matrix with a negative determinant  is the same as saying that hits with A reverse orientation in the sense that 
           vector[1].(vector[2] × vector[3]) and (A.vector[1]).((A.vector[2]) × (A.vector[3]) 
have opposite signs no matter what choices you make of vector[1],vector[2] and vector[3].

Make a new matrix  
             B = (({{vector[1], vector[2], vector[3]}, {↓, ↓, ↓}})).

The product A.B  =  (({{A.vector[1], A.vector[2], A.vector[3]}, {↓, ↓, ↓}})).

On one hand,
      Det[A.B] =  col[1].(col[2] × col[3]) =  A.vector[1].(A.vector[2] × A.vector[3]).
      
On the other hand,
     Det[A.B] = Det[A] Det[B] = Det[A] (vector[1].(vector[2] × vector[3])).
     
So
 A.vector[1].(A.vector[2] × A.vector[3]) = Det[A] (vector[1].(vector[2] × vector[3])) .
 
So saying that hits with A reverse orientation in the sense that 
   vector[1].(vector[2] × vector[3]) and (A.vector[1]).((A.vector[2]) × (A.vector[3])  have the opposites signs 
is the same as saying that  
          Det[A] < 0.

T.6) Matrices that hit on 2D and hang in 3D. 
        Matrices that hit on 3D and hang in 2D

T.6.a.i) Matrices that hit on 2D and hang in 3D

Here's a new kind of matrix:

A=(({{2., -0.4}, {1.3, 1.8}, {-0.9, 1.2}}));
MatrixForm[A]

When you hit this matrix on a 2D Point {x,y}, you get a 3D point:

Clear[x, y];
A . {x, y}

Watch this matrix hit the 2D unit circle and hang the unit circle in 3D:

Clear[x, y, t, hitplotter, hitpointplotter, pointcolor, actionarrows, 
        matrix2D];
{tlow, thigh} = {0, 2 π};
\(\(ranger = 
        Max[1.2, 
          Max[\(SingularValues[
                A]\)[[2]]]];\)
\)
\(\({x[t_], y[t_]} = {Cos[t], Sin[t]};\)
\)
pointcolor[t_] = 
        RGBColor[0.5 (Cos[t] + 1), 0.5 (Sin[t] + 1), 
          0];
\(\(jump = \(thigh - tlow\)\/16;\)
\)
twoDcircleplot = 
        ParametricPlot[{x[t], y[t]}, {t, tlow, thigh}, 
          PlotStyle -> {{Thickness[0.01]}}, 
          PlotRange -> {{-ranger, ranger}, {-ranger, ranger}}, 
          AxesLabel -> {"x", "y"}, 
          DisplayFunction -> Identity];
\(\(twoDpointplot = 
        Table[Graphics[{pointcolor[t], PointSize[0.035], 
              Point[{x[t], y[t]}]}], {t, tlow, thigh - jump, 
            jump}];\)
\)
before = 
        Show[twoDcircleplot, twoDpointplot, PlotLabel -> "Before", 
          DisplayFunction -> $DisplayFunction];
threeDhitplot = 
        ParametricPlot3D[A . {x[t], y[t]}, {t, tlow, thigh}, 
          PlotRange -> {{-ranger, ranger}, {-ranger, 
                ranger}, {-ranger, ranger}}, 
          AxesLabel -> {"x", "y", "z"}, 
          DisplayFunction -> Identity];
\(\(threeDhitpointplot = 
        Table[Graphics3D[{pointcolor[t], PointSize[0.035], 
              Point[A . {x[t], y[t]}]}], {t, tlow, thigh - jump, 
            jump}];\)
\)
after = 
        Show[threeDhitplot, threeDhitpointplot, ThreeAxes[2], 
          PlotLabel -> "After", ViewPoint -> CMView, 
          Boxed -> False, 
          DisplayFunction -> $DisplayFunction];

When you hit the 2D unit circle with A you get an ellipse centered on {0,0,0}  sitting on a plane in 3D.
How do you frame up this ellipse?

You do exactly the same thing you do for 2D matrices:

Clear[alignerframe, hangerframe, k];
{alignerframe[1], alignerframe[2]}=SingularValues[A][[3]];
{xstretch, ystretch}=SingularValues[A][[2]];
{hangerframe[1], hangerframe[2]}=SingularValues[A][[1]];

frameup=Show[after,
Arrow[xstretch hangerframe[1],Tail -> {0, 0, 0},VectorColor -> Red],
Arrow[-xstretch hangerframe[1],Tail -> {0, 0, 0},VectorColor -> Red],
Arrow[ystretch hangerframe[2],Tail -> {0, 0, 0},VectorColor -> Red],
Arrow[-ystretch hangerframe[2],Tail -> {0, 0, 0},VectorColor -> Red]];

There you go.
See the ellipse from a view point perpendicular to the plane determined by the ellipse:

\(\(planenormal = Cross[hangerframe[1], \ hangerframe[2]];\)
\)
Show[frameup, ViewPoint -> 10 planenormal, 
        Boxed -> False];

Just like 2D.

T.6.a.ii) Measuring the planar area enclosed by the ellipse

Take another look at the ellipse from part i)

Show[frameup, ViewPoint -> 10 planenormal, 
        Boxed -> False];

Measure the planar area enclosed by this ellipse.

Remember that you got this ellipse by hitting the unit circle with A.
The planar area enclosed by this ellipse measures out ( in square units) to

circlearea = π;
ellipsearea = xstretch  ystretch  circlearea

Again just like 2D.

T.6.a.iii) Would the determinant help?

Could you have used the determinant of A to help in measuring the area enclosed by the ellipse?

Try it and see:

Det[A]

Useless.
Reason: The determinant of a matrix that hits on 2D and hangs in 3D is not defined.

T.6.a.iv) Another way of framing the ellipse

Take another look at the frame up of the ellipse in part i):

\(\(Show[after, 

        Arrow[xstretch\ hangerframe[1], Tail -> {0, 0, 0}, 
          VectorColor -> Red], 

        Arrow[\(-xstretch\)\ hangerframe[1], Tail -> {0, 0, 0}, 
          VectorColor -> Red], 

        Arrow[ystretch\ hangerframe[2], Tail -> {0, 0, 0}, 
          VectorColor -> Red], 

        Arrow[\(-ystretch\)\ hangerframe[2], Tail -> {0, 0, 0}, 
          VectorColor -> Red]];\)\)

Now look at this:

\(\(Show[after, 

        Arrow[A . alignerframe[1], Tail -> {0, 0, 0}, VectorColor -> Red], 

        Arrow[\(-A . alignerframe[1]\), Tail -> {0, 0, 0}, 
          VectorColor -> Red], 

        Arrow[A . alignerframe[2], Tail -> {0, 0, 0}, VectorColor -> Red], 

        Arrow[\(-A . alignerframe[2]\), Tail -> {0, 0, 0}, 
          VectorColor -> Red]];\)\)

Exactly the same thing. 
Explain why this was guaranteed to happen.

In the first plot, the plotted frame ups are
          xstretch hangerframe[1]
and 
          ystretch hangerframe[2]
and their negatives.
In the second plot, the plotted frame ups are
         A . alignerframe[1]
and 
         A . alignerframe[2]
and their negatives.
The plots are the same because, just as in 2D, SVD analysis guarantees that
        A . alignerframe[1] = xstretch hangerframe[1]
 and
         A . alignerframe[2] = ystretch hangerframe[2]:

A . alignerframe[1] == xstretch hangerframe[1]
A . alignerframe[2] == ystretch hangerframe[2]

T.6.a.v) The rank of A is 2

Stay with the same matrix A as in the earlier parts and say why the rank of A is 2.

The rank of a matrix is the number of dimensions that matrix uses to hang its hits. 
When the above matrix A is hit on all of on all of 2D, it hangs its hits on the two dimensional plane (within 3D) defined by hangerframe[1] and hangerframe[2]. 
That's why the rank of A is 2.

T.6.b.i) Matrices that hit on 3D and hang in 2D

Here's another new kind of matrix:

A=(({{2, -0.4, 1.2}, {1.3, 1.8, -0.9}}));
MatrixForm[A]

When you hit this matrix on a 3D Point {x,y,z}, you get a 2D point:

Clear[x, y, z];
A . {x, y, z}

Watch this matrix hit points on the 3D unit sphere and hang its hits in 2D:

Clear[x, y, z, s, t, pointcolor];
\(\({x[s_, t_], y[s_, t_], z[s_, t_]} = {Sin[s]\ Cos[t], Sin[s]\ Sin[t], 
          Cos[s]};\)
\)
{slow, shigh} = {0, π};
{tlow, thigh} = {0, 2 π};
ranger = 3.5;
sjump = ((shigh - slow)/15);
\(\(tjump = \(thigh - tlow\)\/15;\)
\)
pointcolor[s_, t_] = 
        RGBColor[0.5 (x[s, t] + 1), 0.5 (y[s, t] + 1), 
          0.5 (z[s, t] + 1)];
\(\(threeDpointplot = 
        Table[Graphics3D[{pointcolor[s, t], PointSize[0.025], 
              Point[{x[s, t], y[s, t], z[s, t]}]}], {s, slow, shigh - sjump, 
            sjump}, {t, tlow, thigh - tjump, tjump}];\)
\)
\(\(pointsbefore = 
        Show[threeDpointplot, ThreeAxes[2], 
          PlotLabel -> "Before in 3D", 
          PlotRange -> {{\(-ranger\), ranger}, {\(-ranger\), 
                ranger}, {\(-ranger\), ranger}}, Axes -> True, 
          Boxed -> False, AxesLabel -> {"x", "y", "z"}, 
          ViewPoint -> CMView, 
          DisplayFunction -> $DisplayFunction];\)
\)
\(\(twoDhitpointplot = 
        Table[Graphics[{pointcolor[s, t], PointSize[0.035], 
              Point[A . {x[s, t], y[s, t], z[s, t]}]}], {s, slow, 
            shigh - sjump, sjump}, {t, tlow, thigh - tjump, 
            tjump}];\)
\)
pointsafter = 
        Show[twoDhitpointplot, 
          PlotRange -> {{-ranger, ranger}, {-ranger, ranger}}, 
          Axes -> True, AxesLabel -> {"x", "y"}, 
          PlotLabel -> "After in 2D", 
          DisplayFunction -> $DisplayFunction];

After the hit, the points on the 3D unit sphere seems to have been deposited on and inside an ellipse in 2D. Try to identify and plot this ellipse.

Do the same thing you do for 2D matrices that are of rank 2

Clear[alignerframe, hangerframe, k];
{alignerframe[1], 
          alignerframe[2]} = SingularValues[
            A][[3]];
\(\(aligner = {alignerframe[1], alignerframe[2]};\)
\)
MatrixForm[aligner]

{xstretch, 
          ystretch} = SingularValues[
            A][[2]];
\(\(stretcher = DiagonalMatrix[{xstretch, ystretch}];\)
\)
MatrixForm[stretcher]

\({hangerframe[1], 
        hangerframe[2]} = \(SingularValues[
          A]\)[[1]]; 
    hanger = Transpose[{hangerframe[1], hangerframe[2]}];
\)
MatrixForm[hanger]

Check:

MatrixForm[hanger . stretcher . aligner]
MatrixForm[A]

This checks

The ellipse you are after comes from hitting the two dimensional planar unit circle (within 3D) defined by alignerframe[1] and alignerframe[2] with A. 
See it happen:

Clear[threeDcircleplotter, t];
\(\(threeDcircleplotter[t_] = 
        Cos[t]\ alignerframe[1] + Sin[t]\ alignerframe[2];\)
\)
{tlow, thigh} = {0, 2 π};
\(\(threeDcircle = 
        ParametricPlot3D[threeDcircleplotter[t], {t, tlow, thigh}, 
          DisplayFunction -> Identity];\)
\)
pointcolor[t_] = 
        RGBColor[0.5 (Cos[t] + 1), 0.5 (Sin[t] + 1), 
          0];
\(\(tjump = π\/8;\)
\)
\(\(threeDcirclepoints = 
        Table[Graphics3D[{pointcolor[t], PointSize[0.025], 
              Point[threeDcircleplotter[t]]}], {t, tlow, thigh - tjump, 
            tjump}];\)
\)
\(\(beforehit = 
        Show[threeDcircle, threeDcirclepoints, ThreeAxes[1.5], 
          PlotRange -> {{\(-ranger\), ranger}, {\(-ranger\), 
                ranger}, {\(-ranger\), ranger}}, Axes -> True, 
          Boxed -> False, AxesLabel -> {"x", "y", "z"}, 
          PlotLabel -> "Before", ViewPoint -> CMView, 
          DisplayFunction -> $DisplayFunction];\)
\)
\(\(hitthreeDcircle = 
        ParametricPlot[A . threeDcircleplotter[t], {t, tlow, thigh}, 
          PlotStyle -> {{Thickness[0.01]}}, 
          DisplayFunction -> Identity];\)
\)
\(\(hitthreeDcirclepoints = 
        Table[Graphics[{pointcolor[t], PointSize[0.03], 
              Point[A . threeDcircleplotter[t]]}], {t, tlow, thigh - tjump, 
            tjump}];\)
\)
\(\(afterhit = 
        Show[hitthreeDcircle, hitthreeDcirclepoints, 
          PlotRange -> {{\(-ranger\), ranger}, {\(-ranger\), ranger}}, 
          PlotLabel -> "Hit circle", 
          AxesLabel -> {"x", "y"}, 
          DisplayFunction -> $DisplayFunction];\)
\)
Show[afterhit, pointsafter, 
        PlotLabel -> "Hit circle and hit sphere points"];

There you go.
When you hit the 3D unit sphere with A, you get everything inside and on this ellipse:

ellipseplot = 
        Show[hitthreeDcircle, 
          PlotRange -> {{-ranger, ranger}, {-ranger, ranger}}, 
          AxesLabel -> {"x", "y"}, 
          DisplayFunction -> $DisplayFunction];

A parametric formula for this ellipse is:

Expand[A . threeDcircleplotter[t]]

T.6.b.ii) Framing up the ellipse

Take another look at the ellipse in part i):

Show[pointsafter, ellipseplot];

Frame up this ellipse.

You've got two choices which end up being the same:

frameup = 
        Show[ellipseplot, 
          Arrow[xstretch hangerframe[1], Tail -> {0, 0}, 
            VectorColor -> Red], 
          Arrow[-xstretch hangerframe[1], Tail -> {0, 0}, 
            VectorColor -> Red], 
          Arrow[ystretch hangerframe[2], Tail -> {0, 0}, 
            VectorColor -> Red], 
          Arrow[-ystretch hangerframe[2], Tail -> {0, 0}, 
            VectorColor -> Red]];

Or:

Show[ellipseplot, 
        Arrow[A . alignerframe[1], Tail -> {0, 0}, 
          VectorColor -> Red], 
        Arrow[-A . alignerframe[1], Tail -> {0, 0}, 
          VectorColor -> Red], 
        Arrow[A . alignerframe[2], Tail -> {0, 0}, 
          VectorColor -> Red], 
        Arrow[-A . alignerframe[2], Tail -> {0, 0}, 
          VectorColor -> Red]];

They are the same because SVD analysis always guarantees:

A . alignerframe[1] == xstretch hangerframe[1]
A . alignerframe[2] == ystretch hangerframe[2]

T.6.b.iii) Measuring the area enclosed by the ellipse

Take another look at the framed ellipse in part ii):

Show[frameup];

Measure the area enclosed by this ellipse.

The area enclosed by the ellipse measures out to:

xstretch  ystretch  π

Another way of seeing this is to take the parametric formula for the ellipse:

Expand[A . threeDcircleplotter[t]]

Put:

B=(({{1.71884, -1.62653}, {1.87581, 1.49042}}));
MatrixForm[B]

Note that the ellipse is also parameterized by:

B . {Cos[t], Sin[t]}

Knowing what you do about 2D matrices, you find quickly that the area enclosed by the ellipse measures out to:

Abs[Det[B]] π

T.6.b.iv) Would the determinant help?

Could you have used the determinant of A to help in measuring the area enclosed by the ellipse?

Try it and see:

Det[A]

Useless.
Reason: The determinant of a matrix that hits on 3D and hangs in 2D is not defined.

T.6.b.v) The rank of A is 2

Stay with the same matrix A as in the earlier parts and say why the rank of A is 2.

The rank of a matrix is the number of dimensions that matrix uses to hang its hits. 
When the above matrix A is hit on all of on all of 3D, it hangs its hits on all of 2D.
That's why the rank of A is 2.