flower pot + generation script
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
stl/
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
#!/bin/python3
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent
|
||||||
|
SCAD_DIR = BASE_DIR / "flower_pot"
|
||||||
|
OUT_DIR = BASE_DIR / "stl"
|
||||||
|
|
||||||
|
|
||||||
|
def ask_float(prompt: str) -> float:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
value = float(input(prompt).strip())
|
||||||
|
if value <= 0:
|
||||||
|
print("Please enter a positive number.")
|
||||||
|
continue
|
||||||
|
return value
|
||||||
|
except ValueError:
|
||||||
|
print("Please enter a valid number.")
|
||||||
|
|
||||||
|
|
||||||
|
def render_scad(scad_file: Path, out_file: Path, base_radius: float, wall_height: float, wall_height_tray: float) -> None:
|
||||||
|
cmd = (
|
||||||
|
f'openscad '
|
||||||
|
f'-D base_radius={base_radius} '
|
||||||
|
f'-D wall_height={wall_height} '
|
||||||
|
f'-D wall_height_tray={wall_height_tray} '
|
||||||
|
f'-o "{out_file}" '
|
||||||
|
f'"{scad_file}"'
|
||||||
|
)
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
["bash", "-lc", cmd],
|
||||||
|
cwd=BASE_DIR,
|
||||||
|
text=True,
|
||||||
|
capture_output=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
print(f"\nFailed to render {scad_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}")
|
||||||
|
|
||||||
|
base_radius = ask_float("Flower pot radius (base_radius) in mm: ")
|
||||||
|
wall_height = ask_float("Flower pot height (wall_height) in mm: ")
|
||||||
|
wall_height_tray = ask_float("Tray height (wall_height_tray) in mm: ")
|
||||||
|
|
||||||
|
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
pot_scad = SCAD_DIR / "pot.scad"
|
||||||
|
tray_scad = SCAD_DIR / "tray.scad"
|
||||||
|
|
||||||
|
if not pot_scad.exists():
|
||||||
|
raise SystemExit(f"Missing file: {pot_scad}")
|
||||||
|
if not tray_scad.exists():
|
||||||
|
raise SystemExit(f"Missing file: {tray_scad}")
|
||||||
|
|
||||||
|
render_scad(pot_scad, OUT_DIR / "pot.stl", base_radius, wall_height, wall_height_tray)
|
||||||
|
render_scad(tray_scad, OUT_DIR / "tray.stl", base_radius, wall_height, wall_height_tray)
|
||||||
|
|
||||||
|
print("\nDone.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
// --- Parameters ---
|
||||||
|
base_radius = 45;
|
||||||
|
slot_depth = 2;
|
||||||
|
floor_thickness = 1.5;
|
||||||
|
|
||||||
|
total_base_h = slot_depth + floor_thickness;
|
||||||
|
|
||||||
|
wall_height = 110;
|
||||||
|
wall_thickness = 1.5;
|
||||||
|
flare_angle = 10;
|
||||||
|
|
||||||
|
hole_d = 8;
|
||||||
|
slot_width = 8;
|
||||||
|
$fn = 500;
|
||||||
|
|
||||||
|
// --- assembly ---
|
||||||
|
difference() {
|
||||||
|
flower_pot_body();
|
||||||
|
// radial slots
|
||||||
|
translate([0, 0, -0.1])
|
||||||
|
linear_extrude(height = slot_depth + 0.1)
|
||||||
|
radial_slots_pattern();
|
||||||
|
// drainage holes
|
||||||
|
translate([0, 0, -0.1])
|
||||||
|
linear_extrude(height = total_base_h + 0.2)
|
||||||
|
holes_pattern();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- modules ---
|
||||||
|
module flower_pot_body() {
|
||||||
|
top_x_outer = base_radius + wall_height * tan(flare_angle);
|
||||||
|
top_x_inner = top_x_outer - (wall_thickness / cos(flare_angle));
|
||||||
|
|
||||||
|
rotate_extrude() {
|
||||||
|
polygon(points = [
|
||||||
|
[0, 0],
|
||||||
|
[base_radius, 0],
|
||||||
|
[top_x_outer, wall_height + total_base_h],
|
||||||
|
[top_x_inner, wall_height + total_base_h],
|
||||||
|
[base_radius - wall_thickness, total_base_h],
|
||||||
|
[0, total_base_h]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module radial_slots_pattern() {
|
||||||
|
// 6 slots
|
||||||
|
for(a = [0 : 60 : 359]) {
|
||||||
|
rotate([0, 0, a])
|
||||||
|
translate([base_radius / 2, 0, 0])
|
||||||
|
square([base_radius + 5, slot_width], center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module holes_pattern() {
|
||||||
|
union() {
|
||||||
|
circle(d = hole_d);
|
||||||
|
|
||||||
|
for(r = [18, 30]) {
|
||||||
|
for(a = [0 : 60 : 359]) {
|
||||||
|
rotate([0, 0, a])
|
||||||
|
translate([r, 0, 0])
|
||||||
|
circle(d = hole_d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// --- Parameters ---
|
// --- Parameters ---
|
||||||
base_radius = 55;
|
base_radius = 55;
|
||||||
wall_height = 20;
|
wall_height_tray = 20;
|
||||||
thickness = 1.5;
|
thickness = 1.5;
|
||||||
flare_angle = 20;
|
flare_angle = 20;
|
||||||
$fn = 500;
|
$fn = 500;
|
||||||
@@ -11,8 +11,8 @@ rotate_extrude() {
|
|||||||
polygon(points = [
|
polygon(points = [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[base_radius, 0],
|
[base_radius, 0],
|
||||||
[base_radius + wall_height * tan(flare_angle), wall_height],
|
[base_radius + wall_height_tray * tan(flare_angle), wall_height_tray],
|
||||||
[base_radius + wall_height * tan(flare_angle) - (thickness / cos(flare_angle)), wall_height],
|
[base_radius + wall_height_tray * tan(flare_angle) - (thickness / cos(flare_angle)), wall_height_tray],
|
||||||
[base_radius - thickness, thickness],
|
[base_radius - thickness, thickness],
|
||||||
[0, thickness]
|
[0, thickness]
|
||||||
]);
|
]);
|
||||||
|
|||||||
Reference in New Issue
Block a user