Use EPSILON for feedrate comparison, simplify program appending w/ impl AddAssign, don't turn on tool after path (for laser / others sake)

master
Sameer Puri 6 years ago
parent d82eb8f22b
commit c383a3f2e1

@ -1,4 +1,5 @@
use std::io::{self, Write};
use std::ops::AddAssign;
#[derive(Clone, PartialEq, Eq)]
pub enum Direction {
@ -18,7 +19,34 @@ pub enum Distance {
Incremental,
}
pub type Program = Vec<GCode>;
#[derive(Default, PartialEq, Clone)]
pub struct Program(Vec<GCode>);
impl std::ops::Deref for Program {
type Target = [GCode];
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl AddAssign for Program {
fn add_assign(&mut self, mut other: Program) {
self.0.extend(other.0.drain(..));
}
}
impl From<Vec<GCode>> for Program {
fn from(v: Vec<GCode>) -> Self {
Self(v)
}
}
impl Program {
pub fn push(&mut self, g: GCode) {
self.0.push(g)
}
}
macro_rules! write_if_some {
($w:expr, $s:expr, $v:ident) => {
@ -59,7 +87,7 @@ pub enum GCode {
pub fn program2gcode<W: Write>(p: &Program, mut w: W) -> io::Result<()> {
use GCode::*;
let mut last_feedrate = None;
let mut last_feedrate: Option<f64> = None;
for code in p.iter() {
match code {
RapidPositioning { x, y } => {
@ -84,15 +112,15 @@ pub fn program2gcode<W: Write>(p: &Program, mut w: W) -> io::Result<()> {
))
}
(Some(last), Some(new)) => {
if last != new {
last_feedrate = Some(new);
if (last - *new).abs() < std::f64::EPSILON {
last_feedrate = Some(*new);
Some(new)
} else {
None
}
}
(None, Some(new)) => {
last_feedrate = Some(new);
last_feedrate = Some(*new);
Some(new)
}
(Some(_), None) => None,

@ -4,8 +4,8 @@ use crate::code::*;
pub struct Machine {
tool_state: Option<Tool>,
distance_mode: Option<Distance>,
pub tool_on_action: Program,
pub tool_off_action: Program,
pub tool_on_action: Vec<GCode>,
pub tool_off_action: Vec<GCode>,
}
impl Default for Machine {
@ -20,7 +20,7 @@ impl Default for Machine {
}
impl Machine {
pub fn tool_on(&mut self) -> Program {
pub fn tool_on(&mut self) -> Vec<GCode> {
if self.tool_state == Some(Tool::Off) || self.tool_state == None {
self.tool_state = Some(Tool::On);
self.tool_on_action.clone()
@ -29,7 +29,7 @@ impl Machine {
}
}
pub fn tool_off(&mut self) -> Program {
pub fn tool_off(&mut self) -> Vec<GCode> {
if self.tool_state == Some(Tool::On) || self.tool_state == None {
self.tool_state = Some(Tool::Off);
self.tool_off_action.clone()
@ -38,7 +38,7 @@ impl Machine {
}
}
pub fn distance(&mut self, is_absolute: bool) -> Program {
pub fn distance(&mut self, is_absolute: bool) -> Vec<GCode> {
if is_absolute {
self.absolute()
} else {
@ -46,7 +46,7 @@ impl Machine {
}
}
pub fn absolute(&mut self) -> Program {
pub fn absolute(&mut self) -> Vec<GCode> {
if self.distance_mode == Some(Distance::Incremental) || self.distance_mode == None {
self.distance_mode = Some(Distance::Absolute);
vec![GCode::DistanceMode(Distance::Absolute)]
@ -55,7 +55,7 @@ impl Machine {
}
}
pub fn incremental(&mut self) -> Program {
pub fn incremental(&mut self) -> Vec<GCode> {
if self.distance_mode == Some(Distance::Absolute) || self.distance_mode == None {
self.distance_mode = Some(Distance::Incremental);
vec![GCode::DistanceMode(Distance::Incremental)]

@ -108,14 +108,13 @@ impl Default for ProgramOptions {
}
fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> Program {
let mut p = Program::new();
let mut p = Program::default();
let mut t = Turtle::default();
t.mach = mach;
p.push(GCode::UnitsMillimeters);
p.extend(t.mach.tool_off());
p.extend(t.move_to(true, 0.0, 0.0));
p.extend(t.mach.tool_on());
p += t.mach.tool_off().into();
p += t.move_to(true, 0.0, 0.0).into();
for edge in doc.root().traverse() {
let (node, is_start) = match edge {
@ -147,8 +146,10 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
);
}
}
if let (ElementId::G, true) = (id, is_start) {
p.push(GCode::Named(Box::new(node.id().to_string())));
if let ElementId::G = id {
if is_start {
p.push(GCode::Named(Box::new(node.id().to_string())));
}
}
if let Some(&AttributeValue::Transform(ref trans)) = attrs.get_value(AttributeId::Transform)
{
@ -167,22 +168,20 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
p.push(GCode::Named(Box::new(node.id().to_string())));
t.reset();
for segment in path.iter() {
match segment {
PathSegment::MoveTo { abs, x, y } => {
p.extend(t.move_to(*abs, *x, *y))
}
let segment_gcode = match segment {
PathSegment::MoveTo { abs, x, y } => t.move_to(*abs, *x, *y),
PathSegment::ClosePath { abs } => {
// Ignore abs, should have identical effect: https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand
p.extend(t.close(None, opts.feedrate))
t.close(None, opts.feedrate)
}
PathSegment::LineTo { abs, x, y } => {
p.extend(t.line(*abs, *x, *y, None, opts.feedrate));
t.line(*abs, *x, *y, None, opts.feedrate)
}
PathSegment::HorizontalLineTo { abs, x } => {
p.extend(t.line(*abs, *x, None, None, opts.feedrate));
t.line(*abs, *x, None, None, opts.feedrate)
}
PathSegment::VerticalLineTo { abs, y } => {
p.extend(t.line(*abs, None, *y, None, opts.feedrate));
t.line(*abs, None, *y, None, opts.feedrate)
}
PathSegment::CurveTo {
abs,
@ -192,22 +191,20 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
y2,
x,
y,
} => {
p.extend(t.cubic_bezier(
*abs,
*x1,
*y1,
*x2,
*y2,
*x,
*y,
opts.tolerance,
None,
opts.feedrate,
));
}
PathSegment::SmoothCurveTo { abs, x2, y2, x, y } => {
p.extend(t.smooth_cubic_bezier(
} => t.cubic_bezier(
*abs,
*x1,
*y1,
*x2,
*y2,
*x,
*y,
opts.tolerance,
None,
opts.feedrate,
),
PathSegment::SmoothCurveTo { abs, x2, y2, x, y } => t
.smooth_cubic_bezier(
*abs,
*x2,
*y2,
@ -216,30 +213,26 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
opts.tolerance,
None,
opts.feedrate,
));
}
PathSegment::Quadratic { abs, x1, y1, x, y } => {
p.extend(t.quadratic_bezier(
*abs,
*x1,
*y1,
*x,
*y,
opts.tolerance,
None,
opts.feedrate,
));
}
PathSegment::SmoothQuadratic { abs, x, y } => {
p.extend(t.smooth_quadratic_bezier(
),
PathSegment::Quadratic { abs, x1, y1, x, y } => t.quadratic_bezier(
*abs,
*x1,
*y1,
*x,
*y,
opts.tolerance,
None,
opts.feedrate,
),
PathSegment::SmoothQuadratic { abs, x, y } => t
.smooth_quadratic_bezier(
*abs,
*x,
*y,
opts.tolerance,
None,
opts.feedrate,
));
}
),
PathSegment::EllipticalArc {
abs,
rx,
@ -249,22 +242,21 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
sweep,
x,
y,
} => {
p.extend(t.elliptical(
*abs,
*rx,
*ry,
*x_axis_rotation,
*large_arc,
*sweep,
*x,
*y,
None,
opts.feedrate,
opts.tolerance,
));
}
}
} => t.elliptical(
*abs,
*rx,
*ry,
*x_axis_rotation,
*large_arc,
*sweep,
*x,
*y,
None,
opts.feedrate,
opts.tolerance,
),
};
p += segment_gcode.into();
}
}
}
@ -275,13 +267,12 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
}
}
p.extend(t.mach.tool_off());
p.extend(t.mach.absolute());
p += t.mach.tool_off().into();
p += t.mach.absolute().into();
p.push(GCode::RapidPositioning {
x: 0.0.into(),
y: 0.0.into(),
});
p.extend(t.mach.tool_on());
p.push(GCode::ProgramEnd);
p

@ -1,4 +1,4 @@
use crate::code::{GCode, Program};
use crate::code::{GCode};
use crate::machine::Machine;
use lyon_geom::euclid::{Angle, Transform2D};
use lyon_geom::math::{point, vector, F64Point};
@ -29,7 +29,7 @@ impl Default for Turtle {
}
impl Turtle {
pub fn move_to<X, Y>(&mut self, abs: bool, x: X, y: Y) -> Program
pub fn move_to<X, Y>(&mut self, abs: bool, x: X, y: Y) -> Vec<GCode>
where
X: Into<Option<f64>>,
Y: Into<Option<f64>>,
@ -64,7 +64,7 @@ impl Turtle {
.collect()
}
pub fn close<Z, F>(&mut self, z: Z, f: F) -> Program
pub fn close<Z, F>(&mut self, z: Z, f: F) -> Vec<GCode>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,
@ -85,7 +85,7 @@ impl Turtle {
.collect()
}
pub fn line<X, Y, Z, F>(&mut self, abs: bool, x: X, y: Y, z: Z, f: F) -> Program
pub fn line<X, Y, Z, F>(&mut self, abs: bool, x: X, y: Y, z: Z, f: F) -> Vec<GCode>
where
X: Into<Option<f64>>,
Y: Into<Option<f64>>,
@ -129,7 +129,7 @@ impl Turtle {
tolerance: f64,
z: Z,
f: F,
) -> Program {
) -> Vec<GCode> {
let z = z.into();
let f = f.into();
let last_point = std::cell::Cell::new(self.curpos);
@ -164,7 +164,7 @@ impl Turtle {
tolerance: f64,
z: Z,
f: F,
) -> Program
) -> Vec<GCode>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,
@ -203,7 +203,7 @@ impl Turtle {
tolerance: f64,
z: Z,
f: F,
) -> Program
) -> Vec<GCode>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,
@ -238,7 +238,7 @@ impl Turtle {
tolerance: f64,
z: Z,
f: F,
) -> Program
) -> Vec<GCode>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,
@ -267,7 +267,7 @@ impl Turtle {
tolerance: f64,
z: Z,
f: F,
) -> Program
) -> Vec<GCode>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,
@ -301,7 +301,7 @@ impl Turtle {
z: Z,
f: F,
tolerance: f64,
) -> Program
) -> Vec<GCode>
where
Z: Into<Option<f64>>,
F: Into<Option<f64>>,

Loading…
Cancel
Save