use anyhow::{anyhow, Result};
use crate::instructions::*;
use crate::program::*;
use crate::types::*;
use crate::utils::*;
#[derive(Debug, Clone)]
pub struct Arc {
pub from: Vector3,
pub to: Vector3,
pub center: Vector3,
pub axis: Axis,
pub direction: Direction,
}
impl Arc {
#[must_use]
pub fn new(
from: Vector3,
to: Vector3,
center: Vector3,
axis: Axis,
direction: Direction,
) -> Self {
Self {
from,
to,
center,
axis,
direction,
}
}
#[must_use]
pub fn radius(&self) -> f64 {
self.from
.distance_to(self.center)
.max(self.to.distance_to(self.center))
}
#[must_use]
pub fn bounds(&self) -> Bounds {
Bounds {
min: Vector3::default(),
max: Vector3::default(),
}
}
pub fn to_instructions(&self, context: InnerContext) -> Result<Vec<Instruction>> {
let distance_from = self.from.distance_to(self.center);
let distance_to = self.to.distance_to(self.center);
if (distance_from - distance_to).abs() > 0.0001 {
return Err(anyhow!(
"Arc distances from/center ({:.2} {}) and to/center ({:.2} {}) must be equal",
distance_from,
context.units(),
distance_to,
context.units(),
));
}
let mut instructions = vec![];
instructions.append(&mut vec![
Instruction::Empty(Empty {}),
Instruction::Comment(Comment {
text: format!(
"Cut arc {} at axis {}, from: x = {}, y = {}, z = {}, to: x = {}, y = {}, z = {}",
self.direction,
self.axis,
round_precision(self.from.x),
round_precision(self.from.y),
round_precision(self.from.z),
round_precision(self.to.x),
round_precision(self.to.y),
round_precision(self.to.z),
),
}),
Instruction::G0(G0 {
x: None,
y: None,
z: Some(context.z_safe()),
}),
Instruction::G0(G0 {
x: Some(self.from.x),
y: Some(self.from.y),
z: None,
}),
Instruction::G1(G1 {
x: None,
y: None,
z: Some(self.from.z),
f: Some(context.tool().feed_rate()),
}),
]);
match self.axis {
Axis::X => {
instructions.push(Instruction::G19(G19 {}));
}
Axis::Y => {
instructions.push(Instruction::G18(G18 {}));
}
Axis::Z => {
instructions.push(Instruction::G17(G17 {}));
}
}
match self.direction {
Direction::Clockwise => {
instructions.push(Instruction::G2(G2 {
x: Some(self.to.x),
y: Some(self.to.y),
z: Some(self.to.z),
i: Some(self.center.x - self.from.x),
j: Some(self.center.y - self.from.y),
k: Some(self.center.z - self.from.z),
r: None,
p: None,
f: Some(context.tool().feed_rate()),
}));
}
Direction::Counterclockwise => {
instructions.push(Instruction::G3(G3 {
x: Some(self.to.x),
y: Some(self.to.y),
z: Some(self.to.z),
i: Some(self.center.x - self.from.x),
j: Some(self.center.y - self.from.y),
k: Some(self.center.z - self.from.z),
r: None,
p: None,
f: Some(context.tool().feed_rate()),
}));
}
}
instructions.append(&mut vec![
Instruction::G17(G17 {}),
Instruction::G0(G0 {
x: None,
y: None,
z: Some(context.z_safe()),
}),
]);
Ok(instructions)
}
}