pill container: script to generate the STL files

This commit is contained in:
sam.hadow committed 2026-10-05 11:47:03 +02:00
1 parent 16e69fb10d
commit 7620cec17d
3 files changed
+138

No files matched your search

+7
View File
@@ -28,3 +28,10 @@ To generate the box and lid STL file:
```bash ```bash
python parametric_box.py python parametric_box.py
``` ```
### pill_container
Parameterized pill containers with a sliding lid.
To generate the box and lid STL file:
```bash
python pill_container.py
```
+118
View File
@@ -0,0 +1,118 @@
#!/bin/python3
from __future__ import annotations
import json
import subprocess
import sys
from pathlib import Path
from utils import ask_float, ask_int, ask_yes_no
BASE_DIR = Path(__file__).resolve().parent
SCAD_DIR = BASE_DIR / "pill_container"
OUT_DIR = BASE_DIR / "stl"
DAYS_OF_WEEK = [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",
]
def render_scad(
scad_file: Path,
out_file: Path,
inner_dimension: float,
cases: int,
engraving: str,
) -> None:
"""Render one pill container to an STL file."""
cmd = [
"openscad",
"-D",
f"X={inner_dimension}",
"-D",
f"cases={cases}",
"-D",
f"engraving={json.dumps(engraving)}",
"-D",
'part="plate"',
"-o",
str(out_file),
str(scad_file),
]
result = subprocess.run(
cmd,
cwd=BASE_DIR,
text=True,
capture_output=True,
)
if result.returncode != 0:
print(f"\nFailed to render {out_file.name}")
if result.stdout:
print(result.stdout)
if result.stderr:
print(result.stderr, file=sys.stderr)
raise SystemExit(result.returncode)
print(f"Generated {out_file}")
def main() -> None:
if not SCAD_DIR.exists():
raise SystemExit(f"Missing SCAD directory: {SCAD_DIR}")
scad_file = SCAD_DIR / "pill_container.scad"
if not scad_file.exists():
raise SystemExit(f"Missing OpenSCAD file: {scad_file}")
print("Pill container generator\n")
print("Dimensions less than 20 mm may result in unusable STL files.\n")
use_day_engraving = ask_yes_no("Generate engraved containers for each day of the week? [y/n]: ")
inner_dimension = ask_float("Inner compartment dimension in mm (recommended 20mm): ")
cases = ask_int("Number of compartments (cases): ")
OUT_DIR.mkdir(parents=True, exist_ok=True)
if use_day_engraving:
for day in DAYS_OF_WEEK:
output_file = OUT_DIR / f"pill-container-{day.lower()}.stl"
render_scad(
scad_file=scad_file,
out_file=output_file,
inner_dimension=inner_dimension,
cases=cases,
engraving=day,
)
else:
output_file = OUT_DIR / "pill-container.stl"
render_scad(
scad_file=scad_file,
out_file=output_file,
inner_dimension=inner_dimension,
cases=cases,
engraving="",
)
print("\nDone.")
if __name__ == "__main__":
main()
+13
View File
@@ -26,3 +26,16 @@ def ask_float(prompt: str) -> float:
return value return value
except ValueError: except ValueError:
print("Please enter a valid number.") print("Please enter a valid number.")
def ask_yes_no(prompt: str) -> bool:
"""Prompt the user for a yes/no answer."""
while True:
answer = input(prompt).strip().lower()
if answer in {"y", "yes"}:
return True
if answer in {"n", "no"}:
return False
print("Please enter yes or no. [y/n]")