[User]
Hey, I'm looking to create a customizable bracelet design based on a trigonometric function, kind of like a wavy band. I saw a design that used a "function_trace" module, and that seems like a good way to go.

Here's what I need in the OpenSCAD file:

*   **Basic Shape:** It should generate a bracelet with a generally circular shape, but with an adjustable wavy pattern along its circumference. The wave should be defined by a sine function, and I'd like to control its amplitude and frequency.

*   **Parameters:**
    *   `diameter`: Overall diameter of the bracelet in millimeters.
    *   `height`: Height of the bracelet in millimeters.
    *   `amplitude`: Amplitude of the sine wave, affecting how pronounced the waves are.
    *   `frequency`: Frequency of the sine wave, controlling the number of waves (or "spokes") around the bracelet.
    *   `thickness`: Thickness of the bracelet band in millimeters.
    *    `twist`: Amount of twist (degrees) applied to the bracelet's height.

*   **Function:** Use a function like `g(t)` to define the points along the wave. It should incorporate the `radius`, `amplitude`, and `frequency`.
*   **Module:** The core part should use a `function_trace` module, that takes a `radius` (the bracelet's band thickness), `step`, and `end` as parameters. This `function_trace` should use `hull()` and `translate` to make the band along the curve. The step should be controlled as a variable `step`, defined by some factor times 1.
*   **Extrude:** The main bracelet should be made using `linear_extrude` to give it height and twist, and using the `function_trace` output as its base.

I don't have any OpenSCAD code to give you, as I need this generated from scratch. I'm not using any external libraries like MCAD, BOSL, or anything like that either. Could you please generate an OpenSCAD file that implements this bracelet design with the parameters and function I've described? The output should be a 3D printable file.

[Assistant]
day328_functionbracelet_SUN.scad:
```
// mathgrrl function bracelet - SUN MODEL

/////////////////////////////////////////////////////////
// resolution parameters

$fn = 24*1;
step = .25*1;  // smaller means finer

// Thickness, in mm (recommend between .2 and .8)
th = .2*1;

/////////////////////////////////////////////////////////
// size parameters

// Diameter of the bracelet, in mm (should exceed the wide diameter of your wrist so that you can get the bracelet over your hand)
diameter = 50;

radius = diameter/2;

// Height of the bracelet, in mm (along your wrist)
height = 10;

// Amplitude of the wave, in mm (suggest between 4 and 8, with higher numbers being more flash but less practical; higher amplitude can allow smaller diameters)
amplitude = 8;

// Frequency of the wave (number of spokes)
frequency = 13;

// Amount of twist (recommend 0-10 for best printability)
degrees = 0;

/////////////////////////////////////////////////////////
// define the wrapped wave function

function g(t) =
   [ (radius+amplitude*(1+sin(frequency*t)))*cos(t),
     (radius+amplitude*(1+sin(frequency*t)))*sin(t),
     0
   ];

/////////////////////////////////////////////////////////
// renders

// the bracelet
linear_extrude(height=height,twist=degrees,slices=height/.4)
 function_trace(rad=th, step=step, end=360);

/////////////////////////////////////////////////////////
// module for tracing out a function

module function_trace(rad, step, end) {
 for (t=[0: step: end+step]) {
  hull() {
   translate(g(t)) circle(rad);
   translate(g(t+step)) circle(rad);
       }
   }
};
```


[User]
Hi, I'm looking to design a customizable rod holder for a project I'm working on. I have a basic design in mind, and I'd like you to help me generate the OpenSCAD code for it.

The basic idea is a C-shaped clamp that will hold a rod, and also clamp onto another surface. The clamp will have a thin, flexible 'wall' to apply pressure without damaging the surface it's clamped to. I'd like to be able to adjust the following parameters:

*   `t`: The default profile thickness of the clamp's main structure.
*   `d`: The diameter of the rod to be held.
*   `clearance`: Extra clearance to account for 3D printer tolerances. This should apply to all internal openings, including screw holes.
*   `l`: The length of the top and bottom sides of the C-shaped clamp.
*   `w`: The width between the top and bottom sides of the C-shaped clamp, representing the thickness of the object it's clamping to.
*   `h`: The height of the clamp and rod holder. The number of screw holes should be dependent on the clamp height.
*   `Dscrew`: The diameter of the screws to be used to pressure the clamp.
*   `n`: A thickening factor applied to strengthen the bracket. This should make the clamp able to be tightened more firmly.

The design will be created by starting with a few intersecting cubes, then cutting out the necessary voids to form the C shape and rod holder. The number and position of screw holes should be calculated from the height `h`. A short clamp should have one screw hole, a medium clamp two, and a long clamp three. The screw holes should be created using a subtraction to make them slightly oversized to ensure that the screws will fit. I'm using M5 screws with a diameter of 5mm, and so the diameter of the cut should be a little less than 5mm before adding `clearance`. It should also add a small margin for clearance on the *outer* side of the screw hole to stop the screw head contacting the clamp.

I’d really like to make use of a library for this if that is something you can do. Could you use BOSL for it? I think that would help to make it much easier to use.

Thanks for your help!

[Assistant]
rod_holder.scad:
```
//default profile thickness
t=3;
//Diameter of rod to be held
d=11.5;
//extra clearance to be provided to account for thicker than design extrusions (to make up for 3D printer tolerances). This is applied as an extra clearance on all internal openings including screw holes.
clearance=0.25;
//Length of top and bottom sides of the C shaped clamp
l=30;
//Width between the top and bottom sides of the C shaped clamp. i.e. the thickness of the wall/plate/etc to which the bracket is being clamped.
w=21.6;
//Height of the clamp and rod holder. A short clamp will only have 1 screw hole, a long clamp will have 3.
h=60;
//Diameter of the screws (bolts) to be used to pressure the clamp
Dscrew=5;
//thickening factor applied to strengthen the bracket. The higher the factor, the stronger the clamp will be able to be tightened.
n=1.5;

difference() {

union(){ //start solids group
cube([t,n*t+4*clearance+t/2,h]);

cube([l+n*t,n*t,h]);

translate([t+4*clearance,n*t+4*clearance,0]) {
  cube([l-t-4*clearance,t/2,h]);
}

translate([(l+n*t)/2,n*t+4*clearance+t/2+w+n*t+d/2,0]) {
  cylinder(h = h, d=d+2*t);
}

translate([l,n*t,0]) {
  cube([n*t,4*clearance+t/2+w,h]);
}

translate([0,n*t+4*clearance+t/2+w,0]) {
  cube([l+n*t,n*t,h]);
}
translate([(l+n*t-(d+2*t))/2,n*t+4*clearance+t/2+w,0]) {
  cube([d+2*t,d/2+n*t,h]);
}

}//end solids group

union(){//start cut group

translate([(l+n*t)/2,n*t+4*clearance+t/2+w+n*t+d/2,t]) {
  cylinder(h = h-t, d=d+2*clearance);}
}

if(h>=15*Dscrew){
translate([(l+n*t)/2,0,0.25*h]) {
	rotate([-90,0,0]){
	  cylinder(h = n*t, d=Dscrew-0.6+2*clearance);}
	}
translate([(l+n*t)/2,0,0.5*h]) {
	rotate([-90,0,0]){
	  cylinder(h = n*t, d=Dscrew-0.6+2*clearance);}
	}
translate([(l+n*t)/2,0,0.75*h]) {
	rotate([-90,0,0]){
	  cylinder(h = n*t, d=Dscrew-0.6+2*clearance);}
	}
}else if(h>=10*Dscrew){
translate([(l+n*t)/2,0,0.25*h]) {
	rotate([-90,0,0]){
	  cylinder(h = n*t, d=Dscrew-0.6+2*clearance);}
	}
translate([(l+n*t)/2,0,0.75*h]) {
	rotate([-90,0,0]){
	  cylinder(h = n*t, d=Dscrew-0.6+2*clearance);}
	}
}else if(h>=2.5*Dscrew){
translate([(l+n*t)/2,0,h/2]) {
	rotate([-90,0,0]){
	  cylinder(h = n*t, d=Dscrew-0.6+2*clearance);}
	}
}

if(h>=15*Dscrew){
translate([(l+n*t)/2,n*t+4*clearance+t/2+w+n*t+d/2,0.25*h]) {
	rotate([-90,0,0]){
	  cylinder(h = t+d, d=Dscrew-0.6+2*clearance);}
	}
translate([(l+n*t)/2,n*t+4*clearance+t/2+w+n*t+d/2,0.5*h]) {
	rotate([-90,0,0]){
	  cylinder(h = t+d, d=Dscrew-0.6+2*clearance);}
	}
translate([(l+n*t)/2,n*t+4*clearance+t/2+w+n*t+d/2,0.75*h]) {
	rotate([-90,0,0]){
	  cylinder(h = t+d, d=Dscrew-0.6+2*clearance);}
	}
}else if(h>=10*Dscrew){
translate([(l+n*t)/2,n*t+4*clearance+t/2+w+n*t+d/2,0.25*h]) {
	rotate([-90,0,0]){
	  cylinder(h = t+d, d=Dscrew-0.6+2*clearance);}
	}
translate([(l+n*t)/2,n*t+4*clearance+t/2+w+n*t+d/2,0.75*h]) {
	rotate([-90,0,0]){
	  cylinder(h = t+d, d=Dscrew-0.6+2*clearance);}
	}
}else if(h>=2.5*Dscrew){
translate([(l+n*t)/2,n*t+4*clearance+t/2+w+n*t+d/2,h/2]) {
	rotate([-90,0,0]){
	  cylinder(h = t+d, d=Dscrew-0.6+2*clearance);}
	}
}

}//end cut group
```


[User]
Okay, I'm looking to design a parametric cam system for triggering microswitches, kind of like a mechanical sequencer. I have some existing code that I've been playing with, but it's very rough and I'd like to start from scratch with a more robust design. I'd like it to be in OpenSCAD, of course.

The key features I need are:

*   **Multiple Cam Tracks:** I want to be able to specify how many separate cam tracks there are. Each track will control a single microswitch.
*   **Parametric Cam Shape:** Each cam track should consist of a series of steps around its circumference. Each step can be one of three types: a "hill" (a raised, pointy section), a "flat top", or a basic "flat down" area. I need to be able to define the sequence of steps for each track individually.
*   **Adjustable Cam Dimensions:**  The size (diameter and thickness) of the cam should be adjustable, as well as the height of the raised "hill" parts and the "flat top" sections relative to the base.
*   **Microswitch Placement:** The locations of the microswitches relative to the cam tracks need to be easily adjustable. I'd like to specify an initial offset and the vertical spacing of the switches, since they'll stack up.
*   **Shaft Hole and Key:** The center of the cam needs a hole for a rotating shaft, and also a small keyway to lock the cam to the shaft.
*   **Rounded Plate Base:** I want a function to create a rounded rectangle base object which the microswitches are mounted on. I'm using a 'hull' in my example, but I would like to see what you come up with.
*  **Microswitch Model:** I also need a parametric model of a standard microswitch. This model should include the mounting holes.
* **Library Usage:** I'm open to using libraries for more advanced stuff if needed, like custom fonts for numbering the cams, etc. So maybe check out what's available in `Write.scad` (I used this to put numbers on my cams), since I like the look of the fonts in that library.

I'm basically looking for a flexible system that I can use to experiment with different timing sequences. Could you design the parametric OpenSCAD code that allows for all of this?

[Assistant]
cam.scad:
```
use<Write.scad>

//Size scaling
scale=10; //general setting
rotation1=69; //rotation of the cam spikes
rotation2=1; //rotation of the flat tops, flat tops have to be replaced with semi-circles at some point
hole=1.6; //size of the hole for the shaft
thickness=5; //z-thickness of cams

//Switch placement
//Show microswitches on/off
show_microswitches=1;
//how many mm the switches are apart
switch_spacing=11;

//Initial switch placement
switch_x=0;
switch_y=-29; //Initial switch placement
switch_z=-2.5; //Initial switch placement

//misc
//Steps on the cam
steps=25;
//how many cams are generated
tracks=4;
//general setting
radius=2;

//Westminster chime

//Tracks 1-4, 25 steps
//0=flat,down 1=hill, 2=flat,top
//type=[0,0,0,0,1,1,1,1,0,0,0,0,1,2,2,2,2,0,0,0,0,0,0,0,0,0];
type=[	[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0],
		[0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0],
		[0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0],
		[0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0]];

//don't touch
pi=3.14159;
divisor=(steps/360);

//Rounded plate module - faster than minkowski!
//variables with "customizer" in them are only for the Thingiverse customizer and are not essential.
module rounded_plate(size_x,size_y,size_z,facets,rounding_radius)
{
	hull()
	{
		translate([rounding_radius,rounding_radius,0]) cylinder (h=size_z, r=rounding_radius,$fn=facets);
		translate([size_x-rounding_radius,rounding_radius,0]) cylinder (h=size_z,r=rounding_radius,$fn=facets);
		translate([rounding_radius,size_y-rounding_radius,0]) cylinder (h=size_z,r=rounding_radius,$fn=facets);
		translate([size_x-rounding_radius,size_y-rounding_radius,0]) cylinder (h=size_z,r=rounding_radius,$fn=facets);
	}
}

module microswitch()
{
	union()
	{
		difference()
		{
			rounded_plate(28,16,10,32,2.5);
			//upper, round hole
			#translate([28-(3.2/2)-1.4,16-(3.2/2)-1.4],0) cylinder(r=3.2/2,h=10,$fn=32);

			//Lower, keyed hole
			difference()
			{

				translate([(3.5/2)+1.4,(3.5/2)+1.4],0) cylinder(r=3.5/2,h=11,$fn=32);
				translate([(3.5/2),(3.5/2)+(3.2/2)+1.4,0]) cube([3.5,0.15,10]);
				translate([(3.5/2),(3.5/2)+(3.2/2)+1.4-3.5+0.15,0]) cube([3.5,0.15,10]);
			}
		}

		//cam nipple
		translate([3.2,16,(10-4.2)/2]) cube([3,3/2,4.2]);
		translate([3.2+1.5,16+1.5,(10-4.2)/2]) cylinder(r=3/2,h=4.2,$fn=16);
	}
}

//****************************************+GENERATE CAMS**************************************************
for (s=[0:tracks-1])
{
	translate ([0,0,s*switch_spacing]) rotate([0,0,0])
	{
		for (t=[1:steps])
		{

			//hill,upwards
			if (type[s][t-1]==1)
			{
				translate([sin(t/divisor)*scale,cos(t/divisor)*scale,0])
				rotate([0,0,-t/divisor-rotation1])
				cylinder(r=radius+(scale/10),$fn=3,h=thickness);
			}

			//flat, top
			else if (type[s][t-1]==2)
			{
				translate([sin(t/divisor)*(scale+1),cos(t/divisor)*(scale+1),0])
				rotate([0,0,-t/divisor-rotation2])
				translate ([-radius,-radius/2,0]) cube([radius*2+0.5,radius+0.5,thickness], center=1);
			}
		}

		//Key and shaft hole
		union()
		{
			difference()
			{
				//Inner circle
				cylinder(r=scale+(scale/10),h=thickness);
				//Shaft hole
				cylinder(r=hole,h=thickness+1,$fn=16);
				//Key hole
				translate([0,scale/2,0])cylinder(r=1.5,h=1,$fn=16);
				//Number
				translate([-2,-7,thickness-1]) write(str(s+1),bold=1,h=4,t=2,font="orbitron.dxf");
			}
			//Key
			translate([0,scale/2,thickness])cylinder(r=0.7,h=1);
		}
	}
	if (show_microswitches==1)
	{
		translate([switch_x,switch_y,(s*switch_spacing)+switch_z])microswitch();
	}
}
```


[User]
Hey, I'm looking to generate some customizable bracelets using OpenSCAD, and I really like the concept of the "rib" bracelet described on this maker blog. It uses a function to define a wavy shape, then extrudes that along a helix. I'm envisioning a parametric model where I can control several aspects.

Specifically, I'd like to be able to adjust:

*   **Overall Diameter:** The main size of the bracelet, I'd need to be able to specify this in millimeters.
*   **Height:** The height of the bracelet, also in mm.
*   **Thickness:** The thickness of the "ribs" that make up the bracelet, again in mm.
*   **Wave Amplitude:** How much the wave in the bracelet deviates from a circle, again in mm.
*   **Wave Frequency:** The number of "spokes" or wave peaks that go around the circumference of the bracelet.
*   **Slant:** The amount of twist (in degrees) of the extruded shape. It should be a helix, not just a straight extrusion.

The core shape is based on a function, which the blog post describes as:
```
function g(t) =
   [ (radius+amplitude*(1+sin(frequency*t)))*cos(t),
     (radius+amplitude*(1+sin(frequency*t)))*sin(t),
     0
   ];
```
The blog uses linear extrusion and a hull operation on two circles along the trace to create a rib-like structure, which is exactly what I want. I need to make sure the code properly performs the hull on the circles, and extrapolates along the trace.

I'm not looking to use any special libraries for this, just the basic OpenSCAD functionalities. Can you help me generate that code?

[Assistant]
day329_functionbracelet_RIB.scad:
```
// mathgrrl function bracelet - RIB MODEL

/////////////////////////////////////////////////////////
// resolution parameters

$fn = 24*1;
step = .25*1;  // smaller means finer

// Thickness, in mm (recommend between .2 and .8)
th = .2*1;

/////////////////////////////////////////////////////////
// size parameters

// Diameter of the bracelet, in mm
diameter = 65;
radius = diameter/2;

// Height of the bracelet, in mm (along your wrist)
height = 20;

// Amplitude of the wave, in mm
amplitude = 2*1;

// Frequency of the wave (number of spokes)
frequency = 72*1;

// Amount of slant (to the left or the right)
slant = 0; //[-3,-2,-1,0,1,2,3]
degrees = slant*360/frequency;

/////////////////////////////////////////////////////////
// define the wrapped wave function

function g(t) =
   [ (radius+amplitude*(1+sin(frequency*t)))*cos(t),
     (radius+amplitude*(1+sin(frequency*t)))*sin(t),
     0
   ];

/////////////////////////////////////////////////////////
// renders

// the bracelet
linear_extrude(height=height,twist=degrees,slices=height/.4)
 function_trace(rad=th, step=step, end=360);

/////////////////////////////////////////////////////////
// module for tracing out a function

module function_trace(rad, step, end) {
 for (t=[0: step: end+step]) {
  hull() {
   translate(g(t)) circle(rad);
   translate(g(t+step)) circle(rad);
       }
   }
};
```


[User]
I'd like to generate a customizable bracelet design based on a mathematical function, similar to the "POW" design described in the included blog post. The key is the trigonometric wave pattern that wraps around the bracelet.

Here's what I'm looking for:

*   **Core Shape:** The bracelet should be a hollow cylinder, with the wave pattern applied to the outer circumference.
*   **Customizable Size:**
    *   **Diameter:** I need to be able to set the inner diameter of the bracelet, to fit different wrist sizes.
    *   **Height:** The height of the bracelet should be adjustable.
*   **Customizable Wave:**
    *   **Amplitude:** I need control over how much the wave deviates from the base radius.
    *   **Frequency:** The number of wave peaks/troughs around the bracelet should be adjustable.
    *  **Wave Function Parameters:** I'd like to manipulate the wave function to make more interesting shapes. This means I need parameters `s` and `c` that effect the shape of the wave.
*   **Resolution:**  The level of detail in the curve needs to be configurable, including the thickness of the 'line' that makes up the bracelet and the resolution of the circle approximation
*  **Material:** The walls of the bracelet should have an adjustable thickness.

Essentially, I need a parametric OpenSCAD file where I can modify all of the above parameters, and it will render a 3D printable bracelet with the custom wave pattern. I'd also like the option to output a tester model to make it easy to test the bracelet dimensions before a long print.

The blog post mentioned a basic sine/cosine function to generate the wave pattern. I believe that is all that needs to be implemented for the core design.

[Assistant]
day330_functionbracelet_POW.scad:
```
// mathgrrl function bracelet - POW design

///////////////////////////////////////////////////////////////////////
// resolution parameters

$fn = 24*1;
step = .25*1; 	// smaller means finer

// Thickness, in mm (recommend between .2 and .4)
th = .4;

///////////////////////////////////////////////////////////////////////
// size parameters

// Diameter of the bracelet, in mm (just smaller than the largest part of your hand)
diameter = 60;
radius = diameter/2;

// Height of the bracelet, in mm (along your wrist)
height = 10;

///////////////////////////////////////////////////////////////////////
// style parameters

// Amplitude of the wave, in mm
amplitude = 6;

// Frequency of the wave (number of spokes)
frequency = 12;

///////////////////////////////////////////////////////////////////////
// function parameters
// for simple sine curve choose s=1, c=0

s = 2*1;
c = 1*1;

///////////////////////////////////////////////////////////////////////
// define the wave function

function f(t) = 1+sin(s*frequency*t)*cos(c*frequency*t);

///////////////////////////////////////////////////////////////////////
// define the wrapped wave function

function g(t) =
   [ (radius+amplitude*f(t))*cos(t),
     (radius+amplitude*f(t))*sin(t),
     0
   ];

///////////////////////////////////////////////////////////////////////
// renders

// the bracelet
linear_extrude(height=height,slices=height/.4)
	function_trace(rad=th, step=step, end=360);

// add solid center if desired
//cylinder(h=height,r1=radius+1,r2=flare*(radius+1),$fn=48);

// testing cylinders
//wrist_tester();
//hand_tester();

///////////////////////////////////////////////////////////////////////
// module for tracing out a function

module function_trace(rad, step, end) {
 for (t=[0: step: end+step]) {
  hull() {
   translate(g(t)) circle(rad);
   translate(g(t+step)) circle(rad);
       }
   }
};

///////////////////////////////////////////////////////////////////////
// modules for testing wrist and hand fit

module wrist_tester(){
	wrist_radius = wrist_circumference/(2*3.14159);
	translate([0,0,-height])
		%cylinder(h=3*height,r=wrist_radius,$fn=48);
}

module hand_tester(){
	hand_radius = hand_circumference/(2*3.14159);
	translate([0,0,-height])
		%cylinder(h=3*height,r=hand_radius,$fn=48);
}

```


[User]
Hey there! I'm looking for some help designing a customizable bracelet in OpenSCAD. I've seen some really cool parametric designs, and I'd love to make my own.

Basically, I want a bracelet that's based on a mathematical function, kind of like that "mathgrrl function bracelet - POP design" I found. It's a cool wave shape wrapping around the wrist.

Here’s what I’m hoping to achieve:

*   **Overall Shape:** The bracelet should have a circular base with a wavy profile around its circumference, extruded to create a 3D object. So, think of a circle that's being distorted by a wave.
*   **Customization:** I want to be able to adjust the following parameters:
    *   **Diameter:** The overall diameter of the bracelet, in millimeters. This determines how big the bracelet will be.
    *   **Height:** The height or thickness of the bracelet, in millimeters.
    *   **Wave Amplitude:** The maximum height of the waves in millimeters from the base circumference.
    *   **Wave Frequency:**  The number of "spokes" or waves around the bracelet (e.g., 12 waves).
    *   **Function Parameters:** Allow for adjustment of the `s` and `c` values used within the sine and cosine functions that generate the wave. I want to play around with the function `f(t) = 1+sin(s*frequency*t)*cos(c*frequency*t)` and see what kind of wave shapes I can get.
    *   **Thickness:** The thickness of the bracelet "tube", in millimeters, like the `rad` parameter of the example.

*   **Technical Details:**
    *   I would like the design to be made using a `linear_extrude` and `function_trace` style approach, as it allows a lot of flexibility.
    *   I'd like the function used to create the wave shape to be the one given, `f(t) = 1+sin(s*frequency*t)*cos(c*frequency*t)`, and the parametric function used to generate the circles along the path to be  `g(t) =  [ (radius+amplitude*f(t))*cos(t), (radius+amplitude*f(t))*sin(t), 0 ]`.
    *   The `function_trace` module should use a `hull()` command.
    *  I'm not too worried about extra features like wrist testers.

I'm not sure how exactly I'd write all this from scratch, so any help in generating the full `.scad` file would be greatly appreciated. I don't need any fancy libraries, just plain OpenSCAD is fine.

[Assistant]
day331_functionbracelet_POP.scad:
```
// mathgrrl function bracelet - POP design

///////////////////////////////////////////////////////////////////////
// resolution parameters

$fn = 24*1;
step = .25*1; 	// smaller means finer

// Thickness, in mm (recommend between .2 and .4)
th = .4;

///////////////////////////////////////////////////////////////////////
// size parameters

// Diameter of the bracelet, in mm (just smaller than the largest part of your hand)
diameter = 60;
radius = diameter/2;

// Height of the bracelet, in mm (along your wrist)
height = 10;

///////////////////////////////////////////////////////////////////////
// style parameters

// Amplitude of the wave, in mm
amplitude = 6;

// Frequency of the wave (number of spokes)
frequency = 12;

///////////////////////////////////////////////////////////////////////
// function parameters
// for simple sine curve choose s=1, c=0

s = 1*1;
c = 2*1;

///////////////////////////////////////////////////////////////////////
// define the wave function

function f(t) = 1+sin(s*frequency*t)*cos(c*frequency*t);

///////////////////////////////////////////////////////////////////////
// define the wrapped wave function

function g(t) =
   [ (radius+amplitude*f(t))*cos(t),
     (radius+amplitude*f(t))*sin(t),
     0
   ];

///////////////////////////////////////////////////////////////////////
// renders

// the bracelet
linear_extrude(height=height,slices=height/.4)
	function_trace(rad=th, step=step, end=360);

// add solid center if desired
//cylinder(h=height,r1=radius+1,r2=flare*(radius+1),$fn=48);

// testing cylinders
//wrist_tester();
//hand_tester();

///////////////////////////////////////////////////////////////////////
// module for tracing out a function

module function_trace(rad, step, end) {
 for (t=[0: step: end+step]) {
  hull() {
   translate(g(t)) circle(rad);
   translate(g(t+step)) circle(rad);
       }
   }
};

///////////////////////////////////////////////////////////////////////
// modules for testing wrist and hand fit

module wrist_tester(){
	wrist_radius = wrist_circumference/(2*3.14159);
	translate([0,0,-height])
		%cylinder(h=3*height,r=wrist_radius,$fn=48);
}

module hand_tester(){
	hand_radius = hand_circumference/(2*3.14159);
	translate([0,0,-height])
		%cylinder(h=3*height,r=hand_radius,$fn=48);
}

```


[User]
I'm looking to create a parametric design for corrugated boxes, and I'd like it to be flexible when made without edge caps, and rigid with them. I've got a good idea of what I need but I'm not very good with OpenSCAD so I'd really appreciate if you could help me out!

Essentially, the design should let me control the following:

*   **Overall Size**: I need to set the width, length, and height of the box's outer dimensions.
*   **Corrugation**:
    *   The thickness of the corrugated material.
    *   The thickness of the walls within the corrugations themselves.
    *   The density or frequency of the corrugation, with an option for it to use equilateral triangles as a rough guide.
    *   The smallest gap between corrugation triangles.
*   **Corners**: A way to choose between rounded or sharp/square corners.
*   **Caps**:
    *   The height of the top and bottom edge caps.
    *   The thickness of the base or bottom of the box.

I would expect to control all these with named variables within OpenSCAD so I can make all sorts of boxes without having to edit the code too much.

The final design should include:

*   The main corrugated walls using the parameters.
*   The specified type of corners.
*   The optional edge caps on top and bottom edges.
*   The optional solid base.

I don't need any fancy libraries, but I'd be happy if you'd use `$fn` for any cylinders and other curves, and to use epsilons to avoid any common errors. Let me know if you have any questions, and thanks so much!

[Assistant]
flex_cube_v1-2.scad:
```

/*[Size]*/
_outside_width = 80; // x axis
_outside_length = 80;  // y axis
_box_height = 80; // z axis
_corregation_thickness = 6;

/*[Detail]*/
_corner_style = 0; // [0:Round,1:Corner]

//thickness of the walls used in the corregation
_stroke_thickness = 1;

// frequency of corregations (use 0.866 for equilateral triangles)
_corregation_density = 0.866; //sin(60) for approximate equilateral triangles

// smallest gap between each corregation triangle
_gaps = 0.3;

/*[Caps]*/
// thickness of the edges covering the corregations (use 0 for none)
_edge_cap_height = 0.0;

// thickness of the bottom of the box (use 0 for no bottom)
_bottom_height = 0.0;

// ignore
eps = 0.1 * 1;
$fn = 128 * 1;

module rrect(h, w, l, r) {
	r = min(r, min(w/2, l/2));
	w = max(w, eps);
	l = max(l, eps);
	h = max(h, eps);
	if (r <= 0) {
		translate([-w/2, -l/2,0]) {
			cube([w,l,h]);
		}
	} else {
		hull() {
			for (y = [-l/2 + r, l/2 - r]) {
				for (x = [-w/2 + r, w/2 - r]) {
					translate([x, y, 0]) {
						cylinder(h=h, r=r, center=false);
					}
				}
			}
		}
	}
}

module flexBox() {
	module zee(thickness, length, height, stroke, gap) {
//		#translate([length/4,0,0]) cube([length/2, thickness, 1], center=true);
		radius = stroke/2;
		maxx = length/2 - radius - gap/2;
		minx = gap/2 + stroke/2;
		angle = atan2(thickness - stroke, maxx - minx);
		union() {
			// top
			translate([0, thickness/2 - stroke, 0]) {
				cube([maxx, stroke, height]);
			}
			translate([maxx, thickness/2 - stroke/2, 0]) {
				cylinder(h=height, r=stroke/2, $fn = 32);
			}

			// slant (should be more efficient than using a hull)
			translate([length/4, 0, 0])
			rotate([0, 0, angle])
			translate([0, 0, height/2]) {
				cube([(maxx - minx)/cos(angle), stroke, height], center=true);
			}

			// bottom
			translate([minx, -thickness/2, 0]) {
				cube([maxx, stroke, height]);
			}
			translate([minx, -thickness/2 + stroke/2, 0]) {
				cylinder(h=height, r=stroke/2, $fn = 32);
			}

			// connectors (for avoiding degenerate surfaces)
			translate([0, thickness/2 - stroke/2, 0]) {
				cylinder(h=height, r=stroke/2, $fn=4);
			}
			translate([length/2, -thickness/2 + stroke/2, 0]) {
				cylinder(h=height, r=stroke/2, $fn=4);
			}

		}
	}

	module squiggle(thickness, length, height, stroke, gap) {
		union() {
			zee(thickness, length, height, stroke, gap);
			translate([length/2, 0, 0])
			mirror([0, 1, 0]) {
				zee(thickness, length, height, stroke, gap);
			}
		}
	}

	module squiggleLine(thickness, length, height, stroke, density, gap) {
		numSquiggles = max(1, round(density * length/thickness));
		squiggleLength = length/numSquiggles;
		union()
		for(x=[0:1:numSquiggles-1]) {
			translate([x * squiggleLength,0,0]) {
				squiggle(thickness, squiggleLength, height, stroke, gap);
			}
		}
	}

	module rcorner(thickness, x, y, height, stroke, gap) {
		xflip = (x > 0 ? 1 : -1);
		yflip = (y > 0 ? 1 : -1);
		intersection() {
			translate([x - thickness * xflip, y - thickness * yflip, 0]) {
				difference() {
					cylinder(h=height, r=thickness);
					translate([0, 0, -eps/2]) {
						cylinder(h=height + eps, r=thickness - stroke);
					}
				}
			}
			translate([x - thickness/2 * xflip, y - thickness/2 * yflip, height/2 - eps/2]) {
				cube([thickness, thickness, height + eps], center=true);
			}
		}
	}

	module corner(thickness, x, y, height, stroke, gap) {
		xflip = (x > 0 ? 1 : -1);
		yflip = (y > 0 ? 1 : -1);
		barLength = thickness-stroke/2;
		union() {
			translate([x - (barLength + stroke)/2 * xflip, y - stroke/2 * yflip, height/2]) {
				cube([barLength, stroke, height], center=true);
			}
			translate([x-stroke/2 * xflip,  y - (barLength + stroke)/2 * yflip, height/2]) {
				cube([stroke, barLength, height], center=true);
			}

			hull() {
				translate([x - stroke/2 * xflip, y-stroke/2 * yflip, 0]) {
					cylinder(h=height, r=stroke/2);
				}

				translate([x + (-thickness + stroke/2 + gap) * xflip, y + (-thickness + stroke/2 + gap) * yflip, 0]) {
					cylinder(h=height, r=stroke/2);
				}
			}
		}
	}

	insideWidth = _outside_width - _corregation_thickness*2;
	insideLength = _outside_length - _corregation_thickness*2;
	rounding = _corner_style == 0 ? _corregation_thickness : _stroke_thickness/2;
	hack = 0.001; // offset cap edges to prevent degenerate geometry

	echo("inside width", insideWidth);
	echo("inside length", insideLength);

//	translate([0,0,_box_height/2]) {
//		difference() {
//			cube([_outside_width, _outside_length, _box_height], center=true);
//			cube([insideWidth, insideLength, _box_height+eps], center=true);
//		}
//	}

	union() {

		//	walls
		for (a=[0,180]) {
			rotate([0,0,a])
			translate([-insideWidth/2, insideLength/2 + _corregation_thickness/2,0]) {
				squiggleLine(_corregation_thickness, insideWidth, _box_height, _stroke_thickness, _corregation_density, _gaps);
			}
		}
		for (a=[-1,1]) {
			rotate([0,0,90 * a])
			translate([-insideLength/2, (insideWidth/2 + _corregation_thickness/2),0]) {
				squiggleLine(_corregation_thickness, insideLength, _box_height, _stroke_thickness, _corregation_density, _gaps);
			}
		}

		// corners
		if (_corner_style == 0) {
			rcorner(_corregation_thickness, _outside_width/2, _outside_length/2, _box_height, _stroke_thickness, _gaps);
			rcorner(_corregation_thickness, _outside_width/2, -_outside_length/2, _box_height, _stroke_thickness, _gaps);
			rcorner(_corregation_thickness, -_outside_width/2, _outside_length/2, _box_height, _stroke_thickness, _gaps);
			rcorner(_corregation_thickness, -_outside_width/2, -_outside_length/2, _box_height, _stroke_thickness, _gaps);
		} else {
			corner(_corregation_thickness, _outside_width/2, _outside_length/2, _box_height, _stroke_thickness, _gaps);
			corner(_corregation_thickness, _outside_width/2, -_outside_length/2, _box_height, _stroke_thickness, _gaps);
			corner(_corregation_thickness, -_outside_width/2, _outside_length/2, _box_height, _stroke_thickness, _gaps);
			corner(_corregation_thickness, -_outside_width/2, -_outside_length/2, _box_height, _stroke_thickness, _gaps);
		}

		// note: add these as non-overlapping objects, otherwise degenerate geometry is created

		// edge caps
		if (_edge_cap_height > 0) {
			difference() {
				union() {
					rrect(_edge_cap_height, _outside_width - hack, _outside_length - hack, rounding);
					translate([0, 0, _box_height-_edge_cap_height]) {
						rrect(_edge_cap_height, _outside_width - hack, _outside_length - hack, rounding);
					}
				}
				translate([0, 0, _box_height/2]) {
					cube([insideWidth + hack, insideLength + hack, _box_height+eps], center=true);
				}
			}
		}

		// base
		if (_bottom_height > 0) {
			rrect(_bottom_height, _outside_width - hack, _outside_length - hack, rounding);
		}
	}

}

flexBox();
```


[User]
Hi, I'm looking to get a parametric OpenSCAD design for magnetic rod ends for a delta 3D printer. I've seen a few designs out there but I want something a little sleeker and more customizable. I'd like the design to be based on the following parameters:

*   **`rodRadius`**: The radius of the metal rods used in the printer.
*   **`magnetRadius`**: The radius of the magnets to be embedded within the rod end.
*   **`magnetHeight`**: The height of the magnets.
*   **`wallWidth`**: The thickness of the material surrounding the magnet and rod, set as a multiplier of the printer's extrusion width, to ensure it prints correctly.
*   **`bearingDiameter`**: The diameter of the spherical ball bearing used to connect to the effector.
*  **`bearingHoleDiameter`**: The diameter of the hole that the bearing sits in.
*   **`rodEndLength`**: The overall length of the rod end piece, excluding the sphere.
*   **`chamferAngle`**: Angle for the top chamfer, in degrees.
*   **`chamferHeight`**: Height of the top chamfer.
*   **`tolerance`**: A general tolerance value for clearances, for example, a value of 0.1 to add 0.1mm of clearance to all press-fit holes.
*   **`segments`**: The number of segments used to render curves and circles.

Here's how I envision the overall design:

The rod end will have a cylindrical base that houses the magnet and the rod. It should have a spherical cutout at one end for the ball bearing. At the top of the cylindrical base, there needs to be a small chamfered edge for aesthetic purposes. This should be configurable via an angle and a height.

The length should be set such that the rod passes all the way through the center. The magnet should be flush with the internal rod surface. The ball bearing needs to be properly seated in the cut-out with enough space to allow movement, so a tolerance is needed.

I'd like it if you could generate the entire design, and any functions or modules, in a single file. Can you handle that? Thanks!

[Assistant]
slim_magnetic_rod_ends.scad:
```
// Effective rod length (bearings center-to-center) =
// rodLength + 2(height - magnetLength) + sphereDiameter

// The length of the tube to house your magnet and rod
height=20;

// The radius of your rods and magnets
radius=3.1;

// The width of the walls, set to a multiplier of your extrusion width
wallWidth=2.08;

// The diameter of your bearing of choice
sphereDiameter=7;

hidden_quality=100*1;

difference()
{
  // Main body
  cylinder(r=radius+wallWidth/2, h=height+radius, $fn=hidden_quality);
  union()
  {
    // Magnet and rod cutout
    translate([0,0,-1])cylinder(r=radius, h=height+1, $fn=hidden_quality);

    // Ball bearing cutout
    translate([0,0,height+(sphereDiameter/2)+0.5])sphere(r=sphereDiameter/2, $fn=hidden_quality);
    translate([0,0,height+radius-1])cylinder(r=1+radius+wallWidth/2, h=sphereDiameter, $fn=hidden_quality);

    // Chamfered edge
    difference()
    {
      translate([0,0,-1])cylinder(r=radius+(wallWidth/2)+1, h=2, $fn=hidden_quality);
      cylinder(r1=radius+(wallWidth/4)+0.1, r2=radius+wallWidth/2, h=1, $fn=hidden_quality);
    }
  }
}
```


[User]
Okay, I'm looking to create a parametric holster for a multitool, similar in style to the one Adam Savage made for his Leatherman Wave. I've seen a few designs online, but I'd like one that's fully customizable for different multitool sizes. I want it to be a single piece that's easily 3D printable. I'm thinking something that looks somewhat minimal but is sturdy and functional.

Here are the parameters I need to control:

*   **Multitool Dimensions:**
    *   `thickness`: The thickness of the multitool itself.
    *   `width`: The width of the multitool.
    *   `height`: The height of the multitool.
*   **Case Dimensions:**
    *   `case_thickness`: The thickness of the holster material.
    *   `case_height`: The internal height of the holster cavity (probably related to the tool height, maybe slightly shorter)
*   **Lip and Bottom Lip:**
    *  `lip`: How far the "lips" on the sides of the holster come in to hold the tool in place.
    *  `bottom_lip`: How far the bottom lip comes up to prevent the tool from sliding through the bottom.
    *  `bottom_lip_width`: How wide the bottom lip is on the bottom of the holster.
*   **Radius:**
    * `radius`: The radius for any rounded edges or corners.
*   **Belt Mount:**
    *  `mount_width`: The width of the belt mount.
    *  `belt_thickness`: The thickness of the belt it is meant for.
    *  `belt_width`: The width of the belt it is meant for
*   **General:**
    * I'd like the option of a custom `$fn` for higher detail.

The basic design should have a backplate with two arms that form the sides, and little lips that curve inward to retain the multitool, and a lip at the bottom.  There should also be a belt clip/mount on the back.  I think it should be constructed from a series of rounded boxes, like what I see in the existing design.

I'd like to use the BOSL2 library, mainly for the `rounded_box` function and the `hull` primitive. Is it possible to generate this as a single .scad file?

[Assistant]
leatherman_holster_v2.scad:
```
//Multitool thickness in mm
thickness = 18.5;
//Multitool width in mm
width = 36;
//Multitool height in mm
height = 100;

/* [Hidden] */

$fn = 100;

case_thickness = 3;
case_height = height - 10;
lip = 5;
bottom_lip = 7.5;
bottom_lip_width = 15;
radius = 1;
mount_width = 25;
belt_thickness = 8;
belt_width = 50;

module rounded_rectangle(size, radius, center=false) {
	if(!center)
		translate([size[0] / 2, size[1] / 2])
			rounded_rectangle(size, radius, center=true);
	else
		hull() {
			translate([-(size[0] / 2 - radius), -(size[1] / 2 - radius)])
				circle(radius);
			translate([ (size[0] / 2 - radius), -(size[1] / 2 - radius)])
				circle(radius);
			translate([ (size[0] / 2 - radius),  (size[1] / 2 - radius)])
				circle(radius);
			translate([-(size[0] / 2 - radius),  (size[1] / 2 - radius)])
				circle(radius);
		}
}
module rounded_box(size, radius, center=false) {
	if(!center)
		translate([size[0] / 2, size[1] / 2, size[2] / 2])
			rounded_box(size, radius, center=true);
	else
		assign(hs = [size[0] / 2 - radius, size[1] / 2 - radius, size[2] / 2 - radius])
			hull() {
				translate([-hs[0],  hs[1],  hs[2]])
					sphere(radius);
				translate([ hs[0],  hs[1],  hs[2]])
					sphere(radius);
				translate([-hs[0], -hs[1],  hs[2]])
					sphere(radius);
				translate([ hs[0], -hs[1],  hs[2]])
					sphere(radius);
				translate([-hs[0],  hs[1], -hs[2]])
					sphere(radius);
				translate([ hs[0],  hs[1], -hs[2]])
					sphere(radius);
				translate([-hs[0], -hs[1], -hs[2]])
					sphere(radius);
				translate([ hs[0], -hs[1], -hs[2]])
					sphere(radius);
			}
}

module rsquare(size)
	rounded_box([size[0], size[1], case_height], radius, center=false);

rsquare([case_thickness * 2 + width, case_thickness], radius); // Back
// Left side arm
	rsquare([case_thickness, case_thickness * 2 + thickness]);
translate([0, case_thickness + thickness]) // Left lip
	rsquare([lip + case_thickness, case_thickness]);
translate([case_thickness + width, 0]) // Right side arm
	rsquare([case_thickness, case_thickness * 2 + thickness]);
translate([case_thickness + width - lip, case_thickness + thickness]) // Right lip
	rsquare([lip + case_thickness, case_thickness]);

difference() {
	hull() {
		translate([case_thickness + width / 2 - mount_width / 2, -(case_thickness + belt_thickness), case_height - (case_thickness * 2 + belt_width)])
			rounded_box([mount_width, belt_thickness + case_thickness * 2, case_thickness * 2 + belt_width], 3);
		translate([case_thickness + width / 2 - mount_width / 2, 0, case_height - (case_thickness * 2 + belt_width) - 6])
			sphere(r=.001);
		translate([case_thickness + width / 2 + mount_width / 2, 0, case_height - (case_thickness * 2 + belt_width) - 6])
			sphere(r=.001);
	}
	translate([mount_width * 2, -belt_thickness, case_height - case_thickness - belt_width])
		rotate(90, [0, -1, 0])
			linear_extrude(mount_width * 3)
				rounded_rectangle([belt_width, belt_thickness], belt_thickness / 2);
}

translate([case_thickness + width / 2 - bottom_lip_width / 2, 0, 0])
	rounded_box([bottom_lip_width, bottom_lip + case_thickness, case_thickness], radius);

```


[User]
Hey, I've been working on a project where I need a really versatile connector for building frames out of wooden beams, like for a geodesic dome or a simple cube frame. I've got a basic idea using OpenSCAD, and I'm hoping you can help me make it more robust and parametric.

Right now, my design is in a single `.scad` file and it's pretty messy (I've included the code). It creates a joint that can handle 2, 3, or 4 beams coming in at 90-degree angles. It uses a box and some cylinders to make the basic structure, and subtracts cylinders for holes to connect the beams. I'm using the "lazy.scad" library, which I've also included, since it helps with the repetitive translation and rotation tasks.

What I'd like is a more flexible, parametric approach. Specifically, I want to control:

*   **Beam dimensions:** I need to be able to easily set the width and thickness of the beams.
*   **Support length:** The length of the support part that extends out from the center should be adjustable.
*   **Hole size:** I need a parameter for the diameter of the connection holes.
*   **Number of beams:** It's important to be able to create joints for any number of beams, not just 2, 3, or 4, and also be able to specify the angle between those beams. So, for example, a 5 way joint where the beams are 72 degrees from one another.
*   **Material thickness:** This should be a separate parameter from the beam thickness, to allow for different material configurations on the connector.
*   **Rounded edges:** I want to be able to add a fillet to the edges of the connector to make it look a little more polished and make it safer.
*   **Connection method:** I want to be able to control whether the beams attach with bolts, screws, pegs, or just interference fit (which would require a small offset in size and maybe a slightly different hole shape.

Ultimately, I’d like a set of OpenSCAD files that will allow me to build these connectors, and I would prefer it to be broken up into modular components or functions rather than a single file. The current single file is okay, but I think a more modular design will be more easily reusable. I think using libraries like "lazy.scad" is acceptable, though I'm open to recommendations for other ones as well if you feel they would make more sense for this. Also, it would be great if you could use the library-provided functionality, rather than making your own.

Can you help me design this?

[Assistant]
framejoint.scad:
```
// beam width
w = 11;

// beam support length
l = 20;

// hole diameter
p = 3.5;

// material thickness
t = 3;

// 3 or 4 way joint
n = 4; // [ 2, 3, 4 ]

$fn = 8;

difference()
{
	union()
	{
		for ( z = [ 1 : n ] ) rz( z * 90 )
			for ( x = [ -1, +1 ] )
				txy( x*( t/2 + w/2 ), l/2 + w/2 + t )
					cbox( t, l, w );

		for ( a = [ -1, +1 ], b = [ -1, +1 ] )
			txy( a*w/2+a*t/2, b*w/2+b*t/2 )
				ccyl( r = t*1.5, h = w, $fn = 4 );

		cbox( w+t+t, w+t+t, w );
	}

	for ( a = [ -1, 0, +1 ] )
		tx( a*( l/3*2 + w/2 + t ) )
			rx( 90 )
				rz( 180/8 )
					ccyl( r = p/2, h = w+t*3 );

	for ( a = [ +1, 0, -1 ] )
		ty( a*( l/3*2 + w/2 + t ) )
			ry( 90 )
				rz( 180/8 )
					ccyl( r = p/2, h = w+t*3 );

	cbox( w, w, w*2 );
}

/// lazy.scad 1.2
/// a collection of useful macros for the lazy OpenSCAD programmer
/// http://www.thingiverse.com/thing:512443
// single axis translations
module tx( x ) translate( [ x, 0, 0 ] ) for(c=[0:$children-1])child(c);
module ty( y ) translate( [ 0, y, 0 ] ) for(c=[0:$children-1])child(c);
module tz( z ) translate( [ 0, 0, z ] ) for(c=[0:$children-1])child(c);
// 2d translations
module txy( x, y ) translate( [ x, y, 0 ] ) for(c=[0:$children-1])child(c);
module tyz( y, z ) translate( [ 0, y, z ] ) for(c=[0:$children-1])child(c);
module txz( x, z ) translate( [ x, 0, z ] ) for(c=[0:$children-1])child(c);
// 3d translation
module txyz( x, y, z ) translate( [ x, y, z ] ) for(c=[0:$children-1])child(c);
// single axis rotations
module rx( a ) rotate( [ a, 0, 0 ] ) for(c=[0:$children-1])child(c);
module ry( a ) rotate( [ 0, a, 0 ] ) for(c=[0:$children-1])child(c);
module rz( a ) rotate( [ 0, 0, a ] ) for(c=[0:$children-1])child(c);
// centered box (cube)
module cbox( x, y, z, t, xyz ) assign( s = (xyz==undef?[x,y,z]:xyz) ) if ( t == undef || t == 0 ) cube( s, center = true ); else difference() { cbox( xyz = (t>0?s:s-2*[t,t,t]) ); cbox( xyz = (t>0?s-2*[t,t,t]:s) ); }
// centered cylinder
module ccyl( d, h, d1, d2, r, r1, r2 )
cylinder( h = h, r = ( d == undef ? r : d/2 ), r1 = ( d1 == undef ? r1 : d1/2 ), r2 = ( d2 == undef ? r2 : d2 / 2 ), center = true );
/// end lazy.scad

```


[User]
Hey, I'm looking for an OpenSCAD design for a customizable cufflink. I've seen some cool ones, and I have some specific ideas in mind.

Essentially, I want the cufflink to have a main body with text on it and a "stork" (that’s what the current code calls it - the thin bar that goes through the shirt) that connects to a back piece.

Here’s what I’m thinking for the text part:
*   It should be customizable, so I can set the letters or numbers I want. Let’s call that variable `cufflink_text`.
*   I’d like to control the size of the letters relative to the overall cufflink using another variable - `letters_size_scale`.
*   I need different font options, or at least the flexibility to use fonts from a DXF file, like that *write/orbitron.dxf* file. Let's make `font` a variable, with defaults.
*   The letters need to be supported somehow so that they print nicely without support material. I've seen a technique that extrudes at 45 degrees then chops off to create that support.
*   Finally, I'd want the text to be embossed, not just flat.

For the "stork" part:
*   I need to be able to set its length with a variable, `stock_length`.
*   I want the end of the stork to have a few options for the shape, like "rounded," "straight," and maybe "upright" using a variable, `end_connector`.
*  The stork needs to be strong enough to be functional.

For the back part:
* It should be a kind of "base" with a small cylinder for the stork to attach to.

I'm hoping to be able to control all these aspects via parameters, so it's a truly parametric design. I'm pretty sure I saw somewhere that there is a useful library called `Write.scad` that can help with handling text from DXF files so, maybe keep that in mind? It looks like the text extrudes and supports itself with the `supportedLetters` module, which would be cool to replicate.

It would be great if this could all be in one or two .scad files. Let me know if this sounds feasible.

[Assistant]
cufflink.scad:
```
include <write/Write.scad>

//CUSTOMIZER VARIABLES

//(Advise less than 5 characters, 3 looks best)
cufflink_text="BMS";
//(Relative size)
letters_size_scale = 10; //[5:15]
stock_length = 17; // [14:25]
//(Futuristic has best support)
font = "write/orbitron.dxf";//["write/Letters.dxf":Basic,"write/orbitron.dxf":Futuristic]
end_connector = "rounded" ; //[rounded,straight,upright]

//CUSTOMIZER VARIABLES END

letters_size = letters_size_scale/10;

module supportedLetters(text="ABC", theight=6)
{
    // Need to extrude at 45 degrees.
    // 1 - We strink (inv cos 45)
    // 2 - extrude at 90
    // 3 - Rotate 45 degrees
    // 4 - Chop off at 45 degrees
    // Then add normal extruded letters to the scaffolding
    invCos45 = 0.7071068;
    $fn=60;
    translate([0,-2,-1])  rotate([-90,0,0]) difference()
    {
        union() {
            rotate([45,0,0]) scale([1,invCos45,1]) write(text,h=theight,t=10,font=font, center=true);
        }
        translate([0,-7,0]) cube([len(text)*10,10,20], center=true);
        translate([0,5,0]) cube([len(text)*10,10,20], center=true);
        translate([0,0,-6]) cube([len(text)*10,20,10], center=true);
    }
    write(text,h=6,t=2.,font=font, center=true);
}

module supportedLettersAndBack(text="ABC", theight=6)
{
    translate([0,0,-0])  supportedLetters(text);
    translate([0,theight*0.025/2,-1])  cube([len(text)*(theight*2/3)*1.1,theight*1.025,1], center=true);
}

module stork(length, width, cheight, cradius, end="rounded")
{
    $fn=60;
	translate([0,width/2,-length/2])  union() {

      if(end=="rounded")
      {
        support_stork(width=width, length=length);
        // End part - holding shirt together
        translate([0,-width/2,-(length-cheight)/2]) scale([1.25,1,1])  difference()
        {
	       cylinder(h=cheight, r1=cradius/2, r2=width/4, center=true);
          translate([0,-cheight,0]) cube([cradius*2,cheight*2,cradius], center=true);
		  }
      }
      if(end=="straight")
      {
        support_stork(width=width, length=length);
        // Main stork
	     cube([width,width,length], center=true);
        // End part - holding shirt together
        translate([0,0,-(length)/2+cheight/5]) scale([1.25,1,1])  difference()
        {
	       cube([cheight*1.5,width,width], center=true);
		  }
        translate([0,-width/2,-(length-cheight)/2]) scale([1.25,1,1])  difference()
        {
	       cylinder(h=cheight, r1=cradius/2, r2=width/4, center=true);
          translate([0,-cheight,0]) cube([cradius*2,cheight*2,cradius], center=true);
          translate([0,width*2,0]) cube([cradius*2,width*2,cradius], center=true);
		  }
      }
      if(end=="upright")
      {
        translate([0,(cheight-1)/2,1])  cylinder(h=length,r=1.5,center=true);
      translate([0,(cheight-1)/2,-1/2+length/2]) cylinder(h=1,r1=1.5, r2=3,center=true);
      translate([0,(cheight-1)/2,-length/2+1.25]) cylinder(h=0.5,r1=2, r2=1.5,center=true);
      translate([0,3,-length/2]) cube([4,9,2],center=true);
      }

	}
}

module support_stork(width=width, length=length)
{
// Strengthening stork to main link
		translate([0,-width/2,length/2]) scale([1.25,0.9,0.66]) difference() {
			sphere(r=width*1.25);
			translate([0,0,width*2]) cube([width*4, width*4, width*4], center=true);
			translate([0,-width*2,0]) cube([width*4, width*4, width*4], center=true);
    }
    // Main stork
    cube([width,width,length], center=true);
}

module bottom_()
{
  // base is "squeezed" by brim
  scale([1, 1.,1])  difference()
  {
    union()
    {
      // scale as bottom is not rotated
      cube([12,24,0.8], center=true);
      translate([0,0,(15+0.8)/2]) cylinder(h=15,r=1.5,center=true);
      translate([0,0,0.8]) cylinder(h=1,r1=3, r2=1.5,center=true);
      translate([0,0,15-0.8]) cylinder(h=1,r1=1.2, r2=2.5,center=true);
      difference()
      {
          rotate([0,0,0]) translate([0,0,(15+0.8)])  cube([25,5,2.5	], center=true);
          translate([12,0,(15+1)])  cube([12,5*5,3*2], center=true);
          translate([-12,0,(15+1)])  cube([12,5*5,3*2], center=true);
      }
    }
  translate([0,0,0]) screw_holes(radius=1);
  }
}

module cufflink()
{
    rotate([90,0,0])
    {
        scale([1.5*letters_size,1.5*letters_size,1.5*letters_size]) translate([0,3,1.5]) supportedLettersAndBack(text=cufflink_text);
	     stork(stock_length,3, 7, 10, end=end_connector);
    }
}

cufflink();
```


[User]
I'm looking to create a parametric spool insert for a generic filament spool holder, similar to the one on Thingiverse by Willfly. I have a few specific needs and I want it fully customizable.

Here's what I need:

*   **Core:** The insert needs a central core to fit onto the rod of the spool holder. This core should have an inner diameter matching the rod diameter, and the inner core must go all the way through the insert. The insert should also have an outer diameter slightly larger than the rod diameter for a snug fit, with this larger diameter transitioning to the outer core diameter after the leg portion.
*   **Legs:** The insert will have a number of legs that extend outwards to grip the inside of the spool.
*   **Parameters:** I need to be able to customize the following through parameters:
    *   `diameter`: The inner diameter of the spool.
    *   `rod_diameter`: The diameter of the rod on the spool holder.
    *   `leg_thickness`: The thickness of each leg.
    *   `leg_count`: The number of legs, evenly distributed around the core.
    *   `height`: The height of the leg portion of the insert.
    *   `overall_height`: The total height of the insert.
*   **Design:**
    *   The legs should be connected to the outer core and extend towards the outside diameter.
    * The legs should have gaps in between each of them, such that only the legs are touching the inside of the spool and the insert is not otherwise touching the spool besides at the core.
    * The legs should extend from the base of the insert for the defined `height`.
    * Above the legs, there needs to be a cylindrical extension of the core, such that the spool is held on either side of the rod.

I want this to be a fully parametric OpenSCAD design, and it should be easy to modify the parameters. I don't need the STL import from that example file; it's just there for reference. Please use comments in the code to explain the different parts. Let's go with that!

[Assistant]
SpoolInsert.scad:
```
// of the spool hole
diameter = 59; // [20:75]

rod_diameter = 9; // [4:15]

leg_thickness = 3; // [2:10]

leg_count = 5; // [3:7]

// of the bottom part
height = 7; // [5:20]

overall_height = 30; // [20:60]

/////////////////////////////////////////////////////////

// color([1, 0, 0, 0.5]) import("SpoolInsert.stl");

module leg() {
	intersection() {
		translate([0,0,-2]) cylinder(r=diameter/2, h=height+4, $fn=50);
		union() {
			translate([-rod_diameter*1.1, 0, 0]) cube([leg_thickness, diameter*0.6, height]);
			difference() {
				cylinder(r=diameter/2+1, h=height, $fn=50);
				translate([0,0,-1]) union() {
					cylinder(r=diameter/2-leg_thickness, h=height+2, $fn=50);
					translate([rod_diameter, -diameter, 0]) cube([diameter, diameter*2, height+2]);
					translate([-diameter-rod_diameter*1.1, -diameter, 0]) cube([diameter, diameter*2, height+2]);
					translate([-diameter, -diameter, 0]) cube([diameter*2, diameter, height+2]);
				}
			}
		}
	}
}

module spool_insert() {
	// the main body
	difference() {
		union() {
			translate([0, 0, height]) cylinder(r1=rod_diameter*1.1, r2=rod_diameter/2+1, h=overall_height-height, $fn=50);
			cylinder(r=rod_diameter*1.1, h=height, $fn=50);
		}
		translate([0, 0, -1]) cylinder(r=rod_diameter/2, h=overall_height+2, $fn=50);
	}

	// and legs
	for(i=[0:leg_count-1])
		rotate(i*360/leg_count, [0,0,1]) leg();
}

////////////////////////////////////////////////////////

spool_insert();

```


[User]
Hey, I'm looking to create a 3D-printed slide copying adapter for my macro lens, and I'd like to use OpenSCAD. I saw a design online but it's a bit clunky and I think it could be done better. I want something that screws into the filter threads of my macro lens and holds a slide a set distance away from the lens. I’d like to be able to easily change the design to work with different lens thread sizes, thread pitches, and target distances.

Here’s the basic idea. It’s a three-part design: a threaded tube that screws into the lens, a spring-loaded holder for the slide itself, and an optional diffuser. I’m not too worried about the diffuser for now, but I do need the other two parts.

The threaded tube should have parameters for:

*   **Thread Diameter:** This needs to be variable since lenses have different filter thread sizes. I’d like to specify this in millimeters.
*   **Thread Pitch:** Again, different lenses have different thread pitches. I’d like to be able to change this (also in mm)
*   **Thread Tolerance:** I want to be able to add some tolerance to the thread to ensure it fits together well after printing.
*   **Thread Rotation Angle:** It’d be handy to rotate the thread alignment to match my camera to make it all line up nicely. This should be in degrees.
*   **Tube Length:** This is the distance between the lens filter mount and the slide itself, which is critical for the magnification. This should also be in mm.

The slide holder needs to have parameters for:

*   **Film Format**: I’d like to support either 6x6cm or 35mm slides.
*   **Spring thickness and gap**: It should have springy arms to keep the slide in place; the thickness and distance of the arms would be handy.

I also need to make sure the slide holder is aligned with the threaded tube using a small rim. I think the rim and the alignment can be considered one module.

For now, I'm not going to worry about the diffuser; I can always add it later if the spring holder part can take it. The program needs to take into account the film format, slide size and the tolerances involved.

Finally, the code should be parametric, easy to change, and I'd like to see a preview of all the parts put together when the `exploded` view is selected.

Could you help me generate OpenSCAD code for these parts? It would be good if it included some comments to understand what's going on in each section and to be able to tweak the parameters easily. Also, I'd like to be able to print out a test piece for the threads to see if they align, so the code to do that would be awesome. And, as it uses custom threads, I assume it needs the `Write.scad` library.

Thanks!

[Assistant]
DupliHood20161022.scad:
```
/*	DupliHood -- a slide copying attachment

	This OpenSCAD program creates a slide copy mount that
	screws into the filter mount of a macro lens.  There
	are a multitude of issues -- the most obvious of which
	is that not all macro lenses can focus to 1:1, but the
	fact that you'll often want to copy film slides using
	a camera with a smaller sensor means 1:1 isn't needed,
	and you can always stick an extension tube behind your
	macro lens....

	This program currently supports making copy attachments
	for 6x6cm and 35mm slides. Each slide copier consists
	of two parts, a threaded tube and a spring holder for
	the slide. The tube length is dependent on the lens you
	use and the ratio of the film size you want to copy to
	the sensor size of your camera, thus you must customize
	the filter screw thread and length for it. The slide
	holder is specific to the film format only. The springs
	are printed with enough flex and clearance to accomodate
	glass-mounted slides, but also work fine with standard
	cardboard slide mounts.

	In fact, there is an optional third part to DupliHood:
	a diffuser to fit behind the slide. I don't recommend
	using it because 3D-printed parts often don't transmit
	light evenly enough to be a good diffuser.

	I've written an Instructable giving more details....

	Revisions:

	20140817	Original release
	20140824	Removed print_part() left over from lenscaps,
				increased spring bump & space around film area,
				added thread alignment test part
	20161022	Removed [Global] directive (Customizer is broken!)

	(C) 2014 Hank Dietz
*/

// What is the filter major diameter (size)?
thread_diameter = 550; // [240:24mm,250:25mm,270:27mm,300:30mm.305:30.5mm,340:34mm,355:35.5mm,365:36.5mm,370:37mm,375:37.5mm,390:39mm,405:40.5mm,430:43mm,460:46mm,480:48mm,490:49mm,520:52mm,530:53mm,550:55mm,580:58mm,620:62mm,670:67mm,720:72mm,770:77mm,820:82mm,860:86mm (86M or 86C),940:94mm (94C),950:95mm (95C),1050:105mm (105C),1070:107mm (107 or 107C),1100:110mm,1120:112mm,1125:112.5mm,1250:125mm (125C),1270:127mm,1380:138mm,1450:145mm]

// What is the filter thread pitch?
thread_pitch = 75; // [50:Fine 0.5mm, 75:Standard 0.75mm, 100:Coarse 1.0mm, 150:Very coarse 1.5mm]

// Tolerance to allow for inaccurate filament placement (usually extrusion diameter/2), in microns?
thread_tolerance = 100; // [0:500]

// Thread rotation angle (to align slide mask with the camera)?
thread_rotate = 45; // [0:359]

// What is the distance from the lens front to the slide mount?
tube_length = 125; // [20:200]

// What is the slide format?
film = "film6x6"; // [film6x6:Mounted 6x6cm slides,film35:Mounted 35mm (135 format) slides]

// Which part do you want to make?
part = "exploded"; // [tube:The threaded tube,springpart:The spring cap that holds the slide, diffuser:The optional diffuser,exploded:Exploded view of all three parts,align:Test part for thread rotational alignment]

/* [Hidden] */

use <write/Write.scad>

filmx=((film == "film6x6") ? 60 : 36);
filmy=((film == "film6x6") ? 60 : 24);
framex=((film == "film6x6") ? 70 : 50);
framey=((film == "film6x6") ? 70 : 50);
framez=3.25;
frametol=1;
lip=2;
diag=sqrt(((framex+frametol)*(framex+frametol))+((framey+frametol)*(framey+frametol)));
innertall=80;
overlap=5;
spring=1;

$fn=90;
tol=0.25;
mystep=5;

module male_thread(P, D_maj, Tall, tol=0, step=mystep) {
	// male thread is also called external thread
	assign(H=sqrt(3)/2*P)
	assign(fudge=0.0001)
	intersection() {
		translate([0, 0, Tall/2])
		cube([2*D_maj, 2*D_maj, Tall], center=true);
		for(k=[-P:P:Tall+P]) translate([0, 0, k])
		for(i=[0:step:360-step]) hull() for(j = [0,step]) {
			rotate([0,0,(i+j)])
			translate([D_maj/2, 0, (i+j)/360*P])
			rotate([90, 0, 0])
			linear_extrude(height=0.1, center=true, convexity=10)
			polygon(points=[
[-H*2/8-P/8-tol, 0],
[P/2-H*2/8-P/8-tol, P/2],
[-H*2/8-P/8-tol, P],
[-D_maj/2-fudge, P],
[-D_maj/2-fudge, 0]],
				paths=[[0,1,2,3,4]],
				convexity=10);
		}
	}
}

module springpart() {
	union() {
		echo(str("Making Spring Holder for ", film, "."));

		difference() {
			// outer rim
			cylinder(r=diag/2+lip+lip, h=framez+spring+overlap);

			// slide holder
			translate([0, 0, framez+spring])
			cylinder(r=diag/2+lip, h=1000);

			// slide removal access, shifted up as of 20140824
			translate([0, 500-(framey/2)+frametol/4, 0])
			cube([framex+frametol, 1000, 1000], center=true);
		}

		difference() {
			union() {
				// spring
				translate([0, 0, spring/2])
				cube([framex, (framey+frametol)*1, spring], center=true);

				// bump on the spring, thicker as of 20140824
				difference() {
					translate([0, filmy/7, -filmy*2+spring*3])
					rotate([0, 90, 0])
					cylinder(r=filmy*2, h=framex, center=true, $fn=180);
					translate([0, 0, -500])
					cube([1000, 1000, 1000], center=true);
				}
			}

			// clear film area + double tolerance as of 20140824
			translate([0, 500-(filmy+frametol)/2-frametol, 0])
			cube([filmx+2*frametol, 1000, 1000], center=true);
		}
	}
}

module diffuser() {
	echo(str("Making optional diffuser for ", film, "."));

	translate([0, 0, overlap*2+1])
	mirror([0, 0, 1])
	union() {
		difference() {
			// outer rim
			cylinder(r=diag/2+lip+lip+lip, h=overlap);
			cylinder(r=diag/2+lip+lip, h=1000, center=true);
		}

		translate([0, 0, overlap])
		difference() {
			cylinder(r=diag/2+lip+lip+lip, h=overlap+1);
			cylinder(r1=diag/2+lip+lip-1, r2=diag/2+lip+lip+lip-1, h=overlap);
			translate([0, 0, -500])
			cube([1000, 1000, 1000], center=true);
		}
	}
}

module tube(len=125) {
	assign(dia=thread_diameter/10)
	assign(mag=((dia<49) ? 0.5 : 1))
	assign(pitch=thread_pitch/100.0)
	assign(ctol=thread_tolerance/1000.0)
	union() {
		echo(str("Making Screw-On M-", dia, " X ", pitch, " Slide Copy tube ", len, "mm long."));

		// base
		difference() {
			// flat
			cylinder(r=diag/2+lip, h=overlap);
			translate([0, 0, lip])
			cylinder(r=diag/2, h=overlap);

			// clear film area
			hull() {
				translate([0, 0, -1])
				cube([filmx, filmy, 2], center=true);
				translate([0, 0, 1+lip])
				cube([filmx+lip, filmy+lip, 2], center=true);
			}
		}

		// tube
		translate([0, 0, overlap])
		intersection() {
			difference() {
				union() {
					cylinder(r1=diag/2+lip, r2=dia/2, h=len-overlap-3);
					for (rot=[0,180])
					rotate([0, 0, rot])
					translate([0, diag/2+lip-40/2, lip*2+12])
					rotate([90, 0, 180])
					scale([0.8, 1, 1])
					write("DUPLIHOOD", t=40, h=12, center=true);
				}
				translate([0, 0, -0.01])
				cylinder(r1=diag/2, r2=dia/2-lip, h=len-overlap-3+0.02);
			}
			translate([0, 0, -0.1/2])
			cylinder(r1=diag/2+lip+1, r2=dia/2+1, h=len-overlap-3+0.1);
		}

		// screw filter part
		translate([0, 0, len-3])
		intersection() {
			difference() {
				rotate([0, 0, thread_rotate]) // roughly align thread
				male_thread(pitch, dia-ctol, 3, 0.25);
				cylinder(r=dia/2-lip, h=1000, center=true);
			}
			cylinder(r1=(dia/2)+4, r2=(dia/2)-1, h=3, $fn=90);
		}
	}
}

module aligntest() {
	assign(dia=thread_diameter/10)
	assign(mag=((dia<49) ? 0.5 : 1))
	assign(pitch=thread_pitch/100.0)
	assign(ctol=thread_tolerance/1000.0)
	union() {
		echo(str("Making Screw-On M-", dia, " X ", pitch, " thread alignment test."));

		// base
		difference() {
			union() {
				cylinder(r=dia/2, h=1);

				translate([0, 0, 1])
				// screw filter part
				rotate([0, 0, thread_rotate]) // roughly align thread
				male_thread(pitch, dia-ctol, 3, 0.25);
			}

			translate([0, 0, 2])
			cylinder(r=dia/2-2, h=4);

			difference() {
				hull() {
					cylinder(r=.75*dia/2, h=100, center=true);
					cube([0.001, dia-2*lip, 100], center=true);
				}
				cube([dia*5, 12, 200], center=true);
			}

			translate([0, 0, -10/2+1])
			rotate([180, 0, 0])
			write(str("rotate ", thread_rotate), t=10, h=6, center=true);
		}
	}
}

print_part();

module print_part() {
	if (part == "tube") {
		color("gray")
		tube(tube_length);
	} else if (part == "springpart") {
		color("white")
		springpart();
	} else if (part == "diffuser") {
		color("white")
		diffuser();
	} else if (part == "exploded") {
		union() {
			color("white")
			diffuser();
			translate([0, 0, lip+overlap*2+1])
			union() {
				color("white")
				springpart();
				translate([0, 0, lip*6])
				color("gray")
				tube(tube_length);
			}
		}
	} else {
		color("red")
		aligntest();
	}
}

```


[User]
I'd like to create a customisable 3D face model using OpenSCAD. I've included a base design file which gives a lot of the parameters I'd like to control. It uses spheres and hulls to create the basic forms. I'm envisioning a model where I can adjust features like the head size, chin shape, cheekbones, eye sockets, eyes, nose, and mouth, very similar to what's already present.

Here's what I want:

*   **Head:** A basic sphere shape that can be resized using a diameter parameter.  I'd like to be able to specify the diameter as `headDi` (as in the base file).
*   **Chin:** This needs to be a customizable protrusion from the bottom of the head with adjustable length (`chinLen`), width (`chinX`), thickness (`chinY`), sharpness (`chinZ`), angle (`chinYAng`), and vertical offset from the bottom of the head sphere (`chinZOff`), and an additional 'upturned' offset `chinYOff`
*   **Neck:**  A simple cylinder that connects to the bottom of the head, with controllable diameter (`neckDi`) and height (derived from chinZ in the example file).
*   **Cheekbones:**  These should be created using spheres and positioned and sized independently on both sides of the face. I need to control horizontal position (`cheekX`), depth (`cheekY`), vertical position (`cheekZ`) width (`cheekXs`), depth (`cheekYs`), and height (`cheekZs`)
*   **Eye Sockets:** Indentations in the face, created by subtracting spheres. I need control over their horizontal position (`eyeSockX`), depth (`eyeSockY`), vertical position (`eyeSockZ`), width (`eyeSockXs`), depth (`eyeSockYs`), height (`eyeSockZs`). Also, I need to be able to angle the sockets using three angles, `eyeSockXa`, `eyeSockYa` and `eyeSockZa`.
*  **Eyes:**  Spheres that fit into the sockets, with separate positional parameters (`eyeX`, `eyeY`, `eyeZ`) for each eye and size (`eyeXs`, `eyeYs`, `eyeZs`). I need to be able to independently rotate them using three angles, `eyeXa`, `eyeYa` and `eyeZa`.
*   **Nose:** This should be a more complex shape made up of a nose tip, sides, and a bridge, all customizable in size, length, and position.  Specific parameters I would like to control: nose tip width (`noseTx`), length (`noseTy`), and height (`noseTz`); side lobe width (`noseSx`), length (`noseSy`), and height (`noseSz`), side offset from nose tip (`noseSdx`); bridge height above tip (`noseBdz`), width (`noseBx`), depth (`noseBy`), length (`noseBz`); bridge angle into face (`noseA`); nose position depth on face (`noseMy`) and height (`noseMz`)
*   **Mouth/Lips:**  This should be created using a series of spheres connected using hulls. There should be several parameters for the top lip (Center Radius, Center Distance, Middle Radius, Middle Distance, Middle offset, Outside Radius, Outside Height) and the bottom lip (Middle Radius, Middle distance, Middle Depth, Center Radius, Center Distance, Center Depth), plus general parameters for the width of the mouth, offset from the head and vertical position on face. The precise parameters are: lips width (`lipsW`), lips Top Centre radius (`lipsTCr`), lips Top Centre distance from middle (`lipsTCx`), lips Top Middle radius (`lipsTMr`), lips Top Middle distance from middle (`lipsTMx`), lips Top Middle offset up from centre (`lipsTMz`), lips Top Outside radius (`lipsTOr`), lips Top outside corner distance above centre (`lipsTH`), lips Bottom middle radius (`lipsBMr`), lips Bottom middle distance from middle (`lipsBMx`), lips Bottom middle depth below top (`lipsBMz`), lips Bottom centre radius (`lipsBCr`), lips Bottom centre distance from middle (`lipsBCx`), lips Bottom centre depth below top (`lipsBCz`); mouth distance out of face (`mouthY`) and position down face (`mouthZ`).

I'd like the code to be organized with modules for each feature (head, chin, neck, cheeks, eyesockets, eyes, nose, mouth/lips) for easy modifications. Also, I want all the parameters grouped at the top of the file as variables. Please use a `$fn` variable to control the overall smoothness/quality of the model.

I don't need any additional libraries for this - it should all be achievable with standard OpenSCAD.

[Assistant]
Play.scad:
```
// Play face
// TrevM 17/08/2014

/* [Global] */

// What quality?
$fn = 100;	// [20,40,60,80,100,120,140,160,180]

// main head diameter?
headDi = 30;
// neck diameter?
neckDi = 15;

// chin movement up/down (face tall narrow, short round)
chinZOff = 10;
// chin length
chinLen = 40;
// chin width
chinX = 22;
// chin thickness
chinY = 10;
// chin sharpness
chinZ = 30;
// chin angle (jut or sink)
chinYAng = 20;
// controls how upturned face is
chinYOff = 10;

// cheek bone position sideways
cheekX = 5;
// cheek bone position forward / back
cheekY = -10;
// cheek bone position up / down
cheekZ = -10;
// cheek bone width
cheekXs = 15;
// cheek bone depth
cheekYs = 10;
// cheek bone height
cheekZs = 10;

// eye socket position sideways
eyeSockX = 8;
// eye socket position forward / back
eyeSockY = -1;
// eye socket position up / down
eyeSockZ = -2;
// eye socket width
eyeSockXs = 13;
// eye socket depth
eyeSockYs = 5;
// eye socket height
eyeSockZs = 9;
// eye socket angle (0=flat, 10 = angle 10 degrees in to ears)
eyeSockXa = 10;
// eye socket angle (slant down)
eyeSockYa = -15;
// eye socket angle
eyeSockZa = 10;

// eye position sideways
eyeX = 7;
// eye position forward/back
eyeY = -2.5;
// eye position up/down
eyeZ = -2;
// eye size wide
eyeXs = 5.2;
// eye size depth
eyeYs = 2;
// eye size high
eyeZs = 3.2;
// eye angle outside edge inwards angle
eyeXa = 20;
// eye angle outside edge up / down (slant)
eyeYa = -20;
// eye angle
eyeZa = 10;

// nose tip width
noseTx = 5;
// nose tip length
noseTy = 7;
// nose tip height
noseTz = 5;
// nose width
noseSdx = 3;
// nose side lobe width
noseSx = 2;
// nose side lobe length
noseSy = 2;
// nose side lobe height
noseSz = 2;
// nose bridge height above tip
noseBdz = 5;
// nose bridge width
noseBx = 3;
// nose bridge depth (thickness)
noseBy = 2;
// nose bridge length
noseBz = 7;
// nose bridge angle into face
noseA = 5;
// nose position depth on face
noseMy = 0;
// nose position height on face
noseMz = 1;

// lips width
lipsW=6;
// lips Top Centre radius
lipsTCr = 0.9;
// lips Top Centre distance from middle
lipsTCx = 0.2;
// lips Top Middle radius
lipsTMr = 0.8;
// lips Top Middle distance from middle
lipsTMx = 2;
// lips Top Middle offset up from centre
lipsTMz = 0.5;
// lips Top Outside radius
lipsTOr = 0.2;
// lips Top outside corner distance above centre
lipsTH = 0.2;
// lips Bottom middle radius
lipsBMr = 0.5;
// lips Bottom middle distance from middle
lipsBMx = 4;
// lips Bottom middle depth below top
lipsBMz = 2;
// lips Bottom centre radius
lipsBCr = 1;
// lips Bottom centre distance from middle
lipsBCx = 1;
// lips Bottom centre depth below top
lipsBCz = 3;

// mouth distance out of face
mouthY = 1;
// mounth position down face
mouthZ = -5;

/* [Hidden] */

rotate([0,0,180])	head();
//nose();
//lips();

module head()
{
	eyeSY=(headDi/2)+eyeSockY;
	eyeSZ=chinZOff+eyeSockZ;

	difference()
	{
		hull()
		{
			// basic round head
			translate([0,0,chinZOff])		sphere(r=headDi/2);
			// chin
			translate([0,chinYOff,0])
				rotate([chinYAng,0,0])
					resize([chinX,chinY,chinZ])
						sphere(r=headDi/2);
			// neck / head junction
			translate([0,0,-chinZ/4])
				cylinder(r=neckDi/2,h=chinZ/2);
			// left cheek bone
			translate([-cheekX,-cheekY,chinZOff+cheekZ])
				resize([cheekXs,cheekYs,cheekZs])	sphere(r=cheekXs/2);
			// right cheek bone
			translate([cheekX,-cheekY,chinZOff+cheekZ])
				resize([cheekXs,cheekYs,cheekZs])	sphere(r=cheekXs/2);
		}
		// left eye socket
		translate([-eyeSockX,eyeSY,eyeSZ])
			rotate([0,0,eyeSockXa])
				rotate([0,eyeSockYa,eyeSockZa])
					resize([eyeSockXs,eyeSockYs,eyeSockZs])
						sphere(r=eyeSockXs);
		// right eye socket
		translate([eyeSockX,eyeSY,eyeSZ])
			rotate([0,0,-eyeSockXa])
				rotate([0,-eyeSockYa,-eyeSockZa])
					resize([eyeSockXs,eyeSockYs,eyeSockZs])
						sphere(r=eyeSockXs);
	}
	// left eye
	translate([-eyeX,eyeSY+eyeY,chinZOff+eyeZ])
		rotate([0,0,eyeXa])
			rotate([0,eyeYa,eyeZa])
				resize([eyeXs,eyeYs,eyeZs])
					sphere(r=eyeXs);
	// left eye
	translate([eyeX,eyeSY+eyeY,chinZOff+eyeZ])
		rotate([0,0,-eyeXa])
			rotate([0,-eyeYa,-eyeZa])
				resize([eyeXs,eyeYs,eyeZs])
					sphere(r=eyeXs);
	// neck
	translate([0,0,-chinZ/2])
		cylinder(r=neckDi/2,h=chinZ/2);
	// nose
	translate([0,(headDi/2)+noseMy,noseMz])
		rotate([noseA,0,0])
			nose();
	// lips
	translate([0,(headDi/2)+mouthY,mouthZ])	lips();
}

module nose()
{
	hull()
	{
		resize([noseTx,noseTy,noseTz])		sphere(noseTx);
		translate([-noseSdx,0,0])
			resize([noseSx,noseSy,noseSz])	sphere(noseSx);
		translate([noseSdx,0,0])
			resize([noseSx,noseSy,noseSz])	sphere(noseSx);
		translate([0,0,noseBdz])
			resize([noseBx,noseBy,noseBz])	sphere(noseBx);
	}
}

module lips()
{
	lip();
	mirror([-lipsBCz,0,0])	lip();
}

module lip()
{
	hull()
	{
		// top left centre
		translate([-lipsTMx,0,-lipsTMz])	sphere(lipsTMr);
		translate([-lipsTCx,0,0])			sphere(lipsTCr);
	}
	hull()
	{
		// top left outside
		translate([-lipsTMx,0,-lipsTMz])	sphere(lipsTMr);
		translate([-lipsW,0,lipsTH])		sphere(lipsTOr);
	}
	hull()
	{
		// bottom left outside
		translate([-lipsW,0,lipsTH])		sphere(lipsTOr);
		translate([-lipsBMx,0,lipsTMz-lipsBMz])	sphere(lipsBMr);
	}
	hull()
	{
		// bottom left inside
		translate([-lipsBMx,0,lipsTMz-lipsBMz])	sphere(lipsBMr);
		translate([-lipsBCx,0,lipsTMz-lipsBCz])	sphere(lipsBCr);
	}
	hull()
	{
		translate([-lipsBCx,0,lipsTMz-lipsBCz])	sphere(lipsBCr);
		translate([lipsBCx,0,lipsTMz-lipsBCz])	sphere(lipsBCr);
	}
}

```


[User]
Hey, I'm looking to create a customizable box for card storage, and I'd like to use OpenSCAD to do so. I've got a pretty good idea of what I need, and I'm hoping you can help me generate the necessary SCAD code.

Essentially, I want a box with a base and a lid, plus an optional divider. The box should be parametric, allowing me to specify the dimensions for different types of cards.

Here are the specifics:

*   **Card Types:** I need predefined settings for "class" cards and "overlord" cards, but also the option to specify custom card sizes. For the class cards, the size should be 64x41x5 mm with a window for the symbol that's 30x30mm offset by 4mm, and a label window that is 5x25mm offset by -18mm. The overlord cards should be 89x58x15mm with a symbol window 60x40 offset by 0mm, and a label window at 0x0 with an offset of 0. Custom card sizes and offsets should be input variables for the user to set.
*   **Parts Selection:** I'd like the option to print the entire box, just the lid, just the base, or just the divider. This should be a simple dropdown with the options `Everything`, `Lid Only`, `Base Only` and `Divider Only`.
*   **Window Cutouts:**  For the lid, I need to be able to toggle a window to show the card's symbol, and another to show the label. These should both be togglable on or off, and the size and offset of these should be parameters as well.
*   **Wall Thickness & Margin:** I want to set the wall thickness, margin around the cards, and overhang for the lid.
*   **Roundness:** I want the edges to be rounded, and the amount of roundness should be configurable.
*   **Gap:** There should be a small gap between the lid and the base for a smooth fit - this should be configurable.

I'd like the code to be as parametric as possible, so I can easily adjust these settings. I'm aiming for a design where I can print with 100% infill as the walls will be thin.  Let me know if you need any more info. Oh, and I don't need to use any external libraries.

[Assistant]
CardBox.scad:
```
/*
	Watch out, because all the surfaces are thin.
	Slice with 100% infill
*/

/* [Basic Settings] */

// Which part to print?
part = 0; // [0:Everything, 1:Lid Only, 2:Base Only; 3:DividerOnly]

// Which type of box to print?
CardType = "class"; // [class:Character's class cards,overlord:Overlord cards,custom:Custom]

// Cut a big window to show the card symbol?
CutWindow = 1; //[1:Yes, 0:No]

// Cut a window to show the card label?
CutLabel = 1; //[1:Yes, 0:No]

/* [Settings for Custom] */

CustomHeight = 64;
CustomWidth = 41;
CustomThickness = 5;

CustomWindowX = 30;
CustomWindowY = 30;
CustomWindowOffset = 4;

CustomLabelX = 5;
CustomLabelY = 25;
CustomLabelOffset = -18;

/* [Advanced] */

// Thickness of the walls
t = 1;

// Margin around the cards
Margin = 2;

// Size of the overhang
Overhang = 5;

// Roundness
Roundness = 3;

// Small gap between the base and the lid
gap = 0.5;

/* [Hidden] */

// Sizes of the various predefined card types
ClassSize = [64, 41, 5];
ClassHole = [30, 30, 4]; // X,Y,Offset
ClassLabel = [5, 25, -18]; // X,Y,Offset

OverlordSize = [89, 58, 15];
OverlordHole = [60, 40, 0]; // X,Y,Offset
OverlordLabel = [0, 0, 0]; // X,Y,Offset

// Jitter to ensure there are no coincident-surface problems
j = 0.1;

// Roundness detail. Mostly $fn will be set to this
detail = 50;

// Shortcuts used to make arrays easier to reference
x=0; y=1; z=2;

module TopBottom(card)
{
	h=card[x]+Margin+t+Overhang;
	w=card[y]+Margin+t+Overhang;

	roundbox([h, w, t], Roundness+Overhang/2-t*2, 0);
}

module case(card, hole, label)
{
	if(part == 0)
	{
		translate([-((card[x]+Margin+t+Overhang)+4+(card[y] + Margin / 2))/2, 0, 0])
		translate([(card[x]+Margin+t+Overhang)/2, 0, 0])
		union()
		{
			translate([0, 2, 0])
			translate([0, (card[y]+Margin+t+Overhang)*0.5, 0])
			base(card);

			translate([0, -2, 0])
			translate([0, -(card[y]+Margin+t+Overhang)*0.5, 0])
			lid(card, hole, label);

			translate([4, 0, 0])
			translate([(card[y] + Margin / 2)/2, 0, 0])
			translate([(card[x]+Margin+t+Overhang)/2, 0, 0])
			rotate([0, 0, 90])
			divider(card);
		}
	}
	if(part == 1)
	{
		lid(card);
	}
	if(part == 2)
	{
		base(card);
	}
	if(part == 3)
	{
		divider(card);
	}
}

module divider(card)
{
	h=card[x] + Margin / 2;
	w=card[y] + Margin / 2;
	roundness=t*3;

	roundbox([h, w, t], roundness, 0);
}

module base(card)
{
	// The actual size of the base is a bit (one "t") bigger than a card
	h=card[x]+Margin;
	w=card[y]+Margin;
	d=card[z]+Margin;

	union()
	{
		difference()
		{
			union()
			{
				// Thin base (widest part)
				TopBottom(card);

				// Walls
				roundbox([h+t*2, w+t*2, d+t], Roundness, t);
			}

			// Thumb holes
			translate([0, 0, d+t*2]) scale([1, 1, d/(w/3)])
			rotate([0, 90, 0])
			cylinder(r=w/3, h=h+t*2+j*2, center=true, $fn=detail);

		}
	}
}

module lid(card, hole, label)
{
	// The outer size of the base is a bit (one "t") bigger than a card
	base_h=card[x]+Margin+t;
	base_w=card[y]+Margin+t;
	base_d=card[z]+Margin+t;

	// The size of the lid is a bit (gap) bigger than the base all around
	h=base_h+gap+t;
	w=base_w+gap+t;
	d=base_d;

	r=hole[x]/2;
	s=hole[x]/ (hole[y] == 0 ? 1 : hole[y]); // prevent DivZero
	o=hole[z];

	union()
	{
		difference()
		{
			union()
			{
				// Thin base (widest part)
				TopBottom(card);

				// Walls
				roundbox([h+t*2, w+t*2, d+t], Roundness+t, t);
			}

			if(CutWindow == 1 && hole[x] > 0 && hole[y] > 0)
			{
				// Window
				translate([o, 0, -j]) scale([1, 1/s, 1]) cylinder(r=r, h=t+j*2, $fn=detail*2);
			}

			if(CutLabel == 1 && label[x] > 0 && label[y] > 0)
			{
				translate([label[z], 0, t/2]) cube([label[x], label[y], t+j*2], center=true, $fn=detail);
			}
		}
	}
}

// Size is the outside dimension
module roundbox(size, r, t)
{
	difference()
	{
		hull()
		{
			translate([-r, -r, 0]) translate([ size[x]*0.5,  size[y]*0.5, 0]) cylinder(r=r, h=size[z], $fn=detail);
			translate([ r, -r, 0]) translate([-size[x]*0.5,  size[y]*0.5, 0]) cylinder(r=r, h=size[z], $fn=detail);
			translate([-r,  r, 0]) translate([ size[x]*0.5, -size[y]*0.5, 0]) cylinder(r=r, h=size[z], $fn=detail);
			translate([ r,  r, 0]) translate([-size[x]*0.5, -size[y]*0.5, 0]) cylinder(r=r, h=size[z], $fn=detail);
		}
		if(t>0)
		{
			hull()
			{
				translate([-r, -r, -j]) translate([ size[x]*0.5,  size[y]*0.5, 0]) cylinder(r=r-t, h=size[z]+j*2, $fn=detail);
				translate([ r, -r, -j]) translate([-size[x]*0.5,  size[y]*0.5, 0]) cylinder(r=r-t, h=size[z]+j*2, $fn=detail);
				translate([-r,  r, -j]) translate([ size[x]*0.5, -size[y]*0.5, 0]) cylinder(r=r-t, h=size[z]+j*2, $fn=detail);
				translate([ r,  r, -j]) translate([-size[x]*0.5, -size[y]*0.5, 0]) cylinder(r=r-t, h=size[z]+j*2, $fn=detail);
			}
		}
	}
}

if(CardType == "class")
{
	case(ClassSize, ClassHole, ClassLabel);
}
if(CardType == "overlord")
{
	case(OverlordSize, OverlordHole, OverlordLabel);
}
if(CardType == "custom")
{
	case(
		[CustomHeight, CustomWidth, CustomThickness],
		[CustomWindowX, CustomWindowY, CustomWindowOffset],
		[CustomLabelX, CustomLabelY, CustomLabelOffset]
	);
}

```


[User]
I'm looking to generate some parametric nameplates for a perpetual plaque, and I want to be able to adjust all of the key dimensions and text through customizer variables. I'm envisioning a rectangular plate with rounded corners, two screw holes on the left and right sides, and two lines of text centered on the plate.

Specifically, I need a few customizer variables:

*   `plate_width`: Overall width of the plate.
*   `plate_height`: Overall height of the plate.
*   `plate_depth`: Thickness of the plate.
*   `corner_radius`: The radius of the rounded corners on the plate.
*   `screw_hole_diameter`: Diameter of the screw holes.
*   `screw_hole_offset_from_edge`: Distance of the center of the screw holes from the left and right edges.
*   `text_line_1`: The text for the first line.
*   `text_line_2`: The text for the second line.
*  `text_size1`: The size of the first line of text
*  `text_size2`: The size of the second line of text
*   `text_line_1_offset_y`: Vertical offset of the first line of text from the vertical center of the plate.
*   `text_line_2_offset_y`: Vertical offset of the second line of text from the vertical center of the plate.

I need the text to be centered on the plate horizontally, and I would like the text to be a 2D object so that it will render nicely. I'd like for the text to be cut from the plate.

The text should be rendered using the `Write.scad` library. I don't need you to provide that library file, I will ensure it's in the right place.

Could you generate the necessary OpenSCAD files for this parametric design? Thanks.

[Assistant]
customplaqueplate.scad:
```
	/*
*****************************************************
By Daniel Lindahl
i@d9l.se
2013
*****************************************************
*/
use <write/Write.scad>
//CUSTOMIZER VARIABLES
build_plate_selector = 1; //[0:Replicator 2,1: Replicator,2:Thingomatic,3:Manual]
line_1 = "John Doe";

line_3 = "2005-2006";
plate_height = 32;
plate_width = 89;
plate_depth  = 2;
text_size1 = 8;
text_size2 = 6;
intend = plate_width/2;

rad1 = plate_height-(plate_height/3.45) ;
rad2 = plate_height/2;
rad3 = plate_height-(plate_height/1.45) ;
screw = plate_width-5;
//CUSTOMIZER VARIABLES END

difference() {
				cube([plate_width,plate_height,plate_depth],center=false);
					# translate ([1,1,plate_depth]) {
										cube([plate_width-2,plate_height-2,1],center=false);
					}

						translate([5,rad2,0]) {
										cylinder(h=plate_depth,r=2);
					}
						translate([screw,rad2,0]) {
										cylinder(h=plate_depth,r=2);
					}
}

translate([intend,rad1,plate_depth])
write(line_1 ,h=text_size1,t=2,center=true);

translate([intend,rad3,plate_depth])
write(line_3,h=text_size2 ,t=2,center=true);

```


[User]
I'm looking to design a protective case for a MaxBotix LV-MaxSonar-EZ4 sensor. I'd like the case to be parametric so I can adjust it if needed. The case should consist of two parts: a base and a cover.

The base will have mounting pegs for the sensor's PCB and walls to enclose the sensor. The base should have cutouts for the sensor's pins (+, -) on one side and should also have support pegs for the PCB. The cover should have a cutout to allow the sensor's ultrasonic transducer to function and should close over the base. I'd like to be able to print the cover and base either individually or together as a single file. The case is intended for use with a 3D printer, so some printer settings need to be exposed.

Here are the specific measurements I have for the sensor and other design considerations:

*   **Sensor Board Size:** 20mm x 22.2mm x 2mm (x, y, z)
*   **PCB Thickness:** 1.6mm
*   **Mounting Hole Diameter:** 3mm
*   **Mounting Hole Offsets:** Refer to the existing code (Hole1Pos, Hole2Pos)
*   **Aperture for Transducer:** 16mm diameter
*   **Wall Thickness:** 1mm
*   **Wall Height:** 2 * Thickness + 8mm
*   **Standoff for PCB:** Thickness + j (where j = 0.1mm)

I'm expecting the OpenSCAD files to take printer settings, such as build plate dimensions into account. The user should be able to select between standard printer sizes or a custom size. I'm also assuming some kind of helper library to generate these build plates is available. For the purposes of this project I'll refer to this as `build_plate.scad` within the `utils/` directory, but I don't expect the assistant to use that library literally, just something that achieves the same end.

I'd like the main file to include a variable to select which part to render and that should include an option to render both parts together. The parts should be colored so the user can easily identify the parts. The base should be gray, the cover khaki, and the sensor board should be semi-transparent green.

[Assistant]
maxsonar.scad:
```
/*
###############################################################################
# DESCRIPTION
###############################################################################
This is a small case for mounting and protecting the MaxBotix LV-MaxSonar-EZ4 module.

---

The latest snapshot is available on [GitHub](https://github.com/Cylindric3D/quad_parts).

###############################################################################
# INSTRUCTIONS
###############################################################################
Simply print out one base and one cover, either individually, or with the combined STL.

###############################################################################
 */

/* [Global] */

// Which part would you like to see?
part = "both"; // [both:Both,cover:Cover,base:Base,demo:Demo]

/* [Printer] */
build_plate_selector = 0; //[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 = 180; //[100:400]

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

/* [Hidden] */
j = 0.1;
$fn=100;
x = 0; y = 1; z = 2;

Thickness = 1;
Aperture = 16;
BoardSize = [20, 22.2, 2];
HoleSize = 3;
HoleOffset = 1;
PCBThickness = 1.6;

Hole1Pos = [HoleSize/2 + 2.75, HoleSize/2 + 0.85, 0];
Hole2Pos = [BoardSize[x] - HoleSize/2 - 1, BoardSize[y] - HoleSize/2 - 1.1, 0];
BigHolePos = BoardSize[x]-8-1;

BaseSize = [BoardSize[x]+Thickness*2, BoardSize[y]+Thickness*2, Thickness];
WallHeight = Thickness*2 + 8;

use<utils/build_plate.scad>;

module MaxSonar()
{
	union()
	{
		color([0, 100/255, 0, 0.5])
		difference()
		{
			cube([BoardSize[x], BoardSize[y], PCBThickness]);
			translate([Hole1Pos[x], Hole1Pos[y], -j]) cylinder(r = HoleSize/2, h = BoardSize[z] + j*2);
			translate([Hole2Pos[x], Hole2Pos[y], -j]) cylinder(r = HoleSize/2, h = BoardSize[z] + j*2);
		}

		color([0.5, 0.5, 0.5, 0.5])
		translate([BigHolePos, BoardSize[y]/2, PCBThickness])
		cylinder(r = Aperture / 2, h = 13.9);
	}
}

module PCBPeg(holeDiameter, height, standoff)
{
	union()
	{
		translate([0, 0, standoff - j]) cylinder(r = holeDiameter/2 * 0.9, h = height - standoff - j);
		cylinder(r = (holeDiameter/2 * 0.9)+0.5, h = standoff);
	}
}

module Cover()
{
	color("Khaki")
	union()
	{
		difference()
		{
			cube(BaseSize);

			translate([BigHolePos + Thickness, BaseSize[y]/2, -j])
			cylinder(r = Aperture / 2 + j + 0.2, h = Thickness + j * 2);
		}

		// Closed side
		translate([BaseSize[x] - Thickness, Thickness, 0])
		cube([Thickness, BaseSize[y] - Thickness * 2, WallHeight-4+Thickness]);

		// Closed side PCB grip
		translate([BaseSize[x] - Thickness - 1, Thickness, 0])
		cube([Thickness + j, BaseSize[y] - Thickness * 2, WallHeight-2.7]);

		// Back side
		translate([0, Thickness, 0])
		union()
		{
			cube([BaseSize[x], Thickness, 4]);
		}

		// Front side
		translate([0, BaseSize[y]-Thickness * 2, 0])
		union()
		{
			cube([BaseSize[x]/2, Thickness, WallHeight-2.7]);
			cube([BaseSize[x], Thickness, WallHeight-4]);
		}
	}
}

module Base()
{
	union()
	{
		// Base
		cube(BaseSize);

		difference()
		{
			// Cable side wall
			cube([Thickness, BaseSize[y], 4]);

			// -
			translate([-Thickness/2, 3, 1.75])
			cube([Thickness, 2, 0.5]);

			// +
			translate([-Thickness/2, 6, 1.75]) cube([Thickness, 2, 0.5]);
			translate([-Thickness/2, 7.25, 1]) rotate([90, 0, 0]) cube([Thickness, 2, 0.5]);
		}

		// Opposite side wall
		translate([BaseSize[x]-Thickness, 0, 0]) cube([Thickness, BaseSize[y], 4]);

		// Near wall
		translate([0, 0, j]) cube([BaseSize[x], Thickness, WallHeight-j]);

		// Far wall
		translate([0, BaseSize[y] - Thickness, j]) cube([BaseSize[x], Thickness, WallHeight-j]);

		// PCB Supports
		translate([Thickness, Thickness, Thickness - j])
		union()
		{
			translate(Hole1Pos)
			PCBPeg(HoleSize, Thickness + BoardSize[z] + Thickness *2 + j, Thickness + j);

			translate(Hole2Pos)
			PCBPeg(HoleSize, Thickness + BoardSize[z] + Thickness * 2 + j, Thickness + j);

			translate([Hole1Pos[x], Hole2Pos[y], 0])
			cylinder(r = (HoleSize / 2 * 0.9) + 0.5, h = Thickness + j);

			translate([Hole2Pos[x], Hole1Pos[y], 0])
			cylinder(r = (HoleSize / 2 * 0.9) + 0.5, h = Thickness + j);
		}
	}
}

module print_part()
{
	if (part == "demo")
	{
		translate([-BaseSize[x]/2, -BaseSize[y]/2, 0])
		union()
		{
			Base();

			translate([0, 0, WallHeight+j])
			translate([0, BaseSize[y], Thickness]) rotate([180, 0, 0])
			Cover();

			translate([Thickness, Thickness, Thickness*2])
			%MaxSonar();
		}
	}
	if (part == "both")
	{
		translate([0, -BaseSize[y]/2, 0])
		union()
		{
			translate(-[BaseSize[x]+Thickness, 0, 0]) Base();
			translate([Thickness, 0, 0]) Cover();
		}
	}
	if (part == "cover")
	{
		translate([-BaseSize[x]/2, -BaseSize[y]/2, 0]) Cover();
	}
	if (part == "base")
	{
		translate([-BaseSize[x]/2, -BaseSize[y]/2, 0]) Base();
	}
}

print_part();

%build_plate(build_plate_selector, build_plate_manual_x, build_plate_manual_y);

```


[User]
Hey there! I'm looking to create a parametric funnel design for 3D printing, specifically for filling resin molds from the bottom to minimize air bubbles. I've seen some designs floating around, but I need something I can tweak really easily to match different mold sizes.

Ideally, I want to control these parameters:

*   **funnelTopD:** The diameter of the funnel's mouth (the wide end), in millimeters. I'll need to be able to specify a range for this, say from 10mm to 200mm.
*   **funnelTopL:** The length of the funnel's mouth, in millimeters. A range of 0 to 200mm should be good.
*   **funnelBottomD:** The diameter where the funnel tapers down, also in millimeters, again with a range of 5 to 200mm.
*   **funnelL:** The length of the tapered section of the funnel, in millimeters, with a range of 10 to 200mm.
*   **egressD:** The diameter of the outlet or nozzle, also in millimeters (5-200mm).
*   **egressL:** The length of the outlet or nozzle, in millimeters (0-200mm).
*   **wallT:** The thickness of the funnel walls, in *microns* (not mm!). I'll need a range here from 300 to 5000 microns.

The design should essentially consist of three cylinders stacked on top of each other. The first cylinder represents the funnel's mouth, the second the tapered section, and the third the outlet or nozzle. The inner part of these cylinders should be hollowed out to create the funnel, using the wall thickness parameter. The hollow should go from the top of the funnel down to the end of the outlet, creating a continuous channel for resin to flow.

I’d prefer if the code was reasonably efficient in how it draws the shapes, and all units should be in mm. Also, I'd like to have a reasonable `$fn` value (e.g., 50) for rendering. I'm using OpenSCAD, so a single `.scad` file would be great. I don't have any dependencies I'm planning to use. Thanks!

[Assistant]
ZickFunnel.scad:
```
//copyright 2014 Richard Swika (a.k.a. Zick)
//All Rights Reserved
//Rev. Orig - Augest 19, 2014 - Good for bottom filling resin molds
//Rev. A - March 25, 2016 - Updated to work with changes to customizer
/* [Dimensions] */

//Diameter of funnel mouth? (mm)
funnelTopD = 40; //[10:200]

//Length of funnel mouth? (mm)
funnelTopL = 2; //[0:200]

//Diameter at bottom of funnel taper? (mm)
funnelBottomD = 10; //[5:200]

//Length of funnel taper? (mm)
funnelL = 20; //[10:200]

//Diameter of egress? (mm)
egressD= 5; //[5:200]

//Length of egress? (mm)
egressL = 10; //[0:200]

//Thickness of walls? (micron)
wallT = 400; //[300:5000]

/* [Private] */
tiny=0.05;
$fn=50;
module funnel()
{
	translate([0,0,0])
		difference(){
		union(){
			translate([0,0,(funnelTopL)/2])
			cylinder(d=funnelTopD,h=funnelTopL+tiny,center=true);
			translate([0,0,tiny+funnelTopL+funnelL/2])
			cylinder(d1=funnelTopD,d2=funnelBottomD,h=funnelL+tiny,center=true);
			translate([0,0,funnelTopL+funnelL+egressL/2])
			cylinder(d1=funnelBottomD,d2=egressD,h=egressL+tiny,center=true);
		}
		translate([0,0,-tiny])
		union(){
			translate([0,0,(funnelTopL)/2])
			cylinder(d=funnelTopD-wallT*0.003,h=funnelTopL+2*tiny,center=true);
			translate([0,0,tiny+funnelTopL+funnelL/2])
			cylinder(d1=funnelTopD-wallT*0.003,d2=funnelBottomD-wallT*0.003,h=funnelL+2*tiny,center=true);
			translate([0,0,funnelTopL+funnelL+egressL/2])
			cylinder(d1=funnelBottomD-wallT*0.003,d2=egressD-wallT*0.003,h=egressL+4*tiny,center=true);
		}

	}
}

rotate([0,0,0]) funnel();
```