///|
/// 05-gridfinity-compatible-bin
///
/// A maker-friendly storage bin generator.
///
/// Usage (stdout):
/// moon run --target native examples/05-gridfinity-compatible-bin -- --rows 2 --cols 1 > bin.step
const GRID_UNIT : Double = 42.0
///|
const WALL_THICKNESS : Double = 2.0
///|
const BASE_THICKNESS : Double = 2.0
///|
async fn main {
let base_args_spec = {
"rows": @cli.opt_double(
1.0,
help="Number of grid units in Y (rows)",
min=1.0,
),
"cols": @cli.opt_double(
1.0,
help="Number of grid units in X (cols)",
min=1.0,
),
"height": @cli.opt_double(
30.0,
help="Total bin height (mm)",
min=BASE_THICKNESS + 1.0,
),
"text": @cli.opt_string(help="Label text to engrave"),
"fontSize": @cli.opt_double(
0.0,
help="Font size (mm), default is 60% of wall height",
min=0.0,
),
"depth": @cli.opt_double(
0.5,
help="Engraving depth (mm)",
min=0.0,
max=WALL_THICKNESS - 0.1,
),
}
let args_spec = @cli.with_translate(@common.with_output_args(base_args_spec))
guard @cli.parse(
args_spec,
prog="05-gridfinity-compatible-bin",
description="Generate a Gridfinity-compatible storage bin.",
)
is Some(args) else {
return
}
let rows = args.double("rows").to_int()
let cols = args.double("cols").to_int()
let height = args.double("height")
let text_opt = args.string_opt("text")
let font_size_opt = args.double("fontSize")
let emboss_depth = args.double("depth")
let output = @common.output_paths(args)
let (tx, ty, tz) = match args.translate_xyz() {
Some(v) => v
None => {
@cli.eprintln("error: invalid translation")
return
}
}
let total_width = Double::from_int(cols) * GRID_UNIT
let total_length = Double::from_int(rows) * GRID_UNIT
let mut design = @cad.Design::new(
name="gridfinity-bin",
documentation=args.documentation(),
)
// 1. The Base
let base = @cad.Cuboid::new(total_width, total_length, BASE_THICKNESS)
.with_name("bin-base")
.with_color(@cad.Rgb::red())
.translate(x=tx, y=ty, z=tz)
design = design.add(base)
// 2. Outer Walls
let outer_poly = [
(0.0, 0.0),
(total_width, 0.0),
(total_width, total_length),
(0.0, total_length),
]
// The hole is wound opposite to the outer boundary.
let inner_poly = [
(WALL_THICKNESS, WALL_THICKNESS),
(total_width - WALL_THICKNESS, WALL_THICKNESS),
(total_width - WALL_THICKNESS, total_length - WALL_THICKNESS),
(WALL_THICKNESS, total_length - WALL_THICKNESS),
].rev()
let wall_height = height - BASE_THICKNESS
let walls = @cad.ExtrudedProfile::new(outer_poly, wall_height, holes=[
inner_poly,
])
.with_name("bin-walls")
.with_color(@cad.Rgb::cyan())
.translate(x=tx, y=ty, z=tz + BASE_THICKNESS)
design = design.add(walls)
// 3. Internal Dividers
for i in 1.. {
let font = @cad.load_font("baloo")
if font_size_opt > 0.0 {
design = design.add_text_on_face(
walls,
label,
Back, // min_y face
font,
font_size=font_size_opt,
emboss_depth~,
color=@cad.Rgb::orange(),
)
} else {
design = design.add_text_on_face(
walls,
label,
Back, // min_y face
font,
emboss_depth~,
color=@cad.Rgb::orange(),
)
}
}
None => ()
}
@common.write_output(design, output)
}