Note that we in this demo will consider equations on the form of polynomial curves.
The picture reads integration, it should be integrals! Lets first look some math of how to do the integral of our example, we consider polynomials here, which will be defined as:
$$ y = f(x) = ax^3 + bx^2 + cx + d $$ The integral will be the areal between the function f(x) between startx and endx. Consider the following definition of the indefinite integral: $$\int f(x)\ dx $$ The definite area is then between startx s and endx e is then: $$\int_s^e f(x)dx $$ Some math ensues of to check the calculation of the integral (area), consider this following example :
$$ a = 0.05, b = 0.05, c = 0.05, d = 1 $$. We consider x to be between 1 and 4. Manually calculating the area results in the calculated area of 7.614 (the image shows 7.62, but a check showed it to be 7.614).
Calculation of the integral uses in the hand written calculation the start and end x-values and subtracting the end value of the integral formula with the start value. We consider x here to be between [1..4]. As the screen shot of the demo displays, we approximate this integral to the value 7.60 by calculating the integral as the sum of the midpoint rectangles.
The difference in the specific example between the hand written calculation of 7.62 (exact integral) and approximation of 7.60 is because of the fact that we approximate the integral by summing up the rectangles below the curve. Actually in some cases part of the rectangles are above the curve, there is some discrepancy between the approximate rectangle shape and the true shape of the integral. To get an even more exact value, reducing the increment from 0.5 to 0.25 will get a closer value to the exact one. Reducing the increments will result in smaller rectangles (thinner) following the curve more exact.
Now that we see that our math is sound, we can look at a Plunk with a demo displaying this.
Math integral demo - Plunk
In the sample the graph is displayed with Canvas in HTML 5. The following function in Javascript is used to display the integral and the midpoint rectangles:
Graph.prototype.drawPolynomial = function(polynomialequation, a, b, c, d, increment, isIntegral, color, thickness, startx, endx){ var totalArea = 0.0; var context = this.context; context.save(); context.save(); this.transformContext(); context.beginPath(); context.moveTo(this.minX, polynomialequation(a, b, c, d, this.minX)); for(var x = this.minX + this.iteration; x <= this.maxX; x += this.iteration) { context.lineTo(x, polynomialequation(a, b, c, d, x)); } context.restore(); context.lineJoin = 'round'; context.lineWidth = thickness; context.strokeStyle = color; context.stroke(); context.restore(); if (isIntegral){ var context = this.context; context.save(); this.transformContext(); var currentY = 0.0; context.lineWidth = 0.1; context.strokeStyle = 'red'; for(var x = startx; x < endx; x += increment) { context.beginPath(); currentY = polynomialequation(a, b, c, d, (x+increment/2.0)); context.rect(x, 0, increment, currentY); totalArea += increment * currentY; context.stroke(); } } return totalArea.toFixed(2); }
The following code is used to get the values for the coefficients of the polynomial equation and draw the polynomial function and the corresponding approximation rectangles for the integral.
$(document).ready(function(){ $("#btnDemo").click(function(){ $("#a").val("0.05"); $("#b").val("0.05"); $("#c").val("0.05"); $("#d").val("1"); $("#increment").val("0.25"); $("#startx").val("1.0"); $("#endx").val("4.0"); $("#btnGraph").click(); }); $("#btnGraph").click(function(){ var a,b,c,d,increment,startx,endx = 0; a = parseFloat($("#a").val()); b = parseFloat($("#b").val()); c = parseFloat($("#c").val()); d = parseFloat($("#d").val()); increment = parseFloat($("#increment").val()); startx = parseFloat($("#startx").val()); endx = parseFloat($("#endx").val()); var myGraph = new Graph({ canvasId: 'Graph', minX: -10, minY: -10, maxX: 10, maxY: 10, unitsPerTick: 1 }); var totalArea = myGraph.drawPolynomial(function(a,b,c,d,x){ return ((a*x*x*x) + (b * x*x) + c*x + d * 1.0).toFixed(2); }, a, b, c, d, increment, true, 'blue', 1.0, startx, endx); $("#detailsInfo").append("Total area under graph: " + totalArea); }); });
There is a lot of code to digest here, see through the code in the Plunk the article points to. The key points here is that we pass in a function as a delegate to be our Polynomial equation. We also approximate the integral (area) by summing up the rectangles below it.
Note that this demo also supports calculating the integral when it dips below the positive y axis!
Fix of reloading functionality
One issue with Canvas and a central one is the fact that the Canvas in HTML 5 is a rasterized grid. It is more like a single layer Photoshop image than a vectorized canvas like Illustrator. With that fact in mind, clearing the Canvas for a new redrawing functionality proved hard. In addition, I also use a transformation here from View-Coordinates to Object-Coordinates. A brute force redrawing is therefore preferred. The following ReloadCanvas method will fix this!function ReloadCanvas(canvasId){ //debugger; var oldCanvas = document.getElementById(canvasId); console.log("Old canvas: " + oldCanvas); var newCanvas = document.createElement('canvas'); var oldWidth = 500; var oldHeight = 500; if (oldCanvas){ oldWidth = oldCanvas.width; oldHeight = oldCanvas.height; oldCanvas.parentNode.removeChild(oldCanvas); } newCanvas.id = 'Graph'; newCanvas.width = oldHeight; newCanvas.height = oldWidth; document.body.appendChild(newCanvas); }
We detach the old canvas and insert a new one into the DOM (Document Object Model). I use here old api methods, you could also resort to more use of jQuery of course. Note that I try to get the old Canvas width and height and copy this to the new blank Canvas that I insert. You must use parentNode here to to the appendChild and removeChild methods to do the replacement of Canvas. This way, we can paint the Canvas again with a fresh new Canvas and have a simpler demo! I have updated the Plunk with a fixed Fork below:
Plunk - Integral math demo app
This demo also supports not only a convenient reload method to make the demo easier to test out, but also supports "negative integrals", i.e. sections where the integral dips below the x-axis as shown in the following image:
Note about accuracy
The total area calculated uses some rounding here. I used the .toFixed(2) to stick to a precision of 0.01. You can try out .toFixed(3) to test out a better precision. That will calculate even more precise the calculated area. The increments should of course be small and you will also see that some small values are still imprecise. We calculate the y value to be the midpoint of the polynomial f(x) and the midpoint should follow the curve as good as possible.Actually this integral demo app can support other equations that just polynomials. We could support for example trigonometric functions and so on also. I will look at this in a future demo+article!
So there you have it, Canvas and Js can tutor kids and students math concepts in Calculus quite elegant in a web browser. We are seeing that Javascript and HTML 5 are now just as powerful as Java applets in the good old days to describe different concepts and prove that once again Math is fun, especially when computers also come into play!
Note for students
What we have used in this demo is the calculation of definite integrals using the Midpoint Rule and Riemann sum. You can read more about it here. This is standard 1st year Calculus syllabus.
Riemann Sums (Wikipedia)