VC.02 Perpendicularity
TUTORIALS

\(Off[General::spell]; 
\(Off[General::spell1]; \)\)Off[ParametricPlot3D::ppcom]; Off[ParametricPlot::ppcom]; Off[Plot::plnr]; SetOptions[Limit, Analytic -> True];

CMView = {2.7, 1.6, 1.2};

Vector Drawer

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] == 2Perpend[a_?VectorQ] := 
      Normalize[
          If[a[[1]] == 0, {1, 0, 0}, {0, 
              a[[3]], 
              -a[[2]]}]] /; 
        Length[a] == 3Base3D = 
      Table[{Cos[((2 k π)/8.) ], Sin[((2 k π)/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] == 2Vector[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[#1, tip]]&)/@
                    Partition[
                      (tip - hr diff + #1&)/@
                        ((ap hr Norm[diff] Base3D) . {temp, 
                              Normalize[temp\[Cross]diff]}), 2, 1]]}}]] /; 
        Length[from] == Length[to] == 3Arrow[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[]; \)\)

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

T.1) True scale plots via the options AspectRatio->Automatic and BoxRatios->Automatic

T.1.a)

Look at this:

X = {1, 2}; Y = {-8, 4}; X . Y

This tells you that the two vectors are perpendicular.
Now look at this:

Show[Arrow[X], Arrow[Y], Axes -> True, 
      AxesLabel -> {"x", "y"}, AspectRatio -> 1];

Although you knew in advance that these vectors are perpendicular, they didn't plot out perpendicularly.
What gives?

The two vectors weren't plotted in true scale. To guarantee a true scale plot in 2D graphics, use the plotting option AspectRatio -> Automatic. This way you get the same scale on both axes. 
Try it out:

Show[Arrow[X], Arrow[Y], Axes -> True, 
      AxesLabel -> {"x", "y"}, AspectRatio -> Automatic];

Much better.
In 2D plots, if you don't use AspectRatio -> Automatic, then actual perpendicularity can be obscured.
In 3D plots, if you don't use BoxRatios -> Automatic, then actual perpendicularity can be obscured.
Moral:
When you are studying anything related to perpendicularity, you need to plot in true scale. You are tempting fate if you don't use the options AspectRatio -> Automatic or BoxRatios -> Automatic as the situation demands.

T.2)  Flatness and plotting

T.2.a)

Here are three ways of plotting the same piece of the plane 
       (x/3) -  (y/2) +  z = 1:

\(Clear[x, y]; 

    defaultplot = 
      ParametricPlot3D[{x, y, 1 - x\/3 + y\/2}, {x, \(-3\), 3}, {y, \(-2\), 
          2}, ViewPoint -> CMView, PlotRange -> All, 
        Boxed -> False, PlotLabel -> "Mathematica Default", 
        AxesLabel -> {"x", "y", "z"}]; \)

That took a while, and the plot is covered with little bricks.
Try this one:

betterplot = 
      ParametricPlot3D[{x, y, 1 - (x/3) + (y/2)}, {x, -3, 3}, {y, -2, 
          2}, PlotPoints -> {5, 5}, ViewPoint -> CMView, 
        PlotRange -> All, Boxed -> False, 
        PlotLabel -> "Better plot", AxesLabel -> {"x", "y", "z"}];

That ran a lot faster than the default plot.
The reason: Fewer bricks. The reason: PlotPoints -> {5, 5}.
Now try:

bestplot = 
      ParametricPlot3D[{x, y, 1 - (x/3) + (y/2)}, {x, -3, 3}, {y, -2, 
          2}, PlotPoints -> {2, 2}, ViewPoint -> CMView, 
        PlotRange -> All, Boxed -> False, 
        PlotLabel -> "Best plot", AxesLabel -> {"x", "y", "z"}];

That ran lightning fast.  And it looks really fine.
The reason: NO BRICKS.  The reason:  PlotPoints -> {2, 2}.
Explain what's going on.

The default plot is a good plot to try when the surfaces bend.
But when the surfaces are flat, you can help Mathematica by telling it to evaluate the functions only at the corners, and letting it string up one clean, flat surface.
Here is a situation in which the default plot is very good:

\(Clear[x, y]; 

    defaultplot = 
      ParametricPlot3D[{x, y, 2 - \((x\/3)\)\^2 + \((y\/2)\)\^2}, {x, \(-3\), 
          3}, {y, \(-2\), 2}, ViewPoint -> CMView, 
        PlotRange -> All, Boxed -> False, 
        PlotLabel -> "Mathematica Default", 
        AxesLabel -> {"x", "y", "z"}]; \)

If you tinker with this, the way you tweaked the plot of the plane, then disaster strikes:

\(Clear[x, y]; 

    tweakedplot = 
      ParametricPlot3D[{x, y, 2 - \((x\/3)\)\^2 + \((y\/2)\)\^2}, {x, \(-3\), 
          3}, {y, \(-2\), 2}, PlotPoints -> {2, 2}, 
        ViewPoint -> CMView, PlotRange -> All, Boxed -> False, 
        PlotLabel -> "tweaked plot", 
        AxesLabel -> {"x", "y", "z"}]; \)

This plot is not even close to reality.

Show[defaultplot, tweakedplot, ViewPoint -> CMView, 
      PlotRange -> All, PlotLabel -> None, Boxed -> False, 
      AxesLabel -> {"x", "y", "z"}];

This tweaked plot is on the money only at the corners.
The reason: The actual surface you are plotting is not flat.

T.2.b)

What other situations benefit from this type of tweaking?

Anytime flatness is around.
Look at this:

vector1 = {1, 2, 3}; vector2 = {-1, -2, 5}; \(Clear[r, t]; 

    defaultplot = 
      ParametricPlot3D[
        r\ Cos[t]\ vector1 + r\ Sin[t]\ vector2, {r, 0, 1}, {t, 0, π}, 
        ViewPoint -> CMView, 
        AxesLabel -> {"x", "y", "z"}, 
        PlotLabel -> "Mathematica Default"]; \)

There is flatness around in the r variable.  Try this and look at the PlotPoints setting:

tweakedplot = 
      ParametricPlot3D[
        r Cos[t] vector1 + r Sin[t] vector2, {r, 0, 1}, {t, 0, π}, 
        PlotPoints -> {2, Automatic}, ViewPoint -> CMView, 
        AxesLabel -> {"x", "y", "z"}, PlotLabel -> "Tweaked Plot"];

Nice.
But tinkering with t does not pay off:

ParametricPlot3D[
      r Cos[t] vector1 + r Sin[t] vector2, {r, 0, 1}, {t, 0, π}, 
      PlotPoints -> {2, 3}, ViewPoint -> CMView, 
      AxesLabel -> {"x", "y", "z"}, PlotLabel -> "Bogus"];

The reason:  
With respect to r, the plot is flat. But the plot is not flat with respect to t.

T.2.c)

Plot, in true scale, the cone whose base sits on the ellipse
       (((((x  -  1)/3)))^2)+(((((y  -  2)/5)))^2)=1
in the xy-plane and whose top is at {1, -2, 7}.

top = {1, -2, 10}; \(Clear[baseplotter, coneplotter, s, t]; 

    baseplotter[t_] = {1, 2, 0} + {3\ Cos[t], 5\ Sin[t], 0}; 

    coneplotter[s_, t_] = baseplotter[t] + s\ \((top - baseplotter[t])\); 


    ParametricPlot3D[coneplotter[s, t], {s, 0, 1}, {t, 0, 2\ π}, 
      PlotPoints -> {2, Automatic}, ViewPoint -> CMView, 
      BoxRatios -> Automatic, 
      AxesLabel -> {"x", "y", "z"}]; \)

T.3)  Unit vectors and perpendicularity:
Plotting curves on planes and a new, easy way of calculating the cross product.

A unit vector is just a vector whose length is 1.  Any vector X can be converted to a unit vector unless all its slots are zero.
To wit:

X = {-4, 2}; unitX = (X/(Sqrt[X . X]))

Check:

unitX . unitX

and

X = {-4, 2, 8}; unitX = (X/(Sqrt[X . X]))

Check:

unitX . unitX

Unit vectors are the handiest thing since zip-lock bags. Why? 
Wait and see.

T.3.a)

Here is a true scale plot of y = Sin[x] on the xy-plane:

\(Clear[x]; 

    ParametricPlot[{x, Sin[x]}, {x, \(-π\), 3\ π}, 
      AspectRatio -> Automatic, AxesLabel -> {"x", "y"}]; 
    \)

Plot a duplicate copy of this curve in true scale on the plane through {1, 1, -2} determined by the direction vectors {0.3, -1, -0.2} and {0, 0.4, -1}.

point = {1, 1, 2}; vector1 = {0.3, 1, -0.2}; vector2 = {0, 0.4, -1}; \(Clear[i, j, k]; 
normal = Cross[vector1, vector2]\)

When you think about it for a minute, you see that the same plane is also determined by the given point and the vectors 
       unitvector1 and unitnewvector2 
calculated as follows:

unitvector1 = (vector1/(Sqrt[vector1 . vector1]))

\(Clear[i, j, k]; 
newvector2 = Cross[vector1, normal]; 

    unitnewvector2 = newvector2\/\@\(newvector2 . newvector2\)\)

The great thing about unitvector1 and unitnewvector2 is that they are unit vectors and they are perpendicular:

Chop[unitvector1 . unitnewvector2]

As perpendicular unit vectors, they define axes for plotting on the plane:

\(Clear[x, y, z, s, t]; 
    
{x[s_, t_], y[s_, t_], z[s_, t_]} = 
      point + s\ unitvector1 + t\ unitnewvector2; 

    \({slow, shigh} = {\(-π\), 3\ π}; \)\)\({tlow, thigh} = {\(-3\), 3}; 


    plane = ParametricPlot3D[
        Evaluate[{x[s, t], y[s, t], z[s, t]}], {s, slow, shigh}, {t, tlow, 
          thigh}, PlotPoints -> {2, 2}, 
        DisplayFunction -> Identity]; 


    planeplot = 
      Show[plane, Arrow[2\ unitvector1, Tail -> point], 
        Arrow[2\ unitnewvector2, Tail -> point], Axes -> Automatic, 
        PlotRange -> All, ViewPoint -> CMView, 
        BoxRatios -> Automatic, 
        DisplayFunction -> $DisplayFunction]; \)

Here is a true scale duplicate copy of the curve 
       y = Sin[x] for -π ≤ x ≤ 3  π 
plotted right on this plane.

sineplot = 
      ParametricPlot3D[
        point + s unitvector1 + Sin[s] unitnewvector2, {s, -π, 
          3 π}, DisplayFunction -> Identity]; Show[planeplot, sineplot, DisplayFunction -> $DisplayFunction];

Keen.

T.3.b) A new way of calculating the cross product.

Here is a true scale plot of the circle (x^2) +  (y^2) = 4 on the xy-plane:

\(Clear[t]; 

    ParametricPlot[2\ {Cos[t], Sin[t]}, {t, 0, 2\ π}, 
      AxesLabel -> {"x", "y"}]; \)

Plot a duplicate copy of this circle on the plane through {1, 2, -1} determined by the direction vectors  {1, 0, 2} and {-2, 1, 0}.
Center the circle at {1, 2, -1}.

point = {1, 2, -1}; vector1 = {1, 0, 2}; vector2 = {-2, 1, 0}; normal = Cross[vector1, vector2]

When you think about it for a minute, you see that the same plane is also determined by the given point and the vectors 
       unitvector1 and unitnewvector2 
calculated as follows:

unitvector1 = (vector1/(Sqrt[vector1 . vector1]))

\(newvector2 = Cross[vector1, normal]; 

    unitnewvector2 = newvector2\/\@\(newvector2 . newvector2\)\)

The great thing about unitvector1 and unitnewvector2 is that they are unit vectors and they are perpendicular:

unitvector1 . unitnewvector2

As perpendicular unit vectors, they define axes for plotting on the plane, and allow you to plot the circle where you want it.

Clear[circleplotter, t]; circleplotter[t_] = 
      point + 2 Cos[t] unitvector1 + 2 Sin[t] unitnewvector2; {tlow, thigh} = {0, 2 π}; circle = 
      ParametricPlot3D[Evaluate[circleplotter[t]], {t, tlow, thigh}, 
        DisplayFunction -> Identity]; Clear[planeplotter, r, s]; planeplotter[r_, s_] = point + r unitvector1 + s unitnewvector2; 
    {rlow, rhigh} = {-3, 3}; \({slow, shigh} = {\(-3\), 3}; 


    plane = ParametricPlot3D[
        Evaluate[planeplotter[r, s]], {r, rlow, rhigh}, {s, slow, shigh}, 
        PlotPoints -> {2, 2}, DisplayFunction -> Identity]; 

    Show[plane, circle, 
      Arrow[unitvector1, Tail -> point, VectorColor -> Red], 
      Arrow[unitnewvector2, Tail -> point, VectorColor -> Red], 
      Axes -> Automatic, PlotRange -> All, 
      ViewPoint -> CMView, BoxRatios -> Automatic, 
      DisplayFunction -> $DisplayFunction]; \)

You can make the vectors touch the circle:

Show[plane, circle, 
      Arrow[unitvector1, Tail -> point, VectorColor -> Red, 
        ScaleFactor -> 2], 
      Arrow[ unitnewvector2, Tail -> point, VectorColor -> Red, 
        ScaleFactor -> 2], Axes -> Automatic, 
      PlotRange -> All, ViewPoint -> CMView, 
      BoxRatios -> Automatic, DisplayFunction -> $DisplayFunction];

The reason this worked:
The vectors 
       unitvector1 and unitnewvector2
are perpendicular unit vectors.
If you had used the original vectors 
       vector1 and vector2, 
you would not have gotten a circle.

T.4)  Unit vectors and perpendicularity:
Main unit normals, binormals, tubes, horns, and corrugations

Unit vectors are just vectors whose lengths are 1.
Unit vectors are useful because they convey the idea of direction only.
You can take any vector and make it into a unit vector by dividing it by its length:

X = {2, 1}; unitX = (X/(Sqrt[X . X]))

Show[Arrow[X], Arrow[unitX, VectorColor -> Red], 
      Axes -> Automatic];

The unit vector points in the same direction as X, but its length is 1:

(Sqrt[unitX . unitX])

T.4.a.i)

Here is a curve in three dimensions with some of its unit tangents plotted in true scale:

\(Clear[P, x, y, z, t]; 
x[t_] = 3\ Cos[t]; 
\(y[t_] = 3\ Sin[t]; 
    \)\)z[t_] = 4 Cos[t]; \(P[t_] = {x[t], y[t], z[t]}; 


    curve = ParametricPlot3D[Evaluate[P[t]], {t, 0, 2\ π}, 
        PlotPoints -> 30, DisplayFunction -> Identity]; 


    Clear[unittan]; 

    unittan[t_] = D[P[t], \ t]\/\@\(D[P[t], \ t] . D[P[t], \ t]\); 


    unittanvectors = 
      Table[Arrow[unittan[t], Tail -> P[t], VectorColor -> Blue], {
          t, 0, 2\ π, π\/4}]; 

    \(curveandtans = 
      Show[curve, unittanvectors, ViewPoint -> CMView, 
        PlotRange -> All, BoxRatios -> Automatic, 
        AxesLabel -> {"x", "y", "z"}, 
        DisplayFunction -> $DisplayFunction]; \)\)

Add to the plot the vectors D[unittan[t], t] with tails at the same places as the tails of the unit tangents.
Describe what you see.

\(Clear[newvector]; 
newvector[t_] = D[unittan[t], \ t]; 

    newvectors = 
      Table[Arrow[newvector[t], Tail -> P[t], VectorColor -> Red], {
          t, 0, 2\ π, π\/4}]; 
\(Show[curveandtans, newvectors]; 
    \)\)

They look perpendicular to the curve!
Check this out:

Table[Chop[N[unittan[t] . newvector[t]]], {t, 0, 2 π, (π/4)}]

They are perpendicular to the curve.

T.4.a.ii) The main normal for a 3D curve

Is this outcome peculiar to this curve or does it happen for all other curves too?

Try it for a general (cleared) curve in three dimensions:

\(Clear[x, y, z, t, P, unittan, newvector]; 
P[t_] = {x[t], y[t], z[t]}; 
    
\(unittan[t_] = D[P[t], \ t]\/\@\(D[P[t], \ t] . D[P[t], \ t]\); \)\)\(newvector[t_] = D[unittan[t], \ t]; 

    Simplify[unittan[t] . newvector[t]]\)

No matter what curve you have, the vector D[unittan[t], t] is perpendicular to the curve at P[t]
Most folks make this into a unit vector and call the result the main unit normal vector for the curve.

T.4.a.iii) The main normal for a 2D curve

Does this work in two dimensions as well?

Try it and see:

\(Clear[P, t]; 
P[t_] = {t\/2 - 4\ Sin[t], 3 + 3\ Cos[t]}; 

    \(curve = 
      ParametricPlot[Evaluate[P[t]], {t, 0, 10}, 
        PlotStyle -> Thickness[0.01], DisplayFunction -> Identity]; 
    \)\)Clear[unittan];
unittan[t_]=((P'[t])/(Sqrt[P'[t].P'[t]]));
unittanvectors = 
        Table[Arrow[unittan[t], Tail -> P[t]], {t, 1, 9}];
Clear[mainnormal];
mainnormal[t_] = Simplify[D[unittan[t],  t]];
mainnormalvectors = 
        Table[Arrow[mainnormal[t], Tail -> P[t], 
            VectorColor -> Red], {t, 1, 9}];
Show[curve, unittanvectors, mainnormalvectors, 
        AspectRatio -> Automatic, 
        DisplayFunction -> $DisplayFunction];

Works like a charm in two dimensions.
When you're hot, you're hot.

T.4.b) The binormal for making tubes and horns

Given a curve P[t] = {x[t], y[t], z[t]}: 
-> The unit tangent
       unittan[t]=D[P[t], t]/(Sqrt[D[P[t], t] . D[P[t], t]])
is tangent to the curve at P[t].
-> The main normal
       mainnorm[t] = D[unittan[t], t]
is perpendicular to the curve at P[t].
-> The main unit normal
       mainunitnorm[t]=D[unittan[t], t]/(Sqrt[D[unittan[t], t] . D[unittan[t], t]])
is also perpendicular to the curve at P[t].
You can construct another normal vector by putting
       binormal[t] = unittan[t]×mainunitnorm[t].
This second normal vector always turns out to be a unit vector, for reasons you will learn when you give it a try.
Take a look:

\(Clear[P, x, y, z, t, unittan, mainunitnormal, binormal]; 
x[t_] = t\^2; 
    
\(y[t_] = 1 - 2\ t; \)\)z[t_] = t; P[t_] = {x[t], y[t], z[t]}; curve = 
      ParametricPlot3D[Evaluate[P[t]], {t, 0, 2}, 
        DisplayFunction -> Identity]; unittan[t_]=((P'[t])/(Sqrt[P'[t].P'[t]]));unittanvectors = 
        Table[Arrow[unittan[t], Tail -> P[t]], {t, 0, 2, 0.5}];
mainunitnormal[t_]=N[((unittan'[t])/(Sqrt[Expand[unittan'[t].unittan'[t]]]))];\(mainnormalvectors = 
      Table[Arrow[mainunitnormal[t], Tail -> P[t], 
          VectorColor -> Red], {t, 0, 2, 0.5}]; 

    binormal[t_] = N[Cross[unittan[t], mainunitnormal[t]]]; 

    binormalvectors = 
      Table[Arrow[binormal[t], Tail -> P[t], VectorColor -> Red], {
          t, 0, 2, 0.5}]; 


    everything = 
      Show[curve, unittanvectors, mainnormalvectors, binormalvectors, 
        ViewPoint -> CMView, PlotRange -> All, 
        BoxRatios -> Automatic, 
        AxesLabel -> {"x", "y", "z"}, 
        DisplayFunction -> $DisplayFunction]; \)

Neato.
What's this stuff good for?

You can put in a couple of circles that
-> are centered on the curve, and
-> lie in planes that cut the curve perpendicularly:

radius = 1; circle1 = 
      ParametricPlot3D[
        N[P[1.0] + radius Cos[s] mainunitnormal[1.0] + 
            radius Sin[s] binormal[1.0]], {s, 0, 2 π}, 
        DisplayFunction -> Identity]; circle2 = 
      ParametricPlot3D[
        N[P[1.5] + radius Cos[s] mainunitnormal[1.5] + 
            radius Sin[s] binormal[1.5]], {s, 0, 2 π}, 
        DisplayFunction -> Identity]; Show[everything, circle1, circle2];

But why settle for just a couple of circles when you can go for the whole tube composed of all such circles?

ParametricPlot3D[
      Evaluate[P[t] + radius Cos[s] mainunitnormal[t] + 
          radius Sin[s] binormal[t]], {t, 0, 2}, {s, 0, 2 π}, 
      ViewPoint -> CMView, BoxRatios -> Automatic, 
      AxesLabel -> {"x", "y", "z"}];

Or a horn:

\(Clear[radius]; 
radius[t_] = \((t\/2)\)\^2 + 0.1; 

    \(ParametricPlot3D[
      Evaluate[P[t] + radius[t]\ Cos[s]\ mainunitnormal[t] + 
          radius[t]\ Sin[s]\ binormal[t]], {t, 0, 2}, {s, 0, 2\ π}, 
      ViewPoint -> CMView, BoxRatios -> Automatic, 
      AxesLabel -> {"x", "y", "z"}]; \)\)

Or a corrugation:

ParametricPlot3D[
      P[t] + s mainunitnormal[t] + Cos[3 s] binormal[t], {t, 0, 2}, {s, 
        -π, π}, PlotPoints -> {Automatic, 25}, 
      ViewPoint -> CMView, BoxRatios -> Automatic, 
      AxesLabel -> {"x", "y", "z"}];

Every slice of this surface cut by any plane perpendicular to the original curve is the same Cosine wave.