Bezier area

Area under a Berzier curve

by Richard Morris

HTML

<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<canvas id="canvas" width=400 height=300></canvas>
<br/>Num point:
<input id="nPts" name="sang" value="5" size="5" />
<br/>
<input id="goBut" type="button" value="Go" />Area:
<input id="area" name="sang" value="5" size="5" />

CSS

body {
    background-color: ivory;
}
#canvas {
    border:1px solid green;
}

JavaScript

// canvas and mousedown related variables
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var scrollX = $canvas.scrollLeft();
var scrollY = $canvas.scrollTop();

// save canvas size to vars b/ they're used often
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;

// The control points
var P = [{X:  13, Y: 224 }, 
         {X: 150, Y: 100 }, 
         {X: 251, Y: 224 }, 
         {X: 341, Y:  96 }, ];

ctx.lineWidth = 6;
ctx.strokeStyle = "#333";
ctx.beginPath();
ctx.moveTo(P[0].X, P[0].Y);
ctx.bezierCurveTo(P[1].X, P[1].Y, P[2].X, P[2].Y, P[3].X, P[3].Y);
ctx.stroke();

// draw the control polygon
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(P[0].X, P[0].Y);
ctx.lineTo(P[1].X, P[1].Y);
ctx.lineTo(P[2].X, P[2].Y);
ctx.lineTo(P[3].X, P[3].Y);
ctx.stroke();

function findarea(n) {
    ctx.lineWidth = 3;
    ctx.strokeStyle = "#f00";
    ctx.beginPath();

    var nSteps = n - 1;
    var x = [P[0].X];
    var y = [P[0].Y];
    ctx.moveTo(x[0], y[0]);

    var area = 0.0;
    for (var i = 1; i <= nSteps; ++i) {
        var t = i / nSteps;
        x[i] = P[0].X*(1-t)*(1-t)*(1-t)+3*P[1].X*t*(1-t)*(1-t)+3*P[2].X*t*t*(1-t)+P[3].X*t*t*t;
        y[i] = P[0].Y*(1-t)*(1-t)*(1-t)+3*P[1].Y*t*(1-t)*(1-t)+3*P[2].Y*t*t*(1-t)+P[3].Y*t*t*t;
        ctx.lineTo(x[i], y[i]);

        area += (x[i] - x[i-1]) * (y[i-1] + y[i]) / 2;
        
        if(x[i]<x[i-1]) alert("Not strictly increasing in x, area will be incorrect");
    }
    ctx.stroke();
    $("#area").val(area);
}

$("#goBut").click(function () {
    findarea($("#nPts").val());
});