jsxgraph

How to change n to nslider.Value()?


I wrote jsxgraphic code to draw cardioid bellow. I want to change n to nslider.Value(). Can anyone help me fix it?

var board = JXG.JSXGraph.initBoard('jxgbox', 
    {axis:false, boundingbox:[-8,4,4,-5], keepaspectratio:true});
var R = 3.5;
var k = board.create('slider',[[-7,-3.5],[-3,-3.5],[1, 2, 16]], {snapWidth: 1, name: 'k'});
var nslider = board.create('slider',[[-7,-4.5],[-3,-4.5],[10, 20, 60]], {snapWidth: 10, name: 'n'});
var co = board.create('circle', [[0, 0], R]);

function degToRad(degrees) {
    return degrees * (Math.PI / 180);
};

function plotcardioid(n, k) {
    var px = [], py = [];
    for (let i = 0; i<n; i++) {
        var alpha = degToRad(i*360/n);
        px.push(R*Math.cos(alpha));
        py.push(R*Math.sin(alpha));
    }
    for (let i = 0; i<n; i++) {
        var p = [px[i], py[i]];
        var q = function (){return [px[k.Value()*i%n], py[k.Value()*i % n]]};
        board.create('segment', [p, q]);
    }
}

plotcardioid(128, k);

link: https://jsfiddle.net/fcgej23p/19/


Solution

  • Well, you consequently have to remove n by nslider.Value(). Here is the code, see https://jsfiddle.net/jrgumcqd/1/:

      function plotcardioid(n, k) {
        var px = [], py = [];
            
        for (let i = 0; i < n.Value(); i++) {
            var alpha = degToRad(i*360/n.Value());
            px.push(R*Math.cos(alpha));
            py.push(R*Math.sin(alpha));
        }
        for (let i = 0; i<n.Value(); i++) {
            let p = [px[i], py[i]];
            let q = function (){
                return [
                px[k.Value()*i % n.Value()], 
                py[k.Value()*i % n.Value()]
              ]};
            board.create('segment', [p, q]);
        }
    }
    
    plotcardioid(nslider, k);
    

    However, I would not advise to create elements as reaction to slider movements. In JSXGraph it is relatively expensive to create new elements and additionally it is not really clear what happens with the "old" segments. My suggestion is to create a single curve and update it by overwriting the updateDataArray method. Adding a NaN after each pair of coordinates allows the curve to "jump". Here is the code (https://jsfiddle.net/4wtexsfz/7/):

    var board = JXG.JSXGraph.initBoard('jxgbox', 
        {axis:false, boundingbox:[-8,4,4,-5], keepaspectratio:true});
    var R = 3.5;
    var kslider = board.create('slider',[[-7,-3.5],[-3,-3.5],[1, 2, 16]], {snapWidth: 1, name: 'k'});
    var nslider = board.create('slider',[[-7,-4.5],[-3,-4.5],[10, 128, 160]], {snapWidth: 10, name: 'n'});
    var co = board.create('circle', [[0, 0], R]);
    
    function degToRad(degrees) {
        return degrees * (Math.PI / 180);
    }
    
    var cardioid = board.create('curve', [[], []], {strokeWidth: 0.8, strokeColor: 'purple'});
    cardioid.updateDataArray = function() {
        var px = [], py = [],
            n = nslider.Value(), // global
            k = kslider.Value(); // global
        
        this.dataX = [];
        this.dataY = [];
        
        for (let i = 0; i < n; i++) {
            let alpha = degToRad(i * 360 / n);
            px.push(R * Math.cos(alpha));
            py.push(R * Math.sin(alpha));
        }
        
        for (let i = 0; i < n; i++) {
            this.dataX.push(px[i]);
            this.dataX.push(px[k * i % n]);
            this.dataX.push(NaN);  // Jump
            this.dataY.push(py[i]);
            this.dataY.push(py[k * i % n]);
            this.dataY.push(NaN);  // Jump
        }
    };
    
    board.update();