[User]
I'm looking to design a parametric 3D-printable pommel for a synthetic sword, similar to the ones used on Rawlings sparring swords. I want it to be configurable for different handle sizes and mounting methods. I've got a rough example in SCAD, but I'd like a more robust and flexible design, preferably broken into smaller modules.

Here's what I'm envisioning:

**Overall Structure:**

*   The pommel should be composed of three main parts: the main wheel, a tapered transition area, and a base for attaching to the sword's tang. I'd like to be able to control the diameter and thickness of each section independently.
*   I want to be able to optionally create a hexagonal captive nut recess in the base or a simple threaded hole, both with adjustable tolerances. The mounting hole should also be able to be specified as a standard thread size (like M8), rather than just a diameter for easy modification.

**Specific Parameters:**

*   **Wheel:**
    *   `wheel_diameter`: Diameter of the main wheel portion.
    *   `wheel_thickness`: Thickness of the main wheel portion.
*   **Taper:**
    *   `taper_inner_diameter`: Diameter where the taper connects to the wheel.
    *   `taper_outer_diameter`: Diameter where the taper connects to the base.
    *   `taper_thickness`: Total thickness of the taper (both sides).
*   **Base:**
    *   `base_diameter`: Diameter of the base where it connects to the tang.
    *   `base_height`: Height/length of the base.
    *  `mounting_type`: A string variable that is either "captive nut" or "screw hole".
    *   `mounting_thread`: A string variable that specifies the thread size (e.g. "M8") that is used when `mounting_type` is set to "captive nut"
    *   `screw_hole_diameter`: A diameter that is used when `mounting_type` is set to "screw hole".
    *   `tolerance`: A general tolerance value that is applied to the mounting hole.
*   **General:**
    *   `fn`: Number of facets for curves (smoothness). This should apply globally.
    *   `total_height`: The total height of the final object.

**Requirements:**

*   The design should be parametric so that adjusting a parameter updates the entire model.
*   I'd prefer if the design was broken into separate modules for the wheel, taper, and base, making the code easier to read and modify.
*   The design should use modules where it makes sense.
*   I would like the code to use the `thread` module from the BOLTS library to create the captive nut hole and optionally the screw hole if `mounting_type` is set to "screw hole".

Could you create an OpenSCAD file (or a set of modular files) to accomplish this design? Please use comments to explain the code. I’m not as familiar with how all the libraries and functions work yet, so lots of comments are helpful. Thanks!

[Assistant]
rawlings_wheel_pommel.scad:
```
tolerance = 0.1;
captive_nut = 1; //Set to something else if you'd rather screw directly into plastic
$fn = 60;

difference() {

	union() {
		//Main wheel and tapered faces
		cylinder(r=30, h=20, center=true);
		translate([0,0,-20/2-7/2]) cylinder(r1=24, r2=26, h=7, center=true);
		translate([0,0,20/2+7/2]) cylinder(r1=26, r2=24, h=7, center=true);
		//This should probably just be mirriored, but I'm too lazy.

		//The base
		translate([15,0,0]) rotate([0,90,0]) cylinder(r=25/2, h=30, center=true);
	}

	union(){
		translate([0,0,19/2+7]) cylinder(r=19/2, h=4, center=true);
		translate([0,0,-19/2-7]) cylinder(r=19/2, h=4, center=true);

		if(captive_nut==1){
			rotate([90,0,0]) translate([tolerance, 0, 0]) rotate([0,90,0]) cylinder(r=15/2+tolerance, h=32+tolerance, $fn=6);
		} else {
			translate([-tolerance, 0, 0]) rotate([0,90,0]) cylinder(r=7/2+tolerance,h=32+tolerance);
		}
	}
}
```


[User]
Okay, I'm looking to design a parametric wall holder for a multimeter. I've seen some designs online using rounded cube modules, and I'd like something similar. The holder should have a main cavity for the multimeter to slide into, a back piece that keeps the multimeter off the wall a bit and provides space for probes, and some mounting holes for screws. I'd like to be able to customize the dimensions of the holder easily.

Specifically, I need parameters for the following:

*   `width`: The width of the multimeter.
*   `height`: The height of the main cavity.
*   `depth`: The depth of the main cavity.
*   `backWidth`: How far the back of the holder sticks out from the wall.
*   `wallWidth`: Thickness of the walls, floor, and front of the holder.
*   `screwDiameter`: Diameter of the screw holes.

The design should:

1.  Use a rounded cube function (I've seen it called "cubeX") to create the basic shapes. It should be able to handle a single size value as well as a vector of sizes. The `radius` parameter in `cubeX` should default to 1.
2.  Have a main cutout for the multimeter to slide into, with a gap on all sides of the device.
3.  Have an additional cutout to make the holder lighter. This should also leave a gap around the sides of the device.
4.  Include screw holes, placed vertically along the back, that can accommodate mounting screws, with countersinks to get the screw heads flush.
5.  Use a `tolerance` value (default to 0.1) for cleaner boolean operations.
6.  Have a quality setting `$fn` (default 30).

I'd also like the `cubeX` module included as a separate .scad file so it can be easily re-used.

Could you please generate the OpenSCAD code for this parametric wall holder, using a separate file for the `cubeX` module? I’m hoping that the code will be clean and easy to understand. Thanks!

[Assistant]
MultimeterWallHolder.scad:
```
// <Sopak's Multimeter Wall Holder> (c) by <Kamil Sopko>
//
// <Sopak's Multimeter Wall Holder> is licensed under a
// Creative Commons Attribution-ShareAlike 4.0 Unported License.
//
// You should have received a copy of the license along with this
// work.  If not, see <http://creativecommons.org/licenses/by-sa/4.0/>.

/* [Main Dimensions] */

//width of device
width=84;
//height of holder withot bottom(wallWidth)
height=70;
//depth of device to slide properly
depth=45;

/* [Other Dimensions] */

//back width/distance from wall  for placing probes etc
backWidth=16;
//with of wall, bottom and front
wallWidth=4.5;
//diametter of screw (screw head is  double)
screwDiameter=4;

/* [Other Values] */

//just  for cleaner boolean  operations
tolerance=0.1;
//quality
$fn=30;

//cubeX is from here http://www.thingiverse.com/thing:112008

// Include here  for customizer compatibility
//
// Simple and fast corned cube!
// Anaximandro de Godinho.
//

module cubeX( size, radius=1, rounded=true, center=false )
{
	l = len( size );
	if( l == undef )
		_cubeX( size, size, size, radius, rounded, center );
	else
		_cubeX( size[0], size[1], size[2], radius, rounded, center );
}

module _cubeX( x, y, z, r, rounded, center )
{
	if( rounded )
		if( center )
			translate( [-x/2, -y/2, -z/2] )
			__cubeX( x, y, z, r );
		else
			__cubeX( x, y, z, r );
	else
		cube( [x, y, z], center );
}

module __cubeX(	x, y, z, r )
{
	//TODO: discount r.
	rC = r;
	hull()
	{
		translate( [rC, rC, rC] )
			sphere( r );
		translate( [rC, y-rC, rC] )
			sphere( r );
		translate( [rC, rC, z-rC] )
			sphere( r );
		translate( [rC, y-rC, z-rC] )
			sphere( r );

		translate( [x-rC, rC, rC] )
			sphere( r );
		translate( [x-rC, y-rC, rC] )
			sphere( r );
		translate( [x-rC, rC, z-rC] )
			sphere( r );
		translate( [x-rC, y-rC, z-rC] )
			sphere( r );
	}
}

// end of cubeX customizer compatibility

// holder itself

difference(){
    cubeX([width+2*wallWidth,depth+wallWidth+backWidth,height+wallWidth]);
    translate([wallWidth,backWidth,wallWidth+tolerance]){
        cubeX([width,depth,height]);
        translate([2*wallWidth,wallWidth*2,2*wallWidth])cubeX([width-4*wallWidth,depth,height]);
    }
    for(z=[20:20:height-10]){
        for(x=[-20:10:20]){
            translate([(width+2*wallWidth)/2+x,-tolerance,z])rotate([-90,0,0]){
                cylinder(d=screwDiameter,h=backWidth+2*tolerance);
                translate([0,0,backWidth-screwDiameter/1.5+2*tolerance-wallWidth])cylinder(d1=screwDiameter,d2=screwDiameter*2,h=screwDiameter/1.5);
                translate([0,0,backWidth-wallWidth+2*tolerance])cylinder(d=screwDiameter*2,h=wallWidth*2);
            }
        }
    }
}

```
cubeX.scad:
```
//
// Simple and fast corned cube!
// Anaximandro de Godinho.
//

module cubeX( size, radius=1, rounded=true, center=false )
{
	l = len( size );
	if( l == undef )
		_cubeX( size, size, size, radius, rounded, center );
	else
		_cubeX( size[0], size[1], size[2], radius, rounded, center );
}

module _cubeX( x, y, z, r, rounded, center )
{
	if( rounded )
		if( center )
			translate( [-x/2, -y/2, -z/2] )
			__cubeX( x, y, z, r );
		else
			__cubeX( x, y, z, r );
	else
		cube( [x, y, z], center );
}

module __cubeX(	x, y, z, r )
{
	//TODO: discount r.
	rC = r;
	hull()
	{
		translate( [rC, rC, rC] )
			sphere( r );
		translate( [rC, y-rC, rC] )
			sphere( r );
		translate( [rC, rC, z-rC] )
			sphere( r );
		translate( [rC, y-rC, z-rC] )
			sphere( r );

		translate( [x-rC, rC, rC] )
			sphere( r );
		translate( [x-rC, y-rC, rC] )
			sphere( r );
		translate( [x-rC, rC, z-rC] )
			sphere( r );
		translate( [x-rC, y-rC, z-rC] )
			sphere( r );
	}
}

```


[User]
Hey there! I'm looking to create a custom keyguard for a tablet, something like the one I found on Thingiverse (http://www.thingiverse.com/thing:1325717), but I need it to be fully parametric and a bit more flexible. I'm envisioning something that I can easily adjust for different devices and button layouts.

Ideally, I'd like to be able to define the overall dimensions of the keyguard (height, width, and depth), the number of rows and columns of openings, and the size of the attachment tabs. The openings should be evenly spaced, and the size of the openings will likely need to be adjusted based on how many there are. Oh, and the keyguard should have tabs on the left and right sides that would allow it to be attached to the tablet case.

I don't need anything super fancy, but it would be great if the code was clean, well-commented, and used a modular approach so it's easy to modify down the road. It would be awesome if it could handle a maximum of 5x5 key fields as well - the Thingiverse description mentions that limit. I'm not expecting any libraries, but if you think something might make this easier then feel free to suggest them. I'm just not really comfortable relying on things outside of the core SCAD language.

[Assistant]
KeyguardWithTabs.scad:
```
//////////////////////////////////////////////////KeyguardWithTabs
//author: Tim Driskell
//date: 12/10/2015
/////////////////////////////////////////////////

//////////////user inputs////////////////////////

height =157.15;//desired length of the keyguard
width = 120.65;//desired width of the keyguard
depth = 5;//keyguard thickness
cols= 2;//the number of cutouts in relation to the width of the device
rows = 2;//the number of cutouts in relation to the length of the device
tab_length = 12.5; //thickness of attachment tabs.

////////////////renderings///////////////////////
keyguard();

///////////////////modules///////////////////////
module keyguard(){
    difference(){
      cube([width,height,depth]);
        inserts();
    }
    tabs();
}
module inserts(){
    //alpha changes the size of cutouts. Size of cutout is inversely proportional to alpha
    alpha=0.25;
    //creates cutouts in x-direction
    for (i=[0:cols-1]){
    //creates cutouts in y-direction
        for (j=[0:rows-1]){
    //determines location of each cutout iterations
            translate([width/cols*i+width/(cols*(2*cols+0.75*pow((1/alpha),2))),height/rows*j+height/(rows*(2*rows+0.75*pow((1/alpha),2))),-0.01])
    //cutout size proportional to size of keyguard
            cube([width*(cols/((cols+alpha)*(cols))),height*(rows/((rows)*(rows+alpha))),depth+0.02]);
            //changing alpha increases cutout size.
        }
    }
}

module tabs() {
    translate([-tab_length,0,0])
    cube([tab_length,height,2.54]);
    translate([width,0,0])
    cube([tab_length,height,2.54]);
}
```


[User]
I'm looking to create a personalized heart-shaped puzzle, kind of like a maze, that when printed, two of them will interlock. I really like the style of the "random_heart_to_heart_generator.scad" file I found online but I need to be able to fully customize it with my own parameters.

Specifically, I want the design to have these features:

*   **Personalized Text:** Each heart should include a name, one for my name and one for my partner's name, rendered in bold Courier New.

*   **Heart Shape:** The basic shape should be a heart, constructed with two semi-circles and two isosceles triangles. I want to be able to control the overall height of the heart from its base.

*   **Maze Structure:** Inside each heart, I want a maze formed by concentric rings, with passages and walls, allowing the hearts to interlock. The maze should be generated using a random algorithm that generates a unique maze each time the file is run.

*   **Customizable Parameters:** I need to be able to control the following aspects of the design:
    *   `name_for_you`: My partner's name.
    *   `name_for_me`: My name.
    *   `heart_height`: The height of the heart.
    *   `wall_thickness`: The thickness of the maze walls and the heart outline.
    *   `wall_height`: The height/thickness of the maze walls.
    *   `cblocks`: The number of "pie slice" sections/radiations of the maze.
    *   `levels`: The number of concentric rings within the maze.
    *   `tip_factor`: Used for smoothing the base of the heart (how pointy or rounded the bottom is).
    *   `spacing`: A tolerance, or gap, between the maze lines.
    *   `ring`: An option to add an arc/ring on top of each heart.

*   **Interlocking:** The two resulting heart designs should be mirror images, such that they fit together when printed.

*   **No dependencies:** I don't want to use any external libraries for this, can you make this all from scratch?

Can you help me generate the necessary OpenSCAD file(s) to achieve this? Thanks!

[Assistant]
random_heart_to_heart_generator.scad:
```
name_for_you = "Justin";
name_for_me = "Monica";
heart_height = 30;
wall_thickness = 1.5;
wall_height = 2;
cblocks = 7;
levels = 3;
tip_factor = 15;
spacing = 0.4;
ring = "YES";

// give a [x, y] point and length. draw a line in the x direction
module x_line(point, length, thickness = 1) {
    offset = thickness / 2;
    translate([point[0] - offset, point[1] - offset, 0])
        square([length + thickness, thickness]);
}

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);
       }
}

/*
 * 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
 *
 */

// create the outer wall of maze
module maze_outer_wall(rows, columns, block_width = 5, wall_thickness = 1) {
    x_line([0, rows * block_width], columns * block_width, wall_thickness);
    y_line([0, block_width], (rows - 1) * block_width, wall_thickness);
}

// create the inner wall of maze
module maze_inner_wall(maze, block_width = 5, wall_thickness = 1) {
    for(i = [0:len(maze) - 1]) {
        cord = maze[i];
        x = (cord[0] - 1) * block_width;
        y = (cord[1] - 1) * block_width;
        v = cord[3];

        if(v == 1 || v == 3) {
            x_line([x, y], block_width, wall_thickness);
        }
        if(v == 2 || v == 3) {
            y_line([x + block_width, y], block_width, wall_thickness);
        }
    }
}

// create a maze
module maze(rows, columns, maze_vector, block_width = 5, wall_thickness = 1) {
     maze_outer_wall(rows, columns, block_width, wall_thickness);
     maze_inner_wall(maze_vector, block_width, wall_thickness);
}

/*
 * 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
            )
        )
    );

// The heart is composed of two semi-circles and two isosceles triangles.
// The triangle's two equal sides have length equals to the double `radius` of the circle.
// That's why the `solid_heart` module is drawn according a `radius` parameter.
module solid_heart(radius, tip_factor) {
    offset_h = 2.2360679774997896964091736687313 * radius / 2 - radius * sin(45);
	tip_radius = radius / tip_factor;

    translate([radius * cos(45), offset_h, 0]) rotate([0, 0, -45])
    hull() {
        circle(radius, $fn = 96);
		translate([radius - tip_radius, -radius * 2 + tip_radius, 0])
		    circle(tip_radius, center = true, $fn = 96);
	}

	translate([-radius * cos(45), offset_h, 0]) rotate([0, 0, 45]) hull() {
        circle(radius, $fn = 96);
		translate([-radius + tip_radius, -radius * 2 + tip_radius, 0])
		    circle(tip_radius, center = true, $fn = 96);
	}
}

module ring_heart(radius, tip_factor, thickness) {
    difference() {
	    offset(delta = thickness) solid_heart(radius, tip_factor);
        solid_heart(radius, tip_factor);
	}
}

module ring_heart_sector(radius, angle, tip_factor, thickness, width) {
	intersection() {
		ring_heart(radius - 0.1, tip_factor, thickness + 0.2);
		rotate([0, 0, angle]) x_line([0, 0], radius * 3, width);
	}
}

module heart_to_heart_wall(radius, length, angle, tip_factor, thickness) {
    intersection() {
        difference() {
            solid_heart(radius + length, tip_factor);
		    solid_heart(radius, tip_factor);
	    }
	    rotate([0, 0, angle])
		    x_line([0, 0], (radius + length) * 2, thickness);
	}
}

module heart_to_heart_maze(maze, radius, cblocks, levels, tip_factor, height = 1, thickness = 1, spacing = 0) {
    full_circle_angle = 360;
    arc_angle = full_circle_angle / cblocks;
	r = radius / (levels + 1);

	difference() {
		linear_extrude(height) union() {
			for(i = [1 : levels + 1]) {
				ring_heart(r * i - spacing, tip_factor, thickness + spacing * 2);
			}

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

				angle = cc * arc_angle;

				if(v == 1 || v == 3) {
					heart_to_heart_wall(r * cr - spacing, r, cc * arc_angle + 90, tip_factor, thickness + spacing * 2);
				}
			}
	    }

		linear_extrude(height) union() {
		    // maze entry
		    ring_heart_sector(r - spacing, 1.5 * arc_angle + 90, tip_factor, thickness + spacing * 2, r - thickness / 2 - spacing * 2);

	        // road to the next level
			for(i = [0:len(maze) - 1]) {
				cord = maze[i];
				cr = cord[0];
				cc = cord[1] - 1;
				v = cord[3];

				if(v == 0 || v == 1) {
					ring_heart_sector(r * (cr + 1) - spacing, (cc + 0.5) * arc_angle + 90, tip_factor, thickness + spacing * 2, r - thickness / 2 - spacing * 2);
				}
			}
		}
	}
}

module heart_to_heart_maze_you(maze, radius, cblocks, levels, tip_factor, height = 1, thickness = 1) {
	translate([0, 0, wall_height])
		heart_to_heart_maze(maze, radius, cblocks, levels, tip_factor, wall_height, wall_thickness, 0);
	linear_extrude(wall_height)
		offset(delta = wall_thickness)
			solid_heart(radius, tip_factor, wall_thickness);
}

module heart_to_heart_maze_me(maze, radius, cblocks, levels, tip_factor, height = 1, thickness = 1, spacing = 0.6) {
	translate([0, 0, wall_height]) mirror([1, 0, 0]) union() {
		difference() {
			linear_extrude(wall_height) solid_heart(radius, tip_factor, wall_thickness);
			heart_to_heart_maze(maze, radius, cblocks, levels, tip_factor, wall_height, wall_thickness, spacing);
		}
	}
	linear_extrude(wall_height)
		offset(delta = wall_thickness)
			solid_heart(radius, tip_factor, wall_thickness);
}

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

difference() {
    heart_to_heart_maze_you(maze, heart_height / 3.12,
	cblocks, levels, tip_factor, wall_height, wall_thickness);

    linear_extrude(wall_height / 2)
	    mirror([1, 0, 0])
		    text(name_for_you, font = "Courier New:style=Bold", valign = "center", halign = "center", size = heart_height / (len(name_for_you) + 1) + 1);
}

translate([1.5 * heart_height, 0, 0]) difference() {
	heart_to_heart_maze_me(maze, heart_height / 3.12, cblocks, levels, tip_factor, wall_height, wall_thickness, spacing);

    linear_extrude(wall_height / 2)
	    mirror([1, 0, 0])
		    text(name_for_me, font = "Courier New:style=Bold", valign = "center", halign = "center", size = heart_height / (len(name_for_me) + 1) + 1);
}

if(ring == "YES") {
	translate([0, heart_height / 3.12 + wall_thickness / 2, 0])
		linear_extrude(wall_height)
			arc(heart_height / 3.12 / 2, [45, 135], wall_thickness);

	translate([1.5 * heart_height, heart_height / 3.12 + wall_thickness / 2, 0])
		linear_extrude(wall_height)
			arc(heart_height / 3.12 / 2, [45, 135], wall_thickness);
}
```


[User]
Alright, so I'm looking to design a drink coaster that can mount to the edge of a desk. I've got some specific ideas about how it should work and some dimensions I'd like to be able to adjust.

First off, I want the main part of the coaster to be a sort of rectangular base, with a circular cutout for the cup. I need to be able to specify both the diameter of the cup that the hole should fit and also the overall height of the coaster.

Then, the mounting mechanism should be a couple of rectangular "jaws" or "clips" that go underneath the table. I'd like to specify the depth of these clips (how far they extend under the table) and also the thickness of the material they are made out of. And I need the option to set the table height too, that way the clips know where to clip.

Ideally, it would be cool if the lip of the cup holder area was filleted, or rounded over a bit, to help with placing the cup, and then rounded edges on the whole thing, to get rid of sharp corners.

I'd like this to be a parametric design, so I can easily adjust all of these dimensions. Could you help me design an OpenSCAD file for this? I'm not using any special libraries, I'd like to keep it fairly basic to start with.

It seems like the first step is probably making a cube and cutting out the cylinder and table clips out of it. Maybe you could make the main cup part a single piece, and then cut the table clips out. Then you add the small cylinder and extrude part for the fillet on top, and finally the cylinders to fillet the outside. Is this how you would do it?

[Assistant]
mountableDrinkCoaster_V_0.2.scad:
```
/*update notes vor V 0.2:
	so I'm scrapping a lot of the old code and changing how it creates the file. Hopefully this makes it on the build plate instead of in the middle of it. (fingers crossed)
*/

//CUSTOMIZER VARIABLES

//	These units are in inches
height_Of_table = .75;

//	These units are also in inches
diameter_Of_cup=4;

//	How deep it clips onto the table
depth_Of_slot=3;

//	How thick the part is that clips onto the table
thickness_Of_slot=.125;

//	This option will not appear because of the *1
inch = 25.4*1;

//CUSTOMIZER VARIABLES END

/*I use the inch variable so I can design relative to inches
  but the file will be in mm, aka I'm lazy,
  and it is easier for me to follow
	also I used the capital Of so
	I can easily re-assign the variable*/

height_of_table=height_Of_table*inch;
diameter_of_cup=diameter_Of_cup*inch;
depth_of_slot = depth_Of_slot*inch;
thickness_of_slot = thickness_Of_slot*inch;

height_of_thing = height_of_table+2*thickness_of_slot;
radi_of_cup = diameter_of_cup/2;

difference() {
	//this makes the inital rectangular prism this everything is then cut out of.
	union (){//combines stuff first so it's easier to work with
		translate([0,0,height_of_thing/2]){
			cube([diameter_of_cup+inch/4,diameter_of_cup+inch/4,height_of_thing],center = true);
		}

		//this adds the two small cubes that hold it to the table
		difference(){
			translate([0,diameter_of_cup/2+inch/2,height_of_thing/2]){
				cube([diameter_of_cup+inch/4,depth_of_slot,height_of_thing],center = true);
			}
			translate([0,diameter_of_cup/2+inch/2,height_of_thing/2]){
				cube([diameter_of_cup+inch/2,depth_of_slot+inch/4,height_of_table], center = true);
				//I needed to make the width and length of it a bit
				//larger so there is it is clear it cuts it all out.
			}
		}
	}

	//this cuts out the hole for the cup
	translate([0,0,5]){
		rotate([0, 0, 0])
		cylinder(height_of_thing, r = radi_of_cup, $fn = 100);
	}

	//this fillets the top of the hole so it's easier to put the drink in
	difference(){
		//so this cuts a small cylinder out
		translate([0,0,height_of_thing-inch/8])
			cylinder(inch, r = radi_of_cup+inch/8,$fn = 100);
		//this prevents a small rounded edge from being cut out, this gives the appearance of a fillet
		translate([0,0,height_of_thing/2]){
			rotate_extrude(convexity = 10, $fn = 100)
				translate([radi_of_cup+inch/8,height_of_table/2,0])
				rotate([0,0,90])
					circle(r = inch/8, $fn = 100);
		}
	}

	//this will round the exposed edges
	difference(){
		//this makes a small box
		translate([0,-(diameter_of_cup/2+inch),0])
			cube([diameter_of_cup*2,diameter_of_cup+2*inch,100],center=true);

		//this makes sure a semi-circle remains once it's done.
		translate([0,0,-50])
			cylinder(height_of_table+5*inch, r=radi_of_cup+inch*.125, $fn = 200);

	}

}
```


[User]
I need to design a clip-on hook for flat surfaces, and I'd like to be able to control its dimensions easily. I've got a basic idea in mind: a circular hook portion attached to a rectangular base that acts as a clip.

Specifically, the hook will be a partial cylinder with an outer radius and inner radius. The difference between these two radii will create the hook thickness, and the height of the cylinder the hook height/width. The rectangular base will extend perpendicular from the top of the hook, essentially clipping onto a flat surface. The clip portion has its length along the horizontal plane, its width defined as the same as the hook thickness, and its height is the clip's clamping surface height. Finally, there's an optional cut-out to control the distance the hook protrudes from the flat surface it is clipped to.

I'd like to control the following parameters:
*   `hook_diameter`: The overall diameter of the main circular hook portion.
*   `hook_thickness`: The radial difference between the inner and outer radii of the hook.
*   `hook_height`: The height/width of the cylinder defining the main hook portion
*   `clip_length`: The length of the rectangular clip portion.
*   `clip_thickness`: The thickness of the rectangular clip portion. This should match the hook thickness.
*   `clip_height`: The height of the rectangular clip portion.
*   `clip_cutout_depth`: The depth of the optional cutout to control hook protrusion, if a cutout is specified
*   `clip_cutout_width`: The width of the optional cutout
*   `clip_cutout_height`: The height of the optional cutout

I'd prefer if the design is parametric, so I can change these dimensions easily in the code.

Also, could you please make it so that the clip's length parameter describes the total length, and the clip's cutout position is controlled by a start and end parameter, both measured relative to the clip's start point? I'm realizing that the cutout shouldn't just be at a fixed position relative to the entire thing, but relative to the clip.

I don't have any specific libraries in mind. I'd like to avoid adding dependencies unnecessarily, but if you think a library would significantly improve code readability or maintainability, I'm open to the idea.

[Assistant]
kitchen-hook.scad:
```
// A kitchen hook thingie
// by Cristian Sandu

hook_dia = 20; // mm
hook_width = 2;
hook_depth = 3;

module hook() {
  difference() {
    cylinder(r = hook_dia / 2 + hook_depth, h = hook_width, center=true);
    cylinder(r = hook_dia / 2, h = hook_width + hook_depth , center=true);
  }
}

module base() {
   translate([-hook_dia / 2 - hook_depth / 1.5, 0, hook_width * 2]) {
    rotate([90, 0, 0]) {
      cube(size=[hook_width, hook_dia / 2, hook_width * 5], center=true);
    }
  }
}

difference() {
  union() {
    base();
    hook();
  }

  translate([0, -hook_dia / 2, 0]) {
    cube(size=[hook_dia, hook_dia, hook_width * 2], center=true);
  }
}

```


[User]
I need a design for a set of caps to cover standard fly vials. The caps should be designed to prevent the flies from seeing the contents of the vials. I'd like the design to be parametric so I can easily adjust it for different vial sizes.

Specifically, the cap should be a cylindrical tube with a closed top. I want to be able to adjust the following:

*   **`height`**: The overall height of the cap.
*   **`diameter`**: The outer diameter of the cap which should correspond to the outer diameter of the vial.
*   **`wall_thickness`**: The thickness of the cap's walls.

The cap should have a hollow interior, forming a tube, and the wall thickness should be consistent throughout the tube. I am imagining a single part that slides over the vials. I'd like the cap to be centered, that is, its center should be at [0, 0, 0], and I need a simple, clean design. Please use the OpenSCAD language to generate the files, and provide me with a single .scad file that defines a single module that does this. I don't need the code to include a `customizer_off()` module; I won't be using the customizer for this. Please use `cylinder()` to generate the caps, and define the modules `Base()`, `inside()`, and `final()`, and call `final()` to render the cap.

[Assistant]
Tom_behaviour_caps_customized.scad:
```
//Author: Lucia Prieto Godino
//mail: lucia.prieto@cantab.net
//February 2016
//Cover tubes behaviour

// Customazible variables

// height
height = 30;
// diameter
diameter = 9;

////////////////////////////////////////////////////////
module customizer_off(){};
////////////////////////////////////////////////////////

h1= height;
r1= diameter;
r2 = r1-1;

module Base() {
cylinder($fn=100,h= h1, r = r1, center = true);
}

//Base();

module inside() {
cylinder ( $fn=100,h = h1, r = r2, centre = true);
 translate ([0,0,-h1/2]){cylinder ($fn=100, h = h1, r = r2, centre = true);}
}

//inside();

module final() {
difference () {Base() ; inside();}
}

final();
```


[User] I want to make a customizable name plaque that can stand on its own, not just be mounted to something. I'd like to be able to set the name, width, height, font size, and font. The current version I'm working with is pretty basic, just a flat plaque with the name extruded on it. I need it to have some kind of base so it can stand upright. I’m thinking a simple, rectangular base that extends from the bottom of the plaque, wider than the plaque and deep enough to be stable would work. The plaque itself should be centered on the base. Could you help me generate some OpenSCAD code for this?

[Assistant]
test.scad:
```
//type the name you want on the plaque here
name = "name here";
//How wide do you want it (in inches)
plaque_Width=3;
//How tall do you want it (in inches)
plaque_Height=1;

//The size the letters are
font_size = 12;//[1:50]

//Note: not all fonts may work
text_font = "Arial";

inch = 25.4*1;//my favorite variable

plaque_width = plaque_Width*inch;
plaque_height = plaque_Height*inch;
cube([plaque_width,plaque_height,2], center = true);
linear_extrude(height = 2, convexity = 10){
	translate([-(len(name)+.75)*font_size/3,-font_size/3,.75]){
		text(name, font = text_font, size = font_size);
	}
}
```


[User]
I need a parametric OpenSCAD design for a PCB clip that mounts onto a standard DIN rail. I've got a basic design in mind, and I'd like to be able to customize several aspects.

The clip's main shape will be derived from a 2D polygon, which I've provided as a list of points. I'll need this polygon to be extruded to a specified thickness (CLIP_H). Also, the clip will have a mounting bar running along its back (MOUNT_H), and two pillars that extend out from the mounting bar (PILLAR_H) with holes for mounting screws. The distance between the two pillar center points will be adjustable (PILLAR_PITCH).

Here are the parameters I'd like to control:
*   **CLIP_H:** The thickness of the main clip body (extrusion height).
*   **HOLE_DIAMETER:** The diameter of the screw holes in the pillars.
*   **PILLAR_PITCH:** The distance between the centers of the two mounting pillars.
*   **MOUNT_H:** The thickness of the mounting bar on the back of the clip.
*   **PILLAR_H:** The length of the mounting pillars extending from the mounting bar.

The 2D polygon shape is defined by these coordinates:
`[[9.403850,21.092300],[9.584450,20.854000],[9.593250,20.554200],[9.427250,20.305200],[5.756350,17.154800],[5.495650,17.124500],[5.354950,17.347200],[5.354950,19.249500],[-5.295400,19.249500],[-5.647940,19.095200],[-5.769030,18.756400],[-5.654770,18.417500],[-5.295400,18.264200],[2.869650,18.264200],[3.253450,18.186000],[3.566950,17.975100],[3.777850,17.661600],[3.854950,17.277800],[3.854950,-17.249500],[5.354950,-17.249500],[6.381350,-13.599100],[6.745650,-13.189900],[7.271050,-13.038600],[7.819850,-13.038600],[8.168450,-13.183100],[8.312950,-13.531700],[8.312950,-17.211400],[8.162650,-19.965300],[7.735850,-20.605000],[7.096250,-21.032700],[6.341350,-21.183100],[-9.593250,-21.183100],[-9.593250,21.183100],[9.118650,21.183100]]`

I'd like the main clip body to be centered, and the mounting bar and pillars should be attached to the back of the main clip shape. The screw holes should go all the way through the pillars. It would be great if the design can be easily adjustable by changing these parameters.

I'm not using any external libraries currently, so please generate a self-contained OpenSCAD file or files.

[Assistant]
PCB_din_clip.scad:
```
// Remix of http://www.thingiverse.com/thing:806093

//Clip thickness
CLIP_H = 6;
// Holes diameter
HOLE_DIAMETER = 2.9;
// Distance between the 2 holes
PILLAR_PITCH = 62.23;

// Height of the mounting bar
MOUNT_H = 5;
// Height of pillars
PILLAR_H = 2;

PILLAR_1_Y_OFFSET = PILLAR_PITCH/2;
PILLAR_2_Y_OFFSET = -PILLAR_PITCH/2;

module shape()
{
    p = [[9.403850,21.092300],[9.584450,20.854000],[9.593250,20.554200],[9.427250,20.305200],[5.756350,17.154800],[5.495650,17.124500],[5.354950,17.347200],[5.354950,19.249500],[-5.295400,19.249500],[-5.647940,19.095200],[-5.769030,18.756400],[-5.654770,18.417500],[-5.295400,18.264200],[2.869650,18.264200],[3.253450,18.186000],[3.566950,17.975100],[3.777850,17.661600],[3.854950,17.277800],[3.854950,-17.249500],[5.354950,-17.249500],[6.381350,-13.599100],[6.745650,-13.189900],[7.271050,-13.038600],[7.819850,-13.038600],[8.168450,-13.183100],[8.312950,-13.531700],[8.312950,-17.211400],[8.162650,-19.965300],[7.735850,-20.605000],[7.096250,-21.032700],[6.341350,-21.183100],[-9.593250,-21.183100],[-9.593250,21.183100],[9.118650,21.183100]];

    xm = min([ for (x=p) x[0] ]);
    ym = min([ for (x=p) x[1] ]);
    echo([xm, ym]);
    translate([0,22.183,0]) // This offset is know by displaying
                            // DXF file a CAD software
        rotate([180,0,0])
            translate([-xm, -ym])
                polygon(p);
}

module din_clip() {

	difference() {

		union() {
            linear_extrude(height=CLIP_H, center=true, convexity=5) {
                //import(file="PCB_din_clip.dxf", $fn=64);
                shape();
            }

            translate([-MOUNT_H/2, 0, 0]) {
                cube([MOUNT_H,PILLAR_PITCH+6,CLIP_H], center=true);
            }

            translate([-PILLAR_H/2-MOUNT_H, PILLAR_1_Y_OFFSET, 0]) {
				rotate([0, 0, 0]) {
					cube([PILLAR_H,6,CLIP_H], center = true);
				}
            }

            translate([-PILLAR_H/2-MOUNT_H, PILLAR_2_Y_OFFSET, 0]) {
				rotate([0, 0, 0]) {
					cube([PILLAR_H,6,CLIP_H], center = true);
				}
            }
		}

		union() {
			translate([-PILLAR_H-MOUNT_H-0.5, PILLAR_2_Y_OFFSET, 0]) {
				rotate([0, 90, 0]) {
					cylinder(h= PILLAR_H+MOUNT_H+1, r = HOLE_DIAMETER / 2, $fn = 16);
				}
			}
			translate([-PILLAR_H-MOUNT_H-0.5, PILLAR_1_Y_OFFSET, 0]) {
				rotate([0, 90, 0]) {
					cylinder(h= PILLAR_H+MOUNT_H+1, r = HOLE_DIAMETER / 2, $fn = 16);
				}
			}
		}
    }
}

din_clip();

```


[User]
I'd like to create a customizable paintbrush holder, something like the Cubistand Pen Brush Holder Stand, but I'd like a version that allows for a connecting rod and a cap.

Here's how I'm envisioning it:

The design should consist of four main parts: a base, a top, a connecting rod, and an optional cap. Each part should be easily printed separately and then assembled.

The base and top will be identical except for their z-axis position. They'll have a grid of holes for the paintbrushes. The holes should be rounded rectangles and parameters should control the width and depth of the holes, along with the wall thickness between them. There should also be a parameter for the height of the base and top (I want these to be the same height), and for the thickness of the base's bottom.

The base and top should have rounded corners. A rounding parameter should control the radius of these corners. There should also be a parameter to specify a smaller amount of rounding on the *inside* of the holes, but should also fall back to no rounding if that value would be negative.

The connecting rod should be a rounded rectangle extrusion and should have a height parameter, excluding the parts that go into the base and top.  The ends of the rod that go into the base and top should be slightly smaller than the holes in the base/top to ensure they will fit. There should be a parameter for the 'rod play' (the amount to shrink it). The cap is a simple rounded rectangle and should fit onto the top of the connecting rod. There should be a parameter to control the cap height; if zero, there should be no cap at all.

I would like to be able to specify the number of holes in the width and the depth.

I'd like the whole design to be parametric, so I can change all these dimensions and counts. The parts should be generated using `difference()` and `union()`.

Could you please generate an OpenSCAD file or files for this, taking into account all the parameters I've described? Use `$fn` for controlling the smoothness of curves. The only library needed is the built in one.

[Assistant]
PaintbrushHolder.scad:
```
// Brush holder
//
// ===================================================
// This is a remix of the Cubistand Pen Brush Holder Stand
// by sdmc
//
// ===================================================

// preview[view:south, tilt:top]

/* [Parameters] */

// Which part would you like to see?
part = "fullset"; // [base:Base only,top:Top only,rod:Connecting rod,cap: Connecting rod cap, fullset:Full set of parts]

// Paintbrush hole width.
hole_w = 10;

// Paintbrush hole length.
hole_d = 10;

// Wall thickness.
wall_thickness = 2;

// Holder base and top height
holder_h = 8;

//Rod height (excludes the part that goes into the base and top)
rod_h = 50;

// Number of holes width
holes_count_w = 5;

// Number of holes depth
holes_count_d = 6;

// Rounding. This is the rounding at the corners of the base and top.
rounding = 6;

// Bottom Thickness.
bottom_h = 3; //[1,2,3,4,5]

// Rod play. This shrinks the ends of the rod by a smidge so they can be inserted into the printed base and top.
rod_play = 0.05; // [0,0.05, 0.1, 0.2]

// Cap height. Zero means no cap.
cap_h = 6;

/*[Hidden]*/
full_width = holes_count_w * (hole_w + wall_thickness) + wall_thickness;
full_depth = holes_count_d * (hole_d + wall_thickness) + wall_thickness;
$fn = 64;

inner_rounding = rounding - wall_thickness;
if ( inner_rounding < 0 ) {
    inner_rounding = 0;
}

print_part();

module print_part() {
    if (part=="base") {
        part_base();
    }
    else if (part == "top") {
        part_main();
    }
    else if (part == "cap") {
        part_cap();
    }
    else if (part == "rod") {
        part_rod();
    }
    else if (part=="fullset") {
        part_fullset();
    }
}

module part_fullset() {
    part_base();
    part_main();
    part_rod();
    part_cap();
}

module part_cap() {
    if ( cap_h > 0 ) {
         translate([0,0,rod_h+30]) {
            difference() {
                onecorner_rounded_rectangle(hole_w+2*wall_thickness, hole_d+2*wall_thickness, cap_h, rounding);
                translate([wall_thickness,wall_thickness,-1])
                onecorner_rounded_rectangle(hole_w, hole_d, cap_h - wall_thickness+2, inner_rounding);
            }
        }
    }
}

module part_rod() {
    union() {
        translate([0,0,holder_h])
            onecorner_rounded_rectangle(hole_w+2*wall_thickness, hole_d+2*wall_thickness, rod_h, rounding);

        o = sign(cap_h) * (cap_h - wall_thickness);

        translate([wall_thickness+rod_play,wall_thickness+rod_play,rod_play])
            onecorner_rounded_rectangle(hole_w-rod_play*2,
                    hole_d-rod_play*2,
                    rod_h+(2*holder_h)-rod_play*2 + o,
                    inner_rounding);
    }
}

module part_base() {
    union() {
        holed_rectangle();
        translate([0,0,-bottom_h]) {
            rounded_rectangle(bottom_h);
        }
    }
}

module part_main() {
    translate([0,0,rod_h+holder_h]) {
        holed_rectangle();
    }
}

module holed_rectangle() {
    difference() {
        rounded_rectangle(holder_h);
        for( x=[0:holes_count_w-1]) {
             for( y =[0:holes_count_d-1] ) {
                translate(
                    [wall_thickness+ (hole_w + wall_thickness) * x ,
                     wall_thickness+ (hole_d + wall_thickness) * y,
                     -1]) {
                         if ( (x == 0 && y == 0)) {
                             onecorner_rounded_rectangle( hole_w, hole_d, holder_h+2, inner_rounding);
                         }
                         else if ( x==0 && y == (holes_count_d -1)) {
                             rotated_rounded_hole(180, true);
                         }
                         else if ( x== (holes_count_w -1) && y == (holes_count_d -1)) {
                             rotated_rounded_hole(180, false);
                         }
                         else if ( x==(holes_count_w -1) && y == 0) {
                             rotated_rounded_hole(0, true);
                         }
                         else
                         {
                             onecorner_rounded_rectangle( hole_w, hole_d, holder_h+2,0);
                         }
                }
             }
        }
    }
}

module rotated_rounded_hole(deg, which_corner) {
     translate([hole_w/2, hole_d/2,0]) {
         rotate([0,0,deg]) {
             translate([-hole_w/2, -hole_d/2,0]) {
                 if ( !which_corner)
                     onecorner_rounded_rectangle( hole_w, hole_d, holder_h+2, inner_rounding, 0);
                 else
                     onecorner_rounded_rectangle( hole_w, hole_d, holder_h+2, 0, inner_rounding);
             }
         }
    }
}

module onecorner_rounded_rectangle(w, d, h, r, r1) {
    difference() {
        cube([w, d, h], false);
        if ( r > 0 ) {
            round_corner(r,h);
        }
        if ( r1 > 0 ) {
            other_round_corner(r1, w, h);
        }
    }
}

module round_corner(r, h) {
    p=1;
    difference () {
        translate([-p,-p,-p]) {
            cube( [r+p,r+p,h+p*2] , false);
        }
        translate([r, r, 0]) {
            cylinder(h,r,r);
        }
    }
}

module other_round_corner(r,w,h) {
    p=1;
    difference () {
        translate([w-r,-p,-p]) {
            cube( [r+p,r+p,h+p*2] , false);
        }
        translate([w-r, r, 0]) {
            cylinder(h,r,r);
        }
    }
}

module rounded_rectangle(h) {
    union() {
        translate([0,rounding,0]) {
            cube([full_width,full_depth - (rounding * 2),h], false);
        }
        translate([rounding,0,0]) {
            cube([full_width - (rounding * 2), full_depth ,h], false);
        }
        translate([rounding,rounding,0]) {
            cylinder(h, rounding, rounding);
        }
        translate([full_width - rounding,rounding,0]) {
            cylinder(h, rounding, rounding);
        }
        translate([full_width - rounding,full_depth - rounding,0]) {
            cylinder(h, rounding, rounding);
        }
        translate([rounding,full_depth - rounding,0]) {
            cylinder(h, rounding, rounding);
        }
    }
}

```
PaintbrushHolder.scad:
```
// Brush holder
//
// ===================================================
// This is a remix of the Cubistand Pen Brush Holder Stand
// by sdmc
//
// ===================================================

// preview[view:south, tilt:top]

/* [Parameters] */

// Which part would you like to see?
part = "fullset"; // [base:Base only,top:Top only,rod:Connecting rod,cap: Connecting rod cap, fullset:Full set of parts]

// Paintbrush hole width.
hole_w = 20;

// Paintbrush hole length.
hole_d = 25;

// Wall thickness.
wall_thickness = 3;

// Holder base and top height
holder_h = 30;

//Rod height (excludes the part that goes into the base and top)
rod_h = 100;

// Number of holes width
holes_count_w = 5;

// Number of holes depth
holes_count_d = 6;

// Rounding. This is the rounding at the corners of the base and top.
rounding = 10;

// Bottom Thickness.
bottom_h = 4; //[1,2,3,4,5]

// Rod play. This shrinks the ends of the rod by a smidge so they can be inserted into the printed base and top.
rod_play = 0.05; // [0,0.05, 0.1, 0.2]

// Cap height. Zero means no cap.
cap_h = 12;

/*[Hidden]*/
full_width = holes_count_w * (hole_w + wall_thickness) + wall_thickness;
full_depth = holes_count_d * (hole_d + wall_thickness) + wall_thickness;
$fn = 128;

inner_rounding = rounding - wall_thickness;
if ( inner_rounding < 0 ) {
    inner_rounding = 0;
}

print_part();

module print_part() {
    if (part=="base") {
        part_base();
    }
    else if (part == "top") {
        part_main();
    }
    else if (part == "cap") {
        rotate([0,180,0]) part_cap();
    }
    else if (part == "rod") {
        part_rod();
    }
    else if (part=="fullset") {
        part_fullset();
    }
}

module part_fullset() {
    part_base();
    part_main();
    part_rod();
    translate([0,0,rod_h+30+holder_h*2]) part_cap();
}

module part_cap() {
    if ( cap_h > 0 ) {
         {
            difference() {
                onecorner_rounded_rectangle(hole_w+2*wall_thickness, hole_d+2*wall_thickness, cap_h, rounding);
                translate([wall_thickness,wall_thickness,-1])
                onecorner_rounded_rectangle(hole_w, hole_d, cap_h - wall_thickness+2, inner_rounding);
            }
        }
    }
}

module part_rod() {
    union() {
        translate([0,0,holder_h])
            onecorner_rounded_rectangle(hole_w+2*wall_thickness, hole_d+2*wall_thickness, rod_h, rounding);

        o = sign(cap_h) * (cap_h - wall_thickness);

        translate([wall_thickness+rod_play,wall_thickness+rod_play,rod_play])
            onecorner_rounded_rectangle(hole_w-rod_play*2,
                    hole_d-rod_play*2,
                    rod_h+(2*holder_h)-rod_play*2 + o,
                    inner_rounding);
    }
}

module part_base() {
    union() {
        holed_rectangle();
        translate([0,0,-bottom_h]) {
            rounded_rectangle(bottom_h);
        }
    }
}

module part_main() {
    translate([0,0,rod_h+holder_h]) {
        holed_rectangle();
    }
}

module holed_rectangle() {
    difference() {
        rounded_rectangle(holder_h);
        for( x=[0:holes_count_w-1]) {
             for( y =[0:holes_count_d-1] ) {
                translate(
                    [wall_thickness+ (hole_w + wall_thickness) * x ,
                     wall_thickness+ (hole_d + wall_thickness) * y,
                     -1]) {
                         if ( (x == 0 && y == 0)) {
                             onecorner_rounded_rectangle( hole_w, hole_d, holder_h+2, inner_rounding);
                         }
                         else if ( x==0 && y == (holes_count_d -1)) {
                             rotated_rounded_hole(180, true);
                         }
                         else if ( x== (holes_count_w -1) && y == (holes_count_d -1)) {
                             rotated_rounded_hole(180, false);
                         }
                         else if ( x==(holes_count_w -1) && y == 0) {
                             rotated_rounded_hole(0, true);
                         }
                         else
                         {
                             onecorner_rounded_rectangle( hole_w, hole_d, holder_h+2,0);
                         }
                }
             }
        }
    }
}

module rotated_rounded_hole(deg, which_corner) {
     translate([hole_w/2, hole_d/2,0]) {
         rotate([0,0,deg]) {
             translate([-hole_w/2, -hole_d/2,0]) {
                 if ( !which_corner)
                     onecorner_rounded_rectangle( hole_w, hole_d, holder_h+2, inner_rounding, 0);
                 else
                     onecorner_rounded_rectangle( hole_w, hole_d, holder_h+2, 0, inner_rounding);
             }
         }
    }
}

module onecorner_rounded_rectangle(w, d, h, r, r1) {
    difference() {
        cube([w, d, h], false);
        if ( r > 0 ) {
            round_corner(r,h);
        }
        if ( r1 > 0 ) {
            other_round_corner(r1, w, h);
        }
    }
}

module round_corner(r, h) {
    p=1;
    difference () {
        translate([-p,-p,-p]) {
            cube( [r+p,r+p,h+p*2] , false);
        }
        translate([r, r, -2]) {
            cylinder(h+4,r,r);
        }
    }
}

module other_round_corner(r,w,h) {
    p=1;
    difference () {
        translate([w-r,-p,-p]) {
            cube( [r+p,r+p,h+p*2] , false);
        }
        translate([w-r, r, -2]) {
            cylinder(h+4,r,r);
        }
    }
}

module rounded_rectangle(h) {
    union() {
        translate([0,rounding,0]) {
            cube([full_width,full_depth - (rounding * 2),h], false);
        }
        translate([rounding,0,0]) {
            cube([full_width - (rounding * 2), full_depth ,h], false);
        }
        translate([rounding,rounding,0]) {
            cylinder(h, rounding, rounding);
        }
        translate([full_width - rounding,rounding,0]) {
            cylinder(h, rounding, rounding);
        }
        translate([full_width - rounding,full_depth - rounding,0]) {
            cylinder(h, rounding, rounding);
        }
        translate([rounding,full_depth - rounding,0]) {
            cylinder(h, rounding, rounding);
        }
    }
}

```


[User]
Okay, I need an OpenSCAD design for a picture frame hanger, specifically for those box-framed canvases. The kind where the canvas is mounted in a simple, slightly deeper frame.

The hanger should be a flat piece with teeth on one side that hook over the frame. It will be screwed into the underside of the top frame piece, with the teeth pointing downwards. Here are the parameters I'd like to be able to control:

*   `thickness`: the thickness of the main flat part of the hanger, like, the thickness of the plastic or whatever it's made of.
*   `depth`: how far the main flat part extends out from the teeth side; this needs to be less than the distance between the canvas and the wall.
*   `teeth_height`: how far the teeth stick out from the main part, from the base to the very tip.
*   `number_of_teeth`: how many teeth there are along the hanging edge - I want this to be an even number.
*   `tooth_width`: how wide each individual tooth is.
*   `hole_diameter`: the diameter of the screw holes (there should be two), one on each side, and also a small notch or cut-out in the middle to accommodate the mounting screw for the frame.

The overall width of the design should be calculated from the tooth width, number of teeth, and depth. I don't need to define the width directly; the code should handle that. I also need a small notch in the middle, sort of like a little upside down triangle or 'v' shape, so it can fit over the screw that's often in the middle of the picture frame.

I think that's all I need. Please use OpenSCAD to generate the design. I don't need any external libraries, I just want the basic code in one or more `.scad` files. Thanks!

[Assistant]
box-frame-hanger.scad:
```
//
// Box-framed picture hanging tool
// version 1.0   05/03/2016
// by Matthew Flint (mkflint @ Thingiverse)
//

/* [Main] */
// thickness of the walls
thickness = 2; // [3:8]
// depth; limited by the distance between the canvas and the wall
depth = 10; // [8:20]
// height of the teeth (from the base to the tip of the tooth)
teeth_height = 3; // [2:20]
// number of teeth. Even number!
number_of_teeth = 4; // [2:10]
// width of each tooth
tooth_width = 3; // [2:10]
// diameter of the screw hole
hole_diameter = 4; // [2:10];

/* [Hidden] */
teeth_width = number_of_teeth * tooth_width;
width = teeth_width + (depth * 2);

main();

module main()
{
  render(convexity = 3)
  rotate([0,0,180])
  translate([-width * 0.5, 0, 0])
    union()
    {
      flat_bit();
      teeth();
    }
}

module flat_bit()
{
  difference()
  {
    linear_extrude(thickness)
      flat_bit_shape();
    centre_notch();
  }
}

module flat_bit_shape()
{
  difference()
  {
    square(size=[width,depth]);
    translate([depth*0.5, depth*0.5])
      circle(d=hole_diameter, $fn = 30);
    translate([width - (depth*0.5), depth*0.5])
      circle(d=hole_diameter, $fn = 30);
  }
}

module centre_notch()
{
  translate([width*0.5, 0, 0])
  rotate([-90,0,0])
  linear_extrude(depth)
  {
    rotate([0,0,30])
    circle(d=1, $fn=3);
  }
}

module teeth()
{
  translate([(width-teeth_width)/2,thickness,thickness])
    rotate([90,0,0])
      linear_extrude(thickness)
        teeth_shape();
}

module teeth_shape()
{
  rectangle_height = teeth_height - (tooth_width * cos(60));
  x_offset = (tooth_width * 0.5) + teeth_width - (tooth_width * number_of_teeth);
  y_offset = teeth_height - (tooth_width * cos(60) * 0.5);

  union()
  {
    square(size=[teeth_width,rectangle_height]);
    for (i=[0:number_of_teeth-1]) {
      translate([x_offset + (tooth_width * i), y_offset])
        rotate([0,0,-30])
          circle(d=tooth_width / sin(60), $fn = 3);
    }

  }
}

```
box-frame-hanger.scad:
```
//
// Box-framed picture hanging tool
// version 1.0   05/03/2016
// by Matthew Flint (mkflint @ Thingiverse)
//

/* [Main] */
// thickness of the walls
thickness = 2; // [3:8]
// depth; limited by the distance between the canvas and the wall
depth = 10; // [8:20]
// height of the teeth (from the base to the tip of the tooth)
teeth_height = 3; // [2:20]
// number of teeth. Even number!
number_of_teeth = 4; // [2:10]
// width of each tooth
tooth_width = 3; // [2:10]
// diameter of the screw hole
hole_diameter = 4; // [2:10];

/* [Hidden] */
teeth_width = number_of_teeth * tooth_width;
width = teeth_width + (depth * 2);

main();

module main()
{
  render(convexity = 3)
  rotate([0,0,180])
  translate([-width * 0.5, 0, 0])
    union()
    {
      flat_bit();
      teeth();
    }
}

module flat_bit()
{
  difference()
  {
    linear_extrude(thickness)
      flat_bit_shape();
    centre_notch();
  }
}

module flat_bit_shape()
{
  difference()
  {
    square(size=[width,depth]);
    translate([depth*0.5, depth*0.5])
      circle(d=hole_diameter, $fn = 30);
    translate([width - (depth*0.5), depth*0.5])
      circle(d=hole_diameter, $fn = 30);
  }
}

module centre_notch()
{
  translate([width*0.5, 0, 0])
  rotate([-90,0,0])
  linear_extrude(depth)
  {
    rotate([0,0,30])
    circle(d=1, $fn=3);
  }
}

module teeth()
{
  translate([(width-teeth_width)/2,thickness,thickness])
    rotate([90,0,0])
      linear_extrude(thickness)
        teeth_shape();
}

module teeth_shape()
{
  rectangle_height = teeth_height - (tooth_width * cos(60));
  x_offset = (tooth_width * 0.5) + teeth_width - (tooth_width * number_of_teeth);
  y_offset = teeth_height - (tooth_width * cos(60) * 0.5);

  union()
  {
    square(size=[teeth_width,rectangle_height]);
    for (i=[0:number_of_teeth-1]) {
      translate([x_offset + (tooth_width * i), y_offset])
        rotate([0,0,-30])
          circle(d=tooth_width / sin(60), $fn = 3);
    }

  }
}

```


[User]
Hi, I'm looking to design a caravan bunk bed based on a cot (Feldbett), and I'm hoping you can help me with the OpenSCAD design. I've seen some examples online, but I need something parametric that I can customize.

Essentially, I want to take a standard cot and elevate it within the caravan. The cot will have its middle legs removed, with the whole setup supported by a wooden frame. I would like to be able to adjust the following parameters:

*   **Feldbett (Cot) Dimensions:**
    *   `Feldbett_Laenge`: Length of the cot. (Typically 180-220cm)
    *   `Feldbett_Breite`: Width of the cot. (Typically 50-90cm)
    *   `Feldbett_Hoehe`: Height of the cot. (Typically 30-50cm)
    *   `Feldbett_Rahmen`: Thickness of the cot's frame (Typically 3-8cm)
    *   `Feldbett_B_Abstand`: Distance of cot supports from the side (Typically 1-10cm)
    *   `Feldbett_L_Abstand`: Distance of cot supports from the ends (Typically 1-10cm)

*   **Wooden Support Frame Dimensions:**
    *   `Rahmen_H_Prozent`: Height of the frame base from the bottom of the cot, as a percentage of the cot height. (Typically 10-50%)
    *   `Rahmen_M_Breite`: Width of the wooden beams in the frame (Typically 50-90mm)
    *  `Rahmen_H_Hoehe`: Height of the supporting frame (Typically 50-120mm)

*   **Caravan Dimensions and Placement:**
    *   `WoWa_B_Abstand`: Horizontal offset from the caravan wall to the edge of the cot frame. (Typically 0-50cm)
    *   `WoWa_Hoehe`: Height of the caravan. (Typically 130-190cm)
    *   `WoWa_Laenge`: Length of the caravan. (Typically 180-240cm)
    *   `WoWa_Breite`: Width of the caravan. (Typically 60-140cm)

The design should include:
1.  The cot itself, represented by a box. The frame and the feet should be rendered as separate, colored parts. The cot itself should just be the rectangle that the person would lie on.
2.  A supporting wooden frame underneath the cot with vertical and horizontal supports.
3.  A representation of the caravan walls as a box for reference (this does not need to be detailed).

I'd like the cot in green, the support frame in red, and the caravan in yellow (as shown in the existing code). Also, I'd like the OpenSCAD file(s) to be fully parametric, so I can easily adjust these values and re-render.

I am not requesting any existing libraries be used; that is, all code should be written from first principles.

[Assistant]
Wohnwagen-Hochbett.scad:
```
// Wohnwagen Hochbett aus Feldbett
// http://www.thingiverse.com/thing:1393879

Feldbett_Laenge = 191; // [180:220]
Feldbett_Breite = 72; // [50:90]
Feldbett_Hoehe = 42; // [30:50]
Feldbett_Rahmen = 4; // [3:8]
Feldbett_B_Abstand = 3; // [1:10]
Feldbett_L_Abstand = 6; // [1:10]
Rahmen_H_Prozent = 25; // [10:50]
Rahmen_M_Breite = 30; // [50:90]
Rahmen_H_Hoehe = 75; // [50:120]
WoWa_B_Abstand = 10; // [0:50]
WoWa_Hoehe = 150; // [130:190]
WoWa_Laenge = 198; // [180:240]
WoWa_Breite = 100; // [60:140]

bl=10*Feldbett_Laenge;
bb=10*Feldbett_Breite;
bh=10*Feldbett_Hoehe;
br=10*Feldbett_Rahmen;
ba=10*Feldbett_B_Abstand;
bf=10*Feldbett_L_Abstand;
bd = sqrt(bb*bb+bh*bh); // Fuss
bw = asin((bb)/bd); // Winkel

rf=0.01*Rahmen_H_Prozent;
rl=10*Rahmen_M_Breite;
rh=10*Rahmen_H_Hoehe-bh;
wa=10*WoWa_B_Abstand;
wh=10*WoWa_Hoehe;
wl=10*WoWa_Laenge;
wb=10*WoWa_Breite;

translate([0,0,bh+320+rh+150])
rotate([180,0,0])
wowa_hochbett();

module wowa_hochbett() {
color ("green") bett();
color ("red") gestell();
color ("yellow") wowa();
}

module wowa() {
translate([0,-wa,rh+bh])
cube([wl,wb,150]);
translate([0,-wa,rh+bh])
cube([wl,wb-100,320+150]);
translate([0,0,rh+bh-wh])
cube([wl,wb-250,10]);
}

module gestell() {
// Gestell Mitte
translate([0,(bb-rl)/2,0])
translate([(bl-br)/2,-ba-br/2,bh*rf])
cube([br,rl,br]);
translate([0,(bb)/2-ba-br,bh*rf+br])
cube([bl,br,br]);
// Gestell Unten
translate([bf+br,-ba-br/2,bh])
cube([br,br,rh]);
translate([bf+br,bb-ba-br/2,bh])
cube([br,br,rh]);
translate([bl-bf-br,-ba-br/2,bh])
cube([br,br,rh]);
translate([bl-bf-br,bb-ba-br/2,bh])
cube([br,br,rh]);
// Gestell Querstange
translate([bf+br,-ba-br,bh])
cube([br,bb+ba*2,br]);
translate([bl-bf-br,-ba-br,bh])
cube([br,bb+ba*2,br]);
}

module bett() {
// Liegeflaeche
cube ([bl,bb-2*(br+ba),br/2]);
// Bretter
translate([0,-ba*2,0])
cube ([br,bb,br]);
translate([bl-br,-ba*2,0])
cube ([br,bb,br]);
// Fuesse
translate([bf+br,0,0]) bettfuss();
translate([bl-bf-br,0,0]) bettfuss();
translate([(bl-br)/2,0,0]) bettfuss(0.25);
}

module bettfuss(pl=1) {
// Fuss1
rotate ([-bw,0,0])
translate([0,-ba-br/2,0])
cube([br,br,bd*pl]);
// Fuss2
translate([0,bb-ba*2-br,0])
rotate ([bw,0,0])
cube([br,br,bd*pl]);
}

```


[User]
Hey, I'm looking to generate a parametric model of a square U-bolt and matching nuts in OpenSCAD. I'd like to be able to specify the dimensions in inches and have the model automatically adjust using that input.

Specifically, I need:

*   A square U-bolt with a threaded portion on each leg.
*   Matching nuts for the bolt.
*   All dimensions should be defined in inches.

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

**For the U-bolt:**

*   `thread_diameter`: Bolt diameter (in inches) - this will determine both the bolt's thread diameter and the stock diameter.
*   `TPI`: Threads per inch for the bolt.
*  `inside_length_in`: The inside length of the U (the straight portion from where it starts to curve on one leg to where the curve starts on the other leg) (in inches).
*   `thread_length_in`: The length of the threaded portion on each leg (in inches).
*   `inside_width_in`: The width between the legs of the U-bolt (in inches).

**For the Nuts:**

*   `num_nuts`: The number of nuts to create.

I'd like the nuts to be a standard hex shape, and I'd like the threads to match the bolt exactly.

I'd also like to be able to select whether to generate the U-bolt, the nuts, or both.

I'm aware of Dan Kirshner's threads library, and would prefer you use that for generating the threads, or any other comparable threads library you may be familiar with.

Can you create the necessary OpenSCAD files for this design, including the thread library if necessary? I'm also looking for you to put the thread library code in its own file.

[Assistant]
Square_U_Bolt.scad:
```
//$fn=32;
$fa=6*1;
$fs=0.5*1;
mm_per_in = 25.4*1;

// Which part would you like to create?
part = "U-BOLT"; // [U-BOLT, NUTS, BOTH]

//Bolt diameter (in inches)
thread_diameter = .250;

//Number of threads per linear inch
TPI=20;

/* [U-Bolt] */

//inside length (in inches)
inside_length_in = 2;

//Length of threaded portion of bolt (in inches)
thread_length_in = 1;

//Mouth of u-bolt (in inches)
inside_width_in = 1.375;

/* [Nuts] */

//Number of nuts
num_nuts = 2;

//Create Nuts?
//create_nuts = "YES"; // [YES,NO]

thread_radius = thread_diameter * mm_per_in/2;
//include <threads.scad>
/*
 * ISO-standard metric threads, following this specification:
 *          http://en.wikipedia.org/wiki/ISO_metric_screw_thread
 *
 * Dan Kirshner - dan_kirshner@yahoo.com
 *
 * You are welcome to make free use of this software.  Retention of my
 * authorship credit would be appreciated.
 *
 * Version 1.8.  2016-01-08  Option: (non-standard) angle.
 * Version 1.7.  2015-11-28  Larger x-increment - for small-diameters.
 * Version 1.6.  2015-09-01  Options: square threads, rectangular threads.
 * Version 1.5.  2015-06-12  Options: thread_size, groove.
 * Version 1.4.  2014-10-17  Use "faces" instead of "triangles" for polyhedron
 * Version 1.3.  2013-12-01  Correct loop over turns -- don't have early cut-off
 * Version 1.2.  2012-09-09  Use discrete polyhedra rather than linear_extrude ()
 * Version 1.1.  2012-09-07  Corrected to right-hand threads!
 */

// Examples.
//
// Standard M8 x 1.
// metric_thread (diameter=8, pitch=1, length=4);

// Square thread.
// metric_thread (diameter=8, pitch=1, length=4, square=true);

// Non-standard: long pitch, same thread size.
//metric_thread (diameter=8, pitch=4, length=4, thread_size=1, groove=true);

// Non-standard: 20 mm diameter, long pitch, square "trough" width 3 mm,
// depth 1 mm.
//metric_thread (diameter=20, pitch=8, length=16, square=true, thread_size=6,
//               groove=true, rectangle=0.333);

// English: 1/4 x 20.
//english_thread (diameter=1/4, threads_per_inch=20, length=1);

// Thread for mounting on Rohloff hub.
//difference () {
//   cylinder (r=20, h=10, $fn=100);
//
//   metric_thread (diameter=34, pitch=1, length=10, internal=true, n_starts=6);
//}

// ----------------------------------------------------------------------------
function segments (diameter) = min (50, ceil (diameter*6));

// ----------------------------------------------------------------------------
// internal -    true = clearances for internal thread (e.g., a nut).
//               false = clearances for external thread (e.g., a bolt).
//               (Internal threads should be "cut out" from a solid using
//               difference ()).
// n_starts -    Number of thread starts (e.g., DNA, a "double helix," has
//               n_starts=2).  See wikipedia Screw_thread.
// thread_size - (non-standard) size of a single thread "V" - independent of
//               pitch.  Default: same as pitch.
// groove      - (non-standard) subtract inverted "V" from cylinder (rather than
//               add protruding "V" to cylinder).
// square      - Square threads (per
//               https://en.wikipedia.org/wiki/Square_thread_form).
// rectangle   - (non-standard) "Rectangular" thread - ratio depth/width
//               Default: 1 (square).
// angle       - (non-standard) angle (deg) of thread side from perpendicular to
//               axis (default = standard = 30 degrees).
module metric_thread (diameter=8, pitch=1, length=1, internal=false, n_starts=1,
                      thread_size=-1, groove=false, square=false, rectangle=0,
                      angle=30)
{
   // thread_size: size of thread "V" different than travel per turn (pitch).
   // Default: same as pitch.
   local_thread_size = thread_size == -1 ? pitch : thread_size;
   local_rectangle = rectangle ? rectangle : 1;

   n_segments = segments (diameter);
   h = (square || rectangle) ? local_thread_size*local_rectangle/2 : local_thread_size * cos (angle);

   h_fac1 = (square || rectangle) ? 0.90 : 0.625;

   // External thread includes additional relief.
   h_fac2 = (square || rectangle) ? 0.95 : 5.3/8;

   if (! groove) {
      metric_thread_turns (diameter, pitch, length, internal, n_starts,
                           local_thread_size, groove, square, rectangle, angle);
   }

   difference () {

      // Solid center, including Dmin truncation.
      if (groove) {
         cylinder (r=diameter/2, h=length, $fn=n_segments);
      } else if (internal) {
         cylinder (r=diameter/2 - h*h_fac1, h=length, $fn=n_segments);
      } else {

         // External thread.
         cylinder (r=diameter/2 - h*h_fac2, h=length, $fn=n_segments);
      }

      if (groove) {
         metric_thread_turns (diameter, pitch, length, internal, n_starts,
                              local_thread_size, groove, square, rectangle,
                              angle);
      }
   }
}

// ----------------------------------------------------------------------------
// Input units in inches.
// Note: units of measure in drawing are mm!
module english_thread (diameter=0.25, threads_per_inch=20, length=1,
                      internal=false, n_starts=1, thread_size=-1, groove=false,
                      square=false, rectangle=0)
{
   // Convert to mm.
   mm_diameter = diameter*25.4;
   mm_pitch = (1.0/threads_per_inch)*25.4;
   mm_length = length*25.4;

   echo (str ("mm_diameter: ", mm_diameter));
   echo (str ("mm_pitch: ", mm_pitch));
   echo (str ("mm_length: ", mm_length));
   metric_thread (mm_diameter, mm_pitch, mm_length, internal, n_starts,
                  thread_size, groove, square, rectangle);
}

// ----------------------------------------------------------------------------
module metric_thread_turns (diameter, pitch, length, internal, n_starts,
                            thread_size, groove, square, rectangle, angle)
{
   // Number of turns needed.
   n_turns = floor (length/pitch);

   intersection () {

      // Start one below z = 0.  Gives an extra turn at each end.
      for (i=[-1*n_starts : n_turns+1]) {
         translate ([0, 0, i*pitch]) {
            metric_thread_turn (diameter, pitch, internal, n_starts,
                                thread_size, groove, square, rectangle, angle);
         }
      }

      // Cut to length.
      translate ([0, 0, length/2]) {
         cube ([diameter*3, diameter*3, length], center=true);
      }
   }
}

// ----------------------------------------------------------------------------
module metric_thread_turn (diameter, pitch, internal, n_starts, thread_size,
                           groove, square, rectangle, angle)
{
   n_segments = segments (diameter);
   fraction_circle = 1.0/n_segments;
   for (i=[0 : n_segments-1]) {
      rotate ([0, 0, i*360*fraction_circle]) {
         translate ([0, 0, i*n_starts*pitch*fraction_circle]) {
            thread_polyhedron (diameter/2, pitch, internal, n_starts,
                               thread_size, groove, square, rectangle, angle);
         }
      }
   }
}

// ----------------------------------------------------------------------------
// z (see diagram) as function of current radius.
// (Only good for first half-pitch.)
function z_fct (current_radius, radius, pitch, angle)
   = 0.5* (current_radius - (radius - 0.875*pitch*cos (angle)))
                                                       /cos (angle);

// ----------------------------------------------------------------------------
module thread_polyhedron (radius, pitch, internal, n_starts, thread_size,
                          groove, square, rectangle, angle)
{
   n_segments = segments (radius*2);
   fraction_circle = 1.0/n_segments;

   local_rectangle = rectangle ? rectangle : 1;

   h = (square || rectangle) ? thread_size*local_rectangle/2 : thread_size * cos (angle);
   outer_r = radius + (internal ? h/20 : 0); // Adds internal relief.
   //echo (str ("outer_r: ", outer_r));

   // A little extra on square thread -- make sure overlaps cylinder.
   h_fac1 = (square || rectangle) ? 1.1 : 0.875;
   inner_r = radius - h*h_fac1; // Does NOT do Dmin_truncation - do later with
                                // cylinder.

   translate_y = groove ? outer_r + inner_r : 0;
   reflect_x   = groove ? 1 : 0;

   // Make these just slightly bigger (keep in proportion) so polyhedra will
   // overlap.
   x_incr_outer = (! groove ? outer_r : inner_r) * fraction_circle * 2 * PI * 1.02;
   x_incr_inner = (! groove ? inner_r : outer_r) * fraction_circle * 2 * PI * 1.02;
   z_incr = n_starts * pitch * fraction_circle * 1.005;

   /*
    (angles x0 and x3 inner are actually 60 deg)

                          /\  (x2_inner, z2_inner) [2]
                         /  \
   (x3_inner, z3_inner) /    \
                  [3]   \     \
                        |\     \ (x2_outer, z2_outer) [6]
                        | \    /
                        |  \  /|
             z          |[7]\/ / (x1_outer, z1_outer) [5]
             |          |   | /
             |   x      |   |/
             |  /       |   / (x0_outer, z0_outer) [4]
             | /        |  /     (behind: (x1_inner, z1_inner) [1]
             |/         | /
    y________|          |/
   (r)                  / (x0_inner, z0_inner) [0]

   */

   x1_outer = outer_r * fraction_circle * 2 * PI;

   z0_outer = z_fct (outer_r, radius, thread_size, angle);
   //echo (str ("z0_outer: ", z0_outer));

   //polygon ([[inner_r, 0], [outer_r, z0_outer],
   //        [outer_r, 0.5*pitch], [inner_r, 0.5*pitch]]);
   z1_outer = z0_outer + z_incr;

   // Give internal square threads some clearance in the z direction, too.
   bottom = internal ? 0.235 : 0.25;
   top    = internal ? 0.765 : 0.75;

   translate ([0, translate_y, 0]) {
      mirror ([reflect_x, 0, 0]) {

         if (square || rectangle) {

            // Rule for face ordering: look at polyhedron from outside: points must
            // be in clockwise order.
            polyhedron (
               points = [
                         [-x_incr_inner/2, -inner_r, bottom*thread_size],         // [0]
                         [x_incr_inner/2, -inner_r, bottom*thread_size + z_incr], // [1]
                         [x_incr_inner/2, -inner_r, top*thread_size + z_incr],    // [2]
                         [-x_incr_inner/2, -inner_r, top*thread_size],            // [3]

                         [-x_incr_outer/2, -outer_r, bottom*thread_size],         // [4]
                         [x_incr_outer/2, -outer_r, bottom*thread_size + z_incr], // [5]
                         [x_incr_outer/2, -outer_r, top*thread_size + z_incr],    // [6]
                         [-x_incr_outer/2, -outer_r, top*thread_size]             // [7]
                        ],

               faces = [
                         [0, 3, 7, 4],  // This-side trapezoid

                         [1, 5, 6, 2],  // Back-side trapezoid

                         [0, 1, 2, 3],  // Inner rectangle

                         [4, 7, 6, 5],  // Outer rectangle

                         // These are not planar, so do with separate triangles.
                         [7, 2, 6],     // Upper rectangle, bottom
                         [7, 3, 2],     // Upper rectangle, top

                         [0, 5, 1],     // Lower rectangle, bottom
                         [0, 4, 5]      // Lower rectangle, top
                        ]
            );
         } else {

            // Rule for face ordering: look at polyhedron from outside: points must
            // be in clockwise order.
            polyhedron (
               points = [
                         [-x_incr_inner/2, -inner_r, 0],                        // [0]
                         [x_incr_inner/2, -inner_r, z_incr],                    // [1]
                         [x_incr_inner/2, -inner_r, thread_size + z_incr],      // [2]
                         [-x_incr_inner/2, -inner_r, thread_size],              // [3]

                         [-x_incr_outer/2, -outer_r, z0_outer],                 // [4]
                         [x_incr_outer/2, -outer_r, z0_outer + z_incr],         // [5]
                         [x_incr_outer/2, -outer_r, thread_size - z0_outer + z_incr], // [6]
                         [-x_incr_outer/2, -outer_r, thread_size - z0_outer]    // [7]
                        ],

               faces = [
                         [0, 3, 7, 4],  // This-side trapezoid

                         [1, 5, 6, 2],  // Back-side trapezoid

                         [0, 1, 2, 3],  // Inner rectangle

                         [4, 7, 6, 5],  // Outer rectangle

                         // These are not planar, so do with separate triangles.
                         [7, 2, 6],     // Upper rectangle, bottom
                         [7, 3, 2],     // Upper rectangle, top

                         [0, 5, 1],     // Lower rectangle, bottom
                         [0, 4, 5]      // Lower rectangle, top
                        ]
            );
         }
      }
   }
}

if ((part == "U-BOLT") || (part == "BOTH"))
{
    union()
    {
    cube([inside_width_in*mm_per_in+(2*thread_diameter*mm_per_in),thread_diameter*mm_per_in,thread_diameter*mm_per_in]);
    translate([thread_radius,thread_radius,(thread_diameter)*mm_per_in])
        cylinder(h=(inside_length_in-thread_length_in)*mm_per_in, r1=thread_radius, r2=thread_radius);
    translate([3*thread_radius+inside_width_in*mm_per_in,thread_radius,(thread_diameter)*mm_per_in])
        cylinder(h=(inside_length_in-thread_length_in)*mm_per_in, r1=thread_radius, r2=thread_radius);
    translate([thread_radius,thread_radius,(thread_diameter+inside_length_in-thread_length_in)*mm_per_in])
        english_thread(thread_diameter, TPI, thread_length_in);
    translate([3*thread_radius+inside_width_in*mm_per_in,thread_radius,(thread_diameter+inside_length_in-thread_length_in)*mm_per_in])
        english_thread(thread_diameter, TPI, thread_length_in);
    }
}
if ((part == "NUTS") || (part == "BOTH"))
{
    for(a=[0:1:num_nuts-1])
    {
        // Generate Hex Nut
        translate([3*thread_diameter*mm_per_in*a+(thread_diameter*mm_per_in), 3*thread_diameter*mm_per_in, 0])
        difference()
        {
            translate ([0,0,thread_diameter*mm_per_in/2])
            union()
            {
                cube([thread_diameter*mm_per_in/(sin(60)), 2*thread_diameter*mm_per_in, thread_diameter*mm_per_in], center=true);
                rotate([0,0,60])cube([thread_diameter*mm_per_in/(sin(60)), 2*thread_diameter*mm_per_in, thread_diameter*mm_per_in], center=true);
                rotate([0,0,-60])cube([thread_diameter*mm_per_in/(sin(60)), 2*thread_diameter*mm_per_in, thread_diameter*mm_per_in], center=true);
            }
            translate([0, 0, -1]) english_thread(    thread_diameter, TPI, thread_diameter+.1, true);
        }
        /*  Commented out Square Nut
        translate([3*thread_diameter*mm_per_in*a, 2*thread_diameter*mm_per_in, 0])
        difference()
        {
            cube([2*thread_diameter*mm_per_in, 2*thread_diameter*mm_per_in, thread_diameter*mm_per_in]);

            translate([thread_diameter*mm_per_in, thread_diameter*mm_per_in, -1]) english_thread(    thread_diameter, TPI, thread_diameter+.1, true);
        }
        */
    }
}

```


[User]
Hey, I'm looking to create a customizable handle that can fit either a bolt or a nut, and I want to be able to adjust all the important dimensions. I've got some basic ideas, but I need it to be parametric in OpenSCAD.

Essentially, I need a handle with a cylindrical base that can be adjusted in diameter to fit a bolt or nut. The handle should have a rectangular grip portion and a rounded end that connects to the base. The base should have a tolerance for 3D printing purposes. I also need it to be able to accommodate a hex nut or bolt head, so I need to have a way to specify the hex diameter and thickness. I want to make this parametric so I can easily adjust the dimensions for different sized bolts or nuts.

Here are the key parameters I want to control:

*   **`dia`:** The diameter of the circular base where the bolt/nut sits. This is basically the size of the fitting hole that needs to accommodate the nut/bolt. It should be big enough to fit the hex head.
*   **`hex`:** The circumscribed diameter of the hex head (or nut).
*   **`head`:** The thickness of the hex head (or nut).
*   **`bolt`:** The diameter of the bolt itself (used for creating the tolerance hole).
*  **`thread`**: The depth of the non-hex portion of the fitting.
*   **`handleW`:** The width of the rectangular handle grip.
*   **`handleL`:** The length of the rectangular handle grip (not including the round part of the cylinder).
*   **`res`:** The resolution for the rounded parts of the cylinder (for smooth edges).

The base should have two diameters. One diameter (`dia`) should be big enough for the hex, and the second diameter (`boltTol`) should be a smaller hole for the bolt, with a tolerance added for 3D printing to make sure the bolt fits well. Also, there should be a hex-shaped depression for the hex nut/head that is just a bit deeper than `head`. The total height should be the sum of `head` and `thread`, where `head` is the depth of the hex and `thread` is the depth of the rest of the recess. The handle should be centered on the base with half of the cylinder and half the grip on the opposite side of the center from the hex recess.

Could you create a parametric OpenSCAD file that allows me to adjust these parameters? Also, can we make use of the `fastener` module from the BOLTS library and its `nut()` and `bolt()` functions for the hex nut and bolt head, so we can easily switch between bolts and nuts and keep up with standards? Assume it is already installed.

Thanks!

[Assistant]
bolt_handles.scad:
```
dia=24; //diameter of object (min=hex)

hex=14.5; //circumscribed diameter of hexagon
head=5.5; //thickness of hex head/nut

bolt=8; //diameter of bolt
thread=5.5; //thickness around threads

res=60; //round resolutions

handleW=8; //width of handle (min=bolt)
handleL=40; //length of handle minus the round

//Calc
height=head+thread; //total height
boltTol=(.5+bolt); //3D printing tolerance

union(){
        translate ([-handleW/2,(dia/2-2),0])
        cube([handleW,handleL+2,height], false);
        translate ([0, handleL+dia/2, 0])
        cylinder (height, d=handleW, $fn=res);
difference(){
difference(){
  cylinder (height, d=dia, $fn=res);
  cylinder (height, d=boltTol, $fn=res);
}
translate ([0,0,thread]) cylinder (head,d=hex, $fn=6);
}
}

```


[User]
I'm looking to create a 3D model of a foot-like structure, which I'm calling "vulcanus". It's going to have a few different elements, which I'd like to define parametrically if possible.

First, there's a main body component, I'll call it `parte_principale`. This should consist of a "cubo" shape which is like a bent rectangular prism. Imagine a normal cube, then another prism is attached on the side and then a third is attached on the side of the first one which is rotated 90deg along the x axis. The first and second of these prisms can all be varied using their x, y, and z lengths. The "cubo" also has a "cubetto" shape within it, consisting of two intersecting small prisms. The "cubetto" prisms should also have parametric x, y, and z lengths. Finally this part includes a cylinder that is placed at a distance along the x axis from the combined cubo and cubetto, which should also have variable height and radius.

Then, there are some cylindrical screw-like components, called "viti". I need two of these to be placed on one side of `parte_principale`, and two more on the other side, all a set distance from the edge. The "viti" themselves will have two stacked cylinders with variable dimensions (height and diameter). These will be created using two modules called vite and vite_destra so that they can be placed in the correct direction and positions respectively.

Finally, I'd like to subtract the screw components from the main body. So the final part of this `difference()` of the main body and screw components.

I think I'd like to have all of the dimensions for every primitive be adjustable, so all of this would be parametric, not just the screw positioning. I'm not really sure on good default dimensions but they are not really critical at the moment.

Could you generate the OpenSCAD code for this, making sure all the dimensions are exposed as parameters? I don't have any preference on units or other details, but I'd like it to be well-structured with comments if that's not too much to ask! I'm looking for one file. Thanks!

[Assistant]
piede_vulcanus3.scad:
```

module cubo() {
    union() {
union() {
cube([30,20,15]);

translate([20,0,15])
rotate([0,90,0])

cube([10,20,50]);
}
translate([0,0,0])
rotate([90,0,0])
cube([20,15,50]);
}
}

 module cubetto() {
     union() {
   translate([15,7,17])
rotate([0,90,0])

cube([10,6,55]);

 translate([7,5,7])
rotate([90,0,0])
cube([6,10,55]);
     }

 }

  module vite() {
 translate([10,-30,4])
 cylinder(h=30, d=5.5);
  translate([10,-30,-1])
 cylinder(h=7, d=9);

 }

   module vite_destra() {

 translate([-30,10,4])
 cylinder(h=30, d=5.5);
  translate([-30,10,-1])
 cylinder(h=7, d=9);

 }

 module parte_principale() {

     union() {
  union () {
cubo();

cubetto();
  }
   translate([20,0,0])
 cylinder(h=7, r=55);
  }
 }

 module viti_pezzo() {
 translate([0,20,0])
 vite();

 translate([0,-10,0])
 vite();

  translate([60,0,0])
 vite_destra();

translate([90,0,0])
 vite_destra();
 }

 difference() {

   parte_principale();
      viti_pezzo();
 }

```


[User]
Hey! I'm looking for a parametric stand for my Gunpla models, specifically something like the one I've attached. It's designed for a Gundam, like the RG114 Aile Strike, but I want to be able to adjust it for different models.

Here's what I'd like it to do:

*   **Adjustable Height:** The stand should have an adjustable height (I've given a range from 40-150mm but anything close to that is fine).
*   **Adjustable Diameter:** The base diameter needs to be adjustable too (from around 50mm to 100mm, like in the sample).
*   **Mount Options:** I'd like to be able to choose between a cylindrical mount or a prism (square with rounded edges) mount.
*   **Customizable Dimensions:** Other important dimensions are:
    *   Base Height: The height of the base cylinder (5mm is a good starting point)
    *   Mount Height: The height of the mount piece (around 4.5mm)
    *   Cylinder Mount Diameter: The diameter of the cylinder mount piece (around 3mm)
    *   Prism Width: The width of the prism mount (4.5mm or so)
    *   Prism Edge Radius: The radius of the rounded edges on the prism (1mm)
    *   Corner Radius: The radius of the curved transition at the bottom of the base (1.5mm)
    *   Pole Base Diameter: The diameter at the bottom of the pole (about 18mm)
    *   Pole Middle Diameter: The diameter in the middle of the pole (around 10mm)
    *   Pole Top Diameter: The diameter at the top of the pole (around 5mm)
    *   Pole Middle Height: The length of the widest part of the pole (about 10mm)
    *   Transition Height: The length of the transition between the pole and the mount (around 10mm)

I'd like it to use a variable called `fn` for resolution.  The sample uses 40, but I think this should be configurable by the user as a hidden parameter (so no slider for it).

The code I've got uses hull() and sphere(), I think that's a good way to get the rounded edges for the prism. If you've got a better way I'm happy to see it, though.

Could you generate the OpenSCAD code for this? I don't really need any external libraries, just the standard features of OpenSCAD.

[Assistant]
GunStand.scad:
```
// GuSty Gundam Stand by skytale

/* [Gundam Gunpla Stand] */
// Height:
height = 65; // [40:150]
// Diameter:
diameter = 60; // [50:100]
// Mount type:
mount = 2; // [1:cylinder, 2:prism]

/* [Misc Parameters] */
baseHeight = 5;
mountHeight = 4.5;
cylinderDiameter = 3;

prismWidth = 4.5;
prismEdgeRadius = 1;

cornerRadius = 1.5;

poleBaseDiameter = 18;
poleMiddleDiameter = 10;
poleTopDiameter = 5;
poleMiddleHeight = 10;

transitionHeight = 10;

/* [Hidden] */
fn = 40;

base();
translate([0,0,baseHeight]) pole();
if(mount == 1) translate([0,0,baseHeight + height - transitionHeight]) cylinderMount();
if(mount == 2) translate([0,0,baseHeight + height - transitionHeight]) prismMount();

module base() {
	cylinder(baseHeight - cornerRadius,diameter/2,diameter/2,$fn = fn);
	cylinder(baseHeight, diameter/2-cornerRadius, diameter/2-cornerRadius,$fn = fn);
	translate([0,0,baseHeight-cornerRadius]) rotate_extrude(convexity = 10) translate([diameter/2 - cornerRadius, 0, 0]) circle(r = cornerRadius, $fn = 100);
}

module pole() {
	cylinder(poleMiddleHeight,poleBaseDiameter/2,poleMiddleDiameter/2,$fn = fn);
	translate([0,0,poleMiddleHeight]) cylinder(height-poleMiddleHeight-transitionHeight, poleMiddleDiameter/2, poleTopDiameter/2, $fn = fn);
}

module cylinderMount() {
	cylinder(transitionHeight, poleTopDiameter/2, cylinderDiameter/2, $fn = fn);
	translate([0,0,transitionHeight]) cylinder(mountHeight, cylinderDiameter/2, cylinderDiameter/2, $fn = fn);
}

module prismMount() {
	translate([0,0,transitionHeight]) hull() {
		translate([0,0,(mountHeight-prismEdgeRadius)/2]) cube([prismWidth, prismWidth, mountHeight - prismEdgeRadius], center=true);
		translate([-prismWidth/2 + prismEdgeRadius, +prismWidth/2 - prismEdgeRadius, mountHeight-prismEdgeRadius]) sphere(prismEdgeRadius, $fn = fn);
		translate([+prismWidth/2 - prismEdgeRadius, +prismWidth/2 - prismEdgeRadius, mountHeight-prismEdgeRadius]) sphere(prismEdgeRadius, $fn = fn);
		translate([+prismWidth/2 - prismEdgeRadius, -prismWidth/2 + prismEdgeRadius, mountHeight-prismEdgeRadius]) sphere(prismEdgeRadius, $fn = fn);
		translate([-prismWidth/2 + prismEdgeRadius, -prismWidth/2 + prismEdgeRadius, mountHeight-prismEdgeRadius]) sphere(prismEdgeRadius, $fn = fn);
		translate([0,0,-transitionHeight]) cylinder(transitionHeight, poleTopDiameter/2, poleTopDiameter/2, $fn = fn);
	}

}
```


[User]
Hey, I'm looking for an OpenSCAD script to generate a box, basically a hollow rectangular prism. I'd like to control the overall length, width, and height of the box, as well as the thickness of the walls and the thickness of the bottom separately. The box should be centered on the origin, and the inside should match the outer dimensions minus the wall thickness on all sides, and the bottom thickness only on the bottom. I'm envisioning parameters for:

*   `length` (overall length of the box)
*   `width` (overall width of the box)
*   `height` (overall height of the box)
*   `wall_thickness` (thickness of the walls)
*    `bottom_thickness` (thickness of the box's bottom)

Could you generate that for me? I don't need any fancy features, just a basic box generator with these parameters.

[Assistant]
box_gen.scad:
```
lenght=100;//[20:5:200]
width=50;//[20:5:200]
hight=80;//[20:5:200]
thikness=1;//[0.1:0.1:3]
bottom=1;//[0.1:0.1:3]

difference(){
cube([lenght,width,hight],center=true);
translate(v=[0,0,bottom])
cube([lenght-thikness*2,width-thikness*2,hight-bottom],center=true);}
```