-
Notifications
You must be signed in to change notification settings - Fork 6
API Reference
Instantiate this whole XY-plotter module. You can override the default configuration by specifying an opts
object as seen below.
const plotter = require('xy-plotter')()
const plotter = require('xy-plotter')({
width: 310, // default is 310 mm
height: 380, // default is 380 mm
pen_positions: {
up: 0, // default is 0 degree
down: 30 // default is 30 degree
},
decimals: 2 // default is 2 decimals
})
Return the width of the plotter's drawing area. Default is 310 mm.
const plotter = require('xy-plotter')()
console.log(plotter.width) // 310
Return the height of the plotter's drawing area. Default is 380 mm.
const plotter = require('xy-plotter')()
console.log(plotter.height) // 380
Return an object containing the actual configuration of the plotter.
const plotter = require('xy-plotter')({ decimals : 4 })
console.log(plotter.config)
/* {
width: 310,
height: 380,
pen_positions: {
up: 0,
down: 90
},
decimals: 4
} */
Return an object containing the default configuration of the plotter.
const plotter = require('xy-plotter')({ decimals : 4 })
console.log(plotter.defaultConfig)
/* {
width: 310,
height: 380,
pen_positions: {
up: 0,
down: 30
},
decimals: 2
} */
Each plotter
submodule (plotter.Job
, plotter.Turtle
, plotter.Serial
, etc) exposes a Tiny-Emitter instance, and can be used to subscribe/unsubscribe from events emitted by this submodule, or emit custom events.
Instantiate a new job
with the name jobName
.
This abstraction is from far the more important of the whole module, as it will handle all the drawing API and the commands buffer.
It is by design very similar to the Processing API.
const job = plotter.Job('my-awesome-drawing')
Return the name of the job
.
const job = plotter.Job('my-awesome-drawing')
console.log(job.name) // my-awesome-drawing
Return a copy of the internal commands buffer array of the job
.
const job = plotter.Job('my-awesome-drawing')
let commands = job.buffer
console.log('this job has' + commands.length + 'commands !')
Set the speed movement of the plotter. By default the firmware implements a non-linear speed curve to avoid position shifting, but some jobs will require a more fine tuned speed.
speedPercent
needs to be between 0
and 1
.
const job = plotter.Job('my-awesome-drawing')
job.setSpeed(0.1) // veeeery slooow
job.setSpeed(1) // blazing fast, and quite dangerous
Here is a benchmark describing some real world values with different speed settings :
speedPercent |
real world speed |
---|---|
0.1 | 10.86 mm/s |
0.2 | 11.88 mm/s |
0.3 | 13.57 mm/s |
0.4 | 15.2 mm/s |
0.5 | 17.27 mm/s |
0.6 | 21.11 mm/s |
0.7 | 25.33 mm/s |
0.8 | 31.67 mm/s |
0.9 | 47.5 mm/s |
1.0 | 76 mm/s |
By comparison, the default non-linear speed varies between 10.56 mm/s
and 38 mm/s
.
I encountered during some heavy tests big position shifting when using the default non-linear speed. Setting a linear speed solved the problem.
Also note that the stepper motors tend to make less noise with a small linear speed.
Reset the speed of the plotter to its default non-linear behavior.
const job = plotter.Job('my-awesome-drawing')
job.resetSpeed()
Try to optimize job
commands buffer to reduce the time of drawing and improve the overall quality of it.
Default options will spatially sort the lines and remove all single points of a job.
Note that this method is to be called once the job.buffer
is ready, so just before job
's execution (ie via plotter.Serial
or plotter.Server
).
const job = plotter.Job('my-awesome-drawing')
// job commands
// ...
job.optimize({
sort: true, // spatial sort buffer
points: true, // remove points
startingPosition: [0, 0], // starting position for the spatial sort lookup
skip: ['S1', 'T'] // exclude custom commands from optimization
})
// ...
// job execution
Lift up the plotter's pen by moving its servo to plotter.pen_positions.up
degrees.
If force_motion
is set to true
, the plotter will attempt to lift its pen even if it considers it already lift up.
Note: the plotter begins by default with its pen lift up.
const job = plotter.Job('my-awesome-drawing')
job.pen_up()
job.move(100, 200)
job.pen_up(true) // just to be sure...
job.move(200, 200)
const job = plotter.Job('my-awesome-drawing')
job.pen_up()
.move(100, 200)
.pen_up(true) // just to be sure...
.move(200, 200)
Lower down the plotter's pen by moving its servo to plotter.pen_positions.down
degrees.
If force_motion
is set to true
, the plotter will attempt to lower its pen even if it considers it already lowered.
Note: the plotter begins by default with its pen lift up.
const job = plotter.Job('my-awesome-drawing')
job.pen_up().move(plotter.width / 2, plotter.height / 2)
job.pen_down().move(0, 0)
Set the position of the pen's servo to a specific position
value (in degrees). Useful for pressure related drawings.
const job = plotter.Job('my-awesome-drawing')
for (let a = 0, x = 0, y = 0; a < 90; a++) {
job.pen(a).move(x, y)
x += 10
y += 20
}
Move the plotter to the x, y
coordinates. All values are expressed in millimeters.
const job = plotter.Job('my-awesome-drawing')
job.move(100, 200)
Send the plotter to its 0, 0
home position, pen up.
const job = plotter.Job('my-awesome-drawing')
job.home()
Insert a wait instruction in the job
buffer. When reaching this instruction, the plotter.Serial()
will wait until you hit enter in your TTY. Useful if you want to change the pen or the paper in the middle of a job.
You can override the default waiting behavior by specifying a function returning a Promise object.
const job = plotter.Job('my-awesome-drawing')
// draw a first rectangle
job.rect(50, 50, 20, 20)
// wait until user resume the job
job.wait()
// draw a second rectangle with another pen
job.rect(55, 55, 20, 20)
const job = plotter.Job('my-awesome-drawing')
// draw a first rectangle
job.rect(50, 50, 20, 20)
// wait until the promise resolves
job.wait(() => {
return new Promise(resolve, reject) {
if (ok) resolve()
else reject()
})
})
// draw a second rectangle with another pen
job.rect(55, 55, 20, 20)
Draw the extreme limits of the plotter's drawable area.
const job = plotter.Job('my-awesome-drawing')
job.drawBoundaries()
Draw a point at the specified x, y
coordinates.
const job = plotter.Job('my-awesome-drawing')
const x = plotter.width / 2
const y = plotter.height / 2
for (let i = 0; i < 1000; i++) {
job.point(x + (Math.random() * 100), y + (Math.random() * 100))
}
Draw a line between the point x1, y1
and the point x2, y2
.
const job = plotter.Job('my-awesome-drawing')
job.line(0, 0, 50, 0)
Draw a triangle between the points x1, y1
, x2, y2
and x3, y3
.
const job = plotter.Job('my-awesome-drawing')
let a = {x: 100, y: 200}
let b = {x: 200, y: 200}
let c = {x: 100, y: 100}
job.triangle(a.x, a.y, b.x, b.y, c.x, c.y)
Draw a rectangle of dimensions width
*height
at the coordinates x, y
from its bottom top left corner.
const job = plotter.Job('my-awesome-drawing');
job.rect(plotter.width / 2, plotter.height / 2, 100, 200)
Draw a quadrilateral between the points x1, y1
, x2, y2
, x3, y3
and x4, y4
.
const job = plotter.Job('my-awesome-drawing')
let points = []
for (let i = 0; i < 4; i++) {
let point = {
x : Math.random() * plotter.width,
y : Math.random() * plotter.height
};
points.push(point)
}
job.quad(points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y, points[3].x, points[3].y)
Draw a closed polygon given an array of point
, where point
is an object with a x
and a y
key.
const job = plotter.Job('my-awesome-drawing')
let points = []
for (let i = 0; i < 100; i++) {
const point = [Math.random() * plotter.width, Math.random() * plotter.height]
points.push(point)
}
job.polygon(points)
Draw a circle of radius radius
at the coordinates centerX, centerY
. The optional parameter sides
allows to control the resolution of the circle.
const job = plotter.Job('my-awesome-drawing')
let x = plotter.width / 2
let y = plotter.height / 2
job.circle(x, y, 50)
job.circle(x, y, 50, 3) // this is in fact a triangle
Draw an ellipse of dimensions width
*height
at the coordinates centerX, centerY
. The optional parameter sides
allows to control the resolution of the ellipse.
const job = plotter.Job('my-awesome-drawing')
job.ellipse(10, 100, 50, 10)
job.ellipse(100, 10, 50, 10, 8) // an ellipse with 8 sides
Draw the given string
at the coordinates x, y
, x
being the left side of the text, and y
its baseline.
The default font file is CamBam Stick Font 3.
const job = plotter.Job('my-awesome-text')
job.text('hello world !', 100, 50, {
fontSize: 10, // height of the text in millimeters (default 10)
fontFile: 'path/to/myFont.otf' // support for WOFF, OTF, TTF via opentype.js
})
Draw the given SVG file. The optional transformations
object allows multiple manipulation of position, angle, scale and transformation origin. See the examples below for usage.
Note: the coordinates of the SVG will be interpreted as millimeters : a rectangle of 100px
by 200px
will be drawn as a rectangle of 100mm
by 200mm
.
const job = plotter.Job('my-awesome-drawing')
job.svg('heart.svg')
const job = plotter.Job('my-awesome-drawing')
job.svg('heart.svg', {
x: 100, // x coordinate
y: 200, // y coordinate
width: 200, // custom width
height: 300, // custom height
angle: 90, // angle in degrees
origin: [0.5, 1] // origin point of the transformation
})
The transformation.origin
object defines a point of coordinates between 0
and 1
, [0, 0]
beeing the top left corner and [1, 1]
the bottom right one.
Add the specified cmd
to the job
's buffer. Useful if you modify the plotter's firmware.
const job = plotter.Job('my-awesome-drawing')
let GCode = 'G28'
job.addToBuffer(GCode)
The data
event's callback is called whith a data
object when a new command is pushed to the job
's buffer.
{
cmd: 'cmd', // the pushed command
buffer: [...], // the current buffer
}
Instantiate a new turtle
with the name turtleName
.
This whole module is an alternative to the job
drawing API, using the famous Logo Turtle Graphics API.
You can learn more about the Turtle syntax and logic on this excellent website.
Note that this module is basically a layer on top of the job
module and exposes the same buffer
API, meaning that where modules like Serial
or Server
accept a job
as a parameter, turtle
can also be passed.
Also note that all turtle
methods (except getters) can be chained, allowing a syntax close to the original Logo API.
const turtle = plotter.Turtle('my-turtle', {
x: plotter.width / 2, // starting x position on the plotter
y: plotter.height / 2, // starting y position on the plotter
angle: 0, // starting angle in degrees
})
Return the name of the turtle
.
const turtle = plotter.Turtle('my-turtle')
console.log(turtle.name) // my-turtle
Return a copy of the internal ommands buffer array of the turtle
.
const turtle = plotter.Turtle('my-turtle')
let commands = turtle.buffer
console.log('this turtle has' + commands.length + 'commands !')
Get the current position of the turtle
as a {x, y}
coordinates object. This coordinates are absolute.
Note that this only return the current position during buffer building, not buffer execution, meaning that this is not designed to be used during the actual plotting.
const turtle = plotter.Turtle('my-turtle')
// ...
console.log(turtle.position) // [0, 0]
turtle.forward(10)
console.log(turtle.position) // [10, 0]
Get the current x
coordinate of the turtle
. This is a shorthand for turtle.position.x
Get the current y
coordinate of the turtle
. This is a shorthand for turtle.position.y
Get the current angle of the turtle
in degrees. Works like turtle.position
.
Reset the turtle
angle and position, leaving it as instanciated.
Note that this command calls turtle.up()
before moving it.
const turtle = plotter.Turtle('my-turtle', {
x: 0,
y: 0,
angle: 90,
}) // turtle is at [0, 0] with an angle of 90 degrees
// ...
// lots of moves
// ...
turtle.home() // turtle is now back at [0, 0] with an angle of 90 degrees
Lift up the pen, as described in job.pen_up()
.
const turtle = plotter.Turtle('my-turtle')
turtle.up()
.forward(10) // no drawing here
Lower down the pen, as described in job.pen_down()
.
const turtle = plotter.Turtle('my-turtle')
turtle.up()
.forward(10) // no drawing here...
.down()
.forward(10) // ...but not here
Make the turtle
move forward distance
millimeters.
const turtle = plotter.Turtle('my-turtle')
turtle.forward(100)
Make the turtle
move backward distance
millimeters.
const turtle = plotter.Turtle('my-turtle')
turtle.backward(100)
Shorthand for turtle.backward(distance)
.
Make the turtle
rotate left to alpha
degrees. This rotation is relative to the precedent angle.
const turtle = plotter.Turtle('my-turtle')
turtle.left(90)
Make the turtle
rotate right to alpha
degrees. This rotation is relative to the precedent angle.
const turtle = plotter.Turtle('my-turtle')
turtle.right(90)
Move the turtle
to the specified [x, y]
position. The coordinates are in a cartesian system relative to the turtle
original position (defined at its instanciation), with the X axis going right and the Y axis going up, the point [0, 0]
being the original position.
Note that this will conserve the turtle
's angle, meaning that if turtle.angle === 90
before turtle.setXY()
is called, the angle will still be 90
degrees after the call, no matter where the target position is.
const turtle = plotter.Turtle('my-turtle')
turtle.up()
.setXY(0, 0) // move the turtle at its original position
Repeat the given callback
n
times. This is mainly designed to keep consistency with the original Turtle Graphics API, and could easily be replaced by a basic for
loop.
const turtle = plotter.Turtle('my-turtle')
// draw a square of 100mm length by calling 4 times [forward(100), right(90)]
turtle.repeat(4, turtle => {
turtle.forward(100).right(90)
})
const turtle = plotter.Turtle('my-turtle')
turtle.repeat(100, (turtle, repcount) => {
turtle.forward(repcount).right(60)
})
Store a procedure
in the turtle
API, allowing later reference by calling turtle.procedureName()
. This allows parameters to be passed, see examples below.
procedureName
need to be a valid function name, and procedure
a valid callable function, otherwise turtle.to()
will throw an error.
Note that if a procedure with the same name has already been stored, it will be overwritten by the new one.
const turtle = plotter.Turtle('my-turtle')
// learn to the turtle how to draw a square of length 20
turtle.to('square', turtle => {
turtle.repeat(4, turtle => {
turtle
.forward(20)
.right(90)
})
})
turtle.square() // draw a square of length 20
const turtle = plotter.Turtle('my-turtle')
// learn to the turtle how to draw a square of variable length
turtle.to('square', (turtle, sideLength) => {
turtle.repeat(4, turtle => {
turtle
.forward(sideLength)
.right(90)
})
})
turtle.square(20) // draw a square of length 20
turtle.square(100) // draw a square of length 100
Delete a reference to a previously stored procedure.
const turtle = plotter.Turtle('my-turtle')
// store the 'square' procedure
turtle.to('square', turtle => {
turtle.repeat(4, turtle => { turtle.forward(20).right(90) })
})
turtle.square() // ok
turtle.forget('square')
turtle.square() // throw "TypeError: turtle.square is not a function"
The data
event's callback is called whith a data
object when a new command is pushed to the turtle
's buffer.
{
cmd: 'cmd', // the pushed command
buffer: [...], // the current buffer
}
Instantiate a serial
object on port
.
If options.verbose
and options.progressBar
are both set to true
, the progress bar will show the current command running on the plotter.
When setting options.disconnectOnJobEnd
to false
, you will need to call serial.disconnect()
at the end of the job.
const serial = plotter.Serial('/dev/tty.wchusbserial1410', {
baudRate: 115200, // baudrate of the plotter's firmware
verbose: false, // output running commands in the TTY
progressBar: true, // output job progress in the TTY
disconnectOnJobEnd: true // auto close the serial port at the end of a job
})
Return true
of false
depending on whether the serial port is open or not.
Note: during connection, the plotter is going home before handshaking, so you should test if serial.connected == true
before doing something hacky on the serial port.
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
serial.connect()
console.log(serial.connected) // true
serial.disconnect()
console.log(serial.connected) // false
Return true
of false
depending on whether the current serial communication is paused or not.
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
serial.pause()
console.log(serial.paused) // true
serial.resume()
console.log(serial.paused) // false
Send job
through the serial port specified in const serial = plotter.Serial(port, options)
. Return a Promise object resolved when job
is ended.
If streamed
is set to true
, switch the serial communication to a "realtime job streaming", where Serial
listens to changes in the job
internal buffer (see example below).
If the serial port has not been opened prior to this, automatically open the port by calling serial.connect()
When the job
is done, and if serial.options.disconnectOnJobEnd
is set to true
, automatically close the port by calling serial.disconnect()
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
const job1 = plotter.Job('job-number-1')
serial
.send(job1)
.then(j => {
console.log(`${j.name} is done !``)
});
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
const job = plotter.Job('realtime-random-strokes')
serial
.send(job, true)
.then(j => {
console.log(`'${j.name}' streaming has been terminated.`)
})
setInterval(() => {
let x = Math.random() * plotter.width
let y = Math.random() * plotter.height
job.move(x, y)
}, 1000)
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
const job1 = plotter.Job('job-number-1')
const job2 = plotter.Job('job-number-2')
serial
.send(job1)
.then(j => {
console.log(`${j.name} is done, starting job-number-2 !`j`)
serial.send(job2)
})
const serial = plotter.Serial('/dev/tty.wchusbserial1410', {disonnectOnJobEnd: false})
const job = plotter.Job('my-awesome-job')
serial
.send(job)
.then(j => {
console.log(`${j.name} is done !``)
serial.disconnect()
});
Open the serial port specified in const serial = plotter.Serial(port, options)
, send multiples job
s through it and resolve a Promise when all the job
s are done.
Set serial.options.disonnectOnJobEnd
to false
, to avoid closing the serial port between each job.
const serial = plotter.Serial('/dev/tty.wchusbserial1410', {disonnectOnJobEnd: false})
const jobs = [
plotter.Job('job-number-1'),
plotter.Job('job-number-2')
]
serial
.sendList(jobs)
.then(() => {
console.log('all jobs done !')
serial.disconnect()
})
If job
is being sent or streamed via serial.send(job)
, end it by emitting a job-end
event.
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
const job = plotter.Job('my-soon-to-die-job')
serial.send(job)
something.on('event', () => serial.end(job))
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
const job = plotter.Job('my-soon-to-die-job')
// manually connect and use Promise.resolve to begin interval
// when the plotter is ready, whereas when the script starts
serial.connect().then(() => {
serial
.send(job, true) // serial.send(job, true) to stream
.then(j => {
console.log(`'${j.name}' has ended.`)
clearInterval(randomStrokes)
})
let randomStrokes = setInterval(() => {
let x = Math.random() * plotter.width
let y = Math.random() * plotter.height
job.pen_down().move(x, y)
}, 3000)
// end the stream one minute after it starts
setTimeout(() => serial.end(job), 60000)
})
Manually open the serial port specified in const serial = plotter.Serial(port, options)
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
serial.connect()
Manually close the serial port specified in const serial = plotter.Serial(port, options)
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
serial.connect()
// do something
serial.disconnect()
Pause the current serial communication. For pausing the serial in the context of job buffer, see job.wait()
.
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
const job = plotter.Job('job')
serial.send(job)
// pause the job after 5 seconds
setTimeout(function() {
serial.pause()
}, 5000)
Resume the current paused serial communication.
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
const job = plotter.Job('job')
// begin the job in a paused state
serial.pause().send(job)
// resume the job when a certain event is fired
someObject.on('someEvent', (data) => {
serial.resume()
});
Send a custom command
through the serial port specified in const serial = plotter.Serial(port, options)
. Useful if you modify the plotter's firmware.
Note: you need to have the port open in order to send the command.
const serial = plotter.Serial('/dev/tty.wchusbserial1410')
const hackyCommand = 'G28'
if (!serial.connected) {
serial.connect()
}
serial.sendCommand(hackyCommand)
The error
event's callback is called with an error object when a serial error occurs.
The connect
event's callback is called when the serial communication is established.
The disconnect
event's callback is called when the serial communication is closed.
The pause
event's callback is called when the current serial communication is paused, either by serial.pause()
or by job.wait()
.
The resume
event's callback is called when the current paused serial communication is resumed, either by serial.resume()
or by resolving job.wait()
.
The job-start
event's callback is called with a data
object when a job
starts.
{
job: plotter.job // the job object
}
The job-progress
event's callback is called whith a data
object when a new command is sent to the plotter in the context of a job
.
{
job: plotter.job, // the job object
cmd: 'G1 0 0', // the command sent to the plotter
progress: {
total: 10, // the total length of commands in the buffer
elapsed: 2, // the length of commands already sent
remaining: 8, // the length of remaining commands to send
}
}
The job-done
event's callback is called with a data
object when a job
is ended, either because it is finished or because it has been cancelled by calling serial.end(job)
.
{
job: plotter.job // the job object
}
Instantiate a server
object and open a websocket communication on the specified address
. The default port is 8080
, and can be overridden by setting options.port
.
For more details on setting up the corresponding server, see arnaudjuracek/xy-server.
const server = plotter.Server('xy-server.local', {
port: 8888 // the default port is 8080
})
Send the specified job
to the server
's queue. The optional callback
is executed after the job
has ben sent, and accept a success
arguement which is either true
or false
.
For more details on setting up the corresponding server, see arnaudjuracek/xy-server.
const server = plotter.Server('xy-server.local')
const job = plotter.Job('job')
server.queue(job, (success) => {
if (success) console.log('job successfully queued !')
else console.log('something went wrong...')
})
Instantiate the plotter.File()
module, which handles all file manipulations, such as saving/loading job or exporting images.
const plotter = require('xy-plotter')()
const file = plotter.File()
const plotter = require('xy-plotter')()
const file = plotter.File()
const job = plotter.Job('my-drawing')
file.save(job, '/path/to/the/file.json')
const plotter = require('xy-plotter')()
const file = plotter.File()
const job = file.load('/path/to/the/file.json')
Export the specified job
as an image file.
Format is chosen by specifying the file extension, and can be .png
, .svg
, .jpg
or .jpeg
.
const plotter = require('xy-plotter')()
const file = plotter.File()
const job = plotter.Job('my-drawing')
file.export(job, '/path/to/the/image.png', {
width: plotter.width * 4, // width of the image in px
height: plotter.height * 4, // height of the image in px
stroke: '#000', // stroke color
background: '#FFF', // background color
strokeWeight: 1, // line and point width
quality: 75, // JPEG quality
progressive: false // true to enable JPEG progressive compression
})
Instantiate a stats
object for the specified job
. The stats
object handle all sorts of stats and infos calculation, such as the job
's estimated duration or the distance travelled by the pen.
const plotter = require('xy-plotter')()
const job = plotter.Job('my-drawing')
const stats = plotter.Stats(job)
Return the distance travelled by the pen during the job
specified in the stats
object.
const plotter = require('xy-plotter')()
const job = plotter.Job('my-drawing')
const stats = plotter.Stats(job)
console.log('The pen will travel ' + stats.distance + 'mm during this job')
Return an object containing informations about the duration of the job
specified in the stats
object.
const plotter = require('xy-plotter')()
const job = plotter.Job('my-drawing')
const stats = plotter.Stats(job)
console.log(stats.duration)
/* {
estimation: {
value: 1641,
formatted: '00:27:21'
},
min: {
value: 1476.9,
formatted: '00:24:36'
},
max: {
value: 1805.1,
formatted: '00:30:05'
}
} */
Return an object containing the benchmark used to estimate the duration of the job
.
Note: this benchmark has been made with my very own setup, and may differ on other setups.
const plotter = require('xy-plotter')()
const job = plotter.Job('my-drawing')
const stats = plotter.Stats(job)
console.log(stats.benchmark)
/* {
// benchmark with a movement distance of 380mm
duration: [
// depending on the length of the segment, the default none-linear
// duration varies between 10s and 36s, averaging to 23s
{speedSetting: null, seconds: 23, min: 10, max: 36},
// linear speeds
{speedSetting: 0.1, seconds: 35},
{speedSetting: 0.2, seconds: 32},
{speedSetting: 0.3, seconds: 28},
{speedSetting: 0.4, seconds: 25},
{speedSetting: 0.5, seconds: 22},
{speedSetting: 0.6, seconds: 18},
{speedSetting: 0.7, seconds: 15},
{speedSetting: 0.8, seconds: 12},
{speedSetting: 0.9, seconds: 8},
{speedSetting: 1.0, seconds: 5}
],
speed: {
values: [
// depending on the length of the segment, the default non-linear speed
// varies between 10.56mm/s and 38mm/s, averaging to 24.28mm/s
{speedSetting: null, mmPerSecond: 24.28, min: 10.56, max: 38},
// linear speeds
{speedSetting: 0.1, mmPerSecond: 10.86},
{speedSetting: 0.2, mmPerSecond: 11.88},
{speedSetting: 0.3, mmPerSecond: 13.57},
{speedSetting: 0.4, mmPerSecond: 15.2},
{speedSetting: 0.5, mmPerSecond: 17.27},
{speedSetting: 0.6, mmPerSecond: 21.11},
{speedSetting: 0.7, mmPerSecond: 25.33},
{speedSetting: 0.8, mmPerSecond: 31.67},
{speedSetting: 0.9, mmPerSecond: 47.5},
{speedSetting: 1.0, mmPerSecond: 76},
],
interpolate: function(x) { return 1.3145 * Math.exp(3.8312 * x) 5435; },
lerp: function(x) { return 58.2018 - x; }
}
} */
Recalculate all the stats and return the stats object.
const plotter = require('xy-plotter')()
const job = plotter.Job('my-drawing')
const stats = plotter.Stats(job)
console.log(stats.distance)
// ...
// some modifications to the job's buffer
// ...
console.log(stats.refresh().distance) // get the new distance
Return a pretty string of the stats. The emoji prefixes can be disabled by calling stats.pretty(false)
const plotter = require('xy-plotter')()
const job = plotter.Job('my-drawing')
const stats = plotter.Stats(job)
console.log(stats.pretty())
console.log(stats.pretty(false)) // no emojis
-
Plotter()
- EventEmitter
-
plotter.Job()
job.name
job.buffer()
job.setSpeed()
job.resetSpeed()
job.optimize()
job.pen_up()
job.pen_down()
job.pen()
job.move()
job.home()
job.wait()
job.drawBoundaries()
job.point()
job.line()
job.triangle()
job.rect()
job.quad()
job.polygon()
job.circle()
job.ellipse()
job.text()
job.svg()
job.addToBuffer()
Event: 'data'
-
plotter.Turtle()
-
plotter.Serial()
serial.connected
serial.paused
serial.send()
serial.sendList()
serial.end()
serial.connect()
serial.disconnect()
serial.pause()
serial.resume()
serial.sendCommand()
Event: 'error'
Event: 'connect'
Event: 'disconnect'
Event: 'pause'
Event: 'resume'
Event: 'job-start'
Event: 'job-progress'
Event: 'job-end'
-
plotter.Server()
-
plotter.File()
-
plotter.Stats()