Loading...
Loading...
Detects and visualizes geometric intersections in OpenSCAD models using built-in techniques (intersection(), debug modifiers), BOSL2 utilities (debug_this, ghost), and reusable collision check patterns. Use when checking drawer clearances, door swing interference, shelf spacing, hinge collisions, or any geometric overlap in woodworking projects. Triggers on "check collision", "detect interference", "drawer clearance", "door swing", "check overlap", "assembly interference", or "fits in cabinet". Works with .scad files, woodworkers-lib patterns, BOSL2 attachments, and OpenSCAD 2025 Manifold engine.
npx skill4agent add dawiddutoit/custom-claude openscad-collision-detection// 1. Create reusable checker module
module check_collision(show_overlap=true) {
if (show_overlap) {
color("red", 0.8) intersection() {
children(0);
children(1);
}
}
%children(0); // Ghost first object
children(1); // Solid second object
}
// 2. Apply to your objects
check_collision() {
drawer(); // Moving part
cabinet_interior(); // Fixed structure
}
// 3. Preview (F5) - red regions show collisionsintersection()%// Show collision volume
color("red") intersection() {
drawer();
cabinet_interior();
}
// If result has volume → collision exists| Modifier | Effect | Use Case |
|---|---|---|
| Transparent (ghost) | Show reference geometry |
| Highlight (red) | Emphasize specific object |
| Show only | Isolate object for testing |
| Disable | Temporarily hide geometry |
%cabinet_interior(); // Ghost
#drawer(); // Highlightinclude <BOSL2/std.scad>
debug_this() drawer(); // Shows bounding box + transparent object
ghost() cabinet(); // Semantic equivalent to %module check_collision(show_overlap=true, overlap_color="red") {
if (show_overlap) {
color(overlap_color, 0.8) intersection() {
children(0);
children(1);
}
}
%children(0); // Ghost first object
children(1); // Solid second object
}check_collision() {
drawer_extended();
cabinet_side_panel();
}module show_clearance(clearance=2, zones=true) {
// Original objects
%children(0);
children(1);
// Clearance zones
if (zones) {
color("yellow", 0.2)
offset(r=clearance)
projection(cut=false)
children(0);
}
// Collision check
color("red") intersection() {
children(0);
children(1);
}
}DEBUG_COLLISION = true; // Toggle at file top
module conditional_check() {
if (DEBUG_COLLISION) {
color("red") intersection() {
children(0);
children(1);
}
%children(0);
children(1);
} else {
children(0);
children(1);
}
}module assembly_check(explode=false) {
spacing = explode ? 50 : 0;
// Check overlaps when assembled (explode=false)
if (!explode) {
color("red", 0.8) intersection() {
children(0);
children(1);
}
}
children(0);
translate([spacing, 0, 0]) children(1);
}
// Usage
assembly_check(explode=$preview) {
cabinet_shell();
drawer_assembly();
}include <woodworkers-lib/std.scad>
module drawer_clearance_check(cabinet_dim, drawer_dim, panel=18) {
interior_w = cabinet_dim[0] - 2 * panel;
interior_d = cabinet_dim[1] - panel;
interior_h = cabinet_dim[2] - 2 * panel;
// Ghost cabinet interior
%color("blue", 0.2)
translate([panel, 0, panel])
cube([interior_w, interior_d, interior_h]);
// Show drawer
color("green", 0.5) cube(drawer_dim);
// Highlight collision
color("red") intersection() {
translate([panel, 0, panel]) cube([interior_w, interior_d, interior_h]);
cube(drawer_dim);
}
// Echo clearances
side_clearance = (interior_w - drawer_dim[0]) / 2;
echo(str("Side clearance: ", side_clearance, "mm per side"));
}module door_swing_check(door_width, swing_angle=90, adjacent_pos=500) {
// Door sweep volume
color("yellow", 0.3)
rotate([0, 0, swing_angle])
cube([door_width, 5, 720]);
// Adjacent object
translate([adjacent_pos, 0, 0])
color("green", 0.5)
cube([200, 400, 720]);
// Check interference
color("red") intersection() {
rotate([0, 0, swing_angle]) cube([door_width, 5, 720]);
translate([adjacent_pos, 0, 0]) cube([200, 400, 720]);
}
}module shelf_spacing_check(cabinet_dim, shelf_positions, item_height, panel=18) {
// Draw shelves
for (z = shelf_positions) {
translate([0, 0, z])
%planeBottom([cabinet_dim[0], cabinet_dim[1], panel]);
}
// Check spacing
for (i = [0:len(shelf_positions)-2]) {
spacing = shelf_positions[i+1] - shelf_positions[i] - panel;
if (spacing < item_height) {
echo(str("WARNING: Shelf ", i, " spacing (", spacing,
"mm) < item height (", item_height, "mm)"));
// Highlight insufficient spacing
translate([0, 0, shelf_positions[i] + panel])
color("red", 0.5)
cube([cabinet_dim[0], cabinet_dim[1], spacing]);
}
}
}!drawer(); // Show only drawer (use ! modifier)%cabinet_interior();
drawer();color("red") intersection() {
cabinet_interior();
drawer();
}
// No volume = no collisiondrawer_width = 764;
interior_width = 782;
clearance = interior_width - drawer_width;
echo(str("Total clearance: ", clearance, "mm (", clearance/2, "mm per side)"));
if (clearance < 4) {
echo("ERROR: Insufficient clearance!");
}DRAWER_CLEARANCE = 2; // mm per side
module drawer_with_clearance(interior_width) {
width = interior_width - 2*DRAWER_CLEARANCE;
cube([width, 400, 100]);
}ECHO: "Side clearance: 2.0mm per side"
ECHO: "Top clearance: 5.0mm"
ECHO: "Depth clearance: 10.0mm"ECHO: "WARNING: Drawer collision detected!"
ECHO: "Overlap volume: 15mm × 18mm × 100mm"
ECHO: "Reduce drawer width by 15mm"| Color | Meaning |
|---|---|
| Red | Collision/interference |
| Yellow | Clearance zone |
| Green | Moving parts |
| Blue | Fixed structure |
| Transparent | Reference geometry |
include <woodworkers-lib/std.scad>
module ww_collision_check(outer_dim, inner_dim) {
// Outer box (cabinet)
%color("blue", 0.2) {
planeBottom(outer_dim);
planeTop(outer_dim);
planeLeft(outer_dim, t=-1, b=-1);
planeRight(outer_dim, t=-1, b=-1);
}
// Inner box (drawer)
color("green", 0.5) {
planeBottom(inner_dim);
// ... other planes
}
}include <lib/labels.scad>
module labeled_collision_check() {
labeled_cuboid([800, 400, 100],
name="DRAWER",
box_color="green"
);
translate([0, 0, 100])
labeled_cuboid([800, 400, 18],
name="SHELF",
box_color="brown"
);
// Collision check
color("red") intersection() {
cube([800, 400, 100]);
translate([0, 0, 100]) cube([800, 400, 18]);
}
}include <BOSL2/std.scad>
diff()
cuboid([100, 100, 50])
attach(TOP) tag("remove")
cyl(d=20, h=30); // Check if penetrates too deepcolor("red", 0.5)color("red")assert()--backend CGALassert()assert(clearance >= 4, "Drawer clearance must be >= 4mm");