Graphing Parametric Functions in the Browser

December 3rd, 2009

At school I am just finishing up fall quarter. This was my first quarter of calculus and we are having our last quiz tomorrow on Parametric functions and l'Hopital's Rule. Instead of studying (or does this count?) I built a parametric equation graphing html/js thingy. I say thingy because it is definitely not a "web app", and I refuse to use the acronym "DHTML" in any context. This is just manipulating little DOM nodes around, obviously, there are much better mediums for this sort of thing. Let me have my fun.

As I write this, I just realized I should have tried out HTML5's <canvas>! Wow, I have been meaning to mess with that for a long time, and I feel I just let myself down. I answered "HTML5 and the canvas tag" to the question "What is some technology you are currently excited about?" at my interview for the job I hold now. One moment ago I was giddy over my graphs and now I feel like an idiot. Oh well, I guess I will have to port the code over sometime in the future.

A couple words of warning before I let you have it:

Click Here to Make Some Pretty Graphs!

Here are a couple ideas to get you started:

x = (t/7)*cos(t)
y = (t/7)*sin(t)
from 0 to 15*pi
2000 points
x = 2*cos(5*t)
y = 2*sin(3*t)
from 0 to 2*pi
1000 points

And here is the relevant JS code:

$(document).ready(function () {
    // For performance lets keep a reference to this element so we
    // don't have to search for it all the time.
    window.graph = $("#graph");

    $("#plot").click(function (event) {
        // Prevent form from POSTing and clear the graph.
        event.preventDefault();
        window.graph.html("");
        
        // Create the x and y functions.
        var x = textToFn($("#x").val());
        var y = textToFn($("#y").val());

        // Determine the range and step of t.
        var start = formFieldToNum("#range-start");
        var end = formFieldToNum("#range-end");
        var numPoints = formFieldToNum("#num-points");
        var step = (end - start) / numPoints;
        
        for (var t = start; t < end; t = t + step) {
            // setTimeout so that the browser won't freeze up. Must
            // pass t to a second function or else it will capture
            // the final value of t rather than what it is now
            // because t is passed by reference.
            (function (t) {
                setTimeout(function () {
                    plot(x(t), y(t));
                }, 1);
            }(t));
        }
    });
});

// Takes an x and a y pair that represents a point and plots the point
// on the graph.
function plot(x, y) {
    var point = $("<div class='point'></div>").css({
        "left": x*50 + "px",
        "bottom": y*50 + "px"
    });
    window.graph.append(point);
}

// Returns a function from a sample of text that has mathy things.
function textToFn(text) {
    return new Function(
        "t", ("return " + mathReplace(text) + ";"));
}

// Takes a form field's id selector and returns the number inside.
function formFieldToNum(id) {
    return parseInt(eval(mathReplace($(id).val())), 10);
}

// Convert Cos, Sin, and Pi to the JS equivalents.
function mathReplace(text) {
    return text.replace(/cos/gi, "Math.cos")
                .replace(/pi/gi, "Math.PI")
                .replace(/sin/gi, "Math.sin");
}

« Previous Entry

Next Entry »

View Comments


Recent Entries


setTimeout Patterns in JavaScript

On August 10th, 2010


ParenScript is an Acceptable Lisp

On August 2nd, 2010


TryParenScript.com

On July 23rd, 2010


In response to "A JavaScript Function Guard"

On July 19th, 2010


My Notes from John Resig's "jQuery Hack Day" Talk

On July 5th, 2010


Announcing Pocco

On June 29th, 2010


Yet Another Lisp

On June 25th, 2010


Recent Happenings: All Play and No Work

On June 21st, 2010


Arguments.callee considered extraneous

On June 2nd, 2010


Javascript, "bind", and "this"

On May 20th, 2010


Creative Commons License

Fork me on GitHub