Add marker style and update drawing step

This commit is contained in:
linarphy 2024-01-25 16:26:48 +01:00
parent 3aaa944986
commit 3b9242e287
2 changed files with 233 additions and 90 deletions

View file

@ -197,25 +197,42 @@ class Axes
}
/**
* plot y versus x as lines
* plot y versus x as line
*
* @param 1darray<Number> x x data
* @param 1darray<Number> y y data
* @param object linestyle Object defining a style for a line. The
* structure of the object should be:
* {
* color: color
* style: style
* }
* where color is a string containing
* "rgb(x,y,z)", "#abcdef" or a name of
* a color, and style is "solid", "dotted",
* "dashdot" or "dashed". Default value is
* color = "black" and style = "solid"
* @param String linestyle style of the line (can be "solid",
* "dotted", "dashdot", "dashed" or ""
* for no line)
* @param String linecolor color of the line (can be "#abcdef",
* "rgb(x,y,z)" or a name of a color.
* @param String markerstyle style of the marker used for each
* point (can be "circle", "point",
* "small", "cross" or "" for no
* marker)
* @param String markercolor color of the marker (same
* definition than linecolor)
* @param Number markersize size of the marker
*/
plot(x, y, linestyle = {color: "black", style: "solid"})
plot(
x ,
y ,
linestyle = 'solid' ,
linecolor = 'black' ,
markerstyle = 'circle',
markercolor = 'black' ,
markersize = 5 ,
)
{
let line = new Line(x, y, linestyle);
let line = new Line(
x ,
y ,
linestyle = linestyle ,
linecolor = linecolor ,
markerstyle = markerstyle,
markercolor = markercolor,
markersize = markersize ,
);
this.lines.push(line);
}
@ -223,9 +240,9 @@ class Axes
* render the axes to the canvas
*
* @param ctx CanvasRenderingContext2D Context of the canvas
* @param window 2darray<Number> Window where to draw the canvas
* @param view 2darray<Number> Window where to draw the canvas
*/
draw(ctx, window)
draw(ctx, view)
{
const x_min = get_ext_array(
this.lines.map(
@ -263,20 +280,20 @@ class Axes
)
)
);
let n_window = this.title.draw(
let n_view = this.title.draw(
ctx ,
window,
view,
);
n_window = this.axis.draw(
n_view = this.axis.draw(
ctx ,
n_window,
n_view,
[ [x_min, y_min], [x_max, y_max] ],
);
for (const index_line in this.lines)
{
this.lines[index_line].draw(
ctx ,
n_window,
n_view,
[
[x_min, y_min],
[x_max, y_max],
@ -287,9 +304,9 @@ class Axes
ctx.strokeStyle = 'black';
ctx.setLineDash([]);
ctx.strokeRect(
n_window[0][0], n_window[0][1],
n_window[1][0] - n_window[0][0],
n_window[1][1] - n_window[0][1],
n_view[0][0], n_view[0][1],
n_view[1][0] - n_view[0][0],
n_view[1][1] - n_view[0][1],
);
}
@ -317,52 +334,62 @@ class Axes
*
* @property 1darray<float> x xdata
* @property 1darray<float> y ydata
* @property object linestyle Object defining a style for a line. The
* structure of the object should be:
* {
* color: color
* style: style
* }
* where color is a string containing
* "rgb(x,y,z)", "#abcdef" or a name of
* a color, and style is "solid", "dotted",
* "dashdot" or "dashed". Default value is
* color = "black" and style = "solid"
* @property String linestyle style of the line (can be "solid",
* "dotted", "dashdot", "dashed" or ""
* for no line)
* @property String linecolor color of the line (can be "#abcdef",
* "rgb(x,y,z)" or a name of a color.
* @property String markerstyle style of the marker used for each
* point (can be "circle", "point",
* "small", "cross" or "" for no
* marker)
* @property String markercolor color of the marker (same
* definition than linecolor)
* @property Number markersize size of the marker
*/
class Line
{
/**
* @param 1darray<float> x xdata
* @param 1darray<float> y ydata
* @param object linestyle Object defining a style for a line. The
* structure of the object should be:
* {
* color: color
* style: style
* }
* where color is a string containing
* "rgb(x,y,z)", "#abcdef" or a name of
* a color, and style is "solid", "dotted",
* "dashdot" or "dashed". Default value is
* color = "black" and style = "solid"
* @param string linestyle style of the line (can be "solid",
* "dotted", "dashdot", "dashed" or ""
* for no line)
* @param string linecolor color of the line (can be "#abcdef",
* "rgb(x,y,z)" or a name of a color.
* @param string markerstyle style of the marker used for each
* point (can be "circle", "point",
* "small", "cross" or "" for no
* marker)
* @param string markercolor color of the marker (same
* definition than linecolor)
* @param Number markersize size of the marker
*/
constructor(
x ,
y ,
linestyle = {color: "black", style: "solid"},
linestyle = 'solid' ,
linecolor = 'black' ,
markerstyle = 'circle' ,
markercolor = 'black' ,
markersize = 5 ,
)
{
this.x = x ;
this.y = y ;
this.linestyle = linestyle ;
this.linecolor = linecolor ;
this.markerstyle = markerstyle;
this.markercolor = markercolor;
this.markersize = markersize ;
}
/**
* draw the line in the box coordinate
*
* @param CanvasRenderingContext2d ctx Context of the canvas
* @param 2dlist<int> box Box where to draw the line
* @param 2dlist<float> view Scale of the box (link value <->
* @param CanvasRenderingContext2d ctx context of the canvas
* @param 2dlist<int> box box where to draw the line
* @param 2dlist<float> view scale of the box (link value <->
* coordinate
*/
draw(ctx, box, view)
@ -390,19 +417,52 @@ class Line
);
}
);
if (this.linestyle.style === 'solid')
if (this.linestyle != '')
{
this.drawLine(
ctx,
x_coordinates,
y_coordinates,
);
}
if (this.markerstyle != '')
{
this.drawPoints(
ctx ,
x_coordinates,
y_coordinates,
);
}
}
/**
* draw a line in the given context at the given positions
*
* @param CanvasRenderingContext2d ctx context of the canvas
* @param 1darray<Number> x_coordinates X coordinates of the point
* @param 1darray<Number> y_coordinates Y coordinates of the point
*/
drawLine(ctx, x_coordinates, y_coordinates)
{
ctx.beginPath();
ctx.strokeStyle = this.linecolor;
ctx.moveTo(
x_coordinates[0],
y_coordinates[0],
);
if (this.linestyle === 'solid')
{
ctx.setLineDash([]);
}
else if (this.linestyle.style === 'dashed')
else if (this.linestyle === 'dashed')
{
ctx.setLineDash([15, 5]);
}
else if (this.linestyle.style === 'dotted')
else if (this.linestyle === 'dotted')
{
ctx.setLineDash([2,2]);
}
else if (this.linestyle.style === 'dashdot')
else if (this.linestyle === 'dashdot')
{
ctx.setLineDash([15,2,2,2]);
}
@ -410,21 +470,102 @@ class Line
{
throw _('the style of the line is not correctly defined');
}
ctx.strokeStyle = this.linestyle.color;
ctx.beginPath();
ctx.moveTo(
x_coordinates[0],
y_coordinates[0]
);
for (const index in x_coordinates)
{
ctx.lineTo(
x_coordinates[index],
y_coordinates[index]
y_coordinates[index],
);
}
ctx.stroke();
}
/**
* draw points in the given context at the given positions
*
* @param CanvasRenderingContext2d ctx context of the canvas
* @param 1darray<Number> x_coordinates x coordinate of the point
* @param 1darray<Number> y_coordinates y coordinate of the point
*/
drawPoints(ctx, x_coordinates, y_coordinates)
{
for (const index in x_coordinates)
{
let x = x_coordinates[index];
let y = y_coordinates[index];
ctx.beginPath();
if (this.markerstyle == 'circle')
{
ctx.fillStyle = this.markercolor;
ctx.ellipse(
x ,
y ,
this.markersize,
this.markersize,
0 ,
0 ,
2*Math.PI ,
);
ctx.fill();
}
else if (this.markerstyle == 'point')
{
ctx.fillStyle = this.markercolor;
ctx.ellipse(
x ,
y ,
0.5*this.markersize,
0.5*this.markersize,
0 ,
0 ,
2*Math.PI ,
);
ctx.fill();
}
else if (this.markerstyle == 'small')
{
ctx.fillStyle = this.markercolor;
ctx.ellipse(
x ,
y ,
0.1*this.markersize,
0.1*this.markersize,
0 ,
0 ,
2*Math.PI ,
);
ctx.fill();
}
else if (this.markerstyle == 'cross')
{
ctx.setLineDash([]);
ctx.strokeStyle = this.markercolor;
ctx.moveTo(
x - this.markersize,
y - this.markersize,
);
ctx.lineTo(
x + this.markersize,
y + this.markersize,
);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(
x + this.markersize,
y - this.markersize,
);
ctx.lineTo(
x - this.markersize,
y + this.markersize,
);
ctx.stroke();
}
else
{
throw _('the style of the marker is not correctly defined');
}
}
}
}
/**
@ -494,27 +635,29 @@ class Title
* draw the title in the given windows
*
* @param ctx CanvasRenderingContext2D Context of the canvas
* @param window int<array> Window where to write the title on
* @param box int<array> Window where to write the title on
*
* @return plot_windows int<array> New windows for the plot
* @return plot_box int<array> New windows for the plot
*/
draw(ctx, window)
draw(ctx, box)
{
ctx.font = this.font.toString();
ctx.fillStyle = 'black';
ctx.strokeStyle = 'black';
let width = ctx.measureText(this.content).width;
if (width > window[1][0] - window[0][0] + 2 * this.margin)
if (width > box[1][0] - box[0][0] + 2 * this.margin)
{
ctx.fillText(
this.content ,
window[0][0] ,
box[0][0] ,
this.font.size + this.margin,
window[1][0] - window[0][0],
box[1][0] - box[0][0],
);
}
else
{
let text_position = window[0][0] + (
window[1][0] - window[0][0] - width
let text_position = box[0][0] + (
box[1][0] - box[0][0] - width
) / 2
ctx.fillText(
this.content,
@ -524,10 +667,10 @@ class Title
}
return [
[
window[0][0],
window[0][1] + this.font.size + 2 * this.margin,
box[0][0],
box[0][1] + this.font.size + 2 * this.margin,
],
[window[1][0], window[1][1]],
[box[1][0], box[1][1]],
];
}
}
@ -574,6 +717,8 @@ class Axis
*/
draw(ctx, window, view)
{
ctx.strokeStyle = 'black';
ctx.fillStyle = 'black';
let index = 0;
let start_pos = window[0][1];
let padding = (
@ -588,7 +733,6 @@ class Axis
view[1][1] - index * step
).toString().slice(0,3);
let text_position = current_y + this.text_height / 2
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.moveTo(
window[0][0] + this.margin + width,

15
test.js
View file

@ -5,10 +5,9 @@ manager.add_canvas(1000, 500);
manager.add_canvas(1000, 500).figure.add_axes().plot(
[0,1,2,3,4,5] ,
[0,1,4,9,16,25] ,
{
color: 'rgb(255,0,0)',
style: 'dashed'
}
linestyle = 'dashed' ,
linecolor = 'rgb(255,0,0)',
markerstyle = 'cross' ,
);
manager.list_canvas[0].figure.list_axes[0].title = 'squared and x2';
manager.list_canvas[0].figure.list_axes[0].plot(
@ -18,10 +17,10 @@ manager.list_canvas[0].figure.list_axes[0].plot(
manager.list_canvas[0].figure.add_axes().plot(
[2,4,6,8,10] ,
[1/2,1/4,1/6,1/8,1/10] ,
{
color: 'rgb(0,255,0)',
style: 'dashdot'
}
linestyle = 'dashdot' ,
linecolor = 'rgb(0,255,0)',
markerstyle = 'circle' ,
markercolor = 'rgb(0,0,255)',
);
manager.list_canvas[0].figure.list_axes[0].title = '1/x';
manager.draw();