Merge pull request #5 from lorenrogers/documentation

Documentation
master
Sameer Puri 5 years ago committed by GitHub
commit 084b3a841b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,53 +1,65 @@
/// TODO: Documentation
use std::io::{self, Write}; use std::io::{self, Write};
use std::ops::AddAssign; use std::ops::AddAssign;
// TODO: Documentation
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub enum Direction { pub enum Direction {
Clockwise, Clockwise,
AntiClockwise, AntiClockwise,
} }
// TODO: Documentation
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub enum Tool { pub enum Tool {
Off, Off,
On, On,
} }
// TODO: Documentation
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub enum Distance { pub enum Distance {
Absolute, Absolute,
Incremental, Incremental,
} }
// TODO: Documentation
#[derive(Default, PartialEq, Clone)] #[derive(Default, PartialEq, Clone)]
pub struct Program(Vec<GCode>); pub struct Program(Vec<GCode>);
// TODO: Documentation
impl std::ops::Deref for Program { impl std::ops::Deref for Program {
type Target = [GCode]; type Target = [GCode];
// TODO: Documentation
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
self.0.deref() self.0.deref()
} }
} }
// TODO: Documentation
impl AddAssign for Program { impl AddAssign for Program {
fn add_assign(&mut self, mut other: Program) { fn add_assign(&mut self, mut other: Program) {
self.0.extend(other.0.drain(..)); self.0.extend(other.0.drain(..));
} }
} }
// TODO: Documentation
impl From<Vec<GCode>> for Program { impl From<Vec<GCode>> for Program {
fn from(v: Vec<GCode>) -> Self { fn from(v: Vec<GCode>) -> Self {
Self(v) Self(v)
} }
} }
// TODO: Documentation
impl Program { impl Program {
pub fn push(&mut self, g: GCode) { pub fn push(&mut self, g: GCode) {
self.0.push(g) self.0.push(g)
} }
} }
// TODO: Documentation
macro_rules! write_if_some { macro_rules! write_if_some {
($w:expr, $s:expr, $v:ident) => { ($w:expr, $s:expr, $v:ident) => {
if let Some(v) = $v { if let Some(v) = $v {
@ -58,13 +70,15 @@ macro_rules! write_if_some {
}; };
} }
/// Rudimentary regular expression GCode validator. // TODO: Documentation
// Rudimentary regular expression GCode validator.
pub fn validate_gcode(gcode: &&str) -> bool { pub fn validate_gcode(gcode: &&str) -> bool {
use regex::Regex; use regex::Regex;
let re = Regex::new(r##"^(?:(?:%|\(.*\)|(?:[A-Z^E^U][+-]?\d+(?:\.\d*)?))\h*)*$"##).unwrap(); let re = Regex::new(r##"^(?:(?:%|\(.*\)|(?:[A-Z^E^U][+-]?\d+(?:\.\d*)?))\h*)*$"##).unwrap();
gcode.lines().all(|line| re.is_match(line)) gcode.lines().all(|line| re.is_match(line))
} }
// TODO: Documentation
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub enum GCode { pub enum GCode {
RapidPositioning { RapidPositioning {
@ -93,6 +107,8 @@ pub enum GCode {
Raw(Box<String>), Raw(Box<String>),
} }
// TODO: Documentation
// TODO: This function is too large
pub fn program2gcode<W: Write>(p: &Program, mut w: W) -> io::Result<()> { pub fn program2gcode<W: Write>(p: &Program, mut w: W) -> io::Result<()> {
use GCode::*; use GCode::*;
let mut last_feedrate: Option<f64> = None; let mut last_feedrate: Option<f64> = None;
@ -182,3 +198,18 @@ pub fn program2gcode<W: Write>(p: &Program, mut w: W) -> io::Result<()> {
} }
Ok(()) Ok(())
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_gcode() {
panic!("TODO: basic passing test");
}
#[test]
fn test_program2gcode() {
panic!("TODO: basic passing test");
}
}

@ -1,6 +1,9 @@
/// TODO: Documentation
use crate::code::*; use crate::code::*;
/// Generic machine state simulation, assuming nothing is known about the machine when initialized. // TODO: Documentation
// Generic machine state simulation, assuming nothing is known about the machine when initialized.
pub struct Machine { pub struct Machine {
tool_state: Option<Tool>, tool_state: Option<Tool>,
distance_mode: Option<Distance>, distance_mode: Option<Distance>,
@ -8,6 +11,8 @@ pub struct Machine {
pub tool_off_action: Vec<GCode>, pub tool_off_action: Vec<GCode>,
} }
// TODO: Documentation
// Assigns reasonable default settings that apply to most gcode applications.
impl Default for Machine { impl Default for Machine {
fn default() -> Self { fn default() -> Self {
Self { Self {
@ -33,7 +38,10 @@ impl Default for Machine {
} }
} }
// TODO: Documentation
// Implements the state machine functions to export Gcode.
impl Machine { impl Machine {
// Outputs gcode to turn the tool on.
pub fn tool_on(&mut self) -> Vec<GCode> { pub fn tool_on(&mut self) -> Vec<GCode> {
if self.tool_state == Some(Tool::Off) || self.tool_state == None { if self.tool_state == Some(Tool::Off) || self.tool_state == None {
self.tool_state = Some(Tool::On); self.tool_state = Some(Tool::On);
@ -43,6 +51,7 @@ impl Machine {
} }
} }
// Outputs gcode to turn the tool off.
pub fn tool_off(&mut self) -> Vec<GCode> { pub fn tool_off(&mut self) -> Vec<GCode> {
if self.tool_state == Some(Tool::On) || self.tool_state == None { if self.tool_state == Some(Tool::On) || self.tool_state == None {
self.tool_state = Some(Tool::Off); self.tool_state = Some(Tool::Off);
@ -52,6 +61,7 @@ impl Machine {
} }
} }
// Outputs gcode for how distance should be measured: relative or absolute.
pub fn distance(&mut self, is_absolute: bool) -> Vec<GCode> { pub fn distance(&mut self, is_absolute: bool) -> Vec<GCode> {
if is_absolute { if is_absolute {
self.absolute() self.absolute()
@ -60,6 +70,7 @@ impl Machine {
} }
} }
// Outputs gcode command to use absolute motion
pub fn absolute(&mut self) -> Vec<GCode> { pub fn absolute(&mut self) -> Vec<GCode> {
if self.distance_mode == Some(Distance::Incremental) || self.distance_mode == None { if self.distance_mode == Some(Distance::Incremental) || self.distance_mode == None {
self.distance_mode = Some(Distance::Absolute); self.distance_mode = Some(Distance::Absolute);
@ -69,6 +80,7 @@ impl Machine {
} }
} }
// Outputs gcode command to use relative motion
pub fn incremental(&mut self) -> Vec<GCode> { pub fn incremental(&mut self) -> Vec<GCode> {
if self.distance_mode == Some(Distance::Absolute) || self.distance_mode == None { if self.distance_mode == Some(Distance::Absolute) || self.distance_mode == None {
self.distance_mode = Some(Distance::Incremental); self.distance_mode = Some(Distance::Incremental);
@ -78,3 +90,33 @@ impl Machine {
} }
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tool_on() {
panic!("TODO: basic passing test");
}
#[test]
fn test_tool_off() {
panic!("TODO: basic passing test");
}
#[test]
fn test_distance() {
panic!("TODO: basic passing test");
}
#[test]
fn test_absolute() {
panic!("TODO: basic passing test");
}
#[test]
fn test_incremental() {
panic!("TODO: basic passing test");
}
}

@ -1,3 +1,5 @@
/// TODO: documentation
#[macro_use] #[macro_use]
extern crate clap; extern crate clap;
extern crate env_logger; extern crate env_logger;
@ -23,6 +25,7 @@ use code::*;
use machine::*; use machine::*;
use turtle::*; use turtle::*;
// TODO: Documentation
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
if env::var("RUST_LOG").is_err() { if env::var("RUST_LOG").is_err() {
env::set_var("RUST_LOG", "svg2gcode=info") env::set_var("RUST_LOG", "svg2gcode=info")
@ -82,12 +85,14 @@ fn main() -> io::Result<()> {
program2gcode(&prog, File::create("out.gcode")?) program2gcode(&prog, File::create("out.gcode")?)
} }
// TODO: Documentation
struct ProgramOptions { struct ProgramOptions {
tolerance: f64, tolerance: f64,
feedrate: f64, feedrate: f64,
dpi: f64, dpi: f64,
} }
// Sets the baseline options for the machine.
impl Default for ProgramOptions { impl Default for ProgramOptions {
fn default() -> Self { fn default() -> Self {
ProgramOptions { ProgramOptions {
@ -98,6 +103,8 @@ impl Default for ProgramOptions {
} }
} }
// TODO: Documentation
// TODO: This function is much too large
fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> Program { fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> Program {
let mut p = Program::default(); let mut p = Program::default();
let mut t = Turtle::from(mach); let mut t = Turtle::from(mach);
@ -289,6 +296,7 @@ fn svg2program(doc: &svgdom::Document, opts: ProgramOptions, mach: Machine) -> P
p p
} }
// TODO: Documentation
fn length_to_mm(l: svgdom::Length, dpi: f64) -> f64 { fn length_to_mm(l: svgdom::Length, dpi: f64) -> f64 {
use svgdom::LengthUnit::*; use svgdom::LengthUnit::*;
use uom::si::f64::Length; use uom::si::f64::Length;
@ -305,3 +313,18 @@ fn length_to_mm(l: svgdom::Length, dpi: f64) -> f64 {
length.get::<millimeter>() length.get::<millimeter>()
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_svg2program() {
panic!("TODO: basic passing test");
}
#[test]
fn test_length_to_mm() {
panic!("TODO: basic passing test");
}
}

@ -1,12 +1,14 @@
/// TODO: Documentation
use crate::code::GCode; use crate::code::GCode;
use crate::machine::Machine; use crate::machine::Machine;
use lyon_geom::euclid::{Angle, default::Transform2D}; use lyon_geom::euclid::{Angle, default::Transform2D};
use lyon_geom::math::{point, vector, F64Point}; use lyon_geom::math::{point, vector, F64Point};
use lyon_geom::{ArcFlags, CubicBezierSegment, QuadraticBezierSegment, SvgArc}; use lyon_geom::{ArcFlags, CubicBezierSegment, QuadraticBezierSegment, SvgArc};
/// Turtle graphics simulator for paths that outputs the GCode enum representation for each operation. /// Turtle graphics simulator for paths that outputs the GCode enum
/// Handles trasforms, scaling, position offsets, etc. /// representation for each operation. Handles trasforms, scaling, position
/// See https://www.w3.org/TR/SVG/paths.html /// offsets, etc. See https://www.w3.org/TR/SVG/paths.html
pub struct Turtle { pub struct Turtle {
curpos: F64Point, curpos: F64Point,
initpos: F64Point, initpos: F64Point,
@ -17,6 +19,7 @@ pub struct Turtle {
prev_ctrl: Option<F64Point>, prev_ctrl: Option<F64Point>,
} }
// TODO: Documentation
impl Default for Turtle { impl Default for Turtle {
fn default() -> Self { fn default() -> Self {
Self { Self {
@ -31,6 +34,7 @@ impl Default for Turtle {
} }
} }
// TODO: Documentation
impl From<Machine> for Turtle { impl From<Machine> for Turtle {
fn from(m: Machine) -> Self { fn from(m: Machine) -> Self {
let mut t = Self::default(); let mut t = Self::default();
@ -39,6 +43,7 @@ impl From<Machine> for Turtle {
} }
} }
// TODO: Documentation
impl Turtle { impl Turtle {
pub fn move_to<X, Y>(&mut self, abs: bool, x: X, y: Y) -> Vec<GCode> pub fn move_to<X, Y>(&mut self, abs: bool, x: X, y: Y) -> Vec<GCode>
where where
@ -75,12 +80,14 @@ impl Turtle {
.collect() .collect()
} }
// TODO: Documentation
pub fn close<Z, F>(&mut self, z: Z, f: F) -> Vec<GCode> pub fn close<Z, F>(&mut self, z: Z, f: F) -> Vec<GCode>
where where
Z: Into<Option<f64>>, Z: Into<Option<f64>>,
F: Into<Option<f64>>, F: Into<Option<f64>>,
{ {
// See https://www.w3.org/TR/SVG/paths.html#Segment-CompletingClosePath which could result in a G91 G1 X0 Y0 // See https://www.w3.org/TR/SVG/paths.html#Segment-CompletingClosePath
// which could result in a G91 G1 X0 Y0
if (self.curpos - self.initpos) if (self.curpos - self.initpos)
.abs() .abs()
.lower_than(vector(std::f64::EPSILON, std::f64::EPSILON)) .lower_than(vector(std::f64::EPSILON, std::f64::EPSILON))
@ -104,6 +111,7 @@ impl Turtle {
.collect() .collect()
} }
// TODO: Documentation
pub fn line<X, Y, Z, F>(&mut self, abs: bool, x: X, y: Y, z: Z, f: F) -> Vec<GCode> pub fn line<X, Y, Z, F>(&mut self, abs: bool, x: X, y: Y, z: Z, f: F) -> Vec<GCode>
where where
X: Into<Option<f64>>, X: Into<Option<f64>>,
@ -176,6 +184,8 @@ impl Turtle {
.collect() .collect()
} }
// TODO: Documentation
// TODO: Function too long
pub fn cubic_bezier<Z, F>( pub fn cubic_bezier<Z, F>(
&mut self, &mut self,
abs: bool, abs: bool,
@ -217,6 +227,7 @@ impl Turtle {
self.bezier(cbs, tolerance, z, f) self.bezier(cbs, tolerance, z, f)
} }
// TODO: Documentation
pub fn smooth_cubic_bezier<Z, F>( pub fn smooth_cubic_bezier<Z, F>(
&mut self, &mut self,
abs: bool, abs: bool,
@ -254,6 +265,7 @@ impl Turtle {
self.bezier(cbs, tolerance, z, f) self.bezier(cbs, tolerance, z, f)
} }
// TODO: Documentation
pub fn smooth_quadratic_bezier<Z, F>( pub fn smooth_quadratic_bezier<Z, F>(
&mut self, &mut self,
abs: bool, abs: bool,
@ -281,6 +293,7 @@ impl Turtle {
self.bezier(qbs.to_cubic(), tolerance, z, f) self.bezier(qbs.to_cubic(), tolerance, z, f)
} }
// TODO: Documentation
pub fn quadratic_bezier<Z, F>( pub fn quadratic_bezier<Z, F>(
&mut self, &mut self,
abs: bool, abs: bool,
@ -312,6 +325,7 @@ impl Turtle {
self.bezier(qbs.to_cubic(), tolerance, z, f) self.bezier(qbs.to_cubic(), tolerance, z, f)
} }
// TODO: Documentation
pub fn elliptical<Z, F>( pub fn elliptical<Z, F>(
&mut self, &mut self,
abs: bool, abs: bool,
@ -377,6 +391,7 @@ impl Turtle {
.collect() .collect()
} }
// TODO: Documentation
pub fn stack_scaling(&mut self, scaling: Transform2D<f64>) { pub fn stack_scaling(&mut self, scaling: Transform2D<f64>) {
self.curtran = self.curtran.post_transform(&scaling); self.curtran = self.curtran.post_transform(&scaling);
if let Some(ref current_scaling) = self.scaling { if let Some(ref current_scaling) = self.scaling {
@ -386,6 +401,7 @@ impl Turtle {
} }
} }
// TODO: Documentation
pub fn push_transform(&mut self, trans: Transform2D<f64>) { pub fn push_transform(&mut self, trans: Transform2D<f64>) {
self.transtack.push(self.curtran); self.transtack.push(self.curtran);
if let Some(ref scaling) = self.scaling { if let Some(ref scaling) = self.scaling {
@ -399,6 +415,7 @@ impl Turtle {
} }
} }
// TODO: Documentation
pub fn pop_transform(&mut self) { pub fn pop_transform(&mut self) {
self.curtran = self self.curtran = self
.transtack .transtack
@ -406,6 +423,7 @@ impl Turtle {
.expect("popped when no transforms left"); .expect("popped when no transforms left");
} }
// TODO: Documentation
pub fn reset(&mut self) { pub fn reset(&mut self) {
self.curpos = point(0.0, 0.0); self.curpos = point(0.0, 0.0);
self.curpos = self.curtran.transform_point(self.curpos); self.curpos = self.curtran.transform_point(self.curpos);
@ -413,3 +431,73 @@ impl Turtle {
self.initpos = self.curpos; self.initpos = self.curpos;
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_move_to() {
panic!("TODO: basic passing test");
}
#[test]
fn test_close() {
panic!("TODO: basic passing test");
}
#[test]
fn test_line() {
panic!("TODO: basic passing test");
}
#[test]
fn test_bezier() {
panic!("TODO: basic passing test");
}
#[test]
fn test_cubic_bezier() {
panic!("TODO: basic passing test");
}
#[test]
fn test_smooth_cubic_bezier() {
panic!("TODO: basic passing test");
}
#[test]
fn test_smooth_quadratic_bezier() {
panic!("TODO: basic passing test");
}
#[test]
fn test_quadratic_bezier() {
panic!("TODO: basic passing test");
}
#[test]
fn test_elliptical() {
panic!("TODO: basic passing test");
}
#[test]
fn test_stack_scaling() {
panic!("TODO: basic passing test");
}
#[test]
fn test_push_transform() {
panic!("TODO: basic passing test");
}
#[test]
fn test_pop_transform() {
panic!("TODO: basic passing test");
}
#[test]
fn test_reset() {
panic!("TODO: basic passing test");
}
}

Loading…
Cancel
Save