How to rotate a curve

62 views
Skip to first unread message

Cyrille Piatecki

unread,
Jul 24, 2023, 10:03:40 AM7/24/23
to JSXGraph
In economics, it happens that one may construct the type of diagram diplayed in the figure here attached.
It represent the general equilibrium of an economy with two agents. One represents the utility levels of  A (the green curves) and the ones of B. But B is antipodist that is, the origin for him is at the 0 individu B. This oblige to create a rotation of the utility function.

Whichever be my tentatives I fail to draw some utility functions (say U(x) = N/x for different level of N) from the point of view of B.

Could I have a little help please. '(A and B could have exactly the same utilities).
edgew.png

Alfred Wassermann

unread,
Jul 26, 2023, 9:39:29 AM7/26/23
to JSXGraph
Dear Cyrille,
v1.5.0 has a bug concerning transformations. Can you please check if you can rotate the curve using the current beta version

Best wishes,
Alfred



Cyrille Piatecki

unread,
Jul 31, 2023, 5:33:27 AM7/31/23
to JSXGraph
Hello Alfred,

I just begin to test the beta version. In looking the documentation "https://jsxgraph.org/docs/symbols/Transformation.html", the first exemple seems wrong. there is no p1 point on the board.

I will test all type of configurations and I come back to you.

Alfred Wassermann

unread,
Jul 31, 2023, 6:20:32 AM7/31/23
to JSXGraph
Dear Cyrille,
sorry for being quite about this problem. Unfortunately, transformations are broken in v1.5.0, we are in the final steps to release v1.6.0. Please, before investing more work in this problem, check if the problem also appears with v1.4.6.
Best wishes,
Alfred






Alfred Wassermann

unread,
Jul 31, 2023, 6:25:07 AM7/31/23
to JSXGraph
It would be even better to test the v1.6.0 beta version from https://jsxgraph.org/beta/jsxgraphcore.js.
Best wishes,
Alfred

Cyrille Piatecki

unread,
Jul 31, 2023, 7:27:51 AM7/31/23
to JSXGraph
I have tried but nothing works. But it's perhaps my missunderstanding. Initialy, "transform" was specialized to points. It seems you change its behavior or at least it's call to apply it not only on points. But on internet the documentation seems to be old.
right now I want to display a curvybraket linking two points. In pstricks (I use it for years) it was simple (but of course static). use directly "{" or "}" as a font element and scale it and rotate it. Is there a way to do such a simple operation. of course, the true difficulty is that the bracket must change if you change the location of a point.

here is a try who obviously has no effect (even it generate  no error)

var  q0 = board.create('point',[0,0],{visible:true,fillColor:"cadetBlue",strokeColor:"cadetBlue",name:""});
var  q1 = board.create('point',[3,0],{visible:true,fillColor:"cadetBlue",strokeColor:"cadetBlue",name:""});
var  t0 = board.create('text',[function(){return (q0.X()+q1.X())/2},-.25,"}"],{fontSize:20,visible:true,fillColor:"cadetBlue",strokeColor:"cadetBlue",name:""});
var  r0 = board.create('transform', [90.0*Math.PI/180.0, function(){return (q0.X()+q1.X())/2},-.25], {type:'rotate'});
r0.bindTo(t0);
board.update();

Alfred Wassermann

unread,
Jul 31, 2023, 8:52:17 AM7/31/23
to JSXGraph
Here is an attempt to solve what you are aiming for.

1) For rotating texts using transformations, there is the restriction that only texts with attribute "display:'internal'" can be rotated. This will change soon, but at the time being this restriction still holds.
In the example below, text t0 is rotated (on its original distance from q0) around q0 using the transformation q0. The same is done for the curve c0.

2) For the text t2 we use a different strategy, however you need the beta version of JSXGraph v1.6.0 (from https://jsxgraph.org/beta/jsxgraphcore.js). Here, t1 is placed dynamically in the middle between
q0 and q1 and rotated by the attribute "rotate".

var q0 = board.create('point',[0,0],{visible:true,fillColor:"cadetBlue",strokeColor:"cadetBlue",name:""});
var q1 = board.create('point',[3,0],{visible:true,fillColor:"cadetBlue",strokeColor:"cadetBlue",name:""});

// The transformation r1 rotates t0 on the circle of radius 1.5 around q0 (in radians)
var t0 = board.create('text',[(q0.X() + q1.X()) / 2, -0.25, function(){ return ((q0.X() + q1.X()) / 2).toFixed(2); }],{
    fontSize:20,
    fillColor:"cadetBlue",
    strokeColor:"cadetBlue",
    display: 'internal'
});
var r1 = board.create('transform', [() => Math.atan2(q1.Y() - q0.Y(), q1.X() - q0.X()), q0], {type:'rotate'});
r1.bindTo(t0);

// t0 is in the middle between q0 and q1 and rotated using the attribute rotate (in degrees)
var t1 = board.create('text',[function(){ return (q0.X() + q1.X()) / 2; }, function(){ return (q0.Y() + q1.Y()) / 2; }, 'Ex. 2'],{
    fontSize:20,
    fillColor:"cadetBlue",
    strokeColor:"cadetBlue",
    rotate: () => Math.atan2(q1.Y() - q0.Y(), q1.X() - q0.X()) * 180 / Math.PI
});

// Rotating function graph
var c0 = board.create('functiongraph', [function(x) { return x*x; }, -2, 2]);
r1.bindTo(c0);


Best wishes,
Alfred

Alfred Wassermann

unread,
Jul 31, 2023, 8:54:06 AM7/31/23
to JSXGraph
Here is the same example from above using the beta version of JSXGraph: https://jsfiddle.net/4f1rv36s/2/
Best wishes,
Alfred

Cyrille Piatecki

unread,
Aug 2, 2023, 6:48:00 AM8/2/23
to JSXGraph
Dear Alfred,
I have just began to construct the graph i show you in the figure I send at the beginning of this conversation. When you display the graphics, it initialy seems good. But there is some problems and I do not know if this is caused by a bug or by my incompetence.

There is 4 gliders linked two by two (verticality and horizontality). Before adding functions all is fine there is absolutely no problem. The gliders are connected. But if I add the functions the focus is lost. If you can have a look it would be nice because it's just the start of a more complex graphics. 

----- the code -----

var board = JXG.JSXGraph.initBoard("box1", {pan: {enabled:false},boundingbox: [-1,4, 10,-1], axis:true,
withLines:false,
defaultAxes: {
    x: { ticks: {visible: true} },
    y: { ticks: {visible: true} }
  },
showNavigation:false,showCopyright:false});
var board2 = JXG.JSXGraph.initBoard("box2", {boundingbox: [-1, 1.33, 7, -0.5],visible:false, showNavigation:false,showCopyright:false});
//var btn=board.create("button",[1,1],{id:"btn1"});
board.jc = new JXG.JessieCode();
board.jc.use(board);
board.renderer.container.style.backgroundColor='#E5E4E2';
board.dehighlightAll();
board.renderer.container.style.backgroundColor = '#E5E4E2';
board2.renderer.container.style.backgroundColor='#E5E4E2';
board2.dehighlightAll();
board2.renderer.container.style.backgroundColor = '#E5E4E2';

var checkbox = board.create('checkbox', [-0.5, -.5, '']);


JXG.addEvent(checkbox.rendNodeCheckbox, 'change', function() {
    if (this.Value()) {
      document.getElementById("box2").style.display="block";
    } else {
      document.getElementById("box2").style.display="none";

;
    }
}, checkbox);

cadetBlue="#5F93A0";
venetianRed="#c80815";
grey="#d9d9d6";
mauve="#E2ABBF";
jauneImperial="#FAE22F";
von=true;
vno=false;

var  t0 = board.create('text',[-.15,-.15,"$0$"],{visible:von,name:"",highlight:vno,anchorX:"middle"});
var  t00 = board.create('text',[9.15,3.6,"$0$"],{visible:von,name:"",highlight:vno,anchorX:"middle"});
var  q0 = board.create('point',[0,0],{visible:von,fillColor:cadetBlue,strokeColor:cadetBlue,name:"",highlight:vno});
var  q1 = board.create('point',[9,0],{visible:von,fillColor:mauve,strokeColor:mauve,name:"",highlight:vno});
var  s0 = board.create('segment',[q0,q1],{visible:vno,fillColor:cadetBlue,strokeColor:cadetBlue,name:"",highlight:vno});
var  g0 = board.create('glider',[3,0,s0],{visible:von,fillColor:cadetBlue,strokeColor:"white",name:"",highlight:vno});
var  s1 = board.create('segment',[q0,g0],{visible:von,fillColor:cadetBlue,strokeColor:cadetBlue,strokeWidth:5,name:"",highlight:vno});
var  s2 = board.create('segment',[g0,q1],{visible:von,fillColor:venetianRed,strokeColor:venetianRed,strokeWidth:5,name:"",highlight:vno});
var  t1 = board.create('text',[8.9,-.15,"$\\overline{x}$"],{visible:von,name:"",highlight:vno,anchorX:"middle"});
var  t11 = board.create('text',[.15,3.6,"$\\overline{x}$"],{visible:von,name:"",highlight:vno,anchorX:"middle"});
var  ts0 = board.create('text',[2.95,-.15,"$x_A$"],{visible:von,name:"",highlight:vno,anchorX:"middle"});
var  gr0 = board.create('group',[g0,ts0]);
var  ts1 = board.create('text',[3.15,3.65,"$x_B$"],{visible:von,name:"",highlight:vno,anchorX:"middle"});
var  gr1 = board.create('group',[g0,ts1]);

var  q2 = board.create('point',[0,3.5],{visible:von,fillColor:jauneImperial,strokeColor:jauneImperial,name:"",highlight:von});
var  q3 = board.create('point',[9,3.5],{visible:von,fillColor:venetianRed,strokeColor:venetianRed,name:"",highlight:von});
var  t2 = board.create('text',[-0.2,3.45,"$\\overline{y}$"],{visible:von,name:"",highlight:vno,anchorX:"middle"});
var  t3 = board.create('text',[9.15,0.1,"$\\overline{y}$"],{visible:von,name:"",highlight:vno,anchorX:"middle"});
var  s3 = board.create('segment',[q2,q3],{visible:vno,fillColor:cadetBlue,strokeColor:cadetBlue,name:"",highlight:vno});
var  g1 = board.create('glider',[3,3.5,s3],{visible:von,fillColor:venetianRed,strokeColor:"white",name:"",highlight:vno});
var  s4 = board.create('segment',[q2,g1],{visible:von,fillColor:cadetBlue,strokeColor:cadetBlue,strokeWidth:5,name:"",highlight:vno});
var  s5 = board.create('segment',[g1,q3],{visible:von,fillColor:venetianRed,strokeColor:venetianRed,strokeWidth:5,name:"",highlight:vno});
var  s6 = board.create('segment',[g0,g1],{visible:von,fillColor:"black",strokeColor:"black",strokeWidth:1,name:"",highlight:vno,dash:2});
g0.on('drag', function() {g1.moveTo([g0.X(), 3.5]);});
g1.on('drag', function() {g0.moveTo([g1.X(), 3.5]);});    
var  s7 = board.create('segment',[q0,q2],{visible:vno,fillColor:cadetBlue,strokeColor:cadetBlue,name:"",highlight:vno});
var  g2 = board.create('glider',[0,1,s7 ],{visible:von,fillColor:cadetBlue,strokeColor:"white",name:"",highlight:vno});
var  s8 = board.create('segment',[q0,g2],{visible:von,fillColor:cadetBlue,strokeColor:cadetBlue,strokeWidth:5,name:"",highlight:vno});
var  s9 = board.create('segment',[g2,q2],{visible:von,fillColor:venetianRed,strokeColor:venetianRed,strokeWidth:5,name:"",highlight:vno});
var  s10 = board.create('segment',[q1,q3],{visible:vno,fillColor:cadetBlue,strokeColor:cadetBlue,name:"",highlight:vno});
var  g3 = board.create('glider',[9,1,s10 ],{visible:von,fillColor:cadetBlue,strokeColor:"white",name:"",highlight:vno});
var  s11 = board.create('segment',[q1,g3],{visible:von,fillColor:cadetBlue,strokeColor:cadetBlue,strokeWidth:5,name:"",highlight:vno});
var  s12 = board.create('segment',[g3,q3],{visible:von,fillColor:venetianRed,strokeColor:venetianRed,strokeWidth:5,name:"",highlight:vno});
var  s13 = board.create('segment',[g2,g3],{visible:von,fillColor:"black",strokeColor:"black",strokeWidth:1,name:"",highlight:vno,dash:2});
var  ts2 = board.create('text',[-.15,0.95,"$y_A$"],{visible:von,name:"",highlight:vno,anchorX:"middle"});
var  gr2 = board.create('group',[g2,ts2]);
var  ts3 = board.create('text',[9.2,1.1,"$y_B$"],{visible:von,name:"",highlight:vno,anchorX:"middle"});
var  gr3 = board.create('group',[g3,ts3]);
g2.on('drag', function() {g3.moveTo([9,g2.Y()]);});
g3.on('drag', function() {g2.moveTo([9,g3.Y()]);});
var inter0=board.create('intersection', [s6, s13, 0],{strokecolor:"white",fillColor:"white",name:""});
inter0.on("over",function(){this.setName("$\\text{Allocation Initiale}$");});
inter0.on("out",function(){this.setName("$ $");});


var f = function(x){return (inter0.X()*inter0.Y())/x};
var fu = function(x){return ((inter0.X()*inter0.Y())/x)-3.5};
var rootfu = JXG.Math.Numerics.fzero(fu, [0, 1]);
var f1 = function(x){return ((inter0.X()*inter0.Y()-1)/x)};
var f2 = function(x){return ((inter0.X()*inter0.Y()+1)/x)};
var g1 = board.create('functiongraph',
              [function(x){ return f(x);}, rootfu, 9],{strokeColor:cadetBlue,strokeWidth:3,name:"$\\overline{U}$"});      
var g2 = board.create('functiongraph',
              [function(x){ return f(x);}, 0, 10],{strokeColor:cadetBlue,strokeWidth:1,dash:2});
var g3 = board.create('functiongraph',//couleur
              [function(x){ return f1(x);}, 0, 10],{strokeColor:cadetBlue,strokeWidth:1,dash:2});                    
var g4 = board.create('functiongraph',//couleur
              [function(x){ return f2(x);}, 0, 10],{strokeColor:cadetBlue,strokeWidth:1,dash:2});                    

 

board.addChild(board2);

//////////////


Alfred Wassermann

unread,
Aug 2, 2023, 10:34:43 AM8/2/23
to JSXGraph
Dear Cyrille,
the problem stems from a small programming error: the function graphs and gliders use the same names  g1, g2, and g3.
Therefore, the events linked to the gliders are lead to unpredictable outcome.

Best wishes,
Alfred
 


Cyrille Piatecki

unread,
Aug 3, 2023, 9:36:50 AM8/3/23
to JSXGraph
Thanks I am .... (let you write whatever comes to your mind). Thanks
Reply all
Reply to author
Forward
0 new messages