[User]
I'd like to create a customizable maze in the shape of a Mickey Mouse head, based on a circular maze generator I found. The maze should be formed by concentric circular paths and radial walls, and should be 3D printable.

Here's a breakdown of what I need:

1.  **Overall Shape:** The maze should have a main circular body (Mickey's face) and two smaller circles (Mickey's ears) attached to it.

2.  **Maze Structure:** The maze itself should consist of concentric circular paths, separated by radial walls. The concentric circles should begin from a small starting circle and go outwards.

3.  **Customizable Parameters:**
    *   `radius`: The radius of the main circular face of the maze.
    *   `wall_height`: The height of the maze walls.
    *   `wall_thickness`: The thickness of the maze walls.
    *   `cblocks`: The number of circular blocks, controlling the angular resolution of the maze. This will control how many radial walls form around each circular path.
    *   `rblocks`: The number of radial blocks, controlling the number of concentric circular paths in the maze.
	*   `face_bottom`: A boolean parameter that controls whether there is a solid circular bottom beneath the face (default is `YES`).
	*  `ears_bottom`: A boolean parameter that controls whether there are solid circular bottoms beneath the ears (default is `YES`).

4.  **Maze Generation:**  The maze pattern should be generated algorithmically using a randomized depth-first search approach. This will prevent trivial solutions. I need the algorithm to start from the center and carve paths outwards. It should do this by deleting walls randomly between blocks, ensuring that all areas of the maze are reachable from a central start point. The `PERMUTATION_OF_FOUR` constant in the example gives the order of directions for the maze generation. The directions 1, 2, 3, and 4 correspond to the right, up, left, and down, relative to a starting block, respectively.

5.  **Wall Creation:** The walls should be created between the blocks, in the directions specified by the maze-generation algorithm.

6.  **Ear Positioning:** The ears should be placed symmetrically on the main circle, and their positions should be determined based on the `radius` of the main circle. They should also have their own internal circular mazes using the same algorithms and wall thickness as the main face. Their `cblocks` should be two-thirds that of the main face, rounded down to an integer.

7.  **Bottom:** There should be a configurable option to have a bottom solid piece for the face and/or ears.

I don't need any libraries included, but please be sure to use comments in the code to explain what you're doing.

[Assistant]
maze_mickey_.scad:
```
radius = 20;

wall_height = 2;
wall_thickness = 1;

cblocks = 25;
rblocks = 5;

face_bottom = "YES";
ears_bottom = "YES";

/*
 * constants, for clearness
 *
 */

// random directions, for picking up a direction to visit the next block
function PERMUTATION_OF_FOUR() = [
    [1, 2, 3, 4],
    [1, 2, 4, 3],
    [1, 3, 2, 4],
    [1, 3, 4, 2],
    [1, 4, 2, 3],
    [1, 4, 3, 2],
    [2, 1, 3, 4],
    [2, 1, 4, 3],
    [2, 3, 1, 4],
    [2, 3, 4, 1],
    [2, 4, 1, 3],
    [2, 4, 3, 1],
    [3, 1, 2, 4],
    [3, 1, 4, 2],
    [3, 2, 1, 4],
    [3, 2, 4, 1],
    [3, 4, 1, 2],
    [3, 4, 2, 1],
    [4, 1, 2, 3],
    [4, 1, 3, 2],
    [4, 2, 1, 3],
    [4, 2, 3, 1],
    [4, 3, 1, 2],
    [4, 3, 2, 1]
];

function NO_WALL() = 0;
function UP_WALL() = 1;
function RIGHT_WALL() = 2;
function UP_RIGHT_WALL() = 3;

function NOT_VISITED() = 0;
function VISITED() = 1;

/*
 * modules for creating a maze
 *
 */

function PI() = 3.14159;

module a_quarter_arc(radius, angle, width = 1) {
    outer = radius + width;
    intersection() {
        difference() {
            offset(r = width) circle(radius, $fn=96);
            circle(radius, $fn=96);
        }
        polygon([[0, 0], [outer, 0], [outer, outer * sin(angle)], [outer * cos(angle), outer * sin(angle)]]);
    }
}

module arc(radius, angles, width = 1) {
    angle_from = angles[0];
    angle_to = angles[1];
    angle_difference = angle_to - angle_from;
    outer = radius + width;
    rotate(angle_from)
        if(angle_difference <= 90) {
            a_quarter_arc(radius, angle_difference, width);
        } else if(angle_difference > 90 && angle_difference <= 180) {
            arc(radius, [0, 90], width);
            rotate(90) a_quarter_arc(radius, angle_difference - 90, width);
        } else if(angle_difference > 180 && angle_difference <= 270) {
            arc(radius, [0, 180], width);
            rotate(180) a_quarter_arc(radius, angle_difference - 180, width);
        } else if(angle_difference > 270 && angle_difference <= 360) {
            arc(radius, [0, 270], width);
            rotate(270) a_quarter_arc(radius, angle_difference - 270, width);
       }
}

/*
 * utilities functions
 *
 */

// comare the equality of [x1, y1] and [x2, y2]
function cord_equals(cord1, cord2) = cord1 == cord2;

// is the point visited?
function not_visited(cord, vs, index = 0) =
    index == len(vs) ? true :
        (cord_equals([vs[index][0], vs[index][1]], cord) && vs[index][2] == 1 ? false :
            not_visited(cord, vs, index + 1));

// pick a direction randomly
function rand_dirs() =
    PERMUTATION_OF_FOUR()[round(rands(0, 24, 1)[0])];

// replace v1 in the vector with v2
function replace(v1, v2, vs) =
    [for(i = [0:len(vs) - 1]) vs[i] == v1 ? v2 : vs[i]];

/*
 * functions for generating a maze vector
 *
 */

// initialize a maze
function init_maze(rows, columns) =
    [
	    for(c = [1 : columns])
	        for(r = [1 : rows])
		        [c, r, 0,  UP_RIGHT_WALL()]
	];

// find a vector in the maze vector
function find(i, j, maze_vector, index = 0) =
    index == len(maze_vector) ? [] : (
        cord_equals([i, j], [maze_vector[index][0], maze_vector[index][1]]) ? maze_vector[index] : find(i, j, maze_vector, index + 1)
    );

////
// NO_WALL = 0;
// UP_WALL = 1;
// RIGHT_WALL = 2;
// UP_RIGHT_WALL = 3;
function delete_right_wall(original_block) =
    original_block == NO_WALL() || original_block == RIGHT_WALL() ? NO_WALL() : UP_WALL();

function delete_up_wall(original_block) =
    (original_block == NO_WALL() || original_block == UP_WALL()) ? NO_WALL() : RIGHT_WALL();

function delete_right_wall_of(vs, is_visited, maze_vector) =
    replace(vs, [vs[0], vs[1] , is_visited, delete_right_wall(vs[3])] ,maze_vector);

function delete_up_wall_of(vs, is_visited, maze_vector) =
    replace(vs, [vs[0], vs[1] , is_visited, delete_up_wall(vs[3])] ,maze_vector);

function go_right(i, j, rows, columns, maze_vector) =
    go_maze(i + 1, j, rows, columns, delete_right_wall_of(find(i, j, maze_vector), VISITED(), maze_vector));

function go_up(i, j, rows, columns, maze_vector) =
    go_maze(i, j - 1, rows, columns, delete_up_wall_of(find(i, j, maze_vector), VISITED(), maze_vector));

function visit(v, maze_vector) =
    replace(v, [v[0], v[1], VISITED(), v[3]], maze_vector);

function go_left(i, j, rows, columns, maze_vector) =
    go_maze(i - 1, j, rows, columns, delete_right_wall_of(find(i - 1, j, maze_vector), NOT_VISITED(), maze_vector));

function go_down(i, j, rows, columns, maze_vector) =
    go_maze(i, j + 1, rows, columns, delete_up_wall_of(find(i, j + 1, maze_vector), NOT_VISITED(), maze_vector));

function go_maze(i, j, rows, columns, maze_vector) =
    look_around(i, j, rand_dirs(), rows, columns, visit(find(i, j, maze_vector), maze_vector));

function look_around(i, j, dirs, rows, columns, maze_vector, index = 0) =
    index == 4 ? maze_vector :
        look_around(
            i, j, dirs,
            rows, columns,
            build_wall(i, j, dirs[index], rows, columns, maze_vector),
            index + 1
        );

function build_wall(i, j, n, rows, columns, maze_vector) =
    n == 1 && i != columns && not_visited([i + 1, j], maze_vector) ? go_right(i, j, rows, columns, maze_vector) : (
        n == 2 && j != 1 && not_visited([i, j - 1], maze_vector) ? go_up(i, j, rows, columns, maze_vector)  : (
            n == 3 && i != 1 && not_visited([i - 1, j], maze_vector) ? go_left(i, j,rows, columns,  maze_vector)  : (
                n == 4 && j != rows && not_visited([i, j + 1], maze_vector) ? go_down(i, j, rows, columns, maze_vector) : maze_vector
            )
        )
    );

module x_line(point, length, thickness = 1) {
    offset = thickness / 2;
    translate([point[0] - offset, point[1] - offset, 0])
        square([length + thickness, thickness]);
}

module circle_maze(radius, cblocks, rblocks, thickness = 1) {
    full_circle_angle = 360;
    arc_angle = full_circle_angle / cblocks;
	length_rblock = radius / rblocks ;
	rows = rblocks - 2;

	maze = go_maze(1, 1, cblocks, rows, replace([rows, cblocks, 0, UP_RIGHT_WALL()], [rows, cblocks, 0, UP_WALL()], init_maze(cblocks, rows)));

	// inner circle
	rotate([0, 0, 180])
	    arc(length_rblock, [0, full_circle_angle - arc_angle], thickness);

	rotate([0, 0, 315])
	    x_line([length_rblock + thickness / 2, 0], length_rblock, thickness);

	rotate([0, 0, arc_angle])
	    arc(length_rblock * 2, [0, full_circle_angle - arc_angle], thickness);

	// maze
    for(i = [0:len(maze) - 1]) {
        cord = maze[i];
		cr = cord[0] + 2;
		cc = cord[1] - 1;
        v = cord[3];

        if(v == 1 || v == 3) {
		    rotate([0, 0, cc * arc_angle])
                x_line([(cr - 1)* length_rblock + thickness / 2, 0], length_rblock, thickness);
        }
        if(v == 2 || v == 3) {
		    rotate([0, 0, cc * arc_angle])
		        arc(cr * length_rblock, [0, arc_angle + 0.01], thickness);
        }

		if(v == 0 || v == 1) {
		    r1 = length_rblock * 2;
			r2 = cr * length_rblock;
		    rotate([0, 0, cc * arc_angle])
		        arc(cr * length_rblock, [0, arc_angle * (r2 - r1) / r2], thickness);
		}
    }
}

module mickey_maze(radius, cblocks, rblocks, thickness = 1) {
    // face
	difference() {
		circle_maze(radius, cblocks, rblocks, wall_thickness);

		union() {
		    rotate([0, 0, 91])
				arc(radius - wall_thickness / 2, [0, 360 / cblocks], wall_thickness * 2);
			rotate([0, 0, -360 / cblocks - 2])
				arc(radius - wall_thickness / 2, [0, 360 / cblocks], wall_thickness * 2);
		}
	}

	ear_cblocks = 2 * (cblocks - cblocks % 3) / 3;

	// ear1
	translate([radius * 1.68, -radius * 0.275, 0])
	    rotate([0, 0, 181.5])
		    circle_maze(radius / 1.5, ear_cblocks, rblocks, wall_thickness);

	// ear2
	translate([-radius * 0.275, radius * 1.68, 0])
		rotate([0, 0, -67])
			circle_maze(radius / 1.5, ear_cblocks, rblocks, wall_thickness);
}

module mickey_maze_bottom(radius, cblocks, rblocks, thickness = 1, face_bottom = "YES", ears_bottom = "YES") {
    linear_extrude(wall_thickness) union() {
		if(face_bottom == "YES") {
			circle(radius + wall_thickness, $fn = 96);
		}

		// ears
		if(ears_bottom == "YES") {
			translate([radius * 1.68, -radius * 0.275, 0])
				circle(radius / 1.5 + wall_thickness, $fn = 96);

			translate([-radius * 0.275, radius * 1.68, 0])
				circle(radius / 1.5 + wall_thickness, $fn = 96);
		}
	}
}

if(face_bottom == "YES" || ears_bottom == "YES") {
	mickey_maze_bottom(radius, cblocks, rblocks, wall_thickness, face_bottom, ears_bottom);

	linear_extrude(wall_height + wall_thickness)
		mickey_maze(radius, cblocks, rblocks, wall_thickness);
} else {
	linear_extrude(wall_height)
		mickey_maze(radius, cblocks, rblocks, wall_thickness);
}
```


[User]
I'm trying to design a leaf catcher for my parking's water drain, and I've got a basic idea, but I'd really like it to be parametric so I can adjust it for different drains. The core idea is a cylinder that fits into the drain, and then a series of concentric rings on top to catch leaves.

Here's what I envision:

*   **A cylindrical insert:** This part fits inside the drain. I need to be able to adjust the diameter of this cylinder, its length, and the thickness of its walls.
*   **Concentric filter rings:** On top of the insert, I want a set of concentric rings that act as a filter. The rings should get progressively larger moving outwards from the center. I need to be able to control the number of rings, their thickness, and the spacing between them.
*   **Outer ring:** The filter needs a final, outermost ring that's larger than the insert, to keep leaves from just sliding off the edge. I'd like to set the outer ring's diameter.
*   **Assembly:** All parts should be designed to be joined in a single object.

I'd like the following parameters to be easily adjustable:

*   `tube_diameter`: The outer diameter of the cylindrical insert.
*   `insert_length`: The length of the insert.
*   `wall_thickness`: The thickness of the insert's walls.
*   `filter_diameter`: The outer diameter of the outermost filter ring.
*  `filter_thickness`: The thickness of the filter rings.
*   `filter_number_of_rings`: The number of concentric filter rings (not including the outermost one).

Could you generate an OpenSCAD file that implements this design? I'm not really concerned with the preview quality.

[Assistant]
leaf_catcher.scad:
```
//parameters -----------------------------------------------
tube_diameter=110;
insert_length=25;
wall_thickness=3;

filter_diameter=120;
filter_thickness=5;
filter_number_of_rings=5;

//fine setting ---------------------------------------------
$fn=2000;

//calculations ---------------------------------------------
tube_radius=tube_diameter/2;
filter_radius=filter_diameter/2;

//design ---------------------------------------------------

//FILTER
// init vars for filter rings
ring_radius=(tube_diameter)/((filter_number_of_rings+2)*2)/2;
holder_length=tube_radius*2-wall_thickness;
//INSERT
union(){
	difference(){
		translate([0,0,filter_thickness])
		cylinder(insert_length,tube_radius,tube_radius,center = false);
		cylinder(insert_length+10,tube_radius-wall_thickness,tube_radius-wall_thickness,center = false);
	}

	// rings starting from center

	//center spot
	cylinder(filter_thickness,ring_radius,ring_radius,center = false );
	//filter holder

	translate([-holder_length/2,-ring_radius/2,0]) cube([holder_length,ring_radius,(filter_thickness*2)]);
	translate([-ring_radius/2,-holder_length/2,0]) cube([ring_radius,holder_length,(filter_thickness*2)]);

	// rings
	for(i=[(ring_radius+ring_radius):(ring_radius+ring_radius):tube_radius]){
		//translate([0,i,0]) cube(ring_radius);
		difference(){
			cylinder(filter_thickness,i,i,center = false);
			cylinder(filter_thickness,(i-ring_radius),(i-ring_radius),center = false);
		}

	}
	// external ring

	difference(){
		cylinder(filter_thickness,filter_radius,filter_radius,center = false);
		cylinder(filter_thickness,tube_radius,tube_radius,center = false);
	}
}

```


[User]
Okay, I need a parametric fan mount for an E3D V6 hotend, and I'd like it to be configurable in a few ways.

First, the mount should clamp around the hotend's heatsink. I need to be able to adjust the diameter of this clamp to fit different heatsink sizes; let's call this parameter `heatsinkDiameter`. It should have a reasonable range, say from 15mm to 29mm.  Also, the clamp arms should have adjustable length – let's call this `clampLength`, and allow it to vary between 18.125mm and 32.5mm, in increments of 0.125mm.

Second, I want the option to mount one or two 30mm side-mounted cooling fans. A parameter, `doubleSideFan`, should control this; `1` for two fans (one on each side of the hotend), and `0` for a single fan.

Third, I'd also like to include an optional notch for a z-probe screw. This should be controlled by a `zProbeScrew` parameter, where `1` means the notch is present and `0` means it is absent. When `zProbeScrew` is `1`, I need another parameter, `zProbeScrewHeight`, to adjust the height of that notch. This should be adjustable between 0 and 26mm.

The mount should also have screw holes for the 40mm fan. I'd like the mount to resemble the one in the linked Thingiverse remix (https://www.thingiverse.com/thing:1531997), but it should be a complete rebuild and not a modification of the included OpenSCAD file, which I have copied below for reference:

```
/* [Hotend] */

// Hotend's heatsink diameter
heatsinkDiameter = 25;  // [15:29]
// Length of the clamp
clampLength = 30;  // [18.125:0.125:32.5]
// Z-Probe screw notch
zProbeScrew = 0;  // [1:Present, 0:Absent]
// Height of the Z-Probe Screw
zProbeScrewHeight = 12;  // [0:26]

/* [Fans] */

// Number of fans
doubleSideFan = 0;  // [1:Double, 0:Single]

// E3D V6 chinese clone placeholder
% union() {
  cylinder(30, heatsinkDiameter / 2, heatsinkDiameter / 2, $fn = 200);
  translate([0, 0, 30]) cylinder(6, 3, 3);
  translate([-14.5, -10, 36]) cube([20, 20, 10]);
  translate([0, 0, 46]) cylinder(4, 3, 3);
  translate([0, 0, 50]) cylinder(3, 3, 0.4);
}

module e3d() {
  translate([0, 0, -1]) cylinder(32, heatsinkDiameter / 2, heatsinkDiameter / 2, $fn = 200);
}

module sideCurve40() {
  intersection() {
    translate([-5 + (30 - clampLength), -20, 0]) cube([clampLength, 8, 25]);
    translate([20, 30, -1]) cylinder(32, 50, 50, $fn = 500);
  }
}

module topCurve40(cut = true) {
  difference() {
    difference() {
      translate([20, -20, 24.5]) rotate([0, 0, 90]) cube([33.25, 14, 15.5]);
      translate([1, 0, 38.8275]) rotate([90, 0, 0]) cylinder(44, 15, 15, true, $fn = 200);
    }
    if (cut) {
      e3d();
      translate([20, -21, 0]) rotate([0, -90, 0]) cube([50, 7.75, 15]);
    }
  }
}

module topCurve40Corner() {
  intersection() {
    translate([0, -15, 0]) topCurve40(false);
    translate([0, 0, 25]) sideCurve40();
    translate([20, -21, 0]) rotate([0, -90, 0]) cube([50, 7.75, 15]);
  }
}

module m3Hole() {
  cylinder(16, 1.5, 1.5, $fn = 50);
}

module mainBody() {
  // Hot end attachment & 40mm fan mount
  difference() {
    union() {
      // Hot end attachment
      difference() {
        translate([-3, -13.25, 0]) cube([25, 26.5, 25]);
        e3d();
      }

      // Fan mount
      translate([25, -20, 0]) rotate([0, -90, 0]) cube([40, 40, 6]);

      // Side curves
      difference() {
        union() {
          sideCurve40();
          mirror([0, 1, 0]) sideCurve40();
        }
        e3d();
      }

      // Top curve
      topCurve40(true);
      topCurve40Corner();
      mirror([0, 1, 0]) topCurve40Corner();
    }
    // Fan funnel
    hull() {
      translate([5, 0, 11]) rotate([0, 75, 0]) cylinder(30, 11, 12.5, $fn = 100);
      translate([26, 0, 20]) rotate([0, 90, 0]) cylinder(1, 18, 18, $fn = 100);
    }
    // M3 holes
    translate([10, -16, 3]) rotate([0, 90, 0]) m3Hole();
    mirror([0, 1, 0]) translate([10, -16, 3]) rotate([0, 90, 0]) m3Hole();
    translate([10, -16, 36]) rotate([0, 90, 0]) m3Hole();
    mirror([0, 1, 0]) translate([10, -16, 36]) rotate([0, 90, 0]) m3Hole();
  }
}

module sideMount() {
  hull() {
    translate([-5, -21, 0]) rotate([-90, -90, 0]) cube([30, 30, 1.25]);
    translate([-5, -31, 0]) rotate([-90, -90, 0]) rotate([0, 10, 0]) cube([30, 30, 1.25]);
  }
}

module sideBodyHollowed() {
  // 30mm fan mount
  union() {
    difference() {
      // Shell
      hull() {
        sideMount();
        translate([-6, -36.25, 40]) cube([22.5, 16.25, 1]);
      }
      // Hollow
      hull() {
        translate([0.9, -5.3, 1.5]) scale([0.9, 0.8, 0.9]) sideMount();
        translate([-5, -35.45, 40]) rotate([5, 0, 0]) scale([0.9, 0.9, 1]) cube([22.5, 16.25, 1.5]);
      }
    }

    difference() {
      // Shell
      hull() {
        translate([-6, -36.25, 40]) cube([22.5, 16.25, 2]);
        translate([-7.75, -19.6, 50.75]) scale([1.25, 1.25, 1.25]) rotate([-45, 0, 0]) translate([0, -0.25, 0]) cube([15, 4.5, 1]);
      }
      // Hollow
      hull() {
        translate([-5, -35.45, 38]) rotate([5, 0, 0]) scale([0.9, 0.9, 2.5]) cube([22.5, 16.25, 1.5]);
        translate([-6, -19.6, 50]) rotate([-45, 0, 0]) cube([15, 4, 2]);
      }
    }
  }
}

module sideBodyHoles() {
  translate([10, -29, 15]) rotate([90, 0, 0]) cylinder(15, 10, 13.5, $fn = 100, true);
  translate([0, -25, 0]) union() {
    translate([-1.5, 0, 3.5]) rotate([90, 90, 0]) m3Hole();
    translate([21.5, 0, 3.5]) rotate([90, 90, 0]) m3Hole();
    translate([-1.5, 0, 26.5]) rotate([90, 90, 0]) m3Hole();
    translate([21.5, 0, 26.5]) rotate([90, 90, 0]) m3Hole();
  }
}

module sideBody() {
  difference() {
    sideBodyHollowed();
    sideBodyHoles();
  }
}

module finalPiece() {
  union() {
    mainBody();
    sideBody();
    if (doubleSideFan) {
      mirror([0, 1, 0]) sideBody();
    }
  }
}

if (zProbeScrew) {
  difference() {
      finalPiece();
      translate([-9, 11.75, -1]) cube([10, 5, zProbeScrewHeight + 1]);
  }
} else {
  finalPiece();
}
```
I don't think you need to use any libraries, this should be simple enough to build from scratch. Thanks!

[Assistant]
FanMount.scad:
```
/* [Hotend] */

// Hotend's heatsink diameter
heatsinkDiameter = 25;  // [15:29]
// Length of the clamp
clampLength = 30;  // [18.125:0.125:32.5]
// Z-Probe screw notch
zProbeScrew = 0;  // [1:Present, 0:Absent]
// Height of the Z-Probe Screw
zProbeScrewHeight = 12;  // [0:26]

/* [Fans] */

// Number of fans
doubleSideFan = 0;  // [1:Double, 0:Single]

// E3D V6 chinese clone placeholder
% union() {
  cylinder(30, heatsinkDiameter / 2, heatsinkDiameter / 2, $fn = 200);
  translate([0, 0, 30]) cylinder(6, 3, 3);
  translate([-14.5, -10, 36]) cube([20, 20, 10]);
  translate([0, 0, 46]) cylinder(4, 3, 3);
  translate([0, 0, 50]) cylinder(3, 3, 0.4);
}

module e3d() {
  translate([0, 0, -1]) cylinder(32, heatsinkDiameter / 2, heatsinkDiameter / 2, $fn = 200);
}

module sideCurve40() {
  intersection() {
    translate([-5 + (30 - clampLength), -20, 0]) cube([clampLength, 8, 25]);
    translate([20, 30, -1]) cylinder(32, 50, 50, $fn = 500);
  }
}

module topCurve40(cut = true) {
  difference() {
    difference() {
      translate([20, -20, 24.5]) rotate([0, 0, 90]) cube([33.25, 14, 15.5]);
      translate([1, 0, 38.8275]) rotate([90, 0, 0]) cylinder(44, 15, 15, true, $fn = 200);
    }
    if (cut) {
      e3d();
      translate([20, -21, 0]) rotate([0, -90, 0]) cube([50, 7.75, 15]);
    }
  }
}

module topCurve40Corner() {
  intersection() {
    translate([0, -15, 0]) topCurve40(false);
    translate([0, 0, 25]) sideCurve40();
    translate([20, -21, 0]) rotate([0, -90, 0]) cube([50, 7.75, 15]);
  }
}

module m3Hole() {
  cylinder(16, 1.5, 1.5, $fn = 50);
}

module mainBody() {
  // Hot end attachment & 40mm fan mount
  difference() {
    union() {
      // Hot end attachment
      difference() {
        translate([-3, -13.25, 0]) cube([25, 26.5, 25]);
        e3d();
      }

      // Fan mount
      translate([25, -20, 0]) rotate([0, -90, 0]) cube([40, 40, 6]);

      // Side curves
      difference() {
        union() {
          sideCurve40();
          mirror([0, 1, 0]) sideCurve40();
        }
        e3d();
      }

      // Top curve
      topCurve40(true);
      topCurve40Corner();
      mirror([0, 1, 0]) topCurve40Corner();
    }
    // Fan funnel
    hull() {
      translate([5, 0, 11]) rotate([0, 75, 0]) cylinder(30, 11, 12.5, $fn = 100);
      translate([26, 0, 20]) rotate([0, 90, 0]) cylinder(1, 18, 18, $fn = 100);
    }
    // M3 holes
    translate([10, -16, 3]) rotate([0, 90, 0]) m3Hole();
    mirror([0, 1, 0]) translate([10, -16, 3]) rotate([0, 90, 0]) m3Hole();
    translate([10, -16, 36]) rotate([0, 90, 0]) m3Hole();
    mirror([0, 1, 0]) translate([10, -16, 36]) rotate([0, 90, 0]) m3Hole();
  }
}

module sideMount() {
  hull() {
    translate([-5, -21, 0]) rotate([-90, -90, 0]) cube([30, 30, 1.25]);
    translate([-5, -31, 0]) rotate([-90, -90, 0]) rotate([0, 10, 0]) cube([30, 30, 1.25]);
  }
}

module sideBodyHollowed() {
  // 30mm fan mount
  union() {
    difference() {
      // Shell
      hull() {
        sideMount();
        translate([-6, -36.25, 40]) cube([22.5, 16.25, 1]);
      }
      // Hollow
      hull() {
        translate([0.9, -5.3, 1.5]) scale([0.9, 0.8, 0.9]) sideMount();
        translate([-5, -35.45, 40]) rotate([5, 0, 0]) scale([0.9, 0.9, 1]) cube([22.5, 16.25, 1.5]);
      }
    }

    difference() {
      // Shell
      hull() {
        translate([-6, -36.25, 40]) cube([22.5, 16.25, 2]);
        translate([-7.75, -19.6, 50.75]) scale([1.25, 1.25, 1.25]) rotate([-45, 0, 0]) translate([0, -0.25, 0]) cube([15, 4.5, 1]);
      }
      // Hollow
      hull() {
        translate([-5, -35.45, 38]) rotate([5, 0, 0]) scale([0.9, 0.9, 2.5]) cube([22.5, 16.25, 1.5]);
        translate([-6, -19.6, 50]) rotate([-45, 0, 0]) cube([15, 4, 2]);
      }
    }
  }
}

module sideBodyHoles() {
  translate([10, -29, 15]) rotate([90, 0, 0]) cylinder(15, 10, 13.5, $fn = 100, true);
  translate([0, -25, 0]) union() {
    translate([-1.5, 0, 3.5]) rotate([90, 90, 0]) m3Hole();
    translate([21.5, 0, 3.5]) rotate([90, 90, 0]) m3Hole();
    translate([-1.5, 0, 26.5]) rotate([90, 90, 0]) m3Hole();
    translate([21.5, 0, 26.5]) rotate([90, 90, 0]) m3Hole();
  }
}

module sideBody() {
  difference() {
    sideBodyHollowed();
    sideBodyHoles();
  }
}

module finalPiece() {
  union() {
    mainBody();
    sideBody();
    if (doubleSideFan) {
      mirror([0, 1, 0]) sideBody();
    }
  }
}

if (zProbeScrew) {
  difference() {
      finalPiece();
      translate([-9, 11.75, -1]) cube([10, 5, zProbeScrewHeight + 1]);
  }
} else {
  finalPiece();
}
```


[User]
I'm looking to create a custom window design for a wooden windmill project, and I'd like to use OpenSCAD to generate the models. I need it to be parametric so I can easily change the dimensions for different parts of the windmill.

Here's what I'm envisioning. The window will have a generally rectangular shape with a rounded top – kind of like a half-circle sitting on top of a rectangle. I need to be able to adjust the width and height of the rectangular base, the radius/height of the half-circle, the overall depth of the window frame, the thickness of the frame material itself, and an optional inner border within the frame. I'm imagining that the frame will be created using a difference of two basic shapes, and the basic shape may have to be two shapes united together.

I also need to be able to add horizontal transoms within the window. These transoms should also be adjustable in thickness and position, and there can be multiple of them. So, I need to be able to control how many transoms there are and where they are placed within the window, in the y-axis. The transoms should be simple rectangular extrusions. I am imagining that the transoms should be made from simple cubes.

I also plan on adding multiple windows, so I need the file to be organized so that I can easily copy the code.

Could you generate the necessary parametric OpenSCAD files for this? I'm not sure if I'll need multiple files, but I want to make sure that the code is organized in a way that I can easily add new parts to the windmill. Please do not use any libraries.

[Assistant]
CusomWindow.scad:
```
$fn=50+0;

depth    =  9;
thick    =  2;
border   =  4;
transomD =  2;
transomW =  2;
squareW  = 45;
squareH  = 60;
circleH  = 19;
transomO1= 22;
transomO2= 46;

//Vertical frame
difference(){
    square(squareW+2*thick,squareH+thick,depth+thick);
    translate([0,0.01,0.01]){square(squareW,squareH,depth+thick+0.02);}
}
difference(){
    circle(  squareW+2*thick,  circleH+thick*2  ,depth+thick);
    translate([0,0.01,0.01]){
        circle(squareW,circleH,depth+thick+0.02);
    }

    translate([-squareW,-circleH*2,-(depth+thick)-0.01]){
        cube([squareW*2,circleH*2,depth+thick+0.02]);
    }
}

//Horizontal frame
difference(){
   union(){
        difference(){
            circle(squareW+border*2,circleH+border*2,depth+thick);
            translate([0,0.01,0.01]){circle(squareW,circleH, depth+thick+0.02);}
            translate([-squareW,-circleH*2,-(depth+thick)-0.01]){
                cube([squareW*2,circleH*2,depth+thick+0.02]);
            }
        }
        difference(){
            square(squareW+border*2,squareH+border,depth+thick);
            translate([0,0.01,0.01]){square(squareW,squareH,depth+thick+0.02);}
        }
    }
    w = squareW+border*2+thick*2;
    h = squareH+circleH;
    translate([-w/2-1,-squareH-border-thick-1, -depth-thick-thick]){
        cube([w+2,h+2,depth+thick]);
    }
}

//Transom
translate([-transomW/2,-squareH,-transomD]){
    cube([transomW,squareH+circleH/2,transomD]);
}

translate([-squareW/2, -squareH+transomO1, -transomD]){
    cube([squareW,transomW,transomD]);
}

translate([-squareW/2, -squareH+transomO2, -transomD]){
    cube([squareW,transomW,transomD]);
}

module circle(w,h,d){

    scale = h/w;

    scale([1,scale,1]){
        translate([0,0,-d]){
            cylinder(r=w/2,h=d);
        }
    }
}

module square(w,h,d){
    translate([-w/2,-h,-d]){
        cube([w,h,d]);
    }
}

```


[User]
I'd like a parametric design for a flat spring, something like the one I saw described online. It should have a few key features that I need to be able to tweak:

*   **Overall Width:** I need to be able to set the overall width of the spring, meaning the distance between the flat portions of the spring, not counting the stubs.
*   **Coil Count:** The number of loops or coils in the spring should be adjustable.
*   **Spring Thickness:** I need to be able to specify the thickness of the spring material.
*   **Spring Depth:** This will define the overall height or depth of the spring.
*  **Coil Radius:**  The radius of the rounded bends of the spring.
*  **Stub Length:** The length of the mounting stub at each end of the spring should be an adjustable parameter.

The basic design I'm thinking of is a flat spring with a series of S-shaped curves, with a flat mounting stub extending from each end. I want to be able to control all of the dimensions for the spring via parameters. It should be easily printable.

It would be ideal if the OpenSCAD code generated was well-structured and easy to understand so that I can easily add to or modify it in the future if necessary. Also, I'd prefer not to rely on external libraries, if possible, since that just adds a layer of complexity.

[Assistant]
flat_springV1_3.scad:
```
//----------------------------------------------------------------------------
//	Filename:	flat_springV1_3.scad
//	Author:		R.Pritz ( r@pritz.me )
//	Date:		Sunday, 10 Jan 2016
//
// A parametric spring with end mounting stubs.
//----------------------------------------------------------------------------

/* [Basic] */

//width from opposing coil radius
width = 10;
//number of coils
spring_count = 15;
// how tall the spring will be
depth = 4;

/* [Advanced] */

// length of support stub
stub_length = 5;
// radius of turn in each coil
radius = 1;
// width of spring coils
thickness = 1;

/* [Hidden] */
$fn = 100;

module spring_maker(radius = 5, thickness = 5, depth = 20, width = 40, spring_count = 21, end_len = 30){

    module arc_maker(radius, thickness, depth){
        difference(){
            linear_extrude( depth, center=true)
                circle( radius+(thickness/2) );
            linear_extrude( depth*1.2, center=true )
                circle( radius-(thickness/2) );
            translate([0,-radius-(thickness/2),0])
                linear_extrude( depth*1.2, center=true )
                    square( radius*3 );
        }
    }
    union(){

        translate([(width/2),-((end_len/2)+(radius/2)),0])
            rotate([0,0,90])
            linear_extrude( depth, center=true )
                square( [end_len, thickness], center=true );
        translate([(width/4),-radius,0])
            linear_extrude( depth, center=true )
                square( [width/2, thickness], center=true );
        arc_maker(radius, thickness, depth);

        for (i = [1:spring_count]){
            mod = i%2;
            rotate([0,mod*180,0])
                translate([mod*-width,(radius*2*i),0])
                    arc_maker(radius, thickness, depth);
            translate([width/2,i*(radius*2)-radius,0])
                linear_extrude( depth, center=true )
                    square( [width, thickness], center=true );
        }

        translate([width/4+(spring_count%2*(width/2)),(spring_count+1) *(radius*2)-radius,0])
                linear_extrude( depth, center=true )
                    square( [(width/2), thickness], center=true );
        translate([(width/2),((end_len/2)+(radius/2))+(radius*2*spring_count),0])
            rotate([0,0,90])
            linear_extrude( depth, center=true )
                square( [end_len, thickness], center=true );
    }
}

spring_maker(radius, thickness, depth, width, spring_count, stub_length);
```


[User]
Okay, I need to design a glass support for my Kossel Mini 3D printer. I want it to be parametric so I can adjust the dimensions easily. Basically, it will consist of a circular support piece with an indentation for the glass and a couple of holes for screws.

Here are the specifics:

**Overall Support Structure:**

*   The main support should be a cylinder, with a specified `diam_ext_support` for the outer diameter and a `epaisseur_sur_vitre` for the thickness of the top part that will be holding the glass, along with a `epaisseur_sous_vitre` for the optional thickness of the base support under the glass. I also want an optional "encoche_percent" which is the width of the recess at the side to have the support more easily slide over the glass bed.

* The thickness of the entire support part should be the sum of `epaisseur_sur_vitre`, the height of the glass, and the `epaisseur_sous_vitre`.

*   There should be a circular cutout on the top of the support for the glass to sit in. The diameter of this cutout should be the same as the `vitre_diam` and have a depth to match the glass height.

*   I need a second cutout to provide that the support can slide over the bed, it should be larger by a factor defined by `encoche_percent`.

*   There should be a hole for the screw, and that should have a countersunk or counterbored profile for the screw head. Specify the diameter of the screw body with the `vis_diam` parameter and the screw head with `vis_tete_diam`. Make sure to place this hole at a position offset from the center of the support using a ratio of the outer diameter of the support, and a specified `position_encoche` factor.

**Glass:**

*   I need a module for the glass as well. It should be a simple cylinder with a diameter of `vitre_diam` and a height of `vitre_haut`. This is for visualization purposes in the preview.

**Parameters:**

I want to use these parameters and have the ability to change them:

*   `diam_ext_support`: Outer diameter of the main support cylinder. (e.g., 20, range 10 to 30)
*   `epaisseur_sur_vitre`: Thickness of the top part of the support. (e.g., 3, range 0 to 10)
*   `encoche_percent`: Percentage of the outer diameter used to calculate the size of the slot in the support. (e.g., 0.5, range 0.3 to 0.7)
*   `epaisseur_sous_vitre`: Thickness of the optional support under the glass. (e.g., 0, range 0 to 10)
*   `vis_diam`: Diameter of the screw hole. (e.g., 4, range 2 to 5)
*   `vis_tete_diam`: Diameter of the screw head hole. (e.g., 8, range 4 to 10)
*   `vitre_diam`: Diameter of the glass. (e.g., 200, range 150 to 250)
*   `vitre_haut`: Height of the glass. (e.g., 3, range 2 to 5)
*   `artefact`: A small value to prevent z-fighting. (e.g. 0.05, fixed)
*   `globalView`: A boolean value to toggle the display of the full assembly or just the support. (e.g. 0 or 1)

**Specific Details:**

*   The position of the screw holes should be offset from the center of the support and should be calculated from the `diam_ext_support` divided by a constant value.
*   I need to see the full assembly including the glass to check for fitting issues. There should be an option to display a single support or multiple copies around the glass.

*   Use the `$fn` variable for circle and cylinder segment counts and keep it at 100 to keep a good quality.

Could you generate the OpenSCAD code based on these requirements? I don't have any specific libraries I want to use.

[Assistant]
SupportVitre.scad:
```
/* [Support] */
diam_ext_support=20; // [10:1:30]
epaisseur_sur_vitre=3; // [0:0.1:10]
encoche_percent=0.5; // [0.3:0.1:0.7]
epaisseur_sous_vitre=0; // [0:0.1:10]

/* [Screw] */
vis_diam=4; // [2:0.1:5]
vis_tete_diam=8; // [4:0.1:10]

/* [Glass] */
vitre_diam=200; // [150:1:250]
vitre_haut=3; // [2:0.1:5]

/* [Hidden] */
artefact=0.05;
globalView=0; //[0,1] Put 1 if you want to see a global view

module support_vitre() {
    position_encoche=diam_ext_support/6;
    difference() {
        union(){
        cylinder(h=epaisseur_sur_vitre+vitre_haut+epaisseur_sous_vitre,d=diam_ext_support,$fn=100); //Piece brute
        translate([0,0,epaisseur_sur_vitre+vitre_haut])
            cylinder(h=epaisseur_sous_vitre,d=diam_ext_support,$fn=100); //Piece dessous
        }
        translate([vitre_diam/2+position_encoche,0,epaisseur_sur_vitre])
            cylinder(h=vitre_haut+artefact,d=vitre_diam,$fn=100); //Trou Vitre

        translate([vitre_diam/2+position_encoche/encoche_percent,0,-artefact])
            cylinder(h=vitre_haut+epaisseur_sur_vitre+2*artefact,d=vitre_diam,$fn=100); //Encoche dessus vitre

        translate([-position_encoche,0,-artefact])
            cylinder(h=epaisseur_sur_vitre+vitre_haut+epaisseur_sous_vitre+2*artefact,d=vis_diam,$fn=100); //Trou vis

        translate([-position_encoche,0,-artefact])
            cylinder(h=epaisseur_sur_vitre+artefact,d=vis_tete_diam,$fn=100); //Trou tete vis
        }
}

module glass() {
    translate([0,0,-artefact])
        cylinder(h=vitre_haut+artefact,d=vitre_diam,$fn=100); //Vitre
}

if (globalView) %translate([0,0,10]) rotate([90,0,0]) text("Down view");
if (globalView) %color("LightCyan") translate([0,0,epaisseur_sur_vitre-artefact]) glass();

if (globalView) color("gold") translate([-vitre_diam/2-diam_ext_support/6,0,0]) support_vitre();
else support_vitre();

if (globalView)
    for(angle=[60:60:300])
        %color("gold") rotate([0,0,angle]) translate([-vitre_diam/2-diam_ext_support/6,0,0]) support_vitre();

if (globalView) %translate([0,0,-10]) rotate([-90,0,0]) text("Top view");

```


[User]
I need to design a parametric screw head for an auto-probe auto-retract system, like for a Kossel mini 3D printer. I've got some basic dimensions in mind, but I want to be able to easily adjust them later.

The screw head consists of two main parts: a head and a body. The head has an outer diameter, an inner diameter, and a height. The body also has an inner diameter, a height, and a thickness. There's also a notch cut into the side of the body, and a notch on the head. Finally, there's a small chamfer where the head meets the body.

Here are the initial parameters I have in mind:

*   **Head:**
    *   `tete_diam_ext`: Outer diameter (e.g., 15mm)
    *   `tete_diam_int`: Inner diameter (e.g., 6mm)
    *   `tete_hauteur`: Height (e.g., 7mm)
*   **Body:**
    *   `corps_diam_int`: Inner diameter (e.g., 3.2mm)
    *   `corps_hauteur`: Height (e.g., 12mm)
    *   `corps_epaisseur`: Thickness (e.g., 3mm)
*   **Notch:**
    *   `encoche_hauteur`: Height of the notch (e.g., 4.0mm)
*   **Other:**
    *   `epaisseur`: Thickness of some inner feature of the head (e.g., 1mm)
    *   `artefact`: Small tolerance value for manufacturing (e.g., 0.05mm)

I'd like the design to be done using OpenSCAD and be fully parametric, meaning that all these values can be changed easily to alter the design. I'd prefer the code to be clear and well-organized. Also, make sure that the chamfer on the head is properly created using `hull()` to give a smooth transition. I'm expecting a single `.scad` file that defines all parameters and modules to create this object. Please use `$fn=100` for all cylindrical elements for increased smoothness.

Also, I do not need any of the MCAD or BOLTS libraries.

[Assistant]
TeteVis.scad:
```
tete_diam_ext=15;
tete_diam_int=6;
tete_hauteur=7;

corps_diam_int=3.2;
corps_hauteur=12;
corps_epaisseur=3;

encoche_hauteur=4.0;

epaisseur=1;

artefact=0.05;
module tete() {
    difference() {
        cylinder(h=tete_hauteur,d1=tete_diam_ext,d2=corps_diam_int+2*corps_epaisseur,$fn=100);
        hauteur_interieur=tete_hauteur-epaisseur+artefact;
        translate([0,0,epaisseur+artefact])
            cylinder(h=hauteur_interieur,d=tete_diam_int,$fn=100);
    }
}

module corps(){
    corps_diam_ext=corps_diam_int+2*corps_epaisseur;
    tete_encoche=tete_diam_int;
    corps_encoche=corps_diam_int;
    difference(){
        difference(){ //corps
            cylinder(h=corps_hauteur,d=corps_diam_ext,$fn=100);
            translate([0,0,-artefact])
                cylinder(h=corps_hauteur+2*artefact,d=corps_diam_int,$fn=100);
        }
        translate([corps_encoche,0,corps_hauteur/2+artefact]) //encoche corps vis
            cube([2*corps_encoche,corps_encoche,corps_hauteur+2*artefact],center=true);
        translate([tete_encoche,0,encoche_hauteur/2]) //encoche tete vis
            cube([2*tete_encoche,tete_encoche,encoche_hauteur+2*artefact],center=true);
        translate([0,0,-artefact]) //Trou pour la tete
            cylinder(h=encoche_hauteur+artefact,d=tete_diam_int,$fn=100);
        hull() { //Chanfrein
            translate([0,0,encoche_hauteur/2+2-artefact])
                cylinder(h=2,d1=tete_diam_int,d2=corps_diam_int,$fn=100);
            diam1=2*sqrt((tete_encoche*tete_encoche)/2);
            diam2=2*sqrt((corps_diam_int*corps_diam_int)/2);
            translate([diam2,0,encoche_hauteur/2+2-artefact]) rotate([0,0,45])
                cylinder(h=2,d1=diam1,d2=diam2,$fn=4);
        }
    }
}

tete();

translate([0,0,tete_hauteur])
    corps();
```


[User]
I'm looking to create a fully parametric 90-degree corner bracket for linear extrusions like V-slot. I want a design that's highly customizable, so I need to be able to control things like the overall size, the thickness of the base plates and support, and whether or not to include extra support diagonals or alignment studs.

Here's a more detailed breakdown of the features I'm envisioning:

**Basic Parameters:**

*   **Size:** I need parameters to control the length, width, and height of the bracket. Let's call these `size_x`, `size_y`, and `size_z`. I'd like these to represent the number of extrusion "units", and have another parameter `base_size` to define the length of an extrusion unit (e.g. 20mm). So, a `size_x` of 2 would be 2 * `base_size`.
*   **Incremental Supports:** A boolean parameter (`incremental_supports`) to toggle optional diagonal support ribs. These ribs would run along the length of the bracket.
*   **Alignment Studs:** A boolean parameter (`alignment_studs`) to add alignment studs to the mating faces of the bracket.
*   **Slot Holes:** A boolean parameter (`slot_holes`) to toggle the inclusion of slotted screw holes for adjustability, instead of just simple holes.
*   **Screw Hole Diameter:** A parameter (`hole_d`) to set the diameter of all screw holes.

**Advanced Parameters:**

*   **Base Plate Thickness:** A parameter (`plate_thickness`) to set the thickness of the flat plates that mate with the extrusion.
*   **Side Support Thickness:** A parameter (`side_thickenss`) to define the thickness of the angled support piece.
*   **Base Size:** Parameter `base_size` to set the size of one extrusion unit, such as 20mm.
*   **Alignment Stud Dimensions:** Parameters to control the `alignment_stud_diameter` and `alignment_stud_height`.
*   **Slot Length:** A parameter `slot_length` for the length of the slotted holes.

I need the design to use `difference()` to cut out the necessary shapes, including:

*   The overall hollowed-out shape of the bracket
*   The diagonal support cuts
*   The screw holes
*   The slot cuts in the screw holes (if `slot_holes` is enabled).

The alignment studs should be cylinders on both faces of the bracket. The screw holes should also be cylinders, with the optional slots cut out as cubes and cylinders.

I'd like all parameters to have reasonable default values. I'd also like to use a for loop to place the supports and alignment studs.

I'm hoping this is specific enough. I expect the output to be a single .scad file. I don't need any external libraries for this. Can you please generate the OpenSCAD code?

[Assistant]
VSlotAngleBracket.scad:
```
/*
Aluminum Extrusion 90 Degree corner bracket
Parametric
Author: BinaryConstruct
*/

/* [Basic] */

// length
size_x = 1; // [1:4]

// width
size_y = 2; // [1:4]

// height
size_z = 1; // [1:4]

// include extra diagonals
incremental_supports = 1; // [0:1]

// include alignment studs
alignment_studs = 1; // [0:1]

// slot holes
slot_holes = 1; // [0:1]

// screw hole diameter
hole_d = 5.2;

/* [Advanced] */
// thickness of base plates
plate_thickness = 3; // [2:4]

// thickenss of angled support
side_thickenss = 3; // [2:4]

// size of extrusion increment (20mm)
base_size = 20;

// size of alignement stud
alignment_stud_diameter = 5;
alignment_stud_height = 1;
slot_length = 4;

difference()
{
    union(){
        difference(){
            cube([size_x * base_size,size_y * base_size,size_z * base_size]);

            // hollow cut
            translate([plate_thickness,side_thickenss,plate_thickness]) {
                cube([size_x * base_size, (size_y * base_size) - (side_thickenss * 2),base_size * size_z]);
            }
        }

        if (incremental_supports == 1) {
            for (y=[base_size : base_size : (size_y-1) * base_size])
                translate([0,y-side_thickenss/2,z])
                cube([size_x * base_size,side_thickenss,size_z * base_size]);
        }

        if (alignment_studs == 1) {
            // vertical holes
            for(z=[base_size / 2 : base_size : (size_z * base_size) - (base_size / 2)])
            for(y=[base_size / 2 : base_size : (size_y * base_size) - (base_size / 2)])
            {
                translate([0,y,z-alignment_stud_diameter])
                rotate([0,90,0])
                translate([0,0,-alignment_stud_height])
                { cylinder($fn=16, r=alignment_stud_diameter/2,h=alignment_stud_height); }

                translate([0,y,z+alignment_stud_diameter])
                rotate([0,90,0])
                translate([0,0,-alignment_stud_height])
                { cylinder($fn=16, r=alignment_stud_diameter/2,h=alignment_stud_height); }
            }
        }
    }

    // diagonal cut
    translate([plate_thickness/2,size_y * base_size+1,plate_thickness/2])
    rotate([90,0,0])
        linear_extrude(size_y * base_size+2) {
            polygon([
                [size_x * base_size,0],
                [size_x * base_size,size_z * base_size],
                [0,size_z * base_size]]);
        }

    // bottom holes
    for(x=[base_size / 2  : base_size : (size_x * base_size) - (base_size / 2)])
    for(y=[base_size / 2  : base_size : (size_y * base_size) - (base_size / 2)])
    {

        translate([x,y,-plate_thickness/2])
        union()
        {
            cylinder($fn=16, r=hole_d/2,h=plate_thickness*2);
            if (slot_holes == 1) {

                translate([0,-hole_d/2,0])
                cube([slot_length,hole_d,plate_thickness*2]);

                translate([slot_length,0,0])
                cylinder($fn=16, r=hole_d/2,h=plate_thickness*2);
            }
        }
    }

    // vertical holes
    for(z=[base_size / 2 : base_size : (size_z * base_size) - (base_size / 2)])
    for(y=[base_size / 2 : base_size : (size_y * base_size) - (base_size / 2)])
    {
        translate([0,y,z])
        rotate([0,90,0])
        translate([0,0,-plate_thickness/2])
        { cylinder($fn=16, r=hole_d/2,h=plate_thickness*2); }
    }

}

```


[User]
Hey, I need help designing a 3D-printable adapter for some equipment I'm using. I've got these cylindrical "smokestack" chambers, and I need a way to mount a NAN drive to them at an angle. I've got a basic design in mind that I'll describe, but I'd really like it to be parametric so I can adjust the fit for different chamber and NAN drive sizes.

So, essentially, the adapter will consist of two main parts: a base that fits around the chamber, and an angled mounting plate for the NAN drive. The base will have an inner and outer radius to fit snugly around the chamber. The mounting plate will connect to the base and be angled upwards at a specified degree. I also need some screw holes on the mounting plate so that I can secure the NAN drive.

Here are the parameters I'd like to be able to control:

*   `angle`: The angle of the mounting plate in degrees.
*   `innerbaseradius`: The inner radius of the base cylinder, which fits snugly around the chamber.
*   `outerbaseradius`: The outer radius of the base cylinder.
*   `mountheight`: The height of the mounting plate.
*   `nanmountholes`: A boolean flag (1 or 0) to enable or disable the mounting holes for the NAN drive.
*   `nanmountholedistance`: The distance from the top of the mounting plate to the center of the mounting holes.
*   `mth`: A fixed height parameter relating to the vertical offset of the angled piece.

I was thinking of having the mounting holes be placed in a pattern: two on the x and y axes and two at 45 degree angles. They should all have a diameter sufficient for a 2mm screw.

I'd also like some small, cylindrical supports that connect the base and the mounting plate for extra stability. I was envisioning these as two small cylinders near the edges and two small cube sections. Also, I need a couple of cylinders used to center the mounting plate geometry. The first should be a full cylinder that can be used to intersect and the second should be a cylinder with a larger radius that is translated higher up to cut away material for the upper region of the geometry.

I think I've got everything there. I'm hoping you could generate the OpenSCAD code for this. Let me know if you need any clarifications. I also don't know which libraries would be best here, so if you would like to use a standard set of libraries to make it easier, I can work with that too.

[Assistant]
angled_grid_adapter.scad:
```
/**
 * Jonas Knoell, jonas.knoell@utexas.edu
 */

//in degrees
angle=5;
//fine tune to fit just right
innerbaseradius=12.275;
//outer diameter of base
outerbaseradius=14;
//height of mount piece
mountheight=7;
//create mount holes?
nanmountholes=1;
//mm from top
nanmountholedistance=2;

//usually left unchanged
mth=5.1;

angleminheight=outerbaseradius*sin(angle);
difference(){
	union(){
		difference(){
			cylinder(h = 9.5,r=outerbaseradius,$fn=360);
			cylinder(h = 9.5,r=innerbaseradius,$fn=360);
		}

		intersection(){
			 translate([0.0, mth*sin(angle), 4.5 ])
		    rotate([angle,0,0])
		    difference(){
			  	union(){
			        difference(){
			        scale([1,cos(angle),1])cylinder(h = mth+angleminheight,r=14,$fn=360);
			        cylinder(h = mth+angleminheight,r=10,$fn=360);
			        };

			        difference(){
			        	cylinder(h = mth+mountheight+angleminheight,r=12,$fn=360);
						cylinder(h = mth+mountheight+angleminheight,r=10,$fn=360);
			        }

				}

				if(nanmountholes){
					translate([-15,00,(mth+mountheight-nanmountholedistance+angleminheight)])
					rotate([0,90,0])
					cylinder(r=1, h=30,$fn=360);

					translate([0,15,(mth+mountheight-nanmountholedistance+angleminheight)])
					rotate([90,00,0])
					cylinder(r=1, h=30,$fn=360);

					rotate([90,00,45])
					translate([00,(mth+mountheight-nanmountholedistance+angleminheight),-15])
					cylinder(r=1, h=30,$fn=360);

					rotate([90,00,-45])
					translate([00,(mth+mountheight-nanmountholedistance+angleminheight),-15])
					cylinder(r=1, h=30,$fn=360);
				}

		    }
		    translate([0, 0, 9.5 ])
		    cylinder(h = 50,r=20,$fn=360);

		}
	}

	union(){
		translate([0,15,2])
		rotate([90,0,0])
		cylinder(r=1.5, h=30,$fn=360);

		translate([-15,0,2])
		rotate([0,90,0])
		cylinder(r=1.5, h=30,$fn=360);

		translate([-1.5,-15,-1])
	   cube([3,15,3]);

	}
}
```


[User]
Hey, I need a design for a wall mountable box for a Hampton Bay ceiling fan controller. I've got the basic dimensions, but I want something that's easily customizable in OpenSCAD, so I can adjust it later if needed.

The controller is trapezoidal in shape. At the top of the controller, it's 53mm wide. At the bottom, it's 40mm wide. The depth of the controller, which is how far it sticks out from the wall, is 80mm. The height of the controller is 40mm.

I'd like the box to have screw holes, so it can be mounted to the wall. I'm envisioning a box that surrounds the controller, with some extra material around the edges for the screw holes. I think 15mm of extra material on the sides for those screw holes should work.

So, the final dimensions should be calculated based on that. The main part of the box will need to have a top width equal to 53mm + (15mm * 2) = 83mm, a depth of 80mm + 15mm = 95mm and a height of 40mm + 5mm = 45mm - I added that extra 5mm to account for a bit of clearance, just to be safe.

I'd like the box to have three screw holes: two on the sides and one on the back. The side holes should be positioned roughly 5mm from the side and 10mm from the front. The back hole should be centered width-wise and positioned about 5mm from the back edge. They need to fit a 2mm screw, so the holes should be about 4.2mm in diameter. The screw holes should go all the way through, of course, so the extrusion of those cylinders should be just a bit more than 45mm.

The box needs to have the shape of the controller cutout from the inside, so it can be mounted with the controller snugly inside. The cut out itself will be trapezoidal. The base will have a width of 53mm, and a height of 40mm, with a total depth of 80mm. The "top" will have a width of 40mm.

I think that's about it. I'm hoping for a design that uses modules and parameters, so I can easily tweak dimensions later if needed. I'm not particular about specific libraries to use - whatever works well and is common is fine.

[Assistant]
HamptonBayCeilingFanWallMount.scad:
```
//
//  HamptonBayCeilingFanWallMount.scad
//
//  EvilTeach
//
//  1/10/2015
//

// Width of the controller at the top of the box
controlTopWidth = 53.0;

// Width of the controller at the bottom of the box
controlBotWidth = 40.0;

// Height of the box
controlDepth    = 80.0;

//Thickness of the controller
controlHeight   = 40.0;

// width of the part that the screw holes are in.
wallWidth       = 15.0;

// Make a cube big enough to hold the controller, and enough space for screwholes
cubeWidth  = wallWidth + controlTopWidth + wallWidth;
cubeDepth  = controlDepth + wallWidth;
cubeHeight =  controlHeight + 5;
module base_block()
{
    color("cyan")
        cube([cubeWidth, cubeDepth, cubeHeight]);
}

module trapezoid(width_base, width_top,height,thickness)
{

  linear_extrude(height = thickness)
      polygon(points=[[0,0],
                      [width_base,0],
                      [width_base-(width_base-width_top)/2,height],
                      [(width_base-width_top)/2,height]],
              paths=[[0,1,2,3]]);

}

// Make a controller bottom piece to subtract out of the cube.
module controller_insert()
{
    color("Yellow")
    translate([cubeWidth / 2.0 - controlTopWidth / 2.0, 0, 0])
            trapezoid(controlTopWidth, controlBotWidth, controlDepth, controlHeight);
}

// Make a model to cut away the extra material, and put in screw holes.
cutaway = wallWidth * .7;
module screw_holes()
{
    color("lime")
        translate([0, 0, 5])
        cube([cutaway, cubeDepth, cubeHeight - 5]);

    color("pink")
        translate([cubeWidth - cutaway, 0, 5])
            cube([cutaway, cubeDepth, cubeHeight - 5]);

    color("blue")
        translate([0, cubeDepth - cutaway, 5])
            cube([cubeWidth, cutaway, cubeHeight - 5]);

    color("red")
        translate([5, 10, 0])
            cylinder(r = 2.1, h = 5.0, $fn = 36);

    color("red")
        translate([cubeWidth - 5, 10, 0])
            cylinder(r = 2.1, h = 5.0, $fn = 36);

    color("red")
        translate([(cubeWidth - 5) / 2, cubeDepth - 5, 0])
            cylinder(r = 2.1, h = 5.0, $fn = 36);
}

module main()
{
    // Center it
    translate([-cubeWidth / 2, cubeDepth / 2, cubeHeight])
        // Minimize the need for support material
        rotate([180, 0, 0])
            difference()
            {
                base_block();
                controller_insert();
                screw_holes();
            }
}

main();
```


[User]
Hey, I'm trying to design a tool for removing prints from my heated build plate, and I'd like to use OpenSCAD to make it parametric. I've got a basic design in mind, kind of a wedge shape, and I've even modified an existing file to get close to what I want, but I think I need to start from scratch for it to be more flexible and easier to customize.

Essentially, I need a flat, elongated wedge. The original file I found used the same value for both length and width, but I'd like to be able to control those separately.

Here's a breakdown of the parameters I'd like to control:

*   **`thickness`**: The maximum thickness of the wedge. This should be a positive number, and the tool should be built with the thickest part on the build plate, and thinner to be pointed. I'd really prefer that it not be a negative number, as in the existing SCAD file.
*   **`length`**:  The overall length of the wedge.
*   **`width`**: The width of the wedge, perpendicular to its length.

The wedge should be a 2D shape that's extruded to the `width`. The shape should be a triangle, with one vertex of that triangle having a "thickness" offset from one side. It's probably easier to think about as a triangle with a single vertex pushed back by the thickness.

The original file used a `linear_extrude` with a `polygon` in a `rotate` to create the 3D object, and that seemed pretty good to me. I'd like to use that same technique for this tool.

I don't need any other features, like holes or handles, at this time. I'm happy to experiment with further tweaks myself, once I have a good parametric model.

Could you generate the OpenSCAD file(s) for this? I don't need any libraries for it. Thanks.

[Assistant]
HBP_Wedge_Removal_Tool.scad:
```
// License:  Creative Commons Attribtion-NonCommercial-ShareAlike
// http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode
//
// Author: Jetty, 1st November, 2011
//
//
// Heated Build Platform Wedge Removal Tool
//
// Print with 100% Fill

maxThickness  = -4;
length = 70;
width = 50;

rotate(a=[90, 90, 90])
{
	linear_extrude(height = width, center = true, convexity = 10, twist = 0)
		polygon(points=[ [0,0], [maxThickness, length], [0, length] ], paths=[[0,1,2]]);
}

```


[User]
I'm looking to design a parametric carriage base for a delta 3D printer, specifically for use with V-slot extrusion. I've got some specific ideas about how I want it to work, but I'd like to make it flexible enough to adapt to different setups. The main idea is a "dog-bone" shape, with curved sections around the wheel mounting points.

Here are the key features and parameters I'd like to control:

1.  **Wheel Center X Offset (W_X_Offset):** This is the horizontal distance from the carriage centerline to the center of the wheel mounting holes. This will be crucial for adjusting to different V-slot profiles. I want to use a default of 39.9 mm, which worked well for 2060 V-slot. The design should also work for 19.9 for 2020, 29.9 for 2040, & 49.9 for 2080.

2.  **Wheel Center Y Offset (W_Y_Offset):** The vertical distance from the carriage centerline to the wheel center. The default should be 16mm.

3.  **Top Ledge Offset (L_Offset_Top):**  A distance from the top of the base plate to the top of a ledge that wraps around the perimeter. This ledge should not appear if the FlushTop parameter is enabled and should default to 11.3mm.

4.  **Bottom Ledge Offset (L_Offset_Bot):** Similar to the Top Ledge, but for the bottom ledge.  This ledge should not appear if the FlushBottom parameter is enabled and should default to 11.3mm.

5.  **Base Plate Height (Ht):** The overall thickness of the base plate. I'd like a default of 6mm, but I need to be able to adjust that. It should work for a minimum of 3 mm with ledges enabled, and I may want to go below that with ledges disabled.

6.  **Wheel Bolt Hole Diameter (M5):** The diameter of the holes for the wheel mounting bolts. Let's use 5.5 mm, assuming M5 bolts.

7.  **Eccentric Spacer Hole Diameter (M5_ECC):** The diameter of the hole for the eccentric spacer, which will allow tension adjustments for the wheels.  This should be 7.5mm.

8.  **Bolt Hole Resolution (M5_Res):** The number of segments for drawing the bolt holes. I'd prefer to use 24 segments for a nice round circle.

9.  **Eccentric Bolt Side (ECC_Right):** A boolean parameter where 1 means the eccentric spacers are on the right side, and 0 means they're on the left side.

10. **Flush Top (FlushTop):** Boolean. If set to 1, the top of the carriage base is flat. Otherwise, it has curves at the wheel corners. The default is 0.

11. **Flush Bottom (FlushBottom):** Same as above, but for the bottom of the base. Default is 0.

12. **Flush Sides (FlushSides):** Same as above, but for the sides of the base. Default is 0.

13. **Corner Plate Diameter (Corner_OD):** The diameter of the circular plate around each wheel mount. This should default to 30mm.

14. **Top Chamfer Diameter (UpChamfer_OD):** The diameter of the chamfer cut on the top inside edge of the wheel corners. I'm using a default of 10 mm.

15. **Side Chamfer Diameter (SideChamfer_OD):**  The diameter of the chamfer cut on the outside of the wheel corners. Default to 12mm.

16. **Ledge Perimeter (Ledge_On):** Boolean. If set to 1, a ledge is drawn around the perimeter, if set to 0 then no ledge is drawn. Default is 1.

17. **Draw Carriage (Carriage_On):** Boolean. If set to 1, the carriage that attaches to the base plate is drawn using a separate scad file (provided). If set to 0, only the base plate is drawn. Default is 1.

I'd also like to include a separate file for the carriage itself. This file needs a module called `DrawCarriage()`. I can provide the basic shape as a separate .scad file.

I need the design to handle drawing the ledges correctly and include the chamfers, and I'd like it if the design included the cutouts for the bolt holes and eccentric spacers.  I want all of these features controlled by the variables I've listed.

Could you generate the OpenSCAD files for this design, including the base plate and the carriage, as well as handle the calculations for offsetting the chamfers, curves, and ledges from the wheel mounting holes? No external libraries should be required for this, and the carriage itself is drawn from the provided `.scad` file.

[Assistant]
ParametricCarriageBase_Rev18.scad:
```
//Parametric Carriage Base for V-Slot Printers
//This was designed to be used on my Emmett-Delta
//I made this parametric to make it easy to adjust for different situations
//1/10/2016  By: David Bunch
//
include <Delta_Traxxas_Carriage.scad>;

//CUSTOMIZER VARIABLES

//1. Wheel Center X Offset (default for 2060 V-Slot)
W_X_Offset = 39.9;          //39.85165 measured, but I used 39.9mm
                //2020 measures 39.7082 between holes 19.8541 to centerline
                //2040 measures 59.7033 between holes  29.85165 to centerline
                //2060 measures 79.7033 between holes  39.85165 to centerline
                //2080 measueres 99.7033 between holes  49.85165 to centerline

//2. Wheel Center Y Offset (default 16)
W_Y_Offset =16;

//3. Offset to Top Ledge
L_Offset_Top = 11.3;     //Not used on Top if FlushTop = 1
                        //will draw incorrectly if
                        //Y_Offset + (UpChamfer_OD / 2) > W_Y_Offset

//4. Offset to Bottom Ledge
L_Offset_Bot = 11.3;    //Not used on Bottom if FlushBottom = 1

//5. Height of Carriage Base Plate
Ht = 6;

//6. Diameter of Bolt holes for Wheels
M5 = 5.5;

//7. Diameter of Eccentric Spacers hole
M5_ECC = 7.5;

//8. Bolt Hole Resolution
M5_Res = 24;

//9. Eccentric bolts on (1=Right, 0 = Left) Side
ECC_Right = 1;

//10. Base Plate Flush across the top (1 = Yes)
FlushTop = 0;   //0 = curved at the Top

//11. Base Plate Flush across the Bottom (1 = Yes)
FlushBottom = 0;   //0 = curved at the Bottom

//12. Base Plate Flush on both sides
FlushSides = 0;     //0 = curved on both sides

//13. Diameter of  Plate around each hole
Corner_OD = 30;

//14. Diameter of Chamfer cut on top inside cut of Wheel Corners
UpChamfer_OD = 10;

//15. Diameter of Chamfer cut on outside of wheel Corners
SideChamfer_OD = 12;

//16. Draw the Ledge around perimeter
Ledge_On = 1;

//17. Draw Carriage (1= Yes, 0 = Draw only Base Plate)
Carriage_On = 1;

//CUSTOMIZER VARIABLES END

Corner_Rad = Corner_OD / 2;
UpChamfer_Rad = UpChamfer_OD / 2;
SideChamfer_Rad = SideChamfer_OD / 2;
Sin45 = sin(45);

SideCh_Offset = Sin45 * (Corner_Rad + SideChamfer_Rad);
SideChamfer_X_Offset = SideCh_Offset + W_X_Offset;

SideChamfer_Y_Offset = W_Y_Offset - SideCh_Offset;
echo("SideChamfer_Y_Offset = ",SideChamfer_Y_Offset);
SideCube_Len = Sin45 * Corner_Rad;
echo("SideCube_Len = ",SideCube_Len);
TopCube_Len = Corner_Rad + UpChamfer_Rad;
echo("TopCube_Len = ",TopCube_Len);
TopCube_Wid = L_Offset_Top + UpChamfer_Rad;
echo("TopCube_Wid = ",TopCube_Wid);
BotCube_Wid = L_Offset_Bot + UpChamfer_Rad;

SideCube_Wid = Corner_Rad+SideChamfer_Rad;
SB_OD = SideChamfer_OD+12;               //Side Bump Diameter
SB_Cyl_X_Offset = SideChamfer_X_Offset - (SideChamfer_Rad + 3);
UB_OD = UpChamfer_OD + 12;              //Upper Bump Diameter
UB_Cyl_X_Offset = W_X_Offset - (Corner_Rad-3);
echo("UB_Cyl_X_Offset = ",UB_Cyl_X_Offset);

UB_Cyl_Ht = W_Y_Offset - TopCube_Wid;
echo("UB_Cyl_Ht = ",UB_Cyl_Ht);
LB_Cyl_Ht = W_Y_Offset - BotCube_Wid;
UpChamfer_X_Offset = W_X_Offset - TopCube_Len;
Ledge_Ht = UpChamfer_X_Offset * 2;
echo("(W_X_Offset - TopCube_Len) = ",(W_X_Offset - TopCube_Len));
Wheel_Len = W_X_Offset * 2;
Wheel_Wid = W_Y_Offset * 2;
Wheel_UpFlushLedge_Y = W_Y_Offset + (Corner_Rad - 3);
echo("Wheel_UpFlushLedge_Y = ",Wheel_UpFlushLedge_Y);
Wheel_SideFlushLege_X = W_X_Offset + (Corner_Rad - 3);
echo("Wheel_SideFlushLege_X = ",Wheel_SideFlushLege_X);

//Makes each segment about 1mm and even number of segments
Corner_Res = (round((Corner_OD * 3.14)/4)*4);       //Resolution of Corner Cylinders
echo("Corner_Res = ",Corner_Res);
UpCh_Res = (round((UpChamfer_OD * 3.14)/4)*4);      //Resolution of Upper/Lower Cylinders
echo("UpCh_Res = ",UpCh_Res);
SidCh_Res = (round((SideChamfer_OD * 3.14)/4)*4);   //Resolution of Side Cylinders
echo("SidCh_Res = ",SidCh_Res);
module CornerTop()
{
    union()
    {
        cylinder(d=Corner_OD,h=Ht,$fn=Corner_Res);
        if (Ledge_On == 1)
        {
            translate([0,0,Ht])
            BumpLedge();
        }
        translate([0,-W_Y_Offset,0])
        cube([Corner_Rad,W_Y_Offset,Ht]);       //Fill in to Right of Corner

        translate([-SideCube_Len,-W_Y_Offset,0])
        cube([SideCube_Len,W_Y_Offset,Ht]);     //Left most cube

        translate([0,-W_Y_Offset,0])
        cube([W_X_Offset+.01,L_Offset_Top,Ht]); //Connect Corner to Center

        translate([0,-W_Y_Offset,0])
        cube([TopCube_Len,TopCube_Wid,Ht]);     //Upper Right Cube
    }
}
module CornerBot()
{
    union()
    {
        cylinder(d=Corner_OD,h=Ht,$fn=Corner_Res);
        if (Ledge_On == 1)
        {
            translate([0,0,Ht])
            BumpLedge();
        }
        translate([0,-W_Y_Offset,0])
        cube([Corner_Rad,W_Y_Offset,Ht]);       //Fill in to Right of Corner

        translate([-SideCube_Len,-W_Y_Offset,0])
        cube([SideCube_Len,W_Y_Offset,Ht]);     //Left most cube

        translate([0,-W_Y_Offset,0])
        cube([W_X_Offset+.01,L_Offset_Bot,Ht]); //Connect Corner to Center

        translate([0,-W_Y_Offset,0])
        cube([TopCube_Len,BotCube_Wid,Ht]);     //Upper Right Cube
    }
}
module CornerSideFlush()
{
    difference()
    {
        CornerTop();
        translate([-Corner_OD,-Corner_OD,Ht])
        cube([Corner_OD,Corner_OD,Ht+2]);       //Cut for Side Flush Ledge
    }
}
module CornerTopAndSideFlush()
{
    difference()
    {
        CornerTop();
        translate([0,-W_Y_Offset,Ht])
        cube([Corner_OD,W_Y_Offset*2,Ht+2]);    //Cut for Top Flush Ledge
        translate([-Corner_OD,-Corner_OD,Ht])
        cube([Corner_OD,Corner_OD,Ht+2]);       //Cut for Side Flush Ledge
    }
}
module DrawTopCorner()
{
    union()
    {
        difference()
        {
            translate([-W_X_Offset,W_Y_Offset,0])
            CornerTop();
            CutForCurves();
        }
        if (Ledge_On == 1)
        {
            SideBump();
            SideLedge();
            UpBump();
            if (UB_Cyl_Ht > 0)
            {
                UpLedge();
            }
        }
    }
}
module DrawBotCorner()
{
    union()
    {
        difference()
        {
            translate([-W_X_Offset,W_Y_Offset,0])
            CornerBot();
            CutForCurvesBot();
        }
        if (Ledge_On == 1)
        {
            SideBump();
            SideLedge();
            UpBumpBot();
            if (LB_Cyl_Ht > 0)
            {
                DownLedge();
            }
        }
    }
}
module CutForCurves()
{
    translate([-SideChamfer_X_Offset,SideChamfer_Y_Offset,-1])
    cylinder(d=SideChamfer_OD,h=Ht+2,$fn=SidCh_Res);       //Cut Side Curve
    translate([-UpChamfer_X_Offset,TopCube_Wid,-1])
    cylinder(d=UpChamfer_OD,h=Ht+2,$fn=UpCh_Res);         //Cut Top Right Curve
    if (SideChamfer_Y_Offset > 0)
    {
        translate([-SideChamfer_X_Offset,-.1,-1])
        cube([SideChamfer_Rad,SideChamfer_Y_Offset+.1,Ht+2]);
    }
    translate([-SideChamfer_X_Offset,SideChamfer_Y_Offset,Ht])
    rotate([0,0,-45])
    cube([SideCube_Wid,SideCube_Wid,Ht]);  //Cut off Bottom & Left of Bump
    translate([-W_X_Offset,0,Ht])
    cube([Corner_OD,W_Y_Offset,Ht]);  //Cut off rest of Right Bottom corner
}
module CutForCurvesBot()
{
    translate([-SideChamfer_X_Offset,SideChamfer_Y_Offset,-1])
    cylinder(d=SideChamfer_OD,h=Ht+2,$fn=SidCh_Res);       //Cut Side Curve
    translate([-UpChamfer_X_Offset,BotCube_Wid,-1])
    cylinder(d=UpChamfer_OD,h=Ht+2,$fn=UpCh_Res);         //Cut Top Right Curve
    if (SideChamfer_Y_Offset > 0)
    {
        translate([-SideChamfer_X_Offset,-.1,-1])
        cube([SideChamfer_Rad,SideChamfer_Y_Offset+.1,Ht+2]);
    }
    translate([-SideChamfer_X_Offset,SideChamfer_Y_Offset,Ht])
    rotate([0,0,-45])
    cube([SideCube_Wid,SideCube_Wid,Ht]);  //Cut off Bottom & Left of Bump
    translate([-W_X_Offset,0,Ht])
    cube([Corner_OD,W_Y_Offset,Ht]);  //Cut off rest of Right Bottom corner
}
module CutForSideCurves()
{
    translate([-SideChamfer_X_Offset,SideChamfer_Y_Offset,-1])
    cylinder(d=SideChamfer_OD,h=Ht+2,$fn=SidCh_Res);       //Cut Side Curve
    translate([-UpChamfer_X_Offset,TopCube_Wid,-1])
    cylinder(d=UpChamfer_OD,h=Ht+2,$fn=UpCh_Res);         //Cut Top Right Curve
    if (SideChamfer_Y_Offset > 0)
    {
        translate([-SideChamfer_X_Offset,-.1,-1])
        cube([SideChamfer_Rad,SideChamfer_Y_Offset+.1,Ht+2]);
    }
    translate([-SideChamfer_X_Offset,SideChamfer_Y_Offset,Ht])
    rotate([0,0,-45])
    cube([SideCube_Wid,SideCube_Wid,Ht]);  //Cut off Bottom & Left of Bump
    translate([-W_X_Offset,0,Ht])
    cube([Corner_OD,W_Y_Offset,Ht]);  //Cut off rest of Right Bottom corner
}
module DrawCornerSideFlush()
{
    union()
    {
        difference()
        {
            translate([-W_X_Offset,W_Y_Offset,0])
            CornerSideFlush();
            CutForSideCurves();
        }
        translate([-(W_X_Offset+Corner_Rad),0,0])
        cube([Corner_Rad,W_Y_Offset,Ht]);           //Fill Side Curve
        if (Ledge_On == 1)
        {
            UpBump();
            if (UB_Cyl_Ht > 0)
            {
                UpLedge();
            }
        }
    }
}
module DrawCornerTopAndSideFlush()
{
    union()
    {
        difference()
        {
            translate([-W_X_Offset,W_Y_Offset,0])
            CornerTopAndSideFlush();
            CutForSideCurves();
            translate([-W_X_Offset,0,Ht])
            cube([Wheel_Len,W_Y_Offset+Corner_OD,Ht+2]);
        }
        translate([-W_X_Offset,0,0])
        cube([Wheel_Len/2,W_Y_Offset+Corner_Rad,Ht]);
        translate([-(W_X_Offset+Corner_Rad),0,0])
        cube([Corner_Rad,W_Y_Offset,Ht]);           //Fill Side Curve
        if (Ledge_On == 1)
        {
            TopLedgeFlush();
        }
    }
}
module DrawCornerTopFlush()
{
    union()
    {
        difference()
        {
            translate([-W_X_Offset,W_Y_Offset,0])
            CornerTop();
            CutForSideCurves();
            translate([-W_X_Offset,0,Ht])
            cube([Wheel_Len,W_Y_Offset+Corner_OD,Ht+2]);
        }
        translate([-W_X_Offset,0,0])
        cube([Wheel_Len/2,W_Y_Offset+Corner_Rad,Ht]);
        if (Ledge_On == 1)
        {
            SideBump();
            SideLedge();
            TopLedgeFlush();
        }
    }
}
module BumpLedge(B_OD = Corner_OD,I_R = 108)
{
    CB_D2 = B_OD - 3;              //Corner Bump Diameters
    CB_D3 = B_OD - 12;
    CB_D4 = B_OD - 9 + .0577;
    difference()
    {
        cylinder(d1=B_OD,d2=CB_D2,h=2.6,$fn=I_R);
        translate([0,0,-1])
        cylinder(d=CB_D3,h=6,$fn=I_R);
        cylinder(d1=CB_D3,d2=CB_D4,h=2.7,$fn=I_R);
    }
}
module SideBump()
{
    translate([-SideChamfer_X_Offset,SideChamfer_Y_Offset,Ht])
    difference()
    {
        BumpLedge(SB_OD);
        translate([-SB_OD,-SB_OD,-1])
        cube([SB_OD*2,SB_OD,Ht+2]);        //Cut off Bottom half of Side Bump

        rotate([0,0,-45])
        translate([-SB_OD,-(SB_OD/2-1),-1])
        cube([SB_OD,SB_OD,Ht+2]);           //Cut off Left & 45degs to Match Wheel bump
    }
}
module UpBump()
{
    translate([-UpChamfer_X_Offset,TopCube_Wid,Ht])
    difference()
    {
        BumpLedge(UB_OD);
        translate([-UB_OD,0,-1])
        cube([UB_OD*2,UB_OD,Ht+2]);        //Cut off Top half of Upper Right Bump

        translate([0,-UB_OD,-1])
        cube([UB_OD*2,UB_OD+1,Ht+2]);        //Cut off Bottom half of Side Bump
    }
}
module UpBumpBot()
{
    translate([-UpChamfer_X_Offset,BotCube_Wid,Ht])
    difference()
    {
        BumpLedge(UB_OD);
        translate([-UB_OD,0,-1])
        cube([UB_OD*2,UB_OD,Ht+2]);        //Cut off Top half of Upper Right Bump

        translate([0,-UB_OD,-1])
        cube([UB_OD*2,UB_OD+1,Ht+2]);        //Cut off Bottom half of Side Bump
    }
}
module TopLedge()
{
    translate([0,L_Offset_Top-3,Ht])
    rotate([0,90,0])
    rotate([0,0,90])
    cylinder(d=6,h=Ledge_Ht,$fn=6,center=true);
}
module BotLedge()
{
    translate([0,L_Offset_Bot-3,Ht])
    rotate([0,90,0])
    rotate([0,0,90])
    cylinder(d=6,h=Ledge_Ht,$fn=6,center=true);
}
module TopLedgeFlush()
{
    translate([0,Wheel_UpFlushLedge_Y,Ht])
    rotate([0,90,0])
    rotate([0,0,90])
    cylinder(d=6,h=Wheel_Len,$fn=6,center=true);
}
module SideLedgeFlush()
{
    translate([-Wheel_SideFlushLege_X,0,Ht])
    rotate([90,0,0])
    cylinder(d=6,h=Wheel_Wid,$fn=6,center=true);
}
module UpLedge()
{
    translate([-UB_Cyl_X_Offset,W_Y_Offset,Ht])
    rotate([90,0,0])
    cylinder(d=6,h=UB_Cyl_Ht,$fn=6);
}
module DownLedge()
{
    translate([-UB_Cyl_X_Offset,W_Y_Offset,Ht])
    rotate([90,0,0])
    cylinder(d=6,h=LB_Cyl_Ht,$fn=6);
}
module SideLedge()
{
    translate([-SB_Cyl_X_Offset,0,Ht])
    rotate([90,0,0])
    cylinder(d=6,h=SideChamfer_Y_Offset*2,$fn=6,center=true);
}
module DrawTopSide()
{
    if (FlushTop == 0)
    {
        if (FlushSides == 0)
        {
            DrawTopCorner();
            mirror([1,0,0])
            DrawTopCorner();
        } else {
            DrawCornerSideFlush();
            mirror([1,0,0])
            DrawCornerSideFlush();
        }
        if (Ledge_On == 1)
        {
            TopLedge();
        }
    } else {
        if (FlushSides == 0)
        {
                DrawCornerTopFlush();
                mirror([1,0,0])
                DrawCornerTopFlush();
        } else {
            DrawCornerTopAndSideFlush();
            mirror([1,0,0])
            DrawCornerTopAndSideFlush();
        }
    }
}
module DrawBottomSide()
{
    mirror([0,1,0])
    {
        if (FlushBottom == 0)
        {
            if (FlushSides == 0)
            {
                DrawBotCorner();
                mirror([1,0,0])
                DrawBotCorner();
            } else {
                DrawCornerSideFlush();
                mirror([1,0,0])
                DrawCornerSideFlush();
            }
            if (Ledge_On == 1)
            {
                BotLedge();
            }
        } else {
            if (FlushSides == 0)
            {
                DrawCornerTopFlush();
                mirror([1,0,0])
                DrawCornerTopFlush();
            } else {
                DrawCornerTopAndSideFlush();
                mirror([1,0,0])
                DrawCornerTopAndSideFlush();
            }
        }
    }
}
module DrawUnion()
{
    union()
    {
        DrawTopSide();
        DrawBottomSide();
        if (Carriage_On == 1)
        {
            translate([0,0,Ht])
            DrawCarriage();             //Carriage from Included file
        }
        if (FlushSides == 1)
        {
            if (Ledge_On == 1)
            {
                SideLedgeFlush();
                mirror([1,0,0])
                SideLedgeFlush();
            }
        }
    }
}
module DrawFinal()
{
    difference()
    {
        DrawUnion();
        if (ECC_Right == 1)
        {
            translate([-W_X_Offset,W_Y_Offset,-1])
            cylinder(d=M5,h=Ht+2,$fn=M5_Res);           //Drill Upper left M5 Hole
            translate([-W_X_Offset,-W_Y_Offset,-1])
            cylinder(d=M5,h=Ht+2,$fn=M5_Res);           //Drill Lower left M5 Hole
            translate([W_X_Offset,W_Y_Offset,-1])
            cylinder(d=M5_ECC,h=Ht+2,$fn=M5_Res);       //Drill Upper Right M5 Eccentric Hole
            translate([W_X_Offset,-W_Y_Offset,-1])
            cylinder(d=M5_ECC,h=Ht+2,$fn=M5_Res);       //Drill Lower Right M5 Eccentric Hole
        } else {
            translate([W_X_Offset,W_Y_Offset,-1])
            cylinder(d=M5,h=Ht+2,$fn=M5_Res);           //Drill Upper left M5 Hole
            translate([W_X_Offset,-W_Y_Offset,-1])
            cylinder(d=M5,h=Ht+2,$fn=M5_Res);           //Drill Lower left M5 Hole
            translate([-W_X_Offset,W_Y_Offset,-1])
            cylinder(d=M5_ECC,h=Ht+2,$fn=M5_Res);       //Drill Upper Right M5 Eccentric Hole
            translate([-W_X_Offset,-W_Y_Offset,-1])
            cylinder(d=M5_ECC,h=Ht+2,$fn=M5_Res);       //Drill Lower Right M5 Eccentric Hole
        }
//If you are using a different type of carriage, you might be able to comment out
//the next 5 lines of code
        if (Carriage_On == 1)
        {
            translate([-12,-L_Offset_Bot*4,Ht])
            cube([10,W_Y_Offset*6,10]);             //Cut ledges for Belt clearance
        }
    }
}
DrawFinal();
```
Delta_Traxxas_Carriage.scad:
```
// Modified Carriage for Emmett-Delta
// By David Bunch
//
// Which is based on Delta-Six 3D Printer carriage
// which was Created by Sage Merrill
// Released on Openbuilds.com
// which in turn was Based on orginal design by Johann C. Rocholl (Kossel Printer)
// License = Attribution Share Alike - CC BY SA
//
//Variables for Carriage
Car_Ht = 11.71;
M3 = 3.4;
M3Ht = 14.5;
//M3Nut = 2.066*M3;
M3Nut = 7.0;
M3NutHt = .9*M3;
//echo("M3Nut = ", M3Nut);
//echo("M3NutHt = ", M3NutHt);
M3_ires = 24;
module Carriage()
{
//Draw Basic Outline of Carriage
    linear_extrude(height = Car_Ht, center = false, convexity = 10)polygon(points =
    [[-19.16,-15.95],[19.16,-15.95],[27.5,-7.61],[27.5,-0.39],[21.41,5.71],
    [-21.41,5.71],[-27.5,-0.39],[-27.5,-7.61]]);
}
module BeltGroove()
{
    union()
    {
        translate([0,0,4])
        linear_extrude(height = Car_Ht, center = false, convexity = 10)polygon(points =
        [[9.14,-14.78],[8.85,-14.78],[8.59,-14.66],[8.4,-14.46],[8.3,-14.19],
        [8.3,-13.91],[8.42,-13.65],[8.62,-13.46],[8.88,-13.36],[8.79,-12.81],
        [8.51,-12.81],[8.25,-12.69],[8.05,-12.49],[7.95,-12.22],[7.96,-11.94],
        [8.07,-11.68],[8.27,-11.49],[8.54,-11.39],[8.44,-10.84],[8.16,-10.84],
        [7.9,-10.72],[7.7,-10.52],[7.6,-10.26],[7.61,-9.97],[7.72,-9.71],
        [7.93,-9.52],[8.19,-9.42],[8.09,-8.87],[7.81,-8.87],[7.55,-8.75],
        [7.36,-8.55],[7.25,-8.29],[7.26,-8],[7.37,-7.74],[7.58,-7.55],
        [7.84,-7.45],[7.75,-6.9],[7.46,-6.9],[7.21,-6.78],[7.01,-6.58],
        [6.91,-6.32],[6.91,-6.03],[7.03,-5.77],[7.23,-5.58],[7.49,-5.48],
        [7.4,-4.93],[7.12,-4.93],[6.86,-4.81],[6.66,-4.61],[6.56,-4.35],
        [6.57,-4.06],[6.68,-3.81],[6.88,-3.61],[7.15,-3.51],[7.05,-2.96],
        [6.77,-2.96],[6.51,-2.84],[6.32,-2.64],[6.21,-2.38],[6.22,-2.09],
        [6.33,-1.84],[6.54,-1.64],[6.8,-1.54],[6.7,-0.99],[6.42,-0.99],
        [6.16,-0.87],[5.97,-0.67],[5.87,-0.41],[5.87,-0.12],[5.99,0.13],
        [6.19,0.33],[6.45,0.43],[6.36,0.97],[6.07,0.98],[5.82,1.09],
        [5.62,1.3],[5.52,1.56],[5.52,1.84],[5.64,2.1],[5.84,2.3],
        [6.11,2.4],[6.01,2.94],[5.73,2.95],[5.47,3.06],[5.27,3.27],
        [5.17,3.53],[5.18,3.81],[5.29,4.07],[5.5,4.27],[5.76,4.37],
        [5.66,4.91],[5.38,4.92],[5.12,5.03],[4.93,5.24],[4.69,5.61],
        [4.47,6.2],[6.55,6.2],[10.54,-16.45],[8.55,-16.45],[8.65,-15.88],
        [8.76,-15.62],[8.97,-15.43],[9.23,-15.32]]);
        translate([6.55,6.2,11.7])
        rotate([0,0,10])
        rotate([90,0,0])
        cylinder(d=2.2,h=23,$fn=4);
    }
}

module DrawCarriage()
{
    translate([0,4,0])      //Put traxxas connections on centerline
    difference()
    {
        Carriage();
        translate([-12,-16.95,1])
        cube([10,23.65,20]);
        BeltGroove();
        translate([-3.85,0,0])
        BeltGroove();

        translate([-28.5,-4,7])
        rotate([0,90,0])
        cylinder(d=M3,h=M3Ht,$fn=M3_ires);  //Cut for M3 bolt on Left Side
        translate([14,-4,7])
        rotate([0,90,0])
        cylinder(d=M3,h=M3Ht,$fn=M3_ires);  //Cut for M3 bolt on Left Side

        translate([-20,-4,7])
        rotate([0,90,0])
        cylinder(d=M3Nut,h=M3NutHt,$fn=6);  //Cut opening for Left Jam Nut
        translate([-20,-4,10])
        rotate([0,90,0])
        cylinder(d=M3Nut,h=M3NutHt,$fn=6);  //Make sure nut is open to top

        translate([17.2,-4,7])
        rotate([0,90,0])
        cylinder(d=M3Nut,h=M3NutHt,$fn=6);  //Cut opening for Left Jam Nut
        translate([17.2,-4,10])
        rotate([0,90,0])
        cylinder(d=M3Nut,h=M3NutHt,$fn=6);  //Make sure nut is open to top

        translate([-28,5.71,Car_Ht])
        rotate([0,90,0])
        cylinder(d=16,h=17,$fn=4);           //Chamfer the bottom Left side a little more
    //Originally 11.5,-3.49,11.71, but changed to give more plastic at new belt clamp
        translate([11.2,5.71,Car_Ht])
        rotate([0,90,0])
        cylinder(d1=0,d2=16,h=6,$fn=4);           //Chamfer the bottom Left side a little more
        translate([11.2+6,5.71,Car_Ht])
        rotate([0,90,0])
        cylinder(d=16,h=17,$fn=4);           //Chamfer the bottom Left side a little more

        translate([-27.5,-15.95,Car_Ht])
        rotate([0,90,0])
        cylinder(d=6,h=55,$fn=4);           //Chamfer the bottom side Edge

        translate([-27.5,-15.95,Car_Ht])
        rotate([0,90,0])
        cylinder(d=16,h=16,$fn=4);           //Chamfer the bottom Left side a little more
        translate([-27.5,5.71,Car_Ht])
        rotate([0,90,0])
        cylinder(d=6,h=55,$fn=4);           //Chamfer the bottom side Edge
//slice off top & bottom sides a sliver to make an even dimension
        translate([-30,-25.3,-1])
        cube([60,10,20]);
        translate([-30,4.9,-1])
        cube([60,10,20]);
    }
}
//DrawCarriage();
```


[User]
Hey, I'm looking to design a customizable crate, and I'd like to have it be parametric in OpenSCAD. I need to be able to specify the inside length, inside width, and height of the crate. I'd also like to be able to control the wall thickness.

Additionally, I want the crate to have circular holes all over - on the bottom and on the sides. I want to be able to specify the diameter of these holes as well. The holes should be spaced somewhat evenly, and the spacing should be dependent on the hole diameter to ensure there is some space between them. I'm hoping that the parameters will let me control these aspects.

Could you generate the OpenSCAD code for this design? I'm looking for it to be a single file.

[Assistant]
customizable_crate_2.scad:
```
// Customizable Crate
// by Kevin McCormack

// The length of the inside of the box in mm
inside_length = 50; //[10:1:300]
// The width of the inside of the box in mm
inside_width = 50; //[10:1:300]
// Height of the box in mm
height = 50; //[10:1:300]

// Thickness of the walls in mm
wall_thickness = 1; //[1:0.1:4]

// Diameter of crate holes
hole_d = 5; //[2:1:20]

outside_length = inside_length + (wall_thickness * 2);
outside_width = inside_width + (wall_thickness * 2);

num_x_holes =  floor(inside_length/(hole_d+2));
x_offset = inside_length/num_x_holes;
x_start = (x_offset * num_x_holes / (-2)) + (hole_d/2) + 1;
x_end = x_offset * num_x_holes / 2;

num_y_holes =  floor(inside_width/(hole_d+2));
y_offset = inside_width/num_y_holes;
//y_start = num_y_holes/(-2) * (hole_d+1);
//y_end = num_y_holes/2 * (hole_d+1);
y_start = (y_offset * num_y_holes / (-2)) + (hole_d/2) + 1;
y_end = y_offset * num_y_holes / 2;

num_z_holes =  floor(height/(hole_d+1));
z_start = height/num_z_holes;
z_offset = height/num_z_holes + 1;
z_end = height - hole_d/2 - 1;

module boxBase() {
    difference() {
        translate([0,0,height/2])
        cube([outside_length,outside_width,height],center=true);

        translate([0,0,((height/2) + wall_thickness)])
        cube([inside_length,inside_width,height],center=true);

    }
}

module bottomCuttout() {
    for (y=[y_start:y_offset:y_end]) {
        for (x=[x_start:x_offset:x_end]) {
            translate([x,y,0])
            cylinder(h=wall_thickness*3, d=hole_d, center=true);
        }
    }
}

module xCuttout() {
    for (z=[z_start:z_offset:z_end]) {
        for (y=[y_start:y_offset:y_end]) {
            translate([0,y,z]) rotate([0,90,0])
            cylinder(h=outside_length+5, d=hole_d, center=true);
        }
    }
}

module yCuttout() {
    for (z=[z_start:z_offset:z_end]) {
        for (x=[x_start:x_offset:x_end]) {
            translate([x,0,z]) rotate([90,0,0])
            cylinder(h=outside_width+5, d=hole_d ,center=true);
        }
    }
}

difference() {
    boxBase();
    yCuttout();
    bottomCuttout();
    xCuttout();
}
```


[User]
I'd like to design a parametric desk sign with a stand, and I want to be able to customize the text on two lines, the length of the sign, the tilt angle, and the corner radius. I'm envisioning a design similar to the one described here: [link to Thingiverse: https://www.thingiverse.com/thing:1278048/]. The sign itself should have rounded corners and the stand should have a rounded look as well.

Here are the specific parameters I want to control:

*   **`text_line_1`**: The text for the top line of the sign (default: "Line 1").
*   **`text_line_2`**: The text for the bottom line of the sign (default: "Line 2").
*   **`sign_length`**: The overall length of the sign. The default should be something reasonable like 100, but I need to adjust this to fit the text.
*   **`stand_angle`**: The tilt angle of the sign and stand in degrees. The default should be 60, but should be adjustable.
*   **`radius`**: The corner radius for the rounded edges of the sign. A default radius of 5 seems good.
*   **`$fn`**: This is for the sphere resolution for the rounded corners. A value of 10 seems fine to start with.

The sign should be a base plate with the two text lines extruded out. The stand should be attached at the center bottom of the sign, and consist of a half-cylinder with round ends, also with an adjustable radius.

Could you generate the OpenSCAD file for this? I don't need to use any specific external libraries.

[Assistant]
parametric-sign-with-stand.scad:
```
/*
Parametric Magnetic Name Sign
http://www.thingiverse.com/thing:1278048/

By Paul Houghton
Twitter: @mobile_rat
Email: paulirotta@gmail.com
Blog: http://paul-houghton.com/

Creative Commons Attribution ShareAlike License
https://creativecommons.org/licenses/by-sa/4.0/legalcode
*/

/* [Parametric Sign With Stand options] */
// Sign text top line
text_line_1="3D Print Training";

// Sign text bottom line
text_line_2="10:00 This Friday";

// Length (change to match text)
sign_length=113;

// Tilt from horizontal (90 is straight up)
stand_angle=60;

// Sign corner radius
radius=5;

// Number of facets to approximate a sphere
$fn=10;

rotate([stand_angle,0,0]) {
    sign(line1=text_line_1, line2=text_line_2);
    stand();
}

module sign(line1="Line1", line2="Line2") {
    difference() {
        translate([-4,-6,-radius]) minkowski() {
            cube([sign_length,35,2]);
            sphere(r=radius);
        }

        union() {
            translate([0,15,0]) linear_extrude(height=3) text(line1);
            linear_extrude(height=3)text(line2);
        }
    }
    stand();
 }

module stand() {
    translate([sign_length/2-radius,-3.2,-10]) rotate([-stand_angle,0,0]) minkowski() {
        cylinder(r=20,h=2);
        sphere(r=5);
    }
}
```


[User]
Hey, I'm looking to design a propeller guard for a small quadcopter, specifically the Hovership 3DFly. I have some parameters in mind, and I'd like to be able to customize them easily in OpenSCAD.

Here's what I'm thinking:

**Motor Mount:**

*   I need a circular clip to fit around the motor. The internal diameter of this clip should be adjustable, let's start with a variable `motor_d` set to 8mm.
*   The clip should have a height, `motor_h`, initially set to 3mm.
*   The clip wall thickness, `motor_t`, should start at 1.5mm.
*   There should be a pin on the clip to help secure it to the frame, with a height of `pin_h` (2mm), a width of `pin_w` (2mm), and a rotation angle `pin_r` which starts at 0 degrees.
*   I want a cutout on the side of the clip so it can flex a bit to clip onto the motor. It should have a width of `cut_w` starting at 2mm.

**Propeller Guard Arms:**

*   Two arms should extend from the motor mount. The length of these arms from the motor center should be adjustable via `arm_l` starting at 30mm.
*   The base of the arm should have a height of `arm_base_h` starting at 3mm and a width of `arm_base_w` starting at 2mm.
*   The angle between the two arms needs to be adjustable using the variable `arm_a`, starting at 120 degrees.

**Guard Ring:**

*   A ring that connects the ends of the arms. The ring's height, `guard_h`, should be 1.5mm. The width of the guard ring, `guard_w`, should start at 1mm.

Essentially, I’d like a parametric design where I can adjust all of those values. Could you generate the OpenSCAD code for this?

[Assistant]
3DFly_Prop_Guard.scad:
```
// motor clip internal diameter
motor_d = 8;
// motor clip height
motor_h = 3;
// motor clip thickness
motor_t = 1.5;
// motor clip pin height
pin_h = 2;
// motor clip pin width
pin_w = 2;
// motor clip pin z rotation angle
pin_r = 0;
// motor clip cut width
cut_w = 2;
// guard height
guard_h = 1.5;
// guard width
guard_w = 1;
// arm length from motor center
arm_l = 30;
// arm base height
arm_base_h = 3;
// arm base width
arm_base_w = 2;
// angle between the two arms
arm_a = 120; // [0:180]

module prop_guard() {
    $fn=40;

    difference() {
        union() {
            arm(-arm_a/2);
            arm(arm_a/2);
            cylinder(r=motor_d/2+motor_t,h=motor_h);
            rotate([0,0,0])translate([0,0,motor_h]) motor_pin();
        }
        cylinder(r=motor_d/2,h=motor_h);
        translate([-motor_d/2-motor_t,-cut_w/2,0]) cube([motor_t*2,cut_w,motor_h]);
    }

    intersection() {
        difference() {
            cylinder(r=arm_l,h=2);
            cylinder(r=arm_l-guard_w,h=guard_h);
        }
        hull() {
            rotate([0,0,-arm_a/2]) cube([arm_l*2,0.1,guard_h]);
            cube([arm_l*2,0.1,guard_h]);
            rotate([0,0,arm_a/2]) cube([arm_l*2,0.1,guard_h]);
        }
    }
}

module arm(angle) {
    rotate([0,0,angle])hull() {
        cylinder(r=arm_base_w/2,h=arm_base_h);
        translate([arm_l-guard_w/2,0,0])cylinder(r=guard_w/2,h=guard_h);
    }
}

module motor_pin() {
    intersection() {
        cylinder(r=motor_d/2+motor_t,h=pin_h);
        translate([motor_d/2,-pin_w/2,0])cube([motor_t,pin_w,pin_h]);
    }
}

prop_guard();
```