[User]
I'd like a customizable cactus model in OpenSCAD, similar to the style of thing:1052477, but with parameters for all the dimensions.

Specifically, I'd like to be able to control these things:

*   **Trunk:**
    *   The total length of the trunk, excluding the rounded top.
    *   The radius of the rounded top of the trunk.
    *   The thickness of the entire cactus.

*   **Left Arm:**
    *   The length of the left arm.
    *   The width of the left arm.
    *   The horizontal distance of the left arm from the main trunk.
    *   The vertical position of the left arm on the trunk
    *   The direction of the arm's curve - it should be able to curve backwards as well.

*   **Right Arm:**
    *   The length of the right arm.
    *   The width of the right arm.
    *   The horizontal distance of the right arm from the main trunk.
    *   The vertical position of the right arm on the trunk.
    *   The direction of the arm's curve - it should be able to curve backwards as well.

The arms should be made with a rectangular section and a quarter circle at each end, smoothly joined to the main trunk.

I'm fine with it being 2D and extruded, so just generate one .scad file for the entire design. I don't need to use any libraries for this.

[Assistant]
cactus.scad:
```

/* [Left Arm]*/
// arm length
leftLength=8;
// arm width
leftWidth=8;
// from trunk to arm
leftGap=3;
// quadrant of quarter circle
leftQuad=2;
// up from the bottom
leftUp=10;

/*[Trunk]*/
// Trunk Length excluding Radius of the top
trunkL=40;
// Radius of the top
trunkW=10;
// thickness of cactus
trunkT=5;

/*[Right Arm]*/
// arm length
rightLength=8;
// arm width
rightWidth=7;
// from trunk to arm
rightGap=2;
// quadrant of quarter circle
rightQuad=1;
// up from the bottom
rightUp=15;

cactus();//like thing:1052477 but customizable

module cactus(){
	linear_extrude(height=trunkT){
		translate([-rightUp, trunkW/2,0])
		arm(l=rightLength, w=rightWidth, g=rightGap, q=rightQuad);
		translate([-leftUp, -trunkW/2,0])
		arm(l=leftLength, w=leftWidth, g=leftGap, q=leftQuad);

		translate([-trunkL, -trunkW/2]){
			square([trunkL, trunkW]);
			translate([0, trunkW/2])
			circle(d=trunkW);
		}
	}
}

module arm(l=12, w=5, g=2, q=1, t=8){
	q1= q==1 ? 0:-1;
	q2= q==2 ? -1:1;//q=quadrand 1 or 2

	translate([-l-w, q2*w/2+q2*g])
	circle(r=w/2);

	translate([-l-w, q1*w+(q2*g)])//[-l-w, q1*w+(q2*g)]
	square([l, w]);

	translate([-w, g*q2])
	qCircle(r=w, q=q);

	translate([-w,g*q1])
	square([w, g]);
}

module qCircle(r=10, q=1){//q=quadrant 1, 2, 3 or 4
	rotate(-(q-1)*90)
	difference(){
		circle(r=r);
		translate([-r-1,-r-1])
		square([r+1, r*2+2]);
		translate([0,-r-1])
		square([r+2,r+1]);
	}
}

```


[User]
Hi there! I'm looking to create some transition adapters for model rocket tubes, and I'd like a parametric OpenSCAD design that can generate these. The basic idea is to have a tapered section that connects a larger tube to a smaller tube, and then each of those ends has a short section where the tube diameter is consistent to allow for smooth connections.

Here are the parameters I think I need:

*   **`tube_1`**: The outer diameter of the larger tube. I'd like to be able to specify this using standard Estes rocket tube sizes, like 13.8, 18.7, 24.8, 33.7, 34.2, 41.6, 56.3, 66.04, and 100 (corresponding to BT-5, BT-20, BT-50, BT-55, BT-56, BT-60, BT-70, BT-80, and BT-101 respectively), but the code should be able to handle any valid positive value.
*   **`tube_2`**: The outer diameter of the smaller tube. This should also accept the same standard Estes tube sizes, and any positive value.
*   **`taper_length`**: The length of the tapered section. I'd like to be able to specify this in millimeters.
*   **`hole`**: The diameter of a central hole through the adapter, also in millimeters. If I set this to 0, I don't want any hole. This should default to 0 and be smaller than `tube_2`.
*  **`wall_1`**: This should be a variable that represents the wall thickness for tube_1 and should default to 0.33mm for tube_1 values of 13.8, 18.7, or 24.8 and 0.53 for all other values. This should not be user configurable.
*  **`wall_2`**: This should be a variable that represents the wall thickness for tube_2 and should default to 0.33mm for tube_2 values of 13.8, 18.7, or 24.8 and 0.53 for all other values. This should not be user configurable.

The design should include:

1.  A tapered cylinder connecting the two tube diameters.
2.  A short cylindrical section at the larger end with a consistent diameter equal to `tube_1` less `wall_1`, extending 12.7mm from the taper.
3.  A short cylindrical section at the smaller end with a consistent diameter equal to `tube_2` less `wall_2`, extending 12.7mm from the taper.
4.  An optional through-hole of diameter `hole`, going all the way through.

I'd prefer that the design uses $fn=100$ for all circular objects to make sure the curves are nice. It'd be useful if the output was also in a single .scad file to make it easy to work with. I don't need to use any external libraries for this.

[Assistant]
Transition_Adapter.scad:
```
//All measurements are in millimeters.

//Size of larger tube?
tube_1 = 33.7; //[13.8:BT-5, 18.7:BT-20, 24.8:BT-50, 33.7:BT-55, 34.2:BT-56, 41.6:BT-60, 56.3:BT-70, 66.04:BT-80, 100:BT-101]

//Size of smaller tube?
tube_2 = 13.8; //[13.8:BT-5, 18.7:BT-20, 24.8:BT-50, 33.7:BT-55, 34.2:BT-56, 41.6:BT-60, 56.3:BT-70, 66.04:BT-80, 100:BT-101]

//How long do you want the taper to be?
taper_length = 25;

//Diameter of the hole through the center?  Use "0" for no hole.  Must be smaller than diameter of the small tube.
hole = 0;

wall_1 = tube_1 == 13.8 || tube_1 == 18.7 || tube_1 == 24.8 ? 0.33 : 0.53;

wall_2 = tube_2 == 13.8 || tube_2 == 18.7 || tube_2 == 24.8 ? 0.33 : 0.53;

difference(){

union(){

cylinder(h=taper_length, r1=tube_1/2, r2=tube_2/2, center=false, $fn=100);

translate([0,0,taper_length]) cylinder(h=12.7,r=tube_2/2-wall_2, center=false, $fn=100);

translate([0,0,-12.7]) cylinder(h=12.7,r=tube_1/2-wall_1, center=false, $fn=100);
}

translate([0,0,-12.7]) cylinder(h=taper_length+25.4, r=hole/2, center=false, $fn=100);
}
```


[User]
I need a parametric design for a screw head that's meant to be used as part of a weight. The basic shape is a cylinder with three larger cylinders intersecting it, positioned at 120-degree intervals. There's also a small, central cylinder that goes the full height, creating a through hole.

Here's a breakdown of what I'm looking for:

*   **Base Cylinder:** This is the main cylindrical body of the screw head. I need to be able to control its radius and height. Let's call the radius `base_radius` and the height `base_height`.
*   **Intersecting Cylinders:** There should be three of these, evenly spaced around the base cylinder (at 0, 120, and 240 degrees). I'd like to be able to control their radius (let's call it `intersect_radius`), their offset from the center of the main cylinder (`intersect_offset`), and the height of the intersection, which should be different from base_height (`intersect_height`).
*   **Center Hole:** This is the small cylinder that runs through the center of the base cylinder, creating a hole for the screw or bolt. I need control over its radius (`hole_radius`). The height should match the base cylinder's height.

I want all of these parameters to be easily adjustable in the OpenSCAD file. I also don't want the cylinders to be created one-by-one using the methods in the example - I'd like to have the code use a loop to create the intersection cylinders.

Could you generate an OpenSCAD file for this? Please use descriptive variable names. I'm not worried about fancy visuals, just a solid, parametric model.

I'd like this to be as simple as possible and not rely on any external libraries.

[Assistant]
Hlavicka_Jirka.scad:
```
$fn=100;

difference(){
cylinder(h=10.5, r=17);
	union(){
		rotate([0,0,120]) translate([0,40,-1]) cylinder(r=30,h=17);
		rotate([0,0,240]) translate([0,40,-1]) cylinder(r=30,h=17);
		rotate([0,0,0  ]) translate([0,40,-1]) cylinder(r=30,h=17);
		rotate([0,0,0  ]) translate([0,00,1]) cylinder(r=9/2,h=17);
	}
}
```


[User]
Hey, I need to design a customizable LiPo battery holder and I'm hoping you can help me generate the OpenSCAD code. I've got some basic parameters in mind and want it to be fully adjustable.

Essentially, I want a box-like sleeve with rounded edges to hold the battery, and I need to be able to control the internal dimensions to fit various LiPo sizes. Specifically, I need these parameters: `LIPO_HEIGHT`, `LIPO_WIDTH`, and `LIPO_THICKNESS` all as dimensions for the inside space that the battery will occupy, as well as `WALL_THICKNESS` to define the thickness of the holder walls. It should have a small `AFFORDANCE` parameter to increase the interior dimensions slightly to account for printing tolerances and ensure a snug fit, which should default to 0.5. The actual geometry should have rounded corners for a more smooth design.

There should also be an option to include "hold-downs," which are essentially spherical protrusions on the sides, that can be filed down for a tighter fit to account for manufacturing variability. Let's call that parameter `USE_HOLDOWNS` and make it a boolean.

I'd also like to include some mounting holes. I want 4 attachment points that go through the side walls of the holder, 2 on each side along the length of the battery. The size of the hole should be controlled and default to whatever the `WALL_THICKNESS` is if that's greater than 2, otherwise it should default to 2. There should also be a larger hole on the top.

Lastly, I think it's good to add a small ventilation hole on the bottom. This will just be a rectangle cut out from the bottom.

I think that covers it, please let me know if you have any questions, or can help me out. I want to try to keep the code as readable as possible and not use any libraries if possible.

[Assistant]
LipoHolder.scad:
```
//	   Customizable lipo battery holder
//		    Steven Veltema
//		    October 8, 2015
//
//      Adapted from the Adafruit 500mAh Lipo Pocket
//      http://www.thingiverse.com/thing:1018762

//reduce by amount to stick up past sleeve
LIPO_HEIGHT     = 40; // [10:1:200]
LIPO_WIDTH      = 31; // [10:1:200]
LIPO_THICKNESS  = 6;  // [3:1:50]
WALL_THICKNESS  = 2;  // [1:.5:4]
//increase lipo size in all directions for print tuning
AFFORDANCE      = 0.5;  // [0:0.5:3]
//add holders, file down to match battery size
USE_HOLDOWNS = "false"; // [true,false]

module shell() {
   difference() {
       difference() {
            //rounded outer frame
           hull() {
                sphere(d=WALL_THICKNESS);
                translate([LIPO_WIDTH+WALL_THICKNESS*2+AFFORDANCE,0,0]) sphere(d=WALL_THICKNESS);
                translate([0, LIPO_THICKNESS+WALL_THICKNESS*2+AFFORDANCE,0]) sphere(d=WALL_THICKNESS);
                translate([0,0,LIPO_HEIGHT+WALL_THICKNESS+AFFORDANCE]) sphere(d=WALL_THICKNESS);
                translate([LIPO_WIDTH+WALL_THICKNESS*2+AFFORDANCE,
                    LIPO_THICKNESS+WALL_THICKNESS*2+AFFORDANCE,
                    LIPO_HEIGHT+WALL_THICKNESS+AFFORDANCE]) sphere(d=WALL_THICKNESS);
                translate([0,LIPO_THICKNESS+WALL_THICKNESS*2+AFFORDANCE,
                    LIPO_HEIGHT+WALL_THICKNESS+AFFORDANCE]) sphere(d=WALL_THICKNESS);
                translate([LIPO_WIDTH+WALL_THICKNESS*2+AFFORDANCE,0,
                    LIPO_HEIGHT+WALL_THICKNESS+AFFORDANCE]) sphere(d=WALL_THICKNESS);
                translate([LIPO_WIDTH+WALL_THICKNESS*2+AFFORDANCE,
                    LIPO_THICKNESS+WALL_THICKNESS*2+AFFORDANCE,0]) sphere(d=WALL_THICKNESS);
           }

            //inner
            translate([WALL_THICKNESS,WALL_THICKNESS,WALL_THICKNESS])
                cube([LIPO_WIDTH+AFFORDANCE,
                    LIPO_THICKNESS+AFFORDANCE,
                    LIPO_HEIGHT+AFFORDANCE+10]);
       }

       //bottom vent
       translate([WALL_THICKNESS+AFFORDANCE*.5+LIPO_WIDTH*.25,
            WALL_THICKNESS+AFFORDANCE*.5+LIPO_THICKNESS*.25,
            -WALL_THICKNESS])
            cube([LIPO_WIDTH*.5,LIPO_THICKNESS*.5,WALL_THICKNESS*3]);

       //upper holder hole
      translate([(LIPO_WIDTH+WALL_THICKNESS*2+AFFORDANCE)/2,
            LIPO_THICKNESS+WALL_THICKNESS*2+AFFORDANCE+5,
            LIPO_HEIGHT+WALL_THICKNESS+AFFORDANCE+(LIPO_WIDTH-WALL_THICKNESS)*.1]) //slight offset to make edge softer
            rotate([90,0,0])
                cylinder(h=LIPO_THICKNESS+WALL_THICKNESS*2+AFFORDANCE+10,d=(LIPO_WIDTH-WALL_THICKNESS)*.6);

       //attach holes
       hole_size = WALL_THICKNESS > 2 ? WALL_THICKNESS : 2;

       translate([WALL_THICKNESS*2+AFFORDANCE,
            WALL_THICKNESS+AFFORDANCE,
            hole_size*2+AFFORDANCE])
            attachHoles();

       translate([LIPO_WIDTH,
            WALL_THICKNESS+AFFORDANCE,
            hole_size*2+AFFORDANCE])
            attachHoles();

       translate([WALL_THICKNESS*2+AFFORDANCE,
            WALL_THICKNESS+AFFORDANCE,
            LIPO_HEIGHT-(hole_size*3)])
            attachHoles();

        translate([LIPO_WIDTH,
            WALL_THICKNESS+AFFORDANCE,
            LIPO_HEIGHT-(hole_size*3)])
            attachHoles();
    }

}

module attachHoles() {
    //attachement holes
    hole_size = WALL_THICKNESS > 2 ? WALL_THICKNESS : 2;

    echo("WALL_THICKNESS:",WALL_THICKNESS);
    echo("hole_size:",hole_size);

    rotate([90,0,0]) cylinder(h=hole_size+AFFORDANCE+2,d=hole_size);
    translate([0,0,hole_size*2]) rotate([90,0,0]) cylinder(h=hole_size+AFFORDANCE+2,d=hole_size);
}

module holderBalls() {
   //add holder balls
    translate([(LIPO_WIDTH+WALL_THICKNESS*2+AFFORDANCE)*.5,
        WALL_THICKNESS/2.0+AFFORDANCE,
        (LIPO_HEIGHT+WALL_THICKNESS+AFFORDANCE)*.5])  sphere(d=WALL_THICKNESS*1.2);

  //add holder balls
    translate([(LIPO_WIDTH+WALL_THICKNESS*2+AFFORDANCE)*.5,
        3*WALL_THICKNESS/2.0+LIPO_THICKNESS,
        (LIPO_HEIGHT+WALL_THICKNESS+AFFORDANCE)*.5])  sphere(d=WALL_THICKNESS*1.2);
}

$fn=60;

union() {
shell();
if (USE_HOLDOWNS != "false") {
    holderBalls();
}
}

```


[User]
I'm looking for an OpenSCAD design for a rock climbing hold that's meant to be quite challenging. I've got some specific dimensions in mind, but I'd also like it to be parametric so I can easily adjust things later.

Here's what I'm thinking:

The hold should have a somewhat rounded, irregular shape, kind of like a natural rock formation. I want to achieve this using a combination of cylinders, spheres, and cubes, combined with `hull()` to smooth it out. I've got a basic idea of how to do this, using a few main hull shapes to make it feel like a rounded blob with some interesting details.

The main constraint is that the hold needs a recess to accommodate a bolt head, along with a hole for the bolt itself. I need this to be parametric so that the bolt diameter, bolt head diameter and height, and overall length are all variables I can change. The hole and recess need to be big enough for the head and bolt with a bit of clearance to account for manufacturing tolerances.

Specifically, I'm envisioning that the hold should be made by combining these shapes:
* Four rounded main "lobes" that extend out from a central area, like a plus sign, each made with `hull()`.
* Each lobe starts with a cylinder and has a sphere at the end, with some cube shaping in the middle.
* I'll have a few additional spheres to make the surface more irregular and organic.

The main central area will be hollowed out by subtracting a cube from the center to give it that slightly overhanging feel. And I'll need a difference operation to subtract the bolt hole from the center bottom. The bolthole should go deep enough into the rock to allow the bolt head to be flush with the bottom.

I want to be able to control the following parameters:
*   Bolt head diameter (`B`)
*   Bolt head height (`h`)
*   Overall bolt length (`l`)
*   Bolt diameter (`d`)
*   Radius for the cone shape in the rock (`r`)
*   Height of the cone shape in the rock (`hc`)

I'm not sure about the best way to make sure that the hole for the bolt has the right amount of tolerance, so I'd appreciate your help there. I think it might be good to have an additional parameter for tolerance on the bolt hole and recess.

I don't have any specific material preferences yet. I can manage the printing process myself, I just need to be able to generate the models. I'm happy to receive all the code needed in one file or split across a few, whatever makes sense.

[Assistant]
rock.scad:
```
//Bolt head diamter with clearance for tool
B=30;

// Bolt head height
h=10;

// Bolt overall length
l=69.5;

// diamter
d=15;

//radius for cone in rock
r = 12.5;

//height for cone in rock
hc = 22.5;

module bolt(){
    $fn = 100;
    union() {
		translate([0,0,l-0.1])cylinder(h=h, r=B/2); //space for head
		cylinder(h=l, r=d/2); // bolt shaft
	}
}

module rock() {
    $fn = 50; $fa = 20; $fs = 23;
    difference() {
        union() {
            hull() {
                translate([-2*r,0,0]) cylinder(h, 2*r, r, center = false);
                translate([-2*r,0,hc]) sphere(r);
                translate([0,0,1*hc/4]) cube(size = [4*r,r,3*hc/8], center = true);

            }
            hull() {
                translate([2*r,0,0]) cylinder(h, 2*r, r, center = false);
                translate([2*r,0,hc]) sphere(r);
                translate([0,0,1*hc/4]) cube(size = [4*r,r,3*hc/8], center = true);
            }
            hull() {
                translate([0,-2*r,0]) cylinder(h, 2*r, r, center = false);
                translate([0,-2*r,hc]) sphere(r);
                translate([0,0,1*hc/4]) cube(size = [r,4*r,3*hc/8], center = true);
            }
            hull() {
                translate([0,2*r,0]) cylinder(h, 2*r, r, center = false);
                translate([0,2*r,hc]) sphere(r);
                translate([0,0,1*hc/4]) cube(size = [r,4*r,3*hc/8], center = true);
            }
            translate([2*r,2*r,0]) sphere(4*r/3, center = false);
            translate([2*r,-2*r,0]) sphere(4*r/3, center = false);
            translate([-2*r,-2*r,0]) sphere(4*r/3, center = false);
            translate([-2*r,2*r,0]) sphere(4*r/3, center = false);
        }

        translate([0,0,-4*r]) cube(size = 8*r, center = true);
    }
}

difference() {
    rock();
    translate([0,0,-hc/2]) bolt();
}
```


[User]
I'd like to create a design in OpenSCAD that resembles a kind of studded, futuristic base. It should have a central, cylindrical base with a narrow shaft rising from it, and then a series of spheres attached to the main base and around the central shaft.

Specifically:

1.  **Base:** The base is a large sphere with a cylindrical hole going most of the way through. The hole actually has two parts:
    *   A narrower, central cylinder.
    *   A wider counterbore at the top of the central cylinder.
    *   I think I'll want to control the radius and height of both of these parts, as well as the base sphere diameter itself.
2. **Spheres:** I need to attach a bunch of spheres, of equal radius, to the sides and top.
    *   I want spheres in cardinal directions, both around the sides and higher.
    *   I want spheres in intercardinal directions at the same height, and higher.
    *   I think I also need a series of spheres that start a bit higher than the others, and also need to be at the cardinal and intercardinal positions.
    *   The height of the top spheres needs to be tied to the distance that these are offset from the center.
    *   I'll need to control the sphere radius too.

I need this design to be parametric so I can easily change the size of the spheres, the base, and the cylinder.

Finally, I want to be able to cut the design in half with a cube so I can create a half-model and I want to be able to use this to cut the cylinder as well. So I need the half model too.

Can you generate OpenSCAD files for this? I'm not looking to use any particular external libraries.

[Assistant]
rockhold.scad:
```

module ball(){sphere(d=35, $fn=100);
}

module base(){
difference ()
{sphere(d = 80, $fn=100);
    translate([0,0,-37])
union(){
		translate([0,0,69.5-0.1])cylinder(h=8, r=12.5);
		cylinder(h=69.5, r=5.5);
		}
}}

module whole(){
union(){base();
    translate([0,40,0]) ball();
    translate([0,-40,0]) ball();
    translate([40,0,0]) ball();
    translate([-40,0,0]) ball();

    translate([40*sin(45),40*sin(45),0]) ball();
    translate([-40*sin(45),40*sin(45),0]) ball();
    translate([40*sin(45),-40*sin(45),0]) ball();
    translate([-40*sin(45),-40*sin(45),0]) ball();

    a=35;
    translate([a*sin(67.5),a*sin(22.5),40*sin(22.5)]) ball();
    translate([a*sin(67.5),a*sin(-22.5),40*sin(22.5)]) ball();
    translate([a*sin(-67.5),a*sin(22.5),40*sin(22.5)]) ball();
    translate([a*sin(-67.5),a*sin(-22.5),40*sin(22.5)]) ball();

    translate([a*sin(22.5),a*sin(67.5),40*sin(22.5)]) ball();
    translate([a*sin(22.5),a*sin(-67.5),40*sin(22.5)]) ball();
    translate([a*sin(-22.5),a*sin(67.5),40*sin(22.5)]) ball();
    translate([a*sin(-22.5),a*sin(-67.5),40*sin(22.5)]) ball();

    b=25;
    translate([b*sin(0),b*sin(90),40*sin(45)]) ball();
    translate([b*sin(0),b*sin(-90),40*sin(45)]) ball();
    translate([b*sin(90),b*sin(0),40*sin(45)]) ball();
    translate([b*sin(-90),b*sin(0),40*sin(45)]) ball();

    translate([b*sin(45),b*sin(45),40*sin(45)]) ball();
    translate([-b*sin(45),b*sin(45),40*sin(45)]) ball();
    translate([b*sin(45),-b*sin(45),40*sin(45)]) ball();
    translate([-b*sin(45),-b*sin(45),40*sin(45)]) ball();

}}

module half()
difference ()
{whole();
translate ([0,0,-40]) cube([200,200,80], center=true);
}

difference ()
{half();
    translate([0,0,-37])
union(){
		translate([0,0,69.5-0.1])cylinder(h=8, r=12.5);
		cylinder(h=69.5, r=5.5);
		};
    }

```


[User]
I'd like to design a customizable headset microphone boom that can be 3D printed. The microphone will be attached to a boom arm, and the whole thing will attach to the side of headphones with a magnetic pivot. It should be parametric so I can adjust the dimensions for different microphones and headphones.

Here are the key parameters I need:

*   **Microphone dimensions:** I need to be able to specify the microphone's major diameter, minor diameter (if it tapers), its length, and the diameter of the microphone cable.
*   **Magnet dimensions:**  I need to be able to specify the diameter and height of a cylindrical magnet, which will be used to hold the boom to the mount on the headphones.
*   **Boom parameters:** I need to specify the length of the boom arm (from the pivot center to the mic holder), the angle of the microphone relative to the boom arm, and which side of the headphones the boom mounts to (left or right). I also want a parameter to control the length of the support between the boom and pivot, something like a support factor.
*   **Output Selection:** I need a way to just output the boom or just the mount for the headphones, so I can make sure they fit to my existing hardware before printing the other part.

I'm also thinking about some internal parameters I'd want, but I don't need to expose them to the user. These include things like the wall thickness of the mic holder and boom tube, how much extra room for the cable (cord factor), the outer diameter of the boom tube, a smaller opening for the cable to help retain it, and the diameter of the pivot disc. The number of sides for the boom tube, the diameter of the bumps on the pivot, the diameter of the ring of bumps, and the number of bumps themselves could also be internal parameters. Finally, I would like for all internal parameters to have well-defined default values which should be in millimeters.

I would like for you to design this using basic OpenSCAD primitives. I don't think I'll need any external libraries for this. I would like a working example with default values, with good values for a small, inexpensive electret condenser microphone (like the "Neewer" brand available on Amazon).

[Assistant]
Customizable_headset_mic_boom.scad:
```
// Customizable headset boom mic
// Designed by Rich Moore, Oct 8th, 2016 dr.romeo.chaire@gmail.com

// Note: default values are set to accept an inexpensive "Neewer"
// brand electret condenser microphone, available on amazon.com
// for under $2/ea in quantities of 5 and up. Dimensions may change

/* [Microphone dimensions (mm)] */
// Enter the largest diameter of your microphone in mm
mic_major_dia=10;

// If the body of the microphone is tapered, enter the smaller diameter.  If it's a straight cylinder, enter the major diameter again.
mic_minor_dia=6.2;

// Enter the length of the body of the microphone cylinder in mm.
mic_len=18;

// Enter the diameter of the microphone cable in mm.
cord_dia=2.2;

/* [Magnet dimensions (mm)] */
// Diameter of cylindrical magnet (mm)
mag_dia=8;

// Height of cylindrical magnet (mm)
mag_h=2;

/* [Design Parameters] */

// Which part would you like to create?
part = "boom"; // [boom: Boom Only, mount: Mount Only]

// Length of the microphone boom from center of pivot mount to mic holderBoom Parameters
boom_len=100;   // [25:150]

// Angle of microphone, relative to the boom. 0 is straight, 90 is max angle
mic_angle=60;   // [0:90]

// mount_side is whether you want to mount to the right or left of your headphones
mount_side= -1;  // [-1: Left side, 1: Right side]

// support_factor controls how long the support between the boom and pivot is. This is just a general control, not in mm.
support_factor=3; // [2,3,4,5]

/* [Hidden] */
// other parameters set by default but not in Customizer interface

mic_wall=2.4; // wall thickness of mic holder
boom_wall=1.5; // wall thickness of boom tube
cord_factor=1.2; // opening for cable should have some extra room
boom_dia=cord_dia+2*boom_wall; // outer diameter of boom tube
cord_slot=cord_dia*.9; // opening for cord is slightly smaller to retain cord
mount_dia=20;   // size of the disk that makes up the pivot
boom_facets=25;  // how many sides for the boom tube

bmp_dia=1.8;    // diameter of the detents or bumps on the pivot
bmp_rng_dia=mount_dia*.7; // diameter of the ring of bumps
bump_count=10;  // how many bumps
INF=1000;   // large number used for cutting objects
FF=0.01;    // fudge factor for making sure unions don't have zero width planes
$fn=50;

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

module half_space(size,axis,dir)
{
// half_space is a utility module used to cut objects with difference function
// axis: x=0, y=1, z=2
// dir: -1 or 1, direction of half-space
    sign = dir==-1 ? -1 : 1;
    if (axis==0) // x axis
        translate([sign*size/2,0,0]) cube(size+FF,center=true);
    else if (axis==1)
        translate([0,sign*size/2,0]) cube(size+FF,center=true);
    else
        translate([0,0,sign*size/2]) cube(size+FF,center=true);
}

module boom() {
// create boom by taking a difference of two unions
difference(){

// stuff to add
union()    {
// main pivot -- disk that holds boom to base with magnet
    cylinder(boom_dia,d=mount_dia,center=true);

// add some support to where the pivot meets the boom shaft, looks and strength
    translate([mount_dia/(1+support_factor),0,0])
       difference() {
           scale([support_factor,1,1])
              cylinder(boom_dia,d=mount_dia/2,center=true);
           half_space(100,0,-1);
       }

// boom shaft
    rotate([0,90,0])
        cylinder(boom_len,d=boom_dia,$fn=boom_facets);

// put mic holder at end of boom shaft
    translate([boom_len,0,boom_dia/3]) {
       sphere(d=mic_minor_dia+mic_wall);
          rotate([0,90-mic_angle,0])
            cylinder(mic_len,d1=mic_minor_dia+mic_wall,d2=mic_major_dia+mic_wall);
    }

// place the bumps used to hold the boom in place
    for(ang=[0:360/bump_count:360])
       rotate([0,0,ang])
          translate([bmp_rng_dia/2,0,boom_dia/2])
             sphere(0.8*bmp_dia);
    }

// stuff to subtract
    union() {
// cut cavity in the boom for cord
        rotate([0,90,0])
          translate([0,0,mount_dia/2])
            cylinder(boom_len-mic_minor_dia-2*mic_wall,d=cord_dia*cord_factor);

// cut opening for mic
   translate([boom_len,0,boom_dia/3])
      rotate([0,90-mic_angle,0])
         cylinder(mic_len+mic_wall+FF,d1=mic_minor_dia,d2=mic_major_dia);

// cut slot in boom shaft for cord entry
   translate([mount_dia/2,-cord_dia/2,cord_dia/2])
        cube([boom_len-mount_dia/2,cord_slot,INF]);

// cut slot in mic holder for cord entry
    translate([boom_len,-cord_slot/2,boom_dia/3])
        rotate([0,90-mic_angle,0])
            translate([-mic_len/2,0,0])
                cube([mic_major_dia,cord_slot+FF,2*mic_len]);

// cut groove for cable to exit
    translate([mount_dia/2+cord_slot,mount_side*mount_dia/2,boom_dia/2])
        cube([cord_slot*1.2,mount_dia,boom_dia],center=true);

// take the sharp corners off cord exit
    translate([mount_dia/2+cord_slot,0,boom_dia/2])
        cylinder(boom_dia/2,r=cord_slot,center=true);

// cut magnet hole
    translate([0,0,boom_dia-1.75*mag_h])
       cylinder(mag_h*1.25,d=mag_dia,center=true);
    }
  }
}

module mount()
{
     difference()
     {
         union()
         {
             // pivot mount
                cylinder(mag_h+1,d=mount_dia,center=true);
         }

         union()
         {
             // magnet hole
             cylinder(mag_h,d=mag_dia);

             for(ang=[0:360/bump_count:360])
                rotate([0,0,ang])
                    translate([0,bmp_rng_dia/2,0])
                        cylinder(mag_h,d=2*bmp_dia);
         }
     }
 }

// create desired part based on selection
if (part == "boom") {
    boom();
} else {
    mount();
}

```


[User]
I'm looking to create a customizable parts container, something like the one described in the attached SCAD file, but I'd like to request that you create a new parametric design for me.

Here are the key features I need:

*   **Overall Shape:** It should be a rectangular box with a tab extending upwards from the back side of the container for a label. The tab should have angled rails for a label to slide into. The container itself should be hollow to store parts.
*   **Customizable Dimensions:** I need to be able to adjust the width, height, and depth of the container, as well as the height of the tab. The thickness of the container walls should also be adjustable, including the thickness of the solid frame corners around the cutouts.
*  **Cutout Patterns:** I want the option to cut patterns into the container sidewalls to save material and make it easier to see the contents. The patterns I'd like to choose from should be:
    *   **Rectangular:** A grid of rectangular cutouts. I need to be able to control the height of these rectangles, as well as how many support pillars are placed in both depth and width directions to help with bridging during printing.
    *   **Hexagonal:** A mesh of hexagonal cutouts. I need to be able to control the diameter of the hexagons.
    *   **Solid:** No cutouts at all - just a solid wall.
    *   **Empty:** The equivalent of removing the side walls completely, with the frame still in place.
*   **Label Holder:** The tab should include a recessed area for a label to slide into, with angled rails to hold it in place.
*   **Fillets:** The corners where the tab meets the container walls need to have a fillet to add strength.
*   **Units:** All dimensions should be in millimeters.

I'd like the design to be fully parametric so I can easily modify these dimensions and features as needed using the customizer. I would prefer that the code be clean and easy to follow. It should be a single .scad file.

I think the existing file is pretty close to what I need, but I'd like to make sure it's a clean and fresh implementation. Can you provide a new OpenSCAD design based on these requirements?

[Assistant]
Customizable_parts-container.scad:
```
// Copyright 2015 Arthur Davis (thingiverse.com/artdavis)
// This file is licensed under a Creative Commons Attribution 4.0
// International License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// Customizable parts container

// I designed these bins for small parts storage to fit
// in card catalog style cabinet drawers I happened
// to have. The protruding tab on top has some angled rails
// for sliding in a descriptive label.

// At first I was printing these out solid until I realized
// that was using too much filament. Under the "pattern"
// dropdown box in the Customizer are options for cutting
// out a pattern in the sidewalls so the containers can use
// less material with the added bonus of being able to see
// the small parts cotained inside.

// "Hex" is very cool looking but can be taxing for the computer
// to build the STL. Your mileage may vary getting this to work
// in Customizer but you can always download the source and
// run it locally in OpenSCAD. Also it takes a long time
// to print since the extruder head has to draw a profile for
// all of the wire mesh.

// "Rect" should print much faster but your printer will have
// to do a lot of bridging.

// Units are in mm

/* [Global] */
// Type of pattern cutout for the side walls
pattern = "Rect"; // [Rect, Hex, Empty, Solid]
// Width of the compartment bins
width = 26; // [10:1:50]
// Height of the sidewalls
height = 65; // [10:5:100]
// Depth of the compartment bins
depth = 35; // [10:5:100]
//depth = 15;
//depth = 20;
//depth = 25;
//depth = 30;
//depth = 40;
//depth = 45;
//depth = 50;
// Height of the tab above the sidewall
tabheight = 25; //[10:5:50]
// Wall thickness
thick = 1.0; //[0.5:0.5:3.0]
// Thickness of the solid frame corners
frame_wd = 2.0; // [1:1:5]
// Diameter of the hexagons in the mesh for "Hex" pattern
hexdiam = 6.0;
//hexdiam = 3.0;
// Height of the rectangular cutouts for "Rect" pattern
rectht = 2.0;
// How many support pillars to build for "Rect"  pattern in depth
rect_depth_support = 1; // [0:1:4]
// How many support pillars to build for "Rect"  pattern in width
rect_width_support = 0; // [0:1:4]
// Thickness of the mesh with pattern cutouts
mesh_th = 0.8;
//mesh_th = 0.4;

/* [Hidden] */
// Radius for tab fillet
fillet_rad = 5;
// Y-location for divider at the back
divy = (depth - thick)/2;
lht0 = tabheight - fillet_rad; // Label height
lht1 = lht0 + thick; // Label frame height
lth = 0.8; // Label thickness
fth = 0.8; // Frame thickness
cht = lht1 + 0.2; // Frame cutter height

// Functions for calculating hexagonal axes
// When using a cylinder with $fn=6 for your hex specify
// d=hexmajor(<hexagonal-minor-width>)
function hexminor(major) = sqrt(3) * major / 2;
function hexmajor(minor) = 2 * minor / sqrt(3);

module labelholder() {
        // Label holder
        difference() {
            // Frame
            translate([0, divy-(thick + fth + lth)/2, (height + lht1/2 - thick)])
            cube([width, fth + lth, lht1], center=true);
            // Label cutout
            translate([0, divy-(thick+lth)/2+0.04, (height + lht0/2)+0.1])
            cube([width-2*fth, lth+0.04, lht0+0.1], center=true);
            // Window cutout
            translate([0, divy-(thick/2 + fth + lth)+0.02, (height+cht/2)])
            cube([width-6*fth, 2*(fth + lth), cht], center=true);
        }
}

module cutters(p) {
    // Parameter pattern: [Rect, Hex]
    translate([0, 0, height/2]){
    union() {
        intersection() {
            cube([2*width, depth-2*frame_wd,  height-2*frame_wd], center=true);
            if (p == "Rect") {
                rotate([90,0,0]) rotate([0, 90, 0])
                difference() {
                    rectbars(depth, height);
                    if (rect_depth_support > 0)
                    for (s=[1:rect_depth_support]) {
                        translate([s*depth/(rect_depth_support+1) - depth/2, 0, 0])
                        cube([frame_wd, height,  2*(depth+height)], center=true);
                        }
                    }
                }
            else if (p == "Hex") {
                rotate([90,0,0]) rotate([0, 90, 0])
                hexbars(depth, height); }
            else {
                cube([2*width, depth-2*frame_wd,  height-2*frame_wd], center=true);
                }
        }
          intersection() {
            cube([width-2*frame_wd, 2*depth,  height-2*frame_wd], center=true);
            if (p == "Rect") {
                rotate([90,0,0])
                difference() {
                    rectbars(width, height);
                    if (rect_width_support > 0)
                    for (s=[1:rect_width_support]) {
                        translate([s*width/(rect_width_support+1) - width/2, 0, 0])
                        cube([frame_wd, height,  2*(width+height)], center=true);
                        }
                    }
                }
            else if (p == "Hex") {
                rotate([90,0,0])
                hexbars(width, height); }
            else {
                cube([width-2*frame_wd, 2*depth,  height-2*frame_wd], center=true);
            }
          }
    }
    }
}

module hexcutters() {
    // Help Customizer work
    cutters("Hex");
}

module rectcutters() {
    // Help Customizer work
    cutters("Rect");
}

module emptycutters() {
    // Help Customizer work
    cutters("Empty");
}

module hexbars(wd, ht) {
    ex = 2*(wd + ht); // Extrusion distance
    tilehex = hexdiam + 2*mesh_th;
    //cube([wd, ht,  ex], center=true); // Reference block
    intersection() {
        cube([wd-2*frame_wd, ht-2*frame_wd,  ex*1.1], center=true);
        for (xpos=[-wd: hexminor(tilehex): wd],
             ypos=[-ht: 3*tilehex/2 : ht]) {
        translate([xpos, ypos, 0])
        rotate([0,0,90]) {
        cylinder(d=hexdiam, h=ex, center=true, $fn=6);
        translate([3*tilehex/4, hexminor(tilehex)/2,0])
        cylinder(d=hexdiam, h=ex, center=true, $fn=6);
        }
         }
     }
}

module rectbars(wd, ht) {
    ex = 2*(wd + ht); // Extrusion distance
    //cube([wd, ht,  ex], center=true); // Reference block
    intersection() {
        cube([wd-2*frame_wd, ht-2*frame_wd,  ex*1.1], center=true);
        for (ypos=[-ht: rectht + mesh_th : ht]) {
        translate([0, ypos, 0])
        //rotate([0,0,90])
        cube([1.1*wd, rectht, ex], center=true);
         }
     }
}

module fillcorner() {
translate([0, depth/2, height])
difference() {
    rotate([0,90,0])
    rotate([0,0,45])
    cube([2*fillet_rad, 2*fillet_rad, width], center=true);
    translate([0, width, 0])
    cube(2*width, center=true);
    translate([0, 0, -width])
    cube(2*width, center=true);
    cube([width - 2*thick, 2*width, 2*width], center=true);
}
}

module cylcoord(x, y, z, r, th) {
        translate([x, y, z])
        rotate(a=[90,0,0])
        cylinder(h=th, r=r, center=true, $fn=50);
}

module fillet(x, y, z, r, dir) {
    union() {
        cylcoord(x-r*dir,y,z-r,r,thick);
    difference() {
        children();
        cylcoord(x,y,z,r, 2*thick);
    }}

}

module makebin() {
        difference() {
            fillet((width)/2, divy, height + tabheight, fillet_rad, 1)
            fillet(-(width)/2, divy, height + tabheight, fillet_rad, -1)
            union() {
            difference() {
                // Outer shell
                translate([0, 0, height/2])
                cube([width, depth, height], center = true);
                // Inside cut
                translate([0, 0, height/2 + thick])
                cube([width - 2*thick, 1.1*depth, height], center = true);
            }

            // Divider tab back
            translate([0, divy, (height + tabheight)/2])
            cube([width, thick, height + tabheight], center = true);
            // Divider tab front
            translate([0, -divy, height/2])
            cube([width, thick, height], center = true);
            fillcorner();
            labelholder();
            }
            // Sidewall cutouts
            //if (pattern != "Solid")
            //    cutters(p=pattern);
            if (pattern == "Rect") {
                rectcutters(); }
            else if (pattern == "Hex") {
                hexcutters(); }
            else if (pattern == "Empty") {
                emptycutters(); }
        }
}

// For running in native OpenSCAD
makebin();
// For debugging:
//hexbars(depth, height);
//rectbars(depth, height);
//cutters(pattern="Rect");
//translate([0, divy, height + tabheight/2 - thick])
//cube([width, thick, tabheight], center = true);
//labelholder();
```


[User]
Hi, I'm looking to generate an OpenSCAD model of an origami-style ship. I have an existing SCAD file (which I'll paste below for reference, but I'm not expecting you to modify it, I want a fresh design), but I'd like the new version to be more modular and easier to customize. Basically, the ship is formed from a few connected planes, with a mirrored/doubled hull and a sail.

Here's the general idea I'm going for, with the key parameters and considerations:

*   **Hull:** The hull should be formed of two main sections – a bow section defined by three points, and a midships section defined by four points. The midships section will have one edge that matches the bow's. It's critical that the midship section is actually a quadrilateral, not two triangles, like my reference code has. I need this because it makes a cleaner crease in an actual origami fold. These should be defined parametrically.
*   **Bow Points:** I need to specify the length of the bow (from the center to the tip), the height of the bow, and the width midships and height midships. I also need the waterline length of the bow (from center). The fourth point for the hull needs to be computed based on the fact it has to be coplanar with the other 3 points in the midships section.
*   **Sail:** The sail is a simple triangle, and its height should be adjustable.
*   **Thickness:** I need to be able to specify the thickness of the "paper" or material, as well as the overall scale of the model.
*   **Mirroring/Doubling:** The hull should be doubled/mirrored on two axes - once to make both sides of the hull and once to make the bottom half of the ship.
*   **Ground:** Include a basic ground plane under the model so it renders better.
*   **Quality:** Have a parameter for the sphere quality for rendering purposes.

I'd like the code to use named modules for the different parts – the ship section(s), and the mirrored parts, etc. This will make it easier to combine or modify. I want to make sure you use a function to solve the 4th coplanar point for the midships section. Here's my existing SCAD code (again, just as a reference):

```
/*
   origami ship
   straight sides

   Kit Wallace

*/
// length of bow from centre
lb=15;
// height of bow
hb=12;
// width midships
wm=6;
// height midships
hm=3;
// waterline length e.g. from centre eg. half length of bow
wl=8.5;
// width of hull from centre  - here this is computed so sides has no crease
// wh;

// height of sail
h=10;
//Thickness of paper
thickness=1;
// sphere quality
steps = 20;
// overall scale
scale=2;

module double(axis) {
      union() {
          children();
          mirror(axis) children();
      }
  }
module plane(s,t=0.5) {
    hull()
    for (i=[0:len(s) -1])
       translate(s[i]) sphere(t/2);
    }

module ground(size=50) {
   translate([0,0,-size]) cube(2*size,center=true);
}

// functions to make 4 points coplanar - by computing the value of one value so that determinat of matri of 4 points is zero

function det4(m) =
// from http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/fourD/index.htm
    m[0][3] * m[1][2] * m[2][1] * m[3][0] - m[0][2] * m[1][3] * m[2][1] * m[3][0]- m[0][3] * m[1][1] * m[2][2] * m[3][0]+m[0][1] * m[1][3] * m[2][2] * m[3][0]+ m[0][2] * m[1][1] * m[2][3] * m[3][0]-m[0][1] * m[1][2] * m[2][3] * m[3][0]- m[0][3] * m[1][2] * m[2][0] * m[3][1]+m[0][2] * m[1][3] * m[2][0] * m[3][1]+ m[0][3] * m[1][0] * m[2][2] * m[3][1]-m[0][0] * m[1][3] * m[2][2] * m[3][1]- m[0][2] * m[1][0] * m[2][3] * m[3][1]+m[0][0] * m[1][2] * m[2][3] * m[3][1]+ m[0][3] * m[1][1] * m[2][0] * m[3][2]-m[0][1] * m[1][3] * m[2][0] * m[3][2]- m[0][3] * m[1][0] * m[2][1] * m[3][2]+m[0][0] * m[1][3] * m[2][1] * m[3][2]+ m[0][1] * m[1][0] * m[2][3] * m[3][2]-m[0][0] * m[1][1] * m[2][3] * m[3][2]- m[0][2] * m[1][1] * m[2][0] * m[3][3]+m[0][1] * m[1][2] * m[2][0] * m[3][3]+ m[0][2] * m[1][0] * m[2][1] * m[3][3]-m[0][0] * m[1][2] * m[2][1] * m[3][3]- m[0][1] * m[1][0] * m[2][2] * m[3][3]+m[0][0] * m[1][1] * m[2][2] * m[3][3];

// to iteratively solve det(x) = -
function secant(xn,xn1,eps=0.001) =
     let(fxn=f(xn))
     let(fxn1=f(xn1))
     let(x = xn - fxn*(xn - xn1)/ (fxn - fxn1))
     abs(f(x) - fxn) < eps
        ? x
        : secant(x,xn,eps);

p1=[lb,0,hb];
p2=[wl,0,0];
p3=[0,wm,hm];
p5=[0,0,h];

function f(x) =
 let(m = [
       [lb,0,hb,1],
       [wl,0,0,1],
       [0,wm,hm,1],
       [0,x,0,1]]
     )
  det4(m);

wh= secant(0,wm);
echo(wh);

p4=[0,wh,0];

module ship_q(t) {
   plane([p1,p2,p3],t);
   plane([p2,p3,p4],t);
   plane([p4,p2,p5],t);
};

$fn=steps;
scale(scale)
 difference() {
  double([0,1,0])
     double([1,0,0])
         ship_q(thickness);
 * ground();
 }
```
I'd also like comments in the code, if that's possible, to help me understand how everything works. I'm looking for a clear, easy-to-understand parametric model that I can play with.

Thanks!

[Assistant]
origami_ship_v2.scad:
```
/*
   origami ship
   straight sides

   Kit Wallace

*/
// length of bow from centre
lb=15;
// height of bow
hb=12;
// width midships
wm=6;
// height midships
hm=3;
// waterline length e.g. from centre eg. half length of bow
wl=8.5;
// width of hull from centre  - here this is computed so sides has no crease
// wh;

// height of sail
h=10;
//Thickness of paper
thickness=1;
// sphere quality
steps = 20;
// overall scale
scale=2;

module double(axis) {
      union() {
          children();
          mirror(axis) children();
      }
  }
module plane(s,t=0.5) {
    hull()
    for (i=[0:len(s) -1])
       translate(s[i]) sphere(t/2);
    }

module ground(size=50) {
   translate([0,0,-size]) cube(2*size,center=true);
}

// functions to make 4 points coplanar - by computing the value of one value so that determinat of matri of 4 points is zero

function det4(m) =
// from http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/fourD/index.htm
    m[0][3] * m[1][2] * m[2][1] * m[3][0] - m[0][2] * m[1][3] * m[2][1] * m[3][0]- m[0][3] * m[1][1] * m[2][2] * m[3][0]+m[0][1] * m[1][3] * m[2][2] * m[3][0]+ m[0][2] * m[1][1] * m[2][3] * m[3][0]-m[0][1] * m[1][2] * m[2][3] * m[3][0]- m[0][3] * m[1][2] * m[2][0] * m[3][1]+m[0][2] * m[1][3] * m[2][0] * m[3][1]+ m[0][3] * m[1][0] * m[2][2] * m[3][1]-m[0][0] * m[1][3] * m[2][2] * m[3][1]- m[0][2] * m[1][0] * m[2][3] * m[3][1]+m[0][0] * m[1][2] * m[2][3] * m[3][1]+ m[0][3] * m[1][1] * m[2][0] * m[3][2]-m[0][1] * m[1][3] * m[2][0] * m[3][2]- m[0][3] * m[1][0] * m[2][1] * m[3][2]+m[0][0] * m[1][3] * m[2][1] * m[3][2]+ m[0][1] * m[1][0] * m[2][3] * m[3][2]-m[0][0] * m[1][1] * m[2][3] * m[3][2]- m[0][2] * m[1][1] * m[2][0] * m[3][3]+m[0][1] * m[1][2] * m[2][0] * m[3][3]+ m[0][2] * m[1][0] * m[2][1] * m[3][3]-m[0][0] * m[1][2] * m[2][1] * m[3][3]- m[0][1] * m[1][0] * m[2][2] * m[3][3]+m[0][0] * m[1][1] * m[2][2] * m[3][3];

// to iteratively solve det(x) = -
function secant(xn,xn1,eps=0.001) =
     let(fxn=f(xn))
     let(fxn1=f(xn1))
     let(x = xn - fxn*(xn - xn1)/ (fxn - fxn1))
     abs(f(x) - fxn) < eps
        ? x
        : secant(x,xn,eps);

p1=[lb,0,hb];
p2=[wl,0,0];
p3=[0,wm,hm];
p5=[0,0,h];

function f(x) =
 let(m = [
       [lb,0,hb,1],
       [wl,0,0,1],
       [0,wm,hm,1],
       [0,x,0,1]]
     )
  det4(m);

wh= secant(0,wm);
echo(wh);

p4=[0,wh,0];

module ship_q(t) {
   plane([p1,p2,p3],t);
   plane([p2,p3,p4],t);
   plane([p4,p2,p5],t);
};

$fn=steps;
scale(scale)
 difference() {
  double([0,1,0])
     double([1,0,0])
         ship_q(thickness);
 * ground();
 }
```


[User]
I'm looking to design a parametric 3-way joint, similar to the clever design by Matthias Wandel that's showcased in his video (linked above). I've seen some OpenSCAD implementations of it online but want something that's a little more flexible and easier to customize, and maybe cleaner in terms of code.

Here's what I'm looking for in terms of parameters:

*   **`joint_size`**:  This should control the overall size of the central joint. It will roughly be the "side" length of the cube the main part of the joint would fit within.
*   **`cylinder_dia_mult`**: A multiplier to determine the cylinder diameter relative to the `joint_size`. I expect the final cylinder diameter will be something like `joint_size * sqrt(2) * cylinder_dia_mult`. This lets me play with the clearance.
*   **`cylinder_length_mult`**: Similarly, a multiplier for the cylinder lengths, based off of `joint_size`.
*   **`tol`**: A tolerance parameter, also to be applied to all the parts that intersect and are supposed to be clearanced from one another
*  **`length`**: The length of the rectangular "legs" or parts that slot into the central joint

I want the design to consist of:
    *   The central 3-way joint itself.
    *   A version of the joint with three rectangular legs attached. These legs should be perpendicular to the faces of the center joint, as in the "assembled" versions of the original.
    *  A version of the joint with only one leg attached, which will allow for easy stacking or assembly of multiple such parts. This should take the `length` parameter as the length of the attached leg.

Essentially, I'd like a core module to generate the central joint itself, and other modules to create the assembled versions with different leg configurations. I am not using any existing OpenSCAD libraries or other .scad files.

[Assistant]
way_joint.scad:
```
// 3d model of Matthias Wandel's clever 3-way joint

joint_size = 200;
js = joint_size;
tol = 0.2;
length = 20;

diag = joint_size * sqrt(2);

module cylinder_slice(dia, height, angle, tol=0) {
  difference() {
    cylinder(d=dia, h=height);
    translate([-dia/2-1,-tol,-1]) cube(dia+2);
    translate([0,-2*dia+1,-1]) cube(2*dia);
    rotate(-(90-angle)) translate([-tol/sin(angle),-2*dia+1,-1]) cube(2*dia);
  }
}
/*for (a = [0:2*60:360]) rotate(a) cylinder_slice(50,20,60);*/

module joint_3way() {
  angle = atan(2*js/diag);
  polyhedron(points=[[-js/2, js/2, js/2], [js/2, -js/2, js/2], [-js/2, -js/2, -js/2], [-js/2, -js/2, js/2]], faces=[[0,2,1],[0,1,3],[1,2,3],[0,3,2]]);
  rotate([0,0,-45]) rotate([angle,0,0]) intersection() {
    rotate([-angle,0,0]) rotate([0,0,45]) polyhedron(points=[[-js/2, js/2, js/2], [js/2, -js/2, js/2], [-js/2, -js/2, -js/2], [-js/2, js/2, -js/2], [js/2, -js/2, -js/2], [js/2, js/2, js/2]], faces=[[0,1,2],[3,4,5], [0,5,1], [2, 4, 3], [0,2,3], [1,4,2], [1,5,4], [0,3,5]]);
    rotate(60) for (a = [0:2*60:360]) rotate(a) translate([0,0,-js/2]) cylinder_slice(diag*3/2,js,60, tol);
  }
}
/*joint_3way();*/

module joint_3way_assembled(attached=false) {
  joint_3way();
  rotate([-90,0,0]) rotate(180) joint_3way();
  if ((attached=="perpendicular")||(attached=="right")) {
    translate([0,-(4*js+js)/2,0]) cube([js, 4*js, js], center=true);
    rotate((attached=="right"?0:-90)) translate([0,(4*js+js)/2,0]) cube([js, 4*js, js], center=true);
  }
}
/*joint_3way_assembled();*/
/*joint_3way_assembled("right");*/
/*joint_3way_assembled("perpendicular");*/

module joint_3way_rtp(length) {
  translate([0,0,js/2]) rotate([0,180,0]) {
    joint_3way();
    translate([0,-(length+js)/2,0]) cube([js, length, js], center=true);
  }
}
joint_3way_rtp(length);

```


[User]
Hey there, I'm looking to create a parametric design for a band pulley in OpenSCAD, and I'd like to get your help with it. I already have an example file (`pulley.scad`) that I've put together.

I need a pulley that has a main cylindrical body with a groove for a band, and a hub that attaches to the shaft. The design should include mounting for screws and nuts so that the pulley can be securely attached to the shaft, and a groove that supports the band.

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

*   **`bandDiameter`**: The diameter of the band that will fit into the groove.
*   **`shaftDiameter`**: The diameter of the shaft the pulley will mount to.
*   **`pulleyDiameter`**: The overall diameter of the main body of the pulley.
*   **`pulleyHeight`**: The height of the main pulley body.
*   **`hubDiameter`**: The diameter of the hub.
*   **`hubHeight`**: The height of the hub.
*   **`m3_nut_flats`**: The width of the flats of the M3 nut.
*    **`m3_nut_depth`**: The depth of the M3 nut.
*   **`bandResolution`**: The resolution or number of segments used for the curved band groove.
*    **`bandSegments`**: The overall number of segments used in the rotation extrusion.
*   **`nut_bolt_count`**: The number of nut/bolt mountings, these should be arranged radially around the shaft.

I'd also like the design to include:
*   A circular indentation to capture the nut on one side of the hub
*   A clearance hole for an M3 bolt to pass through the hub and line up with the captured nut.
*   The nut and bolt mountings should be arranged radially (2 is good, but being able to configure the number would be best).

I'm hoping for a parametric design where all of these parameters can be adjusted easily. I would like to keep the existing structure of the `difference` union where you subtract the shaft and screw holes from the combined pulley body and hub. I think using `rotate_extrude()` for the band groove is also good. I want the design to be straightforward, so let's avoid anything too advanced.

Could you please generate the OpenSCAD code for this parametric band pulley, using this detailed description? Thanks!

[Assistant]
pulley.scad:
```
// expects about 0.2 mm of tolerance

bandDiameter   = 3.2; // diameter of band

shaftDiameter  = 5.2; // sized for m5 shaft

pulleyDiameter = 40;
pulleyHeight   = 6;

hubDiameter    = 22;
hubHeight      = 8;

m3_nut_flats = 5.7; // width of m3 nut cave
m3_nut_depth = 2.7; // height of m3 nut for cave
m3_nut_points = (m3_nut_flats / 2) / cos(30); // Nut cave radius

bandPulley();

module bandPulley() {

	bandSegments   = 128;
	bandResolution = 24; // 4 produces a sharp inward groove

	difference() {

		union() {
			// main circumfrence
			difference() {
				cylinder(d = pulleyDiameter, h = pulleyHeight, center = true, $fn = bandSegments);

				// band groove
				rotate_extrude(convexity = 10, $fn = 128) {
					translate([pulleyDiameter / 2, 0, 0]) {
						circle(d = bandDiameter, center = true, $fn = bandResolution);
					}
				}
			}

			// hub
			translate([0, 0, pulleyHeight / 2 + hubHeight / 2]) {
				cylinder( d = hubDiameter, h = hubHeight, center = true, $fn = 64);
			}
		}

		// shaft
		translate([0, 0, hubHeight / 2]) {
			cylinder(d = 5.2, h = pulleyHeight + hubHeight + 1, center = true, $fn = 64);
		}

		for (j = [1:2] ) {
			rotate(360/2 * j, [0,0,1]) {
				rotate(90, [0,1,0]) {

					// nut cave
					translate([-(pulleyHeight / 2 + hubHeight / 2), 0, hubDiameter / 2 - m3_nut_depth - 2]) {
						cylinder(r = m3_nut_points, h = m3_nut_depth, center = true, $fn = 6);
					}

					// nut entrance
					translate([-(pulleyHeight / 2 + hubHeight), 0, hubDiameter / 2 - m3_nut_depth - 2]) {
						cube(size = [hubHeight, m3_nut_flats, m3_nut_depth], center = true);
					}

					// m3 passage
					translate([-(pulleyHeight / 2 + hubHeight / 2), 0, hubDiameter / 4]) {
						cylinder(d = 3.2, h = hubDiameter, center = true, $fn = 24);
					}

				} // end: rotate
			} // end: rotate
		} // end: for

	} // end: difference

}

```


[User]
I need a customizable cube, but I want it to be more than just a simple box. I'd like to control not only its overall size, but also the individual dimensions (length, width, height), and ideally be able to add rounded edges with a configurable radius.

So, could you generate an OpenSCAD file that creates a cube where I can set:

*   `cube_length`
*   `cube_width`
*   `cube_height`
*   `corner_radius`

If `corner_radius` is set to zero, it should just be a normal box with sharp corners. If it's set to a non-zero value, all edges should be rounded using that radius. I'd like the rounded edges to be smooth and consistent. The default values should be 10 for the length, width, and height, and 0 for the corner radius.

I don't need any libraries for this, I just want everything in one simple `.scad` file if that is possible.

[Assistant]
customizable_cube.scad:
```
size= 10;

cube(size);
```


[User]
I'd like to design a customizable rainmaker stick, and I'm hoping you can help me create the OpenSCAD files for it. I'm envisioning a design with several parts: the main tube segment, a cap for the bottom, a cap for the top, and the little beads that go inside.

First, let's talk about the tube. I need to be able to adjust its outer radius, wall thickness, and overall height. Also, I want to have connector sections at each end of the tube that are shorter than the main tube segment but have a specific height and thickness that I can set. The important part is that inside the tube, there should be a helix-like structure that guides the beads as they fall through the tube. I need to be able to control the angle of this twist.

For the beads, I'll need to control their radius, the number of beads, and the space between them. I'd like to have them arranged in a square grid. I might print the beads themselves, but more likely I will just cut small pieces of filament to use as beads.

The top and bottom caps need to fit the tube and ideally have a slightly rounded outer edge that can be set. I also need to be able to set the height of these caps. They also need to have the connector section that goes into the tube.

I need to be able to pick from one of these options - print only the beads, the main tube segment, the bottom cap or the top cap.

I'm thinking this will probably need to use `linear_extrude` and `minkowski` OpenSCAD primitives. The design should have a lot of parameters, allowing for plenty of customization.

[Assistant]
rainmaker_v3.scad:
```
/* [Global] */

part = "tube"; //[beads:Print beads,tube:Tube segment,tubecapbot:Tube cap bottom,tubecaptop:Tube cap top]

/* ---------------------------------------------------- */
/* [Beads] */
/* ---------------------------------------------------- */
//Beads radius (mm)
bead_r=2;

// How many beads
bead_count=64;  //[1,4,9,25,36,49,64]

//Space between beads (mm)
bead_space=5;

/* ---------------------------------------------------- */
/* [Tube setings] */
/* ---------------------------------------------------- */
// Tube outer radius (mm)
tube_outer_r = 30;
// Tube thickess (mm)
tube_thickness = 1;

// Tube height (mm)
tube_height=100;

// Connector height (mm)
connector_height=20;
// Connector thickness (mm)
connector_thickness=1;

// Twist (in angular degree) of the helix inside the tube (the higher the better, but twist is limited by printer)
twist=270; // [180:450]

/* ---------------------------------------------------- */
/* [Tube caps] */
/* ---------------------------------------------------- */
// Tube cap height (mm)
tube_end_height=1; //[1:5]

/* ---------------------------------------------------- */
/* [Hidden] */
/* ---------------------------------------------------- */
$fn=50;
epsilon=0.1;

bead_count_per_row=sqrt(bead_count);

tube_inner_r = tube_outer_r-tube_thickness;

connector_outer_r=tube_inner_r-epsilon;
connector_inner_r=connector_outer_r-connector_thickness;

tube_end_r=tube_outer_r+1;
minkowski_r=1;

/* ---------------------------------------------------- */
/* Main */
/* ---------------------------------------------------- */

if(part=="beads" ) {
  beads();
}

if(part=="tube" ) {
  rainmaker_tube();
}

if(part=="tubecapbot" ) {
  tube_cap_bottom();
}

if(part=="tubecaptop" ) {
  tube_cap_top();
}

module beads() {
  for (x=[0:bead_count_per_row-1]) {
    for (y=[0:bead_count_per_row-1]) {
      translate([x*(bead_r*2+bead_space),y*(bead_r*2+bead_space),0])
        sphere (r=bead_r,center=true,$fn=10);
    }
  }
}

module rainmaker_tube() {
  // outer tube
  translate([0,0,connector_height])
    _tube(tube_height,
      tube_outer_r,
      tube_inner_r-epsilon*3);

  // inner tube
  difference(){
  color("red") _tube(tube_height,
    connector_outer_r,
    connector_inner_r);

    translate([0, 0, connector_height/2-epsilon]) {
      cube([(connector_outer_r+2*epsilon)*2,2,connector_height+2*epsilon],center=true);
      cube([2,(connector_outer_r+2*epsilon)*2,connector_height+2*epsilon],center=true);
    }
  }
  rotate([0,0,80])
    linear_extrude(height = tube_height, center = false, convexity = 10, twist = twist,$fn=360)
      translate([2*epsilon, 0, 0])
        square([connector_outer_r-3*epsilon,2]);

  rotate([0,0,-100])
    linear_extrude(height = tube_height, center = false, convexity = 10, twist = twist,$fn=360)
      translate([2*epsilon, 0, 0])
        square([connector_outer_r-3*epsilon,2]);

  cylinder(h=tube_height,r1=2,r2=2);
}

module tube_cap_bottom() {
  minkowski() {
    cylinder(h = tube_end_height, r1 = tube_end_r, r2 = tube_outer_r, center = false,$fn=100);
    sphere(r=minkowski_r,$fn=100);
  }

  difference() {
    translate ([0,0,tube_end_height+minkowski_r]) {
        _tube(connector_height,
            connector_outer_r,
            connector_inner_r);
    }
    translate ([0,0,connector_height/2+tube_end_height+minkowski_r]) {
      cube([(connector_outer_r+2*epsilon)*2,2,connector_height+2*epsilon],center=true);
      cube([2,(connector_outer_r+2*epsilon)*2,connector_height+2*epsilon],center=true);
    }
  }
}

module tube_cap_top() {
  minkowski() {
    cylinder(h = tube_end_height, r1 = tube_end_r, r2 = tube_outer_r, center = false,$fn=100);
    sphere(r=minkowski_r,$fn=100);
  }

  translate ([0,0,tube_end_height+minkowski_r]) {
      _tube(connector_height+epsilon,
          tube_outer_r,
          tube_inner_r);
  }
}

module _tube(height,r1,r2) {
  difference() {
    cylinder(h = height, r1 = r1, r2 = r1, center = false,$fn=100);
    translate([0,0,-0.5]) cylinder(h = height+1, r1 = r2, r2 = r2, center = false,$fn=100);
  }
}

```


[User]
Hi! I'm looking to design a Z-probe mount for my 3D printer. I've got an existing design I'm working from, and I'd like to have a parametric version so I can easily adjust things for different sensors and printer setups.

Essentially, it's a bracket that mounts to the side of the X-carriage on a Prusa i3 style printer. The bracket holds a cylindrical sensor (like an inductive probe) and needs to be adjustable in terms of its position relative to the carriage. Here's the breakdown:

**Core Components:**

*   **Side Plate:** This is the main mounting piece that attaches to the X-carriage. It has specific cutouts for the carriage's mounting bolts and a couple of screw holes, one with a slot for a nut.
*   **Probe Mount Bracket:** This is the L-shaped bracket that holds the sensor. It has a cylindrical hole for the sensor and is attached to the side plate with two support arms. It needs to be positioned and rotated properly relative to the side plate and be parametrically adjustable in position.

**Key Parameters I Need:**

*   **`SensorDiameter`**:  The diameter of the cylindrical sensor.
*   **`BracketThickness`**: The thickness of the L-shaped sensor bracket arms.
*   **`BracketPosition`**:  The horizontal position of the sensor bracket relative to the side plate. Positive values move it forward, negative move it back.
*  **`PanelThickness`**: The thickness of the X-carriage panel to mount to (usually 6.35mm on a Makerfarm).
*   **`CircleResolution`**: Resolution for circles and cylinders used in the design.
*   **`ClampCut`**: A boolean flag to enable or disable a cut on the top of the bracket. This allows for easier printing of the top clamp section.
*  **`build_plate_selector`**: An integer to choose from a few different printer builds, or use manual dimensions.
*  **`build_plate_manual_x`**: When the selector is set to 'manual' this is the x dimension.
*  **`build_plate_manual_y`**: When the selector is set to 'manual' this is the y dimension.

**Specific Design Considerations:**

*   The side plate will have mounting holes and nut retainers. One hole should be for an M3 screw, and there should be a nut retainer.
*   The probe mount bracket attaches to the side plate with two support arms, and should be parametrically adjustable in horizontal position via `BracketPosition`.
*   The probe mount should have a cylindrical hole that is sized to accommodate the `SensorDiameter`
*   The `ClampCut` option should cut a slot in the top of the clamp to help with printing.

**General Requirements:**

*   I'd like the design to be in multiple files if that makes sense. It'd be great to have a library file that includes any common utilities.
*   I'd like to use the `build_plate` module from the `utils` library that is used in the example.
*   The code should be well-commented, making it easy to understand what is going on.

Could you generate a parametric OpenSCAD design based on these specifications? I'm not too worried about the specific dimensions of the X-Carriage side panel itself as I already have those as polygon coordinates, but I'd like a function to generate it from those coordinates just in case, which you can call `XSidePlate`. Thanks!

[Assistant]
z_probe_remix20151010.scad:
```
/* [Basic Settings] */

// What is the diameter of your sensor?
SensorDiameter = 18;

// How thick do you want the bracket arms to be?
BracketThickness = 6;

// Where should the bracket be? 0 is default, positive moves it forward, negative move it back
BracketPosition = 0; // [-25:30]

/* [Advanced Settings] */

// The thickness of the wooden panels of the carriage? Usually 6.35 for MakerFarm i3
PanelThickness=6.35;

// Cylinder resolution. set it to 10 if you're mucking about, about 120 if you're exporting STL's
CircleResolution = 60;

// Cut the arms if you're having trouble printing the tops of the clamps
ClampCut = false;

/* [Printer] */
build_plate_selector = 3; //[0:Replicator 2,1: Replicator,2:Thingomatic,3:Manual]

//when Build Plate Selector is set to "manual" this controls the build plate x dimension
build_plate_manual_x = 100; //[100:400]

//when Build Plate Selector is set to "manual" this controls the build plate y dimension
build_plate_manual_y = 100; //[100:400]

/* [Hidden] */
// Jitter is used to prevent coincident-surface problems with CSG. Should be set to something small.
j = 0.01;

// Short-cuts used to make arrays easier to reference
x=0; y=1; z=2;

// Convenience values
SensorRadius = SensorDiameter/2;
$fn = CircleResolution;

use<utils/build_plate.scad>;

// Side panel with the various holes cut out
module XSidePlate(endstop_hole=false)
{
	translate([0, 0, PanelThickness])
	rotate([180, 0, 0])
	difference()
	{
		linear_extrude(height=PanelThickness)
		polygon(points=[
			[0, 0],       // 0
			[12.2, 0],    // 1
			[12.2, -5.8], // 2
			[31.9, -5.8], // 3
			[31.9, 0],    // 4
			[45, 0],      // 5
			[45, 19],     // 6
			[25, 28.5],   // 7
			[0, 28.5],    // 8
			[0, 22.5],    // 9
			[-6, 22.5],   //10
			[-6, 16.5],   //11
			[0, 16.5]     //12
		]);

		// Main mounting bolt hole
		translate([22.05, -2.9, -j])
		cylinder(h=PanelThickness+j+j, r=2, $fn=30);

        // Rear mount screw hole and nut retainer
        translate([-1,11,PanelThickness/2]) rotate([0,90,0]) cylinder(r=1.6, h=13);
        translate([9,11,PanelThickness/2]) cube([2.8,5.8,PanelThickness+2],center=true);
        }
}

module XSideProbeMountBracket(extend = 0)
{
	translate([-SensorRadius-BracketThickness, 0, 0])
	difference()
	{
		union()
		{
			// Lower squared off part of bracket
			translate([0, 0, -extend])
			cube([SensorDiameter+BracketThickness*2, BracketThickness, SensorRadius+BracketThickness+extend]);
			intersection()
			{
				// Outer boundary of the whole bracket
				cube([SensorDiameter+BracketThickness*2, BracketThickness, SensorDiameter+BracketThickness*2]);

				// Upper rounded part of bracket
				translate([SensorRadius+BracketThickness, 0, SensorRadius+BracketThickness])
				rotate([-90, 0, 0])
				cylinder(r = SensorRadius+BracketThickness, h = BracketThickness);
			}
		}

		// Cut a slot in the top of the clamp?
		if(ClampCut)
		{
			translate([SensorRadius+BracketThickness, BracketThickness+j, 0])
			rotate([90, 0, 0])
			linear_extrude(height=PanelThickness+j*2)
			polygon(points=[
				[-SensorDiameter, 2*SensorDiameter+BracketThickness*2],
				[SensorDiameter, 2*SensorDiameter+BracketThickness*2],
				[0, (SensorDiameter*0.75)+BracketThickness]
			]);
		}

		// Cut the hole for the sensor
		translate([SensorRadius+BracketThickness, -j, SensorRadius+BracketThickness])
		rotate([-90, 0, 0])
		cylinder(r = SensorRadius, h = BracketThickness+j*2);
	}
}

module XSideSensorMount()
{
	difference()
	{
		union()
		{
			// Main body
			scale([-1, 1, 1])
			XSidePlate();

			// Supports
			translate([-15-BracketPosition, -5, +j])
			{
				translate([0, -14, 0])
				rotate([0, 180, 180])
				XSideProbeMountBracket(extend = PanelThickness);

				translate([0, -1, 0])
				rotate([0, 180, 0])
				XSideProbeMountBracket(extend = PanelThickness);
			}
		}

	}
}

translate([20, -12, 6.35])
rotate([180, 0, 0])
XSideSensorMount();

%build_plate(build_plate_selector, build_plate_manual_x, build_plate_manual_y);

```


[User]
I'm looking for a parametric OpenSCAD design for a T-nut that I can use with 2020 aluminum extrusion. I want to be able to customize the design for different screw sizes, nut sizes, and overall dimensions.

I'm specifically aiming for a design that has a slot to hold a nut, and ideally, I'd like to be able to make a grid of these T-nuts easily.

Here's what I need to be customizable:

*   **Nut Size (flat-to-flat):**  This needs to be adjustable to fit different nut sizes. I'd like to be able to specify the flat-to-flat measurement directly.
*   **Screw Hole Diameter:** I need to be able to change the diameter of the hole for the screw.
*   **Nut Rotation:**  I'd like to control the rotation of the nut within the plastic part.
*   **T-Nut Length:**  The overall length of the T-nut needs to be adjustable.
*   **Number of Rows and Columns:** I want to easily generate an array of T-nuts with adjustable rows and columns.
*   **Nut Depth Adjustment:**  A parameter to adjust the vertical position of the nut within the plastic body would be helpful, to make the nut sit slightly higher or lower within the printed piece.

For the design, I envision a simple T-nut with a hexagonal recess to hold the nut and a hole for the screw. I'm picturing something similar to what's described in the provided text - basically a T-nut with a slot for the nut. I do not want a design that overlaps the extrusion slot in the way that some T-nuts do.

I'm not particularly concerned about fine details like fillets or chamfers for now, but I want the design to be robust and easily customizable to fit different hardware. It'd also be great to have this all in one `.scad` file, if possible. I would like the use of linear extrude to generate the T-Nut base and a hull of hexagonal shapes to define the nut cavity. I don't need to use any external libraries.

[Assistant]
OpenBuild_t-nut_M3.scad:
```
// Size of the hole for the nut (flat-to-flat)
nutSize = 5.5;

// Diameter for the screw hole
holeSize = 3.1;

// Rotation for the nut
nutRotation = 90;

// Length of the T-Nut
length = 10;

// Number of Rows and Columns of T-Nuts
rows = 5;
columns = 10;

// Adjustment for height of nut inside T-Nut
depthChange = 0;

/* {Hidden} */

// definitions for the hexagonal nut shape
module box(w,h,d) {
	scale ([w,h,d]) cube(1, true);
}
module hexagon(height, depth)
{
	boxWidth=height/1.75;

	union()
	{
		box(boxWidth, height, depth);
		rotate([0,0,60]) box(boxWidth, height, depth);
		rotate([0,0,-60]) box(boxWidth, height, depth);
	}
}

module nut()
{
	rotate([180,0,0])
	difference()
	{
		translate([-5.25, -length/2, 0]) rotate([270,0,0]) linear_extrude(height=length) polygon([ [0,0], [10.5, 0], [10.5, 1.4], [7.75, 3.9], [2.75, 3.9], [0, 1.4] ]);
		translate([0,0,-1.2]) cylinder(d=holeSize, h=1.25, $fn=100);

		hull()
		{
			translate([0,0.3,-5+depthChange]) rotate([0,0,nutRotation]) hexagon(nutSize, 8.0);
			translate([0,-0.3,-5+depthChange]) rotate([0,0,nutRotation]) hexagon(nutSize, 8.0);
		}
	}
}

for(x=[1:columns]) for(y=[1:rows])
{
	translate([x*13, y*(length + 2), 0]) nut();
}

//translate([-6, -7.5, 0]) cube([120, 120, 1]);
//nut();

```


[User]
I'd like to create some parametric coasters based on the periodic table. I want each coaster to feature an element's symbol, name, and atomic mass, and also represent its electron configuration visually.

Specifically, I want the following:

*   **Element Selection:** The user should be able to select an element from a list (ideally using a dropdown or similar parameter in the OpenSCAD customizer) corresponding to the first 20 elements in the periodic table (Hydrogen to Calcium).
*   **Data Display:** The coaster should prominently display:
    *   The element's atomic number.
    *   The element's symbol (e.g., "H", "He", "Li").
    *   The element's full name (e.g., "Hydrogen", "Helium", "Lithium").
    *   The element's atomic mass.
*   **Visual Electron Configuration:** The electron configuration should be represented by concentric circles (representing electron shells) around a central point. The number of electrons in each shell should be visualized as small spheres equally spaced around each circle. The radius of each circle should increase as the atomic number increases, and the spheres should be consistently sized.
*   **Coaster Shape:** The base of the coaster should be a cylinder with a small rim around the top. The entire design should be centered on the base of the coaster.
*   **Parametric Design:** All dimensions, such as coaster diameter, rim height, text size, spacing, and the circles' radii, should be easily adjustable using parameters in OpenSCAD's customizer.
*   **Font:** I'd like to use the "Russo One" font.

I'm attaching the code I wrote for a prototype, but I'd like a more robust version. This version's a bit messy, and I'd like it to be written in a clearer way that I can build off. Please feel free to break this up into separate files if necessary.

[Assistant]
Element_Coasters.scad:
```
// preview[view:south, tilt:top]

//Select the element you want on the coaster.
choose_the_element=1; //[1:Hydrogen, 2:Helium, 3:Lithium, 4:Beryllium, 5:Boron, 6:Carbon, 7:Nitrogen, 8:Oxygen, 9:Fluorine, 10:Neon, 11:Sodium, 12:Magnesium, 13:Aluminium, 14:Silicon, 15:Phosphorus, 16:Sulfur, 17:Chlorine, 18:Argon, 19:Potassium, 20:Calcium]

atomic_number=choose_the_element;

coaster(atomic_number);

element_data=[
[0, "", "", 0],
[1, "H", "Hydrogen", 1.008],
[2, "He", "Helium", 4.003],
[3, "Li", "Lithium", 6.941],
[4, "Be", "Beryllium", 9.012],
[5, "B", "Boron", 10.811],
[6, "C", "Carbon", 12.011],
[7, "N", "Nitrogen", 14.007],
[8, "O", "Oxygen", 15.999],
[9, "F", "Fluorine", 18.998],
[10, "Ne", "Neon", 20.180],
[11, "Na", "Sodium", 22.990],
[12, "Mg", "Magnesium", 24.305],
[13, "Al", "Aluminium", 26.982],
[14, "Si", "Silicon", 28.086],
[15, "P", "Phosphorus", 30.974],
[16, "S", "Sulfur", 32.065],
[17, "Cl", "Chlorine", 35.453],
[18, "Ar", "Argon", 39.948],
[19, "K", "Potassium", 39.098],
[20, "Ca", "Calcium", 40.078]
];

module coaster(atomic_number){

    symbol=element_data[atomic_number][1];
    element=element_data[atomic_number][2];
    atomic_mass=element_data[atomic_number][3];

    $fn = 50;
    difference(){
        cylinder(r=45, h=4);
        translate([0, 0, 2]){
            if(atomic_number<=2){
                cylinder(r=22, h=3);
            }
            if(atomic_number<=10 && atomic_number>2){
                cylinder(r=29, h=3);
            }
            if(atomic_number<=18 && atomic_number>10){
                cylinder(r=36, h=3);
            }
            if(atomic_number<=20 && atomic_number>18){
                cylinder(r=43, h=3);
            }
        }
    }
    if(atomic_number>18){
        translate([0, 0, 1]){
            difference(){
                cylinder(r=41, h=3);
                cylinder(r=36, h=4);
                if(atomic_number<=20){
                    for(r=[0:(360/(atomic_number-18)):360]){
                        rotate([0,0,r]){
                            translate([0, 38.5, 4]){
                                sphere(r=2);
                            }
                        }
                    }
                }
            }
        }
    }
    if(atomic_number>10){
        translate([0, 0, 1]){
            difference(){
                cylinder(r=34, h=3);
                cylinder(r=29, h=4);
                if(atomic_number<=18){
                    for(r=[0:(360/(atomic_number-10)):360]){
                        rotate([0,0,r]){
                            translate([0, 31.5, 4]){
                                sphere(r=2);
                            }
                        }
                    }
                }
                if(atomic_number>18){
                    for(r=[0:(360/8):360]){
                        rotate([0,0,r]){
                            translate([0, 31.5, 4]){
                                sphere(r=2);
                            }
                        }
                    }
                }
            }
        }
    }
    if(atomic_number>2){
        translate([0, 0, 1]){
            difference(){
                cylinder(r=27, h=3);
                cylinder(r=22, h=4);
                if(atomic_number<=10){
                    for(r=[0:(360/(atomic_number-2)):360]){
                        rotate([0,0,r]){
                            translate([0, 24.5, 4]){
                                sphere(r=2);
                            }
                        }
                    }
                }
                if(atomic_number>10){
                    for(r=[0:(360/8):360]){
                        rotate([0,0,r]){
                            translate([0, 24.5, 4]){
                                sphere(r=2);
                            }
                        }
                    }
                }
            }
        }
    }
    translate([0, 0, 1]){
        difference(){
            cylinder(r=20, h=3);
            cylinder(r=15, h=4);
            if(atomic_number<=2){
                for(r=[0:(360/atomic_number):360]){
                    rotate([0,0,r]){
                        translate([0, 17.5, 4]){
                            sphere(r=2);
                        }
                    }
                }
            }
            if(atomic_number>2){
                for(r=[0:(360/2):360]){
                    rotate([0,0,r]){
                        translate([0, 17.5, 4]){
                            sphere(r=2);
                        }
                    }
                }
            }
        }
    }
    font_choice="Russo One"; //set font
    linear_extrude(height=4){
        translate([0, 10, 2]){
            text(str(atomic_number), font=font_choice, size=3, halign="center", valign="center");
        }
        translate([0, 2, 2]){
            text(symbol, size=6, font=font_choice, halign="center", valign="center");
        }
        translate([0, -6, 2]){
            text(element, size=3, font=font_choice, halign="center", valign="center", spacing=1.2);
        }
        translate([0, -10, 2]){
            text(str(atomic_mass), size=3, font=font_choice, halign="center", valign="center", spacing=1.2);
        }
    }
}
```


[User] I'd like a customizable OpenSCAD design for an allen wrench, or hex key. I need to be able to specify the diameter of the key, its height, the length of the short arm, and the number of faces it has. I'm looking for a standard hex key, so the number of faces should default to 6 but I want the ability to change it for experimenting, maybe with an octagon or something. I want the handle to be a cylinder that has a diameter that is equal to the key diameter, and the short arm should also be a cylinder with that same diameter. The short arm should also be offset so it looks like a typical allen key. I'd really like it if the code was nicely commented too.

[Assistant]
allen_wrench.scad:
```
// Key diameter
diameter=5;

//Height
height=50;

//Lenth
lenth=20;

//Number of faces
$fn=8;

/* [Hidden] */

z=(-height)+diameter/2.165;

x=diameter/-2.1645021645;

rotation=(360/$fn)/2;

radius=diameter/2;

rotate([0,0,rotation]){
cylinder(r=radius, h=height);
    }

rotate([0,90,0]){
    translate([z,0,x]){
        rotate([0,0,rotation]){
            cylinder(r=radius, h=lenth);
        }
    }
}
```


[User]
I'd like to design a round lid with a customizable hexagonal pattern cut into it. I've already got a square version of this pattern, but I need one that's circular now.

The lid should have a circular border and a circular cutout with the hexagonal pattern. The pattern itself needs to be fully parametric, meaning I want to be able to control things like:

*   **Overall diameter:**  The diameter of the lid.
*   **Overall height:** The total thickness of the lid (although I think I'll control border and pattern height separately).
*   **Border width:** The thickness of the solid outer edge.
*   **Border height:** The height of the border part of the lid.
*   **Hex radius:** The size of the individual hexagons.
*   **Hex border width:** The "thickness" of each hexagon, meaning how deep it is cut and how thick the wall around each hexagon will be.

So essentially, the lid will be a cylinder with a smaller cylinder hollowed out from the center, and that hollowed-out section will have the hex pattern. I need a single OpenSCAD file that has all of those parameters and that I can customize to generate the lid. I'd like to be able to control everything through parameters at the top of the file as I usually do.

I'm familiar with standard OpenSCAD primitives and functions but I haven't used any external libraries before. I'm okay with the standard way of making a hollowed cylinder using the `difference` operation if that's what you would normally do.

[Assistant]
round_hexgrid.scad:
```
// Customizable hex pattern
// Created by Kjell Kernen
// Date 11.10.2015

/*[Pattern Parameters]*/
// of the pattern in mm:
diameter=100;           // [10:150]

// of the pattern in tens of mm:
height=20;              // [2:200]

// in tens of mm:
border_width=20;        // [2:100]

// in tens of mm:
border_height=30;       // [2:100]

// in mm:
hex_radius=8;           // [1:20]

// in tens of mm:
hex_border_width=25;    // [2:50]

/*[Hidden]*/
x=sqrt(3/4*hex_radius*hex_radius);
ystep=2*x;
xstep=3*hex_radius/2;

module hex(x,y)
{
	difference()
	{
		translate([x,y,-height/20])
			cylinder(r=(hex_radius+hex_border_width/20), h=height/10, $fn=6);
		translate([x,y,-(height/20)-1])
			cylinder(r=(hex_radius-hex_border_width/20), h=(height/10)+2, $fn=6);
	}
}

//Pattern
intersection()
{
    intersection()
	{
		for (xi=[0:xstep:diameter])
			for(yi=[0:ystep:diameter])
				hex(xi-diameter/2,((((xi/xstep)%2)==0)?0:ystep/2)+yi-diameter/2);
		translate([-diameter/2, -diameter/2, -height/20])
			cube([diameter,diameter,height/10]);
	}
	cylinder( d=diameter, h=height );
}

// Frame
difference()
{
	cylinder( d=diameter, h=border_height/10 );
	translate ([0,0,-1])
		cylinder( d=diameter-border_width/10, h=(border_height/10) + 2  );
}

```


[User]
Hey, I'm looking to design a customizable bin using OpenSCAD, and I have a few ideas about how it should work.

Basically, I need a rectangular bin with rounded edges, a label on each of its four sides, and a customizable main text label. I also want to be able to set the overall height and width of the bin, the wall thickness, and the text for each label. It'd be nice to have the main text be centered on each face, too.

Here's a breakdown of what I'm after:

*   **Shape:** The bin itself should be a rectangular prism with rounded vertical edges.
*   **Dimensions:** I need to specify:
    *   `binHeight`: The height of the bin.
    *   `binWidth`: The width and depth of the bin (it should be a square base).
    *   `binThickness`: The thickness of the bin walls.
*   **Labels:**
    *   Four labels, one on each side, horizontally centered.
    *   The text of each label should be customizable using `label[0-3]` strings.
    *   These labels should be placed at a fixed distance below the top of the bin (like 17mm). They also should be slightly raised from the surface of the bin wall.
*   **Main Text:**
    *   The main text, `mainText`, should also be customizable.
    *   It should be centered horizontally and vertically on each face, and slightly raised from the surface.
*   **Rounding:** The vertical edges should be rounded.
*   **Text:** The text should be raised a bit from the surface.
*   **Libraries:** I'd like to be able to use `minkowski` and `linear_extrude`, and so on, so I'm assuming no specific libraries are necessary beyond what OpenSCAD provides by default.

Could you generate the OpenSCAD code for this? I'm pretty excited to try this out.

[Assistant]
Bin.scad:
```
$fn=200;

gBinHeight=100;
gBinWidth=100;
gBinThickness=3;

gBinName="Recycle";

difference()
{
	minkowski()
	{
		translate([1,1,0]*-gBinWidth/2)
		cube([gBinWidth, gBinWidth, gBinHeight]);
		cylinder(r=2, h=1);

	}

	for(i = [0:3])
	{
		rotate([0,0,90*i])
		translate([0,-gBinWidth/2+gBinThickness,gBinHeight-17])
		rotate([90,0,0])
		linear_extrude(gBinThickness*2)
		text(gBinName, halign="center", valign="center");
	}

	minkowski()
	{
		translate([1,1,0]*-(gBinWidth/2-gBinThickness))
		translate([0,0,gBinThickness])
		cube([gBinWidth-gBinThickness*2, gBinWidth-gBinThickness*2, gBinHeight]);
		cylinder(r=2, h=1);
	}
}

```


[User]
I need a parametric OpenSCAD design for a bearing spacer, basically a cylindrical washer with a lip on one side. The main body of the spacer will have an inner and outer diameter and a height. The lip will be on one side, will have a given thickness, and a given width, which will be added to the outer diameter of the main body.

So I need parameters for:

*   `inner_diameter`: The inner diameter of the spacer.
*   `outer_diameter`: The outer diameter of the main body of the spacer, not including the lip.
*   `height`: The height of the main body of the spacer.
*   `lip_thickness`: The thickness of the lip.
*   `lip_width`: The width of the lip, which will be added to the outer diameter when generating the lip.
*   `fn`: The number of fragments for generating the cylinders.

The design should be made from two `difference()` operations. The first will create the main body by subtracting the inner cylinder from the outer cylinder, and the second will create the lip by subtracting the inner cylinder from the outer cylinder with the lip. The main body will also need to be translated up by the `lip_thickness` to align correctly with the lip.

Please provide me with a single .scad file with the design.

[Assistant]
BearingSpacer.scad:
```
/* [Spacer] */
inner_diameter = 22.3;
outer_diameter = 26.5;
// (not including lip thickness)
height = 6;
/* [Lip] */
lip_thickness = 1;
// (will be added to outer diameter)
lip_width = 2;
/* [Hidden] */
fn = 100;

// Spacer
translate([0, 0, lip_thickness])
    difference() {
        cylinder(r=outer_diameter/2, h=height, $fn=fn);
        cylinder(r=inner_diameter/2, h=height, $fn=fn);
    }

// Lip
difference() {
    cylinder(r=(outer_diameter/2)+lip_width, h=lip_thickness, $fn=fn);
    cylinder(r=inner_diameter/2, h=lip_thickness, $fn=fn);
}
```


[User]
I'd like to create a rounded cylinder that can be customized. It should have a main cylinder with a radius and a height, and then have rounded edges at the top and/or bottom.

Specifically, I need the following:

*   **Base Cylinder Parameters:** I need to be able to specify the radius (`r`) and height (`h`) of the main cylinder.
*   **Rounding Parameter:** I need a `rounding` parameter to control the radius of the rounding on the edges. This rounding should not exceed the cylinder radius or the height (or half the height if both ends are rounded).
*   **Top-Only Rounding Option:** I want a boolean option, `roundTopOnly`, so I can choose whether to round just the top edge, or both the top and bottom edges. If `roundTopOnly` is true, then just the top is rounded, otherwise both are rounded.
*   **Fragment Control:** I need a way to control the number of fragments (`fn`) used to render the rounded edges. This should be equivalent to the `$fn` parameter in OpenSCAD and it should support global `$fs` and `$fa` parameters in the same way.
*   **Library Usage:** I need to be able to easily use this design in other OpenSCAD files by importing it as a library.
*   **Customizer Compatibility:** I should be able to use it as a customizer object with the above parameters.

Essentially, I want a module that behaves like a cylinder, but with rounded edges. I'm not looking for a simple fillet operation because I need to be able to specify separate rounding radii. I want the corners to be smooth using a sphere-like shape for the rounding.

The `roundedCylinder.scad` file I've provided shows what I'm after. Can you generate a fresh version of this in a file, or multiple files if you think that's cleaner. I'm not looking for existing OpenSCAD libraries.

[Assistant]
roundedcylinder.scad:
```
//Radius of the cylinder
r=20;

// Height of the cylinder
h=50;

// rounding radius on the edge of the cylinder
rounding=5;

// Should we round only top?
roundTopOnly=false; // [true, false]

// Number of fragments of the cylinder.
fn=100;

module roundedCylinder(r, h, rounding, roundTopOnly=false){
    function getFn(r, fn, fs, fa) =
        (fn > 0.0) ? floor(fn >= 3 ? fn : 3)
                   : ceil(max(min(360.0 / fa, r*2*PI / fs), 5));

    function point(a, c, N) =
        c*(N+1) + a;

    function face(a, c, N, flag) =
        let (c1 = c==0?4*N:c-1)
            [
                point(a, c, N),
                point(a-1, c1, N),
                flag ? point(a-1, c, N) : point(a, c1, N)
            ];

    fn = getFn(r, $fn, $fs, $fa);
    K=fn/360;
    N=K*90;
    points = [
        for (c= [0: 4*N])
            for (a = [0 : N])
                let (b=a/K, d=c/K)
                    [
                        rounding*sin(b) * cos(d) + (r-rounding)*cos(d),
                        rounding*sin(b) * sin(d) + (r-rounding)*sin(d),
                        rounding*cos(b)
                    ]
            ];

    faces = [
        for (c= [0:4*N])
            for (a = [1:N])
                for (flag=[false, true])
                    face(a, c, N, flag)
            ];

    hull(){
        translate([0, 0, h-rounding])
            polyhedron(points=points, faces=faces);

        if(!roundTopOnly){
            translate([0, 0, rounding])
            rotate([180, 0, 0])
                polyhedron(points=points, faces=faces);
        }

        if(roundTopOnly){
            cylinder(r=r, h=h-rounding);
        }

    }
}

roundedCylinder(r=r, h=h, rounding=min(rounding, h/(roundTopOnly?1:2), r), roundTopOnly=roundTopOnly, $fn=fn);
```


[User]
Hey, I've been playing around with making tree-like structures in OpenSCAD, and I've got an idea for something really customizable. I’d like to create a parametric tree generator that allows for a lot of control over the shape and branching. I'm hoping you can help me design the necessary OpenSCAD files.

Basically, I want to be able to generate a tree by recursively adding branches. Each branch should be a cylinder, and the parameters I want to be able to control are:

*   **Level:** The recursion depth (how many levels of branching there are).
*   **`rr1`:** The radius at the base of the current cylinder branch.
*  **`rr2`:** The radius at the tip of the current cylinder branch.
*   **`lh`:** The length/height of the current cylinder branch.
*   **`c`:** The number of child branches emanating from each parent branch (around the circumference).
*   **`a`:** The initial angle of the child branches away from the parent (in degrees).
*   **`amod`:** An angle modifier that changes the angle of child branches relative to their position around the circumference of the parent branch
*   **`deltarr`:** The scaling factor for the tip radius (`rr2`) of child branches relative to the parent's.
*   **`deltalh`:** The scaling factor for the length/height (`lh`) of child branches relative to the parent's.
*   **`deltaa`:** The scaling factor for the branch angle (`a`) of child branches relative to the parent's.
*   **`roffset`:** A rotation offset to apply around the branch axis.

The basic idea is that the trunk is a cylinder. Then, at the top of each branch, a certain number of child branches are created around the circumference, angling outwards by some amount, and each of those gets the same treatment recursively. The parameters for each generation of child branches can be a function of the parent branch.

I'm thinking a single SCAD file would be sufficient, a module that takes all those parameters, and a call to that module with some default values. I’m not too fussed about rendering performance for now. It would be helpful to have the module use the name `rec`, like it does in my example. Also, I'd like the `cylinder` command to have `$fn` (number of facets) set externally by the user so that the user can define the smoothness of the cylinders. I don't think I need any specialized libraries for this. Thanks!

[Assistant]
recursivetreev1.scad:
```
module rec(level=3, rr1=2, rr2=1.8, lh=20, c=3, a=45, amod=.1, deltarr=.6, deltalh=.8 , deltaa=1.1, roffset = 0) {
  cylinder(r1=rr1, r2=rr2,h=lh);
  if (level > 1) {
    translate([0,0,lh]) {
      for (r=[360/c:360/c:360])
        translate([0,0,-rr1 ]) rotate([0,a -((r - 360/c ) * amod) ,r + roffset]) rec(level=level-1, rr1=rr2, rr2=rr2*deltarr, lh=lh *deltalh, c=c,  a=a*deltaa, amod=amod, deltarr=deltarr, deltalh=deltalh, deltaa=deltaa, roffset=roffset+1);
    }
  }
}

rec(level=4, rr1=2, rr2=1.2, lh=20, c=5, a=25, amod=0.35, deltarr=.5, deltalh=.75, deltaa=.7, roffset = -50, $fn=20);
```


[User]
I'd like to design a parametric orchid pot, and I'm having trouble figuring out how to make the mesh pattern correctly. It needs to be a tapered pot with a brim, and the mesh should be consistent but also scaled to the taper. Here's a breakdown of what I'm looking for:

**Overall Shape:**

*   The pot should be a tapered cylinder, wider at the top than the bottom.
*   It needs a brim that extends outwards from the top edge of the pot.
*   The base of the pot should be flat.

**Parameters:**

*   `diameter`: The diameter of the top of the pot.
*   `height`: The total height of the pot (excluding the brim).
*  `ratio`: A ratio (less than 1.0) that controls the taper. A ratio of 1 means the pot is a straight cylinder. A ratio of 0.5 means that the diameter of the bottom will be half the top.
*   `wall`: The thickness of the pot walls.
*   `size`: The size of the mesh holes.
*   `shape`: The shape of the mesh holes, either a cube or a cylinder (circle).
*   `brim_girth`: The width of the brim extending outwards from the pot.
*   `brim_thickness`: The thickness of the brim.
* `$fn`: to control the smoothness of the curves (I plan on using 24 for testing).

**Mesh Pattern:**

*   The mesh should be created by a series of holes that are evenly spaced around the pot and in columns from top to bottom.
*   The spacing of the holes should be based on the `size` parameter, and a certain amount of space should be between holes in a row and between columns of holes.
* The columns should be staggered based on the taper of the pot.
*   The hole pattern should not overlap.

**Output:**

*   I'd like to have three options for the output: just the pot itself (with mesh), just the brim, or both the pot and the brim combined in a single object.

I'm thinking the design will need to have modules for:

*   The main structure of the pot with the mesh pattern (including the main difference of the cup).
*   The brim (as a separate module so it can be selected separately).
*   A module to create the perforations (the holes) in the pot, and how they will be positioned.
*   A module for the single "shaft" hole itself (either a cube or a cylinder).
* A module for the tapered part of the pot (the "cup").

I don't need the code to use any particular library, so please don't worry about that. I just want plain OpenSCAD. I'm really struggling with the logic for staggering the mesh holes based on the taper - could you please focus on making that correct?

[Assistant]
latest_orchid_pot_-195-170.scad:
```
// configured
// part
which = "pot"; // [pot:pot,brim:brim,both:both]
// top
diameter = 195;
// height
height = 170;
// taper
ratio = .95;
// thickness
wall = 2.4;
// mesh hole
size = 5;
// hole
shape = "cylinder"; // [cube:Square,cylinder:Circle]
// smoothing
$fn = 24;
// brim
girth=3;
// brim
thickness=2.4;
// derived
radius = diameter / 2;
circumference = PI * diameter;
// function
function space() = shape=="cube" ? size / 1.4142 : size;
// procedures
main();
module main() {
	both = which == "both";
	if (both || which == "pot") {
		difference() {
			pot();
			mesh();
		}
	}
	if (both || which == "brim") {
		brim();
	}
}
module brim() {
	position = diameter + radius;
	translate([0,0,thickness])
	difference() {
		translate([position, 0, -thickness])
			cylinder(r = radius + wall + girth, h = thickness);
		translate([position, 0, -height + wall])
			cup(radius);
	}
}
module mesh() {
	// perforate vessel
	// fit as many as can be around in a row, the smallest row
	count = circumference * ratio / (space() + space() / 2);
	step = 360 / count;
	for (i = [0 : step : 360 - step]) {
		rotate([0, 0, i]) {
			holes();
		}
	}
}
module holes() {
	// single column of holes
	// fit as many as can be top to bottom in a column
	steps = (height - wall) / (space() + space() / 2);
	stepsize = space() + space() / 2;
	// do not overlap these and create many unions or gcal will choke (#350)
	// stagger inward based on taper
	offset = (diameter - (diameter * ratio)) / steps / 2;
	function stagger(_i) = (steps - _i) * offset;
	for(i = [1 : 1 : steps]) {
		translate([0, stagger(i), stepsize * i - space() / 2])
			shaft();
	}
}
module shaft() {
	// single hole
	rotate([90, 45, 0]) {
		if (shape == "cube") {
			translate([0, 0, radius])
			cube([space(), space(), radius / 2], center = true);
		}
		else {
			translate([0, 0, radius])
			cylinder(r = space()/2, h = radius / 2, center = true );
		}
	}
}
module pot() {
	// create vessel and hollow it
	difference() {
		cup(radius);
		translate([0, 0, wall])
			cup(radius - wall);
		translate([0,0,height])
			cylinder(r = radius + wall, h=wall);
	}
}
module cup(_radius) {
	// create tapered shape
	hull() {
		cylinder(r = _radius * ratio);
		translate([0, 0, height]) cylinder(r = _radius);
	}
}

```