Sunday 6 August 2017

Drawing intercepting lines with HTML 5 and Js - Part One

I am working with a sample demo that will draw two lines and calculate the intersection. The demo will use Js and HTML 5 Canvas. I have made a Plunk available here:

Canvas line drawing Plunk

The image belows shows a rendering of two lines on the form : y = f(x) = ax + b, y1 = x + 1, y2 = -x + 3

The HTML and Js code is below. I will in the later articles focus on calculating the interception with an iterative approximation method for the intercept. In a future article I will clean up the code and I will look on the code bits and look at Canvas functionality. Here is the code:




















<!DOCTYPE html>
<html>

  <head>
    <meta charset="UTF-8" />
    <script data-require="jquery@*" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <link data-require="bootstrap-css@*" data-semver="4.0.0-alpha.4" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/css/bootstrap.min.css" />
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <h1>Intersection of two lines with Canvas and Js </h1>
    
    <fieldset>
      <label>y = mx + b</label> <br /><br />
      
      <table>
        <tr>
        
          <td> <label for="m1">m1:</label> <input id="m1" type="text" style="width:50px" /></td>
          <td> <label for="b1">b1:</label> <input id="b1" type="text" style="width:50px" /></td>

          <td> <label for="slope2">m2:</label> <input id="m2" type="text" style="width:50px" /></td>
          <td> <label for="b2">b2:</label> <input id="b2" type="text" style="width:50px" /></td>

        </tr>
        <tr>
          <td><input id="btnGraph" type="button" value="Draw line" /></td>
        </tr>
      </table>
      
      <br />
      <h3>Graph</h3>
      
      <canvas id="Graph" style="background:aliceblue;border:1px solid #AFAFAF" width="600" height="600"></canvas>
     
    </fieldset>
    
      <script>
      function Graph(config) {
        // user defined properties
        this.canvas = document.getElementById(config.canvasId);
        this.minX = config.minX;
        this.minY = config.minY;
        this.maxX = config.maxX;
        this.maxY = config.maxY;
        this.unitsPerTick = config.unitsPerTick;

        // constants
        this.axisColor = '#aaa';
        this.font = '8pt Calibri';
        this.tickSize = 20;

        // relationships
        this.context = this.canvas.getContext('2d');
        this.rangeX = this.maxX - this.minX;
        this.rangeY = this.maxY - this.minY;
        this.unitX = this.canvas.width / this.rangeX;
        this.unitY = this.canvas.height / this.rangeY;
        this.centerY = Math.round(Math.abs(this.minY / this.rangeY) * this.canvas.height);
        this.centerX = Math.round(Math.abs(this.minX / this.rangeX) * this.canvas.width);
        this.iteration = (this.maxX - this.minX) / 1000;
        this.scaleX = this.canvas.width / this.rangeX;
        this.scaleY = this.canvas.height / this.rangeY;

        // draw x and y axis
        this.drawXAxis();
        this.drawYAxis();
      }

      Graph.prototype.drawXAxis = function() {
        var context = this.context;
        context.save();
        context.beginPath();
        context.moveTo(0, this.centerY);
        context.lineTo(this.canvas.width, this.centerY);
        context.strokeStyle = this.axisColor;
        context.lineWidth = 2;
        context.stroke();

        // draw tick marks
        var xPosIncrement = this.unitsPerTick * this.unitX;
        var xPos, unit;
        context.font = this.font;
        context.textAlign = 'center';
        context.textBaseline = 'top';

        // draw left tick marks
        xPos = this.centerX - xPosIncrement;
        unit = -1 * this.unitsPerTick;
        while(xPos > 0) {
          context.moveTo(xPos, this.centerY - this.tickSize / 2);
          context.lineTo(xPos, this.centerY + this.tickSize / 2);
          context.stroke();
          context.fillText(unit, xPos, this.centerY + this.tickSize / 2 + 3);
          unit -= this.unitsPerTick;
          xPos = Math.round(xPos - xPosIncrement);
        }

        // draw right tick marks
        xPos = this.centerX + xPosIncrement;
        unit = this.unitsPerTick;
        while(xPos < this.canvas.width) {
          context.moveTo(xPos, this.centerY - this.tickSize / 2);
          context.lineTo(xPos, this.centerY + this.tickSize / 2);
          context.stroke();
          context.fillText(unit, xPos, this.centerY + this.tickSize / 2 + 3);
          unit += this.unitsPerTick;
          xPos = Math.round(xPos + xPosIncrement);
        }
        context.restore();
      };

      Graph.prototype.drawYAxis = function() {
        var context = this.context;
        context.save();
        context.beginPath();
        context.moveTo(this.centerX, 0);
        context.lineTo(this.centerX, this.canvas.height);
        context.strokeStyle = this.axisColor;
        context.lineWidth = 2;
        context.stroke();

        // draw tick marks
        var yPosIncrement = this.unitsPerTick * this.unitY;
        var yPos, unit;
        context.font = this.font;
        context.textAlign = 'right';
        context.textBaseline = 'middle';

        // draw top tick marks
        yPos = this.centerY - yPosIncrement;
        unit = this.unitsPerTick;
        while(yPos > 0) {
          context.moveTo(this.centerX - this.tickSize / 2, yPos);
          context.lineTo(this.centerX + this.tickSize / 2, yPos);
          context.stroke();
          context.fillText(unit, this.centerX - this.tickSize / 2 - 3, yPos);
          unit += this.unitsPerTick;
          yPos = Math.round(yPos - yPosIncrement);
        }

        // draw bottom tick marks
        yPos = this.centerY + yPosIncrement;
        unit = -1 * this.unitsPerTick;
        while(yPos < this.canvas.height) {
          context.moveTo(this.centerX - this.tickSize / 2, yPos);
          context.lineTo(this.centerX + this.tickSize / 2, yPos);
          context.stroke();
          context.fillText(unit, this.centerX - this.tickSize / 2 - 3, yPos);
          unit -= this.unitsPerTick;
          yPos = Math.round(yPos + yPosIncrement);
        }
        context.restore();
      };

      Graph.prototype.drawEquation = function(equation, color, thickness) {


        var context = this.context;
        context.save();
        context.save();
        this.transformContext();

        context.beginPath();
        context.moveTo(this.minX, equation(this.minX));

        for(var x = this.minX + this.iteration; x <= this.maxX; x += this.iteration) {
          context.lineTo(x, equation(x));
        }

        context.restore();
        context.lineJoin = 'round';
        context.lineWidth = thickness;
        context.strokeStyle = color;
        context.stroke();
        context.restore();
      };

       Graph.prototype.drawLine = function(slope, yintercept, color, thickness) {

        console.log("Inside drawline");

        console.log("this.maxX: " + this.maxX + " this.maxY: " + this.maxY);

        var context = this.context;

        // draw x and y axis
        this.drawXAxis();
        this.drawYAxis();

        //context.clearRect(0, 0, this.canvas.width, this.canvas.height);

        context.save();
        context.save();
        this.transformContext();

        console.log("this.minX: " + this.minX);
        console.log("this.iteration: " + this.iteration);
        console.log("yintercept: " + yintercept);
        console.log("slope:" + slope);

        context.beginPath();
        context.moveTo(this.minX, slope * this.minX + yintercept);

        for(var x = this.minX + this.iteration; x <= this.maxX; x += this.iteration) {
          if (this.iteration % 200 == 0){
           console.log("x: " + x + " y: " + (slope * x + yintercept));
          }
          context.lineTo(x, slope * x + yintercept);
        }

        context.restore();
        context.lineJoin = 'round';
        context.lineWidth = thickness;
        context.strokeStyle = color;
        context.stroke();
        context.restore();
      };

      Graph.prototype.transformContext = function() {
        var context = this.context;

        // move context to center of canvas
        this.context.translate(this.centerX, this.centerY);

        /*
         * stretch grid to fit the canvas window, and
         * invert the y scale so that that increments
         * as you move upwards
         */
        context.scale(this.scaleX, -this.scaleY);
      };
    
    </script>
    
    <script>
     $(document).ready(function(){
     
      $("#btnGraph").click(function(){

        var m1,b1,m2,b2 = 0;

        m1 = parseFloat($("#m1").val());
        b1 = parseFloat($("#b1").val());
        m2 = parseFloat($("#m2").val());
        b2 = parseFloat($("#b2").val());



       
        var myGraph = new Graph({
         canvasId: 'Graph',
         minX: -10,
         minY: -10,
         maxX: 10,
         maxY: 10,
         unitsPerTick: 1
        });      

        myGraph.drawLine(m1, b1, 'blue', 3);

        myGraph.drawLine(m2, b2, 'red', 4);

        //myGraph.drawEquation(function(x) {
         //return 1 * x;
        //}, 'red', 3);

     
      });
     
     });
     
     </script>
    
  </body>

</html>


Wednesday 2 August 2017

Calculating the square root in Javascript using the Babylonian method

Calculating the square root in Javascript is easily done using Math.sqrt(n). But it can be entertaining to use an approximation method instead and build up an algorithm to calculate the square root. We will use the Babylonian method to approximate the square root using an iterative approximation method.

The Babylonian method is described in Wikipedia here:
Babylonian method.

The following image shows how each step of a revised value for the square root is calculated.


We calculate the square root of S by using an inital guess and then revise that step by adding that guess with S divided by the guess and dividing by 2. The revised value is then used again as the new guess value. We stop iterating when the margin of error is below a given treshold. In the calculus, x is the step guess value and e is the error.

We start the calculation sample by adding in Bootstrap CSS and jQuery.















<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <script data-require="jquery@*" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <link data-require="bootstrap-css@*" data-semver="4.0.0-alpha.4" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/css/bootstrap.min.css" />
</head>

<body>
  <br />
  <div class="container">
    <h2>Find square root in JS with long division algorithm</h2>

    <hr />
    <!-- html code here -->
    <h3>Estimate Square Root</h3> Enter Number:
    <input id="num" value="700" size="2" type="text" />
    <br />
    <input id="submitButton" value="Calculate" type="submit" />
    <br />
    <br />
    <div id="details"></div>
  </div>
  <script type="text/javascript">
    "use strict";
    var x = 25;
    var guess = 9;
    var marginOfError = 0.1;
    var error = 0;
    var counter = 0;
    var htmlout = "";
    $(document).ready(function() {
      // function code goes here
      function getGuess(g) {
        console.log(g);
        var newguess = (g + x / g) / 2;
        return newguess;
      }
      $('#submitButton').click(function() {
        // JavaScript code here
        console.clear();
        counter = 0;
        x = parseFloat($('#num').val());
        guess = Math.floor(Math.random() * x + 1);
        error = Math.abs(guess * guess - x);
        while (error >= marginOfError) {
          guess = getGuess(guess)
          error = Math.abs(guess * guess - x);
          //console.log(guess);
          counter += 1;
        }
        console.log('Count is ' + counter)
        htmlout = "Square Root is " + guess.toFixed(2) + ". It took " + counter + " guesses";
        $('#details').html(htmlout);
        
      });
    });
  </script>
</body>

</html>

Let us clean up the code using classes in Ecmascript 6 (ES6) and use Traceur to support the ES6 syntax.

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
     <script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script>
        <script src="https://google.github.io/traceur-compiler/bin/BrowserSystem.js"></script>
        <script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script>
  <script data-require="jquery@*" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <link data-require="bootstrap-css@*" data-semver="4.0.0-alpha.4" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/css/bootstrap.min.css" />
</head>

<body>
  <br />
  <div class="container">
    <h2>Find square root in JS with long division algorithm</h2>

    <hr />
    <!-- html code here -->
    <h3>Estimate Square Root</h3> Enter Number:
    <input id="num" value="700" size="2" type="text" />
    <br />
    <input id="submitButton" value="Calculate" type="submit" />
    <br />
    <br />
    <div id="details"></div>
  </div>
  <script type="text/javascript">
    "use strict";
    
    class BabylonianSquareRootSolver {
      
      
      
      constructor(x_0, S, marginOfError = 0.1){
        this.S = S;
        this.x_0 = x_0;
        this.marginOfError = marginOfError;
      }
      
      getRevisedSquareRoot (x_n, S){
       var revisedValue = (x_n + (S/x_n)) / 2;
       return revisedValue;
      }
      
      calculateSqrt(){
        
        var counter = 0;
        var error = 0;
        var guess = this.x_0;
        
        error = Math.abs(this.x_0 * this.x_0 - S);
    
       while (error >= marginOfError) {
          guess = this.getRevisedSquareRoot(guess, this.S)
          error = Math.abs(guess * guess - this.S);
          console.log(guess);
          counter += 1;
          if (counter > 10)
           break;
        }
        
        var result = {
          S : this.S,
          error : error,
          iterations : counter,
          root : guess
        };
        
        return result;
        
      }
      
    }
  
    
    var S = 1;
    var guess = Math.floor(Math.random()*S);
    var marginOfError = 0.1;
    var error = 0;
    var counter = 0;
    var htmlout = "";
    $(document).ready(function() {
      // function code goes here
    
      $('#submitButton').click(function() {
        // JavaScript code here
        console.clear();
        counter = 0;
        S = parseFloat($('#num').val());
        guess = Math.floor(Math.random()*S);
        var bab = new BabylonianSquareRootSolver(guess, S);
        
        console.log(bab);
        var res = bab.calculateSqrt();
        htmlout = "Square Root is approximated to " + res.root.toFixed(2) + ". It took " + res.iterations 
        + " iterations. The error for this approximation is: " + res.error.toFixed(4);
        $('#details').html(htmlout);
        console.log(bab.calculateSqrt());
        
      });
    });
  </script>
</body>

</html>


You can test out the code yourself with the following Plunk:
Babylonian method - Plunk Here is an image of the GUI:

Monday 17 July 2017

Promises in ES6 for async operations

This article will present a new feature in ES6 which is the Promise object. This object will ease the burden of programming async operations in Javascript. In classic JS building up multiple asynchronous operations has been cumbersome and there is a lot of ceremony to catch exception. This article will describe some simple uses of Promise(s) and provide some code examples.

I will use Plunkr as an editor and Traceur to support ES6 Javascript code. Traceur is a library to provide the necessary ES6 polyfills and shims to allow using ES6 JS code in browsers, regardless of their lacking support of ES6. Of course, more and more browsers support different functionality in ES6 already.

I will also use Jasmine to test out these Promise(s) using Test Driven Development (TDD) library Jasmine.

First off, we need to add in Traceur and Jasmine. I also include jQuery here. You might want to include these libraries with a local copy and not through a Content Delivery Network (CDN). Add first this to your HTML code:


<!DOCTYPE html>
<html>

  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <link data-require="jasmine@2.4.1" data-semver="2.4.1" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine.css" />
    <script data-require="jasmine@2.4.1" data-semver="2.4.1" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine.js"></script>
    <script data-require="jasmine@2.4.1" data-semver="2.4.1" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine-html.js"></script>
    <script data-require="jasmine@2.4.1" data-semver="2.4.1" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/boot.js"></script>
    <script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script>
    <script src="https://google.github.io/traceur-compiler/bin/BrowserSystem.js"></script>
    <script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  </head>



After adding in the necessary HTML code we will make use of Jasmine. We also create a simple helper function to return a Promise object to a function that returns a Promise object.


function getPromise(value, delay){
 return new Promise(resolve => {
  setTimeout(() => resolve(value), delay);
 });
}

describe("Promises in Ecmascript 6", function(){
 it("should execute Promise.race with expected result", function (done){
  let promise1 = getPromise('value: 1', 350);
  let promise2 = getPromise('value: 2', 450);
  let promise3 = getPromise('value: 3', 550);

  let fastestPromise = Promise.race([promise1, promise2, promise3 ]);
   // console.log(fastestPromise);
   fastestPromise.then(result => {
   expect(result).toBe('value: 1');
   done();
   }); //then

  }); //it
}); //describe

We use the built in functionality of Jasmine to test out and wait for asynchronous code to complete, passing into the SPEC function (the function named it) the parameter of done. By calling done(); we signal to Jasmin that the asynchronous code should have completed. Jasmin will wait for a specified time and signal a timeout if it does receive the result from the asynchronous operation.

We also here use ES6 arrow functions in the setTimeout method for compact syntax and we use setTimeout to simulate an easy asynchronous operation. Then we build up three Promises by calling the method getPromise. We then use the static method Promise.race which will on a given array of Promise objects return the quickest result. This is in behavior similar to the .WaitAny method in C# Task Parallel Library (TPL) for the happy .Net coders out there.

Moving on, we use the .then method on the Promise.race object (which is a Promise itself) and we use Jasmin's expect method (Similar to Assert in NUnit) and expect that the quickest method "won" the race, since it was the function with the shortest delay passed into the method getPromise and its call to setTimout.

The Promise object in ES6 will be further built upon in ES2017. Here, the await keywords will be added and make Javascript functional asynchronous programming more syntax-like and operational/behavior like much of that in .Net.

Most important, Promises in ES6 makes asynchronous programming and its necessary passing of callbacks and error catching much easier by allowing the programmer to chain multiple asynchronous operations and build asynchronous APIs. Multiple Promises can be passed in, chaining multiple Promises and "paths" of asynchronous operations and multiple async operations can be catched in a single or multiple common error handler with the .catch for error handling and the .then for the chained success function.

You can experiment yourself with the code above using Traceur and Jasmin. I have included a Plunk at the following url:

ES 6 Promises Plunk sample code Important - Note that inside an asynchronous operation we must signal that the async operation is completed. We use the resolve method or static Promise.resolve method to do that. We can also reject the success of the async operation by using the reject method or static Promise.rejec.

The call to done(); is because we use Jasmin as previously described and to support async operations inside a Jasmin TDD spec.

Let us also look at another type of Promises, chaining multiple Promises. We use the Promise.resolve method to build up Promises.