Support custom tool on/off gcode, use uom for unit conversions, rename Named=>Comment after reviewing NIST spec, update dependencies

master
Sameer Puri 6 years ago
parent 75cbb34d60
commit c04ba6b625

42
Cargo.lock generated

@ -29,7 +29,7 @@ name = "atty"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -84,9 +84,9 @@ name = "euclid_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -112,7 +112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.51"
version = "0.2.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -171,7 +171,7 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "0.4.28"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -187,7 +187,7 @@ name = "quote"
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -259,7 +259,9 @@ dependencies = [
"env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"lyon_geom 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"svgdom 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
"uom 0.22.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -285,10 +287,10 @@ dependencies = [
[[package]]
name = "syn"
version = "0.15.32"
version = "0.15.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -306,7 +308,7 @@ name = "termion"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)",
"numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -328,6 +330,11 @@ dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "typenum"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ucd-util"
version = "0.1.3"
@ -343,6 +350,15 @@ name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "uom"
version = "0.22.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "utf8-ranges"
version = "1.0.2"
@ -408,7 +424,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum float-cmp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "134a8fa843d80a51a5b77d36d42bc2def9edcb0262c914861d08129fd1926600"
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917"
"checksum libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)" = "ec350a9417dfd244dc9a6c4a71e13895a4db6b92f0b106f07ebbc3f3bc580cee"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum lyon_geom 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0ea0ba5f8d2d91d6d895aca54d1ec0d84ddfa4826f33fbfe8abb39f08f9e4153"
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
@ -417,7 +433,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
"checksum proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)" = "ba92c84f814b3f9a44c5cfca7d2ad77fa10710867d2bbb1b3d175ab5f47daa12"
"checksum proc-macro2 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)" = "64c827cea7a7ab30ce4593e5e04d7a11617ad6ece2fa230605a78b00ff965316"
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252"
@ -431,14 +447,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum svgdom 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ffe3c59d84b307fc361bbf0baff2aa6f6d7c946fdd4f1fbbcbb7efcd04b0334"
"checksum svgtypes 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "06280cc80ac6d6be32d497f068c40a25552cc837519265edab70d9040e64c52b"
"checksum syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)" = "846620ec526c1599c070eff393bfeeeb88a93afa2513fc3b49f1fea84cf7b0ed"
"checksum syn 0.15.33 (registry+https://github.com/rust-lang/crates.io-index)" = "ec52cd796e5f01d0067225a5392e70084acc4c0013fa71d55166d38a8b307836"
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum uom 0.22.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5cbf1d58ad58167ac4d22381cf4e2361f321712f7f876c8252ba5757989de53e"
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"

@ -11,3 +11,5 @@ lyon_geom = "^0"
clap = "^2"
log = "^0"
env_logger = "^0"
uom = "^0"
regex = "^1"

@ -9,6 +9,7 @@ Convert any SVG 1.1 path to gcode for a pen plotter, laser engraver, etc.
- [x] Px, pc, in to mm
- [x] Configurable DPI for px/pc to mm
- [ ] Sort paths by distance to reduce G0 distances
- [ ] Configurable start/end sequence
## Known bugs & whether fixed
- [ ] Smooth curves should not use the control point when the previous curve is not of the same type (quadratic -> smooth cubic, cubic -> smooth quadratic)

@ -58,6 +58,13 @@ macro_rules! write_if_some {
};
}
/// Rudimentary regular expression GCode validator.
pub fn validate_gcode(gcode: &&str) -> bool {
use regex::Regex;
let re = Regex::new(r##"^(?:(?:%|\(.*\)|(?:[A-Z^E^U][+-]?\d+(?:\.\d*)?))\h*)*$"##).unwrap();
gcode.lines().all(|line| re.is_match(line))
}
#[derive(Clone, PartialEq)]
pub enum GCode {
RapidPositioning {
@ -82,7 +89,8 @@ pub enum GCode {
},
StopSpindle,
DistanceMode(Distance),
Named(Box<String>),
Comment(Box<String>),
Raw(Box<String>),
}
pub fn program2gcode<W: Write>(p: &Program, mut w: W) -> io::Result<()> {
@ -164,10 +172,11 @@ pub fn program2gcode<W: Write>(p: &Program, mut w: W) -> io::Result<()> {
}
)?;
}
Named(name) => {
if name.len() > 0 {
writeln!(w, "({})", name)?;
}
Comment(name) => {
writeln!(w, "({})", name)?;
}
Raw(raw) => {
writeln!(w, "{}", raw)?;
}
}
}

@ -13,8 +13,22 @@ impl Default for Machine {
Self {
tool_state: None,
distance_mode: None,
tool_on_action: vec![],
tool_off_action: vec![],
tool_on_action: vec![
GCode::Dwell { p: 0.1 },
GCode::StartSpindle {
d: Direction::Clockwise,
s: 70.0,
},
GCode::Dwell { p: 0.1 },
],
tool_off_action: vec![
GCode::Dwell { p: 0.1 },
GCode::StartSpindle {
d: Direction::Clockwise,
s: 50.0,
},
GCode::Dwell { p: 0.1 },
],
}
}
}

@ -1,10 +1,12 @@
#[macro_use]
extern crate clap;
extern crate env_logger;
extern crate svgdom;
#[macro_use]
extern crate log;
extern crate lyon_geom;
extern crate regex;
extern crate svgdom;
extern crate uom;
use std::env;
use std::fs::File;
@ -31,9 +33,11 @@ fn main() -> io::Result<()> {
(author: crate_authors!())
(about: crate_description!())
(@arg FILE: "Selects the input SVG file to use, else reading from stdin")
(@arg tolerance: "Sets the interpolation tolerance for curves")
(@arg feedrate: "Sets the machine feed rate")
(@arg dpi: "Sets the DPI for SVGs with units in pt, pc, etc.")
(@arg tolerance: --tolerance "Sets the interpolation tolerance for curves")
(@arg feedrate: --feedrate "Sets the machine feed rate")
(@arg dpi: --dpi "Sets the DPI for SVGs with units in pt, pc, etc.")
(@arg tool_on_action: --tool_on_action "Sets the tool on GCode sequence")
(@arg tool_off_action: --tool_off_action "Sets the tool off GCode sequence")
)
.get_matches();
@ -65,24 +69,11 @@ fn main() -> io::Result<()> {
opts.dpi = dpi;
}
if true {
mach.tool_on_action = vec![
GCode::StartSpindle {
d: Direction::Clockwise,
s: 70.0,
},
GCode::Dwell { p: 0.1 },
];
if let Some(tool_on_action) = matches.value_of("tool_on_action").filter(validate_gcode) {
mach.tool_on_action = vec![GCode::Raw(Box::new(tool_on_action.to_string()))];
}
if true {
mach.tool_off_action = vec![
GCode::Dwell { p: 0.1 },
GCode::StartSpindle {
d: Direction::Clockwise,
s: 50.0,
},
GCode::Dwell { p: 0.1 },
];
if let Some(tool_off_action) = matches.value_of("tool_off_action").filter(validate_gcode) {
mach.tool_off_action = vec![GCode::Raw(Box::new(tool_off_action.to_string()))];
}
let doc = svgdom::Document::from_str(&input).expect("Invalid or unsupported SVG file");
@ -109,8 +100,7 @@ impl Default for ProgramOptions {
fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> Program {
let mut p = Program::default();
let mut t = Turtle::default();
t.mach = mach;
let mut t = Turtle::from(mach);
p.push(GCode::UnitsMillimeters);
p += t.mach.tool_off().into();
@ -121,11 +111,13 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
svgdom::NodeEdge::Start(node) => (node, true),
svgdom::NodeEdge::End(node) => (node, false),
};
let id = if let svgdom::QName::Id(id) = *node.tag_name() {
id
} else {
continue;
};
let attrs = node.attributes();
if let (ElementId::Svg, true) = (id, is_start) {
if let Some(&AttributeValue::ViewBox(vbox)) = attrs.get_value(AttributeId::ViewBox) {
@ -148,7 +140,7 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
}
if let ElementId::G = id {
if is_start {
p.push(GCode::Named(Box::new(node.id().to_string())));
p.push(GCode::Comment(Box::new(node.id().to_string())));
}
}
if let Some(&AttributeValue::Transform(ref trans)) = attrs.get_value(AttributeId::Transform)
@ -165,7 +157,7 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
match id {
ElementId::Path => {
if let Some(&AttributeValue::Path(ref path)) = attrs.get_value(AttributeId::D) {
p.push(GCode::Named(Box::new(node.id().to_string())));
p.push(GCode::Comment(Box::new(node.id().to_string())));
t.reset();
for segment in path.iter() {
let segment_gcode = match segment {
@ -280,14 +272,17 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
fn length_to_mm(l: svgdom::Length, dpi: f64) -> f64 {
use svgdom::LengthUnit::*;
let scale = match l.unit {
Cm => 0.1,
Mm => 1.0,
In => 25.4,
Pt => 25.4 / dpi,
Pc => 25.4 / (6.0 * (dpi / 72.0)),
_ => 1.0,
use uom::si::f64::Length;
use uom::si::length::*;
let length = match l.unit {
Cm => Length::new::<centimeter>(l.num),
Mm => Length::new::<millimeter>(l.num),
In => Length::new::<inch>(l.num),
Pt => Length::new::<point_printers>(l.num) * dpi / 72.0, // See https://github.com/iliekturtles/uom/blob/5cad47d4e67c902304c4c2b7feeb9c3d34fdffba/src/si/length.rs#L61
Pc => Length::new::<pica_printers>(l.num) * dpi / 72.0, // See https://github.com/iliekturtles/uom/blob/5cad47d4e67c902304c4c2b7feeb9c3d34fdffba/src/si/length.rs#L58
_ => Length::new::<millimeter>(l.num),
};
l.num * scale
length.get::<millimeter>()
}

@ -31,6 +31,14 @@ impl Default for Turtle {
}
}
impl From<Machine> for Turtle {
fn from(m: Machine) -> Self {
let mut t = Self::default();
t.mach = m;
t
}
}
impl Turtle {
pub fn move_to<X, Y>(&mut self, abs: bool, x: X, y: Y) -> Vec<GCode>
where

Loading…
Cancel
Save