[User]
I need a parametric OpenSCAD design for a childproof cabinet lock. This lock is designed to secure two cabinet doors that open away from each other, using their existing knobs as part of the locking mechanism.

The lock should consist of a main bar that connects to both knobs and a release mechanism. Here's a breakdown of the requirements:

**Core Components and Parameters:**

1.  **Main Bar:**
    *   The main bar should be a flat, rectangular piece that spans between the two knobs.
    *   The width of the bar needs to be parametric, specified by a `between_centers` variable. This represents the distance between the centers of the two cabinet knobs.
    *   The thickness of the bar also needs to be parametric, specified by a `thickness` variable, to control its flexibility and security.
    *   The bar needs to have circular cutouts for each knob’s spindle/post. The diameter of these cutouts should be controlled by a `spindle_diameter` variable.
    *   The cutouts should be designed to grip the knob spindles. This gripping mechanism should be adjustable via a `fixed_side_tightness` parameter. A value of 1 would imply a perfect fit, 0 a large gap, and a value around 0.8 might be suitable for PLA.
    *   The depth of the entire lock will be specified by a `depth` variable, but I want it to be consistent across the whole model so I don't need to specify it in the individual modules.

2.  **Release Mechanism:**
    *   The release mechanism should be located at one end of the bar (let's say the right side of the bar in an x-positive direction) and will require a more involved shape than the main bar.
    *   It should consist of an angled arc that follows the circumference of one of the circular cutouts.
    *   This arc should have a `thumb_r` radius parameter controlling the radius of the overall shape.
    *   The arc is followed by a smaller arc whose angle is controlled by a `thumb_angle2` variable. This second arc should be attached to a small cylinder with a radius equal to the `thickness` and with the same depth as the lock.
    *   A `thumb_angle` variable will control how much the arc rotates from a vertical line.

**Additional Notes:**

*   I need this to be fully parametric so I can easily adjust it to fit different cabinet setups.
*   I'm thinking it might be useful to preview this by tilting to the top in the preview window, so including that might be helpful.
*   The design should be relatively simple to print and install.
*   No extra libraries are required.

I think that's it. I'm looking forward to seeing what you come up with!

[Assistant]
cabinet_lock.scad:
```
// What is the diameter of your knob spindle? (mm) This means, what is the radius of the approximately cylindrical post that connects the larger knob to the cabinet?
spindle_diameter = 8.7;

// What is the distance between centers of your two knobs? (mm)
between_centers = 57;

// What is the desired thickness of the piece? (mm) This significantly affects the flexiblity of the piece so a thicker piece will make it harder to release and certainly more secure, more baby-proof. If you think it's too hard to release, make it thinner.
thickness = 2; //[1:0.2:4]

// What is the desired depth of the extrusion? (mm) You will need to tilt the preview to see the effect of this parameter.
depth = 6;

/* [Advanced] */

// Coefficient between 0.65 and 0.9 to define how tightly the fixed side of the lock holds onto the knob. Lower numbers mean it's more tightly held on there but may mean it's difficult to get it on there in the first place. I've found that about 0.8 is good with PLA.
fixed_side_tightness = 0.8;

// Radius of the release part (mm)
thumb_r = 16;

// Angle #1 to fine tune the geometry and "tightness" of the release (degrees)
thumb_angle = 135; //[100:2:150]

// Angle #2 to fine tune the geometry and "tightness" of the release (degrees)
thumb_angle2 = 60; //[30:2:100]

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

linear_extrude(depth) {
    translate([-0.001,0,0]) square([between_centers+0.002,thickness]); //.001 and .002 are to ensure intersection
    translate([0,-spindle_diameter/2]) difference() {
        circle(r=spindle_diameter/2+thickness,$fs=1);
        translate([0,0]) circle(r=spindle_diameter/2,$fs=1);

        cutout_height = spindle_diameter*fixed_side_tightness;

        translate([0,(spindle_diameter/2)-cutout_height]) square([spindle_diameter+thickness,cutout_height]);
    }
}

translate([between_centers,-spindle_diameter/2,0]) rotate([0,0,-thumb_angle+90]) {
    mirror([1,1,0]) arc(thickness,depth,spindle_diameter/2+thickness,thumb_angle);

    translate([thumb_r+spindle_diameter/2,0,0]) mirror([0,1,0]) mirror([1,0,0]) mirror([1,1,0]) {

        arc(thickness,depth,thumb_r,thumb_angle2);
        rotate([0,0,-thumb_angle2]) translate([0,-thumb_r+thickness/2,0]) cylinder(h=depth,d=thickness,$fs=0.5);

    }
}

module arc( height, depth, radius, degrees ) {
    // This dies a horible death if it's not rendered here
    // -- sucks up all memory and spins out of control
    render() {
        difference() {
            // Outer ring
            rotate_extrude($fn = 100)
                translate([radius - height, 0, 0])
                    square([height,depth]);

            // Cut half off
            translate([0,-(radius+1),-.5])
                cube ([radius+1,(radius+1)*2,depth+1]);

            // Cover the other half as necessary
            rotate([0,0,180-degrees])
            translate([0,-(radius+1),-.5])
                cube ([radius+1,(radius+1)*2,depth+1]);

        }
    }
}
```


[User]
I'd like to design a parametric wall-mounted planter for small succulents, and I'm thinking a triangular shape would be cool. The basic idea is a triangular prism with a hollowed-out interior to hold the soil. I need to be able to control the width, height, and depth of the planter, as well as the wall thickness.

I want to also have the option to include a nail mount on the back for easy hanging. The nail mount should be a couple of overlapping cylinders that are offset a bit to create a stronger mount. I need to be able to switch the nail mount on or off as a boolean option. I'm imagining the nail mount to be something that is printed as part of the vase itself (not a separate piece).

Here are the main parameters I need to adjust:

*   **width**: The overall width of the planter at its widest point.
*   **height**: The overall height of the planter.
*   **depth**: The depth of the planter.
*   **thickness**: The thickness of the planter walls.
*   **with_nailmount**: A boolean to include or exclude a nail mount.

I'd also like the code to be set up to print the planter so that no rotation is necessary after slicing. I'd like a custom module for each of the planter options: `vase` and `vase_with_nailmount` so that it's easy to adjust later. I will be using OpenSCAD to print, so I'd like the design in .scad format. Please do not use any external libraries.

[Assistant]
corner.scad:
```
$fn=30 * 1;

width=80;    // [25:200]
height=70;   // [25:200]
depth=40;    // [5:200]
thickness=2; // [0.5:5]
with_nailmount="no"; // [yes,no]

module poly(x1, x2, x3, y1, y2, z1, z2) {
    polyhedron(
        points=[
            [x1, y1, z1],  // 0
            [x2, y1, z2],  // 1
            [x3, y1, z2],  // 2
            [x1, y2, z2]], // 3
        faces=[[3, 0, 1],
               [3, 1, 2],
               [2, 0, 3],
               [1, 2, 3],
               [1, 0, 2]]);
}

module nailmount(d) {
    ot = d - .3;
    it = d - ot;
    rotate([90, 270, 0]) {
        // Outside (uneven circles)
       hull() {
            translate([d, 0, 0]) cylinder(h=d, r=2.5);
            translate([3 + d, 0, 0]) cylinder(h=d, r=1.5);
        }
        // Inside bits (even circles)
        hull() {
            translate([d, 0, 0]) cylinder(h=ot, r=2.5);
            translate([3 + d, 0]) cylinder(h=ot, r=2.5);
        }
    }
}

module vase(w, h, d, t) {
    ih = (d - (2*t)) / (d/h);
    iw = (d - (2*t)) / (d / (w/2));
    rotate([90, 0, 0]) {
        difference() {
            poly(0, w/2, -w/2, 0, d, 0, h);
            poly(0, iw-t, -iw+t, t, d-(2*t), h-ih, h+.1);
        }
    }
}

module vase_with_nailmount(w, h, d, t) {
    difference() {
        vase(w, h, d, t);
        translate([0, t-.20001, h*.75]) nailmount(t-.2);
    }
}

if (with_nailmount == "yes") {
    vase_with_nailmount(width, h=height, d=depth, t=thickness);
} else {
    vase(width, h=height, d=depth, t=thickness);
}

```


[User]
I'd like to create a parametric lid for a cylindrical container, designed to be printed using a spiralized outer contour. I've been experimenting with a basic design, but I'd really appreciate it if you could make it more flexible and easier to customize for different container sizes.

My current design is based on a cylinder with a small cone shape subtracted from one end. Here are the core parameters I'm using currently:

*   **cylinder_diameter**: This is the diameter of the main cylinder. Currently it's set to 33.8mm.
*   **cylinder_height**: The height of the main cylinder, currently 88mm.
*   **cone_base**:  The diameter of the base of the cone that is subtracted. Currently 4mm.
*   **cone_tip**: The diameter of the tip of the cone. Currently 1.25mm.
*   **cone_height**: The height of the cone. Currently 2mm.

I'd like the code to be parametric so I can adjust these easily. And, since I'm likely going to be using this with a set of containers I'm also designing, I'd like the ability to easily add a small clearance to the cylinder diameter. Ideally, I would also like the option to have a completely flat top on the cylinder instead of subtracting the cone, in case I just want a plain lid. Finally, it would be useful to be able to control the `$fn` value to manage the cylinder and cone smoothness, I usually use `$fn=200` for best results. I would like to keep this number configurable.

Could you create an OpenSCAD file that incorporates all these elements? I don't have any specific needs regarding external libraries.

[Assistant]
giftbox-lid-solid.scad:
```
//These measurements work well on my machine for PETG at 100% scale and 101% flow and PLA at 104% scale and 99% flow.
cylinder_diameter=33.8;
cylinder_height=88;
cone_base=4;
cone_tip=1.25;
cone_height=2;
$fn=200;

difference(){
cylinder(d=cylinder_diameter,h=cylinder_height);
translate([0,cylinder_diameter/2,cylinder_height-cone_base/2-1.5])
rotate([90,0,0]){
cylinder(d1=cone_base,d2=cone_tip,h=cone_height);
}
}
```


[User]
I want to design a customizable maze box, building off of some existing ideas. I'm picturing a cylindrical container with a maze cut into the exterior, like a puzzle box where you have to navigate a small object (maybe a ball bearing) through the maze to open it.

I'd like to be able to control the following:

*   **Overall Dimensions:** The diameter and height of the main cylinder. Also, the thickness of the "cap" at the top and the thickness of the walls between the maze channels. And how deep to cut into the cylinder when creating the maze.
*   **Maze Details:**
    *   The number of "sectors" the cylinder is divided into. This dictates how granular the maze can be around the circumference.
    *   The height of the narrow bottom and wider top of each channel.
    *   Beveled edges on the channels. These will need extra width so that the channels match up correctly.
    *   A small locking nub at the base of the cylinder. This helps the top stay on firmly. I need to specify the diameter of that nub and its offset from the main body
    *   The maze itself is defined as a 2D array of strings (like the example).  I want to control the number of rows as well as the character representation of walls vs. paths
*   **Channel Shape:** Instead of just rectangular cuts, I'd like the channels to have a trapezoidal cross-section, with the narrower part at the base of the cut and the wider part at the surface. This will make it easier to print. The trapezoid is what is rotated about an axis to make the channel cuts.

I need these parameters to be adjustable in the code. It's important that the design is fully parametric so the dimensions and maze layout can be easily modified, and it is created from scratch and doesn't try to modify the code I provided, which is only for reference.  I will need it to output a single .scad file, not a set of .scad files, that defines the entire object.

Also, the "spiralize the outer contour" option in Cura is very useful, so I'd like the main body to be a solid cylinder. That is, I need there to be a cylindrical base object before any features are cut into it.

I think I need the following modules/functions:

*   **pie(r, f, s, h)**: To create a pie section for the edges of the maze.
*   **trapz(r1, r2, h1, h2, off)**: To make the trapezoid shapes for channels
*   **owedge(r1, r2, h1, h2)**: To make a rotated trapezoid, like a wedge with angled sides.
*   **polar(x,y, off)**: To position maze elements around the cylinder.
*  **beam(l=1)** : To create a segment of a vertical channel based on how long a sequence of maze spaces is at a given X and Y.
*   **wedge(l, xtra=10)** : To create segments of a horizontal channel based on the length of spaces along a single row in the maze.
*   **xlen2(row, x)** : To calculate the length of a continuous open horizontal space in a given row.
*   **xlen(row, x)** : To return 0 if a character is not the space character or if that character is at the end of the line (or if it is next to another wall character, or is next to another space character); otherwise it returns the result of xlen2().
*  **ylen2(m, x, y)** : To calculate the length of a continuous open vertical space at position X,Y in the given maze
*   **ylen(m, x, y)** : To return 0 if a character is not the space character or if that character is at the end of the line (or if it is next to another wall character, or is next to another space character); otherwise it returns the result of ylen2().

I will define the 2D array that represents the maze myself.

[Assistant]
lmaze06b-solid.scad:
```

/**
 *	A maze-box based off Sneakypoo's fantastic Labyrinth Gift Box at
 *	http://www.thingiverse.com/thing:201097
 *
 * A little editing in blender made a 'key blank' that I could
 *	subtract from in openscad, and a bunch more programming
 *	let it take a maze described in an array.
 *
 * So instead of making a maze with a lot of tedious hand-editing
 * of 3d objects, you can make a maze with a lot of tedious
 *	hand-editing of openscad data :D
 */
cylinder(d=25,h=82.65);
rows=20;
sectors=32; 	// How many sectors do we divide a circle into

bolt_r=30.75/2;	// radius of the unchiselled bolt
cap_h=15;	// Thickness of the 'cap' on the end
wall=2.5;	// thickness of vertical walls between maze channels
depth=2;		// how deep to cut into the bolt
w1=1;			// The narrow bottom of the channels
w2=5;			// The wider tops
//aoff=-33;	// Adjust this to line the maze up with the hexagon

arcw=360/(sectors);		// How many degrees per sector
aslop=18;// Bevelled edges mean we need them extra-wide for the channels to match
va=18;
nubd=2;	// Diameter of the locking nub

// 1 = left of dot, -1 = right of dot
drift=1;
col=15.25;
aoff=(8-col)*arcw;
//aoff=-33;
m=[
   "############################# ##",
   "  #             #       #        ",
   "# # ######### ### ##### # ### ##",
   "# # #       #     #   #     #   ",
   "  # # ##### ####### # ########   ",
   "#   #   # #   #   # #       #   ",
   "# ### # # ### # # # ####### # ##",
   "#   # # #     # # # #   # # #   ",
   "### ### # ####### # # # # # ### ",
   "# #   # # #       #   # # #     ",
   "# ### # # # ### ####### # ##### ",
   "# #     #   #   #       #     # ",
   "# # ####### ##### ####### ##### ",
   "#   #   #   #     #       #     ",
   "##### ### ### ##### ##### # ####",
   "#     # # # # #     # #   # #   ",
   "# ##### # # # # ##### # ### # # ",
   "#     #     # #   #   #     # # ",
   "##### ####### ### ### ######### ",
   "#             #                 ",
// "################################",
];

aoff_old=(360/sectors)*6;
m_old=[
	"################### ############",
	"# ###   # #   #       #   #   # ",
	"# ### ### # ### # ### ### # # # ",
	"#             # #   #     # # # ",
	"##### ########### ### ### # # # ",
	"###     #   # # #   #     #     ",
	"# ####### ### # # ### # # ### ##",
	"#   #   #   # #   # # # # # # ##",
	"# ######### # ### # ### ### ####",
	"  #   ###   #     #       # #    ", // connects around to left side
	"# ### ### ##### ####### ### # # ",
	"# # # ### #   # #   #   #   # # ",
	"# # # ##### ##### ##### # ### ##",
	"#   #     #         #       # # ",
	"# ######### ####### ### ### # # ",
	"      ###   #     # # # ### # #  ", // Connects around to other side
	"# ########### # # ### # ##### # ",
	"#             # #   #     ### # ",
	"# ### # ### ####### # # ##### ##",
	"    # # #     #       #   #    #",
//	"################################",
];

function xlen2(row, x)=(row[x]==" ")?1+xlen2(row,x+1) : 0;
function xlen(row,x)=	(
			(row[x] != " ")
			|| (x >= (len(row)-1))
			|| (( x < (len(row)-1)) && (row[x+1] != " "))
			|| ((x>0) && (row[x-1]==" "))
	) ? 0 : xlen2(row,x);

function ylen2(m, x, y)=(m[y][x]==" ")?1+ylen2(m,x,y+1) : 0;
function ylen(m, x, y)=(
			(m[y][x] != " ")
			|| (y >= (len(m)-1))
			|| (( y < (len(m)-1)) && (m[y+1][x] != " "))
			|| ((y>0) && (m[y-1][x]==" "))
	) ? 0 : ylen2(m,x,y);

// An ungraceful but functional way to make a pie-section.
module pie(r=10, f=270, s=0, h=1) {
	d=f-s;
	intersection() {
//	cylinder(r=r, h=h);
	translate([0,0,-1]) linear_extrude(h+2)	polygon([
			[0,0],
			[2*r*sin(s+d*(0/4)), 2*r*cos(s+d*(0/4))],
			[2*r*sin(s+d*(1/4)), 2*r*cos(s+d*(1/4))],
			[2*r*sin(s+d*(2/4)), 2*r*cos(s+d*(2/4))],
			[2*r*sin(s+d*(3/4)), 2*r*cos(s+d*(3/4))],
			[2*r*sin(s+d*(4/4)), 2*r*cos(s+d*(4/4))],
		]);
	}
}

module trapz(r1=bolt_r-depth, r2=bolt_r, h1=w1, h2=w2, off=bolt_r-depth) assign(d=(r2-r1)) {
			translate([off,0]) polygon(points=[	[0, -h1/2],
							[0, h1/2],
							[d, h2/2],
							[d, -h2/2] ]);
}

/**
 *	Spinning a trapezoid in cross-section to get a less-square
 *	channel shape.
 */
module owedge(r1=bolt_r-depth, r2=bolt_r, h1=w1, h2=w2)
	assign(off=h2-h1) {
		translate([0,0,h2/2]) rotate_extrude() trapz();
//			polygon(points=[	[r1, -h1/2],
//							[r1, h1/2],
//							[r2, h2/2],
//							[r2, -h2/2] ]);
}

/**
 *	The little nub at the bottom to make the bolt 'snap' shut
 *	on the case.
 */
rotate(drift * [0,0,arcw]/3)
	translate([0,bolt_r-depth,wall]) sphere(nubd/2);

//lt_h=100;

module polar(x,y, off=bolt_r) {
	rotate([0,0,arcw]*x) translate([off,0,(y*bolt_h)/(rows+1)]) children();
}

bolt_h=88-10;

module beam(l=1) translate([0,0,w2]/2) rotate([-90,0,0]) intersection() {
	linear_extrude(w2, center=true) hull() {
		trapz(off=0);
		translate([0,0.95*(l*bolt_h)/rows]) trapz(off=0);
	}
	rotate([90,180,180]) translate([0,0,-5]) linear_extrude(10+((l*bolt_h)/rows)) trapz(off=0);
}

module wedge(l, xtra=10) difference() {
	intersection() {
		owedge();
		rotate([0,0,270]) pie(bolt_r+10, xtra, -xtra-arcw*l, 6);
	}

	rotate([180,0,5-xtra/2]) translate([-.1+bolt_r-depth, 0, -7]) rotate([0,0,30]) cube([10,10,10]);
	rotate([0,0,-5+(arcw*l)+xtra/2])	translate([-.1+bolt_r-depth, 0, -3]) rotate([0,0,30]) cube([10,10,10]);
}

//wedge(10, 10);
//translate(-[2,2]) wedge(10, 0);

difference() {

//	translate([0,0,-4]) cylinder(r=bolt_r-.5, h=bolt_h+2);
	translate(-[.25,0,cap_h+wall]) import("blank.stl");

	rotate([0,0,aoff]) union() {

		// Row 0 needs to be longer.
		for(y=[0:0]) for(x=[0:sectors-1]) assign(h=ylen(m,x,y)-1) if(h > 0)
			polar(x,3+rows-y-1,off=bolt_r-depth) beam(h+3);

		for(y=[1:rows-1])	for(x=[0:sectors-1]) assign(h=ylen(m,x,y)-1) if(h>0)
			polar(x,rows-y-1,off=bolt_r-depth) beam(h);

		for(y=[0:rows-1])
		for(x=[0:sectors-1])
			if(xlen(m[rows-y-1], x)) polar(x,y,off=0) wedge(xlen(m[rows-y-1],x)-1);
	}

}

```


[User]
Hi, I'm looking for an OpenSCAD design for a customizable enclosure, similar to the one I have, but I want to make some changes and need it to be fully parametric so I can easily adjust things.

Essentially, I need a box with a separate lid or bottom piece. The box should have rounded corners, and I'd like to be able to specify the outer dimensions (width, length, and height), the wall thickness, and the corner radius. I also need to control the gap between the box and the bottom piece, both in the XY plane and the Z axis, to account for tolerances.

Importantly, the design needs to include screw holes for attaching the bottom to the box. I need to specify the screw hole diameter, the wall thickness of the screw posts, the screw head diameter, the distance from the holes to the walls, and the thickness of the PCB that will sit inside, since the screw posts will need to account for that. There should also be a step in the case to allow the bottom to sit flush.

Finally, I want to be able to adjust the quality of the curves by setting a `$fn` parameter.

It would be great if the bottom piece was separate and had countersunk holes for the screws. I'd like it if the bottom were positioned in the way it would be printed, not like the example where it is below the case.

I'm not using any external libraries currently so I don't need any included.

[Assistant]
customizable_enclosure_v2.scad:
```
/* [Outer Dimensions] */
//Width of the Box in mm
outer_width = 65; 	// [0:0.1:500]
//outer_length of the Box in mm
outer_length = 85; // [0:0.1:500]
//Height of the Box in mm
outer_height = 38;	// [0:0.1:500]

/* [Wall Settings] */
//Wallthickness in mm
wall = 3.6; 	// [0:0.1:25]
//Radius of rounded Corner
corner = 2;	// [0:0.1:20]
//Gap between sides of case and Bottom in mm
gap_xy = 0.2; 	// [0:0.05:2]
//Gap between lip of case and Bottom in mm
gap_z = 0.2; 	// [0:0.05:2]

/* [Hole Settings] */
//Threaddiameter in mm
screw_hole = 2; // [0:0.1:20]
//Wall thickness of screwpost in mm
screw_wall_thickness = 2; // [0:0.1:20]
//Diameter of Screw Head in mm
screw_head = 7; // [0:0.1:50]
//Distance from Hole to Wall in mm
hole_distance = 1.5; // [0:0.1:50]
//Thickness of Circuit Board to be sandwiched between Case and Bottom in mm
pcb_height = 1.6; // [0:0.1:15]
//Step between Case and Bottom in mm
step = 1; 	// [0:0.1:10]

/* [Quality] */
//Quality (simply experiment)
Quality = 25;	// [1:100]

$fn = Quality;
case(outer_width, outer_length,	outer_height, wall, corner, gap_xy, gap_z, screw_hole,
	screw_wall_thickness, screw_head, pcb_height, hole_distance, step, Quality);

//Case with rounded corners, screwholes and bottom
module case
(
	outer_width = 35,
	outer_length = 45,
	outer_height = 38,
	wall = 3.6,
	corner = 2,
	gap_xy = 0.2,
	gap_z = 1,
	screw_hole = 2,
	screw_wall_thickness = 2,
	screw_head = 7,
	pcb_height = 0,
	hole_distance = 1.5,
	step = 1.5,
	quality = 25
)
{
    $fn = quality;

    //case
    union()
    {
        difference()
        {
            translate([corner, corner, corner])
            {
                minkowski()
                {
                    cube([outer_width - 2*corner, outer_length - 2*corner, outer_height - 2*corner], false);
                    $fn = 15;
                    sphere(corner);
                }
            }

            translate([wall, wall, wall])
            {
                cube([outer_width - 2*wall, outer_length - 2*wall, outer_height + corner], false);
            }

			translate([wall - step, wall - step, outer_height - wall])
            {
                cube([outer_width + 2*step - 2*wall, outer_length + 2*step - 2*wall, 2*wall], false);
            }
        }

        if(screw_hole > 0)
            {
                h_offset = wall + hole_distance + screw_hole/2;
                h_height = outer_height - 2 * wall - pcb_height + 0.1;
                dia = screw_hole + screw_wall_thickness*2;

                translate([h_offset, h_offset, wall - 0.1])
                {
                    difference()
                    {
                        cylinder(h_height, d = dia);
                        cylinder(outer_height, d = screw_hole);
                    }
                }

                translate([outer_width - h_offset, h_offset, wall - 0.1])
                {
                    difference()
                    {
                        cylinder(h_height, d = dia);
                        cylinder(outer_height, d = screw_hole);
                    }
                }

                translate([h_offset, outer_length - h_offset, wall - 0.1])
                {
                    difference()
                    {
                        cylinder(h_height, d = dia);
                        cylinder(outer_height, d = screw_hole);
                    }
                }

                translate([outer_width - h_offset, outer_length - h_offset, wall - 0.1])
                {
                    difference()
                    {
                        cylinder(h_height, d = dia);
                        cylinder(outer_height, d = screw_hole);
                    }
                }
            }
    }

    //Bottom
    //#translate([wall - step + gap_xy, wall - step + gap_xy, height - wall + gap_z]) //Mounted Pos
	translate([0, outer_length + 5*wall, 0]) //Printing Pos
    {
        difference()
        {
			cube_x = outer_width + 2*(step - wall - gap_xy);
			cube_y = outer_length + 2*(step - wall - gap_xy);

            cube([cube_x, cube_y, wall - gap_z], false);

            if(screw_hole > 0)
            {
                b_h_offset = step + screw_hole/2 - gap_xy + hole_distance;
                b_width = outer_width - 2 * wall;
                b_depth = outer_length - 2 * wall;
                h_depth = wall * (1/4);

                translate([b_h_offset, b_h_offset, -1])
                {
                    cylinder(wall + 2, d = screw_hole);
					translate([0, 0, 1 + h_depth])cylinder(wall, d = screw_head);
                }

                translate([cube_x - b_h_offset, b_h_offset, -1])
                {
                    cylinder(wall + 2, d = screw_hole);
					translate([0, 0, 1 + h_depth])cylinder(wall, d = screw_head);
                }
                translate([b_h_offset, cube_y - b_h_offset, -1])
                {
                    cylinder(wall + 2, d = screw_hole);
					translate([0, 0, 1 + h_depth])cylinder(wall, d = screw_head);
                }

                translate([cube_x - b_h_offset, cube_y - b_h_offset, -1])
                {
                    cylinder(wall + 2, d = screw_hole);
					translate([0, 0, 1 + h_depth])cylinder(wall, d = screw_head);
                }

            }
        }
    }
}
```


[User]
I'd like to design a classically shaped vase that's easy to 3D print. I'm attaching a SCAD file called "albina.scad" that has the basic profile I want, but it's not very flexible. I'd like to be able to change the overall height of the vase while maintaining the proportions of the original profile. Ideally, it would also be nice to easily change the wall thickness of the vase. I'd prefer to avoid requiring any supports during printing and I don't want to have to do a lot of post-processing.

Could you generate a parametric OpenSCAD file or files that allows me to do this? I don't need anything too fancy, just the basic vase shape with these parameters. It would be great if the resulting design is still based on a `rotate_extrude` so that the profile remains smooth. It also uses some of the typical `$fa` and `$fs` variables, I'd like to keep those defaults as they are defined as `const` within the provided file. Please ensure to use the `resize()` function to manage the height before the `rotate_extrude` operation. The `eps` workaround is not strictly needed since we are not using CSG in the final design, but you're free to keep it if it makes the code clearer.

[Assistant]
albina.scad:
```
/*
 * Copyright © 2016 by Jarek Cora <jarek@stormdust.net>
 *
 * This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License.
 */

// Marker for non-configurable values
function const(x) = x;
// Minimum angle of a fragment - circle has no more fragments than 360 divided by this number
$fa = const(1);
// The minimum size of a fragment
$fs = const(0.1);
// Workaround for CSG operations
eps = const(0.1);

// Height of the vase in milimeters
height = 180; // [150:5:200]

rotate_extrude() {
    resize([0, height, 0], auto = true) polygon([
        [47.1811,4.732280000000003],
        [46.773189,5.587778999999983],
        [46.423926,6.748019999999997],
        [46.120569,8.477358999999979],
        [45.970201,10.836371999999983],
        [46.079907000000006,13.885638999999998],
        [46.55677,17.68573599999999],
        [47.507873000000004,22.297240999999985],
        [49.040299000000005,27.780731999999986],
        [51.261133,34.19678599999999],
        [54.277458,41.605980999999986],
        [58.196358000000004,50.06889499999998],
        [63.124915,59.64610499999999],
        [69.170214,70.39818999999999],
        [76.439338,82.385725],
        [85.03937,95.66928999999999],
        [88.842613,101.79630599999999],
        [90.37474700000001,104.65333899999999],
        [91.66177300000001,107.40222999999999],
        [92.704604,110.06510899999999],
        [93.504152,112.66410599999999],
        [94.06133,115.221353],
        [94.37705,117.75897799999998],
        [94.452225,120.29911399999999],
        [94.287767,122.86389],
        [93.88459,125.47543599999999],
        [93.243605,128.155883],
        [92.365726,130.927362],
        [91.25186400000001,133.812003],
        [88.319845,140.00929299999999],
        [84.454848,146.92479699999998],
        [79.664175,154.735557],
        [67.33500000000001,173.751024],
        [51.390727000000005,198.472042],
        [42.08118,213.414741],
        [31.889760000000003,230.314959],
        [29.745893000000002,234.387812],
        [28.077158000000004,238.51042999999999],
        [26.842993000000003,242.663346],
        [26.002839,246.827094],
        [25.516134000000005,250.982206],
        [25.342319000000003,255.109218],
        [25.440832000000004,259.188663],
        [25.771114000000004,263.201073],
        [26.292603000000003,267.126984],
        [26.964739,270.94692799999996],
        [28.598712000000003,278.191051],
        [31.889760000000003,290.551179],
        [32.136006,290.92715799999996],
        [32.604536,291.19571299999996],
        [33.87626,291.410558],
        [35.040562,291.19571299999996],
        [35.374813,290.92715799999996],
        [35.43307,290.551179],
        [32.362544,278.864965],
        [30.921529000000003,272.293563],
        [30.342426000000003,268.844433],
        [29.902484000000005,265.293453],
        [29.635373000000005,261.64594999999997],
        [29.574762000000003,257.90725199999997],
        [29.754320000000003,254.08268499999997],
        [30.207716000000005,250.177576],
        [30.968621000000002,246.197252],
        [32.070701,242.147042],
        [33.547628,238.03226999999998],
        [35.43307,233.858266],
        [38.793524000000005,227.337404],
        [42.219506,221.0553],
        [49.197987000000005,209.165843],
        [56.228372,198.10684999999998],
        [63.17052,187.79527199999998],
        [76.229544,169.082182],
        [82.06613899999999,160.51457599999998],
        [87.25393500000001,152.362202],
        [89.56073900000001,148.415774],
        [91.65279100000001,144.542013],
        [93.512573,140.730535],
        [95.122568,136.970962],
        [96.46525700000001,133.25291199999998],
        [97.523123,129.566004],
        [98.278649,125.899858],
        [98.714317,122.244092],
        [98.81261,118.588326],
        [98.55601,114.92218],
        [97.926999,111.23527199999998],
        [96.90806,107.51722099999999],
        [95.481675,103.75764799999999],
        [93.630327,99.94617],
        [91.336498,96.072408],
        [88.58267000000001,92.12598],
        [83.80480700000001,85.626745],
        [79.425956,79.41298199999999],
        [75.429896,73.47949999999999],
        [71.800407,67.821108],
        [68.521269,62.43261699999999],
        [65.57626300000001,57.308835999999985],
        [62.949169000000005,52.444574999999986],
        [60.623765000000006,47.834642999999986],
        [56.813153,39.35700399999999],
        [54.014667,31.834396999999996],
        [52.098548,25.225298999999993],
        [50.935035000000006,19.488186999999996],
        [50.394369000000005,14.581537999999995],
        [50.346790000000006,10.463827999999978],
        [50.662539,7.093533999999977],
        [51.211855,4.429132999999979],
        [51.864979000000005,2.429102999999998],
        [52.49215100000001,1.051918999999998],
        [53.14960000000001,0],
        [0,0],
        [0,4.732280000000003]
    ]);
}

```


[User]
Hey, I'm looking for an OpenSCAD design for a car phone holder that fits into the CD slot. I want it to be parametric so I can adjust it for different phone sizes and car CD slots.

Essentially, I need two main parts: a phone cradle and a CD slot mount.

The phone cradle should be a box-like structure with a cutout to hold the phone. I'd like to specify the phone's length, depth, and a bit of frame around it. I'll also need to set how tall the cradle goes up the back of the phone so it doesn't block any buttons or the like. The cutout should be adjustable based on `Smartphone_length`, `Smartphone_depth`, `Smartphone_frame_left_right` and `Smartphone_frame_bottom` and `Smartphone_height_button` parameters.

The CD slot mount needs to be a flat part with a wedge that fits into the CD slot. I'd like to set the `CD_slot_angle` and the overall `CD_slot_height` and `CD_slot_depth`. The mount should be strong enough to hold the phone steady. The connection between the phone cradle and the mount should be solid, so probably built right into one another. I don't want any separate pieces to deal with.

I'm hoping the whole design can be rendered so I can see the shape and adjust dimensions as needed. I'd prefer if the design didn't use any external libraries.

Here's a summary of the parameters I expect to be able to adjust:

*   `Smartphone_length`:  The length of the smartphone.
*   `Smartphone_depth`: The depth of the smartphone.
*   `Smartphone_frame_left_right`: The width of the frame around the left and right edges of the phone.
*   `Smartphone_frame_bottom`:  The width of the frame at the bottom of the phone.
*  `Smartphone_height_button`: The height of the back of the phone holder.
*   `CD_slot_angle`: The angle of the CD slot wedge.
*   `CD_slot_height`: The overall height of the CD slot mount.
*  `CD_slot_depth`: The depth of the CD slot wedge.

Can you generate the OpenSCAD file?

[Assistant]
CD_Slot_Phone_V02.scad:
```
// CD Slot Smartphone holder

Smartphone_length = 146;
Smartphone_depth = 11;
Smartphone_frame_left_right = 10;
Smartphone_frame_bottom = 4;
Smartphone_height_button = 25;
CD_slot_angle = 15;
CD_slot_height= 52;
CD_slot_depth = 25;

union() {
    difference() {
        translate([-(Smartphone_length+4)/2,-(Smartphone_depth+4)/2,0]) {
            cube([Smartphone_length+4,Smartphone_depth+4,Smartphone_height_button+2]);
        }
        translate([-Smartphone_length/2,-Smartphone_depth/2,2]) {
            cube([Smartphone_length,Smartphone_depth,Smartphone_height_button+2]);
        }
        translate([-(Smartphone_length-2*Smartphone_frame_left_right)/2,-10,Smartphone_frame_bottom+2]) {
            cube([Smartphone_length-2*Smartphone_frame_left_right,10,Smartphone_height_button]);
        }
    }

    translate([-110/2,(Smartphone_depth)/2,0]) {
        cube([110,2,CD_slot_height]);
    }

    translate([-110/2,(Smartphone_depth+2)/2,CD_slot_height]) {
        rotate([-90-CD_slot_angle,0,0]) {
            union() {
                translate([2,0,CD_slot_depth]) {
                    rotate([-90,0,0]) {
                        cylinder(1.5,2,2);
                    }
                }
                translate([110-2,0,CD_slot_depth]) {
                    rotate([-90,0,0]) {
                        cylinder(1.5,2,2);
                    }
                }
                cube([110,1.5,CD_slot_depth]);
                translate([2,0,CD_slot_depth]) {
                    cube([110-4,1.5,2]);
                }
            }
        }
    }
}
```


[User]
I'd like to have a customizable award base designed in OpenSCAD. It should consist of a series of stacked cylinders to create a tiered base, and it should also have an optional label and an optional mounting hole for a statue.

Here are the specific requirements for the base:

*   **Base Structure:** The base should be composed of four stacked cylinders with the following parameters (diameter, height):
    *   Cylinder 1: 56.2mm diameter, 3mm height
    *   Cylinder 2: 52.5mm diameter, 1.4mm height
    *   Cylinder 3: 46.7mm diameter, 21.5mm height
    *   Cylinder 4: 40mm diameter, 3.1mm height

    The cylinders should be stacked vertically, with the first cylinder at the bottom and the fourth cylinder on top. There should be a slight overlap between the cylinders; the second cylinder should be placed with its bottom at 1 delta (0.01mm) below the top of the first cylinder, the third cylinder should be placed with its bottom at 1 delta (0.01mm) below the top of the second cylinder, and the fourth cylinder should be placed with its bottom at the top of the third cylinder.

*   **Label:** There should be an optional cylindrical label that wraps around the third cylinder.
    *   It should be a hollowed out cylinder with an outer diameter of 46.7mm (the same diameter as cylinder 3) + 0.01mm, and an inner diameter 3mm smaller (so, an outer diameter of 46.71mm, and an inner diameter of 43.71mm) .
     * The label height should be 21.5mm - labelMargin. The labelMargin should be customizable, and should default to 5mm.
    *  The label should be cut through a plane. The cutting plane should start 11mm along the X axis and be 50mm wide in the x direction, and very large in the other two directions.
   * The label should be rotated by 90 degrees on the Z-axis before any other transformations.
  * The label should be positioned above the third cylinder of the base, starting at the top of cylinder 2. (taking into account the overlap of the cylinders.)

*   **Mounting Hole:** There should be an optional rectangular mounting hole on the top of the base, centered on the base's center.
    *   It should be a simple rectangular cuboid, with customizable `holeLength`, `holeWidth`, and `holeDepth`.
   *  It should be centered on the X and Y axes, and should have its top face flush with the top face of the fourth cylinder. The top of the hole should be flush with the top of the base.
    *   The hole should only be cut into the base if a `holeEnabled` parameter is set to "yes".

*   **Customization:** The following parameters should be customizable:
    *   `holeEnabled` (yes/no - default should be "yes")
    *   `holeLength` (default 15.5)
    *   `holeWidth` (default 3)
    *   `holeDepth` (default 20)
    *   `labelMargin` (default 5)
    *   `printItem` (should accept "Both", "Base only", or "Label only")

*   **Output:** I'd like to be able to select what gets printed via the `printItem` parameter. If "Both" is selected (or left as default), then both the base and the label should be included. If "Base only" is selected, then only the base should be generated. If "Label only" is selected, then only the label should be generated.

*   **Libraries:** I don't think this design requires any external libraries.
*   **Colors:** The base should be colored "DimGrey" and the label should be colored "Gold".

Also please make sure to use `$fn = 180;` to create smooth curves.

[Assistant]
Award_Base.scad:
```
// Customizable Award Base
// by György Balássy 2016 (http://gyorgybalassy.wordpress.com)
// Inspired by TheNewHobbyist's Customizable Movie Award Base (http://www.thingiverse.com/thing:244025).
// http://www.thingiverse.com/thing:1991203

// What do you want to print?
printItem = "Both"; // [Both, Base only, Label only]

// Do you want a square hole on the top of the base to mount a statue?
holeEnabled = "yes";  // [yes,no]

// The size of the mount hole for the statue in X dimension.
holeLength = 15.5;

// The size of the mount hole for the statue in Y dimension.
holeWidth = 3;

// The depth of the mount hole for the statue in Z dimension.
holeDepth = 20;

/* [Hidden] */

$fn = 180;
delta = .01;

// Ring sizes: [0] = Ring diameter, [1] = Ring height.
c1 = [56.2, 3];
c2 = [52.5, 1.4];
c3 = [46.7, 21.5];
c4 = [40, 3.1];

// Label size.
labelThickness = 3;
labelMargin = 5;

if (printItem == "Both" || printItem == "Base only") {
  base();
}
if (printItem == "Both" || printItem == "Label only") {
  label();
}

module label() {
  color("Gold")
    rotate([0, 0, 90]) {
      difference(){
        // External ring.
        translate([0, 0, 0 + c1[1] + c2[1] - delta + labelMargin / 2])
          cylinder(d = c3[0] + delta, h = c3[1] - labelMargin, center = false);

        // Internal ring.
        translate([0, 0, 0 + c1[1] + c2[1] - delta * 2 + labelMargin / 2])
          cylinder(d = c3[0] - labelThickness, h = c3[1] - labelMargin + delta * 2, center = false);

        // Cutting plane.
        translate([11, 0, 0]) // The first parameter determines the width of the label.
          cube([50,  100,  100], center = true);
      }
    }
}

module hole() {
  translate([0, 0, -holeDepth / 2 + c1[1] + c2[1] + c3[1] + c4[1] + delta])
    cube([holeLength,  holeWidth,  holeDepth], center = true);
}

module base() {
  color("DimGrey")
    difference(){
      union(){
        translate([0, 0, 0])
          cylinder(d = c1[0], h = c1[1], center = false);
        translate([0, 0, 0 + c1[1] - delta])
          cylinder(d = c2[0], h = c2[1], center = false);
        translate([0, 0, 0 + c1[1] + c2[1] - delta])
          cylinder(d = c3[0], h = c3[1], center = false);
        translate([0, 0, 0 + c1[1] + c2[1] + c3[1]])
          cylinder(d = c4[0], h = c4[1], center = false);
      }
      label();

      if (holeEnabled == "yes") {
        hole();
      }
    }
}

```


[User]
Hey, I'm looking to generate some interesting egg-like containers, and I was inspired by a design I saw that uses a phyllotaxis pattern. I'd like to be able to customize a few things, and I'd like the result to be a container that can be screwed together.

Ideally, I'd like to generate four different files: a complete sphere, an upper semisphere, a lower semisphere, and a screw to connect the two halves. The core of the design should be a sphere decorated with elements arranged according to a phyllotaxis pattern. I'd like to be able to choose between two types of decorative elements: 'bulbs' and 'spikes'. I'd like to be able to set which of the two types is the "primary" pattern, and also choose to have the second pattern appear every N steps, so I can create a more complex pattern.

For the 'spikes', I need to be able to control their scale and distribution on the sphere. I should be able to choose whether the spikes are bigger at the top, bigger in the center, or a uniform size. I also need to be able to control a "variation" parameter to control the size fluctuation throughout the sphere.

For the 'bulbs', I need to choose the type of top decoration: a hole, a ball, or a flat top.

Finally, the two halves should be connected with a screw, using a custom screw design. I know this design uses the "Poor Man's Screw Library" for this (though I don't have that specific library). I think the script is including the necessary functions from that library in the main script itself (e.g., `screw_thread`, `hex_nut`).

Can you generate the OpenSCAD code that can achieve this, including all necessary screw generation code so that I have a functional container and not just the decorative pieces?

[Assistant]
phyllo_sphere_customizer.scad:
```
/*

Phyllotaxis Sphere

http://www.thingiverse.com/thing:1995900

Fernando Jerez 2016

*/

// Wich part want to see
part = "all"; // [ all:Sphere, up:Upper semisphere, down:Lower semisphere, screw:Screw ]

// Phyllotaxis angle
angle = 137.51;

// Pattern #1
pattern1 = "bulb"; // [bulb:Bulb, spike:Spike]
// Pattern #2
pattern2 = "spike"; // [bulb:Bulb, spike:Spike]

// Draw one Pattern #2 every N steps
pattern2_every = 3;

// For spikes: Set scale factor
spikes_scale = 1;
// For spikes: Set scale distribution
spikes_distribution = "Bigger_at_top"; // [Bigger_at_top:Bigger at top, Bigger_at_center:Bigger at center, uniform:Uniform ]
// For spikes: Set scale oscilation trough the sphere
spikes_variation = 0.5; // [0.5:0.5:5]

// For bulbs: Set top decoration
bulb_type="hole"; // [hole:Hole, ball:Ball, flat:Flat ]

/* [Hidden] */
$fn = 16;
c = 3;
num = 360;
zmult = spikes_variation;

//screw
if(part=="screw"){
    translate([0,0,-10]){
        rotate([0,0,0]){
            difference(){
                union(){
                    translate([0,0,0])
                    scale([2,2,1]){
                        screw_thread(45,8,55,20,PI/2,2);
                    }
                    //translate([0,0,8]) cylinder(r1=43,r2=45,h=2,$fn=60);
                }
                translate([0,0,-6]) cylinder(r=37, h = 40,$fn=40);
            }
        }
    }

}else{
    // PHYLLOTAXIS sphere
    difference(){
        union(){
            difference(){
                union(){
                    // Phyllotaxis loop
                    for(i=[0:num]){

                        // spikes orientation (perpendicular to sphere)
                        gx = 0;
                        gy = 90-90*cos(i*0.5)*abs(cos(i*0.5));
                        gz = 0;

                        // Scale of spikes
                        sx = c*(0.5+abs(sin(i*0.5)));
                        sy = sx;
                        sz = sx;

                        // Distribution of spikes (sphere)
                        r = c*15*sin(i*0.5); // distance XY
                        z = c*15*cos(i*0.5); // distance Z

                        rx = 0;
                        ry = i*0.25;
                        rz = angle*i;

                        translate([0,0,z])
                        rotate([rx,0,rz]){
                            translate([r,0,0]){
                                    scale([sx,sy,sz]){
                                            rotate([gx,gy,gz]){

                                        if(i%pattern2_every==0){
                                            // Pattern 2
                                            if(pattern2=="spike"){
                                                spike(i);
                                            }else{
                                                bulb(i);
                                            }

                                        }else{
                                            // pattern 1
                                            if(pattern1=="spike"){
                                                spike(i);
                                            }else{
                                                bulb(i);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                    }

                    difference(){
                        sphere(47,$fn=50);
                        sphere(43,$fn=50);
                        if(part!="all"){
                            translate([0,0,8]) cylinder(r1=46,r2 = 35,h=8,$fn=50);
                            rotate([180,0,0]) translate([0,0,8]) cylinder(r1=46,r2 = 35,h=8,$fn=50);
                        }
                    }

                }
                if(part!="all"){
                    translate([0,0,-10]) cylinder(r=45.5,h=20,$fn=60);
                }
            }

            //nut
            if(part!="all"){
                translate([0,0,-10]){
                    scale([2,2,1]){
                          hex_nut(46,20,8,55,45,0.5);
                    }
                }
            }

        } // fin union

        // Diferencia con un cubo para partir por la mitad
        if(part=="up"){
            translate([0,0,-100]) rotate([0,0,0]) cube([200,200,200],center = true); // up
        }
        if(part=="down"){
            translate([0,0,100]) rotate([0,0,0]) cube([200,200,200],center = true); // up
        }
        //    translate([0,0,50]) rotate([0,0,0]) cube([200,200,100],center = true); // down
    } // fin difference

}// fin else

// some modules for geometry
module spike(i){
    color("orange"){
        if(spikes_distribution == "Bigger_at_top"){
            z = 0.5+spikes_scale*abs(cos(i*zmult));
            scale([1,1,z])
            cylinder(r1=c*0.75, r2 = c*0.1, h = c*1);
        }else{
            if(spikes_distribution == "Bigger_at_center"){
                z = 0.5+spikes_scale*abs(sin(i*zmult));
                scale([1,1,z])
                cylinder(r1=c*0.75, r2 = c*0.1, h = c*1);
            }else{
                z = spikes_scale;
                scale([1,1,z])
                cylinder(r1=c*0.75, r2 = c*0.1, h = c*1);
            }
        }
    }
}

module bulb(i){
    difference(){
        cylinder(r1=c*0.8,r2 = c*0.3, h = c*0.5,$fn=15);

        if(bulb_type=="hole"){
            translate([0,0,c*0.2])
            cylinder(r1=c*0,r2=c*0.3,h=c*0.5,$fn = 6);

        }

    }
    if(bulb_type=="ball"){
        translate([0,0,c*0.5])
        //cylinder(r1=c*0,r2=c*0.3,h=c*0.5,$fn = 6);
        sphere(r = c*0.25, $fn=10);
    }

}

// COPY-PASTE of Poor man's screw library (just for customizer)

/*
 *    polyScrewThread_r1.scad    by aubenc @ Thingiverse
 *
 * This script contains the library modules that can be used to generate
 * threaded rods, screws and nuts.
 *
 * http://www.thingiverse.com/thing:8796
 *
 * CC Public Domain
 */

module screw_thread(od,st,lf0,lt,rs,cs)
{
    or=od/2;
    ir=or-st/2*cos(lf0)/sin(lf0);
    pf=2*PI*or;
    sn=floor(pf/rs);
    lfxy=360/sn;
    ttn=round(lt/st+1);
    zt=st/sn;

    intersection()
    {
        if (cs >= -1)
        {
           thread_shape(cs,lt,or,ir,sn,st);
        }

        full_thread(ttn,st,sn,zt,lfxy,or,ir);
    }
}

module hex_nut(df,hg,sth,clf,cod,crs)
{

    difference()
    {
        hex_head_1(hg,df); // modfied by Fernando Jerez (for 'ring nuts')
        // hex_head(hg,df); // original library code

        hex_countersink_ends(sth/2,cod,clf,crs,hg);

        screw_thread(cod,sth,clf,hg,crs,-2);
    }
}

module hex_screw(od,st,lf0,lt,rs,cs,df,hg,ntl,ntd)
{
    ntr=od/2-(st/2)*cos(lf0)/sin(lf0);

    union()
    {
        hex_head(hg,df);

        translate([0,0,hg])
        if ( ntl == 0 )
        {
            cylinder(h=0.01, r=ntr, center=true);
        }
        else
        {
            if ( ntd == -1 )
            {
                cylinder(h=ntl+0.01, r=ntr, $fn=floor(od*PI/rs), center=false);
            }
            else if ( ntd == 0 )
            {
                union()
                {
                    cylinder(h=ntl-st/2,
                             r=od/2, $fn=floor(od*PI/rs), center=false);

                    translate([0,0,ntl-st/2])
                    cylinder(h=st/2,
                             r1=od/2, r2=ntr,
                             $fn=floor(od*PI/rs), center=false);
                }
            }
            else
            {
                cylinder(h=ntl, r=ntd/2, $fn=ntd*PI/rs, center=false);
            }
        }

        translate([0,0,ntl+hg]) screw_thread(od,st,lf0,lt,rs,cs);
    }
}

module hex_screw_0(od,st,lf0,lt,rs,cs,df,hg,ntl,ntd)
{
    ntr=od/2-(st/2)*cos(lf0)/sin(lf0);

    union()
    {
        hex_head_0(hg,df);

        translate([0,0,hg])
        if ( ntl == 0 )
        {
            cylinder(h=0.01, r=ntr, center=true);
        }
        else
        {
            if ( ntd == -1 )
            {
                cylinder(h=ntl+0.01, r=ntr, $fn=floor(od*PI/rs), center=false);
            }
            else if ( ntd == 0 )
            {
                union()
                {
                    cylinder(h=ntl-st/2,
                             r=od/2, $fn=floor(od*PI/rs), center=false);

                    translate([0,0,ntl-st/2])
                    cylinder(h=st/2,
                             r1=od/2, r2=ntr,
                             $fn=floor(od*PI/rs), center=false);
                }
            }
            else
            {
                cylinder(h=ntl, r=ntd/2, $fn=ntd*PI/rs, center=false);
            }
        }

        translate([0,0,ntl+hg]) screw_thread(od,st,lf0,lt,rs,cs);
    }
}

module thread_shape(cs,lt,or,ir,sn,st)
{
    if ( cs == 0 )
    {
        cylinder(h=lt, r=or, $fn=sn, center=false);
    }
    else
    {
        union()
        {
            translate([0,0,st/2])
              cylinder(h=lt-st+0.005, r=or, $fn=sn, center=false);

            if ( cs == -1 || cs == 2 )
            {
                cylinder(h=st/2, r1=ir, r2=or, $fn=sn, center=false);
            }
            else
            {
                cylinder(h=st/2, r=or, $fn=sn, center=false);
            }

            translate([0,0,lt-st/2])
            if ( cs == 1 || cs == 2 )
            {
                  cylinder(h=st/2, r1=or, r2=ir, $fn=sn, center=false);
            }
            else
            {
                cylinder(h=st/2, r=or, $fn=sn, center=false);
            }
        }
    }
}

module full_thread(ttn,st,sn,zt,lfxy,or,ir)
{
  if(ir >= 0.2)
  {
    for(i=[0:ttn-1])
    {
        for(j=[0:sn-1]){
			pt = [	[0,                  0,                  i*st-st            ],
                        [ir*cos(j*lfxy),     ir*sin(j*lfxy),     i*st+j*zt-st       ],
                        [ir*cos((j+1)*lfxy), ir*sin((j+1)*lfxy), i*st+(j+1)*zt-st   ],
								[0,0,i*st],
                        [or*cos(j*lfxy),     or*sin(j*lfxy),     i*st+j*zt-st/2     ],
                        [or*cos((j+1)*lfxy), or*sin((j+1)*lfxy), i*st+(j+1)*zt-st/2 ],
                        [ir*cos(j*lfxy),     ir*sin(j*lfxy),     i*st+j*zt          ],
                        [ir*cos((j+1)*lfxy), ir*sin((j+1)*lfxy), i*st+(j+1)*zt      ],
                        [0,                  0,                  i*st+st            ]	];

            polyhedron(points=pt,
              		  faces=[	[1,0,3],[1,3,6],[6,3,8],[1,6,4],
											[0,1,2],[1,4,2],[2,4,5],[5,4,6],[5,6,7],[7,6,8],
											[7,8,3],[0,2,3],[3,2,7],[7,2,5]	]);
        }
    }
  }
  else
  {
    echo("Step Degrees too agresive, the thread will not be made!!");
    echo("Try to increase de value for the degrees and/or...");
    echo(" decrease the pitch value and/or...");
    echo(" increase the outer diameter value.");
  }
}

module hex_head(hg,df)
{
	rd0=df/2/sin(60);
	x0=0;	x1=df/2;	x2=x1+hg/2;
	y0=0;	y1=hg/2;	y2=hg;

	intersection()
	{
	   cylinder(h=hg, r=rd0, $fn=6, center=false);

		rotate_extrude(convexity=10, $fn=6*round(df*PI/6/0.5))
		polygon([ [x0,y0],[x1,y0],[x2,y1],[x1,y2],[x0,y2] ]);
	}
}

module hex_head_0(hg,df)
{
    cylinder(h=hg, r=df/2/sin(60), $fn=60, center=false);
}

/*************
Added by Fernando Jerez (useful for 'ring nuts'
*/
module hex_head_1(hg,df)
{
    cylinder(h=hg, r=df/2, $fn=60, center=false);
}
/**************/

module hex_countersink_ends(chg,cod,clf,crs,hg)
{
    translate([0,0,-0.1])
    cylinder(h=chg+0.01,
             r1=cod/2,
             r2=cod/2-(chg+0.1)*cos(clf)/sin(clf),
             $fn=floor(cod*PI/crs), center=false);

    translate([0,0,hg-chg+0.1])
    cylinder(h=chg+0.01,
             r1=cod/2-(chg+0.1)*cos(clf)/sin(clf),
             r2=cod/2,
             $fn=floor(cod*PI/crs), center=false);
}

```


[User]
I'd like to request a parametric OpenSCAD design for a flute wall mount. The design should be as compact as possible while securely holding a standard flute. I have some specific dimensions and design considerations in mind.

The flute's inner bore diameter is 18.25mm, and I'd like a 19mm clearance around that for easy insertion and removal. The engagement height for the flute should be 30mm. There needs to be a platen that holds the flute - the platen diameter should be 23mm.

The mount should have two screw holes for attaching to the wall, and should be designed to accept screws with a maximum head diameter of 8.7mm, a root diameter of 3.8mm, a taper height of 3.85mm, and a thread width of 4.8mm.

I'd also like a gusset to provide structural support. I calculate the gusset width to be the sum of the flute installation wiggle room plus half of the flute platen diameter, times two. The gusset should be 10mm thick. The whole design should account for the screw head and have the mount extending past the screw head's height.

The design should have rounded lead-ins for both the flute shaft and the screw holes. The gusset should also be angled at 45 degrees. Please try to minimize material use as much as possible while ensuring strength and stability.

I am not including any code I have for this, and will trust your work completely. I would prefer if the OpenSCAD code were as efficient as possible.

[Assistant]
Flute_Wall_Hanger.scad:
```
/* Flute Wall Hanger
Inner Bore of flute 18.25mm
give a 19mm berth
30mm engagement height
45 degree gusset
rounded lead in
*/
/////////////////////////////////////////
fluteInnerBore = 18.25;
fluteEngagementHeight = 30;
flutePlatenDiameter = 23;
fluteInstallWiggleRoom = 19;
screwHeadDiameterMax = 8.7;
screwHeadDiameterRoot = 3.8;
screwHeadTaperHeight = 3.85;
screwThreadWidth = 4.8;
gussetWidth = fluteInstallWiggleRoom+flutePlatenDiameter/2+flutePlatenDiameter/2;
gussetThickness = 10;
wallPlateShaftHeight = fluteEngagementHeight+gussetWidth+fluteInnerBore/2+screwHeadDiameterMax*2;
/////////////////////////////////////////
wallPlate();
gusset();
fluteEngagement();
/////////////////////////////////////////
module wallPlate(){
    translate([gussetWidth*.95,0,-gussetWidth-screwHeadDiameterMax]){
        wallPlateShaft();
    }
}
module wallPlateShaft(){
    difference(){
        union(){
            cylinder(d=flutePlatenDiameter,h=wallPlateShaftHeight,$fn=100);
            sphere(d=flutePlatenDiameter,center=true,$fn=100);
            translate([0,0,wallPlateShaftHeight]){
                sphere(d=flutePlatenDiameter,center=true,$fn=100);
            }
        }
        wallModel();
        screwHoleLower();
        screwHoleUpper();
    }
}
module wallModel(){
translate([flutePlatenDiameter/2,0,wallPlateShaftHeight/2]){
        cube([flutePlatenDiameter,flutePlatenDiameter,wallPlateShaftHeight+flutePlatenDiameter],center=true);
    }
}
module screwHoleLower(){
    translate([-flutePlatenDiameter/2+2,0,screwHeadDiameterMax/2]){
        rotate([0,90,0]){
            screwHole();
        }
    }
}
module screwHoleUpper(){
    translate([-flutePlatenDiameter/2+2,0,wallPlateShaftHeight-screwHeadDiameterMax/2]){
        rotate([0,90,0]){
            screwHole();
        }
    }
}
module screwHole(){
        cylinder(d1 = screwHeadDiameterMax, d2 = screwHeadDiameterRoot,h = screwHeadTaperHeight,$fn = 100);
    cylinder(d=screwThreadWidth,100,$fn = 100);
    translate([0,0,-100]){
        cylinder(d=screwHeadDiameterMax,100,$fn=100);
    }
}
/////////////////////////////////////////
module gusset(){
    difference(){
    gussetPrimal();
    uglyAngleCutoff();
    angleCutoff();
    }
}
module uglyAngleCutoff(){
        translate([-gussetWidth/2-flutePlatenDiameter/2+(flutePlatenDiameter-fluteInnerBore)/2,0,-gussetWidth/2]){
          cube([gussetWidth,gussetThickness,gussetWidth],center=true);
            }
}
module gussetPrimal(){
    translate([gussetWidth/2-flutePlatenDiameter/2,0,-gussetWidth/2]){
cube([gussetWidth,gussetThickness,gussetWidth],center=true);
    }
}
module angleCutoff(){
    translate([gussetWidth/2-flutePlatenDiameter/2,0,-gussetWidth/2]){
        rotate([0,135,0]){
            translate([gussetWidth,0,0]){
                cube([gussetWidth*2,gussetThickness*2,gussetWidth*2],center=true);
            }
        }
    }
}
/////////////////////////////////////////
module fluteEngagement(){
flutePlaten();
fluteShaft();
}
module flutePlaten(){
    difference(){
 sphere(d=flutePlatenDiameter,$fn=100);
        cylinder(d=flutePlatenDiameter*2,h=flutePlatenDiameter);
    }
}
module fluteShaft(){
 cylinder(d = fluteInnerBore,h = fluteEngagementHeight,$fn=100);
    translate([0,0,fluteEngagementHeight]){
    sphere(d=fluteInnerBore, $fn=100);
    }
}
```


[User]
I'm looking for an OpenSCAD design for a customizable floor stand, similar to the "Mini Floor Stands" design on Thingiverse, but with more flexibility in text and part selection for dual extrusion. I want to be able to print just the text portion, just the sign portion, or both.

Specifically, I need a design that has the following features:

*   **Text:** It should have four lines of text, each with its own customizable font size (and ideally, in OpenSCAD, font style, though I understand this might not be visible in the customizer).  I’d like the font size to be adjustable in the range of 1-6, with 6pt being the largest for reasonable spacing. I need to be able to change the text of each of these four lines.
*   **Part Selection:** I need a way to easily select whether to print only the text part, only the sign part, or both.  This is important for dual extrusion, where the text might be one color and the sign another.
*   **Sign Design:** The sign itself should have a male and female side with a way to connect together, similar to the provided design. I want it to be durable, and if needed, it can be a similar size to the example given, about 80mm by 40mm.
*   **Rounded edges:** I want the sign to have rounded edges.
*   **OpenSCAD:** I'd like a parametric design so that I can change dimensions later, if necessary.
*   **Dual Extrusion:** The design should be conducive to dual extrusion, as that’s my main reason for asking for this.

I'm not asking you to use any existing code I've provided, but would prefer a fresh design from scratch. I would like the code to be well-commented as well. No need to use any external libraries, just standard OpenSCAD functions. Let me know if you have any questions.

[Assistant]
floor_stand.scad:
```
text1 = "DO NOT"; // always use four entries
text2 = "TOUCH";
text3 = "THE 3D";
text4 = "PRINTER";
font_size1 = 5; // [1:6]
font_size2 = 5; // [1:6]
font_size3 = 5; // [1:6]
font_size4 = 5; // [1:6]
part = "both"; // [text:Text Only,sign:Sign Only,both:Both]
print_part();

/* [hidden] */
$fn = 100; // upgrade resolution
font_style1 = "Liberation Sans:style=Bold";
font_style2 = "Liberation Sans:style=Bold";
font_style3 = "Liberation Sans:style=Bold";
font_style4 = "Liberation Sans:style=Bold";

module print_part()
{
    // text part
    if (part != "sign")
    {
        color("White")
        {
            // male side
            difference()
            {
                translate([34,20,5]) cube([48.5,34,3],center=true);
                translate([34,20,5]) cube([46.5,32,5],center=true);
            }
            translate([16,20,5]) raisedText();

            // female side
            rotate([0,0,180]) translate([15,-40,0])
            {
                difference()
                {
                    translate([34,20,5]) cube([48.5,34,3],center=true);
                    translate([34,20,5]) cube([46.5,32,5],center=true);
                }
                translate([16,20,5]) raisedText();
            }
        }
    }

    // sign part
    if (part != "text")
    {
        signMale();
        rotate([0,0,180]) translate([15,-40,0]) signFemale();
    }
}

module roundedBox(xdim, ydim, zdim, rdim)
{
    hull()
    {
        translate([rdim,rdim,0]) cylinder(h=zdim,r=rdim);
        translate([xdim-rdim,rdim,0]) cylinder(h=zdim,r=rdim);
        translate([rdim,ydim-rdim,0]) cylinder(h=zdim,r=rdim);
        translate([xdim-rdim,ydim-rdim,0]) cylinder(h=zdim,r=rdim);
    }
}

module raisedText()
{
    rotate([0,0,90]) linear_extrude(height=2)
    {
        text(text=text1, font=font_style1, halign="center", valign="center", size=font_size1);
        translate([0,-12,0]) text(text=text2, font=font_style2, halign="center", valign="center", size=font_size2);
        translate([0,-24,0]) text(text=text3, font=font_style3, halign="center", valign="center", size=font_size3);
        translate([0,-36,0]) text(text=text4, font=font_style4, halign="center", valign="center", size=font_size4);
    }
}

module signFemale()
{
    // box
    difference()
    {
        roundedBox(80,40,5,3);
        translate([68,-2,0]) rotate([0,23,0]) cube([15,44,10]);
        translate([3,10,-1]) cube([4,19,7]);
        translate([62,10,-1]) cube([9,20,7]);
        translate([48,15,-1]) cube([4,10,4]);
    }
    translate([48,15,0]) cube([2,5.5,1]);

    // notch
    rotate([0,0,180])
    {
        translate([7,-9.5,2.5]) rotate([90,0,0]) cylinder(h=21,r=1);
        translate([7,-25,0]) cube([8,10,5]);
        translate([7,-15,2.5]) rotate([90,0,0]) cylinder(h=10,r=2.5);
    }
}

module signMale()
{
    // box
    difference()
    {
        roundedBox(80,40,5,3);
        translate([68,-2,0]) rotate([0,23,0]) cube([15,44,10]);
        translate([3,10,-1]) cube([4,19,7]);
        translate([62,10,-1]) cube([9,20,7]);
        translate([10,17,-1]) cube([38,6,4]);
        translate([48,23,0]) rotate([90,0,0]) cylinder(h=6,r=3);
        translate([48,25,1.2]) rotate([90,0,0]) cylinder(h=10,r=0.7);
    }

    // arm
    difference()
    {
        translate([11,18,0]) cube([37,4,2.6]);
        translate([13,17.5,1]) cube([3,5,1.7]);
    }
    translate([48,22,1.3]) rotate([90,0,0]) cylinder(h=4,r=1.3);
    translate([48,24,1.3]) rotate([90,0,0]) cylinder(h=8,r=0.5);

    // notch
    difference()
    {
        union()
        {
            translate([-15,7,0]) cube([7,26,5]);
            translate([-8,33,2.5]) rotate([90,0,0]) cylinder(h=26,r=2.5);
        }

        translate([-15,14,-1]) cube([12,12,7]);
        translate([-8,31,2.5]) rotate([90,0,0]) cylinder(h=22,r=1.5);
    }
}

```


[User]
Okay, I'd like to create a customizable dragon egg design using OpenSCAD, similar to the one I saw on Thingiverse but with a few of my own tweaks.  The basic idea is to have a phyllotaxis pattern of shapes distributed across a roughly egg-shaped surface.

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

1.  **Phyllotaxis Angle:**  This should be an adjustable angle, with the default being around 137.51 degrees. This controls how the shapes spiral around the egg.

2.  **Shape Types:** I want two different types of shapes, which I'll call "pattern1" and "pattern2". I need to be able to choose between two basic forms for each:  "bulb" and "spike".

3.  **Pattern Frequency:** I want to control how often "pattern2" appears.  For example, I want to say "place a pattern2 shape every 3 steps" and the rest will be pattern 1.

4.  **Spike Scaling:** If either pattern is set to "spike", I need a parameter to control the height of the spikes using a scale factor, like 1, or 2, etc.  Ideally it can scale with the index, getting taller at higher indexes (further along the spiral)

5.  **Bulb Decoration:**  If either pattern is set to "bulb", I'd like a choice for its top decoration.  Options should be "hole" (a recessed circle at the top), "ball" (a small sphere on top), or "flat" (just a flat top).

6.  **Overall Size:** While I can scale the final object, I'd like parameters to control some overall base size.

7.  **Smoothness:** Control over the number of faces for the shapes, like the $fn variable.

I'm not looking for anything complex regarding a "box" or any internal space. This is purely a decorative object, similar to the one described here: [http://www.thingiverse.com/thing:1995900](http://www.thingiverse.com/thing:1995900)

I'd like a single OpenSCAD file with all these parameters. I don't think I need any external libraries for this.  Please let me know if you have any questions or require more clarification, thanks.

[Assistant]
phyllo_egg_customizer.scad:
```
/*

Phyllotaxis II : Dragon eggs

Fernando Jerez 2016

*/
// Phyllotaxis angle
angle = 137.51;

// Pattern #1
pattern1 = "bulb"; // [bulb:Bulb, spike:Spike]
// Pattern #2
pattern2 = "spike"; // [bulb:Bulb, spike:Spike]

// Draw one Pattern #2 every N steps
pattern2_every = 3;

// For spikes: Set scale factor
spikes_scale = 1;

// For bulbs: Set top decoration
bulb_type="flat"; // [hole:Hole, ball:Ball, flat:Flat ]

/* [Hidden] */

$fn = 16;
c = 2;
num = 350;
phy = angle;

scale([1,1,-1]) // flip vertical
union(){
    for(i=[0:num]){
        r = c*sqrt(i);
        sx = 2;
        sy = sx;
        sz = sx;

        rx = 0;
        ry = i*0.25;
        rz = phy*i;

        rotate([rx,ry,rz]){
            translate([r,0,0]){
                rotate([0,ry,0]){
                    translate([0,0,0])
                    scale([sx,sy,sz]){
                            rotate([0,15*cos(ry),0]){

                                    if(i%pattern2_every==0){
                                        // Pattern 2
                                        if(pattern2=="spike"){
                                            spike(i);
                                        }else{
                                            bulb(i);
                                        }

                                    }else{
                                        // pattern 1
                                        if(pattern1=="spike"){
                                            spike(i);
                                        }else{
                                            bulb(i);
                                        }
                                    }
                        }
                    }
                }
            }
        }

    }

}

// some modules for geometry
module spike(i){
    z = 1+spikes_scale*sqrt(i/num);
    scale([1,1,z])
    color("orange")

    cylinder(r1=c*0.75, r2 = c*0.1, h = c);
}

module bulb(i){
    difference(){
        cylinder(r1=c*0.8,r2 = c*0.3, h = c*0.5,$fn=15);

        if(bulb_type=="hole"){
            translate([0,0,c*0.2])
            cylinder(r1=c*0,r2=c*0.3,h=c*0.5,$fn = 6);

        }

    }
    if(bulb_type=="ball"){
        translate([0,0,c*0.5])
        //cylinder(r1=c*0,r2=c*0.3,h=c*0.5,$fn = 6);
        sphere(r = c*0.25, $fn=10);
    }

}
```


[User]
I'm looking to create a parametric design for a Yagi Uda antenna element holder, something that can be 3D printed. I've seen a few designs, but I want one that's fully customizable without using screws. It should use snap-fit joints instead. I want to be able to adjust things like the boom and element diameters, the distance between them, and the overall width of the part. Also, I want to be able to choose between different types of element attachment: a down, mid, and up style attachment, or a combination of all of them. I'd also like to have a space for a label text and some control over the kind of plastic it’s made of so I can adjust the snap fit tolerance.

Here's a more detailed breakdown of what I need:

**Core Structure:**

*   The basic shape should be a sort of rectangular block with holes for the boom and the antenna element. The main body should be adjustable in width based on a given factor (WidthFactor).
*   I need to control the Boom Diameter (BD), Element Diameter (ED), and Boom Element Distance (BED).
*   There should be a parameter for the overall length of the part based on the boom and element distances and their diameters.
*   The shape of the boom and element holes should have adjustable polygon counts (Boom_Shape, Elem_Shape).

**Element Attachment:**

*   I want to select from different element attachment configurations:
    *   **Down:** element attachment at the "bottom" of the boom.
    *   **Mid:** element attachment at the "middle" of the boom.
    *  **Up:** element attachment at the "top" of the boom.
    *   **All 1:** shows all of the attachment points on one object, good for demo
    *   **All 2:** shows all of the attachment points on separate objects, good for printing
*   The attachment should be a snap-fit joint. I want to use the parametric design principles from the "Simple Snap-Fit Joints Library" by "Whistle_blower" on Thingiverse. This will involve calculating the appropriate size and depth of the snap-fit features based on material properties (elongation at break).

**Material Properties:**

*   I need a parameter for plastic type (PT) to adjust snap-fit tolerances. I want to be able to choose between PLA, ABS, and PETG so it can calculate the appropriate elongation-at-break automatically.

**Other Features:**

*   A text label should be optional on the model. It should be configurable with a text string (Label) and its size (LabelSize) and spacing (LabelSpace) should be adjustable relative to the rest of the body.
*   I want to be able to add a window to the element hole (WinSpace).

**OpenSCAD Specifics**

*   I'd like the design to be fully parametric, with all dimensions driven by variables.
*   I'm assuming you'll create the snap fit using linear extrudes of custom polygons for the snap features themselves.
*   I'm also assuming that you'll use the minkowski function for smoothing.
* I'd like the code to use modules, that are defined with clear names, and well commented.

Could you generate the OpenSCAD files for this design? I don't need any external libraries aside from the ones you need to generate the snap-fit, so you don't need to worry about including files for those.

[Assistant]
YagiUdaPlastic_1.0.scad:
```
/*
 All Plastic Yagi Uda Element Holder on
 http://www.thingiverse.com/thing:1997494
 by fpetrac

*/

/* [EleJoinMode] */
EleType=0; //[1:down, 2:mid, 3:up, 4:all_1, 5:all_2]

/* [Element options] */
//boom diameter
BD=20;
//element diameter
ED=8;
//boom element distance
BED=3;
//width factor of the part
WidthFactor=1; //[0.7,1,1.2,1.5,2]
//size of the window on element (set to 0 to disable)
WinSpace=0;

/* [Text options] */
Label= "YUEHP"; //text

/* [Plastic Type] */
//Elongation at break factor
PT=1; //[1:PLA, 2:ABS, 3:PETG]

/* [Shape] */
//Shape of Boom (number of edge)
Boom_Shape=32; //[3,4,6,8,16,32,64,128]
//Shape of Element (number of edge)
Elem_Shape=64; //[3,4,6,8,16,32,64,128]
$fn=64; //num of polygons

/* [Main body] */
BEdistance=BD/2+ED/2+BED; //Boom Element distance
MbW=WidthFactor*BD*2; //width of the part
MbH=BD+ED; //heigth of the part
MbL=(BD+ED)+3*BEdistance; // lenght of the part

//Text size incrase of from 0 no text to 14 max size
LabelSize = MbW/12;
//Spacing on text
LabelSpace = 1.2*1;

BSnapH=BD/4;
BSnapL=(2*BEdistance+BD)/4;
ESnapH=ED/2;
ESnapL=(2*BEdistance+ED)/4;

module printEle(EleType){
    yB=Ysnap(BSnapL,BSnapH,1);
    if(EleType==1)
        rotate([0,0,-90])translate([-BEdistance/2,0,MbH/2])YUEdown();
    else if(EleType==2)
        rotate([0,0,-90])translate([-BEdistance/2,0,MbH/2-2*yB])YUEmid();
    else if(EleType==3)
       rotate([0,0,-90])translate([BEdistance/2,0,MbW/2])rotate([90,0,0]) YUEup();
    else if(EleType==4)
        Demo(1);
    else if(EleType==5)
        Demo(0);
}
printEle(EleType);
module Demo(type=1){
    if(type==1){
        translate([0,0,MbH]) YUEdown();YUEmid();translate([0,MbW]) YUEup();}
    else{
        color( "blue", 0.5 ) YUEdown();
        color( "red", 0.5 ) YUEmid();
        color( "green", 0.5 )YUEup();
        }
}
//Demo(1);

module BoomSnap(){
    l=BSnapL;
    h=BSnapH;
    a=30;
    b=MbH;
    y=Ysnap(l,h,1);
    for(f=[0,1]) mirror([0,f,0])translate([BEdistance/2,-MbW/2+h,-b/2])
        SnapY(l,h,a,b);

}
module BoomSnapHole(){
    l=BSnapL;
    h=BSnapH;
    a=30;
    b=2*MbH;
    y=Ysnap(l,h,1);
    for(f=[0,1]) mirror([0,f,0])translate([BEdistance/2,-MbW/2+h,-b/2])
        SnapHole(l,h,a,b,4);

    //union(){        translate([0,-MbW,0])cube([l,MbW,b],center=false);translate([l,-MbW,0])cube([MbL,MbW+y,b],center=false);          }
}

module ElementSnap(){
    l=ESnapL;
    h=ESnapH;
    a=30;
    b=MbW;
    y=Ysnap(l,h,1);
    for(f=[0,1])
        mirror([0,0,f])
            translate([-BEdistance/2,b/2,-MbH/2+h])
                rotate([90,0,0])SnapY(l,h,a,b);
}
module ElementSnapHole(){
    l=ESnapL;
    h=ESnapH;
    a=30;
    b=2*MbL;
    y=Ysnap(l,h,1);
    hmax=MbL;  //riporta le quote per la stampa
    for(f=[0,1])
            mirror([0,0,f])
                translate([-BEdistance/2,b/2,-MbH/2+h])
                    rotate([90,0,0])
                        SnapHoleQ(l,h,a,b,4,6);
}
//ElementSnap();

module YUEdown(){
    difference(){
        baseDOWN();
        union(){
            BoomSnapHole();//Snap hole
            translate([BEdistance/2,0,0]) rotate([0,0,45]) cylinder(2*MbH,d=BD,center=true, $fn=Boom_Shape); //boom hole
            translate([2*BSnapL-1,0,0])
                rotate([90,0,90])
                    linear_extrude(height = 3, center = true, convexity = 10, twist = 0) text(Label, size=LabelSize, font="Liberation Sans:style=Bold",halign="center", valign="center",spacing=LabelSpace );//label
        }
   }
}

module YUEmid(){

    difference(){
        union(){
        baseMID();
        BoomSnap();
        }
        union(){
             translate([BEdistance/2,0,0]) rotate([0,0,45]) cylinder(2*MbH,d=BD,center=true, $fn=Boom_Shape); //boom hole
             rotate([90,0,0]) translate([-BEdistance/2,0,0]) cylinder(2*MbW, d=ED, center=true,$fn=Elem_Shape); //el hole
            ElementSnapHole();

        }
    }
}
//YUEmid();

module YUEup(){
tollBhole=1.05; //5%
    difference(){
        union(){
           ElementSnap();
           baseUP();
        }
         union(){
             translate([BEdistance/2,0,0]) rotate([0,0,45]) cylinder(2*MbH,d=BD*tollBhole,center=true, $fn=Boom_Shape); //boom hole
             union(){
                 rotate([90,0,0]) translate([-BEdistance/2,0,0]) cylinder(2*MbW, d=ED, center=true,$fn=Elem_Shape);//element hole            //translate([-BEdistance/2-MbL/2,0,0])cube([MbL,WinSpace,MbH+2],true);//window
                translate([-BEdistance/2-WinSpace/2,0,0])cylinder(d=WinSpace,h=MbH+2,center=true,$fn=Elem_Shape);//
                translate([-MbH-BEdistance-WinSpace,0,0]/2)cube([MbH,WinSpace,MbH+2],center=true);
             }
                 }
    }
}
//YUEup();
module base(){
    minkowski(){
        cube([MbL-14,MbW-14,MbH],true);
        cylinder(h=.01,d=14);
        }
}

module baseUP(){
    l=2*BEdistance+ED/2;
    difference(){
        minkowski(){
            cube([l-14,MbW-14,MbH],true);
            cylinder(h=.01,d=14);
        }
        union(){
            translate([MbL/2-BEdistance/2,0,0])cube([MbL,2*MbW,2*MbH],true);
        }
    }
}
//baseUP();

module baseMID(){
    difference(){
        minkowski(){
        cube([MbL-14,MbW-14,MbH],true);
        cylinder(h=.01,d=14);
        }
        union(){
            translate([MbL/2+BEdistance/2,0,0])
                cube([MbL,2*MbW,2*MbH],true);
            translate([-MbL/2-BEdistance/2,0,0])
                cube([MbL,2*MbW,2*MbH],true);
        }
    }
}
module baseDOWN(){
    l=4*BSnapL; //2*BEdistance+BD;
    difference(){
        minkowski(){
        cube([l-14,MbW-14,MbH],true);
        cylinder(h=.01,d=14);
        }
        translate([-MbL/2+BEdistance/2,0,0])
            cube([MbL,2*MbW,2*MbH],true);
    }
}

///lib start

eps= PT==1 ? 0.5*6/100 : PT==2 ? 0.5*12/100 : 0.5*18/100;
/*
//
eps=0.5*6/100;//Elongation at break of PLA=6%
eps=0.5*12/100;//Elongation at break of ABS=12%
eps=0.5*18/100;//Elongation at break of PETG=18%
*/

echo(eps);
function Hsnap(l,y,f)= (1.09/f)*(eps*pow(l,2))/(y);
function Ysnap(l,h,f)= (1.09/f)*(eps*pow(l,2))/(h);

//SnapH(l,y,a,b,f=1) Define y calculate h and divide the calculte h value to a factor f
module SnapH(l,y,a,b,f=1)
{
    h=Hsnap(l,y,f);
    p=y;
    echo("h is",h);
linear_extrude(height = b, center = f, convexity = 10, twist = 0)
polygon([[0,0],[l,0],[l,y],[l+p,y],[l+p+(y+h/4)/tan(a),-h/4],[l,-h/2],[0,-h]]);
}
//SnapY(l,h,a,b,f=1) Define h calculate y and divide the calculte y value to a factor f
module SnapY(l,h,a,b,f=1)
{
    y=Ysnap(l,h,f);
    p=y;
    echo("y is", y);
linear_extrude(height = b, center = f, convexity = 10, twist = 0)
polygon([[0,0],[l,0],[l,y],[l+p,y],[l+p+(y+h/4)/tan(a),-h/4],[l,-h/2],[0,-h]]);
}

module SnapHole(l,h,a,b,Pr=2){
        //%SnapY(l,h,a,b);
        //hole
        y=Ysnap(l,h,1);
        YY=Pr*h;//profondità Y;
        XX=1.1*(y+(y+h/4)/tan(a)); //Altezza totale +10%
        ZZ=0+b; //largezza piu tolleranza
        union(){
        translate([0,-YY,(b-ZZ)/2])cube([l,YY,ZZ],center=false); //gambo
        translate([l,-YY,(b-ZZ)/2])cube([XX,YY+y,ZZ],center=false);//testa
        }
 }
 //SnapHole(15,5,25,5);
module SnapHoleQ(l,h,a,b,Pr=2,Q=4){
        //%SnapY(l,h,a,b);
        //hole
        y=Ysnap(l,h,1);
        YY=Pr*h;//profondità Y;
        XX=1.1*(y+(y+h/4)/tan(a)); //Altezza totale +10%
        ZZ=0+b; //largezza piu tolleranza
        union(){
            translate([0,-YY,(b-ZZ)/2])cube([Q*l,YY,ZZ],center=false); //gambo
            translate([l,-YY,(b-ZZ)/2])cube([XX,YY+y,ZZ],center=false);//testa
        }
 }
//!SnapHoleQ(15,5,25,5);
 //lib end
```


[User]
Okay, I'm looking to have an OpenSCAD design generated for a customizable pocket hole jig. I've been using a design I found online (and have included as a reference below) but it has some limitations. I'd like the new design to be fully parametric, allowing me to easily adjust dimensions for different material thicknesses and screw sizes.

Here are the key features I need in the new design:

1.  **Material Thickness:** The jig should be adjustable for various material thicknesses. I need to be able to specify the thickness of the wood I'm working with, the thickness of the jig's clamping plate, and the desired depth the screw should penetrate the target material. This last value won't actually change the jig itself but is useful for the calculation of the required collar set point for the drill bit.

2.  **Drill Size:** I need to specify the drill bit diameter to make sure the jig works with the correct hole size.

3.  **Hole Spacing:** The distance between the two pocket holes should be adjustable.

4.  **Total Channel Length:** The overall length of the angled channel that guides the drill bit needs to be adjustable.

5.  **Angle:** I need to be able to adjust the pocket hole angle.

6.  **Metal Inserts:** The design should include holes that are sized for copper couplings for the metal inserts, but the dimensions of those holes should be controlled by their own parameters, in case I want to use different inserts.

7.  **Units:** I need the ability to specify dimensions in either inches or millimeters, and the text on the jig should reflect this.

8. **Collar Position Text:** There needs to be a label on the jig showing the collar position so I can easily set up my drill bit. There also needs to be text indicating the total length for easy reference.

9.  **Additional Features:** The design should also include:
    *   A hole for hanging the jig.
    *   A hole to store a 2.5mm hex key.
    *   A bevel on the front edge to compensate for first layer printing issues.
    *   Finger grips along the sides.
    *   A small dust hole for removing debris.
    *   A simple label with "3D.RTCONS.COM" on the side (not critical, but helpful).

I'd like to keep the overall shape of the jig somewhat similar to the reference I'm providing, with the clamping plate running along the top and the channel for the drill bit going at an angle. I'm not too worried about optimization of the 3d print settings, but it does need to be printable without supports.

I would like this to be written entirely from scratch; I don't need any modifications to the code I provided.

Here is the reference SCAD file, it isn't required for you to look at it but I included it for context:

```
/* [Basic] */
thickness=0.75;
units="inch";//[inch,mm]
drillsize=0.375;
platethick=0.5;
woodremain=0.625;

/* [Advanced] */
angle=15; //[10:45]
holespacing=1;
th=0.125;
totallength=4;
bump=0.125;
collarod=0.438;
collarlen=0.7;

/* [hidden] */
inmm=25.4;
cf=units=="inch"?inmm:1;
tl=totallength-bump;
unittext=units=="inch"?"in":"mm";
maxh=sin(angle)*totallength*cf;
//Hex key is 2.5mm, 2.71 diameter
//56mm long
//20.3mm across
//Radiused at about 5mm

//Eyeline
if(0){
translate([-50,0,-(thickness/2)*cf]){
  rotate([0,90,0]){
    cylinder(100,1,1);
}}
}

collarset=totallength-woodremain;

//rotate([angle,0,0]){cylinder(1000,5,5,$fn=120);}
//tl is the distance from the end of the collar to where the wood comes out.
//For 3/4 to 3/4, Kreg recommends 1 1/4 (32mm) screws.
//Screws to penetrate to a depth of 0.622" or 15.8mm
//That is 16.4mm of the screw. Let's call it 1/2 so need approximately
//5/8 of the material remaining.
//
//Note, seems approximately you want half the screw in each piece as long as that means the screw would not exit the target material.

//            translate([0,-(drillsize+th*2)*cf,tl*cf])rotate([90,0,0]){
//              scale(1)text(str(round(100*collarset)/100,units));
            //}
//union(){
intersection(){
//  union(){
  difference(){
    union(){
      translate([0,0,-thickness*cf/2]){

        rotate([-90+angle,0,0]){
//          union(){
          difference(){
            translate([-cf*(th*2+drillsize+holespacing)/2,-(drillsize*cf/2+th*cf),0]){
              cube([cf*(th*2+drillsize+holespacing),tan(angle)*totallength*cf,tl*cf]);

            }
            //Collar position text
            translate([-cf*(th*2+drillsize+holespacing)/2+1,-(drillsize/2+th)*cf+1,tl*cf-22])rotate([90,0,0]){
              linear_extrude(2)text(str("C ",round(100*collarset)/100,unittext),5);
            }
            //Total length text
            translate([-cf*(th*2+drillsize+holespacing)/2+1,-(drillsize/2+th)*cf+1,tl*cf-13])rotate([90,0,0]){
              linear_extrude(2)text(str("L ",totallength,unittext),5);
            }

        }

        //Collar1
        translate([holespacing/2*cf,0,0]){
          cylinder(tl*cf+bump*cf,drillsize*cf/2+th*cf,drillsize*cf/2+th*cf,$fn=24);
        }
        //Collar2
        translate([-holespacing/2*cf,0,0]){
          cylinder(tl*cf+bump*cf,drillsize*cf/2+th*cf,drillsize*cf/2+th*cf,$fn=24);
        }

        }
      }
      //Clamp plate
      translate([-cf*(th*2+drillsize+holespacing)/2,0,0]){
       cube([cf*(th*2+drillsize+holespacing),tl*cf*cos(angle)-(th+drillsize/2)*cf*sin(angle),platethick*cf]);
      }

    }
    translate([0,0,-thickness*cf/2]){
      rotate([-90+angle,0,0]){
        //Hole1
        translate([holespacing/2*cf,0,0]){
          cylinder(totallength*cf*1.1,drillsize*cf/2,drillsize*cf/2,$fn=24);
        }
        //Hole2
        translate([-holespacing/2*cf,0,0]){
          cylinder(totallength*cf*1.1,drillsize*cf/2,drillsize*cf/2,$fn=24);
        }
        //Metal1
        translate([holespacing/2*cf,0,(tl+bump-collarlen)*cf]){
          cylinder(collarlen*cf+0.01,collarod/2*cf,collarod/2*cf,$fn=24);
        }
        //Metal2
        translate([-holespacing/2*cf,0,(tl+bump-collarlen)*cf]){
          cylinder(collarlen*cf+0.01,collarod/2*cf,collarod/2*cf,$fn=24);
        }

      }
    }
//    translate([-500,-500,-1000]){cube([1000,1000,1000]);}
    //hanger
    translate([0,6,0])cylinder(maxh,2,2,$fn=12);

    //Finger grips
    translate([-cf*(th*2+drillsize+holespacing)/2-1,20,0])cylinder(maxh,2,2,$fn=12);
    translate([-cf*(th*2+drillsize+holespacing)/2-1,25,0])cylinder(maxh,2,2,$fn=12);
    translate([-cf*(th*2+drillsize+holespacing)/2-1,30,0])cylinder(maxh,2,2,$fn=12);
    translate([-cf*(th*2+drillsize+holespacing)/2-1,35,0])cylinder(maxh,2,2,$fn=12);

    //Finger grips
    translate([cf*(th*2+drillsize+holespacing)/2+1,20,0])cylinder(maxh,2,2,$fn=12);
    translate([cf*(th*2+drillsize+holespacing)/2+1,25,0])cylinder(maxh,2,2,$fn=12);
    translate([cf*(th*2+drillsize+holespacing)/2+1,30,0])cylinder(maxh,2,2,$fn=12);
    translate([cf*(th*2+drillsize+holespacing)/2+1,35,0])cylinder(maxh,2,2,$fn=12);

    //Bevel
    translate([-cf*(th*2+drillsize+holespacing)/2-2,-1,2])rotate([-135,0,0])cube([cf*(th*2+drillsize+holespacing)+4,4,4]);

    //Dust hole
    translate([-cf*(drillsize+holespacing)/2,(tl*cf*cos(angle)-(th+drillsize/2)*cf*sin(angle))*0.45,platethick*cf/2]){
    cube([cf*(drillsize+holespacing),10,maxh]);
    }

    //Hex holder
    translate([-cf*(th*2+drillsize+holespacing)/2-2,10,5]){
      rotate([0,90,0])cylinder(cf*(th*2+drillsize+holespacing)+4,2.75/2,2.75/2,$fn=12);
    }

    //Vanity
                translate([cf*(th*2+drillsize+holespacing)/2-2,15,platethick*cf-1])rotate([0,0,180]){
              linear_extrude(2)text("3D.RTCONS.COM",3);
            }

  }
  translate([-cf*(th*2+drillsize+holespacing)/2-2,0,0]){cube([cf*(th*2+drillsize+holespacing)+4,totallength*1.2*cf,maxh]);}
}

```

Thanks!

[Assistant]
jig.scad:
```
/* [Basic] */
thickness=0.75;
units="inch";//[inch,mm]
drillsize=0.375;
platethick=0.5;
woodremain=0.625;

/* [Advanced] */
angle=15; //[10:45]
holespacing=1;
th=0.125;
totallength=4;
bump=0.125;
collarod=0.438;
collarlen=0.7;

/* [hidden] */
inmm=25.4;
cf=units=="inch"?inmm:1;
tl=totallength-bump;
unittext=units=="inch"?"in":"mm";
maxh=sin(angle)*totallength*cf;
//Hex key is 2.5mm, 2.71 diameter
//56mm long
//20.3mm across
//Radiused at about 5mm

//Eyeline
if(0){
translate([-50,0,-(thickness/2)*cf]){
  rotate([0,90,0]){
    cylinder(100,1,1);
}}
}

collarset=totallength-woodremain;

//rotate([angle,0,0]){cylinder(1000,5,5,$fn=120);}
//tl is the distance from the end of the collar to where the wood comes out.
//For 3/4 to 3/4, Kreg recommends 1 1/4 (32mm) screws.
//Screws to penetrate to a depth of 0.622" or 15.8mm
//That is 16.4mm of the screw. Let's call it 1/2 so need approximately
//5/8 of the material remaining.
//
//Note, seems approximately you want half the screw in each piece as long as that means the screw would not exit the target material.

//            translate([0,-(drillsize+th*2)*cf,tl*cf])rotate([90,0,0]){
//              scale(1)text(str(round(100*collarset)/100,units));
            //}
//union(){
intersection(){
//  union(){
  difference(){
    union(){
      translate([0,0,-thickness*cf/2]){

        rotate([-90+angle,0,0]){
//          union(){
          difference(){
            translate([-cf*(th*2+drillsize+holespacing)/2,-(drillsize*cf/2+th*cf),0]){
              cube([cf*(th*2+drillsize+holespacing),tan(angle)*totallength*cf,tl*cf]);

            }
            //Collar position text
            translate([-cf*(th*2+drillsize+holespacing)/2+1,-(drillsize/2+th)*cf+1,tl*cf-22])rotate([90,0,0]){
              linear_extrude(2)text(str("C ",round(100*collarset)/100,unittext),5);
            }
            //Total length text
            translate([-cf*(th*2+drillsize+holespacing)/2+1,-(drillsize/2+th)*cf+1,tl*cf-13])rotate([90,0,0]){
              linear_extrude(2)text(str("L ",totallength,unittext),5);
            }

        }

        //Collar1
        translate([holespacing/2*cf,0,0]){
          cylinder(tl*cf+bump*cf,drillsize*cf/2+th*cf,drillsize*cf/2+th*cf,$fn=24);
        }
        //Collar2
        translate([-holespacing/2*cf,0,0]){
          cylinder(tl*cf+bump*cf,drillsize*cf/2+th*cf,drillsize*cf/2+th*cf,$fn=24);
        }

        }
      }
      //Clamp plate
      translate([-cf*(th*2+drillsize+holespacing)/2,0,0]){
       cube([cf*(th*2+drillsize+holespacing),tl*cf*cos(angle)-(th+drillsize/2)*cf*sin(angle),platethick*cf]);
      }

    }
    translate([0,0,-thickness*cf/2]){
      rotate([-90+angle,0,0]){
        //Hole1
        translate([holespacing/2*cf,0,0]){
          cylinder(totallength*cf*1.1,drillsize*cf/2,drillsize*cf/2,$fn=24);
        }
        //Hole2
        translate([-holespacing/2*cf,0,0]){
          cylinder(totallength*cf*1.1,drillsize*cf/2,drillsize*cf/2,$fn=24);
        }
        //Metal1
        translate([holespacing/2*cf,0,(tl+bump-collarlen)*cf]){
          cylinder(collarlen*cf+0.01,collarod/2*cf,collarod/2*cf,$fn=24);
        }
        //Metal2
        translate([-holespacing/2*cf,0,(tl+bump-collarlen)*cf]){
          cylinder(collarlen*cf+0.01,collarod/2*cf,collarod/2*cf,$fn=24);
        }

      }
    }
//    translate([-500,-500,-1000]){cube([1000,1000,1000]);}
    //hanger
    translate([0,6,0])cylinder(maxh,2,2,$fn=12);

    //Finger grips
    translate([-cf*(th*2+drillsize+holespacing)/2-1,20,0])cylinder(maxh,2,2,$fn=12);
    translate([-cf*(th*2+drillsize+holespacing)/2-1,25,0])cylinder(maxh,2,2,$fn=12);
    translate([-cf*(th*2+drillsize+holespacing)/2-1,30,0])cylinder(maxh,2,2,$fn=12);
    translate([-cf*(th*2+drillsize+holespacing)/2-1,35,0])cylinder(maxh,2,2,$fn=12);

    //Finger grips
    translate([cf*(th*2+drillsize+holespacing)/2+1,20,0])cylinder(maxh,2,2,$fn=12);
    translate([cf*(th*2+drillsize+holespacing)/2+1,25,0])cylinder(maxh,2,2,$fn=12);
    translate([cf*(th*2+drillsize+holespacing)/2+1,30,0])cylinder(maxh,2,2,$fn=12);
    translate([cf*(th*2+drillsize+holespacing)/2+1,35,0])cylinder(maxh,2,2,$fn=12);

    //Bevel
    translate([-cf*(th*2+drillsize+holespacing)/2-2,-1,2])rotate([-135,0,0])cube([cf*(th*2+drillsize+holespacing)+4,4,4]);

    //Dust hole
    translate([-cf*(drillsize+holespacing)/2,(tl*cf*cos(angle)-(th+drillsize/2)*cf*sin(angle))*0.45,platethick*cf/2]){
    cube([cf*(drillsize+holespacing),10,maxh]);
    }

    //Hex holder
    translate([-cf*(th*2+drillsize+holespacing)/2-2,10,5]){
      rotate([0,90,0])cylinder(cf*(th*2+drillsize+holespacing)+4,2.75/2,2.75/2,$fn=12);
    }

    //Vanity
                translate([cf*(th*2+drillsize+holespacing)/2-2,15,platethick*cf-1])rotate([0,0,180]){
              linear_extrude(2)text("3D.RTCONS.COM",3);
            }

  }
  translate([-cf*(th*2+drillsize+holespacing)/2-2,0,0]){cube([cf*(th*2+drillsize+holespacing)+4,totallength*1.2*cf,maxh]);}
}

```


[User]
Okay, I'm working on a project that uses 2020 aluminum extrusion and I need a versatile bracket for mounting an Arduino Mega.  I want to be able to easily access the USB and power connectors once it's mounted. I'd also like the bracket to be parametric so I can easily adjust it for different sized extrusions in the future and potentially different Arduino boards.

I have an existing design in mind, and I'll describe it in detail. I need a base plate that mounts to the side of the extrusion, with standoffs that the Arduino Mega's mounting holes can rest on. I'd also like some braces connecting the standoff to the base. The holes in the standoffs should be sized for self-tapping M3 screws. And most importantly, the bracket should be offset from the extrusion such that the Arduino’s connectors are easily accessible. The extrusion mounting holes should also be parametric.

Here's a breakdown of the parameters I need:

*   **`extrusion_size`**: The size of the extrusion (e.g., 20 for 2020, 15 for 1515, etc.). This should drive the overall width and offset of the bracket.
*   **`brace_width`**: The width of the braces supporting the Arduino.
*   **`attach_thick`**:  The thickness of the mounting plate that attaches to the extrusion.
*   **`screw_dia`**: The diameter of the screws used to mount to the extrusion.
*  **`support_dia`**: The diameter of the standoffs for the Arduino mounting holes.
*  **`wall_thick`**: The wall thickness of the overall bracket.
*   **`support_h`**: Height of the standoffs
*  **`arduino_width`** and **`arduino_length`**: Dimensions of the Arduino board itself. (Can start with the Mega, but these should be adjustable). I think the Mega's width is about 53 mm and length is about 102.
*   **`usb_offset`** and **`power_offset`**: The x coordinate (relative to the origin in the back left corner of the board) of the Arduino's USB and power connectors. These offsets should determine the position of the open face of the bracket relative to the extrusion. I think the USB is roughly 14mm from the left edge and the power connector is roughly 97 mm.

The mounting holes on the Arduino should be positioned based on the provided coordinates in the original code, with those offsets to the edge of the board, if possible.

I'd like the code to use the BOSL library if that's alright, just because it seems like a popular way to do parameterization in OpenSCAD. The main things I'd need from BOSL are the parameter handling modules/functions. I'm not asking you to use anything else.

Could you generate an OpenSCAD file for this? I'm okay with it being multiple files if needed. Let me know if you need anything else from me.

[Assistant]
arduino_mega.scad:
```
// Arduino Mega / 2020 mount
// Designed by Marius Gheorghescu, December 2017

// thickness of the braces
brace_width = 2.4;

// thickness of the attachment pads
attach_thick = 3;

// extrusion size in mm
extrusion_size = 20;

// mount screw diameter (use 3.3 for M3, 4.3 for M4, 6.75 for 1/4-20)
screw_dia = 3.3;

/* [Advanced] */

support_dia = 5.0;

/* [Hidden] */

wall_thick = extrusion_size-5;

support_h = wall_thick+3;

epsilon = 0.01;
$fn=50;

module nub(neg=0)
{
    translate([0,0,support_h/2])
    if (neg)
        cylinder(r=2.6/2, h=support_h+epsilon, center=true);
    else
        cylinder(r=support_dia/2, h=support_h, center=true);
}

module holes(neg)
{
    translate([13.97, 2.54, 0]) nub(neg);
    translate([15.24, 50.8, 0]) nub(neg);

    translate([66.04, 7.62, 0]) nub(neg);
    translate([66.04, 35.56, 0]) nub(neg);

    translate([90.17, 50.8, 0]) nub(neg);
    translate([96.52, 2.54, 0]) nub(neg);
}

module plate()
{
    translate([14, 53/2,0])
        cube([brace_width, 53, wall_thick], center=true);

    translate([66, 53/2,0])
        cube([brace_width, 53, wall_thick], center=true);

    translate([96.5 + support_dia/2, 53/2,0])
        cube([brace_width, 53, wall_thick], center=true);

    translate([(96.5++ support_dia/2)/2, brace_width/2, 0])
        cube([96.5 + support_dia/2, brace_width, wall_thick], center=true);

    translate([(96.5 + support_dia/2)/2, 53 - brace_width/2,0])
        cube([96.5 + + support_dia/2, brace_width, wall_thick], center=true);

}

module mega()
{
    difference() {
        union() {
            holes();
            translate([0,0,wall_thick/2])
                plate();
        }

        holes(1);
    }
}

difference() {
    union() {

        translate([0, -53/2, -extrusion_size/2])
        mega();

        translate([-attach_thick/2,0,0])
            cube([attach_thick, 53, extrusion_size], center=true);

        translate([extrusion_size/2 - attach_thick, 0, -extrusion_size/2 + attach_thick/2])
            cube([extrusion_size, 53, attach_thick], center=true);
    }

    translate([0,15,0])
    rotate([0,90,0])
        cylinder(r=screw_dia/2, h=500, center=true);

    translate([0,-15,0])
    rotate([0,90,0])
        cylinder(r=screw_dia/2, h=500, center=true);

    translate([extrusion_size/2 - attach_thick, 15,0])
        cylinder(r=screw_dia/2, h=100, center=true);

    translate([extrusion_size/2 - attach_thick, -15,0])
        cylinder(r=screw_dia/2, h=100, center=true);

}
```