Home
Random example
Search
Applications
Chemistry
Economy
Famous theorems
Geography
Physics
Sports
Test
Assessment
Calculus
3D
Applied calculus
Basic calculus
Differential equations
Function plotting
Implicit plotting
Sequences and series
Charts and data
Charts
Statistics
Curves
Interpolation
Intersection, Union, Difference
Lindenmayer Systems
Splines
Geometry
3D
Analytic
Euclidean
Basic constructions
Mappings
Non-Euclidean
Projective
Symmetry
Technical
Animation
Roulettes
Board options
First steps
Images
JSXGraph objects
Arcs and angles
Axes
Circles
Groups
Lines and arrows
Point
Polygons
Slider
Turtle
Vectors
JessieCode
Texts
Transformations
Video
jsxgraph.org
JSXGraph logo
JSXGraph
JSXGraph share

Share

Projectile motion
Show plain example
QR code
<iframe 
    src="https://www.jsxgraph.uni-bayreuth.de/share/iframe/projectile-motion" 
    style="border: 1px solid black; overflow: hidden; width: 550px; aspect-ratio: 55 / 65;" 
    name="JSXGraph example: Projectile motion" 
    allowfullscreen
></iframe>
This code has to
<div id="board-0-wrapper" class="jxgbox-wrapper " style="width: 100%; ">
   <div id="board-0" class="jxgbox" style="aspect-ratio: 1 / 1; width: 100%;" data-ar="1 / 1"></div>
</div>

<script type = "text/javascript"> 
    /*
    This example is licensed under a 
    Creative Commons Attribution ShareAlike 4.0 International License.
    https://creativecommons.org/licenses/by-sa/4.0/
    
    Please note you have to mention 
    The Center of Mobile Learning with Digital Technology
    and the autor Wigand Rathmann (https://en.www.math.fau.de/rathmann/)
    in the credits.
    */
    
    const BOARDID = 'board-0';

    var angle, v, friction, tFinal, curveN,  // Sliders
        point,   // Start point
        cf, cf2; // Curves
    
    const board = JXG.JSXGraph.initBoard(BOARDID, {
        axis: true,
        boundingbox: [-5, 5, 5, -5]
    });
    
    // Create some sliders to control the model
    angle = board.create('slider', [[1.1, 4.3], [3.1, 4.3], [0, 0.7, 1.57]], {name: 'angle'});
    v = board.create('slider', [[1.1, 4.7], [3.1, 4.7], [0, 10, 10]], {name: 'velocity'});
    friction = board.create('slider', [[1.1, 3.9], [3.1, 3.9], [0, 0.16, 2]], {name: 'friction', snapWidth: 0.05});
    tFinal = board.create('slider', [[1.1, 3.5], [3.1, 3.5], [0, 5, 15]], {name: 'tEnd'});
    curveN = board.create('slider', [[1.1, 3.1], [3.1, 3.1], [20, 100, 200]], {name: 'N', snapWidth: 1});
    
    // Trajectory:
    // Initial point 
    point = board.create('point', [-4, 0], {
        name: '(x_0,y_0)',
        color: 'red'
    });
    
    // ODE for projectile
    var frk = function(t, x) {
        // Friction
        let y = [
            x[2],
            x[3],
            0 - friction.Value() * x[2] * x[2],
            -9.81 - friction.Value() * x[3] * x[3]
        ];
        return y;
    };
    
    // Forward solver using JSXGraph's Runge-Kutta algorithm.
    // Note: x[0] is x, x[1] is y, x[2] is \dot x, x[3] is \dot y
    var forwardSolver = function() {
        var I, x0;
    
        // Time interval
        I = [0, tFinal.Value()];
        // Initial value 
        x0 = [point.X(), point.Y(), v.Value() * Math.cos(angle.Value()), v.Value() * Math.sin(angle.Value())];
        // Solve the ODE
        return JXG.Math.Numerics.rungeKutta('heun', x0, I, curveN.Value(), frk);
    };
    
    // Create and update curve which approximates the trajectory with friction
    cf = board.create('curve', [[], []], {strokeWidth: 2});
    cf.updateDataArray = function() {
        var i;
    
        // Solve ODE
        var data = forwardSolver();
        this.dataX = [];
        this.dataY = [];
        // Copy ODE solution to the curve
        for (i = 0; i < data.length; i++) {
            this.dataX[i] = data[i][0];
            this.dataY[i] = data[i][1];
        }
    }
    
    // Show the analytic solution without friction
    cf2 = board.create('curve', [
        (t) => v.Value() * Math.cos(angle.Value()) * t + point.X(),
        (t) => v.Value() * Math.sin(angle.Value()) * t - 9.81 / 2 * t * t + point.Y(),
        0, () => tFinal.Value()
    ], {
        strokeWidth: 1,
        strokeColor: 'red'
    });
    
 </script> 
/*
This example is licensed under a 
Creative Commons Attribution ShareAlike 4.0 International License.
https://creativecommons.org/licenses/by-sa/4.0/

Please note you have to mention 
The Center of Mobile Learning with Digital Technology
and the autor Wigand Rathmann (https://en.www.math.fau.de/rathmann/)
in the credits.
*/

const BOARDID = 'your_div_id'; // Insert your id here!

var angle, v, friction, tFinal, curveN,  // Sliders
    point,   // Start point
    cf, cf2; // Curves

const board = JXG.JSXGraph.initBoard(BOARDID, {
    axis: true,
    boundingbox: [-5, 5, 5, -5]
});

// Create some sliders to control the model
angle = board.create('slider', [[1.1, 4.3], [3.1, 4.3], [0, 0.7, 1.57]], {name: 'angle'});
v = board.create('slider', [[1.1, 4.7], [3.1, 4.7], [0, 10, 10]], {name: 'velocity'});
friction = board.create('slider', [[1.1, 3.9], [3.1, 3.9], [0, 0.16, 2]], {name: 'friction', snapWidth: 0.05});
tFinal = board.create('slider', [[1.1, 3.5], [3.1, 3.5], [0, 5, 15]], {name: 'tEnd'});
curveN = board.create('slider', [[1.1, 3.1], [3.1, 3.1], [20, 100, 200]], {name: 'N', snapWidth: 1});

// Trajectory:
// Initial point 
point = board.create('point', [-4, 0], {
    name: '(x_0,y_0)',
    color: 'red'
});

// ODE for projectile
var frk = function(t, x) {
    // Friction
    let y = [
        x[2],
        x[3],
        0 - friction.Value() * x[2] * x[2],
        -9.81 - friction.Value() * x[3] * x[3]
    ];
    return y;
};

// Forward solver using JSXGraph's Runge-Kutta algorithm.
// Note: x[0] is x, x[1] is y, x[2] is \dot x, x[3] is \dot y
var forwardSolver = function() {
    var I, x0;

    // Time interval
    I = [0, tFinal.Value()];
    // Initial value 
    x0 = [point.X(), point.Y(), v.Value() * Math.cos(angle.Value()), v.Value() * Math.sin(angle.Value())];
    // Solve the ODE
    return JXG.Math.Numerics.rungeKutta('heun', x0, I, curveN.Value(), frk);
};

// Create and update curve which approximates the trajectory with friction
cf = board.create('curve', [[], []], {strokeWidth: 2});
cf.updateDataArray = function() {
    var i;

    // Solve ODE
    var data = forwardSolver();
    this.dataX = [];
    this.dataY = [];
    // Copy ODE solution to the curve
    for (i = 0; i < data.length; i++) {
        this.dataX[i] = data[i][0];
        this.dataY[i] = data[i][1];
    }
}

// Show the analytic solution without friction
cf2 = board.create('curve', [
    (t) => v.Value() * Math.cos(angle.Value()) * t + point.X(),
    (t) => v.Value() * Math.sin(angle.Value()) * t - 9.81 / 2 * t * t + point.Y(),
    0, () => tFinal.Value()
], {
    strokeWidth: 1,
    strokeColor: 'red'
});
<jsxgraph width="100%" aspect-ratio="1 / 1" title="Projectile motion" description="This construction was copied from JSXGraph examples database: BTW HERE SHOULD BE A GENERATED LINKuseGlobalJS="false">
   /*
   This example is licensed under a 
   Creative Commons Attribution ShareAlike 4.0 International License.
   https://creativecommons.org/licenses/by-sa/4.0/
   
   Please note you have to mention 
   The Center of Mobile Learning with Digital Technology
   and the autor Wigand Rathmann (https://en.www.math.fau.de/rathmann/)
   in the credits.
   */
   
   var angle, v, friction, tFinal, curveN,  // Sliders
       point,   // Start point
       cf, cf2; // Curves
   
   const board = JXG.JSXGraph.initBoard(BOARDID, {
       axis: true,
       boundingbox: [-5, 5, 5, -5]
   });
   
   // Create some sliders to control the model
   angle = board.create('slider', [[1.1, 4.3], [3.1, 4.3], [0, 0.7, 1.57]], {name: 'angle'});
   v = board.create('slider', [[1.1, 4.7], [3.1, 4.7], [0, 10, 10]], {name: 'velocity'});
   friction = board.create('slider', [[1.1, 3.9], [3.1, 3.9], [0, 0.16, 2]], {name: 'friction', snapWidth: 0.05});
   tFinal = board.create('slider', [[1.1, 3.5], [3.1, 3.5], [0, 5, 15]], {name: 'tEnd'});
   curveN = board.create('slider', [[1.1, 3.1], [3.1, 3.1], [20, 100, 200]], {name: 'N', snapWidth: 1});
   
   // Trajectory:
   // Initial point 
   point = board.create('point', [-4, 0], {
       name: '(x_0,y_0)',
       color: 'red'
   });
   
   // ODE for projectile
   var frk = function(t, x) {
       // Friction
       let y = [
           x[2],
           x[3],
           0 - friction.Value() * x[2] * x[2],
           -9.81 - friction.Value() * x[3] * x[3]
       ];
       return y;
   };
   
   // Forward solver using JSXGraph's Runge-Kutta algorithm.
   // Note: x[0] is x, x[1] is y, x[2] is \dot x, x[3] is \dot y
   var forwardSolver = function() {
       var I, x0;
   
       // Time interval
       I = [0, tFinal.Value()];
       // Initial value 
       x0 = [point.X(), point.Y(), v.Value() * Math.cos(angle.Value()), v.Value() * Math.sin(angle.Value())];
       // Solve the ODE
       return JXG.Math.Numerics.rungeKutta('heun', x0, I, curveN.Value(), frk);
   };
   
   // Create and update curve which approximates the trajectory with friction
   cf = board.create('curve', [[], []], {strokeWidth: 2});
   cf.updateDataArray = function() {
       var i;
   
       // Solve ODE
       var data = forwardSolver();
       this.dataX = [];
       this.dataY = [];
       // Copy ODE solution to the curve
       for (i = 0; i < data.length; i++) {
           this.dataX[i] = data[i][0];
           this.dataY[i] = data[i][1];
       }
   }
   
   // Show the analytic solution without friction
   cf2 = board.create('curve', [
       (t) => v.Value() * Math.cos(angle.Value()) * t + point.X(),
       (t) => v.Value() * Math.sin(angle.Value()) * t - 9.81 / 2 * t * t + point.Y(),
       0, () => tFinal.Value()
   ], {
       strokeWidth: 1,
       strokeColor: 'red'
   });
   
</jsxgraph>

Projectile motion

Applied calculus
Calculus
Differential equations
Function plotting
Physics
This example computes and shows the trajectory of a projectile with friction. The movement of the projectile can be modelled with the following second order differential equation: \[ \begin{align} \ddot x (t) = & -\mbox{friction} \cdot \dot x^2(t)\\ \ddot y (t) = & -g -\mbox{friction} \cdot \dot y^2(t) \end{align} \] JSXGraph has a Runge-Kutta solver for systems of ODEs. A well-know formulation of a second order differential equation as system of ODEs is \[\begin{align} \dot z_1(t) = & z_3(t)\\\dot z_2(t) = & z_4(t)\\ \dot z_3(t) = & -\mbox{friction} \cdot z_3^2(t)\\ \dot z_4(t) = & -\mbox{friction} \cdot z_4^2(t) -g \end{align}\] Using the identities for the position \(z_1=x\), \(z_2=y\) and the velocities \(z_3=\dot x=v_x\) and \(z_4=\dot y = v_y\) one can implement nonlinear behavior of this system. This implementation is not suitable for noncontinuous behavior to model e.g. scattering. The trajectory of the projectile with friction is shown in blue, the frictionless reference solution is shown in red.
Special thanks to the author Wigand Rathmann.
// Define the id of your board in BOARDID

var angle, v, friction, tFinal, curveN,  // Sliders
    point,   // Start point
    cf, cf2; // Curves

const board = JXG.JSXGraph.initBoard(BOARDID, {
    axis: true,
    boundingbox: [-5, 5, 5, -5]
});

// Create some sliders to control the model
angle = board.create('slider', [[1.1, 4.3], [3.1, 4.3], [0, 0.7, 1.57]], {name: 'angle'});
v = board.create('slider', [[1.1, 4.7], [3.1, 4.7], [0, 10, 10]], {name: 'velocity'});
friction = board.create('slider', [[1.1, 3.9], [3.1, 3.9], [0, 0.16, 2]], {name: 'friction', snapWidth: 0.05});
tFinal = board.create('slider', [[1.1, 3.5], [3.1, 3.5], [0, 5, 15]], {name: 'tEnd'});
curveN = board.create('slider', [[1.1, 3.1], [3.1, 3.1], [20, 100, 200]], {name: 'N', snapWidth: 1});

// Trajectory:
// Initial point 
point = board.create('point', [-4, 0], {
    name: '(x_0,y_0)',
    color: 'red'
});

// ODE for projectile
var frk = function(t, x) {
    // Friction
    let y = [
        x[2],
        x[3],
        0 - friction.Value() * x[2] * x[2],
        -9.81 - friction.Value() * x[3] * x[3]
    ];
    return y;
};

// Forward solver using JSXGraph's Runge-Kutta algorithm.
// Note: x[0] is x, x[1] is y, x[2] is \dot x, x[3] is \dot y
var forwardSolver = function() {
    var I, x0;

    // Time interval
    I = [0, tFinal.Value()];
    // Initial value 
    x0 = [point.X(), point.Y(), v.Value() * Math.cos(angle.Value()), v.Value() * Math.sin(angle.Value())];
    // Solve the ODE
    return JXG.Math.Numerics.rungeKutta('heun', x0, I, curveN.Value(), frk);
};

// Create and update curve which approximates the trajectory with friction
cf = board.create('curve', [[], []], {strokeWidth: 2});
cf.updateDataArray = function() {
    var i;

    // Solve ODE
    var data = forwardSolver();
    this.dataX = [];
    this.dataY = [];
    // Copy ODE solution to the curve
    for (i = 0; i < data.length; i++) {
        this.dataX[i] = data[i][0];
        this.dataY[i] = data[i][1];
    }
}

// Show the analytic solution without friction
cf2 = board.create('curve', [
    (t) => v.Value() * Math.cos(angle.Value()) * t + point.X(),
    (t) => v.Value() * Math.sin(angle.Value()) * t - 9.81 / 2 * t * t + point.Y(),
    0, () => tFinal.Value()
], {
    strokeWidth: 1,
    strokeColor: 'red'
});

license

This example is licensed under a Creative Commons Attribution ShareAlike 4.0 International License.
Please note you have to mention The Center of Mobile Learning with Digital Technology
and the author Wigand Rathmann in the credits.