Canvas draw library: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
mNo edit summary
No edit summary
Line 1: Line 1:
{{Note|Canvas draw is currently work in progress. You can test and improve it by downloading the [[Addons|CanvasDrawDev add-on]]. }}
{{tip|The basic canvas.draw library was merged into FGDATA in 03/2020 so it available by default now. }}
{{tip| A merge of canvas.draw library into FGDATA as optional module has been requested 02/2020. Please check [[Nasal Initialization]] for information on how to activate the module ''canvas_draw''. }}


{{Canvas Navigation}}
{{Canvas Navigation}}
= CanvasDrawDev add-on =
= Introduction =
{{Note|As of 12/2018, the add-on is largely based on GPL'ed [[How to manipulate Canvas elements|plot2D code]] written originally by {{Usr|Rodolfo}} (rleibner on the forums) as part of the [[Spoken GCA]], [[PAR instrument]] and [[Oscilloscope addon|Oscilloscope]] add-ons.}}
 
The purpose of this add-on is to develop and grow a nasal library of canvas drawing
functions. This lib should eventually be moved to FGDATA/Nasal once it has
reached a sufficient quality.
 
== Motivation ==
There are basically two ways to populate a canvas, loading an SVG file which
There are basically two ways to populate a canvas, loading an SVG file which
has been created with some tool like inkscape, or by writing a nasal program
has been created with some tool like inkscape, or by writing a nasal program
Line 17: Line 9:
Both ways are valid and have their pros and cons.
Both ways are valid and have their pros and cons.


The canvas API is quite limited (at the time of writing), only a few basic  
The canvas API was quite limited, only a few basic commands were available, so canvas.draw library was created
commands are available. There should be more drawing commands to allow rapid
to provide more drawing commands.
development of canvas instruments for other aircraft.
 
{{Note|Development of this library started in 12/2018 as a separate [[Addons|CanvasDrawDev add-on]] and is largely based on GPL'ed [[How to manipulate Canvas elements|plot2D code]] written originally by {{Usr|Rodolfo}}
(rleibner on the forums) as part of the [[Spoken GCA]], [[PAR instrument]] and [[Oscilloscope addon|Oscilloscope]] add-ons.}}


== Goals ==
== Goals ==
Line 25: Line 19:
* Provide complex drawing commands needed for e.g. compass rose or speed tapes  
* Provide complex drawing commands needed for e.g. compass rose or speed tapes  
* Provide easy to use styles  
* Provide easy to use styles  
* Support API versioning to allow later extensions of the library


= canvas.draw API =
= canvas.draw API =
{{Note|This API is subject to change without notice until it has been released with FG in FGDATA}}
== draw module ==
== draw module ==
All draw methods expect a canvas group element 'cgroup' as first parameter to draw on.  
{{note|All draw methods expect a canvas group element 'cgroup' as first parameter to draw on.}}


=== draw.colors ===
=== draw.colors ===
Line 282: Line 273:
Set length of subdivision marker in %marker_length
Set length of subdivision marker in %marker_length


== Modules ==
= References =
[[CompassRose]]
[[CompassRose]] is based on canvas draw.
{{Note|You can test, improve and play around with canvas.draw by downloading the [[Addons|CanvasDrawDev add-on]]. }}

Revision as of 08:24, 9 March 2020

Tip  The basic canvas.draw library was merged into FGDATA in 03/2020 so it available by default now.

Introduction

There are basically two ways to populate a canvas, loading an SVG file which has been created with some tool like inkscape, or by writing a nasal program that calls drawing functions of the canvas API.

Both ways are valid and have their pros and cons.

The canvas API was quite limited, only a few basic commands were available, so canvas.draw library was created to provide more drawing commands.

Note  Development of this library started in 12/2018 as a separate CanvasDrawDev add-on and is largely based on GPL'ed plot2D code written originally by Rodolfo

(rleibner on the forums) as part of the Spoken GCA, PAR instrument and Oscilloscope add-ons.

Goals

  • Make the code flexible and powerful so people will like to use it
  • Provide complex drawing commands needed for e.g. compass rose or speed tapes
  • Provide easy to use styles

canvas.draw API

draw module

Note  All draw methods expect a canvas group element 'cgroup' as first parameter to draw on.

draw.colors

A hash with some standard colors like white, black, red, green, blue, cyan, magenta, yellow, orange. Just in case you need them ;)

circle()

circle(cgroup, radius, center_x = nil, center_y = nil)

radius in pixel

center_x, center_y optional center of circle

ellipse()

ellipse(cgroup, radius, center_x = nil, center_y = nil)

radius_x, radius_y in pixel

center_x, center_y optional center of ellipse

arc()

circular marks

arc(cgroup, radius, center, from_deg = nil, to_deg = nil)

Draw an arc (part of a circle) with given radius around center. In the example image a red, green and blue arc are shown, nasal code below.

center center point of circle as vector [x,y]

from_deg, to_deg start and end of arc in degree of compass rose (0 = North, 90 = East, ...); defaults to 0, 360 (full circle)

    # [CX, CY] center point
    var start = -40;
    canvas.draw.arc(myGroup, radius, [CX, CY], start, start+190).setColor(COLORS["red"]);
    start += 90;
    canvas.draw.arc(myGroup, radius, [CX, CY], start, start+270).setColor(COLORS["green"]);
    start += 90;
    canvas.draw.arc(myGroup, radius, [CX, CY], start, start+190).setColor(COLORS["blue"]);

rectange()

rectangle(cgroup, width, height, x = 0, y = 0, rounded = nil)

width, height dimensions in pixels

x, y top-left corner of rectangle

rounded optional radius of corners in pixel

square()

square(cgroup, length, center_x = 0, center_y = 0, cfg = nil)

shorthand for rectangle with width = height = length

deltoid()

Canvas-draw-shapes01.png

deltoid (cgroup, dx, dy1, dy2, x = 0, y = 0)

Deltoid draws a kite (dy1 > 0 and dy2 > 0) or a arrow head (dy2 < 0).

dx width

dy1 height of "upper" triangle

dy2 height of "lower" triangle, < 0 draws an arrow head

x, y position of tip

    var dx = 40;
    #rhombus draws around a center point while deltoid uses x,y for tip point
    shapes["rhombus1"] = canvas.draw.rhombus(group, dx, 2*dx, 5 + dx/2, CY)
        .setColor(COLORS["cyan"]);

    # width = 40, height = 25 + 50;
    shapes["deltoid1"] = canvas.draw.deltoid(group, dx, 25, 50, 2*dx, CY)
        .setColor(COLORS["magenta"]);

    # y2 < 0 results in arrow head
    canvas.draw.deltoid(group, dx, 2*dx, -dx, 4*dx, CY)
        .setColor(COLORS["yellow"]);

    # y2 = 0 results in triangle
    canvas.draw.deltoid(group, dx, 2*dx, 0, 6*dx, CY)
        .setColor(COLORS["green"]);

    # y2 < 0 and |y2| > y1 results in arrowhead with tip above baseline
    canvas.draw.deltoid(group, dx, 1.5*dx, -2.5*dx, 8*dx, CY)
        .setColor(COLORS["red"]);

rhombus() / diamond()

rhombus: func(cgroup, dx, dy, center_x = 0, center_y = 0)

draws a diamond around [center_x, center_y] (first element from left in sample image above)

dx width

dy height


grid()

Canvas-draw-grids01.png

Draw horizontal and verical lines. Two signatures are available

1) (cgroup, [sizeX, sizeY], dx, dy, border = 1)

2) (cgroup, nx, ny, dx, dy, border = 1)

size [width, height] of grid in pixels.

nx, ny number of lines in x/y direction

dx, dy distance between lines in pixels.

border optional boolean, draw lines at sizeX and sizeY, true by default.

    var group = myRoot.createChild("group", "grid_scales");
    #-- grid test --
    canvas.draw.grid(group, [62, 55], 10, 10, 0).setTranslation(10, 100);
    canvas.draw.grid(group, [62, 55], 10, 10, 1).setTranslation(100, 100);
    canvas.draw.grid(group, 4, 4, 20, 10, 0).setTranslation(10, 200);
    canvas.draw.grid(group, 4, 4, 20, 10, 1).setTranslation(100, 200);

Marks

Marks can be used to create scales / gauges.

marksLinear()

linear marks (horizontal)
linear marks (vertical)

marksLinear(cgroup, orientation, num_marks, interval, style)

Draw marks for a linear scale on a canvas group, e.g. speed tape. Mark lines are draws perpendicular to baseline.

orientation of baseline, "up", "down" (="vertical"), "left", "right" (="horizontal"), only first character is evaluated (u,d,v,l,r,h).

num_marks number of marks to draw

interval distance between marks (pixel)

style marksStyle hash with more parameters

    #-- marks for linear scales --
    var group = myRoot.createChild("group", "marks");
    var style = canvas.draw.marksStyle.new()
        .setBaseline(1)
        .setMarkLength(0.8)     # 0.8 * interval
        .setSubdivisions(2);
    
    canvas.draw.marksLinear(group, "right", 5, 30, style).setTranslation(CX, 150)
        .setColor(COLORS["green"]);
    
    style.setSubdivisions(1);
    style.setMarkOffset(style.MARK_LEFT); # left/up
    canvas.draw.marksLinear(group, "v", 5, 20, style).setTranslation(50, CY)
        .setColor(COLORS["red"]);
    canvas.draw.marksLinear(group, "h", 4, 20, style).setTranslation(CX, 30)
        .setColor(COLORS["red"]);
    style.setMarkOffset(style.MARK_CENTER); #center
    canvas.draw.marksLinear(group, "down", 5, 20, style).setTranslation(100, CY)
        .setColor(COLORS["green"]);
    canvas.draw.marksLinear(group, "left", 4, 20, style).setTranslation(CX, 70)
        .setColor(COLORS["green"]);
    style.setMarkOffset(style.MARK_RIGHT); #right / down
    canvas.draw.marksLinear(group, "up", 5, 20, style).setTranslation(150, CY)
        .setColor(COLORS["blue"]);
    canvas.draw.marksLinear(group, "r", 4, 20, style).setTranslation(CX, 110)
        .setColor(COLORS["blue"]);

marksCircular()

circular marks

marksCircular(cgroup, radius, interval, phi_start = 0, phi_stop = 360, style = nil)

draw marks along an arc or circle of given radius

radius of baseline (circle)

interval distance of marks in degree

phi_start position of first mark in degree (default 0 = north)

phi_stop position of last mark in degree (default 360)

    #-- marks on arc / circle --
    style.setMarkLength(0.1);
    style.setMarkOffset(style.MARK_IN); # pointing to center
    style.setSubdivisions(2);
    style.setBaseline(1);
    var radius = 150;
    var interval = 30;
    canvas.draw.marksCircular(group, radius, interval, 30, 120, style)
        .setTranslation(CX,CY);

    style.setMarkOffset(style.MARK_OUT); # pointing outside
    style.setSubdivisions(1);
    radius = 90;
    interval = 10;
    canvas.draw.marksCircular(group, radius, interval, 0, 360, style)
        .setTranslation(CX,CY)
        .setColor(COLORS["cyan"]);

draw.style

Base class for styles.

draw.marksStyle

Parameter hash for drawing marks (see above).

new()

Create a new style instance.

var myMarkStyle = canvas.draw.marksStyle.new()

setMarkLength()

Set length of marker in %interval or %radius

setMarkOffset()

Set alignment of markers.

You can use marksStyle.MARK_LEFT marks left of vertical baseline

MARK_UP marks above horizontal baseline

MARK_CENTER marks centered on baseline

MARK_RIGHT marks right of vertical baseline

MARK_DOWN marks below horizontal baseline

var myMarkStyle = canvas.draw.marksStyle.new()
myMarkStyle.setMarkOffset(myMarkStyle.MARK_LEFT);

setMarkWidth()

Set line width in pixel.

setSubdivisions()

Set number of subdivisions (default = 0).

setSubdivisionLength()

Set length of subdivision marker in %marker_length

References

CompassRose is based on canvas draw.

Note  You can test, improve and play around with canvas.draw by downloading the CanvasDrawDev add-on.