use crate::parser::GCodeValue;
use lyon_path::geom::point;
use lyon_path::Path;
use std::cell::RefCell;
pub trait GCodeValueHandler {
fn start(&mut self) {}
fn handle_gcode_value(&mut self, gcode_value_line: Vec<GCodeValue>);
fn end(&mut self) {}
}
pub struct GCodeValueHandlerImpl {
pub line_count: usize,
}
impl Default for GCodeValueHandlerImpl {
fn default() -> Self {
GCodeValueHandlerImpl { line_count: 0 }
}
}
impl GCodeValueHandler for GCodeValueHandlerImpl {
fn start(&mut self) {
self.line_count = 0;
}
fn handle_gcode_value(&mut self, gcode_value_line: Vec<GCodeValue>) {
self.line_count += 1;
println!("{:?}", gcode_value_line);
}
fn end(&mut self) {
println!("line_count:{}", self.line_count);
}
}
pub struct GCodeValueHandlerPath {
pub layers: Vec<GCodeValueHandlerPathLayer>,
mm_value_scale: f32,
is_relative: bool,
last_x: f32,
last_y: f32,
z: Option<GCodeValue>,
last_path_builder: RefCell<Option<lyon_path::Builder>>,
is_path_begin: bool,
is_path_line: bool,
}
impl Default for GCodeValueHandlerPath {
fn default() -> Self {
GCodeValueHandlerPath {
layers: vec![],
mm_value_scale: 1.0,
is_relative: false,
last_x: 0.0,
last_y: 0.0,
z: None,
last_path_builder: RefCell::new(None),
is_path_begin: false,
is_path_line: false,
}
}
}
impl GCodeValueHandlerPath {
fn move_to(&mut self, gcode_value_line: &Vec<GCodeValue>) {
let x_value = gcode_value_line
.iter()
.find(|gcode_value| gcode_value.is_x());
let y_value = gcode_value_line
.iter()
.find(|gcode_value| gcode_value.is_y());
let x = if let Some(x_value) = x_value {
let x = x_value.value_f32() * self.mm_value_scale;
if self.is_relative { x + self.last_x } else { x }
} else {
self.last_x
};
let y = if let Some(y_value) = y_value {
let y = y_value.value_f32() * self.mm_value_scale;
if self.is_relative { y + self.last_y } else { y }
} else {
self.last_y
};
if self.last_path_builder.borrow().is_none() {
self.last_path_builder = RefCell::new(Some(lyon_path::Builder::new()));
self.is_path_begin = false;
self.is_path_line = false;
}
if let Some(last_path_builder) = self.last_path_builder.get_mut() {
if self.is_path_begin {
self.is_path_begin = false;
last_path_builder.end(false);
}
self.is_path_begin = true;
last_path_builder.begin(point(x, y));
}
}
fn line_to(&mut self, gcode_value_line: &Vec<GCodeValue>) {
let x_value = gcode_value_line
.iter()
.find(|gcode_value| gcode_value.is_x());
let y_value = gcode_value_line
.iter()
.find(|gcode_value| gcode_value.is_y());
let x = if let Some(x_value) = x_value {
let x = x_value.value_f32() * self.mm_value_scale;
if self.is_relative { x + self.last_x } else { x }
} else {
self.last_x
};
let y = if let Some(y_value) = y_value {
let y = y_value.value_f32() * self.mm_value_scale;
if self.is_relative { y + self.last_y } else { y }
} else {
self.last_y
};
if self.last_path_builder.borrow().is_none() {
self.last_path_builder = RefCell::new(Some(lyon_path::Builder::new()));
self.is_path_begin = false;
self.is_path_line = false;
if let Some(last_path_builder) = self.last_path_builder.get_mut() {
self.is_path_begin = true;
last_path_builder.begin(point(x, y));
}
} else {
if let Some(last_path_builder) = self.last_path_builder.get_mut() {
self.is_path_line = true;
last_path_builder.line_to(point(x, y));
}
}
}
fn append_last_layer(&mut self) {
if (self.is_path_line) {
if let Some(mut last_path_builder) = self.last_path_builder.clone().into_inner() {
if self.is_path_begin {
last_path_builder.end(false);
}
let path = last_path_builder.build();
self.layers.push(GCodeValueHandlerPathLayer {
z: self.z.clone(),
path,
});
}
}
self.z = None;
self.last_path_builder = RefCell::new(None);
self.is_path_begin = false;
self.is_path_line = false;
}
}
pub struct GCodeValueHandlerPathLayer {
pub z: Option<GCodeValue>,
pub path: Path,
}
impl GCodeValueHandlerPathLayer {
pub fn have_z(&self) -> bool {
self.z.is_some()
}
pub fn z_f32(&self) -> f32 {
if let Some(value) = &self.z {
return value.value_f32();
}
0.0
}
pub fn z_f64(&self) -> f64 {
if let Some(value) = &self.z {
return value.value_f64();
}
0.0
}
}
impl GCodeValueHandler for GCodeValueHandlerPath {
fn handle_gcode_value(&mut self, gcode_value_line: Vec<GCodeValue>) {
for gcode_value in &gcode_value_line {
let cmd = gcode_value.to_string();
match cmd.as_str() {
"G90" => {
self.is_relative = false;
}
"G91" => {
self.is_relative = true;
}
"G20" => {
self.mm_value_scale = 25.4;
}
"G21" => {
self.mm_value_scale = 1.0;
}
"G0" => {
let have_xy = gcode_value_line
.iter()
.any(|gcode_value| gcode_value.is_xy());
if have_xy {
self.move_to(&gcode_value_line);
break;
}
}
"G1" => {
let have_xy = gcode_value_line
.iter()
.any(|gcode_value| gcode_value.is_xy());
if have_xy {
self.line_to(&gcode_value_line);
break;
}
}
_ => {
if match gcode_value.command.as_str() {
"Z" => {
self.append_last_layer();
self.z = Some(gcode_value.clone());
true
}
_ => false,
} {
break;
}
}
}
}
}
fn end(&mut self) {
self.append_last_layer()
}
}