Some Math

The HTML file:

<head>
  <script type="text/javascript" async src="trig.js"> </script>
  <script type="text/javascript" async src="trans.js"> </script>
 <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
  <script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML"> </script>
   <script type="text/x-mathjax-config">

MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});
</script>

 <link rel="stylesheet" href="http://mirkwood.cs.edinboro.edu/~bennett/style/hw.css">
</head>

<body>
<h1> Some Math</h1>
<ul>
    <li> The <a href="http://mirkwood.cs.edinboro.edu/~bennett/f360-19/arrow/">goal</a>
    <li> Some of this is from page 175+ in the book.
    <li> A point in 2 space is represented as a triple
    <ul>
         <li> (x,y) => [x,y,1]
    </ul>
    <li> Remember vector matrix multiplication
    <ul>
         <li> $a =  \begin{bmatrix} x \\ y \\ 1 \end{bmatrix}$
	 <li> $T = \begin{bmatrix} a & b & c \\ d & e & f \\ g & h & i \end{bmatrix}$
	 <li> $ T \times a =  \begin{bmatrix} a & b & c \\ d & e & f \\ g & h & i \end{bmatrix} \times \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} =  \begin{bmatrix} ax + by + c & dx + ey + f & gx + hy + i\end{bmatrix}$
    </ul>
    <li> Remember matrix matrix multiplication
    <ul>
         <li> $ A \times B \ne B \times A$
    </ul>
    <li> Translate shifts the entire plane by the amount given.
    <ul>
        <li> $x_{new} = x_{old} + t_x$
        <li> $y_{new} = y_{old} + t_y$
	<li> $ T = \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{bmatrix}$
    </ul>   
    <li> Scale shrinks or grows every point by the given amount
    <ul>
        <li> $x_{new} = x_{old} \times s_x$
        <li> $y_{new} = y_{old} \times s_y$
	<li> $ S = \begin{bmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \end{bmatrix}$
    </ul>   
    <li> Rotate rotates the entire plane about 0 by a given angle.
    <ul>
         <li> The math is a bit more complex.
	 <lI> We will discuss it later.
         <li> $x_{new} = x_{old} \times \cos\theta - y_{old} \times \sin\theta $
         <li> $x_{new} = x_{old} \times \sin\theta + y_{old} \times \cos\theta $
	<li> $ R = \begin{bmatrix} \cos\theta  & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix}$
    </ul>
    <li> But what are these cos and sin things?
    <ul>
        <li> In a triangle
	<table >
	<tr> <td>
	<canvas id="tri1" width=200 height=200 style="border:2px solid"></canvas>
	</td><td>
	<div id="output">
	<span>
Theta = 45
<p>
cos(Theta) = 0.707
<p>
sin(Theta) = 0.707
        </span>
	</div>
	</td></tr>
	</table>
<p>
Angle:
<input
      type="text"
      maxLength = "4"
      size = "4"
      id="angle"
      onchange ="DoTri()">
	<p>

    </ul>
<script>
    'use strict'

    var canvas = document.getElementById('tri1');
    var ctx = canvas.getContext('2d');

    document.getElementById('angle').value = 45;
    DoTri();
</script>
    <p>
    <li> So how does this work.
    <ul>
        <li> In the HTML5 canvas the context contains a Transformation Matrix $M$
	<ul>
	    <li> This is initialized to the identity matrix
	    <li> $M =  \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}$
	    <li> When a specific transformation (X)  is applied, M is multiplied by that matrix in the form  $M = M \times X$
	    <li> Or you can think of a series of transformations like this
	    <li> $M = I \times X_1  \times X_2 \cdots \times X_n$
	</uL>
	<li> When a point is "drawn", the transformation matrix is applied
	<ul>
	       <li> $v_1' = M \times v_1$
	       <li> This is equivalent to 
	       <li>  $ I \times X_1  \times X_2 \cdots \times X_n \times v_1$
	       <li> Or $X_n$ is applied to $v_1$, 
	       <li> then $X_{n-1}$ and so on.
	       <li> This is applied to all points.
	</ul>
	<li> So the following code
	<ul>
	    <li> <pre class="prettyprint">
ctx.rotate(35)         // rotation matrix R
ctx.translate(50,20)  // translate matrix T
ctx.scale(3,0.9)         // scale matrix S

ctx.strokeRect(10, 20, 5, 5);
</pre>
	    <li> The transformation matrix will be $M = IRTS$
	    <li> The computations will be 
	    <ul>
	         <li> $M \times \begin{bmatrix} 10 \\ 20 \\ 1\end{bmatrix} $ 
	         <li> which will 
	         <ol TYPE=A>
		    <li> Scale that point by 3,0.9
		    <lI> Then Translate that point by 50,20
	            <lI> Then Rotate about the origin by 35 degrees
		  </ol>
		  <li> To produce the final coordinate to be displayed
		  <li> The same will happen for 
		  <ul>
	         <li> $M \times \begin{bmatrix} 15 \\ 25 \\ 1\end{bmatrix} $ 
		 </ul>
	    </ul>
	</ul>
	<li> One more thing:
	<ul>
	   <li> <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations#Transforms">ctx.transform()</a>
	   <ul>
	       <li> Will allow us to apply whatever transformation matrix we want.
	       <lI> Well sort of, the parameters are (a,b,c,d,e,f)
	       <li> And this forms the matrix 
	       <li> $M =  \begin{bmatrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{bmatrix}$
	   </ul>
	   <li> We really would like to reflect the entire picture about the line y=height/2
	   <ul>
	       <li> So this can be accomplished with
	       <li> $M =  \begin{bmatrix} 1 & 0 & 0 \\ 0 & -1 & h \\ 0 & 0 & 1 \end{bmatrix}$
	       <li> $M \times  \begin{bmatrix} x \\ y \\  1  \end{bmatrix} =  (x , h-y, 1)$
	   </ul>
	</ul>
	<p>
	<table>
	<tr><td rowspan = 5>
	<canvas id="trans" width=200 height=200 style="border:2px solid"></canvas>
	</td>
	<td> 
Angle:
<input
      type="text"
      maxLength = "4"
      size = "4"
      id="transAngle">
</td></tr>
	<tr><td>
	Translate X:
<input
      type="text"
      maxLength = "4"
      size = "4"
      id="transX">
Y: 
<input
      type="text"
      maxLength = "4"
      size = "4"
      id="transY">
</td></tr>
	<tr><td> Scale X:
<input
      type="text"
      maxLength = "4"
      size = "4"
      id="scaleX">
Y: 
<input
      type="text"
      maxLength = "4"
      size = "4"
      id="scaleY">

</td></tr>
<tr><td> 
Order:
<select id="transOrder">
   <option value="RST">Rotate Scale Translate</option>
   <option value="RTS" selected >Rotate Translate Scale </option>
   <option value="SRT">Scale Rotate Translate </option>
   <option value="STR">Scale Translate Rotate </option>
   <option value="TRS">Translate Rotate Scale </option>
   <option value="TSR">Translate Scale Rotate </option>
</select>
</td></tr>
	<tr><td>
	<button type="button" id="redraw" onclick="TransRedisplay()">Redraw</button>
	</td></tr>
	</table>
	<script>
var tcanvas = document.getElementById('trans');
var tctx  = tcanvas.getContext('2d');

tctx.transform(1,0,0,-1,0,tcanvas.height);

var tRotate = 35;
var tTranslate = [50,20];
var tScale = [3,0.9];

document.getElementById('transAngle').value = tRotate;
document.getElementById('transX').value = tTranslate[0];
document.getElementById('transY').value = tTranslate[1];
document.getElementById('scaleX').value = tScale[0];
document.getElementById('scaleY').value = tScale[1];
TransRedisplay();
	</script>
    </ul>

    <li> The unit circle
    <ul>
         <li> Given an angle &theta; and a radius r, we can compute the position of a point in cartesian space using
	 <ul>
	     <li> $ x = r \cos\theta $
	     <li> $ y = r \sin\theta $
	<table >
	<tr> <td>
	<canvas id="uc" width=200 height=200 style="border:2px solid"></canvas>
	</td><td>
	<div id="ucoutput">
	<span>
Angle = 45
<p>
Step Size: 0
<p>
Old x = 0, New x  = 0.707
<p>
Old y = 0, New y  = 0.707
        </span>
	</div>
	</td></tr>
	</table>
<p>
Angle:
<input
      type="text"
      maxLength = "4"
      size = "4"
      id="ucangle"
      onchange ="DoUC()">
	 </ul>

<script>
'use strict'
    var uccanvas = document.getElementById('uc');
    var uctx = uccanvas.getContext('2d');
    var radius = Math.floor(.4*Math.min(uccanvas.width, uccanvas.height))
    var xc = uccanvas.width/2;
    var yc = uccanvas.height/2;
    document.getElementById('ucangle').value = 45;
    DoUC();
</script>

    </ul>
</ul>
</body>

trans.js

'use strict'

function DrawFigure(color, step) {

      // draw the happy man
      tctx.strokeStyle = color;
      tctx.fillStyle = "yellow";
      tctx.beginPath();
      tctx.arc(40,40,10,0,Math.PI * 2);
      tctx.stroke(); 
      tctx.fill(); 
      tctx.moveTo(40,30);
      tctx.lineTo(40,10);
      tctx.lineTo(30,0);
      tctx.moveTo(40,10);
      tctx.lineTo(50,0);
      tctx.moveTo(30,25);
      tctx.lineTo(50,25);
      tctx.stroke(); 
      tctx.closePath();

      tctx.beginPath();
      tctx.strokeText(step, 45, 20);
}

function ApplyTransform(letter) {
   switch(letter) {
      case 'R':
          tctx.rotate(tRotate * Math.PI/180);
	  break;
      case 'S':
          tctx.scale(tScale[0],tScale[1]);
	  break;
      case 'T':
          tctx.translate(tTranslate[0],tTranslate[1]);
	  break;
   }
}

function TransRedisplay() {
     let colors = ['red','green', 'blue'];

     tRotate = document.getElementById('transAngle').value;
     tTranslate[0] = document.getElementById('transX').value;
     tTranslate[1] = document.getElementById('transY').value;
     tScale[0] = document.getElementById('scaleX').value;
     tScale[1] = document.getElementById('scaleY').value;

     let order = document.getElementById("transOrder").value;

     tctx.clearRect(0,0,tcanvas.width, tcanvas.height);

     tctx.save();

     // draw the untransformed figure
     DrawFigure("black","A");

     for (let i=0;i<order.length;i++) {
          ApplyTransform(order[i]);      
          DrawFigure(colors[i],order[i]);
     }

     tctx.restore();
}

trig.js

   'use strict'

    function Circle(ox, oy, r) {

         let holdColor = ctx.strokeStyle;
         ctx.strokeStyle= "blue";

         ctx.beginPath();
         ctx.moveTo(ox,oy);
         ctx.arc(ox, oy, r, 0, -Math.PI/2,true);
         ctx.closePath();
         ctx.stroke();

         ctx.strokeStyle = holdColor;
    }
        function Triangle(ox, oy, x,y) {
         ctx.beginPath();
         ctx.moveTo(ox,oy);
         ctx.lineTo(x,oy);
         ctx.lineTo(x, y)
         ctx.lineTo(ox,oy);
         ctx.stroke();
         ctx.closePath();
    }

    function DoOutput(theta) {
         let text = "Theta = " + -theta;
         text = text + "<p>cos(Theta) = " + Math.cos(-theta * Math.PI/180).toFixed(3);
         text = text + "<p>sin(Theta) = " + Math.sin(-theta * Math.PI/180).toFixed(3);
         document.getElementById('output').innerHTML = text;
    }

    function LabelTheta(ox, oy, x, y, radius, theta) {

         let holdColor = ctx.strokeStyle;
         ctx.strokeStyle= "red";

         let newRadius = Math.min(radius/2, (x-ox)/2)

         let divisor = 3/2;
         if (theta > -20) {
             divisor = 3/4;
         } else if (theta < -30) {
             divisor = 3;
         }

         let tx = ox + newRadius/divisor * Math.cos(theta/2*Math.PI/180);
         let ty = oy + newRadius/divisor * Math.sin(theta/2*Math.PI/180);

         ctx.beginPath();
         ctx.moveTo(tx,ty);
         let text = String(-theta);
         ctx.fillText(text, tx, ty);

         ctx.beginPath();
         ctx.arc(ox, oy,  newRadius, 0, theta * Math.PI/180, true);
         ctx.stroke();
         ctx.moveTo(ox/2, oy/2)
         ctx.closePath();
         ctx.strokeStyle = holdColor;
    }

    function GetTheta() {
         let theta =  parseInt(document.getElementById('angle').value);
         if (! typeof theta === 'number') {
            theta = 45;
         }

         if (theta < 0 || theta > 90) {
             theta = 45;
         }

         document.getElementById('angle').value = theta;
         return -theta;
    }

    function DoTri() {

         ctx.clearRect(0,0,canvas.width,canvas.height);

         let theta = GetTheta();

         let dim = Math.min(canvas.width, canvas.height);
         let r = (dim - 20 )

         let ox = 10;
         let oy = canvas.height-10;

         let x  = ox + r * Math.cos(theta * Math.PI/180);
         let y  = oy +  r * Math.sin(theta * Math.PI/180);

         DoOutput(theta);
         LabelTheta(ox,oy, x, y, r, theta);
         Circle(ox,oy,r);
         Triangle(ox,oy,x,y);
    }

    function DoUCOutput(theta) {
         let text = "Angle = " + theta;
	 text = text + "<p>Step Size = " + radius ;
         text = text + "<p>Old x  = "  + xc + ", New x = "
	             + Math.floor(xc + radius * Math.cos(-theta * Math.PI/180));
         text = text + "<p>Old y =  "  + yc + ", New y = "
	             + Math.floor(yc - radius * Math.sin(-theta * Math.PI/180))
         document.getElementById('ucoutput').innerHTML = text;
    }

    function DoUC() {
        let theta =  parseInt(document.getElementById('ucangle').value);

        let x = xc + radius * Math.cos(theta*Math.PI/180);
        let y = yc - radius * Math.sin(theta*Math.PI/180);

        uctx.clearRect(0,0,uccanvas.width, uccanvas.height);

        // draw the unit circle
        uctx.beginPath()
        uctx.strokeStyle = "blue";
        uctx.arc(xc, yc, radius, 0, 2*Math.PI);
        uctx.stroke();
        uctx.closePath();

        // draw a circle at the center
        uctx.beginPath();
        uctx.fillStyle = "green";
        uctx.arc(xc, yc, 5, 0, 2*Math.PI);
        uctx.fill();
        uctx.closePath();

        // draw a circle at the next step.
        uctx.beginPath();
        uctx.fillStyle = "green";
        uctx.arc(x, y, 5, 0, 2*Math.PI);
        uctx.fill();
        uctx.closePath();

        DoUCOutput(theta);
    }