How to use x and y Ranges (Restrictions)?

681 views
Skip to first unread message

Tanzeel Ghumman

unread,
Mar 23, 2018, 6:22:41 AM3/23/18
to JSXGraph
Using JSXGraph, how can we use restrictions and ranges like Desmos does here: http://learn.desmos.com/restrictions/

I want to draw a graph within two X and Y values. I am drawing multiple graphs on single board so restricting x-axis and y-axis won't work in this case.

Thank you

Tanzeel Ghumman

unread,
Mar 23, 2018, 6:24:23 AM3/23/18
to JSXGraph
I am using Curve, line, and points.

Alfred Wassermann

unread,
Mar 23, 2018, 8:56:30 AM3/23/18
to JSXGraph
For curves, you can implement restrictions directly into the terms defining the functions.
If one value (for the x- or y-coordinate) is not allowed, simply return "NaN".
Here is an example, see it live at https://jsfiddle.net/vcL7aepo/230/ :

const board = JXG.JSXGraph.initBoard('jxgbox', {
                  boundingbox
: [-5, 5, 5, -5],
                  axis
: true
             
});
     
var c1 = board.create('curve', [
   
function(t) {
           
var val = Math.cos(t);
       
if (val < 0.5) {
           
return val;
       
} else {
           
return NaN;
       
}
   
},
   
function(t) {
       
return Math.sin(t) + t;
   
},
   
-2 * Math.PI,
   
2 * Math.PI
], {strokeWidth: 3});



For lines, I do not see an easy way to implement general restrictions. One way would be to add invisible (curve) elements which mark the restricted area and intersect
the (also invisible) line with this invisible element. Then, define a segment through the intersection points.

For points, it depends what you want: do you want points to be invisible outside the allowed region, or do you want to prevent that points are dragged into the restricted area?.
For the first, you can supply a function as value for the attribute visible:

var A = board.create('point', [0,0], {visible: function() { return (A.X() < 0) ? true : false; }});



For the second, you can work with events:

A = board.create('point', [0,0]);
A
.on('drag', function() {
   
if (A.X() < 0) {
        A
.moveTo([0, A.Y()]);
   
}
});



Best wishes,
Alfred

Tanzeel Ghumman

unread,
Mar 24, 2018, 5:17:53 AM3/24/18
to JSXGraph
Thank you Alfred for the help. NaN as not allowed value makes sense to me. I have played around with this function but not getting what i want to achieve here. Let me put my code here and expected result so that you are in better position to help.

If we put this equation in Desmos:

y=x^2{1<y<5}{x<2}

and we get the result like that  (this is expected result for me too):


Here is what i am writing as to translate above equation into code to get same results in JSXGraph. Let me know where i am doing wrong? I want restriction to be applied at x and y on same time like desmos does in above example:

var c = board.create('curve', [function (t) {
   
if (t < 2) {
     
return t;
    } else {
     
return NaN;
    }
}, func('x^2'), 1, 5], set);

*set is variable having settings.

I am trying to apply Y restrictions as 3rd and 4th parameter (1,5) and X restrictions into function where i am comparing t value. Or it can be visa versa for X and Y. Tried both.

I must be missing something here. Please keep in mind that i take function as input from user and wrapping the equation in func(). x^2 is user input here.

Looking forward for your suggestions.

Many thanks Alfred.

Cheers,

Alfred Wassermann

unread,
Mar 26, 2018, 5:43:13 AM3/26/18
to JSXGraph
One way to restrict the function values with a wrapper function would be something like this.  The restrictions are stored in arrays 'x_interval', 'y_interval' of size two:

const board = JXG.JSXGraph.initBoard('jxgbox', {

                                boundingbox
: [-6, 6, 6, -6],
                  axis
: true
             
});

// User input
var txt = 'x^2'; // Input from user
var f = board.jc.snippet(txt, true, 'x', true); // Create a JavaScript function from the user input

// Restrictions
var x_interval = [-Infinity, 2];
var y_interval = [1, 5];

// Wrapper function
var wrap = function(x) {
       
var y = f(x);
       
if (x_interval[0] < x && x < x_interval[1] &&
            y_interval
[0] < y && y < y_interval[1]
   
) {
       
return y;
   
} else {
       
return NaN;
   
}
}
board
.create('functiongraph', [wrap, -10, 10]);



See a demo at https://jsfiddle.net/vcL7aepo/260/

Best wishes,
Alfred


Tanzeel Ghumman

unread,
Mar 26, 2018, 7:08:00 AM3/26/18
to JSXGraph
Brilliant. It worked for me. Thank you Alfred. You are a champ (y).

Tanzeel Ghumman

unread,
Mar 27, 2018, 9:21:42 AM3/27/18
to JSXGraph
One problem i got. Few functions are not plotting graphs like:

e^(x*log(x))

and 

JXG.Math.mod(x,6)

I tried

mod(x,6)

too.

Plus all stat functions.

Is there anything else i am not doing in order to work these functions perfectly?

Thank you Alfred.

Alfred Wassermann

unread,
Mar 27, 2018, 9:56:53 AM3/27/18
to JSXGraph
If you take a string and convert it to a JavaScript function via board.jc.snippet(), it means you are using the JessieCode parser of JSXGraph, see https://github.com/jsxgraph/JessieCode .
Now, in JessieCode the mod function is realized with the %-operator, i.e. you have to use 'x % 6', and the mathematical constant e is named EULER in JessieCode.
That means, your code could look like this:

const board = JXG.JSXGraph.initBoard('jxgbox', {

                                boundingbox
: [-5, 5, 5, -5],
                  axis
: true
             
});
     
var f = board.jc.snippet('EULER^(x*log(x))', true, 'x', true);
board
.create('functiongraph', [f]);

var g = board.jc.snippet('x % 6', true, 'x', true);
board
.create('functiongraph', [g]);



See also https://jsfiddle.net/vcL7aepo/274/.
The statistical functions of JSXGraph are not yet available in JessieCode. For these you have to supply a JavaScript function like

board.create('functiongraph', [
   
function(x) { return JXG.Math.Statistics.mean([x, 1, 2, 3]); }
]);



Best wishes,
Alfred

Tanzeel Ghumman

unread,
Mar 27, 2018, 10:23:31 AM3/27/18
to JSXGraph
And how can i apply restrictions on Stat functions? my initial question remains there for stat functions.

I tried that:

f = 'function(x) { return ' + eq + '; }';

Where eq = JXG.Math.Statistics.mean([x, 1, 2, 3]);

Thank you Alfred.

Alfred Wassermann

unread,
Mar 27, 2018, 10:38:44 AM3/27/18
to JSXGraph
Do you want to use an arbitrary statistics function or a specific one?
Can you post an example?

Tanzeel Ghumman

unread,
Mar 27, 2018, 12:43:51 PM3/27/18
to JSXGraph
I am using following stat functions:


That's how i was plotting graph before restrictions, but now i have to add restrictions and i started this post.

var eq = 'JXG.Math.Statistics.mean([x, 1, 2, 3]'; // User input, i am formatting it like that to pass to jsx. Formatting other stat functions too like that.

var
key = 'somekey';

var set = {
 
name: key,
 strokeWidth: 2,
 strokeColor: "#333333",
 withLabel: false,
 highlightStrokeColor: "#333333",
 needsRegularUpdate: true,
};

obj_graph
[key] = board.create('curve', [function (t) {
 
return t;
},
  func(eq)], set);

var func = function(fun) {
 
var evl = eval("g = function(x){ with(Math) return " + mathjs(fun) + " }");
 return evl;
}

This works good for all stat functions (without x and y restrictions)

I am also using Algebra functions, like GCD, LCM, Round, log, mod, squarroot..etc include linear and polynomial equations.

It would be great help if we can find generic solution for all graphs.

Also can you please share JessieCode documentation URL? specially the syntax JessieCode understands.

Thank you for all the help Alfred.

Alfred Wassermann

unread,
Mar 28, 2018, 5:01:16 AM3/28/18
to JSXGraph
This is interesting!
I would do it like in the code below. I removed the call of "mathjs()" in the example, because it was nowhere defined. But this does not change anything.

    var set = {
        strokeWidth
: 2,
       
// ... some more attributes
   
};

   
// The function (in x) which we want to plot
   
var eq = 'JXG.Math.Statistics.mean([x, 1, 2, 3])';

   
var func = function(fun) {
       
// Create a JavaScript function.
        // var g = new Function('x', 'with (Math) return ' + mathjs(fun) + ';');
       
var g = new Function('x', 'with (Math) return ' + fun + ';');


       
// Restrictions
       
var x_interval = [-Infinity, 2];
       
var y_interval = [1, 5];

       
// Wrapper function
       
var wrap = function(x) {

           
var y = g(x);

           
if (x_interval[0] < x && x < x_interval[1] &&
                y_interval
[0] < y && y < y_interval[1]
               
) {
               
return y;
           
} else {
               
return NaN;
           
}

       
};

       
return wrap;
   
}

    board
.create('functiongraph', [func(eq)], set);



Best wishes,
Alfred

Tanzeel Ghumman

unread,
Mar 28, 2018, 8:35:42 AM3/28/18
to JSXGraph
Works like a charm (y). mathjs is to perform some formatting it is necessary for my implementation. You nailed it Alfred. Will perform some more testing to see how it goes. It is working for all the functions i tested so far.

Thank you very much Alfred.

Tanzeel Ghumman

unread,
Apr 5, 2018, 6:52:07 AM4/5/18
to JSXGraph
Alfred,

Using solution you mentioned, every thing is working good, but when i plot graph of sin(x) on x axis (not y) default range of displaying graph remains [10,-10] despite the limit mentioned is Infinity in js wrapper. When i put some limit like [5000, -5000] graph starts behaving distorted. See by code below in both cases and image if distorted graph.

var set = {
 
name: 'name',
  strokeWidth: 2,
  strokeColor: "#333333",
  withLabel: false,
  highlightStrokeColor: "#333333",
  needsRegularUpdate: true,
};

function generateWrapper(eq, key){
 
var x_start,x_end,y_start,y_end;
  // Parse and Get ranges defined in equation.
// Returns like [-Infinity, Infinity, -Infinity, Infinity]
  var vals = calculateRanges(key);
  x_start = vals[0];
  x_end = vals[1];
  y_start = vals[2];
  y_end = vals[3];
  // Creates a JavaScript function.
//  var g = new Function('x', 'with (Math) return ' + mathjs(eq) + ';');
  var g = new Function('x', 'with (Math) return ' + eq + ';');
  // Restrictions
  var x_interval = [x_start, x_end];
  var y_interval = [y_start, y_end];
  // Wrapper js function.
  var wrap = function(x) {
   
//var y = f(x);
    var y = g(x);
    if (x_interval[0] < x && x < x_interval[1] &&
     
y_interval[0] < y && y < y_interval[1]
   
) {
     
return y;
    } else {
     
return NaN;
    }
 
}
 
return wrap;
}

// Plotting with xcoordinats limists while plotting curve.
obj_graph[key] = board.create('curve', [wrap,
  function (t) {
   
return t;
  },-5000,5000], set);

// Plotting withOUT xcoordinats limists while plotting curve. DEFAULT VALUE IS BEING SET TO [-10 10]
obj_graph[key] = board.create('curve', [wrap,
  function (t) {
   
return t;
  }], set);



Distorted graph image (when moving the graph up and down):


Thank you Alfred for all the help.

On Wednesday, 28 March 2018 14:01:16 UTC+5, Alfred Wassermann wrote:

Tanzeel Ghumman

unread,
Apr 10, 2018, 4:51:56 AM4/10/18
to JSXGraph
Alfred, can you please enlighten the solution of problem i am having as described in my last post?


On Wednesday, 28 March 2018 14:01:16 UTC+5, Alfred Wassermann wrote:

Alfred Wassermann

unread,
Apr 11, 2018, 6:34:54 AM4/11/18
to JSXGraph
Dear Tanzeel,
in your code, you can control the visible area in two different ways.
Suppose we have curve of the form
    (X(t), Y(t)) where t runs from a to b,
which we want to display.
The default method of JSXGraph for such a curve is to supply a and b as parent elements:

 
   board.create('curve', [X, Y, a, b]);

Unfortunately, the documentation is outdated: if you do not supply a and b, the default values are not -10 and 10, but the range of the x-axis. (We will change this for general curves).

The wrapper function in your application gives you an additional control to hide parts of the curve.
Every part of the curve which is outside of the supplied intervals x_interval and y_interval will be suppressed.

That means that x_interval and y_interval can only impose a further RESTRICTION of the curve.

Regarding the distorted graph image:
During mouse drags, curves are always plotted with less precision, in order to save computing resources.

Best wishes,
Alfred



Tanzeel Ghumman

unread,
Apr 11, 2018, 6:44:01 AM4/11/18
to JSXGraph
Thank you Alfred for taking some time out from you busy schedule :)

I put a and b values, where a = -5000, and b=5000, but when i put this limit, graph starts distorted (even after releasing the mouse, not during drag). For current screen it appears ok, but when i move up graph is distorted. Is there anything i need to do to fix that?

Thank you,

Alfred Wassermann

unread,
Apr 11, 2018, 6:56:32 AM4/11/18
to JSXGraph
What is the bounding box of the board?


Tanzeel Ghumman

unread,
Apr 11, 2018, 9:17:12 AM4/11/18
to JSXGraph
Here are default settings of boundingBox:

// Zoom settings
var zoom_setting = {
 
enabled: true,
 factorX: 1.75,
 factorY: 1.75,
 wheel: true,
 needShift: false,
 min: 0.01,
 max: 5000.0,
 pinchHorizontal: true,
 pinchVertical: true,
 pinchSensitivity: 7,
 keepaspectratio:true
};
// Pan settings
var pan_setting = {
 
needTwoFingers: false,
 needShift: false,
 needCtrl: false,
 enabled: true
};
// Default settings with bondingbox, which displays grids.
var default_setting = {boundingbox:[-10,10,10,-10],xlabel:'', grid:true,
  keepaspectratio:true, axis:false,showNavigation:true,zoom:zoom_setting,
  needsRegularUpdate: true, pan:pan_setting };


I also update the board dynamically using settings form to set x and y ticks + labels..etc.

Also using axis with dynamic data, and not using default axis. Here is code to generate axis:

x_axis = board.create('axis', [[0, 0], [1, 0]], {name:new_setting.xlabel,
     withLabel: true, label: {position: 'rt', offset: [-15, 20]},
margin: 0,ticks: {drawLabels: new_setting.axis_number, ticksDistance: 5},
     lastArrow: false,needsRegularUpdate: true});

y_axis = board.create('axis', [[0, 0], [0, 1]], {name:new_setting.ylabel,
     withLabel: true,label: {position: 'top',offset: [-20, 0] },
margin: -30,ticks: {drawLabels: new_setting.axis_number,
       ticksDistance: 5}, lastArrow: false,needsRegularUpdate: true});

* Some variables are used, please ignore them as they are dynamic.

Alfred Wassermann

unread,
Apr 12, 2018, 5:47:15 AM4/12/18
to JSXGraph
Are you sure that there is no bug in your code? Did you watch the console output?
Every final update after releasing the mouse button should trigger a replot with high quality, i.e. with the same quality as the initial plot.
So, I'm wondering why the quality of the plot is still inferior even after releasing the mouse button.

Nevertheless, I implemented a long-standing request: control the plot-quality by attributes.
In the next nightly build there are two new curve attributes (with default values):

recursionDepthHigh: 17,
recursionDepthLow
: 13


If you set recursionDepthLow to let's say 16, updates during dragging will still be faster, but the quality is quite good. That saying your set of attributes should look like:

var set = {
  name
: 'name',
  strokeWidth
: 2,
  strokeColor
: "#333333",
  withLabel
: false,
  highlightStrokeColor
: "#333333",
  needsRegularUpdate
: true,

  recursionDepthLow
: 16,
  recursionDepthLow
: 17
};



Best wishes,
Alfred



Alfred Wassermann

unread,
Apr 12, 2018, 5:48:05 AM4/12/18
to JSXGraph
Sorry, the set of attributes should be


var set = {
  name: 'name',
  strokeWidth: 2,
  strokeColor: "#333333",
  withLabel: false,
  highlightStrokeColor: "#333333",
  needsRegularUpdate: true,
  recursionDepthLow: 16,
  recursionDepthHigh: 17
};

Tanzeel Ghumman

unread,
Apr 12, 2018, 6:10:40 AM4/12/18
to JSXGraph
Alfred,

Thank you for the changes, i am waiting for nightly release to try it out.

 yes i have checked the console output, no error.

If i set bigger limit, it gets more distorted, as we go down with values of a and b, it starts getting smooth (not distorted), like if i put -1000, 1000 as a and b value, graph will be much better. Just sharing if that can help.

Tanzeel Ghumman

unread,
Apr 16, 2018, 2:35:05 AM4/16/18
to JSXGraph
Alfred,

I have tried nightly build (4-15-2018) and graph distorted issue remains same. I created fiddle so that you can play around to see where the devil lies: https://jsfiddle.net/owntgLhu/6/

Every time where y values reaches to 70, graph starts distorting to where y value is 75.

Have a look please and help me here.

Thank you,

Alfred Wassermann

unread,
Apr 16, 2018, 5:21:25 AM4/16/18
to JSXGraph
In your example, the update quality is not yet adapted. Please, use e.g.  recursionDepthLow:16:

board.create('curve', [wrap,
           
function (t) {
             
return t;

           
}, -2000, 2000], {recursionDepthLow:16});



See https://jsfiddle.net/owntgLhu/10/ .
Best wishes,
Alfred



Tanzeel Ghumman

unread,
Apr 16, 2018, 5:40:11 AM4/16/18
to JSXGraph
Alfred,

It was mistake in fiddle, but result remains same. Please see screenshot with both new parameters:

Update the fiddle too: https://jsfiddle.net/owntgLhu/15/

Thank you Alfred.

Alfred Wassermann

unread,
Apr 16, 2018, 6:22:35 AM4/16/18
to JSXGraph
You are right!.
There are few more parameters which have influence on the plot quality. Now I changed one of these other parameters and it should work now (taking slightly more CPU time to plot).
Again, it will be in the next nightly build.



Tanzeel Ghumman

unread,
Apr 17, 2018, 7:19:07 AM4/17/18
to JSXGraph
Alfred,

Great. It works good now.

But, I am using 0.99.5 version of JSXGraph, when i move to 99.6 or nightly builds, i start facing 2 issues:

1) My functions (like GCD, LCM) stop working. Is there anything i need to update in those functions? i am using these functions like mentioned in https://jsxgraph.uni-bayreuth.de/docs/symbols/JXG.Math.html and they work perfectly with 0.99.5.

2) Board is not clickable any more, like i can't click on any graph to select or call "board.on('hit',event_hit)" event. Looks like some layer overlapping the graph and left the board non-clickable. Do i need to change something else other than just adding new version of core JSXGraph file?

Much appreciated Alfred.

Alfred Wassermann

unread,
Apr 17, 2018, 9:39:52 AM4/17/18
to JSXGraph
Do the nightly builds work?
Best wishes,
Alfred

Tanzeel Ghumman

unread,
Apr 17, 2018, 9:43:04 AM4/17/18
to JSXGraph
Yes, it works, but i am having 2 issues after that:

1) My functions (like GCD, LCM) stop working. Is there anything i need to update in those functions? i am using these functions like mentioned in https://jsxgraph.uni-bayreuth.de/docs/symbols/JXG.Math.html and they work perfectly with 0.99.5.

2) Board is not clickable any more, like i can't click on any graph to select or call "board.on('hit',event_hit)" event. Looks like some layer overlapping the graph and left the board non-clickable. Do i need to change something else other than just adding new version of core JSXGraph file?

Thank you Alfred, and sorry for the trouble :D

Alfred Wassermann

unread,
Apr 17, 2018, 9:45:33 AM4/17/18
to JSXGraph
What about dragging of objects? Does that work?


Alfred Wassermann

unread,
Apr 17, 2018, 9:54:01 AM4/17/18
to JSXGraph
A quick check showed:
  • JXG.Math.gcd(a, b) still works
  • JXG.Math.lcm(a, b) does not exist - neither now nor in 0.99.5

I am irritated now...


Tanzeel Ghumman

unread,
Apr 17, 2018, 10:01:40 AM4/17/18
to JSXGraph
Alfred,

If i set these values: recursionDepthLow: 13, recursionDepthHigh: 17

During dragging it appears distorted but at re-plotting on release works fantastically. If i increased recursionDepthLow: 16, it works perfectly, but you are right it slow down the performance a bit, specially on mobile phone.

Cheers,

Tanzeel Ghumman

unread,
Apr 17, 2018, 10:14:19 AM4/17/18
to JSXGraph
:O That's strange. I have been using it JXG.Math.lcm(4,x), and it plots a graph.

Tanzeel Ghumman

unread,
Apr 17, 2018, 10:26:58 AM4/17/18
to JSXGraph
Ah, It turned out one of our team member added lcm function in the file. Sorry to bother you about this point.

Alfred Wassermann

unread,
Apr 18, 2018, 4:26:27 AM4/18/18
to JSXGraph
Dear Tanzeel,
thank you very much for your bug report.
Indeed, the hti/mousehit events werde broken. The bug is fixed now and will be available in the next nightly build.
I would appreciate it very much if you could test it and give me feedback.

By the way: We want to encourage all developers to create bug reports on Github if they find a bug or a regression in a new version.

Best wishes and many thanks,
Alfred
 

Tanzeel Ghumman

unread,
Apr 18, 2018, 4:29:02 AM4/18/18
to JSXGraph
Awesome. I will surely give the feedback.
Reply all
Reply to author
Forward
0 new messages