Texts and Transformations II: Difference between revisions
From JSXGraph Wiki
A WASSERMANN (talk | contribs) No edit summary |
A WASSERMANN (talk | contribs) No edit summary |
||
(21 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
<jsxgraph with="500" height="500"> | === The problem === | ||
This example is similar to the one [[Texts and Transformations]], beside that the x-axis and | |||
the y-axis have different scalings. To be precise, the ratio of the two scalings is equal to 4. | |||
The result is that rotating the text and the image will also stretch these objects. | |||
<jsxgraph with="500" height="500" box="box1"> | |||
(function(){ | |||
var brd, txt, im, p0, p1; | |||
brd = JXG.JSXGraph.initBoard('box1', {boundingbox:[-5,20,5,-20], axis:true, showNavigation:true, showCopyright:true}); | |||
p0 = brd.create('point', [0,0], {style:5, name:'offset'}); | |||
p1 = brd.create('point', [3,0], {style:5, name:'rotate'}); | |||
txt = brd.create('text',[0,0, 'Hello'], {fontSize:64}); | |||
im = brd.create('image',["/distrib/images/uccellino.jpg", [0,0], [3,12]], {opacity:0.5}); | |||
var tOff = brd.create('transform', [function(){return p0.X()},function(){return p0.Y()}], {type:'translate'}); | |||
tOff.bindTo(txt); | |||
tOff.bindTo(im); | |||
tOff.bindTo(p1); | |||
// Rotate text around point "offset" by dragging point "rotate" | |||
var tRot = brd.create('transform', [function(){return Math.atan2(p1.Y()-p0.Y(),p1.X()-p0.X())}, p0], {type:'rotate'}); | |||
tRot.bindTo(txt); | |||
tRot.bindTo(im); | |||
})(); | |||
</jsxgraph> | |||
Here is the code for this example. | |||
<source lang="javascript"> | |||
(function(){ | |||
var brd, txt, im, p0, p1; | |||
brd = JXG.JSXGraph.initBoard('box1', {boundingbox:[-5,20,5,-20], axis:true, showNavigation:true, showCopyright:true}); | |||
p0 = brd.create('point', [0,0], {style:5, name:'offset'}); | |||
p1 = brd.create('point', [3,0], {style:5, name:'rotate'}); | |||
txt = brd.create('text',[0,0, 'Hello'], {fontSize:64}); | |||
im = brd.create('image',["/distrib/images/uccellino.jpg", [0,0], [3,12]], {opacity:0.5}); | |||
var tOff = brd.create('transform', [function(){return p0.X()},function(){return p0.Y()}], {type:'translate'}); | |||
tOff.bindTo(txt); | |||
tOff.bindTo(im); | |||
tOff.bindTo(p1); | |||
// Rotate text around point "offset" by dragging point "rotate" | |||
var tRot = brd.create('transform', [function(){return Math.atan2(p1.Y()-p0.Y(),p1.X()-p0.X())}, p0], {type:'rotate'}); | |||
tRot.bindTo(txt); | |||
tRot.bindTo(im); | |||
})(); | |||
</source> | |||
=== The solution === | |||
In order to avoid this effect, we have to do the following steps: | |||
* The rotation center has to be moved to the origin. | |||
<source lang="javascript"> | |||
var tOffInv = brd.create('transform', [function(){return -p0.X()},function(){return -p0.Y()}], {type:'translate'}); | |||
</source> | |||
* The objects have to be scaled by the ratio between the scalings of the axes, i.e. 4. | |||
<source lang="javascript"> | |||
var ts1 = brd.create('transform', [function(){return ratio;}, function(){return 1;}], {type:'scale'}); | |||
</source> | |||
* Now we rotate around the the origin (where the angle is also scaled) | |||
<source lang="javascript"> | |||
var tRot = brd.create('transform', [function(){return Math.atan2((p1.Y()-p0.Y())/ratio, p1.X()-p0.X());}], {type:'rotate'}); | |||
</source> | |||
* The scaling has to be undone. | |||
<source lang="javascript"> | |||
var ts2 = brd.create('transform', [function(){return 1/ratio;}, function(){return 1;}], {type:'scale'}); | |||
</source> | |||
* The rotation center is moved back. | |||
<source lang="javascript"> | |||
var tOff = brd.create('transform', [function(){return p0.X()},function(){return p0.Y()}], {type:'translate'}); | |||
</source> | |||
All these transformations have to be applied to the image and the text: | |||
<source lang="javascript"> | |||
tOffInv.bindTo(txt); ts1.bindTo(txt); tRot.bindTo(txt); ts2.bindTo(txt); tOff.bindTo(txt); | |||
tOffInv.bindTo(im); ts1.bindTo(im); tRot.bindTo(im); ts2.bindTo(im); tOff.bindTo(im); | |||
</source> | |||
<jsxgraph with="500" height="500" box="box2"> | |||
(function(){ | (function(){ | ||
var brd, txt, p0, p1, p2, im; | var brd, txt, p0, p1, p2, im; | ||
brd = JXG.JSXGraph.initBoard(' | brd = JXG.JSXGraph.initBoard('box2', {boundingbox:[-5,20,5,-20], axis:true, showNavigation:true, showCopyright:true}); | ||
p0 = brd.create('point', [0,0], {style:5, name:'offset'}); | p0 = brd.create('point', [0,0], {style:5, name:'offset'}); | ||
p1 = brd.create('point', [3,0], {style:5, name:'rotate here'}); | p1 = brd.create('point', [3,0], {style:5, name:'rotate here'}); | ||
p2 = brd.create('point', [0,4], {color:'blue', trace:true}); | p2 = brd.create('point', [0,4], {color:'blue', trace:true}); | ||
txt = brd.create('text',[ | txt = brd.create('text',[0, 0, JXG.JSXGraph.rendererType], {fontSize:64}); | ||
im = brd.create('image',["/distrib/images/uccellino.jpg", [0,0], [3, | im = brd.create('image',["/distrib/images/uccellino.jpg", [0,0], [3,12]], {opacity:0.5}); | ||
var tOffInv = brd.create('transform', [function(){return -p0.X()},function(){return -p0.Y()}], {type:'translate'}); | var tOffInv = brd.create('transform', [function(){return -p0.X()},function(){return -p0.Y()}], {type:'translate'}); | ||
Line 15: | Line 91: | ||
tOff.bindTo(p1); | tOff.bindTo(p1); | ||
tOff.bindTo(txt); | |||
tOff.bindTo(im); | tOff.bindTo(im); | ||
Line 24: | Line 101: | ||
var tRot = brd.create('transform', [function(){return Math.atan2((p1.Y()-p0.Y())/ratio, p1.X()-p0.X());}], {type:'rotate'}); | var tRot = brd.create('transform', [function(){return Math.atan2((p1.Y()-p0.Y())/ratio, p1.X()-p0.X());}], {type:'rotate'}); | ||
// Rotate text around point "offset" by dragging point " | // Rotate text around point "offset" by dragging point "rotate" | ||
tOffInv.bindTo(txt); ts1.bindTo(txt); tRot.bindTo(txt); ts2.bindTo(txt); tOff.bindTo(txt); | tOffInv.bindTo(txt); ts1.bindTo(txt); tRot.bindTo(txt); ts2.bindTo(txt); tOff.bindTo(txt); | ||
tOffInv.bindTo(im); ts1.bindTo(im); tRot.bindTo(im); ts2.bindTo(im); tOff.bindTo(im); | tOffInv.bindTo(im); ts1.bindTo(im); tRot.bindTo(im); ts2.bindTo(im); tOff.bindTo(im); | ||
Line 31: | Line 108: | ||
brd.update(); | brd.update(); | ||
})(); | })(); | ||
</jsxgraph> | </jsxgraph> | ||
===The JavaScript code=== | ===The JavaScript code=== | ||
Here is the complete code | Here is the complete code. | ||
<source lang="javascript"> | <source lang="javascript"> | ||
(function(){ | |||
var brd, txt, p0, p1, p2, im; | |||
brd = JXG.JSXGraph.initBoard('box2', {boundingbox:[-5,20,5,-20], axis:true, showNavigation:true, showCopyright:true}); | |||
p0 = brd.create('point', [0,0], {style:5, name:'offset'}); | |||
p1 = brd.create('point', [3,0], {style:5, name:'rotate here'}); | |||
p2 = brd.create('point', [0,4], {color:'blue', trace:true}); | |||
txt = brd.create('text',[0, 0, JXG.JSXGraph.rendererType], {fontSize:64}); | |||
im = brd.create('image',["/distrib/images/uccellino.jpg", [0,0], [3,12]], {opacity:0.5}); | |||
var tOffInv = brd.create('transform', [function(){return -p0.X()},function(){return -p0.Y()}], {type:'translate'}); | |||
var tOff = brd.create('transform', [function(){return p0.X()},function(){return p0.Y()}], {type:'translate'}); | |||
tOff.bindTo(p1); | |||
tOff.bindTo(txt); | |||
tOff.bindTo(im); | |||
// This is a rotation in screen coordinates. | |||
// ratio is the the ratio between the board dimensions (maxY-minY)/(maxX-minX) in user coordinates | |||
ratio = 4; | |||
var ts1 = brd.create('transform', [function(){return ratio;}, function(){return 1;}], {type:'scale'}); | |||
var ts2 = brd.create('transform', [function(){return 1/ratio;}, function(){return 1;}], {type:'scale'}); | |||
var tRot = brd.create('transform', [function(){return Math.atan2((p1.Y()-p0.Y())/ratio, p1.X()-p0.X());}], {type:'rotate'}); | |||
// Rotate text around point "offset" by dragging point "rotate" | |||
tOffInv.bindTo(txt); ts1.bindTo(txt); tRot.bindTo(txt); ts2.bindTo(txt); tOff.bindTo(txt); | |||
tOffInv.bindTo(im); ts1.bindTo(im); tRot.bindTo(im); ts2.bindTo(im); tOff.bindTo(im); | |||
tRot.bindTo(p2); // For comparison, a rotation in user coordinates. | |||
brd.update(); | |||
})(); | |||
</source> | </source> | ||
[[Category:Examples]] | [[Category:Examples]] | ||
[[Category:Text]] |
Latest revision as of 15:54, 9 August 2023
The problem
This example is similar to the one Texts and Transformations, beside that the x-axis and the y-axis have different scalings. To be precise, the ratio of the two scalings is equal to 4. The result is that rotating the text and the image will also stretch these objects.
Here is the code for this example.(function(){
var brd, txt, im, p0, p1;
brd = JXG.JSXGraph.initBoard('box1', {boundingbox:[-5,20,5,-20], axis:true, showNavigation:true, showCopyright:true});
p0 = brd.create('point', [0,0], {style:5, name:'offset'});
p1 = brd.create('point', [3,0], {style:5, name:'rotate'});
txt = brd.create('text',[0,0, 'Hello'], {fontSize:64});
im = brd.create('image',["/distrib/images/uccellino.jpg", [0,0], [3,12]], {opacity:0.5});
var tOff = brd.create('transform', [function(){return p0.X()},function(){return p0.Y()}], {type:'translate'});
tOff.bindTo(txt);
tOff.bindTo(im);
tOff.bindTo(p1);
// Rotate text around point "offset" by dragging point "rotate"
var tRot = brd.create('transform', [function(){return Math.atan2(p1.Y()-p0.Y(),p1.X()-p0.X())}, p0], {type:'rotate'});
tRot.bindTo(txt);
tRot.bindTo(im);
})();
The solution
In order to avoid this effect, we have to do the following steps:
- The rotation center has to be moved to the origin.
var tOffInv = brd.create('transform', [function(){return -p0.X()},function(){return -p0.Y()}], {type:'translate'});
- The objects have to be scaled by the ratio between the scalings of the axes, i.e. 4.
var ts1 = brd.create('transform', [function(){return ratio;}, function(){return 1;}], {type:'scale'});
- Now we rotate around the the origin (where the angle is also scaled)
var tRot = brd.create('transform', [function(){return Math.atan2((p1.Y()-p0.Y())/ratio, p1.X()-p0.X());}], {type:'rotate'});
- The scaling has to be undone.
var ts2 = brd.create('transform', [function(){return 1/ratio;}, function(){return 1;}], {type:'scale'});
- The rotation center is moved back.
var tOff = brd.create('transform', [function(){return p0.X()},function(){return p0.Y()}], {type:'translate'});
All these transformations have to be applied to the image and the text:
tOffInv.bindTo(txt); ts1.bindTo(txt); tRot.bindTo(txt); ts2.bindTo(txt); tOff.bindTo(txt);
tOffInv.bindTo(im); ts1.bindTo(im); tRot.bindTo(im); ts2.bindTo(im); tOff.bindTo(im);
The JavaScript code
Here is the complete code.
(function(){
var brd, txt, p0, p1, p2, im;
brd = JXG.JSXGraph.initBoard('box2', {boundingbox:[-5,20,5,-20], axis:true, showNavigation:true, showCopyright:true});
p0 = brd.create('point', [0,0], {style:5, name:'offset'});
p1 = brd.create('point', [3,0], {style:5, name:'rotate here'});
p2 = brd.create('point', [0,4], {color:'blue', trace:true});
txt = brd.create('text',[0, 0, JXG.JSXGraph.rendererType], {fontSize:64});
im = brd.create('image',["/distrib/images/uccellino.jpg", [0,0], [3,12]], {opacity:0.5});
var tOffInv = brd.create('transform', [function(){return -p0.X()},function(){return -p0.Y()}], {type:'translate'});
var tOff = brd.create('transform', [function(){return p0.X()},function(){return p0.Y()}], {type:'translate'});
tOff.bindTo(p1);
tOff.bindTo(txt);
tOff.bindTo(im);
// This is a rotation in screen coordinates.
// ratio is the the ratio between the board dimensions (maxY-minY)/(maxX-minX) in user coordinates
ratio = 4;
var ts1 = brd.create('transform', [function(){return ratio;}, function(){return 1;}], {type:'scale'});
var ts2 = brd.create('transform', [function(){return 1/ratio;}, function(){return 1;}], {type:'scale'});
var tRot = brd.create('transform', [function(){return Math.atan2((p1.Y()-p0.Y())/ratio, p1.X()-p0.X());}], {type:'rotate'});
// Rotate text around point "offset" by dragging point "rotate"
tOffInv.bindTo(txt); ts1.bindTo(txt); tRot.bindTo(txt); ts2.bindTo(txt); tOff.bindTo(txt);
tOffInv.bindTo(im); ts1.bindTo(im); tRot.bindTo(im); ts2.bindTo(im); tOff.bindTo(im);
tRot.bindTo(p2); // For comparison, a rotation in user coordinates.
brd.update();
})();