use crate::error::Error;
use crate::shape::{BooleanShape, Shape};
use glam::DVec3;
fn extrude_tool_faces(result: &BooleanShape, delta: DVec3) -> Result<Shape, Error> {
let mut filler: Option<Shape> = None;
for face in result.shape.faces().filter(|f| result.is_tool_face(f)) {
let extruded = Shape::from(face.extrude(delta)?);
filler = Some(match filler {
None => extruded,
Some(f) => Shape::from(f.union(&extruded)?),
});
}
Ok(filler.unwrap_or_else(Shape::empty))
}
pub fn revolve_section(
shape: &Shape,
origin: DVec3,
axis_direction: DVec3,
plane_normal: DVec3,
angle: f64,
) -> Result<Shape, Error> {
let half = Shape::half_space(origin, -plane_normal.normalize());
let intersect_result = shape.intersect(&half)?;
let mut result: Option<Shape> = None;
for face in intersect_result.shape.faces().filter(|f| intersect_result.is_tool_face(f)) {
let revolved = Shape::from(face.revolve(origin, axis_direction, angle)?);
result = Some(match result {
None => revolved,
Some(r) => Shape::from(r.union(&revolved)?),
});
}
Ok(result.unwrap_or_else(Shape::empty))
}
pub fn helix_section(
shape: &Shape,
origin: DVec3,
axis_direction: DVec3,
plane_normal: DVec3,
pitch: f64,
turns: f64,
) -> Result<Shape, Error> {
let half = Shape::half_space(origin, -plane_normal.normalize());
let intersect_result = shape.intersect(&half)?;
let mut result: Option<Shape> = None;
for face in intersect_result.shape.faces().filter(|f| intersect_result.is_tool_face(f)) {
let swept = Shape::from(face.helix(origin, axis_direction, pitch, turns, false)?);
result = Some(match result {
None => swept,
Some(r) => Shape::from(r.union(&swept)?),
});
}
Ok(result.unwrap_or_else(Shape::empty))
}
pub fn stretch_vector(shape: &Shape, origin: DVec3, delta: DVec3) -> Result<Shape, Error> {
let half = Shape::half_space(origin, -delta.normalize());
let intersect_result = shape.intersect(&half)?;
let part_pos = Shape::from(shape.subtract(&half)?).translated(delta);
let filler = extrude_tool_faces(&intersect_result, delta)?;
let part_neg = intersect_result.shape;
let combined = Shape::from(part_neg.union(&filler)?);
combined.union(&part_pos).map(Shape::from)
}