use crate::handler::GCodeValueHandlerPath;
use crate::lines::each_path_line;
use crate::parser::GCodeParser;
use crate::path_bounds;
use rc_bytes::writer::ByteWriter;
fn path_to_ydd_bytes(
path: &lyon_path::Path,
precision: usize,
data_version: u8,
tolerance: f32,
interval: f32,
le: bool,
) -> Vec<u8> {
let mut bytes_writer = ByteWriter::default();
let mut points: Vec<(f32, f32)> = vec![];
let pe = precision as f32;
let append_points = |writer: &mut ByteWriter, points: &Vec<(f32, f32)>| {
if !points.is_empty() {
writer.write_int8(0, le);
writer.write_int16(points.len() as i16, le);
for p in points.iter() {
if data_version == 2 {
writer.write_float32(p.0, le);
writer.write_float32(p.1, le);
} else {
writer.write_int16((p.0 * pe) as i16, le);
writer.write_int16((p.1 * pe) as i16, le);
}
}
}
};
each_path_line(path, tolerance, interval, |new_line, p| {
if new_line {
append_points(&mut bytes_writer, &points);
points = vec![];
}
if let Some(p) = p {
points.push((p.0, p.1));
}
});
append_points(&mut bytes_writer, &points);
bytes_writer.bytes
}
pub fn gcode_to_ydd_bytes(
gcode: &String,
precision: usize,
data_version: u8,
tolerance: f32,
interval: f32,
le: bool,
) -> Vec<u8> {
let mut parser = GCodeParser::new(gcode);
let mut handler = GCodeValueHandlerPath::default();
parser.parse(&mut handler);
let mut min_x = f32::MAX;
let mut max_x = f32::MIN;
let mut min_y = f32::MAX;
let mut max_y = f32::MIN;
let mut group_writer = ByteWriter::default();
let mut count = 0;
for (i, layer) in handler.layers.iter().enumerate() {
let z = layer.z_f32();
let path = &layer.path;
let item_bounds = path_bounds(path);
min_x = min_x.min(item_bounds.0);
min_y = min_y.min(item_bounds.1);
max_x = max_x.max(item_bounds.2);
max_y = max_y.max(item_bounds.3);
let bytes = path_to_ydd_bytes(path, precision, data_version, tolerance, interval, le);
let mut item_part1_writer = ByteWriter::default();
item_part1_writer.write_int16(0x10, le); item_part1_writer.write_float32(item_bounds.0, le);
item_part1_writer.write_float32(item_bounds.1, le);
let w = item_bounds.2 - item_bounds.0;
item_part1_writer.write_float32(w, le);
let h = item_bounds.3 - item_bounds.1;
item_part1_writer.write_float32(h, le);
item_part1_writer.write_int16(0, le);
let mut item_part2_writer = ByteWriter::default();
item_part2_writer.write_int16(0, le); item_part2_writer.write_int32(60 * 1000, le); item_part2_writer.write_int8(1, le); item_part2_writer.write_int16(60, le); item_part2_writer.write_int16(20, le); item_part2_writer.write_int16(1, le); item_part2_writer.write_float32(z, le);
let mut item_writer = ByteWriter::default();
item_writer.write_int8(item_part1_writer.bytes.len() as i8, le);
item_writer.write_vec(&item_part1_writer.bytes);
item_writer.write_int8(item_part2_writer.bytes.len() as i8, le);
item_writer.write_vec(&item_part2_writer.bytes);
item_writer.write_int32(bytes.len() as i32, le);
item_writer.write_vec(&bytes);
group_writer.write_vec(&item_writer.bytes);
count += 1;
}
let mut result_writer = ByteWriter::default();
result_writer.write_ascii_string("YDMG");
let mut result_part1_writer = ByteWriter::default();
result_part1_writer.write_int8(1, le);
result_part1_writer.write_int8(0, le);
result_writer.write_int8(result_part1_writer.bytes.len() as i8, le);
result_writer.write_vec(&result_part1_writer.bytes);
let mut result_part2_writer = ByteWriter::default();
result_part2_writer.write_int16(count, le);
result_part2_writer.write_int8(0, le);
result_part2_writer.write_float32(min_x, le);
result_part2_writer.write_float32(min_y, le);
let w = max_x - min_x;
result_part2_writer.write_float32(w, le);
let h = max_y - min_y;
result_part2_writer.write_float32(h, le);
result_part2_writer.write_int32(group_writer.bytes.len() as i32, le);
result_writer.write_int8(result_part2_writer.bytes.len() as i8, le);
result_writer.write_vec(&result_part2_writer.bytes);
result_writer.write_vec(&group_writer.bytes);
result_writer.bytes
}
#[cfg(test)]
mod tests {
use crate::ydd::gcode_to_ydd_bytes;
#[test]
fn test_gcode_to_ydd_bytes() {
let input = "../rust_crates/tests/.output/path_to_gcode.gcode";
let gcode = std::fs::read_to_string(&input).unwrap();
let bytes = gcode_to_ydd_bytes(&gcode, 100, 1, 0.01, 0.0, true);
println!("{:?}", bytes);
}
}