How to manipulate Canvas elements: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
 
(43 intermediate revisions by 2 users not shown)
Line 3: Line 3:
'''Plot2D''' is nothing more than a collection of helpers that aims to facilitate the task of coding. It makes intensive use of the [[Canvas Nasal API|Canvas API]], a mandatory reference for those who intend to refine the result beyond what is offered by plot2D.<br />
'''Plot2D''' is nothing more than a collection of helpers that aims to facilitate the task of coding. It makes intensive use of the [[Canvas Nasal API|Canvas API]], a mandatory reference for those who intend to refine the result beyond what is offered by plot2D.<br />
It is assumed here that you already have a minimal knowledge about [[Canvas]].<br />
It is assumed here that you already have a minimal knowledge about [[Canvas]].<br />
For now '''Plot2D''' resides in the '''SpokenGCA''' addon (and you may download it from  [https://sourceforge.net/p/flightgear/fgaddon/HEAD/tree/trunk/Addons/SpokenGCA/plot2D.nas here]) , but the idea is that in the future it could be included in the $FG-ROOT/Nasal/canvas directory.<br />
For now, '''Plot2D''' resides in the '''SpokenGCA''' addon, but the idea is that in the future it could be included in the $FG-ROOT/Nasal/canvas directory.<br />
If you have not the SpokenGCA addon installed, you may download '''''plot2D.nas''''' from  [https://sourceforge.net/p/flightgear/fgaddon/HEAD/tree/trunk/Addons/SpokenGCA/plot2D.nas here], put it into your ''$FG-HOME/Nasal/'' folder and then execute:
<syntaxhighlight lang="nasal">
  var home = getprop("/sim/fg-home");
  io.load_nasal( home ~ '/Nasal/plot2D.nas', "canvas" );
</syntaxhighlight>Once executed, you can try the examples given below.<br />


== ''"Create"'' helpers ==
== ''Create'' helpers ==


=== line ===
=== line ===
  '''Parameters:''' (group, from, to, color)
  '''Parameters:''' (group, from, to, color="#0")
Plots a line as <'''group'''>'s child.
Plots a line as <'''group'''>'s child.
* '''from''' as [x,y] in pixels.
* '''from''' as [x,y] in pixels.
Line 17: Line 22:
! example !! Screenshot
! example !! Screenshot
|-
|-
| <syntaxhighlight>
| <syntaxhighlight lang="nasal">
var window = canvas.Window.new([200,200],"dialog")
var window = canvas.Window.new([200,200],"dialog")
     .set("title","Plot2D demo"  );
     .set("title","Plot2D demo"  );
Line 31: Line 36:
|}
|}
<hr/>
<hr/>
=== hzLine ===
=== hzLine ===
  '''Parameters:''' (group, from, length, color)
  '''Parameters:''' (group, from, length, color="#0")
Plots an horizontal line as <'''group'''>'s child.
Plots an horizontal line as <'''group'''>'s child.
* '''from''' as [x,y] in pixels.
* '''from''' as [x,y] in pixels.
Line 38: Line 44:
* '''color''' optional as [r,g,b] or "#rrggbb". Black by default.
* '''color''' optional as [r,g,b] or "#rrggbb". Black by default.
<hr/>
<hr/>
=== vtLine ===
=== vtLine ===
  '''Parameters:''' (group, from, length, color)
  '''Parameters:''' (group, from, length, color="#0")
Plots a vertical line as <'''group'''>'s child.
Plots a vertical line as <'''group'''>'s child.
* '''from''' as [x,y] in pixels.
* '''from''' as [x,y] in pixels.
Line 45: Line 52:
* '''color''' optional as [r,g,b] or "#rrggbb". Black by default.
* '''color''' optional as [r,g,b] or "#rrggbb". Black by default.
<hr/>
<hr/>
=== dashedLine ===
=== dashedLine ===
  '''Parameters:''' (group, from, length, color)
  '''Parameters:''' (group, from, to, dash=8, color="#0")
Plots a vertical line as <'''group'''>'s child.
Plots a vertical line as <'''group'''>'s child.
* '''from''' as [x,y] in pixels.
* '''from''' as [x,y] in pixels.
Line 56: Line 64:
! example !! Screenshot
! example !! Screenshot
|-
|-
| <syntaxhighlight>
| <syntaxhighlight lang="nasal">
var window = canvas.Window.new([200,200],"dialog").set("title","Plot2D demo"  );
var window = canvas.Window.new([200,200],"dialog").set("title","Plot2D demo"  );
var myCanvas = window.createCanvas().set("background", "#eeeeee");
var myCanvas = window.createCanvas().set("background", "#eeeeee");
Line 69: Line 77:
|}
|}
<hr/>
<hr/>
=== rectangle ===
=== rectangle ===
  '''Parameters:''' (group, size ,origin=nil, color="#0", fill=nil, rounded=nil)
  '''Parameters:''' (group, size ,origin=nil, color="#0", fill=nil, rounded=nil)
Line 91: Line 100:
! example !! Screenshot
! example !! Screenshot
|-
|-
| <syntaxhighlight lang="xml">
| <syntaxhighlight lang="nasal">
var window = canvas.Window.new([200,200],"dialog").set("title","Plot2D demo"  );
var window = canvas.Window.new([200,200],"dialog").set("title","Plot2D demo"  );
var myCanvas = window.createCanvas().set("background", "#eeeeee");
var myCanvas = window.createCanvas().set("background", "#eeeeee");
Line 105: Line 114:
|}<hr/>
|}<hr/>
=== text ===
=== text ===
  '''parameters''': (group, text, size, origin=nil, color="#0", align="left-baseline")
  '''parameters''': (group, text, origin=nil, size=nil, color="#0", align="left-baseline")
Plots a text as <'''group'''>'s child.
Plots a text as <'''group'''>'s child.
* '''text''' the text itself as string.
* '''text''' the text itself as string.
* '''size''' font size and aspect as [<size-px>,<height/width>].
* '''origin''' optional as [x,y] in pixels, [0,0] by default.
* '''origin''' optional as [x,y] in pixels, [0,0] by default.
* '''size''' optional font size and aspect as [<size-px>,<height/width>]. [11,1] by default.
* '''color''' optional font color as [r,g,b] or "#rrggbb". Black  by default.
* '''color''' optional font color as [r,g,b] or "#rrggbb". Black  by default.
* '''align''' optional origin reference. "left-baseline" by default.
* '''align''' optional origin reference. "left-baseline" by default.
Line 124: Line 133:
! example !! Screenshot
! example !! Screenshot
|-
|-
| <syntaxhighlight lang="xml">
|
var window = canvas.Window.new([200,200],"dialog").set("title","Plot2D demo" );
  {{Note| This assumes that you already have a top-level root group set up, and his ''group'' child named '''myGroup'''. }} <syntaxhighlight lang="nasal">
var myCanvas = window.createCanvas().set("background", "#eeeeee");
var (red,blue,green,orange) = ['#ee0000', [0,0,1], [0,0.8,0], '#ea9a32' ];
var root = myCanvas.createGroup();
var myGroup = root.createChild("group");
var (red,blue,green) = ['#ee0000', [0,0,1], [0,0.8,0] ];
canvas.plot2D.polyline(myGroup,[150,181,194,157,199],[52,20,64,28,36]);
canvas.plot2D.polyline(myGroup,[150,181,194,157,199],[52,20,64,28,36]);
   ## 3 vertices with default values:
   ## 3 vertices with default values:
canvas.plot2D.polyline(myGroup,[20,30,70],[15,55,65]);
canvas.plot2D.polyline(myGroup,[20,30,70],[15,55,65]);
canvas.plot2D.text(myGroup,'defaults',[75,25]);
   ## 3 vertices with symmetrical = 'x':
   ## 3 vertices with symmetrical = 'x':
canvas.plot2D.polyline(myGroup,[20,30,70],[130,170,180],blue,"x");
canvas.plot2D.polyline(myGroup,[20,30,70],[130,170,180],blue,"x");
canvas.plot2D.text(myGroup,'Symmetrical="x"',[20,195],,blue);
   ## 3 vertices with symmetrical = 'y':
   ## 3 vertices with symmetrical = 'y':
canvas.plot2D.polyline(myGroup,[150,160,200],[90,130,140],red,"y");
canvas.plot2D.polyline(myGroup,[150,160,200],[90,130,140],red,"y");
canvas.plot2D.text(myGroup,'Symmetrical="y"',[198,180],,red,'right-baseline');
   ## 3 vertices with symmetrical = 'xy':
   ## 3 vertices with symmetrical = 'xy':
canvas.plot2D.polyline(myGroup,[50,60,100],[100,140,150],green,"xy");
canvas.plot2D.polyline(myGroup,[50,60,100],[100,140,150],green,"xy");
canvas.plot2D.text(myGroup,'Symmetrical="xy"',[55,75],,green);
   ## 3 vertices with symmetrical = 'yx':
   ## 3 vertices with symmetrical = 'yx':
canvas.plot2D.polyline(myGroup,[100,110,150],[50,90,100],'#0',"yx");
canvas.plot2D.polyline(myGroup,[100,110,150],[50,90,100],orange,"yx");
canvas.plot2D.text(myGroup,'Symmetrical="yx"',[12,125],,orange);
</syntaxhighlight>
</syntaxhighlight>
|| [[File:Plot2D.rectangle and grid.png|thumb]]
|| [[File:Plot2D.polyline.png|thumb|plot2D.polyline example]]
|}
<hr/>
=== graphic ===
'''parameters''': (group, ySet, dx=nil, origin=nil, color="#0"
Plots the curve sampled in <'''ySet'''> with a resolution of <'''dx'''>.
* '''ySet''' as [y0,...,yn] in pixels.
* '''dx''' optional curve resolution in pixels. 1 px by default.
* '''origin''' optional as [x,y] in pixels, [0,0] by default.
* '''color''' optional grid color as [r,g,b] or "#rrggbb". Black  by default.
{| class="wikitable"
|-
! example !! Screenshot
|-
|
{{Note| This assumes that you already have a top-level root group set up, and his ''group'' child named '''myGroup'''. }} <syntaxhighlight lang="nasal">
  var (red,blue,green,orange) = ['#ee0000', [0,0,1], [0,0.8,0], '#ea9a32' ];
  var yValues = [];
  for(var i=0;i<460;i+=4) append(yValues, 30*math.sin(i*D2R));
  canvas.plot2D.hzLine(myGroup, [10,100],175,blue);
  canvas.plot2D.vtLine(myGroup, [15,180],-175,blue);
  canvas.plot2D.graphic(myGroup, yValues,,[15,100],red);
 
</syntaxhighlight>
|| [[File:Plot2D,graphic.png|thumb]]
|}
|}
<hr/>
== ''Movement'' helpers ==
=== flipX ===
'''parameters''': (elem, Xaxis=0)
Flips horizontally the element.
* '''elem''' element to be flipped.
* '''Xaxis''' optional abscissa of the symmetry axis . If 0 (default) element flips in-place.
<hr/>
=== flipY ===
'''parameters''': (elem, Yaxis=0)
Flips vertically the element.
* '''elem''' element to be flipped.
* '''Yaxis''' optional ordenate of the symmetry axis . If 0 (default) element flips in-place.
<hr/>
=== rotate180 ===
'''parameters''': (elem, center=nil)
Rotates the element 180 deg around '''center'''.
* '''elem''' element to be rotated.
* '''center''' optional as [Cx,Cy] in pixels. Rotates in-place by default.
<hr/>
=== alignX ===
'''parameters''': (elem, ref, alignment)
Aligns the element, moving it horizontaly to '''ref'''.
* '''elem''' element to be moved.
*  '''ref''' reference may be an integer or another element.
*  '''alignment''' as string: may be 'left-left', 'left-center', 'left-right',
            'center-left', 'center-center', 'center-right',
'right-left', 'right-center', or 'right-right'.<br />
If '''ref''' is a single number, the 2nd word is ignored.
<hr/>
=== alignY ===
'''parameters''': (elem, ref, alignment)
Aligns the element, moving it vertically to '''ref'''.
* '''elem''' element to be moved.
*  '''ref''' reference may be an integer or another element.
*  '''alignment''' as string: may be top-top', 'top-center', 'top-bottom',
            'center-top', 'center-center', 'center-bottom',
'bottom-top', 'bottom-center', or 'bottom-bottom'.<br />
''Text'' elements also accept   'baseline' as reference.<br />
If '''ref''' is a single number, the 2nd word is ignored.
== ''Resize'' helpers ==
=== stretchX ===
'''parameters''': (elem, factor, ref='left')
Stretchs horizontally the element .
* '''elem''' element to be stretched.
*  '''factor''' the <new-width>/<old-width> ratio.
*  '''ref''' optional: the relative point to keep inplace. May be 'left' (default),'center' or 'right'.
<hr/>
=== stretchY ===
'''parameters''': (elem,factor,ref='top')
Stretchs vertically the element .
* '''elem''' element to be stretched.
*  '''factor''' tthe <new-height>/<old-height> ratio.
*  '''ref''' optional: the relative point to keep in-place. May be 'top' (default),'center' or 'bottom'.
<hr/>
=== resize ===
'''parameters''': (elem,factors,ref='left-top')
Resizes vertically the element along both ''X'' and ''Y'' axis.
* '''elem''' element to be resized.
*  '''factors''' as [Xfactor, Yfactor].
*  '''ref''' optional: the relative point to keep in-place, as string. May be left-top', 'left-center', 'left-bottom',
            'center-top', 'center-center', 'center-bottom',
'right-top', 'right-center', or 'right-bottom'.<br />
== Behind the scenes ==
Let's see in detail the elements Canvas.<br />
Open the [[Interactive Nasal REPL]] interpreter and execute (you can copy&paste, then {{key press|Enter}}:
<syntaxhighlight>
var window = canvas.Window.new([300,200],"dialog").set("title","Plot2D demo"  );
var myCanvas = window.createCanvas().set("background", "#eeeeee");
var root = myCanvas.createGroup();
var myGroup = root.createChild("group");</syntaxhighlight>
We have our new canvas, ready to play with.<br />
At the ''>>>'' prompt type:<syntaxhighlight>
var arrow = canvas.plot2D.polyline(myGroup,[90,120,10],[20,30,30],'#0',"y");</syntaxhighlight>
Do not forget the {{key press|Enter}}.[[File:My_Arrow.png|thumb]]
You should have something like this:<br />
Let's get closer to see some hidden stuff:<br />[[File:Arrow.gif|none]] <br />
Our '''''arrow''''' has (like any other element) its own <big>'''''intrinsic'''''</big> coordinate system.
=== Internal Coordinates ===
Typing:
<syntaxhighlight>
arrow.getBoundingBox();
</syntaxhighlight> you get ''[9.5,19.5, 120.5,40.5]'' which are the values for [Xmin,Ymin, Xmax,Ymax].<br />
The virtual points (the red flashing ones) are usually named as (from 1 to 9):<br />
<span style="background: white; color: red">'left-top'    'center-top'    'right-top'
'left-center'  'center-center'  'right-center'
'left-bottom'  'center-bottom'  'right-bottom'</span> Is nothing other than a convenient way to refer to (Xmin,Ymin), (xXmin+Xnax/2,Ymin), etc.
'''Plot2D''' (and '''Canvas API''') uses such nomenclature.<br />
Let's apply a translation:
<syntaxhighlight>
arrow.setTranslation(150, 80);
</syntaxhighlight>[[File:Translated01.png|none|Translated arrow]]
The blue axis and labels are showing the <span style="background: white; color: blue">( '''u, v''' )</span> <big>absolute</big> coodinate system.<br />
Note that the translated arrow has brought with him his intrinsic coordenate system and his BoundingBox remains unchanged.<br />
Calling the ''getTranslation()'' we get [Tx, Ty] (In our case [150, 80] ).<br />
All points of the element meet the following equations::<br />
<big>'''''u = T<sub>x</sub> + x'''''</big>
<big>'''''v = T<sub>y</sub> + y'''''</big>
In a similar way, scaling works. Type:
<syntaxhighlight>
arrow.setTranslation(0,0);
arrow.setScale(2,4);
arrow.getScale();
</syntaxhighlight> you get ''[2,4]'' which are the values for [Sx, Sy].<br />[[File:Scaled.png|none|Scaled arrow]]
Again, the BoundingBox and the intrinsic coordenate system remains unchanged.<br />
=== Fundamental Equations ===
Now the general case, applying both Translation and Scaling:
<syntaxhighlight>
arrow.setTranslation(150,80);
arrow.setScale(2,4);
</syntaxhighlight>[[File:General.png|none|Translated and scaled arrow]]<br />
The Fundamental Equations:
<big><big>'''''u = T<sub>x</sub> + x * Sx'''''</big></big>
<big><big>'''''v = T<sub>y</sub> + y * Sy'''''</big></big>
                            and his reciprocals:
<big><big>'''''T<sub>x</sub> =  u - x * Sx'''''</big></big>
<big><big>'''''T<sub>y</sub> =  v - y * Sy'''''</big></big>
'''Plot2D''' makes extensive use of these equations.

Latest revision as of 18:25, 7 December 2017

The purpose of this document is to introduce the plot2D tool and provide basic information about its use.
Plot2D is nothing more than a collection of helpers that aims to facilitate the task of coding. It makes intensive use of the Canvas API, a mandatory reference for those who intend to refine the result beyond what is offered by plot2D.
It is assumed here that you already have a minimal knowledge about Canvas.
For now, Plot2D resides in the SpokenGCA addon, but the idea is that in the future it could be included in the $FG-ROOT/Nasal/canvas directory.
If you have not the SpokenGCA addon installed, you may download plot2D.nas from here, put it into your $FG-HOME/Nasal/ folder and then execute:

  var home = getprop("/sim/fg-home");
  io.load_nasal( home ~ '/Nasal/plot2D.nas', "canvas" );

Once executed, you can try the examples given below.

Create helpers

line

Parameters: (group, from, to, color="#0")

Plots a line as <group>'s child.

  • from as [x,y] in pixels.
  • to as [x,y] in pixels.
  • color optional as [r,g,b] or "#rrggbb", Black by default.
example Screenshot
var window = canvas.Window.new([200,200],"dialog")
    .set("title","Plot2D demo"  );
var myCanvas = window.createCanvas()
    .set("background", "#eeeeee");
var root = myCanvas.createGroup();
var myGroup = root.createChild("group");
canvas.plot2D.line(myGroup,[20,20],[50,100]);
canvas.plot2D.line(myGroup,[20,180],[180,20],'#ee0000')
    .setStrokeLineWidth(2);
Plot2D.line.png

hzLine

Parameters: (group, from, length, color="#0")

Plots an horizontal line as <group>'s child.

  • from as [x,y] in pixels.
  • length in pixels.
  • color optional as [r,g,b] or "#rrggbb". Black by default.

vtLine

Parameters: (group, from, length, color="#0")

Plots a vertical line as <group>'s child.

  • from as [x,y] in pixels.
  • length in pixels.
  • color optional as [r,g,b] or "#rrggbb". Black by default.

dashedLine

Parameters: (group, from, to, dash=8, color="#0")

Plots a vertical line as <group>'s child.

  • from as [x,y] in pixels.
  • to as [x,y] in pixels.
  • dash optional dash&space lengths in pixels, 8 pixels by default.
  • color optional as [r,g,b] or "#rrggbb". Black by default.
example Screenshot
var window = canvas.Window.new([200,200],"dialog").set("title","Plot2D demo"  );
var myCanvas = window.createCanvas().set("background", "#eeeeee");
var root = myCanvas.createGroup();
var myGroup = root.createChild("group");
canvas.plot2D.dashedLine(myGroup,[20,20],[150,120]).setStrokeLineWidth(2);
var (red,blue) = ['#ee0000', [0,0,1] ];
canvas.plot2D.hzLine(myGroup,[30,40],120,red);
canvas.plot2D.vtLine(myGroup,[120,180],-110,blue);
Plot2D.dashedLine example.png

rectangle

Parameters: (group, size ,origin=nil, color="#0", fill=nil, rounded=nil)

Plots a rectangle as <group>'s child.

  • size as [width,height] in pixels.
  • origin optional as [x,y] in pixels, [0,0] by default.
  • color optional border color as [r,g,b] or "#rrggbb" or nil (for no border). Black by default.
  • fill optional fill color as [r,g,b] or "#rrggbb", No filled by default.
  • rounded optional corner radius in pixels, Not rounded by default.

grid

Parameters: (group, size, dx, dy, origin=nil, color="#0", border=1)

Plots a grid as <group>'s child.

  • size as [width,height] in pixels.
  • dx tiles width in pixels.
  • dy tiles height in pixels.
  • color optional grid color as [r,g,b] or "#rrggbb". Black by default.
  • origin optional as [x,y] in pixels, [0,0] by default.
  • border optional as boolean, True by default.
example Screenshot
var window = canvas.Window.new([200,200],"dialog").set("title","Plot2D demo"  );
var myCanvas = window.createCanvas().set("background", "#eeeeee");
var root = myCanvas.createGroup();
var myGroup = root.createChild("group");
var (red,blue,grey) = ['#ee0000', [0,0,1], [.8,.8,.8] ];
  ## Note: to eventually handle an element, you must assign a variable:
var myRect = canvas.plot2D.rectangle(myGroup,[40,160],[15,20],red,grey,10);
myRect.setStrokeLineWidth(3);
canvas.plot2D.grid(myGroup,[120,100],20,25,[70,30],blue).setRotation(30*D2R);
Plot2D.rectangle and grid.png

text

parameters: (group, text, origin=nil, size=nil, color="#0", align="left-baseline")

Plots a text as <group>'s child.

  • text the text itself as string.
  • origin optional as [x,y] in pixels, [0,0] by default.
  • size optional font size and aspect as [<size-px>,<height/width>]. [11,1] by default.
  • color optional font color as [r,g,b] or "#rrggbb". Black by default.
  • align optional origin reference. "left-baseline" by default.

polyline

parameters: (group, xSet, ySet, color="#0", symmetrical=' ')

Plots a polyLine as <group>'s child.

  • xSet as [x0,...,xn] in pixels.
  • ySet as [y0,...,yn] in pixels.
  • color optional grid color as [r,g,b] or "#rrggbb". Black by default.
  • symmetrical optional string, may be 'x', 'y', 'xy' or 'yx'. Non symmetrical by default.
example Screenshot
Note  This assumes that you already have a top-level root group set up, and his group child named myGroup.
var (red,blue,green,orange) = ['#ee0000', [0,0,1], [0,0.8,0], '#ea9a32' ];
canvas.plot2D.polyline(myGroup,[150,181,194,157,199],[52,20,64,28,36]);
   ## 3 vertices with default values:
canvas.plot2D.polyline(myGroup,[20,30,70],[15,55,65]);
canvas.plot2D.text(myGroup,'defaults',[75,25]);
   ## 3 vertices with symmetrical = 'x':
canvas.plot2D.polyline(myGroup,[20,30,70],[130,170,180],blue,"x");
canvas.plot2D.text(myGroup,'Symmetrical="x"',[20,195],,blue);
   ## 3 vertices with symmetrical = 'y':
canvas.plot2D.polyline(myGroup,[150,160,200],[90,130,140],red,"y");
canvas.plot2D.text(myGroup,'Symmetrical="y"',[198,180],,red,'right-baseline');
   ## 3 vertices with symmetrical = 'xy':
canvas.plot2D.polyline(myGroup,[50,60,100],[100,140,150],green,"xy");
canvas.plot2D.text(myGroup,'Symmetrical="xy"',[55,75],,green);
   ## 3 vertices with symmetrical = 'yx':
canvas.plot2D.polyline(myGroup,[100,110,150],[50,90,100],orange,"yx");
canvas.plot2D.text(myGroup,'Symmetrical="yx"',[12,125],,orange);
plot2D.polyline example

graphic

parameters: (group, ySet, dx=nil, origin=nil, color="#0"

Plots the curve sampled in <ySet> with a resolution of <dx>.

  • ySet as [y0,...,yn] in pixels.
  • dx optional curve resolution in pixels. 1 px by default.
  • origin optional as [x,y] in pixels, [0,0] by default.
  • color optional grid color as [r,g,b] or "#rrggbb". Black by default.
example Screenshot
Note  This assumes that you already have a top-level root group set up, and his group child named myGroup.
  var (red,blue,green,orange) = ['#ee0000', [0,0,1], [0,0.8,0], '#ea9a32' ];
  var yValues = [];
  for(var i=0;i<460;i+=4) append(yValues, 30*math.sin(i*D2R));
  canvas.plot2D.hzLine(myGroup, [10,100],175,blue);
  canvas.plot2D.vtLine(myGroup, [15,180],-175,blue);
  canvas.plot2D.graphic(myGroup, yValues,,[15,100],red);
Plot2D,graphic.png

Movement helpers

flipX

parameters: (elem, Xaxis=0) 

Flips horizontally the element.

  • elem element to be flipped.
  • Xaxis optional abscissa of the symmetry axis . If 0 (default) element flips in-place.

flipY

parameters: (elem, Yaxis=0) 

Flips vertically the element.

  • elem element to be flipped.
  • Yaxis optional ordenate of the symmetry axis . If 0 (default) element flips in-place.

rotate180

parameters: (elem, center=nil) 

Rotates the element 180 deg around center.

  • elem element to be rotated.
  • center optional as [Cx,Cy] in pixels. Rotates in-place by default.

alignX

parameters: (elem, ref, alignment) 

Aligns the element, moving it horizontaly to ref.

  • elem element to be moved.
  • ref reference may be an integer or another element.
  • alignment as string: may be 'left-left', 'left-center', 'left-right',

'center-left', 'center-center', 'center-right', 'right-left', 'right-center', or 'right-right'.
If ref is a single number, the 2nd word is ignored.


alignY

parameters: (elem, ref, alignment) 

Aligns the element, moving it vertically to ref.

  • elem element to be moved.
  • ref reference may be an integer or another element.
  • alignment as string: may be top-top', 'top-center', 'top-bottom',

'center-top', 'center-center', 'center-bottom', 'bottom-top', 'bottom-center', or 'bottom-bottom'.
Text elements also accept 'baseline' as reference.
If ref is a single number, the 2nd word is ignored.

Resize helpers

stretchX

parameters: (elem, factor, ref='left') 

Stretchs horizontally the element .

  • elem element to be stretched.
  • factor the <new-width>/<old-width> ratio.
  • ref optional: the relative point to keep inplace. May be 'left' (default),'center' or 'right'.

stretchY

parameters: (elem,factor,ref='top') 

Stretchs vertically the element .

  • elem element to be stretched.
  • factor tthe <new-height>/<old-height> ratio.
  • ref optional: the relative point to keep in-place. May be 'top' (default),'center' or 'bottom'.

resize

parameters: (elem,factors,ref='left-top') 

Resizes vertically the element along both X and Y axis.

  • elem element to be resized.
  • factors as [Xfactor, Yfactor].
  • ref optional: the relative point to keep in-place, as string. May be left-top', 'left-center', 'left-bottom',

'center-top', 'center-center', 'center-bottom', 'right-top', 'right-center', or 'right-bottom'.

Behind the scenes

Let's see in detail the elements Canvas.
Open the Interactive Nasal REPL interpreter and execute (you can copy&paste, then Enter:

var window = canvas.Window.new([300,200],"dialog").set("title","Plot2D demo"  );
var myCanvas = window.createCanvas().set("background", "#eeeeee");
var root = myCanvas.createGroup();
var myGroup = root.createChild("group");

We have our new canvas, ready to play with.

At the >>> prompt type:

var arrow = canvas.plot2D.polyline(myGroup,[90,120,10],[20,30,30],'#0',"y");

Do not forget the Enter.

My Arrow.png

You should have something like this:

Let's get closer to see some hidden stuff:

Arrow.gif


Our arrow has (like any other element) its own intrinsic coordinate system.

Internal Coordinates

Typing:

arrow.getBoundingBox();

you get [9.5,19.5, 120.5,40.5] which are the values for [Xmin,Ymin, Xmax,Ymax].

The virtual points (the red flashing ones) are usually named as (from 1 to 9):

'left-top'     'center-top'     'right-top'
'left-center'  'center-center'  'right-center'
'left-bottom'  'center-bottom'  'right-bottom' Is nothing other than a convenient way to refer to (Xmin,Ymin), (xXmin+Xnax/2,Ymin), etc.

Plot2D (and Canvas API) uses such nomenclature.
Let's apply a translation:

arrow.setTranslation(150, 80);
Translated arrow

The blue axis and labels are showing the ( u, v ) absolute coodinate system.
Note that the translated arrow has brought with him his intrinsic coordenate system and his BoundingBox remains unchanged.
Calling the getTranslation() we get [Tx, Ty] (In our case [150, 80] ).
All points of the element meet the following equations::

u = Tx + x
v = Ty + y

In a similar way, scaling works. Type:

arrow.setTranslation(0,0);
arrow.setScale(2,4);
arrow.getScale();

you get [2,4] which are the values for [Sx, Sy].

Scaled arrow

Again, the BoundingBox and the intrinsic coordenate system remains unchanged.

Fundamental Equations

Now the general case, applying both Translation and Scaling:

arrow.setTranslation(150,80);
arrow.setScale(2,4);
Translated and scaled arrow


The Fundamental Equations:

u = Tx + x * Sx
v = Ty + y * Sy
                            and his reciprocals:
Tx =  u - x * Sx
Ty =  v - y * Sy

Plot2D makes extensive use of these equations.