///|
/// 33-filament-runout-sensor-housing
///
/// A housing generator with controlled clearances for switches and fasteners.
/// Demonstrates complex assemblies, rounded profiles, and face-based engraving.
///
/// Usage (stdout):
/// moon run --target native examples/33-filament-runout-sensor-housing -- > housing.step
///
/// Usage (write file):
/// moon run --target native examples/33-filament-runout-sensor-housing -- -o housing.step
async fn main {
let base_args_spec = {
"bodyLength": @cli.opt_double(
45.0,
help="Housing body length (mm)",
min=0.0,
min_exclusive=true,
),
"bodyWidth": @cli.opt_double(
30.0,
help="Housing body width (mm)",
min=0.0,
min_exclusive=true,
),
"bodyHeight": @cli.opt_double(
18.0,
help="Housing body height (mm)",
min=0.0,
min_exclusive=true,
),
"wallThickness": @cli.opt_double(
3.0,
help="Wall thickness (mm)",
min=0.0,
min_exclusive=true,
),
"filamentDia": @cli.opt_double(
1.75,
help="Filament diameter (mm)",
min=0.0,
min_exclusive=true,
),
"filamentClearance": @cli.opt_double(
0.6,
help="Clearance around filament (mm)",
min=0.0,
),
"switchWidth": @cli.opt_double(
20.0,
help="Microswitch width (mm)",
min=0.0,
min_exclusive=true,
),
"switchLength": @cli.opt_double(
10.0,
help="Microswitch length (mm)",
min=0.0,
min_exclusive=true,
),
"switchHeight": @cli.opt_double(
6.0,
help="Microswitch height (mm)",
min=0.0,
min_exclusive=true,
),
}
let args_spec = @cli.with_translate(@common.with_output_args(base_args_spec))
guard @cli.parse(
args_spec,
prog="33-filament-runout-sensor-housing",
description="Generate a filament runout sensor housing.",
)
is Some(args) else {
return
}
let body_l = args.double("bodyLength")
let body_w = args.double("bodyWidth")
let body_h = args.double("bodyHeight")
let wall = args.double("wallThickness")
let fil_path_dia = args.double("filamentDia") +
args.double("filamentClearance")
let sw_w = args.double("switchWidth")
let sw_l = args.double("switchLength")
let sw_h = args.double("switchHeight")
let output = @common.output_paths(args)
let (tx, ty, tz) = match args.translate_xyz() {
Some(v) => v
None => {
@cli.eprintln("error: invalid translation")
abort("")
}
}
// 1. Main Housing Body (Side-view extrusion to include filament bore)
let body_radius = 4.0
let n = 8
let side_pts = []
// Bottom-right arc
side_pts.push_iter(
@cad.Profile2D::arc(
2.0 * body_radius,
1.5 * @math.PI,
2.0 * @math.PI,
segments=n,
)
.iter()
.map(fn(p) { (p.0 + body_l - body_radius, p.1 + body_radius) }),
)
// Top-right arc
side_pts.push_iter(
@cad.Profile2D::arc(2.0 * body_radius, 0.0, 0.5 * @math.PI, segments=n)
.iter()
.map(fn(p) { (p.0 + body_l - body_radius, p.1 + body_h - body_radius) }),
)
// Top-left arc
side_pts.push_iter(
@cad.Profile2D::arc(2.0 * body_radius, 0.5 * @math.PI, @math.PI, segments=n)
.iter()
.map(fn(p) { (p.0 + body_radius, p.1 + body_h - body_radius) }),
)
// Bottom-left corner (SHARP) - this corner touches the mounting bracket
side_pts.push((0.0, 0.0))
let fil_hole = @cad.Profile2D::circle(fil_path_dia).rev()
let fil_hole_translated = @cad.translate_pts(
fil_hole,
body_l / 2.0,
body_h / 2.0,
)
let housing = @cad.ExtrudedProfile::new(side_pts, body_w, holes=[
fil_hole_translated,
])
.with_name("housing")
.with_color(@cad.Rgb::new(0.6, 0.2, 0.8)) // Vibrant Purple
.rotate_x(90.0)
.translate(x=tx - body_l / 2.0, y=ty + body_w / 2.0, z=tz)
// 2. Mounting Flange
let flange_w = body_w + 15.0
let flange_l = 12.0
let flange_outer = @cad.Profile2D::rounded_rect(flange_l, flange_w, 3.0)
let m_hole = @cad.Profile2D::circle(4.0).rev()
let flange_holes = [
@cad.translate_pts(m_hole, flange_l / 2.0, 5.0),
@cad.translate_pts(m_hole, flange_l / 2.0, flange_w - 5.0),
]
let flange = @cad.ExtrudedProfile::new(flange_outer, wall, holes=flange_holes)
.with_name("flange")
.with_color(@cad.Rgb::new(0.4, 0.1, 0.6)) // Darker Purple
.rotate_y(-90.0)
.translate(x=tx - body_l / 2.0, y=ty - flange_w / 2.0, z=tz)
// 3. The Microswitch (Placeholder)
let switch = @cad.Cuboid::new(sw_w, sw_l, sw_h)
.with_name("microswitch")
.with_color(@cad.Rgb::magenta())
.translate(x=tx - sw_w / 2.0, y=ty - sw_l / 2.0, z=tz + body_h / 2.0 + 1.0)
// 4. Design and Labels
let font = @cad.load_font("baloo")
let design = @cad.Design::new(
name="filament-runout-sensor",
documentation=args.documentation(),
)
.add(housing)
.add(flange)
.add(switch)
.add_text_on_face(
housing,
"FILAMENT",
Front,
font,
font_size=4.0,
offset_y=4.0,
rotation=180.0,
)
.add_text_on_face(
housing,
"SENSOR",
Front,
font,
font_size=4.0,
offset_y=-4.0,
rotation=180.0,
)
@common.write_output(design, output)
}