Oscillator

From JSXGraph Wiki
Revision as of 18:37, 10 August 2012 by Michael (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

This little JXSGraph application simulates a damped oscillator. If You can catch the weight with the mouse, you can drag it and the animation restarts after releasing the mouse.

The underlying JavaScript code

var board = JXG.JSXGraph.initBoard('jxgbox', {boundingbox: [-10, 10, 10, -10], keepaspectratio: true, axis: true, grid: false}),
    line = board.create('line', [[0,8], [0,-10]], {visible: false, straightFirst: false, straightLast: false}),
    point = board.create('glider', [-8, -7, line], {name: 'Weight'}),
    isInDragMode = false,
    springHangup = board.create('point', [0, 9], {color: 'black', name: 'Spring', fixed: true}),
    i, numberOfSpringRings = 10, springRings = [];

for(i=0; i<numberOfSpringRings; i++) {
    springRings[i] = board.create('point', [0.5-i%2, function(i) { return function() { return springHangup.Y()-(i+1)*Math.abs((springHangup.Y() - point.Y())/(numberOfSpringRings+1))}; }(i)], {withLabel: false, color: 'black', size: 1});
    if(i>0)
        board.create('segment', [springRings[i-1], springRings[i]], {color: 'black', strokeWidth: 1});
}
board.create('segment', [springHangup, springRings[0]], {color: 'black', strokeWidth: 1});
board.create('segment', [springRings[numberOfSpringRings-1], point], {color: 'black', strokeWidth: 1});

function startAnimation(startY) {
    point.moveAlong(function() {
        var f = function(t, x) {
                var c = 0.1, k = 0.5, m = 1;
                return [x[1], -c / m * x[1] - k / m * x[0]];
            },
            area = [0, 200],
            numberOfEvaluations = (area[1] - area[0]) * 100,
            data = JXG.Math.Numerics.rungeKutta('heun', [startY, 0], area, numberOfEvaluations, f),
            duration = 20 * 1e3;

        return function(t) {
            if (t >= duration)
                return NaN;

            return [0, data[Math.floor(t / duration * numberOfEvaluations)][0]];
        }
    }());
}

function hook() {
    if(!isInDragMode) {
        if(board.mode === board.BOARD_MODE_DRAG) {
            board.stopAllAnimation();
            isInDragMode = true;
        }
    }

    if(isInDragMode) {
        if(board.mode !== board.BOARD_MODE_DRAG) {
            isInDragMode = false;
            startAnimation(point.Y());
        }
    }
}
board.addHook(hook);
startAnimation(-5);